Changeset 2945c6f for root_commands.c


Ignore:
Timestamp:
2010-07-24T21:16:18Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
f1f7b5e
Parents:
ef14a83 (diff), 593971d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge ui-fix (which includes killerbee (i.e. file transfers and libpurple
support)). ui-fix rewrites the complete IRC core, fixing many things that
were broken/hacky/limited so far.

The list is too long to include here, but http://wiki.bitlbee.org/UiFix
has a summary, as does doc/CHANGES and of course the full revision history.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • root_commands.c

    ref14a83 r2945c6f  
    2626#define BITLBEE_CORE
    2727#include "commands.h"
    28 #include "crypting.h"
    2928#include "bitlbee.h"
    3029#include "help.h"
    31 #include "chat.h"
    32 
    33 #include <string.h>
    34 
    35 void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
    36 {
    37         char *cmd[IRC_MAX_ARGS];
    38         char *s;
    39         int k;
    40         char q = 0;
    41        
    42         memset( cmd, 0, sizeof( cmd ) );
    43         cmd[0] = command;
    44         k = 1;
    45         for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ )
    46                 if( *s == ' ' && !q )
    47                 {
    48                         *s = 0;
    49                         while( *++s == ' ' );
    50                         if( *s == '"' || *s == '\'' )
    51                         {
    52                                 q = *s;
    53                                 s ++;
    54                         }
    55                         if( *s )
    56                         {
    57                                 cmd[k++] = s;
    58                                 s --;
    59                         }
    60                         else
    61                         {
    62                                 break;
    63                         }
    64                 }
    65                 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
    66                 {
    67                         char *cpy;
    68                        
    69                         for( cpy = s; *cpy; cpy ++ )
    70                                 cpy[0] = cpy[1];
    71                 }
    72                 else if( *s == q )
    73                 {
    74                         q = *s = 0;
    75                 }
    76         cmd[k] = NULL;
    77        
    78         root_command( irc, cmd );
     30#include "ipc.h"
     31
     32void root_command_string( irc_t *irc, char *command )
     33{
     34        root_command( irc, split_command_parts( command ) );
    7935}
    8036
     
    9349void root_command( irc_t *irc, char *cmd[] )
    9450{       
    95         int i;
     51        int i, len;
    9652       
    9753        if( !cmd[0] )
    9854                return;
    9955       
     56        len = strlen( cmd[0] );
    10057        for( i = 0; commands[i].command; i++ )
    101                 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
    102                 {
     58                if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 )
     59                {
     60                        if( commands[i+1].command &&
     61                            g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 )
     62                                /* Only match on the first letters if the match is unique. */
     63                                break;
     64                       
    10365                        MIN_ARGS( commands[i].required_parameters );
    10466                       
     
    141103static void cmd_identify( irc_t *irc, char **cmd )
    142104{
    143         storage_status_t status = storage_load( irc, cmd[1] );
    144         char *account_on[] = { "account", "on", NULL };
    145        
    146         if( strchr( irc->umode, 'R' ) != NULL )
     105        storage_status_t status;
     106        gboolean load = TRUE;
     107        char *password = cmd[1];
     108       
     109        if( irc->status & USTATUS_IDENTIFIED )
    147110        {
    148111                irc_usermsg( irc, "You're already logged in." );
    149112                return;
    150113        }
     114       
     115        if( strncmp( cmd[1], "-no", 3 ) == 0 )
     116        {
     117                load = FALSE;
     118                password = cmd[2];
     119        }
     120        else if( strncmp( cmd[1], "-force", 6 ) == 0 )
     121        {
     122                password = cmd[2];
     123        }
     124        else if( irc->b->accounts != NULL )
     125        {
     126                irc_usermsg( irc,
     127                             "You're trying to identify yourself, but already have "
     128                             "at least one IM account set up. "
     129                             "Use \x02identify -noload\x02 or \x02identify -force\x02 "
     130                             "instead (see \x02help identify\x02)." );
     131                return;
     132        }
     133       
     134        if( password == NULL )
     135        {
     136                MIN_ARGS( 2 );
     137        }
     138       
     139        if( load )
     140                status = storage_load( irc, password );
     141        else
     142                status = storage_check_pass( irc->user->nick, password );
    151143       
    152144        switch (status) {
     
    158150                break;
    159151        case STORAGE_OK:
    160                 irc_usermsg( irc, "Password accepted, settings and accounts loaded" );
    161                 irc_setpass( irc, cmd[1] );
     152                irc_usermsg( irc, "Password accepted%s",
     153                             load ? ", settings and accounts loaded" : "" );
     154                irc_setpass( irc, password );
    162155                irc->status |= USTATUS_IDENTIFIED;
    163156                irc_umode_set( irc, "+R", 1 );
    164                 if( set_getbool( &irc->set, "auto_connect" ) )
    165                         cmd_account( irc, account_on );
     157               
     158                /* The following code is a bit hairy now. With takeover
     159                   support, we shouldn't immediately auto_connect in case
     160                   we're going to offer taking over an existing session.
     161                   Do it in 200ms since that should give the parent process
     162                   enough time to come back to us. */
     163                if( load )
     164                {
     165                        irc_channel_auto_joins( irc, NULL );
     166                        if( !set_getbool( &irc->default_channel->set, "auto_join" ) )
     167                                irc_channel_del_user( irc->default_channel, irc->user,
     168                                                      IRC_CDU_PART, "auto_join disabled "
     169                                                      "for this channel." );
     170                        if( set_getbool( &irc->b->set, "auto_connect" ) )
     171                                irc->login_source_id = b_timeout_add( 200,
     172                                        cmd_identify_finish, irc );
     173                }
     174               
     175                /* If ipc_child_identify() returns FALSE, it means we're
     176                   already sure that there's no takeover target (only
     177                   possible in 1-process daemon mode). Start auto_connect
     178                   immediately. */
     179                if( !ipc_child_identify( irc ) && load &&
     180                    set_getbool( &irc->b->set, "auto_connect" ) )
     181                        cmd_identify_finish( irc, 0, 0 );
     182               
    166183                break;
    167184        case STORAGE_OTHER_ERROR:
     
    170187                break;
    171188        }
     189}
     190
     191gboolean cmd_identify_finish( gpointer data, gint fd, b_input_condition cond )
     192{
     193        char *account_on[] = { "account", "on", NULL };
     194        irc_t *irc = data;
     195       
     196        cmd_account( irc, account_on );
     197       
     198        b_event_remove( irc->login_source_id );
     199        irc->login_source_id = -1;
     200        return FALSE;
    172201}
    173202
     
    202231        storage_status_t status;
    203232       
    204         status = storage_remove (irc->nick, cmd[1]);
     233        status = storage_remove (irc->user->nick, cmd[1]);
    205234        switch (status) {
    206235        case STORAGE_NO_SUCH_USER:
     
    214243                irc->status &= ~USTATUS_IDENTIFIED;
    215244                irc_umode_set( irc, "-R", 1 );
    216                 irc_usermsg( irc, "Account `%s' removed", irc->nick );
     245                irc_usermsg( irc, "Account `%s' removed", irc->user->nick );
    217246                break;
    218247        default:
     
    222251}
    223252
    224 struct cmd_account_del_data
    225 {
    226         account_t *a;
    227         irc_t *irc;
    228 };
    229 
    230 void cmd_account_del_yes( void *data )
    231 {
    232         struct cmd_account_del_data *cad = data;
    233         account_t *a;
    234        
    235         for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
    236        
    237         if( a == NULL )
    238         {
    239                 irc_usermsg( cad->irc, "Account already deleted" );
    240         }
    241         else if( a->ic )
    242         {
    243                 irc_usermsg( cad->irc, "Account is still logged in, can't delete" );
    244         }
    245         else
    246         {
    247                 account_del( cad->irc, a );
    248                 irc_usermsg( cad->irc, "Account deleted" );
    249         }
    250         g_free( data );
    251 }
    252 
    253 void cmd_account_del_no( void *data )
    254 {
    255         g_free( data );
     253static void cmd_save( irc_t *irc, char **cmd )
     254{
     255        if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
     256                irc_usermsg( irc, "Please create an account first" );
     257        else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
     258                irc_usermsg( irc, "Configuration saved" );
     259        else
     260                irc_usermsg( irc, "Configuration could not be saved!" );
    256261}
    257262
     
    269274typedef int (*cmd_set_checkflags)( irc_t*, set_t *set );
    270275
    271 static int cmd_set_real( irc_t *irc, char **cmd, cmd_set_findhead findhead, cmd_set_checkflags checkflags )
    272 {
    273         char *set_full = NULL, *set_name = NULL, *tmp;
    274         set_t **head;
     276static int cmd_set_real( irc_t *irc, char **cmd, set_t **head, cmd_set_checkflags checkflags )
     277{
     278        char *set_name = NULL, *value = NULL;
     279        gboolean del = FALSE;
    275280       
    276281        if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
    277282        {
    278283                MIN_ARGS( 2, 0 );
    279                 set_full = cmd[2];
    280         }
    281         else
    282                 set_full = cmd[1];
    283        
    284         if( findhead == NULL )
    285         {
    286                 set_name = set_full;
    287                
    288                 head = &irc->set;
    289         }
    290         else
    291         {
    292                 char *id;
    293                
    294                 if( ( tmp = strchr( set_full, '/' ) ) )
    295                 {
    296                         id = g_strndup( set_full, ( tmp - set_full ) );
    297                         set_name = tmp + 1;
    298                 }
    299                 else
    300                 {
    301                         id = g_strdup( set_full );
    302                 }
    303                
    304                 if( ( head = findhead( irc, id ) ) == NULL )
    305                 {
    306                         g_free( id );
    307                         irc_usermsg( irc, "Could not find setting." );
    308                         return 0;
    309                 }
    310                 g_free( id );
    311         }
    312        
    313         if( cmd[1] && cmd[2] && set_name )
     284                set_name = cmd[2];
     285                del = TRUE;
     286        }
     287        else
     288        {
     289                set_name = cmd[1];
     290                value = cmd[2];
     291        }
     292       
     293        if( set_name && ( value || del ) )
    314294        {
    315295                set_t *s = set_find( head, set_name );
     
    319299                        return 0;
    320300               
    321                 if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
     301                if( del )
    322302                        st = set_reset( head, set_name );
    323303                else
    324                         st = set_setstr( head, set_name, cmd[2] );
     304                        st = set_setstr( head, set_name, value );
    325305               
    326306                if( set_getstr( head, set_name ) == NULL )
    327307                {
     308                        /* This happens when changing the passwd, for example.
     309                           Showing these msgs instead gives slightly clearer
     310                           feedback. */
    328311                        if( st )
    329312                                irc_usermsg( irc, "Setting changed successfully" );
     
    353336}
    354337
    355 static set_t **cmd_account_set_findhead( irc_t *irc, char *id )
    356 {
    357         account_t *a;
    358        
    359         if( ( a = account_get( irc, id ) ) )
    360                 return &a->set;
    361         else
    362                 return NULL;
    363 }
    364 
    365338static int cmd_account_set_checkflags( irc_t *irc, set_t *s )
    366339{
     
    384357{
    385358        account_t *a;
     359        int len;
    386360       
    387361        if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) )
     
    391365        }
    392366       
    393         if( g_strcasecmp( cmd[1], "add" ) == 0 )
     367        len = strlen( cmd[1] );
     368       
     369        if( len >= 1 && g_strncasecmp( cmd[1], "add", len ) == 0 )
    394370        {
    395371                struct prpl *prpl;
     
    404380                        return;
    405381                }
    406 
    407                 a = account_add( irc, prpl, cmd[3], cmd[4] );
     382               
     383                for( a = irc->b->accounts; a; a = a->next )
     384                        if( a->prpl == prpl && prpl->handle_cmp( a->user, cmd[3] ) == 0 )
     385                                irc_usermsg( irc, "Warning: You already have an account with "
     386                                             "protocol `%s' and username `%s'. Are you accidentally "
     387                                             "trying to add it twice?", prpl->name, cmd[3] );
     388               
     389                a = account_add( irc->b, prpl, cmd[3], cmd[4] );
    408390                if( cmd[5] )
    409391                {
     
    414396               
    415397                irc_usermsg( irc, "Account successfully added" );
    416         }
    417         else if( g_strcasecmp( cmd[1], "del" ) == 0 )
    418         {
    419                 MIN_ARGS( 2 );
    420 
    421                 if( !( a = account_get( irc, cmd[2] ) ) )
    422                 {
    423                         irc_usermsg( irc, "Invalid account" );
    424                 }
    425                 else if( a->ic )
    426                 {
    427                         irc_usermsg( irc, "Account is still logged in, can't delete" );
    428                 }
    429                 else
    430                 {
    431                         struct cmd_account_del_data *cad;
    432                         char *msg;
    433                        
    434                         cad = g_malloc( sizeof( struct cmd_account_del_data ) );
    435                         cad->a = a;
    436                         cad->irc = irc;
    437                        
    438                         msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will "
    439                                                "also forget all your saved nicknames. If you want "
    440                                                "to change your username/password, use the `account "
    441                                                "set' command. Are you sure you want to delete this "
    442                                                "account?", a->prpl->name, a->user );
    443                         query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
    444                         g_free( msg );
    445                 }
    446         }
    447         else if( g_strcasecmp( cmd[1], "list" ) == 0 )
     398               
     399                return;
     400        }
     401        else if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 )
    448402        {
    449403                int i = 0;
     
    452406                        irc_usermsg( irc, "Account list:" );
    453407               
    454                 for( a = irc->accounts; a; a = a->next )
     408                for( a = irc->b->accounts; a; a = a->next )
    455409                {
    456410                        char *con;
     
    465419                                con = "";
    466420                       
    467                         irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con );
     421                        irc_usermsg( irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con );
    468422                       
    469423                        i ++;
    470424                }
    471425                irc_usermsg( irc, "End of account list" );
    472         }
    473         else if( g_strcasecmp( cmd[1], "on" ) == 0 )
    474         {
    475                 if( cmd[2] )
    476                 {
    477                         if( ( a = account_get( irc, cmd[2] ) ) )
    478                         {
    479                                 if( a->ic )
    480                                 {
    481                                         irc_usermsg( irc, "Account already online" );
    482                                         return;
    483                                 }
    484                                 else
    485                                 {
    486                                         account_on( irc, a );
    487                                 }
    488                         }
    489                         else
    490                         {
    491                                 irc_usermsg( irc, "Invalid account" );
    492                                 return;
    493                         }
    494                 }
    495                 else
    496                 {
    497                         if ( irc->accounts ) {
    498                                 irc_usermsg( irc, "Trying to get all accounts connected..." );
     426               
     427                return;
     428        }
     429        else if( cmd[2] )
     430        {
     431                /* Try the following two only if cmd[2] == NULL */
     432        }
     433        else if( len >= 2 && g_strncasecmp( cmd[1], "on", len ) == 0 )
     434        {
     435                if ( irc->b->accounts )
     436                {
     437                        irc_usermsg( irc, "Trying to get all accounts connected..." );
     438               
     439                        for( a = irc->b->accounts; a; a = a->next )
     440                                if( !a->ic && a->auto_connect )
     441                                        account_on( irc->b, a );
     442                }
     443                else
     444                {
     445                        irc_usermsg( irc, "No accounts known. Use `account add' to add one." );
     446                }
     447               
     448                return;
     449        }
     450        else if( len >= 2 && g_strncasecmp( cmd[1], "off", len ) == 0 )
     451        {
     452                irc_usermsg( irc, "Deactivating all active (re)connections..." );
     453               
     454                for( a = irc->b->accounts; a; a = a->next )
     455                {
     456                        if( a->ic )
     457                                account_off( irc->b, a );
     458                        else if( a->reconnect )
     459                                cancel_auto_reconnect( a );
     460                }
     461               
     462                return;
     463        }
     464       
     465        MIN_ARGS( 2 );
     466        len = strlen( cmd[2] );
     467       
     468        /* At least right now, don't accept on/off/set/del as account IDs even
     469           if they're a proper match, since people not familiar with the new
     470           syntax yet may get a confusing/nasty surprise. */
     471        if( g_strcasecmp( cmd[1], "on" ) == 0 ||
     472            g_strcasecmp( cmd[1], "off" ) == 0 ||
     473            g_strcasecmp( cmd[1], "set" ) == 0 ||
     474            g_strcasecmp( cmd[1], "del" ) == 0 ||
     475            ( a = account_get( irc->b, cmd[1] ) ) == NULL )
     476        {
     477                irc_usermsg( irc, "Could not find account `%s'. Note that the syntax "
     478                             "of the account command changed, see \x02help account\x02.", cmd[1] );
     479               
     480                return;
     481        }
     482       
     483        if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 )
     484        {
     485                if( a->ic )
     486                {
     487                        irc_usermsg( irc, "Account is still logged in, can't delete" );
     488                }
     489                else
     490                {
     491                        account_del( irc->b, a );
     492                        irc_usermsg( irc, "Account deleted" );
     493                }
     494        }
     495        else if( len >= 2 && g_strncasecmp( cmd[2], "on", len ) == 0 )
     496        {
     497                if( a->ic )
     498                        irc_usermsg( irc, "Account already online" );
     499                else
     500                        account_on( irc->b, a );
     501        }
     502        else if( len >= 2 && g_strncasecmp( cmd[2], "off", len ) == 0 )
     503        {
     504                if( a->ic )
     505                {
     506                        account_off( irc->b, a );
     507                }
     508                else if( a->reconnect )
     509                {
     510                        cancel_auto_reconnect( a );
     511                        irc_usermsg( irc, "Reconnect cancelled" );
     512                }
     513                else
     514                {
     515                        irc_usermsg( irc, "Account already offline" );
     516                }
     517        }
     518        else if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 )
     519        {
     520                cmd_set_real( irc, cmd + 2, &a->set, cmd_account_set_checkflags );
     521        }
     522        else
     523        {
     524                irc_usermsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[2] );
     525        }
     526}
     527
     528static void cmd_channel( irc_t *irc, char **cmd )
     529{
     530        irc_channel_t *ic;
     531        int len;
     532       
     533        len = strlen( cmd[1] );
     534       
     535        if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 )
     536        {
     537                GSList *l;
     538                int i = 0;
     539               
     540                if( strchr( irc->umode, 'b' ) )
     541                        irc_usermsg( irc, "Channel list:" );
     542               
     543                for( l = irc->channels; l; l = l->next )
     544                {
     545                        irc_channel_t *ic = l->data;
    499546                       
    500                                 for( a = irc->accounts; a; a = a->next )
    501                                         if( !a->ic && a->auto_connect )
    502                                                 account_on( irc, a );
    503                         }
    504                         else
    505                         {
    506                                 irc_usermsg( irc, "No accounts known. Use `account add' to add one." );
    507                         }
    508                 }
    509         }
    510         else if( g_strcasecmp( cmd[1], "off" ) == 0 )
    511         {
    512                 if( !cmd[2] )
    513                 {
    514                         irc_usermsg( irc, "Deactivating all active (re)connections..." );
     547                        irc_usermsg( irc, "%2d. %s, %s channel%s", i, ic->name,
     548                                     set_getstr( &ic->set, "type" ),
     549                                     ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : "" );
    515550                       
    516                         for( a = irc->accounts; a; a = a->next )
    517                         {
    518                                 if( a->ic )
    519                                         account_off( irc, a );
    520                                 else if( a->reconnect )
    521                                         cancel_auto_reconnect( a );
    522                         }
    523                 }
    524                 else if( ( a = account_get( irc, cmd[2] ) ) )
    525                 {
    526                         if( a->ic )
    527                         {
    528                                 account_off( irc, a );
    529                         }
    530                         else if( a->reconnect )
    531                         {
    532                                 cancel_auto_reconnect( a );
    533                                 irc_usermsg( irc, "Reconnect cancelled" );
    534                         }
    535                         else
    536                         {
    537                                 irc_usermsg( irc, "Account already offline" );
    538                                 return;
    539                         }
    540                 }
    541                 else
    542                 {
    543                         irc_usermsg( irc, "Invalid account" );
    544                         return;
    545                 }
    546         }
    547         else if( g_strcasecmp( cmd[1], "set" ) == 0 )
    548         {
    549                 MIN_ARGS( 2 );
    550                
    551                 cmd_set_real( irc, cmd + 1, cmd_account_set_findhead, cmd_account_set_checkflags );
    552         }
    553         else
    554         {
    555                 irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[1] );
     551                        i ++;
     552                }
     553                irc_usermsg( irc, "End of channel list" );
     554               
     555                return;
     556        }
     557       
     558        if( ( ic = irc_channel_get( irc, cmd[1] ) ) == NULL )
     559        {
     560                /* If this doesn't match any channel, maybe this is the short
     561                   syntax (only works when used inside a channel). */
     562                if( ( len = strlen( cmd[1] ) ) &&
     563                    g_strncasecmp( cmd[1], "set", len ) == 0 &&
     564                    ( ic = irc_channel_by_name( irc, irc->last_root_cmd ) ) )
     565                        cmd_set_real( irc, cmd + 1, &ic->set, NULL );
     566                else
     567                        irc_usermsg( irc, "Could not find channel `%s'", cmd[1] );
     568               
     569                return;
     570        }
     571       
     572        MIN_ARGS( 2 );
     573        len = strlen( cmd[2] );
     574       
     575        if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 )
     576        {
     577                cmd_set_real( irc, cmd + 2, &ic->set, NULL );
     578        }
     579        else if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 )
     580        {
     581                if( !( ic->flags & IRC_CHANNEL_JOINED ) &&
     582                    ic != ic->irc->default_channel )
     583                {
     584                        irc_usermsg( irc, "Channel %s deleted.", ic->name );
     585                        irc_channel_free( ic );
     586                }
     587                else
     588                        irc_usermsg( irc, "Couldn't remove channel (main channel %s or "
     589                                          "channels you're still in cannot be deleted).",
     590                                          irc->default_channel->name );
     591        }
     592        else
     593        {
     594                irc_usermsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] );
    556595        }
    557596}
     
    569608        }
    570609       
    571         if( !( a = account_get( irc, cmd[1] ) ) )
     610        if( !( a = account_get( irc->b, cmd[1] ) ) )
    572611        {
    573612                irc_usermsg( irc, "Invalid account" );
     
    587626                        return;
    588627                }
    589                 else if( user_find( irc, cmd[3] ) )
     628                else if( irc_user_by_name( irc, cmd[3] ) )
    590629                {
    591630                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
     
    594633                else
    595634                {
    596                         nick_set( a, cmd[2], cmd[3] );
     635                        nick_set_raw( a, cmd[2], cmd[3] );
    597636                }
    598637        }
    599638       
    600639        if( add_on_server )
    601                 a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
    602         else
    603                 /* Yeah, officially this is a call-*back*... So if we just
    604                    called add_buddy, we'll wait for the IM server to respond
    605                    before we do this. */
    606                 imcb_add_buddy( a->ic, cmd[2], NULL );
    607        
    608         irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
     640        {
     641                irc_channel_t *ic;
     642                char *s, *group = NULL;;
     643               
     644                if( ( ic = irc_channel_by_name( irc, irc->last_root_cmd ) ) &&
     645                    ( s = set_getstr( &ic->set, "fill_by" ) ) &&
     646                    strcmp( s, "group" ) == 0 &&
     647                    ( group = set_getstr( &ic->set, "group" ) ) )
     648                        irc_usermsg( irc, "Adding `%s' to contact list (group %s)",
     649                                     cmd[2], group );
     650                else
     651                        irc_usermsg( irc, "Adding `%s' to contact list", cmd[2] );
     652               
     653                a->prpl->add_buddy( a->ic, cmd[2], group );
     654        }
     655        else
     656        {
     657                bee_user_t *bu;
     658                irc_user_t *iu;
     659               
     660                /* Only for add -tmp. For regular adds, this callback will
     661                   be called once the IM server confirms. */
     662                if( ( bu = bee_user_new( irc->b, a->ic, cmd[2], BEE_USER_LOCAL ) ) &&
     663                    ( iu = bu->ui_data ) )
     664                        irc_usermsg( irc, "Temporarily assigned nickname `%s' "
     665                                     "to contact `%s'", iu->nick, cmd[2] );
     666        }
     667       
     668}
     669
     670static void cmd_remove( irc_t *irc, char **cmd )
     671{
     672        irc_user_t *iu;
     673        bee_user_t *bu;
     674        char *s;
     675       
     676        if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) )
     677        {
     678                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
     679                return;
     680        }
     681        s = g_strdup( bu->handle );
     682       
     683        bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL );
     684        nick_del( bu );
     685        if( g_slist_find( irc->users, iu ) )
     686                bee_user_free( irc->b, bu );
     687       
     688        irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
     689        g_free( s );
     690       
     691        return;
    609692}
    610693
     
    616699        if( !cmd[2] )
    617700        {
    618                 user_t *u = user_find( irc, cmd[1] );
    619                 if( !u || !u->ic )
     701                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
     702                if( !iu || !iu->bu )
    620703                {
    621704                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    622705                        return;
    623706                }
    624                 ic = u->ic;
    625                 cmd[2] = u->handle;
    626         }
    627         else if( !( a = account_get( irc, cmd[1] ) ) )
     707                ic = iu->bu->ic;
     708                cmd[2] = iu->bu->handle;
     709        }
     710        else if( !( a = account_get( irc->b, cmd[1] ) ) )
    628711        {
    629712                irc_usermsg( irc, "Invalid account" );
     
    648731static void cmd_rename( irc_t *irc, char **cmd )
    649732{
    650         user_t *u;
    651        
    652         if( g_strcasecmp( cmd[1], irc->nick ) == 0 )
    653         {
    654                 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    655         }
    656         else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    657         {
    658                 if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
    659                 {
    660                         u = user_find( irc, irc->nick );
    661                        
    662                         irc_part( irc, u, irc->channel );
    663                         g_free( irc->channel );
    664                         irc->channel = g_strdup( cmd[2] );
    665                         irc_join( irc, u, irc->channel );
    666                        
    667                         if( strcmp( cmd[0], "set_rename" ) != 0 )
    668                                 set_setstr( &irc->set, "control_channel", cmd[2] );
    669                 }
    670         }
    671         else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
     733        irc_user_t *iu, *old;
     734       
     735        iu = irc_user_by_name( irc, cmd[1] );
     736       
     737        if( iu == NULL )
     738        {
     739                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
     740        }
     741        else if( iu == irc->user )
     742        {
     743                irc_usermsg( irc, "Use /nick to change your own nickname" );
     744        }
     745        else if( !nick_ok( cmd[2] ) )
     746        {
     747                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
     748        }
     749        else if( ( old = irc_user_by_name( irc, cmd[2] ) ) && old != iu )
    672750        {
    673751                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
    674752        }
    675         else if( !nick_ok( cmd[2] ) )
    676         {
    677                 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
    678         }
    679         else if( !( u = user_find( irc, cmd[1] ) ) )
    680         {
    681                 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    682         }
    683         else
    684         {
    685                 user_rename( irc, cmd[1], cmd[2] );
    686                 irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] );
    687                 if( g_strcasecmp( cmd[1], irc->mynick ) == 0 )
    688                 {
    689                         g_free( irc->mynick );
    690                         irc->mynick = g_strdup( cmd[2] );
    691                        
     753        else
     754        {
     755                if( !irc_user_set_nick( iu, cmd[2] ) )
     756                {
     757                        irc_usermsg( irc, "Error while changing nick" );
     758                        return;
     759                }
     760               
     761                if( iu == irc->root )
     762                {
    692763                        /* If we're called internally (user did "set root_nick"),
    693764                           let's not go O(INF). :-) */
    694765                        if( strcmp( cmd[0], "set_rename" ) != 0 )
    695                                 set_setstr( &irc->set, "root_nick", cmd[2] );
    696                 }
    697                 else if( u->send_handler == buddy_send_handler )
    698                 {
    699                         nick_set( u->ic->acc, u->handle, cmd[2] );
     766                                set_setstr( &irc->b->set, "root_nick", cmd[2] );
     767                }
     768                else if( iu->bu )
     769                {
     770                        nick_set( iu->bu, cmd[2] );
    700771                }
    701772               
     
    708779        irc_t *irc = set->data;
    709780       
    710         if( strcmp( irc->mynick, new_nick ) != 0 )
    711         {
    712                 char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL };
     781        if( strcmp( irc->root->nick, new_nick ) != 0 )
     782        {
     783                char *cmd[] = { "set_rename", irc->root->nick, new_nick, NULL };
    713784               
    714785                cmd_rename( irc, cmd );
    715786        }
    716787       
    717         return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
    718 }
    719 
    720 char *set_eval_control_channel( set_t *set, char *new_name )
    721 {
    722         irc_t *irc = set->data;
    723        
    724         if( strcmp( irc->channel, new_name ) != 0 )
    725         {
    726                 char *cmd[] = { "set_rename", irc->channel, new_name, NULL };
    727                
    728                 cmd_rename( irc, cmd );
    729         }
    730        
    731         return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
    732 }
    733 
    734 static void cmd_remove( irc_t *irc, char **cmd )
    735 {
    736         user_t *u;
    737         char *s;
    738        
    739         if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )
    740         {
    741                 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
    742                 return;
    743         }
    744         s = g_strdup( u->handle );
    745        
    746         u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );
    747         nick_del( u->ic->acc, u->handle );
    748         user_del( irc, cmd[1] );
    749        
    750         irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
    751         g_free( s );
    752        
    753         return;
     788        return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID;
    754789}
    755790
     
    759794        account_t *a;
    760795       
    761         if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
     796        if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
    762797        {
    763798                char *format;
     
    772807                for( l = a->ic->deny; l; l = l->next )
    773808                {
    774                         user_t *u = user_findhandle( a->ic, l->data );
    775                         irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
     809                        bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
     810                        irc_user_t *iu = bu ? bu->ui_data : NULL;
     811                        irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
    776812                }
    777813                irc_usermsg( irc, "End of list." );
     
    781817        else if( !cmd[2] )
    782818        {
    783                 user_t *u = user_find( irc, cmd[1] );
    784                 if( !u || !u->ic )
     819                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
     820                if( !iu || !iu->bu )
    785821                {
    786822                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    787823                        return;
    788824                }
    789                 ic = u->ic;
    790                 cmd[2] = u->handle;
    791         }
    792         else if( !( a = account_get( irc, cmd[1] ) ) )
     825                ic = iu->bu->ic;
     826                cmd[2] = iu->bu->handle;
     827        }
     828        else if( !( a = account_get( irc->b, cmd[1] ) ) )
    793829        {
    794830                irc_usermsg( irc, "Invalid account" );
     
    809845                imc_rem_allow( ic, cmd[2] );
    810846                imc_add_block( ic, cmd[2] );
    811                 irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] );
     847                irc_usermsg( irc, "Buddy `%s' moved from allow- to block-list", cmd[2] );
    812848        }
    813849}
     
    818854        account_t *a;
    819855       
    820         if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
     856        if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
    821857        {
    822858                char *format;
     
    831867                for( l = a->ic->permit; l; l = l->next )
    832868                {
    833                         user_t *u = user_findhandle( a->ic, l->data );
    834                         irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
     869                        bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
     870                        irc_user_t *iu = bu ? bu->ui_data : NULL;
     871                        irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
    835872                }
    836873                irc_usermsg( irc, "End of list." );
     
    840877        else if( !cmd[2] )
    841878        {
    842                 user_t *u = user_find( irc, cmd[1] );
    843                 if( !u || !u->ic )
     879                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
     880                if( !iu || !iu->bu )
    844881                {
    845882                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    846883                        return;
    847884                }
    848                 ic = u->ic;
    849                 cmd[2] = u->handle;
    850         }
    851         else if( !( a = account_get( irc, cmd[1] ) ) )
     885                ic = iu->bu->ic;
     886                cmd[2] = iu->bu->handle;
     887        }
     888        else if( !( a = account_get( irc->b, cmd[1] ) ) )
    852889        {
    853890                irc_usermsg( irc, "Invalid account" );
     
    869906                imc_add_allow( ic, cmd[2] );
    870907               
    871                 irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] );
     908                irc_usermsg( irc, "Buddy `%s' moved from block- to allow-list", cmd[2] );
    872909        }
    873910}
     
    913950static void cmd_set( irc_t *irc, char **cmd )
    914951{
    915         cmd_set_real( irc, cmd, NULL, NULL );
    916 }
    917 
    918 static void cmd_save( irc_t *irc, char **cmd )
    919 {
    920         if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
    921                 irc_usermsg( irc, "Please create an account first" );
    922         else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
    923                 irc_usermsg( irc, "Configuration saved" );
    924         else
    925                 irc_usermsg( irc, "Configuration could not be saved!" );
     952        cmd_set_real( irc, cmd, &irc->b->set, NULL );
    926953}
    927954
     
    929956{
    930957        int online = 0, away = 0, offline = 0;
    931         user_t *u;
     958        GSList *l;
    932959        char s[256];
    933960        char *format;
     
    950977                format = "%-16.16s  %-40.40s  %s";
    951978       
    952         irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" );
    953        
    954         for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away )
    955         {
     979        irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" );
     980       
     981        for( l = irc->users; l; l = l->next )
     982        {
     983                irc_user_t *iu = l->data;
     984                bee_user_t *bu = iu->bu;
     985               
     986                if( !bu || ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE )
     987                        continue;
     988               
    956989                if( online == 1 )
    957990                {
    958991                        char st[256] = "Online";
    959992                       
    960                         if( u->status_msg )
    961                                 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
     993                        if( bu->status_msg )
     994                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg );
    962995                       
    963                         g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
    964                         irc_usermsg( irc, format, u->nick, s, st );
     996                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
     997                        irc_usermsg( irc, format, iu->nick, s, st );
    965998                }
    966999               
     
    9681001        }
    9691002
    970         for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away )
    971         {
     1003        for( l = irc->users; l; l = l->next )
     1004        {
     1005                irc_user_t *iu = l->data;
     1006                bee_user_t *bu = iu->bu;
     1007               
     1008                if( !bu || !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) )
     1009                        continue;
     1010               
    9721011                if( away == 1 )
    9731012                {
    974                         g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
    975                         irc_usermsg( irc, format, u->nick, s, u->away );
     1013                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
     1014                        irc_usermsg( irc, format, iu->nick, s, irc_user_get_away( iu ) );
    9761015                }
    9771016                n_away ++;
    9781017        }
    9791018       
    980         for( u = irc->users; u; u = u->next ) if( u->ic && !u->online )
    981         {
     1019        for( l = irc->users; l; l = l->next )
     1020        {
     1021                irc_user_t *iu = l->data;
     1022                bee_user_t *bu = iu->bu;
     1023               
     1024                if( !bu || bu->flags & BEE_USER_ONLINE )
     1025                        continue;
     1026               
    9821027                if( offline == 1 )
    9831028                {
    984                         g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
    985                         irc_usermsg( irc, format, u->nick, s, "Offline" );
     1029                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
     1030                        irc_usermsg( irc, format, iu->nick, s, "Offline" );
    9861031                }
    9871032                n_offline ++;
     
    9891034       
    9901035        irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );
    991 }
    992 
    993 static void cmd_nick( irc_t *irc, char **cmd )
    994 {
    995         account_t *a;
    996 
    997         if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )
    998         {
    999                 irc_usermsg( irc, "Invalid account");
    1000         }
    1001         else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
    1002         {
    1003                 irc_usermsg( irc, "That account is not on-line" );
    1004         }
    1005         else if ( !cmd[2] )
    1006         {
    1007                 irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );
    1008         }
    1009         else if ( !a->prpl->set_my_name )
    1010         {
    1011                 irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
    1012         }
    1013         else
    1014         {
    1015                 irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );
    1016                
    1017                 a->prpl->set_my_name( a->ic, cmd[2] );
    1018         }
    10191036}
    10201037
     
    10391056}
    10401057
    1041 static void cmd_join_chat( irc_t *irc, char **cmd )
    1042 {
    1043         irc_usermsg( irc, "This command is now obsolete. "
    1044                           "Please try the `chat' command instead." );
    1045 }
    1046 
    1047 static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )
    1048 {
    1049         struct chat *c;
    1050        
    1051         if( ( c = chat_get( irc, id ) ) )
    1052                 return &c->set;
    1053         else
    1054                 return NULL;
    1055 }
    1056 
    10571058static void cmd_chat( irc_t *irc, char **cmd )
    10581059{
    10591060        account_t *acc;
    1060         struct chat *c;
    10611061       
    10621062        if( g_strcasecmp( cmd[1], "add" ) == 0 )
    10631063        {
    10641064                char *channel, *s;
     1065                struct irc_channel *ic;
    10651066               
    10661067                MIN_ARGS( 3 );
    10671068               
    1068                 if( !( acc = account_get( irc, cmd[2] ) ) )
     1069                if( !( acc = account_get( irc->b, cmd[2] ) ) )
    10691070                {
    10701071                        irc_usermsg( irc, "Invalid account" );
     1072                        return;
     1073                }
     1074                else if( !acc->prpl->chat_join )
     1075                {
     1076                        irc_usermsg( irc, "Named chatrooms not supported on that account." );
    10711077                        return;
    10721078                }
     
    10851091                if( strchr( CTYPES, channel[0] ) == NULL )
    10861092                {
    1087                         s = g_strdup_printf( "%c%s", CTYPES[0], channel );
     1093                        s = g_strdup_printf( "#%s", channel );
    10881094                        g_free( channel );
    10891095                        channel = s;
    1090                 }
    1091                
    1092                 if( ( c = chat_add( irc, acc, cmd[3], channel ) ) )
    1093                         irc_usermsg( irc, "Chatroom added successfully." );
    1094                 else
     1096                       
     1097                        irc_channel_name_strip( channel );
     1098                }
     1099               
     1100                if( ( ic = irc_channel_new( irc, channel ) ) &&
     1101                    set_setstr( &ic->set, "type", "chat" ) &&
     1102                    set_setstr( &ic->set, "chat_type", "room" ) &&
     1103                    set_setstr( &ic->set, "account", cmd[2] ) &&
     1104                    set_setstr( &ic->set, "room", cmd[3] ) )
     1105                {
     1106                        irc_usermsg( irc, "Chatroom successfully added." );
     1107                }
     1108                else
     1109                {
     1110                        if( ic )
     1111                                irc_channel_free( ic );
     1112                       
    10951113                        irc_usermsg( irc, "Could not add chatroom." );
    1096                
     1114                }
    10971115                g_free( channel );
    10981116        }
    1099         else if( g_strcasecmp( cmd[1], "list" ) == 0 )
    1100         {
    1101                 int i = 0;
    1102                
    1103                 if( strchr( irc->umode, 'b' ) )
    1104                         irc_usermsg( irc, "Chatroom list:" );
    1105                
    1106                 for( c = irc->chatrooms; c; c = c->next )
    1107                 {
    1108                         irc_usermsg( irc, "%2d. %s(%s) %s, %s", i, c->acc->prpl->name,
    1109                                           c->acc->user, c->handle, c->channel );
    1110                        
    1111                         i ++;
    1112                 }
    1113                 irc_usermsg( irc, "End of chatroom list" );
    1114         }
    1115         else if( g_strcasecmp( cmd[1], "set" ) == 0 )
    1116         {
     1117        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
     1118        {
     1119                irc_user_t *iu;
     1120               
    11171121                MIN_ARGS( 2 );
    11181122               
    1119                 cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL );
    1120         }
    1121         else if( g_strcasecmp( cmd[1], "del" ) == 0 )
    1122         {
    1123                 MIN_ARGS( 2 );
    1124                
    1125                 if( ( c = chat_get( irc, cmd[2] ) ) )
    1126                 {
    1127                         chat_del( irc, c );
    1128                 }
    1129                 else
    1130                 {
    1131                         irc_usermsg( irc, "Could not remove chat." );
    1132                 }
    1133         }
    1134         else if( g_strcasecmp( cmd[1], "with" ) == 0 )
    1135         {
    1136                 user_t *u;
    1137                
    1138                 MIN_ARGS( 2 );
    1139                
    1140                 if( ( u = user_find( irc, cmd[2] ) ) && u->ic && u->ic->acc->prpl->chat_with )
    1141                 {
    1142                         if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
     1123                if( ( iu = irc_user_by_name( irc, cmd[2] ) ) &&
     1124                    iu->bu && iu->bu->ic->acc->prpl->chat_with )
     1125                {
     1126                        if( !iu->bu->ic->acc->prpl->chat_with( iu->bu->ic, iu->bu->handle ) )
    11431127                        {
    11441128                                irc_usermsg( irc, "(Possible) failure while trying to open "
    1145                                                   "a groupchat with %s.", u->nick );
     1129                                                  "a groupchat with %s.", iu->nick );
    11461130                        }
    11471131                }
     
    11511135                }
    11521136        }
     1137        else if( g_strcasecmp( cmd[1], "list" ) == 0 ||
     1138                 g_strcasecmp( cmd[1], "set" ) == 0 ||
     1139                 g_strcasecmp( cmd[1], "del" ) == 0 )
     1140        {
     1141                irc_usermsg( irc, "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command." );
     1142                cmd_channel( irc, cmd );
     1143        }
    11531144        else
    11541145        {
     
    11571148}
    11581149
     1150static void cmd_group( irc_t *irc, char **cmd )
     1151{
     1152        GSList *l;
     1153        int len;
     1154       
     1155        len = strlen( cmd[1] );
     1156        if( g_strncasecmp( cmd[1], "list", len ) == 0 )
     1157        {
     1158                int n = 0;
     1159               
     1160                if( strchr( irc->umode, 'b' ) )
     1161                        irc_usermsg( irc, "Group list:" );
     1162               
     1163                for( l = irc->b->groups; l; l = l->next )
     1164                {
     1165                        bee_group_t *bg = l->data;
     1166                        irc_usermsg( irc, "%d. %s", n ++, bg->name );
     1167                }
     1168                irc_usermsg( irc, "End of group list" );
     1169        }
     1170        else
     1171        {
     1172                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "group", cmd[1] );
     1173        }
     1174}
     1175
     1176static void cmd_transfer( irc_t *irc, char **cmd )
     1177{
     1178        GSList *files = irc->file_transfers;
     1179        enum { LIST, REJECT, CANCEL };
     1180        int subcmd = LIST;
     1181        int fid;
     1182
     1183        if( !files )
     1184        {
     1185                irc_usermsg( irc, "No pending transfers" );
     1186                return;
     1187        }
     1188
     1189        if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) )
     1190        {
     1191                subcmd = REJECT;
     1192        }
     1193        else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) &&
     1194                 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) )
     1195        {
     1196                subcmd = CANCEL;
     1197        }
     1198
     1199        for( ; files; files = g_slist_next( files ) )
     1200        {
     1201                file_transfer_t *file = files->data;
     1202               
     1203                switch( subcmd ) {
     1204                case LIST:
     1205                        if ( file->status == FT_STATUS_LISTENING )
     1206                                irc_usermsg( irc,
     1207                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
     1208                        else
     1209                        {
     1210                                int kb_per_s = 0;
     1211                                time_t diff = time( NULL ) - file->started ? : 1;
     1212                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
     1213                                        kb_per_s = file->bytes_transferred / 1024 / diff;
     1214                                       
     1215                                irc_usermsg( irc,
     1216                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
     1217                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
     1218                        }
     1219                        break;
     1220                case REJECT:
     1221                        if( file->status == FT_STATUS_LISTENING )
     1222                        {
     1223                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
     1224                                imcb_file_canceled( file->ic, file, "Denied by user" );
     1225                        }
     1226                        break;
     1227                case CANCEL:
     1228                        if( file->local_id == fid )
     1229                        {
     1230                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
     1231                                imcb_file_canceled( file->ic, file, "Canceled by user" );
     1232                        }
     1233                        break;
     1234                }
     1235        }
     1236}
     1237
     1238/* IMPORTANT: Keep this list sorted! The short command logic needs that. */
    11591239const command_t commands[] = {
     1240        { "account",        1, cmd_account,        0 },
     1241        { "add",            2, cmd_add,            0 },
     1242        { "allow",          1, cmd_allow,          0 },
     1243        { "blist",          0, cmd_blist,          0 },
     1244        { "block",          1, cmd_block,          0 },
     1245        { "channel",        1, cmd_channel,        0 },
     1246        { "chat",           1, cmd_chat,           0 },
     1247        { "drop",           1, cmd_drop,           0 },
     1248        { "ft",             0, cmd_transfer,       0 },
     1249        { "group",          1, cmd_group,          0 },
    11601250        { "help",           0, cmd_help,           0 },
    11611251        { "identify",       1, cmd_identify,       0 },
     1252        { "info",           1, cmd_info,           0 },
     1253        { "no",             0, cmd_yesno,          0 },
     1254        { "qlist",          0, cmd_qlist,          0 },
    11621255        { "register",       1, cmd_register,       0 },
    1163         { "drop",           1, cmd_drop,           0 },
    1164         { "account",        1, cmd_account,        0 },
    1165         { "add",            2, cmd_add,            0 },
    1166         { "info",           1, cmd_info,           0 },
     1256        { "remove",         1, cmd_remove,         0 },
    11671257        { "rename",         2, cmd_rename,         0 },
    1168         { "remove",         1, cmd_remove,         0 },
    1169         { "block",          1, cmd_block,          0 },
    1170         { "allow",          1, cmd_allow,          0 },
    11711258        { "save",           0, cmd_save,           0 },
    11721259        { "set",            0, cmd_set,            0 },
     1260        { "transfer",       0, cmd_transfer,       0 },
    11731261        { "yes",            0, cmd_yesno,          0 },
    1174         { "no",             0, cmd_yesno,          0 },
    1175         { "blist",          0, cmd_blist,          0 },
    1176         { "nick",           1, cmd_nick,           0 },
    1177         { "qlist",          0, cmd_qlist,          0 },
    1178         { "join_chat",      2, cmd_join_chat,      0 },
    1179         { "chat",           1, cmd_chat,           0 },
    11801262        { NULL }
    11811263};
Note: See TracChangeset for help on using the changeset viewer.