source: root_commands.c @ 8ad5c34

Last change on this file since 8ad5c34 was 767a148, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-21T16:06:31Z

Merging in file transfer support. Most important points from my review
are fixed now, time to let it settle in and get people to try it.

  • Property mode set to 100644
File size: 28.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 "crypting.h"
29#include "bitlbee.h"
30#include "help.h"
[b75acf6]31#include "chat.h"
[b7d3cc34]32
33#include <string.h>
34
[f73b969]35void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
[7e563ed]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                        }
[619a681]60                        else
61                        {
62                                break;
63                        }
[7e563ed]64                }
[79c6f9f]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                }
[7e563ed]72                else if( *s == q )
73                {
74                        q = *s = 0;
75                }
76        cmd[k] = NULL;
77       
[f73b969]78        root_command( irc, cmd );
[7e563ed]79}
80
[3b99524]81#define MIN_ARGS( x, y... )                                                    \
82        do                                                                     \
83        {                                                                      \
[07054a5]84                int blaat;                                                     \
85                for( blaat = 0; blaat <= x; blaat ++ )                         \
86                        if( cmd[blaat] == NULL )                               \
[3b99524]87                        {                                                      \
88                                irc_usermsg( irc, "Not enough parameters given (need %d).", x ); \
89                                return y;                                      \
90                        }                                                      \
91        } while( 0 )
92
[f73b969]93void root_command( irc_t *irc, char *cmd[] )
[7e563ed]94{       
95        int i;
96       
97        if( !cmd[0] )
[f73b969]98                return;
[7e563ed]99       
100        for( i = 0; commands[i].command; i++ )
101                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
102                {
[3b99524]103                        MIN_ARGS( commands[i].required_parameters );
104                       
[7e563ed]105                        commands[i].execute( irc, cmd );
[f73b969]106                        return;
[7e563ed]107                }
108       
109        irc_usermsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] );
110}
111
[f73b969]112static void cmd_help( irc_t *irc, char **cmd )
[b7d3cc34]113{
114        char param[80];
115        int i;
116        char *s;
117       
118        memset( param, 0, sizeof(param) );
119        for ( i = 1; (cmd[i] != NULL && ( strlen(param) < (sizeof(param)-1) ) ); i++ ) {
120                if ( i != 1 )   // prepend space except for the first parameter
121                        strcat(param, " ");
122                strncat( param, cmd[i], sizeof(param) - strlen(param) - 1 );
123        }
124
125        s = help_get( &(global.help), param );
126        if( !s ) s = help_get( &(global.help), "" );
127       
128        if( s )
129        {
130                irc_usermsg( irc, "%s", s );
131                g_free( s );
132        }
133        else
134        {
135                irc_usermsg( irc, "Error opening helpfile." );
136        }
137}
138
[90bbb0e]139static void cmd_account( irc_t *irc, char **cmd );
140
[f73b969]141static void cmd_identify( irc_t *irc, char **cmd )
[b7d3cc34]142{
[3183c21]143        storage_status_t status = storage_load( irc, cmd[1] );
[90bbb0e]144        char *account_on[] = { "account", "on", NULL };
[b7d3cc34]145       
[e9cf291]146        if( strchr( irc->umode, 'R' ) != NULL )
147        {
148                irc_usermsg( irc, "You're already logged in." );
149                return;
150        }
151       
[09adf08]152        switch (status) {
153        case STORAGE_INVALID_PASSWORD:
[b7d3cc34]154                irc_usermsg( irc, "Incorrect password" );
[09adf08]155                break;
156        case STORAGE_NO_SUCH_USER:
[b7d3cc34]157                irc_usermsg( irc, "The nick is (probably) not registered" );
[09adf08]158                break;
159        case STORAGE_OK:
[6ee9d2d]160                irc_usermsg( irc, "Password accepted, settings and accounts loaded" );
[3183c21]161                irc_setpass( irc, cmd[1] );
162                irc->status |= USTATUS_IDENTIFIED;
[238f828]163                irc_umode_set( irc, "+R", 1 );
[d5ccd83]164                if( set_getbool( &irc->set, "auto_connect" ) )
[90bbb0e]165                        cmd_account( irc, account_on );
[09adf08]166                break;
[c121f89]167        case STORAGE_OTHER_ERROR:
[09adf08]168        default:
[c121f89]169                irc_usermsg( irc, "Unknown error while loading configuration" );
[09adf08]170                break;
[b7d3cc34]171        }
172}
173
[f73b969]174static void cmd_register( irc_t *irc, char **cmd )
[b7d3cc34]175{
176        if( global.conf->authmode == AUTHMODE_REGISTERED )
177        {
178                irc_usermsg( irc, "This server does not allow registering new accounts" );
[f73b969]179                return;
[b7d3cc34]180        }
[1ee6c18]181
[3183c21]182        switch( storage_save( irc, cmd[1], FALSE ) ) {
[a1f17d4]183                case STORAGE_ALREADY_EXISTS:
184                        irc_usermsg( irc, "Nick is already registered" );
185                        break;
186                       
187                case STORAGE_OK:
[0383943]188                        irc_usermsg( irc, "Account successfully created" );
[3183c21]189                        irc_setpass( irc, cmd[1] );
[79e826a]190                        irc->status |= USTATUS_IDENTIFIED;
[238f828]191                        irc_umode_set( irc, "+R", 1 );
[a1f17d4]192                        break;
193
194                default:
195                        irc_usermsg( irc, "Error registering" );
196                        break;
[b7d3cc34]197        }
198}
199
[f73b969]200static void cmd_drop( irc_t *irc, char **cmd )
[b7d3cc34]201{
[a1f17d4]202        storage_status_t status;
203       
[ab49fdc]204        status = storage_remove (irc->nick, cmd[1]);
[a1f17d4]205        switch (status) {
206        case STORAGE_NO_SUCH_USER:
[b7d3cc34]207                irc_usermsg( irc, "That account does not exist" );
[f73b969]208                break;
[a1f17d4]209        case STORAGE_INVALID_PASSWORD:
[1ee6c18]210                irc_usermsg( irc, "Password invalid" );
[f73b969]211                break;
[a1f17d4]212        case STORAGE_OK:
[7cad7b4]213                irc_setpass( irc, NULL );
[79e826a]214                irc->status &= ~USTATUS_IDENTIFIED;
[238f828]215                irc_umode_set( irc, "-R", 1 );
[a1f17d4]216                irc_usermsg( irc, "Account `%s' removed", irc->nick );
[f73b969]217                break;
[a1f17d4]218        default:
[30ce1ce]219                irc_usermsg( irc, "Error: `%d'", status );
[f73b969]220                break;
[b7d3cc34]221        }
222}
223
[f35aee7]224struct cmd_account_del_data
[7f421d6]225{
[f35aee7]226        account_t *a;
227        irc_t *irc;
228};
229
230void cmd_account_del_yes( void *data )
231{
232        struct cmd_account_del_data *cad = data;
233        account_t *a;
[7f421d6]234       
[f35aee7]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 )
[7f421d6]242        {
[f35aee7]243                irc_usermsg( cad->irc, "Account is still logged in, can't delete" );
[7f421d6]244        }
245        else
246        {
[f35aee7]247                account_del( cad->irc, a );
248                irc_usermsg( cad->irc, "Account deleted" );
[7f421d6]249        }
[f35aee7]250        g_free( data );
[7f421d6]251}
252
[f35aee7]253void cmd_account_del_no( void *data )
[7f421d6]254{
[8dbe021f]255        g_free( data );
[7f421d6]256}
257
[f536a99]258static void cmd_showset( irc_t *irc, set_t **head, char *key )
[f3579fd]259{
[f536a99]260        char *val;
[f3579fd]261       
[f536a99]262        if( ( val = set_getstr( head, key ) ) )
263                irc_usermsg( irc, "%s = `%s'", key, val );
[f3579fd]264        else
[f536a99]265                irc_usermsg( irc, "%s is empty", key );
[f3579fd]266}
267
[e7bc722]268typedef set_t** (*cmd_set_findhead)( irc_t*, char* );
[c05eb5b]269typedef int (*cmd_set_checkflags)( irc_t*, set_t *set );
[e7bc722]270
[c05eb5b]271static int cmd_set_real( irc_t *irc, char **cmd, cmd_set_findhead findhead, cmd_set_checkflags checkflags )
[e7bc722]272{
273        char *set_full = NULL, *set_name = NULL, *tmp;
274        set_t **head;
275       
276        if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
[d4810df]277        {
278                MIN_ARGS( 2, 0 );
[e7bc722]279                set_full = cmd[2];
[d4810df]280        }
[e7bc722]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 )
314        {
315                set_t *s = set_find( head, set_name );
316                int st;
317               
[8a08d92]318                if( s && checkflags && checkflags( irc, s ) == 0 )
[e7bc722]319                        return 0;
320               
321                if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
322                        st = set_reset( head, set_name );
323                else
324                        st = set_setstr( head, set_name, cmd[2] );
325               
326                if( set_getstr( head, set_name ) == NULL )
327                {
328                        if( st )
329                                irc_usermsg( irc, "Setting changed successfully" );
330                        else
331                                irc_usermsg( irc, "Failed to change setting" );
332                }
333                else
334                {
335                        cmd_showset( irc, head, set_name );
336                }
337        }
338        else if( set_name )
339        {
340                cmd_showset( irc, head, set_name );
341        }
342        else
343        {
344                set_t *s = *head;
345                while( s )
346                {
347                        cmd_showset( irc, &s, s->key );
348                        s = s->next;
349                }
350        }
351       
352        return 1;
353}
354
355static 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
[c05eb5b]365static int cmd_account_set_checkflags( irc_t *irc, set_t *s )
366{
367        account_t *a = s->data;
368       
369        if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY )
370        {
371                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" );
372                return 0;
373        }
374        else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY )
375        {
376                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" );
377                return 0;
378        }
379       
380        return 1;
381}
382
[f73b969]383static void cmd_account( irc_t *irc, char **cmd )
[b7d3cc34]384{
385        account_t *a;
386       
[3af70b0]387        if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) )
[b7d3cc34]388        {
389                irc_usermsg( irc, "This server only accepts registered users" );
[f73b969]390                return;
[b7d3cc34]391        }
392       
393        if( g_strcasecmp( cmd[1], "add" ) == 0 )
394        {
[7b23afd]395                struct prpl *prpl;
[b7d3cc34]396               
[3b99524]397                MIN_ARGS( 4 );
[b7d3cc34]398               
[a9a7287]399                prpl = find_protocol( cmd[2] );
[b7d3cc34]400               
[7b23afd]401                if( prpl == NULL )
[b7d3cc34]402                {
403                        irc_usermsg( irc, "Unknown protocol" );
[f73b969]404                        return;
[b7d3cc34]405                }
406
[7b23afd]407                a = account_add( irc, prpl, cmd[3], cmd[4] );
[b7d3cc34]408                if( cmd[5] )
[30ce1ce]409                {
410                        irc_usermsg( irc, "Warning: Passing a servername/other flags to `account add' "
411                                          "is now deprecated. Use `account set' instead." );
[5100caa]412                        set_setstr( &a->set, "server", cmd[5] );
[30ce1ce]413                }
[b7d3cc34]414               
415                irc_usermsg( irc, "Account successfully added" );
416        }
417        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
418        {
[3b99524]419                MIN_ARGS( 2 );
420
421                if( !( a = account_get( irc, cmd[2] ) ) )
[b7d3cc34]422                {
423                        irc_usermsg( irc, "Invalid account" );
424                }
[0da65d5]425                else if( a->ic )
[b7d3cc34]426                {
427                        irc_usermsg( irc, "Account is still logged in, can't delete" );
428                }
429                else
430                {
[f35aee7]431                        struct cmd_account_del_data *cad;
[7f421d6]432                        char *msg;
433                       
[f35aee7]434                        cad = g_malloc( sizeof( struct cmd_account_del_data ) );
435                        cad->a = a;
436                        cad->irc = irc;
[8dbe021f]437                       
[7f421d6]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 );
[f35aee7]443                        query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
[7f421d6]444                        g_free( msg );
[b7d3cc34]445                }
446        }
447        else if( g_strcasecmp( cmd[1], "list" ) == 0 )
448        {
449                int i = 0;
450               
[e6e1f18]451                if( strchr( irc->umode, 'b' ) )
452                        irc_usermsg( irc, "Account list:" );
453               
[b7d3cc34]454                for( a = irc->accounts; a; a = a->next )
455                {
456                        char *con;
457                       
[0da65d5]458                        if( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) )
[b7d3cc34]459                                con = " (connected)";
[0da65d5]460                        else if( a->ic )
[b7d3cc34]461                                con = " (connecting)";
462                        else if( a->reconnect )
463                                con = " (awaiting reconnect)";
464                        else
465                                con = "";
466                       
[7b23afd]467                        irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con );
[b7d3cc34]468                       
469                        i ++;
470                }
471                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                        {
[0da65d5]479                                if( a->ic )
[b7d3cc34]480                                {
481                                        irc_usermsg( irc, "Account already online" );
[f73b969]482                                        return;
[b7d3cc34]483                                }
484                                else
485                                {
486                                        account_on( irc, a );
487                                }
488                        }
489                        else
490                        {
491                                irc_usermsg( irc, "Invalid account" );
[f73b969]492                                return;
[b7d3cc34]493                        }
494                }
495                else
496                {
497                        if ( irc->accounts ) {
498                                irc_usermsg( irc, "Trying to get all accounts connected..." );
499                       
500                                for( a = irc->accounts; a; a = a->next )
[0da65d5]501                                        if( !a->ic && a->auto_connect )
[b7d3cc34]502                                                account_on( irc, a );
503                        } 
504                        else
505                        {
[30ce1ce]506                                irc_usermsg( irc, "No accounts known. Use `account add' to add one." );
[b7d3cc34]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..." );
515                       
516                        for( a = irc->accounts; a; a = a->next )
517                        {
[0da65d5]518                                if( a->ic )
[b7d3cc34]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                {
[0da65d5]526                        if( a->ic )
[b7d3cc34]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" );
[f73b969]538                                return;
[b7d3cc34]539                        }
540                }
541                else
542                {
543                        irc_usermsg( irc, "Invalid account" );
[f73b969]544                        return;
[b7d3cc34]545                }
546        }
[5100caa]547        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
548        {
[3b99524]549                MIN_ARGS( 2 );
[5100caa]550               
[c05eb5b]551                cmd_set_real( irc, cmd + 1, cmd_account_set_findhead, cmd_account_set_checkflags );
[5100caa]552        }
[b7d3cc34]553        else
554        {
[a9a7287]555                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[1] );
[b7d3cc34]556        }
557}
558
[f73b969]559static void cmd_add( irc_t *irc, char **cmd )
[b7d3cc34]560{
561        account_t *a;
[f0cb961]562        int add_on_server = 1;
[f8de26f]563       
564        if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
565        {
[77fc000c]566                MIN_ARGS( 3 );
[f0cb961]567                add_on_server = 0;
[7adc657]568                cmd ++;
[f8de26f]569        }
[b7d3cc34]570       
571        if( !( a = account_get( irc, cmd[1] ) ) )
572        {
573                irc_usermsg( irc, "Invalid account" );
[f73b969]574                return;
[b7d3cc34]575        }
[0da65d5]576        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]577        {
578                irc_usermsg( irc, "That account is not on-line" );
[f73b969]579                return;
[b7d3cc34]580        }
581       
582        if( cmd[3] )
583        {
584                if( !nick_ok( cmd[3] ) )
585                {
586                        irc_usermsg( irc, "The requested nick `%s' is invalid", cmd[3] );
[f73b969]587                        return;
[b7d3cc34]588                }
589                else if( user_find( irc, cmd[3] ) )
590                {
591                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
[f73b969]592                        return;
[b7d3cc34]593                }
594                else
595                {
[5b52a48]596                        nick_set( a, cmd[2], cmd[3] );
[b7d3cc34]597                }
598        }
[f8de26f]599       
[f0cb961]600        if( add_on_server )
[0da65d5]601                a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
[7adc657]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 );
[f0cb961]607       
608        irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
[b7d3cc34]609}
610
[f73b969]611static void cmd_info( irc_t *irc, char **cmd )
[b7d3cc34]612{
[0da65d5]613        struct im_connection *ic;
[b7d3cc34]614        account_t *a;
615       
616        if( !cmd[2] )
617        {
618                user_t *u = user_find( irc, cmd[1] );
[0da65d5]619                if( !u || !u->ic )
[b7d3cc34]620                {
621                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]622                        return;
[b7d3cc34]623                }
[0da65d5]624                ic = u->ic;
[b7d3cc34]625                cmd[2] = u->handle;
626        }
627        else if( !( a = account_get( irc, cmd[1] ) ) )
628        {
629                irc_usermsg( irc, "Invalid account" );
[f73b969]630                return;
[b7d3cc34]631        }
[0da65d5]632        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]633        {
634                irc_usermsg( irc, "That account is not on-line" );
[f73b969]635                return;
[b7d3cc34]636        }
637       
[0da65d5]638        if( !ic->acc->prpl->get_info )
[b7d3cc34]639        {
640                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
641        }
[f73b969]642        else
643        {
[0da65d5]644                ic->acc->prpl->get_info( ic, cmd[2] );
[f73b969]645        }
[b7d3cc34]646}
647
[f73b969]648static void cmd_rename( irc_t *irc, char **cmd )
[b7d3cc34]649{
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        }
[0baed0d]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        }
[f73b969]671        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
[b7d3cc34]672        {
673                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
674        }
[f73b969]675        else if( !nick_ok( cmd[2] ) )
[b7d3cc34]676        {
677                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
678        }
[f73b969]679        else if( !( u = user_find( irc, cmd[1] ) ) )
[b7d3cc34]680        {
681                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
682        }
[f73b969]683        else
[b7d3cc34]684        {
[f73b969]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] );
[1195cec]691                       
[7125cb3]692                        /* If we're called internally (user did "set root_nick"),
693                           let's not go O(INF). :-) */
[1195cec]694                        if( strcmp( cmd[0], "set_rename" ) != 0 )
695                                set_setstr( &irc->set, "root_nick", cmd[2] );
[f73b969]696                }
697                else if( u->send_handler == buddy_send_handler )
698                {
[0da65d5]699                        nick_set( u->ic->acc, u->handle, cmd[2] );
[f73b969]700                }
701               
702                irc_usermsg( irc, "Nick successfully changed" );
[b7d3cc34]703        }
704}
705
[1195cec]706char *set_eval_root_nick( set_t *set, char *new_nick )
707{
708        irc_t *irc = set->data;
709       
710        if( strcmp( irc->mynick, new_nick ) != 0 )
711        {
712                char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL };
713               
714                cmd_rename( irc, cmd );
715        }
716       
[7125cb3]717        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
[1195cec]718}
719
[0baed0d]720char *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
[f73b969]734static void cmd_remove( irc_t *irc, char **cmd )
[b7d3cc34]735{
736        user_t *u;
737        char *s;
738       
[0da65d5]739        if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )
[b7d3cc34]740        {
741                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
[f73b969]742                return;
[b7d3cc34]743        }
744        s = g_strdup( u->handle );
745       
[0da65d5]746        u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );
747        nick_del( u->ic->acc, u->handle );
[b7d3cc34]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       
[f73b969]753        return;
[b7d3cc34]754}
755
[f73b969]756static void cmd_block( irc_t *irc, char **cmd )
[b7d3cc34]757{
[0da65d5]758        struct im_connection *ic;
[b7d3cc34]759        account_t *a;
760       
[0da65d5]761        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
[87b6a3e]762        {
763                char *format;
764                GSList *l;
765               
766                if( strchr( irc->umode, 'b' ) != NULL )
767                        format = "%s\t%s";
768                else
[57ef864]769                        format = "%-32.32s  %-16.16s";
[87b6a3e]770               
771                irc_usermsg( irc, format, "Handle", "Nickname" );
[0da65d5]772                for( l = a->ic->deny; l; l = l->next )
[87b6a3e]773                {
[0da65d5]774                        user_t *u = user_findhandle( a->ic, l->data );
[87b6a3e]775                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
776                }
777                irc_usermsg( irc, "End of list." );
778               
779                return;
780        }
781        else if( !cmd[2] )
[b7d3cc34]782        {
783                user_t *u = user_find( irc, cmd[1] );
[0da65d5]784                if( !u || !u->ic )
[b7d3cc34]785                {
786                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]787                        return;
[b7d3cc34]788                }
[0da65d5]789                ic = u->ic;
[b7d3cc34]790                cmd[2] = u->handle;
791        }
792        else if( !( a = account_get( irc, cmd[1] ) ) )
793        {
794                irc_usermsg( irc, "Invalid account" );
[f73b969]795                return;
[b7d3cc34]796        }
[0da65d5]797        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]798        {
799                irc_usermsg( irc, "That account is not on-line" );
[f73b969]800                return;
[b7d3cc34]801        }
802       
[0da65d5]803        if( !ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit )
[b7d3cc34]804        {
805                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
806        }
807        else
808        {
[84b045d]809                imc_rem_allow( ic, cmd[2] );
810                imc_add_block( ic, cmd[2] );
[da3b536]811                irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] );
[b7d3cc34]812        }
813}
814
[f73b969]815static void cmd_allow( irc_t *irc, char **cmd )
[b7d3cc34]816{
[0da65d5]817        struct im_connection *ic;
[b7d3cc34]818        account_t *a;
819       
[0da65d5]820        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
[87b6a3e]821        {
822                char *format;
823                GSList *l;
824               
825                if( strchr( irc->umode, 'b' ) != NULL )
826                        format = "%s\t%s";
827                else
[57ef864]828                        format = "%-32.32s  %-16.16s";
[87b6a3e]829               
830                irc_usermsg( irc, format, "Handle", "Nickname" );
[0da65d5]831                for( l = a->ic->permit; l; l = l->next )
[87b6a3e]832                {
[0da65d5]833                        user_t *u = user_findhandle( a->ic, l->data );
[87b6a3e]834                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
835                }
836                irc_usermsg( irc, "End of list." );
837               
838                return;
839        }
840        else if( !cmd[2] )
[b7d3cc34]841        {
842                user_t *u = user_find( irc, cmd[1] );
[0da65d5]843                if( !u || !u->ic )
[b7d3cc34]844                {
845                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
[f73b969]846                        return;
[b7d3cc34]847                }
[0da65d5]848                ic = u->ic;
[b7d3cc34]849                cmd[2] = u->handle;
850        }
851        else if( !( a = account_get( irc, cmd[1] ) ) )
852        {
853                irc_usermsg( irc, "Invalid account" );
[f73b969]854                return;
[b7d3cc34]855        }
[0da65d5]856        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]857        {
858                irc_usermsg( irc, "That account is not on-line" );
[f73b969]859                return;
[b7d3cc34]860        }
861       
[0da65d5]862        if( !ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit )
[b7d3cc34]863        {
864                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
865        }
866        else
867        {
[84b045d]868                imc_rem_block( ic, cmd[2] );
869                imc_add_allow( ic, cmd[2] );
[b7d3cc34]870               
[da3b536]871                irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] );
[b7d3cc34]872        }
873}
874
[f73b969]875static void cmd_yesno( irc_t *irc, char **cmd )
[b7d3cc34]876{
877        query_t *q = NULL;
878        int numq = 0;
879       
880        if( irc->queries == NULL )
881        {
882                irc_usermsg( irc, "Did I ask you something?" );
[f73b969]883                return;
[b7d3cc34]884        }
885       
886        /* If there's an argument, the user seems to want to answer another question than the
887           first/last (depending on the query_order setting) one. */
888        if( cmd[1] )
889        {
890                if( sscanf( cmd[1], "%d", &numq ) != 1 )
891                {
892                        irc_usermsg( irc, "Invalid query number" );
[f73b969]893                        return;
[b7d3cc34]894                }
895               
896                for( q = irc->queries; q; q = q->next, numq -- )
897                        if( numq == 0 )
898                                break;
899               
900                if( !q )
901                {
902                        irc_usermsg( irc, "Uhm, I never asked you something like that..." );
[f73b969]903                        return;
[b7d3cc34]904                }
905        }
906       
907        if( g_strcasecmp( cmd[0], "yes" ) == 0 )
908                query_answer( irc, q, 1 );
909        else if( g_strcasecmp( cmd[0], "no" ) == 0 )
910                query_answer( irc, q, 0 );
911}
912
[f73b969]913static void cmd_set( irc_t *irc, char **cmd )
[b7d3cc34]914{
[c05eb5b]915        cmd_set_real( irc, cmd, NULL, NULL );
[b7d3cc34]916}
917
[f73b969]918static void cmd_save( irc_t *irc, char **cmd )
[b7d3cc34]919{
[3183c21]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 )
[b7d3cc34]923                irc_usermsg( irc, "Configuration saved" );
924        else
925                irc_usermsg( irc, "Configuration could not be saved!" );
926}
927
[f73b969]928static void cmd_blist( irc_t *irc, char **cmd )
[b7d3cc34]929{
930        int online = 0, away = 0, offline = 0;
931        user_t *u;
[aefa533e]932        char s[256];
933        char *format;
[b7d3cc34]934        int n_online = 0, n_away = 0, n_offline = 0;
935       
936        if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 )
937                online = offline = away = 1;
938        else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 )
939                offline = 1;
940        else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 )
941                away = 1;
942        else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 )
943                online = 1;
944        else
[449a51d]945                online = away = 1;
[b7d3cc34]946       
[aefa533e]947        if( strchr( irc->umode, 'b' ) != NULL )
948                format = "%s\t%s\t%s";
949        else
950                format = "%-16.16s  %-40.40s  %s";
951       
952        irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" );
[b7d3cc34]953       
[0da65d5]954        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away )
[b7d3cc34]955        {
[aefa533e]956                if( online == 1 )
957                {
[449a51d]958                        char st[256] = "Online";
959                       
960                        if( u->status_msg )
961                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
962                       
[e731120]963                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
[449a51d]964                        irc_usermsg( irc, format, u->nick, s, st );
[aefa533e]965                }
966               
[b7d3cc34]967                n_online ++;
968        }
969
[0da65d5]970        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away )
[b7d3cc34]971        {
[aefa533e]972                if( away == 1 )
973                {
[e731120]974                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
[aefa533e]975                        irc_usermsg( irc, format, u->nick, s, u->away );
976                }
[b7d3cc34]977                n_away ++;
978        }
979       
[0da65d5]980        for( u = irc->users; u; u = u->next ) if( u->ic && !u->online )
[b7d3cc34]981        {
[aefa533e]982                if( offline == 1 )
983                {
[e731120]984                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
[aefa533e]985                        irc_usermsg( irc, format, u->nick, s, "Offline" );
986                }
[b7d3cc34]987                n_offline ++;
988        }
989       
[aa5ac01]990        irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );
[b7d3cc34]991}
992
[f73b969]993static void cmd_nick( irc_t *irc, char **cmd ) 
[b7d3cc34]994{
995        account_t *a;
996
997        if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )
998        {
999                irc_usermsg( irc, "Invalid account");
1000        }
[0da65d5]1001        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
[b7d3cc34]1002        {
1003                irc_usermsg( irc, "That account is not on-line" );
1004        }
1005        else if ( !cmd[2] ) 
1006        {
[0da65d5]1007                irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );
[b7d3cc34]1008        }
[0da65d5]1009        else if ( !a->prpl->set_my_name ) 
[b7d3cc34]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               
[0da65d5]1017                a->prpl->set_my_name( a->ic, cmd[2] );
[b7d3cc34]1018        }
1019}
1020
[f73b969]1021static void cmd_qlist( irc_t *irc, char **cmd )
[b7d3cc34]1022{
1023        query_t *q = irc->queries;
1024        int num;
1025       
1026        if( !q )
1027        {
1028                irc_usermsg( irc, "There are no pending questions." );
[f73b969]1029                return;
[b7d3cc34]1030        }
1031       
1032        irc_usermsg( irc, "Pending queries:" );
1033       
1034        for( num = 0; q; q = q->next, num ++ )
[0da65d5]1035                if( q->ic ) /* Not necessary yet, but it might come later */
[c2fb3809]1036                        irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->acc->user, q->question );
[5c09a59]1037                else
1038                        irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );
[b7d3cc34]1039}
1040
[fa29d093]1041static void cmd_join_chat( irc_t *irc, char **cmd )
1042{
[a9a7287]1043        irc_usermsg( irc, "This command is now obsolete. "
1044                          "Please try the `chat' command instead." );
1045}
1046
[e7bc722]1047static 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
[a9a7287]1057static void cmd_chat( irc_t *irc, char **cmd )
1058{
1059        account_t *acc;
1060        struct chat *c;
1061       
1062        if( g_strcasecmp( cmd[1], "add" ) == 0 )
1063        {
[07054a5]1064                char *channel, *s;
1065               
1066                MIN_ARGS( 3 );
[a9a7287]1067               
1068                if( !( acc = account_get( irc, cmd[2] ) ) )
1069                {
1070                        irc_usermsg( irc, "Invalid account" );
1071                        return;
1072                }
1073               
[07054a5]1074                if( cmd[4] == NULL )
1075                {
1076                        channel = g_strdup( cmd[3] );
1077                        if( ( s = strchr( channel, '@' ) ) )
1078                                *s = 0;
1079                }
1080                else
1081                {
1082                        channel = g_strdup( cmd[4] );
1083                }
1084               
1085                if( strchr( CTYPES, channel[0] ) == NULL )
1086                {
1087                        s = g_strdup_printf( "%c%s", CTYPES[0], channel );
1088                        g_free( channel );
1089                        channel = s;
1090                }
1091               
1092                if( ( c = chat_add( irc, acc, cmd[3], channel ) ) )
[a9a7287]1093                        irc_usermsg( irc, "Chatroom added successfully." );
1094                else
1095                        irc_usermsg( irc, "Could not add chatroom." );
[07054a5]1096               
1097                g_free( channel );
[a9a7287]1098        }
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        }
[e7bc722]1115        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
1116        {
[2ea8736]1117                MIN_ARGS( 2 );
1118               
[c05eb5b]1119                cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL );
[e7bc722]1120        }
[d995c9b]1121        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
1122        {
[3b99524]1123                MIN_ARGS( 2 );
[d995c9b]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        }
[39f93f0]1134        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
1135        {
1136                user_t *u;
[3b99524]1137               
1138                MIN_ARGS( 2 );
[39f93f0]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 ) )
1143                        {
1144                                irc_usermsg( irc, "(Possible) failure while trying to open "
1145                                                  "a groupchat with %s.", u->nick );
1146                        }
1147                }
1148                else
1149                {
1150                        irc_usermsg( irc, "Can't open a groupchat with %s.", cmd[2] );
1151                }
1152        }
[a9a7287]1153        else
1154        {
1155                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] );
1156        }
[fa29d093]1157}
1158
[b8a491d]1159static void cmd_transfer( irc_t *irc, char **cmd )
[2c2df7d]1160{
1161        GSList *files = irc->file_transfers;
1162        enum { LIST, REJECT, CANCEL };
1163        int subcmd = LIST;
1164        int fid;
1165
1166        if( !files )
1167        {
1168                irc_usermsg( irc, "No pending transfers" );
1169                return;
1170        }
1171
[b8a491d]1172        if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) )
[2c2df7d]1173        {
1174                subcmd = REJECT;
1175        }
[b8a491d]1176        else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) && 
1177                 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) )
[2c2df7d]1178        {
1179                subcmd = CANCEL;
1180        }
1181
1182        for( ; files; files = g_slist_next( files ) )
1183        {
1184                file_transfer_t *file = files->data;
1185               
1186                switch( subcmd ) {
1187                case LIST:
1188                        if ( file->status == FT_STATUS_LISTENING )
1189                                irc_usermsg( irc, 
1190                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
1191                        else 
1192                        {
1193                                int kb_per_s = 0;
[44961cb]1194                                time_t diff = time( NULL ) - file->started ? : 1;
[2c2df7d]1195                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
1196                                        kb_per_s = file->bytes_transferred / 1024 / diff;
1197                                       
1198                                irc_usermsg( irc, 
1199                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, 
1200                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
1201                        }
1202                        break;
1203                case REJECT:
1204                        if( file->status == FT_STATUS_LISTENING )
1205                        {
1206                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
1207                                imcb_file_canceled( file, "Denied by user" );
1208                        }
1209                        break;
1210                case CANCEL:
1211                        if( file->local_id == fid )
1212                        {
1213                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
1214                                imcb_file_canceled( file, "Canceled by user" );
1215                        }
1216                        break;
1217                }
1218        }
1219}
1220
[0298d11]1221const command_t commands[] = {
1222        { "help",           0, cmd_help,           0 }, 
1223        { "identify",       1, cmd_identify,       0 },
1224        { "register",       1, cmd_register,       0 },
1225        { "drop",           1, cmd_drop,           0 },
1226        { "account",        1, cmd_account,        0 },
1227        { "add",            2, cmd_add,            0 },
1228        { "info",           1, cmd_info,           0 },
1229        { "rename",         2, cmd_rename,         0 },
1230        { "remove",         1, cmd_remove,         0 },
1231        { "block",          1, cmd_block,          0 },
1232        { "allow",          1, cmd_allow,          0 },
1233        { "save",           0, cmd_save,           0 },
1234        { "set",            0, cmd_set,            0 },
1235        { "yes",            0, cmd_yesno,          0 },
1236        { "no",             0, cmd_yesno,          0 },
1237        { "blist",          0, cmd_blist,          0 },
1238        { "nick",           1, cmd_nick,           0 },
1239        { "qlist",          0, cmd_qlist,          0 },
[fa29d093]1240        { "join_chat",      2, cmd_join_chat,      0 },
[a9a7287]1241        { "chat",           1, cmd_chat,           0 },
[b8a491d]1242        { "transfer",       0, cmd_transfer,       0 },
[0298d11]1243        { NULL }
1244};
Note: See TracBrowser for help on using the repository browser.