Esempio n. 1
0
static void irc_cmd_whowas( irc_t *irc, char **cmd )
{
	/* For some reason irssi tries a whowas when whois fails. We can
	   ignore this, but then the user never gets a "user not found"
	   message from irssi which is a bit annoying. So just respond
	   with not-found and irssi users will get better error messages */
	
	irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
	irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
}
Esempio n. 2
0
File: irc_im.c Progetto: meh/bitlbee
static gboolean bee_irc_user_status(bee_t *bee, bee_user_t *bu, bee_user_t *old)
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = bu->ui_data;

	/* Do this outside the if below since away state can change without
	   the online state changing. */
	iu->flags &= ~IRC_USER_AWAY;
	if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) {
		iu->flags |= IRC_USER_AWAY;
	}

	if ((bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE)) {
		if (bu->flags & BEE_USER_ONLINE) {
			if (g_hash_table_lookup(irc->watches, iu->key)) {
				irc_send_num(irc, 600, "%s %s %s %d :%s", iu->nick, iu->user,
				             iu->host, (int) time(NULL), "logged online");
			}
		} else {
			if (g_hash_table_lookup(irc->watches, iu->key)) {
				irc_send_num(irc, 601, "%s %s %s %d :%s", iu->nick, iu->user,
				             iu->host, (int) time(NULL), "logged offline");
			}

			/* Send a QUIT since those will also show up in any
			   query windows the user may have, plus it's only
			   one QUIT instead of possibly many (in case of
			   multiple control chans). If there's a channel that
			   shows offline people, a JOIN will follow. */
			if (set_getbool(&bee->set, "offline_user_quits")) {
				irc_user_quit(iu, "Leaving...");
			}
		}
	}

	/* Reset this one since the info may have changed. */
	iu->away_reply_timeout = 0;

	bee_irc_channel_update(irc, NULL, iu);

	/* If away-notify enabled, send status updates when:
	 * Away or Online state changes
	 * Status changes (e.g. "Away" to "Mobile")
	 * Status message changes
	 */
	if ((irc->caps & CAP_AWAY_NOTIFY) &&
	    ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) ||
	     (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE) ||
	     (g_strcmp0(bu->status, old->status) != 0) ||
	     (g_strcmp0(bu->status_msg, old->status_msg) != 0))) {
		irc_send_away_notify(iu);
	}

	return TRUE;
}
Esempio n. 3
0
static void irc_cmd_privmsg( irc_t *irc, char **cmd )
{
	irc_channel_t *ic;
	irc_user_t *iu;
	
	if( !cmd[2] ) 
	{
		irc_send_num( irc, 412, ":No text to send" );
		return;
	}
	
	/* Don't treat CTCP actions as real CTCPs, just convert them right now. */
	if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 )
	{
		cmd[2] += 4;
		memcpy( cmd[2], "/me", 3 );
		if( cmd[2][strlen(cmd[2])-1] == '\001' )
			cmd[2][strlen(cmd[2])-1] = '\0';
	}
	
	if( irc_channel_name_ok( cmd[1] ) &&
	    ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
	{
		if( cmd[2][0] == '\001' )
		{
			/* CTCPs to channels? Nah. Maybe later. */
		}
		else if( ic->f->privmsg )
			ic->f->privmsg( ic, cmd[2] );
	}
	else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) )
	{
		if( cmd[2][0] == '\001' )
		{
			char **ctcp;
			
			if( iu->f->ctcp == NULL )
				return;
			if( cmd[2][strlen(cmd[2])-1] == '\001' )
				cmd[2][strlen(cmd[2])-1] = '\0';
			
			ctcp = split_command_parts( cmd[2] + 1 );
			iu->f->ctcp( iu, ctcp );
		}
		else if( iu->f->privmsg )
		{
			iu->last_channel = NULL;
			iu->f->privmsg( iu, cmd[2] );
		}
	}
	else
	{
		irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
	}
}
Esempio n. 4
0
void irc_send_motd(irc_t *irc)
{
	char motd[2048];
	ssize_t len;
	int fd;

	fd = open(global.conf->motdfile, O_RDONLY);
	if (fd == -1 || (len = read(fd, motd, sizeof(motd) - 1)) <= 0) {
		irc_send_num(irc, 422, ":We don't need MOTDs.");
	} else {
		char linebuf[80];
		char *add = "", max, *in;

		in = motd;
		motd[len] = '\0';
		linebuf[79] = len = 0;
		max = sizeof(linebuf) - 1;

		irc_send_num(irc, 375, ":- %s Message Of The Day - ", irc->root->host);
		while ((linebuf[len] = *(in++))) {
			if (linebuf[len] == '\n' || len == max) {
				linebuf[len] = 0;
				irc_send_num(irc, 372, ":- %s", linebuf);
				len = 0;
			} else if (linebuf[len] == '%') {
				linebuf[len] = *(in++);
				if (linebuf[len] == 'h') {
					add = irc->root->host;
				} else if (linebuf[len] == 'v') {
					add = BITLBEE_VERSION;
				} else if (linebuf[len] == 'n') {
					add = irc->user->nick;
				} else if (linebuf[len] == '\0') {
					in--;
				} else {
					add = "%";
				}

				strncpy(linebuf + len, add, max - len);
				while (linebuf[++len]) {
					;
				}
			} else if (len < max) {
				len++;
			}
		}
		irc_send_num(irc, 376, ":End of MOTD");
	}

	if (fd != -1) {
		close(fd);
	}
}
Esempio n. 5
0
void irc_send_login(irc_t *irc)
{
	irc_send_num(irc,   1, ":Welcome to the %s gateway, %s", PACKAGE, irc->user->nick);
	irc_send_num(irc,   2, ":Host %s is running %s %s %s/%s.", irc->root->host,
	             PACKAGE, BITLBEE_VERSION, ARCH, CPU);
	irc_send_num(irc,   3, ":%s", IRCD_INFO);
	irc_send_num(irc,   4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES);
	irc_send_num(irc,   5, "PREFIX=(ohv)@%%+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d CHANNELLEN=%d "
	             "NETWORK=BitlBee SAFELIST CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 "
	             "FLOOD=0/9999 :are supported by this server",
	             CTYPES, CMODES, MAX_NICK_LENGTH - 1, MAX_NICK_LENGTH - 1);
	irc_send_motd(irc);
}
Esempio n. 6
0
static void irc_cmd_oper_hack( irc_t *irc, char **cmd )
{
	char *password = g_strjoinv( " ", cmd + 2 );
	
	/* /OPER can now also be used to enter IM/identify passwords without
	   echoing. It's a hack but the extra password security is worth it. */
	if( irc->status & OPER_HACK_ACCOUNT_ADD )
	{
		account_t *a;
		
		for( a = irc->b->accounts; a; a = a->next )
			if( strcmp( a->pass, PASSWORD_PENDING ) == 0 )
			{
				set_setstr( &a->set, "password", password );
				irc_rootmsg( irc, "Password added to IM account "
				             "%s", a->tag );
				/* The IRC client may expect this. 491 suggests the OPER
				   password was wrong, so the client won't expect a +o.
				   It may however repeat the password prompt. We'll see. */
				irc_send_num( irc, 491, ":Password added to IM account "
				              "%s", a->tag );
			}
	}
	else if( irc->status & OPER_HACK_IDENTIFY )
	{
		char *send_cmd[] = { "identify", password, NULL, NULL };
		irc->status &= ~OPER_HACK_IDENTIFY;
		if( irc->status & OPER_HACK_IDENTIFY_NOLOAD )
		{
			send_cmd[1] = "-noload";
			send_cmd[2] = password;
		}
		else if( irc->status & OPER_HACK_IDENTIFY_FORCE )
		{
			send_cmd[1] = "-force";
			send_cmd[2] = password;
		}
		irc_send_num( irc, 491, ":Trying to identify" );
		root_command( irc, send_cmd );
	}
	else if( irc->status & OPER_HACK_REGISTER )
	{
		char *send_cmd[] = { "register", password, NULL };
		irc_send_num( irc, 491, ":Trying to identify" );
		root_command( irc, send_cmd );
	}
	
	irc->status &= ~OPER_HACK_ANY;
	g_free( password );
}
Esempio n. 7
0
static void irc_cmd_pass( irc_t *irc, char **cmd )
{
	if( irc->status & USTATUS_LOGGED_IN )
	{
		char *send_cmd[] = { "identify", cmd[1], NULL };
		
		/* We're already logged in, this client seems to send the PASS
		   command last. (Possibly it won't send it at all if it turns
		   out we don't require it, which will break this feature.)
		   Try to identify using the given password. */
		root_command( irc, send_cmd );
		return;
	}
	/* Handling in pre-logged-in state, first see if this server is
	   password-protected: */
	else if( global.conf->auth_pass &&
	    ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ?
	        md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 :
	        strcmp( cmd[1], global.conf->auth_pass ) == 0 ) )
	{
		irc->status |= USTATUS_AUTHORIZED;
		irc_check_login( irc );
	}
	else if( global.conf->auth_pass )
	{
		irc_send_num( irc, 464, ":Incorrect password" );
	}
	else
	{
		/* Remember the password and try to identify after USER/NICK. */
		irc_setpass( irc, cmd[1] );
		irc_check_login( irc );
	}
}
Esempio n. 8
0
static void irc_cmd_watch( irc_t *irc, char **cmd )
{
	int i;
	
	/* Obviously we could also mark a user structure as being
	   watched, but what if the WATCH command is sent right
	   after connecting? The user won't exist yet then... */
	for( i = 1; cmd[i]; i ++ )
	{
		char *nick;
		irc_user_t *iu;
		
		if( !cmd[i][0] || !cmd[i][1] )
			break;
		
		nick = g_strdup( cmd[i] + 1 );
		nick_lc( nick );
		
		iu = irc_user_by_name( irc, nick );
		
		if( cmd[i][0] == '+' )
		{
			if( !g_hash_table_lookup( irc->watches, nick ) )
				g_hash_table_insert( irc->watches, nick, nick );
			
			if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE )
				irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user,
				              iu->host, (int) time( NULL ), "is online" );
			else
				irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*",
				              (int) time( NULL ), "is offline" );
		}
		else if( cmd[i][0] == '-' )
		{
			gpointer okey, ovalue;
			
			if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
			{
				g_hash_table_remove( irc->watches, okey );
				g_free( okey );
				
				irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
			}
		}
	}
}
Esempio n. 9
0
static void irc_cmd_part( irc_t *irc, char **cmd )
{
	irc_channel_t *ic;
	
	if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
	{
		irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
	}
	else if( irc_channel_del_user( ic, irc->user, IRC_CDU_PART, cmd[2] ) )
	{
		if( ic->f->part )
			ic->f->part( ic, NULL );
	}
	else
	{
		irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] );
	}
}
Esempio n. 10
0
static void irc_cmd_topic( irc_t *irc, char **cmd )
{
	irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] );
	const char *new = cmd[2];
	
	if( ic == NULL )
	{
		irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
	}
	else if( new )
	{
		if( ic->f->topic == NULL )
			irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name );
		else if( ic->f->topic( ic, new ) )
			irc_send_topic( ic, TRUE );
	}
	else
	{
Esempio n. 11
0
static void irc_cmd_whois( irc_t *irc, char **cmd )
{
	char *nick = cmd[1];
	irc_user_t *iu = irc_user_by_name( irc, nick );
	
	if( iu )
		irc_send_whois( iu );
	else
		irc_send_num( irc, 401, "%s :Nick does not exist", nick );
}
Esempio n. 12
0
static void irc_cmd_oper( irc_t *irc, char **cmd )
{
	/* Very non-standard evil but useful/secure hack, see below. */
	if( irc->status & OPER_HACK_ANY )
		return irc_cmd_oper_hack( irc, cmd );
	
	if( global.conf->oper_pass &&
	    ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
	        md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
	        strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
	{
		irc_umode_set( irc, "+o", 1 );
		irc_send_num( irc, 381, ":Password accepted" );
	}
	else
	{
		irc_send_num( irc, 491, ":Incorrect password" );
	}
}
Esempio n. 13
0
static void irc_cmd_ison( irc_t *irc, char **cmd )
{
	char buff[IRC_MAX_LINE];
	int lenleft, i;
	
	buff[0] = '\0';
	
	/* [SH] Leave room for : and \0 */
	lenleft = IRC_MAX_LINE - 2;
	
	for( i = 1; cmd[i]; i ++ )
	{
		char *this, *next;
		
		this = cmd[i];
		while( *this )
		{
			irc_user_t *iu;
			
			if( ( next = strchr( this, ' ' ) ) )
				*next = 0;
			
			if( ( iu = irc_user_by_name( irc, this ) ) &&
			    iu->bu && iu->bu->flags & BEE_USER_ONLINE )
			{
				lenleft -= strlen( iu->nick ) + 1;
				
				if( lenleft < 0 )
					break;
				
				strcat( buff, iu->nick );
				strcat( buff, " " );
			}
			
			if( next )
			{
				*next = ' ';
				this = next + 1;
			}
			else
			{
				break;
			}    
		}
		
		/* *sigh* */
		if( lenleft < 0 )
			break;
	}
	
	if( strlen( buff ) > 0 )
		buff[strlen(buff)-1] = '\0';
	
	irc_send_num( irc, 303, ":%s", buff );
}
Esempio n. 14
0
static gboolean bee_irc_user_status( bee_t *bee, bee_user_t *bu, bee_user_t *old )
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = bu->ui_data;
	
	/* Do this outside the if below since away state can change without
	   the online state changing. */
	iu->flags &= ~IRC_USER_AWAY;
	if( bu->flags & BEE_USER_AWAY || !( bu->flags & BEE_USER_ONLINE ) )
		iu->flags |= IRC_USER_AWAY;
	
	if( ( bu->flags & BEE_USER_ONLINE ) != ( old->flags & BEE_USER_ONLINE ) )
	{
		if( bu->flags & BEE_USER_ONLINE )
		{
			if( g_hash_table_lookup( irc->watches, iu->key ) )
				irc_send_num( irc, 600, "%s %s %s %d :%s", iu->nick, iu->user,
				              iu->host, (int) time( NULL ), "logged online" );
		}
		else
		{
			if( g_hash_table_lookup( irc->watches, iu->key ) )
				irc_send_num( irc, 601, "%s %s %s %d :%s", iu->nick, iu->user,
				              iu->host, (int) time( NULL ), "logged offline" );
			
			/* Send a QUIT since those will also show up in any
			   query windows the user may have, plus it's only
			   one QUIT instead of possibly many (in case of
			   multiple control chans). If there's a channel that
			   shows offline people, a JOIN will follow. */
			if( set_getbool( &bee->set, "offline_user_quits" ) )
				irc_user_quit( iu, "Leaving..." );
		}
	}
	
	/* Reset this one since the info may have changed. */
	iu->away_reply_timeout = 0;
	
	bee_irc_channel_update( irc, NULL, iu );
	
	return TRUE;
}
Esempio n. 15
0
static void irc_cmd_invite( irc_t *irc, char **cmd )
{
	irc_channel_t *ic;
	irc_user_t *iu;
	
	if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL )
	{
		irc_send_num( irc, 401, "%s :No such nick", cmd[1] );
		return;
	}
	else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL )
	{
		irc_send_num( irc, 403, "%s :No such channel", cmd[2] );
		return;
	}
	
	if( !ic->f->invite )
		irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] );
	else if( ic->f->invite( ic, iu ) )
		irc_send_num( irc, 341, "%s %s", iu->nick, ic->name );
}
Esempio n. 16
0
static void irc_cmd_mode( irc_t *irc, char **cmd )
{
	if( irc_channel_name_ok( cmd[1] ) )
	{
		irc_channel_t *ic;
		
		if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
			irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
		else if( cmd[2] )
		{
			if( *cmd[2] == '+' || *cmd[2] == '-' )
				irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
			else if( *cmd[2] == 'b' )
				irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
		}
		else
			irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );
	}
	else
	{
		if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
		{
			if( cmd[2] )
				irc_umode_set( irc, cmd[2], 0 );
			else
				irc_send_num( irc, 221, "+%s", irc->umode );
		}
		else
			irc_send_num( irc, 502, ":Don't touch their modes" );
	}
}
Esempio n. 17
0
static void irc_cmd_nick( irc_t *irc, char **cmd )
{
	irc_user_t *iu;
	
	if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user )
	{
		irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] );
	}
	else if( !nick_ok( cmd[1] ) )
	{
		/* [SH] Invalid characters. */
		irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] );
	}
	else if( irc->status & USTATUS_LOGGED_IN )
	{
		/* WATCH OUT: iu from the first if reused here to check if the
		   new nickname is the same (other than case, possibly). If it
		   is, no need to reset identify-status. */
		if( ( irc->status & USTATUS_IDENTIFIED ) && iu != irc->user )
		{
			irc_setpass( irc, NULL );
			irc->status &= ~USTATUS_IDENTIFIED;
			irc_umode_set( irc, "-R", 1 );
			irc_rootmsg( irc, "Changing nicks resets your identify status. "
			             "Re-identify or register a new account if you want "
			             "your configuration to be saved. See \x02help "
			             "nick_changes\x02." );
		}
		
		if( strcmp( cmd[1], irc->user->nick ) != 0 )
			irc_user_set_nick( irc->user, cmd[1] );
	}
	else
	{
		g_free( irc->user->nick );
		irc->user->nick = g_strdup( cmd[1] );
		
		irc_check_login( irc );
	}
}
Esempio n. 18
0
static void irc_cmd_notice( irc_t *irc, char **cmd )
{
	if( !cmd[2] ) 
	{
		irc_send_num( irc, 412, ":No text to send" );
		return;
	}
	
	/* At least for now just echo. IIRC some IRC clients use self-notices
	   for lag checks, so try to support that. */
	if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
		irc_send_msg( irc->user, "NOTICE", irc->user->nick, cmd[2], NULL );
}
Esempio n. 19
0
static void irc_cmd_nick( irc_t *irc, char **cmd )
{
	irc_user_t *iu;
	
	if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user )
	{
		irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] );
	}
	else if( !nick_ok( cmd[1] ) )
	{
		/* [SH] Invalid characters. */
		irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] );
	}
	else if( irc->status & USTATUS_LOGGED_IN )
	{
		if( irc->status & USTATUS_IDENTIFIED )
		{
			irc_setpass( irc, NULL );
			irc->status &= ~USTATUS_IDENTIFIED;
			irc_umode_set( irc, "-R", 1 );
			irc_usermsg( irc, "Changing nicks resets your identify status. "
			             "Re-identify or register a new account if you want "
			             "your configuration to be saved. See \x02help "
			             "nick_changes\x02." );
		}
		
		irc_user_set_nick( irc->user, cmd[1] );
	}
	else
	{
		g_free( irc->user->nick );
		irc->user->nick = g_strdup( cmd[1] );
		
		irc_check_login( irc );
	}
}
Esempio n. 20
0
static void cmd_register(irc_t *irc, char **cmd)
{
	char s[16];

	if (global.conf->authmode == AUTHMODE_REGISTERED) {
		irc_rootmsg(irc, "This server does not allow registering new accounts");
		return;
	}

	if (cmd[1] == NULL) {
		irc_rootmsg(irc, "About to register, use /OPER to enter the password");
		irc->status |= OPER_HACK_REGISTER;
		return;
	}

	switch (storage_save(irc, cmd[1], FALSE)) {
	case STORAGE_ALREADY_EXISTS:
		irc_rootmsg(irc, "Nick is already registered");
		break;

	case STORAGE_OK:
		irc_rootmsg(irc, "Account successfully created");
		irc_setpass(irc, cmd[1]);
		irc->status |= USTATUS_IDENTIFIED;
		irc_umode_set(irc, "+R", 1);

		if (irc->caps & CAP_SASL) {
			irc_user_t *iu = irc->user;
			irc_send_num(irc, 900, "%s!%s@%s %s :You are now logged in as %s",
				iu->nick, iu->user, iu->host, iu->nick, iu->nick);
		}

		/* Set this var now, or anyone who logs in to his/her
		   newly created account for the first time gets the
		   whatsnew story. */
		g_snprintf(s, sizeof(s), "%d", BITLBEE_VERSION_CODE);
		set_setstr(&irc->b->set, "last_version", s);
		break;

	default:
		irc_rootmsg(irc, "Error registering");
		break;
	}
}
Esempio n. 21
0
static void irc_cmd_who( irc_t *irc, char **cmd )
{
	char *channel = cmd[1];
	irc_channel_t *ic;
	irc_user_t *iu;
	
	if( !channel || *channel == '0' || *channel == '*' || !*channel )
		irc_send_who( irc, irc->users, "**" );
	else if( ( ic = irc_channel_by_name( irc, channel ) ) )
		irc_send_who( irc, ic->users, channel );
	else if( ( iu = irc_user_by_name( irc, channel ) ) )
	{
		/* Tiny hack! */
		GSList *l = g_slist_append( NULL, iu );
		irc_send_who( irc, l, channel );
		g_slist_free( l );
	}
	else
		irc_send_num( irc, 403, "%s :No such channel", channel );
}
Esempio n. 22
0
static void irc_cmd_userhost( irc_t *irc, char **cmd )
{
	int i;
	
	/* [TV] Usable USERHOST-implementation according to
		RFC1459. Without this, mIRC shows an error
		while connecting, and the used way of rejecting
		breaks standards.
	*/
	
	for( i = 1; cmd[i]; i ++ )
	{
		irc_user_t *iu = irc_user_by_name( irc, cmd[i] );
		
		if( iu )
			irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick,
			              irc_user_get_away( iu ) ? '-' : '+',
			              iu->user, iu->host );
	}
}
Esempio n. 23
0
static void cmd_identify(irc_t *irc, char **cmd)
{
	storage_status_t status;
	gboolean load = TRUE;
	char *password = cmd[1];

	if (irc->status & USTATUS_IDENTIFIED) {
		irc_rootmsg(irc, "You're already logged in.");
		return;
	}

	if (cmd[1] == NULL) {
	} else if (strncmp(cmd[1], "-no", 3) == 0) {
		load = FALSE;
		password = cmd[2];
		if (password == NULL) {
			irc->status |= OPER_HACK_IDENTIFY_NOLOAD;
		}
	} else if (strncmp(cmd[1], "-force", 6) == 0) {
		password = cmd[2];
		if (password == NULL) {
			irc->status |= OPER_HACK_IDENTIFY_FORCE;
		}
	} else if (irc->b->accounts != NULL) {
		irc_rootmsg(irc,
		            "You're trying to identify yourself, but already have "
		            "at least one IM account set up. "
		            "Use \x02identify -noload\x02 or \x02identify -force\x02 "
		            "instead (see \x02help identify\x02).");
		return;
	}

	if (password == NULL) {
		irc_rootmsg(irc, "About to identify, use /OPER to enter the password");
		irc->status |= OPER_HACK_IDENTIFY;
		return;
	}

	status = auth_check_pass(irc, irc->user->nick, password);
	if (load && (status == STORAGE_OK)) {
		status = storage_load(irc, password);
	}

	switch (status) {
	case STORAGE_INVALID_PASSWORD:
		irc_rootmsg(irc, "Incorrect password");
		break;
	case STORAGE_NO_SUCH_USER:
		irc_rootmsg(irc, "The nick is (probably) not registered");
		break;
	case STORAGE_OK:
		irc_rootmsg(irc, "Password accepted%s",
		            load ? ", settings and accounts loaded" : "");
		irc->status |= USTATUS_IDENTIFIED;
		irc_umode_set(irc, "+R", 1);

		if (irc->caps & CAP_SASL) {
			irc_user_t *iu = irc->user;
			irc_send_num(irc, 900, "%s!%s@%s %s :You are now logged in as %s",
				iu->nick, iu->user, iu->host, iu->nick, iu->nick);
		}

		bitlbee_whatsnew(irc);

		/* The following code is a bit hairy now. With takeover
		   support, we shouldn't immediately auto_connect in case
		   we're going to offer taking over an existing session.
		   Do it in 200ms since that should give the parent process
		   enough time to come back to us. */
		if (load) {
			irc_channel_auto_joins(irc, NULL);
			if (!set_getbool(&irc->default_channel->set, "auto_join")) {
				irc_channel_del_user(irc->default_channel, irc->user,
				                     IRC_CDU_PART, "auto_join disabled "
				                     "for this channel.");
			}
			if (set_getbool(&irc->b->set, "auto_connect")) {
				irc->login_source_id = b_timeout_add(200,
				                                     cmd_identify_finish, irc);
			}
		}

		/* If ipc_child_identify() returns FALSE, it means we're
		   already sure that there's no takeover target (only
		   possible in 1-process daemon mode). Start auto_connect
		   immediately. */
		if (!ipc_child_identify(irc) && load) {
			cmd_identify_finish(irc, 0, 0);
		}

		break;
	case STORAGE_OTHER_ERROR:
	default:
		irc_rootmsg(irc, "Unknown error while loading configuration");
		break;
	}
}
Esempio n. 24
0
static void irc_cmd_join( irc_t *irc, char **cmd )
{
	char *comma, *s = cmd[1];
	
	while( s )
	{
		irc_channel_t *ic;
		
		if( ( comma = strchr( s, ',' ) ) )
			*comma = '\0';
		
		if( ( ic = irc_channel_by_name( irc, s ) ) == NULL &&
		    ( ic = irc_channel_new( irc, s ) ) )
		{
			if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 )
			{
				/* Autoconfiguration is for control channels only ATM. */
			}
			else if( bee_group_by_name( ic->irc->b, ic->name + 1, FALSE ) )
			{
				set_setstr( &ic->set, "group", ic->name + 1 );
				set_setstr( &ic->set, "fill_by", "group" );
			}
			else if( set_setstr( &ic->set, "protocol", ic->name + 1 ) )
			{
				set_setstr( &ic->set, "fill_by", "protocol" );
			}
			else if( set_setstr( &ic->set, "account", ic->name + 1 ) )
			{
				set_setstr( &ic->set, "fill_by", "account" );
			}
			else
			{
				/* The set commands above will run this already,
				   but if we didn't hit any, we have to fill the
				   channel with the default population. */
				bee_irc_channel_update( ic->irc, ic, NULL );
			}
		}
		else if( ic == NULL )
		{
			irc_send_num( irc, 479, "%s :Invalid channel name", s );
			goto next;
		}
		
		if( ic->flags & IRC_CHANNEL_JOINED )
			/* Dude, you're already there...
			   RFC doesn't have any reply for that though? */
			goto next;
		
		if( ic->f->join && !ic->f->join( ic ) )
			/* The story is: FALSE either means the handler
			   showed an error message, or is doing some work
			   before the join should be confirmed. (In the
			   latter case, the caller should take care of that
			   confirmation.) TRUE means all's good, let the
			   user join the channel right away. */
			goto next;
		
		irc_channel_add_user( ic, irc->user );
		
next:
		if( comma )
		{
			s = comma + 1;
			*comma = ',';
		}
		else
			break;
	}
}