diff options
Diffstat (limited to 'root_commands.c')
| -rw-r--r-- | root_commands.c | 359 | 
1 files changed, 174 insertions, 185 deletions
| diff --git a/root_commands.c b/root_commands.c index e4e07605..7a4c021e 100644 --- a/root_commands.c +++ b/root_commands.c @@ -25,57 +25,15 @@  #define BITLBEE_CORE  #include "commands.h" -#include "crypting.h"  #include "bitlbee.h"  #include "help.h"  #include "chat.h"  #include <string.h> -void root_command_string( irc_t *irc, user_t *u, char *command, int flags ) +void root_command_string( irc_t *irc, char *command )  { -	char *cmd[IRC_MAX_ARGS]; -	char *s; -	int k; -	char q = 0; -	 -	memset( cmd, 0, sizeof( cmd ) ); -	cmd[0] = command; -	k = 1; -	for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ ) -		if( *s == ' ' && !q ) -		{ -			*s = 0; -			while( *++s == ' ' ); -			if( *s == '"' || *s == '\'' ) -			{ -				q = *s; -				s ++; -			} -			if( *s ) -			{ -				cmd[k++] = s; -				s --; -			} -			else -			{ -				break; -			} -		} -		else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) -		{ -			char *cpy; -			 -			for( cpy = s; *cpy; cpy ++ ) -				cpy[0] = cpy[1]; -		} -		else if( *s == q ) -		{ -			q = *s = 0; -		} -	cmd[k] = NULL; -	 -	root_command( irc, cmd ); +	root_command( irc, split_command_parts( command ) );  }  #define MIN_ARGS( x, y... )                                                    \ @@ -92,14 +50,20 @@ void root_command_string( irc_t *irc, user_t *u, char *command, int flags )  void root_command( irc_t *irc, char *cmd[] )  {	 -	int i; +	int i, len;  	if( !cmd[0] )  		return; +	len = strlen( cmd[0] );  	for( i = 0; commands[i].command; i++ ) -		if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) +		if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 )  		{ +			if( commands[i+1].command && +		            g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 ) +		        	/* Only match on the first letters if the match is unique. */ +		        	break; +		          			MIN_ARGS( commands[i].required_parameters );  			commands[i].execute( irc, cmd ); @@ -161,7 +125,7 @@ static void cmd_identify( irc_t *irc, char **cmd )  		irc_setpass( irc, cmd[1] );  		irc->status |= USTATUS_IDENTIFIED;  		irc_umode_set( irc, "+R", 1 ); -		if( set_getbool( &irc->set, "auto_connect" ) ) +		if( set_getbool( &irc->b->set, "auto_connect" ) )  			cmd_account( irc, account_on );  		break;  	case STORAGE_OTHER_ERROR: @@ -201,7 +165,7 @@ static void cmd_drop( irc_t *irc, char **cmd )  {  	storage_status_t status; -	status = storage_remove (irc->nick, cmd[1]); +	status = storage_remove (irc->user->nick, cmd[1]);  	switch (status) {  	case STORAGE_NO_SUCH_USER:  		irc_usermsg( irc, "That account does not exist" ); @@ -213,7 +177,7 @@ static void cmd_drop( irc_t *irc, char **cmd )  		irc_setpass( irc, NULL );  		irc->status &= ~USTATUS_IDENTIFIED;  		irc_umode_set( irc, "-R", 1 ); -		irc_usermsg( irc, "Account `%s' removed", irc->nick ); +		irc_usermsg( irc, "Account `%s' removed", irc->user->nick );  		break;  	default:  		irc_usermsg( irc, "Error: `%d'", status ); @@ -221,6 +185,16 @@ static void cmd_drop( irc_t *irc, char **cmd )  	}  } +static void cmd_save( irc_t *irc, char **cmd ) +{ +	if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) +		irc_usermsg( irc, "Please create an account first" ); +	else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) +		irc_usermsg( irc, "Configuration saved" ); +	else +		irc_usermsg( irc, "Configuration could not be saved!" ); +} +  struct cmd_account_del_data  {  	account_t *a; @@ -232,7 +206,7 @@ void cmd_account_del_yes( void *data )  	struct cmd_account_del_data *cad = data;  	account_t *a; -	for( a = cad->irc->accounts; a && a != cad->a; a = a->next ); +	for( a = cad->irc->b->accounts; a && a != cad->a; a = a->next );  	if( a == NULL )  	{ @@ -244,7 +218,7 @@ void cmd_account_del_yes( void *data )  	}  	else  	{ -		account_del( cad->irc, a ); +		account_del( cad->irc->b, a );  		irc_usermsg( cad->irc, "Account deleted" );  	}  	g_free( data ); @@ -285,7 +259,7 @@ static int cmd_set_real( irc_t *irc, char **cmd, cmd_set_findhead findhead, cmd_  	{  		set_name = set_full; -		head = &irc->set; +		head = &irc->b->set;  	}  	else   	{ @@ -356,7 +330,7 @@ static set_t **cmd_account_set_findhead( irc_t *irc, char *id )  {  	account_t *a; -	if( ( a = account_get( irc, id ) ) ) +	if( ( a = account_get( irc->b, id ) ) )  		return &a->set;  	else  		return NULL; @@ -404,7 +378,7 @@ static void cmd_account( irc_t *irc, char **cmd )  			return;  		} -		a = account_add( irc, prpl, cmd[3], cmd[4] ); +		a = account_add( irc->b, prpl, cmd[3], cmd[4] );  		if( cmd[5] )  		{  			irc_usermsg( irc, "Warning: Passing a servername/other flags to `account add' " @@ -418,7 +392,7 @@ static void cmd_account( irc_t *irc, char **cmd )  	{  		MIN_ARGS( 2 ); -		if( !( a = account_get( irc, cmd[2] ) ) ) +		if( !( a = account_get( irc->b, cmd[2] ) ) )  		{  			irc_usermsg( irc, "Invalid account" );  		} @@ -440,7 +414,7 @@ static void cmd_account( irc_t *irc, char **cmd )  			                       "to change your username/password, use the `account "  			                       "set' command. Are you sure you want to delete this "  			                       "account?", a->prpl->name, a->user ); -			query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad ); +			//query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );  			g_free( msg );  		}  	} @@ -451,7 +425,7 @@ static void cmd_account( irc_t *irc, char **cmd )  		if( strchr( irc->umode, 'b' ) )  			irc_usermsg( irc, "Account list:" ); -		for( a = irc->accounts; a; a = a->next ) +		for( a = irc->b->accounts; a; a = a->next )  		{  			char *con; @@ -474,7 +448,7 @@ static void cmd_account( irc_t *irc, char **cmd )  	{  		if( cmd[2] )  		{ -			if( ( a = account_get( irc, cmd[2] ) ) ) +			if( ( a = account_get( irc->b, cmd[2] ) ) )  			{  				if( a->ic )  				{ @@ -483,7 +457,7 @@ static void cmd_account( irc_t *irc, char **cmd )  				}  				else  				{ -					account_on( irc, a ); +					account_on( irc->b, a );  				}  			}  			else @@ -494,12 +468,13 @@ static void cmd_account( irc_t *irc, char **cmd )  		}  		else  		{ -			if ( irc->accounts ) { +			if ( irc->b->accounts ) +			{  				irc_usermsg( irc, "Trying to get all accounts connected..." ); -				for( a = irc->accounts; a; a = a->next ) +				for( a = irc->b->accounts; a; a = a->next )  					if( !a->ic && a->auto_connect ) -						account_on( irc, a ); +						account_on( irc->b, a );  			}   			else  			{ @@ -513,19 +488,19 @@ static void cmd_account( irc_t *irc, char **cmd )  		{  			irc_usermsg( irc, "Deactivating all active (re)connections..." ); -			for( a = irc->accounts; a; a = a->next ) +			for( a = irc->b->accounts; a; a = a->next )  			{  				if( a->ic ) -					account_off( irc, a ); +					account_off( irc->b, a );  				else if( a->reconnect )  					cancel_auto_reconnect( a );  			}  		} -		else if( ( a = account_get( irc, cmd[2] ) ) ) +		else if( ( a = account_get( irc->b, cmd[2] ) ) )  		{  			if( a->ic )  			{ -				account_off( irc, a ); +				account_off( irc->b, a );  			}  			else if( a->reconnect )  			{ @@ -568,7 +543,7 @@ static void cmd_add( irc_t *irc, char **cmd )  		cmd ++;  	} -	if( !( a = account_get( irc, cmd[1] ) ) ) +	if( !( a = account_get( irc->b, cmd[1] ) ) )  	{  		irc_usermsg( irc, "Invalid account" );  		return; @@ -586,7 +561,7 @@ static void cmd_add( irc_t *irc, char **cmd )  			irc_usermsg( irc, "The requested nick `%s' is invalid", cmd[3] );  			return;  		} -		else if( user_find( irc, cmd[3] ) ) +		else if( irc_user_by_name( irc, cmd[3] ) )  		{  			irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );  			return; @@ -600,14 +575,36 @@ static void cmd_add( irc_t *irc, char **cmd )  	if( add_on_server )  		a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );  	else -		/* Yeah, officially this is a call-*back*... So if we just -		   called add_buddy, we'll wait for the IM server to respond -		   before we do this. */ -		imcb_add_buddy( a->ic, cmd[2], NULL ); +		/* Only for add -tmp. For regular adds, this callback will +		   be called once the IM server confirms. */ +		bee_user_new( irc->b, a->ic, cmd[2] );  	irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );  } +static void cmd_remove( irc_t *irc, char **cmd ) +{ +	irc_user_t *iu; +	bee_user_t *bu; +	char *s; +	 +	if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) ) +	{ +		irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); +		return; +	} +	s = g_strdup( bu->handle ); +	 +	bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL ); +	nick_del( bu->ic->acc, bu->handle ); +	//TODO(wilmer): bee_user_free() and/or let the IM mod do it? irc_user_free( irc, cmd[1] ); +	 +	irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); +	g_free( s ); +	 +	return; +} +  static void cmd_info( irc_t *irc, char **cmd )  {  	struct im_connection *ic; @@ -615,16 +612,16 @@ static void cmd_info( irc_t *irc, char **cmd )  	if( !cmd[2] )  	{ -		user_t *u = user_find( irc, cmd[1] ); -		if( !u || !u->ic ) +		irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); +		if( !iu || !iu->bu )  		{  			irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );  			return;  		} -		ic = u->ic; -		cmd[2] = u->handle; +		ic = iu->bu->ic; +		cmd[2] = iu->bu->handle;  	} -	else if( !( a = account_get( irc, cmd[1] ) ) ) +	else if( !( a = account_get( irc->b, cmd[1] ) ) )  	{  		irc_usermsg( irc, "Invalid account" );  		return; @@ -647,62 +644,51 @@ static void cmd_info( irc_t *irc, char **cmd )  static void cmd_rename( irc_t *irc, char **cmd )  { -	user_t *u; +	irc_user_t *iu; -	if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) -	{ -		irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); -	} -	else if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) +	iu = irc_user_by_name( irc, cmd[1] ); +	 +	if( iu == NULL )  	{ -		if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) ) -		{ -			u = user_find( irc, irc->nick ); -			 -			irc_part( irc, u, irc->channel ); -			g_free( irc->channel ); -			irc->channel = g_strdup( cmd[2] ); -			irc_join( irc, u, irc->channel ); -			 -			if( strcmp( cmd[0], "set_rename" ) != 0 ) -				set_setstr( &irc->set, "control_channel", cmd[2] ); -		} +		irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );  	} -	else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) +	else if( iu == irc->user )  	{ -		irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); +		irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );  	}  	else if( !nick_ok( cmd[2] ) )  	{  		irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );  	} -	else if( !( u = user_find( irc, cmd[1] ) ) ) +	else if( irc_user_by_name( irc, cmd[2] ) )  	{ -		irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); +		irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );  	}  	else  	{ -		user_rename( irc, cmd[1], cmd[2] ); -		irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] ); -		if( g_strcasecmp( cmd[1], irc->mynick ) == 0 ) +		if( !irc_user_set_nick( iu, cmd[2] ) ) +		{ +			irc_usermsg( irc, "Error while changing nick" ); +			return; +		} +		 +		if( iu == irc->root )  		{ -			g_free( irc->mynick ); -			irc->mynick = g_strdup( cmd[2] ); -			  			/* If we're called internally (user did "set root_nick"),  			   let's not go O(INF). :-) */  			if( strcmp( cmd[0], "set_rename" ) != 0 ) -				set_setstr( &irc->set, "root_nick", cmd[2] ); +				set_setstr( &irc->b->set, "root_nick", cmd[2] );  		} -		else if( u->send_handler == buddy_send_handler ) +		else if( iu->bu )  		{ -			nick_set( u->ic->acc, u->handle, cmd[2] ); +			nick_set( iu->bu->ic->acc, iu->bu->handle, cmd[2] );  		}  		irc_usermsg( irc, "Nick successfully changed" );  	}  } +#if 0  char *set_eval_root_nick( set_t *set, char *new_nick )  {  	irc_t *irc = set->data; @@ -731,28 +717,6 @@ char *set_eval_control_channel( set_t *set, char *new_name )  	return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;  } -static void cmd_remove( irc_t *irc, char **cmd ) -{ -	user_t *u; -	char *s; -	 -	if( !( u = user_find( irc, cmd[1] ) ) || !u->ic ) -	{ -		irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); -		return; -	} -	s = g_strdup( u->handle ); -	 -	u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL ); -	nick_del( u->ic->acc, u->handle ); -	user_del( irc, cmd[1] ); -	 -	irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); -	g_free( s ); -	 -	return; -} -  static void cmd_block( irc_t *irc, char **cmd )  {  	struct im_connection *ic; @@ -871,6 +835,7 @@ static void cmd_allow( irc_t *irc, char **cmd )  		irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] );  	}  } +#endif  static void cmd_yesno( irc_t *irc, char **cmd )  { @@ -915,16 +880,7 @@ static void cmd_set( irc_t *irc, char **cmd )  	cmd_set_real( irc, cmd, NULL, NULL );  } -static void cmd_save( irc_t *irc, char **cmd ) -{ -	if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) -		irc_usermsg( irc, "Please create an account first" ); -	else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) -		irc_usermsg( irc, "Configuration saved" ); -	else -		irc_usermsg( irc, "Configuration could not be saved!" ); -} - +#if 0  static void cmd_blist( irc_t *irc, char **cmd )  {  	int online = 0, away = 0, offline = 0; @@ -990,34 +946,6 @@ static void cmd_blist( irc_t *irc, char **cmd )  	irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );  } -static void cmd_nick( irc_t *irc, char **cmd )  -{ -	account_t *a; - -	if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) ) -	{ -		irc_usermsg( irc, "Invalid account"); -	} -	else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) ) -	{ -		irc_usermsg( irc, "That account is not on-line" ); -	} -	else if ( !cmd[2] )  -	{ -		irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" ); -	} -	else if ( !a->prpl->set_my_name )  -	{ -		irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); -	} -	else -	{ -		irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); -		 -		a->prpl->set_my_name( a->ic, cmd[2] ); -	} -} -  static void cmd_qlist( irc_t *irc, char **cmd )  {  	query_t *q = irc->queries; @@ -1038,12 +966,6 @@ static void cmd_qlist( irc_t *irc, char **cmd )  			irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );  } -static void cmd_join_chat( irc_t *irc, char **cmd ) -{ -	irc_usermsg( irc, "This command is now obsolete. " -	                  "Please try the `chat' command instead." ); -} -  static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )  {  	struct chat *c; @@ -1156,26 +1078,93 @@ static void cmd_chat( irc_t *irc, char **cmd )  	}  } +static void cmd_transfer( irc_t *irc, char **cmd ) +{ +	GSList *files = irc->file_transfers; +	enum { LIST, REJECT, CANCEL }; +	int subcmd = LIST; +	int fid; + +	if( !files ) +	{ +		irc_usermsg( irc, "No pending transfers" ); +		return; +	} + +	if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) ) +	{ +		subcmd = REJECT; +	} +	else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) &&  +		 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) ) +	{ +		subcmd = CANCEL; +	} + +	for( ; files; files = g_slist_next( files ) ) +	{ +		file_transfer_t *file = files->data; +		 +		switch( subcmd ) { +		case LIST: +			if ( file->status == FT_STATUS_LISTENING ) +				irc_usermsg( irc,  +					"Pending file(id %d): %s (Listening...)", file->local_id, file->file_name); +			else  +			{ +				int kb_per_s = 0; +				time_t diff = time( NULL ) - file->started ? : 1; +				if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) ) +					kb_per_s = file->bytes_transferred / 1024 / diff; +					 +				irc_usermsg( irc,  +					"Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,  +					file->bytes_transferred/1024, file->file_size/1024, kb_per_s); +			} +			break; +		case REJECT: +			if( file->status == FT_STATUS_LISTENING ) +			{ +				irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name ); +				imcb_file_canceled( file, "Denied by user" ); +			} +			break; +		case CANCEL: +			if( file->local_id == fid ) +			{ +				irc_usermsg( irc, "Canceling file transfer for %s", file->file_name ); +				imcb_file_canceled( file, "Canceled by user" ); +			} +			break; +		} +	} +} +#endif + +/* IMPORTANT: Keep this list sorted! The short command logic needs that. */  const command_t commands[] = { -	{ "help",           0, cmd_help,           0 },  -	{ "identify",       1, cmd_identify,       0 }, -	{ "register",       1, cmd_register,       0 }, -	{ "drop",           1, cmd_drop,           0 },  	{ "account",        1, cmd_account,        0 },  	{ "add",            2, cmd_add,            0 }, +	{ "drop",           1, cmd_drop,           0 }, +	{ "help",           0, cmd_help,           0 },  +	{ "identify",       1, cmd_identify,       0 },  	{ "info",           1, cmd_info,           0 }, -	{ "rename",         2, cmd_rename,         0 }, +	{ "no",             0, cmd_yesno,          0 }, +	{ "register",       1, cmd_register,       0 },  	{ "remove",         1, cmd_remove,         0 }, -	{ "block",          1, cmd_block,          0 }, -	{ "allow",          1, cmd_allow,          0 }, +	{ "rename",         2, cmd_rename,         0 },  	{ "save",           0, cmd_save,           0 },  	{ "set",            0, cmd_set,            0 },  	{ "yes",            0, cmd_yesno,          0 }, -	{ "no",             0, cmd_yesno,          0 }, +#if 0 +	{ "allow",          1, cmd_allow,          0 },  	{ "blist",          0, cmd_blist,          0 }, -	{ "nick",           1, cmd_nick,           0 }, -	{ "qlist",          0, cmd_qlist,          0 }, -	{ "join_chat",      2, cmd_join_chat,      0 }, +	{ "block",          1, cmd_block,          0 },  	{ "chat",           1, cmd_chat,           0 }, +	{ "ft",             0, cmd_transfer,       0 }, +	{ "join_chat",      2, cmd_join_chat,      0 }, +	{ "qlist",          0, cmd_qlist,          0 }, +	{ "transfer",       0, cmd_transfer,       0 }, +#endif  	{ NULL }  }; | 
