source: root_commands.c @ f1d488e

Last change on this file since f1d488e was f1d488e, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-07-18T15:04:19Z

Add some context sensitivity to the "add" command: If it's used in a
group-specific control channel, automatically add the person to that group.

Also added the "group list" command I planned for a while already.

  • Property mode set to 100644
File size: 30.3 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[0baed0d]4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
7/* User manager (root) commands                                         */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "commands.h"
28#include "bitlbee.h"
29#include "help.h"
[f1c2b21]30#include "ipc.h"
[b7d3cc34]31
[280c56a]32void root_command_string( irc_t *irc, char *command )
[7e563ed]33{
[24b8bbb]34        root_command( irc, split_command_parts( command ) );
[7e563ed]35}
36
[3b99524]37#define MIN_ARGS( x, y... )                                                    \
38        do                                                                     \
39        {                                                                      \
[07054a5]40                int blaat;                                                     \
41                for( blaat = 0; blaat <= x; blaat ++ )                         \
42                        if( cmd[blaat] == NULL )                               \
[3b99524]43                        {                                                      \
44                                irc_usermsg( irc, "Not enough parameters given (need %d).", x ); \
45                                return y;                                      \
46                        }                                                      \
47        } while( 0 )
48
[f73b969]49void root_command( irc_t *irc, char *cmd[] )
[7e563ed]50{       
[6c56f42]51        int i, len;
[7e563ed]52       
53        if( !cmd[0] )
[f73b969]54                return;
[7e563ed]55       
[6c56f42]56        len = strlen( cmd[0] );
[7e563ed]57        for( i = 0; commands[i].command; i++ )
[6c56f42]58                if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 )
[7e563ed]59                {
[6c56f42]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                       
[3b99524]65                        MIN_ARGS( commands[i].required_parameters );
66                       
[7e563ed]67                        commands[i].execute( irc, cmd );
[f73b969]68                        return;
[7e563ed]69                }
70       
71        irc_usermsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] );
72}
73
[f73b969]74static void cmd_help( irc_t *irc, char **cmd )
[b7d3cc34]75{
76        char param[80];
77        int i;
78        char *s;
79       
80        memset( param, 0, sizeof(param) );
81        for ( i = 1; (cmd[i] != NULL && ( strlen(param) < (sizeof(param)-1) ) ); i++ ) {
82                if ( i != 1 )   // prepend space except for the first parameter
83                        strcat(param, " ");
84                strncat( param, cmd[i], sizeof(param) - strlen(param) - 1 );
85        }
86
87        s = help_get( &(global.help), param );
88        if( !s ) s = help_get( &(global.help), "" );
89       
90        if( s )
91        {
92                irc_usermsg( irc, "%s", s );
93                g_free( s );
94        }
95        else
96        {
97                irc_usermsg( irc, "Error opening helpfile." );
98        }
99}
100
[90bbb0e]101static void cmd_account( irc_t *irc, char **cmd );
102
[f73b969]103static void cmd_identify( irc_t *irc, char **cmd )
[b7d3cc34]104{
[92cb8c4]105        storage_status_t status;
106        gboolean load = TRUE;
107        char *password = cmd[1];
[b7d3cc34]108       
[92cb8c4]109        if( irc->status & USTATUS_IDENTIFIED )
[e9cf291]110        {
111                irc_usermsg( irc, "You're already logged in." );
112                return;
113        }
114       
[92cb8c4]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 );
143       
[09adf08]144        switch (status) {
145        case STORAGE_INVALID_PASSWORD:
[b7d3cc34]146                irc_usermsg( irc, "Incorrect password" );
[09adf08]147                break;
148        case STORAGE_NO_SUCH_USER:
[b7d3cc34]149                irc_usermsg( irc, "The nick is (probably) not registered" );
[09adf08]150                break;
151        case STORAGE_OK:
[92cb8c4]152                irc_usermsg( irc, "Password accepted%s",
153                             load ? ", settings and accounts loaded" : "" );
154                irc_setpass( irc, password );
[3183c21]155                irc->status |= USTATUS_IDENTIFIED;
[238f828]156                irc_umode_set( irc, "+R", 1 );
[6c2404e]157               
[e92c4f4]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 )
[6c2404e]164                {
[e92c4f4]165                        irc_channel_auto_joins( irc, NULL );
[fe4f28f]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." );
[e92c4f4]170                        if( set_getbool( &irc->b->set, "auto_connect" ) )
[6c2404e]171                                irc->login_source_id = b_timeout_add( 200,
172                                        cmd_identify_finish, irc );
173                }
[e92c4f4]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" ) )
[6c2404e]181                        cmd_identify_finish( irc, 0, 0 );
182               
[09adf08]183                break;
[c121f89]184        case STORAGE_OTHER_ERROR:
[09adf08]185        default:
[c121f89]186                irc_usermsg( irc, "Unknown error while loading configuration" );
[09adf08]187                break;
[b7d3cc34]188        }
189}
190
[6c2404e]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       
[af9f2ca]198        b_event_remove( irc->login_source_id );
[f545372]199        irc->login_source_id = -1;
[6c2404e]200        return FALSE;
201}
202
[f73b969]203static void cmd_register( irc_t *irc, char **cmd )
[b7d3cc34]204{
205        if( global.conf->authmode == AUTHMODE_REGISTERED )
206        {
207                irc_usermsg( irc, "This server does not allow registering new accounts" );
[f73b969]208                return;
[b7d3cc34]209        }
[1ee6c18]210
[3183c21]211        switch( storage_save( irc, cmd[1], FALSE ) ) {
[a1f17d4]212                case STORAGE_ALREADY_EXISTS:
213                        irc_usermsg( irc, "Nick is already registered" );
214                        break;
215                       
216                case STORAGE_OK:
[0383943]217                        irc_usermsg( irc, "Account successfully created" );
[3183c21]218                        irc_setpass( irc, cmd[1] );
[79e826a]219                        irc->status |= USTATUS_IDENTIFIED;
[238f828]220                        irc_umode_set( irc, "+R", 1 );
[a1f17d4]221                        break;
222
223                default:
224                        irc_usermsg( irc, "Error registering" );
225                        break;
[b7d3cc34]226        }
227}
228
[f73b969]229static void cmd_drop( irc_t *irc, char **cmd )
[b7d3cc34]230{
[a1f17d4]231        storage_status_t status;
232       
[1f92a58]233        status = storage_remove (irc->user->nick, cmd[1]);
[a1f17d4]234        switch (status) {
235        case STORAGE_NO_SUCH_USER:
[b7d3cc34]236                irc_usermsg( irc, "That account does not exist" );
[f73b969]237                break;
[a1f17d4]238        case STORAGE_INVALID_PASSWORD:
[1ee6c18]239                irc_usermsg( irc, "Password invalid" );
[f73b969]240                break;
[a1f17d4]241        case STORAGE_OK:
[7cad7b4]242                irc_setpass( irc, NULL );
[79e826a]243                irc->status &= ~USTATUS_IDENTIFIED;
[238f828]244                irc_umode_set( irc, "-R", 1 );
[1f92a58]245                irc_usermsg( irc, "Account `%s' removed", irc->user->nick );
[f73b969]246                break;
[a1f17d4]247        default:
[30ce1ce]248                irc_usermsg( irc, "Error: `%d'", status );
[f73b969]249                break;
[b7d3cc34]250        }
251}
[1f92a58]252
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!" );
261}
[b7d3cc34]262
[f536a99]263static void cmd_showset( irc_t *irc, set_t **head, char *key )
[f3579fd]264{
[f536a99]265        char *val;
[f3579fd]266       
[f536a99]267        if( ( val = set_getstr( head, key ) ) )
268                irc_usermsg( irc, "%s = `%s'", key, val );
[f3579fd]269        else
[f536a99]270                irc_usermsg( irc, "%s is empty", key );
[f3579fd]271}
272
[e7bc722]273typedef set_t** (*cmd_set_findhead)( irc_t*, char* );
[c05eb5b]274typedef int (*cmd_set_checkflags)( irc_t*, set_t *set );
[e7bc722]275
[e907683]276static int cmd_set_real( irc_t *irc, char **cmd, set_t **head, cmd_set_checkflags checkflags )
[e7bc722]277{
[e907683]278        char *set_name = NULL, *value = NULL;
279        gboolean del = FALSE;
[e7bc722]280       
281        if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
[d4810df]282        {
283                MIN_ARGS( 2, 0 );
[e907683]284                set_name = cmd[2];
285                del = TRUE;
[d4810df]286        }
[e7bc722]287        else
288        {
[e907683]289                set_name = cmd[1];
290                value = cmd[2];
[e7bc722]291        }
292       
[e907683]293        if( set_name && ( value || del ) )
[e7bc722]294        {
295                set_t *s = set_find( head, set_name );
296                int st;
297               
[8a08d92]298                if( s && checkflags && checkflags( irc, s ) == 0 )
[e7bc722]299                        return 0;
300               
[e907683]301                if( del )
[e7bc722]302                        st = set_reset( head, set_name );
303                else
[e907683]304                        st = set_setstr( head, set_name, value );
[e7bc722]305               
306                if( set_getstr( head, set_name ) == NULL )
307                {
[e907683]308                        /* This happens when changing the passwd, for example.
309                           Showing these msgs instead gives slightly clearer
310                           feedback. */
[e7bc722]311                        if( st )
312                                irc_usermsg( irc, "Setting changed successfully" );
313                        else
314                                irc_usermsg( irc, "Failed to change setting" );
315                }
316                else
317                {
318                        cmd_showset( irc, head, set_name );
319                }
320        }
321        else if( set_name )
322        {
323                cmd_showset( irc, head, set_name );
324        }
325        else
326        {
327                set_t *s = *head;
328                while( s )
329                {
330                        cmd_showset( irc, &s, s->key );
331                        s = s->next;
332                }
333        }
334       
335        return 1;
336}
337
[c05eb5b]338static int cmd_account_set_checkflags( irc_t *irc, set_t *s )
339{
340        account_t *a = s->data;
341       
342        if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY )
343        {
344                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" );
345                return 0;
346        }
347        else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY )
348        {
349                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" );
350                return 0;
351        }
352       
353        return 1;
354}
355
[f73b969]356static void cmd_account( irc_t *irc, char **cmd )
[b7d3cc34]357{
358        account_t *a;
[c7eb771]359        int len;
[b7d3cc34]360       
[3af70b0]361        if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) )
[b7d3cc34]362        {
363                irc_usermsg( irc, "This server only accepts registered users" );
[f73b969]364                return;
[b7d3cc34]365        }
366       
[c7eb771]367        len = strlen( cmd[1] );
368       
369        if( len >= 1 && g_strncasecmp( cmd[1], "add", len ) == 0 )
[b7d3cc34]370        {
[7b23afd]371                struct prpl *prpl;
[b7d3cc34]372               
[3b99524]373                MIN_ARGS( 4 );
[b7d3cc34]374               
[a9a7287]375                prpl = find_protocol( cmd[2] );
[b7d3cc34]376               
[7b23afd]377                if( prpl == NULL )
[b7d3cc34]378                {
379                        irc_usermsg( irc, "Unknown protocol" );
[f73b969]380                        return;
[b7d3cc34]381                }
382
[d860a8d]383                a = account_add( irc->b, prpl, cmd[3], cmd[4] );
[b7d3cc34]384                if( cmd[5] )
[30ce1ce]385                {
386                        irc_usermsg( irc, "Warning: Passing a servername/other flags to `account add' "
387                                          "is now deprecated. Use `account set' instead." );
[5100caa]388                        set_setstr( &a->set, "server", cmd[5] );
[30ce1ce]389                }
[b7d3cc34]390               
391                irc_usermsg( irc, "Account successfully added" );
[e907683]392               
393                return;
[b7d3cc34]394        }
[c7eb771]395        else if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 )
[b7d3cc34]396        {
397                int i = 0;
398               
[e6e1f18]399                if( strchr( irc->umode, 'b' ) )
400                        irc_usermsg( irc, "Account list:" );
401               
[d860a8d]402                for( a = irc->b->accounts; a; a = a->next )
[b7d3cc34]403                {
404                        char *con;
405                       
[0da65d5]406                        if( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) )
[b7d3cc34]407                                con = " (connected)";
[0da65d5]408                        else if( a->ic )
[b7d3cc34]409                                con = " (connecting)";
410                        else if( a->reconnect )
411                                con = " (awaiting reconnect)";
412                        else
413                                con = "";
414                       
[7b23afd]415                        irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con );
[b7d3cc34]416                       
417                        i ++;
418                }
419                irc_usermsg( irc, "End of account list" );
[e907683]420               
421                return;
422        }
423        else if( cmd[2] )
424        {
425                /* Try the following two only if cmd[2] == NULL */
[b7d3cc34]426        }
[c7eb771]427        else if( len >= 2 && g_strncasecmp( cmd[1], "on", len ) == 0 )
[b7d3cc34]428        {
[e907683]429                if ( irc->b->accounts )
[b7d3cc34]430                {
[e907683]431                        irc_usermsg( irc, "Trying to get all accounts connected..." );
432               
433                        for( a = irc->b->accounts; a; a = a->next )
434                                if( !a->ic && a->auto_connect )
[d860a8d]435                                        account_on( irc->b, a );
[e907683]436                } 
[b7d3cc34]437                else
438                {
[e907683]439                        irc_usermsg( irc, "No accounts known. Use `account add' to add one." );
[b7d3cc34]440                }
[e907683]441               
442                return;
[b7d3cc34]443        }
[c7eb771]444        else if( len >= 2 && g_strncasecmp( cmd[1], "off", len ) == 0 )
[b7d3cc34]445        {
[e907683]446                irc_usermsg( irc, "Deactivating all active (re)connections..." );
447               
448                for( a = irc->b->accounts; a; a = a->next )
[b7d3cc34]449                {
[0da65d5]450                        if( a->ic )
[d860a8d]451                                account_off( irc->b, a );
[b7d3cc34]452                        else if( a->reconnect )
453                                cancel_auto_reconnect( a );
[e907683]454                }
455               
456                return;
457        }
458       
459        MIN_ARGS( 2 );
[c7eb771]460        len = strlen( cmd[2] );
[e907683]461       
462        /* At least right now, don't accept on/off/set/del as account IDs even
463           if they're a proper match, since people not familiar with the new
464           syntax yet may get a confusing/nasty surprise. */
465        if( g_strcasecmp( cmd[1], "on" ) == 0 ||
466            g_strcasecmp( cmd[1], "off" ) == 0 ||
467            g_strcasecmp( cmd[1], "set" ) == 0 ||
468            g_strcasecmp( cmd[1], "del" ) == 0 ||
469            ( a = account_get( irc->b, cmd[1] ) ) == NULL )
470        {
471                irc_usermsg( irc, "Could not find account `%s'. Note that the syntax "
472                             "of the account command changed, see \x02help account\x02.", cmd[1] );
473               
474                return;
475        }
476       
[c7eb771]477        if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 )
[e907683]478        {
479                if( a->ic )
480                {
481                        irc_usermsg( irc, "Account is still logged in, can't delete" );
[b7d3cc34]482                }
483                else
484                {
[e907683]485                        account_del( irc->b, a );
486                        irc_usermsg( irc, "Account deleted" );
[b7d3cc34]487                }
488        }
[c7eb771]489        else if( len >= 2 && g_strncasecmp( cmd[2], "on", len ) == 0 )
[5100caa]490        {
[e907683]491                if( a->ic )
492                        irc_usermsg( irc, "Account already online" );
493                else
494                        account_on( irc->b, a );
495        }
[c7eb771]496        else if( len >= 2 && g_strncasecmp( cmd[2], "off", len ) == 0 )
[e907683]497        {
498                if( a->ic )
499                {
500                        account_off( irc->b, a );
501                }
502                else if( a->reconnect )
503                {
504                        cancel_auto_reconnect( a );
505                        irc_usermsg( irc, "Reconnect cancelled" );
506                }
507                else
508                {
509                        irc_usermsg( irc, "Account already offline" );
510                }
511        }
[c7eb771]512        else if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 )
[e907683]513        {
514                cmd_set_real( irc, cmd + 2, &a->set, cmd_account_set_checkflags );
[5100caa]515        }
[b7d3cc34]516        else
517        {
[e907683]518                irc_usermsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[2] );
[b7d3cc34]519        }
520}
521
[e907683]522static void cmd_channel( irc_t *irc, char **cmd )
[c133d4b8]523{
524        irc_channel_t *ic;
[c7eb771]525        int len;
526       
527        len = strlen( cmd[1] );
[c133d4b8]528       
[c7eb771]529        if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 )
[36562b0]530        {
531                GSList *l;
532                int i = 0;
533               
534                if( strchr( irc->umode, 'b' ) )
535                        irc_usermsg( irc, "Channel list:" );
536               
537                for( l = irc->channels; l; l = l->next )
538                {
539                        irc_channel_t *ic = l->data;
540                       
541                        irc_usermsg( irc, "%2d. %s, %s channel%s", i, ic->name,
542                                     set_getstr( &ic->set, "type" ),
543                                     ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : "" );
544                       
545                        i ++;
546                }
547                irc_usermsg( irc, "End of channel list" );
[e907683]548               
549                return;
[36562b0]550        }
[e907683]551       
552        MIN_ARGS( 2 );
[c7eb771]553        len = strlen( cmd[2] );
[e907683]554       
555        if( ( ic = irc_channel_get( irc, cmd[1] ) ) == NULL )
[a4d920b]556        {
[e907683]557                irc_usermsg( irc, "Could not find channel `%s'", cmd[1] );
558                return;
559        }
560       
[c7eb771]561        if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 )
[e907683]562        {
563                cmd_set_real( irc, cmd + 2, &ic->set, NULL );
564        }
[c7eb771]565        else if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 )
[e907683]566        {
567                if( !( ic->flags & IRC_CHANNEL_JOINED ) &&
[a4d920b]568                    ic != ic->irc->default_channel )
569                {
570                        irc_usermsg( irc, "Channel %s deleted.", ic->name );
571                        irc_channel_free( ic );
572                }
573                else
574                        irc_usermsg( irc, "Couldn't remove channel (main channel %s or "
575                                          "channels you're still in cannot be deleted).",
[5266354]576                                          irc->default_channel->name );
[a4d920b]577        }
[c133d4b8]578        else
579        {
[e907683]580                irc_usermsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] );
[c133d4b8]581        }
582}
583
[f73b969]584static void cmd_add( irc_t *irc, char **cmd )
[b7d3cc34]585{
586        account_t *a;
[f0cb961]587        int add_on_server = 1;
[f8de26f]588       
589        if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
590        {
[77fc000c]591                MIN_ARGS( 3 );
[f0cb961]592                add_on_server = 0;
[7adc657]593                cmd ++;
[f8de26f]594        }
[b7d3cc34]595       
[dbb0ce3]596        if( !( a = account_get( irc->b, cmd[1] ) ) )
[b7d3cc34]597        {
598                irc_usermsg( irc, "Invalid account" );
[f73b969]599                return;
[b7d3cc34]600        }
[0da65d5]601        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]602        {
603                irc_usermsg( irc, "That account is not on-line" );
[f73b969]604                return;
[b7d3cc34]605        }
606       
607        if( cmd[3] )
608        {
609                if( !nick_ok( cmd[3] ) )
610                {
611                        irc_usermsg( irc, "The requested nick `%s' is invalid", cmd[3] );
[f73b969]612                        return;
[b7d3cc34]613                }
[dbb0ce3]614                else if( irc_user_by_name( irc, cmd[3] ) )
[b7d3cc34]615                {
616                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
[f73b969]617                        return;
[b7d3cc34]618                }
619                else
620                {
[b1f818b]621                        nick_set_raw( a, cmd[2], cmd[3] );
[b7d3cc34]622                }
623        }
[f8de26f]624       
[f0cb961]625        if( add_on_server )
[f1d488e]626        {
627                irc_channel_t *ic;
628                char *s, *group = NULL;;
629               
630                if( ( ic = irc_channel_by_name( irc, irc->last_root_cmd ) ) &&
631                    ( s = set_getstr( &ic->set, "fill_by" ) ) &&
632                    strcmp( s, "group" ) == 0 &&
633                    ( group = set_getstr( &ic->set, "group" ) ) )
634                        irc_usermsg( irc, "Adding `%s' to contact list (group %s)",
635                                     cmd[2], group );
636                else
637                        irc_usermsg( irc, "Adding `%s' to contact list", cmd[2] );
638               
639                a->prpl->add_buddy( a->ic, cmd[2], group );
640        }
[7adc657]641        else
[f1d488e]642        {
643                bee_user_t *bu;
644                irc_user_t *iu;
645               
[dbb0ce3]646                /* Only for add -tmp. For regular adds, this callback will
647                   be called once the IM server confirms. */
[f1d488e]648                if( ( bu = bee_user_new( irc->b, a->ic, cmd[2], BEE_USER_LOCAL ) ) &&
649                    ( iu = bu->ui_data ) )
650                        irc_usermsg( irc, "Temporarily assigned nickname `%s' "
651                                     "to contact `%s'", iu->nick, cmd[2] );
652        }
[f0cb961]653       
[b7d3cc34]654}
655
[dbb0ce3]656static void cmd_remove( irc_t *irc, char **cmd )
657{
658        irc_user_t *iu;
659        bee_user_t *bu;
660        char *s;
661       
662        if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) )
663        {
664                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
665                return;
666        }
667        s = g_strdup( bu->handle );
668       
669        bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL );
[b1f818b]670        nick_del( bu );
[5e98ff0]671        if( g_slist_find( irc->users, iu ) )
672                bee_user_free( irc->b, bu );
[dbb0ce3]673       
674        irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
675        g_free( s );
676       
677        return;
678}
679
[f73b969]680static void cmd_info( irc_t *irc, char **cmd )
[b7d3cc34]681{
[0da65d5]682        struct im_connection *ic;
[b7d3cc34]683        account_t *a;
684       
685        if( !cmd[2] )
686        {
[aa44bdd]687                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
688                if( !iu || !iu->bu )
[b7d3cc34]689                {
690                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]691                        return;
[b7d3cc34]692                }
[aa44bdd]693                ic = iu->bu->ic;
694                cmd[2] = iu->bu->handle;
[b7d3cc34]695        }
[aa44bdd]696        else if( !( a = account_get( irc->b, cmd[1] ) ) )
[b7d3cc34]697        {
698                irc_usermsg( irc, "Invalid account" );
[f73b969]699                return;
[b7d3cc34]700        }
[0da65d5]701        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]702        {
703                irc_usermsg( irc, "That account is not on-line" );
[f73b969]704                return;
[b7d3cc34]705        }
706       
[0da65d5]707        if( !ic->acc->prpl->get_info )
[b7d3cc34]708        {
709                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
710        }
[f73b969]711        else
712        {
[0da65d5]713                ic->acc->prpl->get_info( ic, cmd[2] );
[f73b969]714        }
[b7d3cc34]715}
716
[f73b969]717static void cmd_rename( irc_t *irc, char **cmd )
[b7d3cc34]718{
[9a9b520]719        irc_user_t *iu, *old;
[b7d3cc34]720       
[57c96f7]721        iu = irc_user_by_name( irc, cmd[1] );
722       
723        if( iu == NULL )
[0baed0d]724        {
[57c96f7]725                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[0baed0d]726        }
[57c96f7]727        else if( iu == irc->user )
[b7d3cc34]728        {
[6c2404e]729                irc_usermsg( irc, "Use /nick to change your own nickname" );
[b7d3cc34]730        }
[f73b969]731        else if( !nick_ok( cmd[2] ) )
[b7d3cc34]732        {
733                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
734        }
[9a9b520]735        else if( ( old = irc_user_by_name( irc, cmd[2] ) ) && old != iu )
[b7d3cc34]736        {
[57c96f7]737                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
[b7d3cc34]738        }
[f73b969]739        else
[b7d3cc34]740        {
[57c96f7]741                if( !irc_user_set_nick( iu, cmd[2] ) )
742                {
743                        irc_usermsg( irc, "Error while changing nick" );
744                        return;
745                }
746               
747                if( iu == irc->root )
[f73b969]748                {
[7125cb3]749                        /* If we're called internally (user did "set root_nick"),
750                           let's not go O(INF). :-) */
[1195cec]751                        if( strcmp( cmd[0], "set_rename" ) != 0 )
[57c96f7]752                                set_setstr( &irc->b->set, "root_nick", cmd[2] );
[f73b969]753                }
[57c96f7]754                else if( iu->bu )
[f73b969]755                {
[b1f818b]756                        nick_set( iu->bu, cmd[2] );
[f73b969]757                }
758               
759                irc_usermsg( irc, "Nick successfully changed" );
[b7d3cc34]760        }
761}
762
[1195cec]763char *set_eval_root_nick( set_t *set, char *new_nick )
764{
765        irc_t *irc = set->data;
766       
[0a6e5d1]767        if( strcmp( irc->root->nick, new_nick ) != 0 )
[1195cec]768        {
[0a6e5d1]769                char *cmd[] = { "set_rename", irc->root->nick, new_nick, NULL };
[1195cec]770               
771                cmd_rename( irc, cmd );
772        }
773       
[0a6e5d1]774        return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID;
[1195cec]775}
[0baed0d]776
[f73b969]777static void cmd_block( irc_t *irc, char **cmd )
[b7d3cc34]778{
[0da65d5]779        struct im_connection *ic;
[b7d3cc34]780        account_t *a;
781       
[2272cb3]782        if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
[87b6a3e]783        {
784                char *format;
785                GSList *l;
786               
787                if( strchr( irc->umode, 'b' ) != NULL )
788                        format = "%s\t%s";
789                else
[57ef864]790                        format = "%-32.32s  %-16.16s";
[87b6a3e]791               
792                irc_usermsg( irc, format, "Handle", "Nickname" );
[0da65d5]793                for( l = a->ic->deny; l; l = l->next )
[87b6a3e]794                {
[2272cb3]795                        bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
796                        irc_user_t *iu = bu ? bu->ui_data : NULL;
797                        irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
[87b6a3e]798                }
799                irc_usermsg( irc, "End of list." );
800               
801                return;
802        }
803        else if( !cmd[2] )
[b7d3cc34]804        {
[2272cb3]805                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
806                if( !iu || !iu->bu )
[b7d3cc34]807                {
808                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]809                        return;
[b7d3cc34]810                }
[2272cb3]811                ic = iu->bu->ic;
812                cmd[2] = iu->bu->handle;
[b7d3cc34]813        }
[2272cb3]814        else if( !( a = account_get( irc->b, cmd[1] ) ) )
[b7d3cc34]815        {
816                irc_usermsg( irc, "Invalid account" );
[f73b969]817                return;
[b7d3cc34]818        }
[0da65d5]819        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]820        {
821                irc_usermsg( irc, "That account is not on-line" );
[f73b969]822                return;
[b7d3cc34]823        }
824       
[0da65d5]825        if( !ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit )
[b7d3cc34]826        {
827                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
828        }
829        else
830        {
[84b045d]831                imc_rem_allow( ic, cmd[2] );
832                imc_add_block( ic, cmd[2] );
[f1d488e]833                irc_usermsg( irc, "Buddy `%s' moved from allow- to block-list", cmd[2] );
[b7d3cc34]834        }
835}
836
[f73b969]837static void cmd_allow( irc_t *irc, char **cmd )
[b7d3cc34]838{
[0da65d5]839        struct im_connection *ic;
[b7d3cc34]840        account_t *a;
841       
[2272cb3]842        if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
[87b6a3e]843        {
844                char *format;
845                GSList *l;
846               
847                if( strchr( irc->umode, 'b' ) != NULL )
848                        format = "%s\t%s";
849                else
[57ef864]850                        format = "%-32.32s  %-16.16s";
[87b6a3e]851               
852                irc_usermsg( irc, format, "Handle", "Nickname" );
[0da65d5]853                for( l = a->ic->permit; l; l = l->next )
[87b6a3e]854                {
[2272cb3]855                        bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
856                        irc_user_t *iu = bu ? bu->ui_data : NULL;
857                        irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
[87b6a3e]858                }
859                irc_usermsg( irc, "End of list." );
860               
861                return;
862        }
863        else if( !cmd[2] )
[b7d3cc34]864        {
[2272cb3]865                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
866                if( !iu || !iu->bu )
[b7d3cc34]867                {
868                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]869                        return;
[b7d3cc34]870                }
[2272cb3]871                ic = iu->bu->ic;
872                cmd[2] = iu->bu->handle;
[b7d3cc34]873        }
[2272cb3]874        else if( !( a = account_get( irc->b, cmd[1] ) ) )
[b7d3cc34]875        {
876                irc_usermsg( irc, "Invalid account" );
[f73b969]877                return;
[b7d3cc34]878        }
[0da65d5]879        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]880        {
881                irc_usermsg( irc, "That account is not on-line" );
[f73b969]882                return;
[b7d3cc34]883        }
884       
[0da65d5]885        if( !ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit )
[b7d3cc34]886        {
887                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
888        }
889        else
890        {
[84b045d]891                imc_rem_block( ic, cmd[2] );
892                imc_add_allow( ic, cmd[2] );
[b7d3cc34]893               
[f1d488e]894                irc_usermsg( irc, "Buddy `%s' moved from block- to allow-list", cmd[2] );
[b7d3cc34]895        }
896}
897
[f73b969]898static void cmd_yesno( irc_t *irc, char **cmd )
[b7d3cc34]899{
900        query_t *q = NULL;
901        int numq = 0;
902       
903        if( irc->queries == NULL )
904        {
905                irc_usermsg( irc, "Did I ask you something?" );
[f73b969]906                return;
[b7d3cc34]907        }
908       
909        /* If there's an argument, the user seems to want to answer another question than the
910           first/last (depending on the query_order setting) one. */
911        if( cmd[1] )
912        {
913                if( sscanf( cmd[1], "%d", &numq ) != 1 )
914                {
915                        irc_usermsg( irc, "Invalid query number" );
[f73b969]916                        return;
[b7d3cc34]917                }
918               
919                for( q = irc->queries; q; q = q->next, numq -- )
920                        if( numq == 0 )
921                                break;
922               
923                if( !q )
924                {
925                        irc_usermsg( irc, "Uhm, I never asked you something like that..." );
[f73b969]926                        return;
[b7d3cc34]927                }
928        }
929       
930        if( g_strcasecmp( cmd[0], "yes" ) == 0 )
931                query_answer( irc, q, 1 );
932        else if( g_strcasecmp( cmd[0], "no" ) == 0 )
933                query_answer( irc, q, 0 );
934}
935
[f73b969]936static void cmd_set( irc_t *irc, char **cmd )
[b7d3cc34]937{
[e907683]938        cmd_set_real( irc, cmd, &irc->b->set, NULL );
[b7d3cc34]939}
940
[f73b969]941static void cmd_blist( irc_t *irc, char **cmd )
[b7d3cc34]942{
943        int online = 0, away = 0, offline = 0;
[4c3519a]944        GSList *l;
[aefa533e]945        char s[256];
946        char *format;
[b7d3cc34]947        int n_online = 0, n_away = 0, n_offline = 0;
948       
949        if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 )
950                online = offline = away = 1;
951        else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 )
952                offline = 1;
953        else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 )
954                away = 1;
955        else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 )
956                online = 1;
957        else
[449a51d]958                online = away = 1;
[b7d3cc34]959       
[aefa533e]960        if( strchr( irc->umode, 'b' ) != NULL )
961                format = "%s\t%s\t%s";
962        else
963                format = "%-16.16s  %-40.40s  %s";
964       
[4c3519a]965        irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" );
[b7d3cc34]966       
[4c3519a]967        for( l = irc->users; l; l = l->next )
[b7d3cc34]968        {
[4c3519a]969                irc_user_t *iu = l->data;
970                bee_user_t *bu = iu->bu;
971               
972                if( !bu || ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE )
973                        continue;
974               
[aefa533e]975                if( online == 1 )
976                {
[449a51d]977                        char st[256] = "Online";
978                       
[4c3519a]979                        if( bu->status_msg )
980                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg );
[449a51d]981                       
[4c3519a]982                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
983                        irc_usermsg( irc, format, iu->nick, s, st );
[aefa533e]984                }
985               
[b7d3cc34]986                n_online ++;
987        }
988
[4c3519a]989        for( l = irc->users; l; l = l->next )
[b7d3cc34]990        {
[4c3519a]991                irc_user_t *iu = l->data;
992                bee_user_t *bu = iu->bu;
993               
994                if( !bu || !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) )
995                        continue;
996               
[aefa533e]997                if( away == 1 )
998                {
[4c3519a]999                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
1000                        irc_usermsg( irc, format, iu->nick, s, irc_user_get_away( iu ) );
[aefa533e]1001                }
[b7d3cc34]1002                n_away ++;
1003        }
1004       
[4c3519a]1005        for( l = irc->users; l; l = l->next )
[b7d3cc34]1006        {
[4c3519a]1007                irc_user_t *iu = l->data;
1008                bee_user_t *bu = iu->bu;
1009               
1010                if( !bu || bu->flags & BEE_USER_ONLINE )
1011                        continue;
1012               
[aefa533e]1013                if( offline == 1 )
1014                {
[4c3519a]1015                        g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
1016                        irc_usermsg( irc, format, iu->nick, s, "Offline" );
[aefa533e]1017                }
[b7d3cc34]1018                n_offline ++;
1019        }
1020       
[aa5ac01]1021        irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );
[b7d3cc34]1022}
1023
[f73b969]1024static void cmd_qlist( irc_t *irc, char **cmd )
[b7d3cc34]1025{
1026        query_t *q = irc->queries;
1027        int num;
1028       
1029        if( !q )
1030        {
1031                irc_usermsg( irc, "There are no pending questions." );
[f73b969]1032                return;
[b7d3cc34]1033        }
1034       
1035        irc_usermsg( irc, "Pending queries:" );
1036       
1037        for( num = 0; q; q = q->next, num ++ )
[0da65d5]1038                if( q->ic ) /* Not necessary yet, but it might come later */
[c2fb3809]1039                        irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->acc->user, q->question );
[5c09a59]1040                else
1041                        irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );
[b7d3cc34]1042}
1043
[a9a7287]1044static void cmd_chat( irc_t *irc, char **cmd )
1045{
1046        account_t *acc;
1047       
1048        if( g_strcasecmp( cmd[1], "add" ) == 0 )
1049        {
[07054a5]1050                char *channel, *s;
[7b71feb]1051                struct irc_channel *ic;
[07054a5]1052               
1053                MIN_ARGS( 3 );
[a9a7287]1054               
[7b71feb]1055                if( !( acc = account_get( irc->b, cmd[2] ) ) )
[a9a7287]1056                {
1057                        irc_usermsg( irc, "Invalid account" );
1058                        return;
1059                }
[5a75d15]1060                else if( !acc->prpl->chat_join )
1061                {
1062                        irc_usermsg( irc, "Named chatrooms not supported on that account." );
1063                        return;
1064                }
[a9a7287]1065               
[07054a5]1066                if( cmd[4] == NULL )
1067                {
1068                        channel = g_strdup( cmd[3] );
1069                        if( ( s = strchr( channel, '@' ) ) )
1070                                *s = 0;
1071                }
1072                else
1073                {
1074                        channel = g_strdup( cmd[4] );
1075                }
1076               
1077                if( strchr( CTYPES, channel[0] ) == NULL )
1078                {
[7b71feb]1079                        s = g_strdup_printf( "#%s", channel );
[07054a5]1080                        g_free( channel );
1081                        channel = s;
[134a02c]1082                       
1083                        irc_channel_name_strip( channel );
[07054a5]1084                }
1085               
[5a75d15]1086                if( ( ic = irc_channel_new( irc, channel ) ) &&
[547ea68]1087                    set_setstr( &ic->set, "type", "chat" ) &&
[5a75d15]1088                    set_setstr( &ic->set, "chat_type", "room" ) &&
1089                    set_setstr( &ic->set, "account", cmd[2] ) &&
1090                    set_setstr( &ic->set, "room", cmd[3] ) )
1091                {
1092                        irc_usermsg( irc, "Chatroom successfully added." );
1093                }
1094                else
[a9a7287]1095                {
[5a75d15]1096                        if( ic )
1097                                irc_channel_free( ic );
[a9a7287]1098                       
[5a75d15]1099                        irc_usermsg( irc, "Could not add chatroom." );
[d995c9b]1100                }
[d7db346]1101                g_free( channel );
[d995c9b]1102        }
[39f93f0]1103        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
1104        {
[c1a8a16]1105                irc_user_t *iu;
[3b99524]1106               
1107                MIN_ARGS( 2 );
[39f93f0]1108               
[c1a8a16]1109                if( ( iu = irc_user_by_name( irc, cmd[2] ) ) &&
1110                    iu->bu && iu->bu->ic->acc->prpl->chat_with )
[39f93f0]1111                {
[c1a8a16]1112                        if( !iu->bu->ic->acc->prpl->chat_with( iu->bu->ic, iu->bu->handle ) )
[39f93f0]1113                        {
1114                                irc_usermsg( irc, "(Possible) failure while trying to open "
[c1a8a16]1115                                                  "a groupchat with %s.", iu->nick );
[39f93f0]1116                        }
1117                }
1118                else
1119                {
1120                        irc_usermsg( irc, "Can't open a groupchat with %s.", cmd[2] );
1121                }
1122        }
[7cd2e8a]1123        else if( g_strcasecmp( cmd[1], "list" ) == 0 ||
1124                 g_strcasecmp( cmd[1], "set" ) == 0 ||
1125                 g_strcasecmp( cmd[1], "del" ) == 0 )
1126        {
1127                irc_usermsg( irc, "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command." );
1128                cmd_channel( irc, cmd );
1129        }
[a9a7287]1130        else
1131        {
1132                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] );
1133        }
[fa29d093]1134}
1135
[f1d488e]1136static void cmd_group( irc_t *irc, char **cmd )
1137{
1138        GSList *l;
1139        int len;
1140       
1141        len = strlen( cmd[1] );
1142        if( g_strncasecmp( cmd[1], "list", len ) == 0 )
1143        {
1144                int n = 0;
1145               
1146                if( strchr( irc->umode, 'b' ) )
1147                        irc_usermsg( irc, "Group list:" );
1148               
1149                for( l = irc->b->groups; l; l = l->next )
1150                {
1151                        bee_group_t *bg = l->data;
1152                        irc_usermsg( irc, "%d. %s", n ++, bg->name );
1153                }
1154                irc_usermsg( irc, "End of group list" );
1155        }
1156        else
1157        {
1158                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "group", cmd[1] );
1159        }
1160}
1161
[b8a491d]1162static void cmd_transfer( irc_t *irc, char **cmd )
[2c2df7d]1163{
1164        GSList *files = irc->file_transfers;
1165        enum { LIST, REJECT, CANCEL };
1166        int subcmd = LIST;
1167        int fid;
1168
1169        if( !files )
1170        {
1171                irc_usermsg( irc, "No pending transfers" );
1172                return;
1173        }
1174
[b8a491d]1175        if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) )
[2c2df7d]1176        {
1177                subcmd = REJECT;
1178        }
[b8a491d]1179        else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) && 
1180                 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) )
[2c2df7d]1181        {
1182                subcmd = CANCEL;
1183        }
1184
1185        for( ; files; files = g_slist_next( files ) )
1186        {
1187                file_transfer_t *file = files->data;
1188               
1189                switch( subcmd ) {
1190                case LIST:
1191                        if ( file->status == FT_STATUS_LISTENING )
1192                                irc_usermsg( irc, 
1193                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
1194                        else 
1195                        {
1196                                int kb_per_s = 0;
[44961cb]1197                                time_t diff = time( NULL ) - file->started ? : 1;
[2c2df7d]1198                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
1199                                        kb_per_s = file->bytes_transferred / 1024 / diff;
1200                                       
1201                                irc_usermsg( irc, 
1202                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, 
1203                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
1204                        }
1205                        break;
1206                case REJECT:
1207                        if( file->status == FT_STATUS_LISTENING )
1208                        {
1209                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
[9d4352c]1210                                imcb_file_canceled( file->ic, file, "Denied by user" );
[2c2df7d]1211                        }
1212                        break;
1213                case CANCEL:
1214                        if( file->local_id == fid )
1215                        {
1216                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
[9d4352c]1217                                imcb_file_canceled( file->ic, file, "Canceled by user" );
[2c2df7d]1218                        }
1219                        break;
1220                }
1221        }
1222}
1223
[6c56f42]1224/* IMPORTANT: Keep this list sorted! The short command logic needs that. */
[0298d11]1225const command_t commands[] = {
[d860a8d]1226        { "account",        1, cmd_account,        0 },
[6c56f42]1227        { "add",            2, cmd_add,            0 },
[2272cb3]1228        { "allow",          1, cmd_allow,          0 },
[4c3519a]1229        { "blist",          0, cmd_blist,          0 },
[2272cb3]1230        { "block",          1, cmd_block,          0 },
[c133d4b8]1231        { "channel",        1, cmd_channel,        0 },
1232        { "chat",           1, cmd_chat,           0 },
[6c56f42]1233        { "drop",           1, cmd_drop,           0 },
[9d4352c]1234        { "ft",             0, cmd_transfer,       0 },
[f1d488e]1235        { "group",          1, cmd_group,          0 },
[6c56f42]1236        { "help",           0, cmd_help,           0 }, 
[0298d11]1237        { "identify",       1, cmd_identify,       0 },
[aa44bdd]1238        { "info",           1, cmd_info,           0 },
[6c56f42]1239        { "no",             0, cmd_yesno,          0 },
[9d4352c]1240        { "qlist",          0, cmd_qlist,          0 },
[0298d11]1241        { "register",       1, cmd_register,       0 },
[dbb0ce3]1242        { "remove",         1, cmd_remove,         0 },
[0298d11]1243        { "rename",         2, cmd_rename,         0 },
[6c56f42]1244        { "save",           0, cmd_save,           0 },
[0298d11]1245        { "set",            0, cmd_set,            0 },
[9d4352c]1246        { "transfer",       0, cmd_transfer,       0 },
[0298d11]1247        { "yes",            0, cmd_yesno,          0 },
1248        { NULL }
1249};
Note: See TracBrowser for help on using the repository browser.