source: root_commands.c @ c1a3c27

Last change on this file since c1a3c27 was e8c8d00, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-17T15:15:19Z

Merging mainline.

  • Property mode set to 100644
File size: 27.6 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
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"
31#include "chat.h"
32
33#include <string.h>
34
35void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
36{
37        char *cmd[IRC_MAX_ARGS];
38        char *s;
39        int k;
40        char q = 0;
41       
42        memset( cmd, 0, sizeof( cmd ) );
43        cmd[0] = command;
44        k = 1;
45        for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ )
46                if( *s == ' ' && !q )
47                {
48                        *s = 0;
49                        while( *++s == ' ' );
50                        if( *s == '"' || *s == '\'' )
51                        {
52                                q = *s;
53                                s ++;
54                        }
55                        if( *s )
56                        {
57                                cmd[k++] = s;
58                                s --;
59                        }
60                        else
61                        {
62                                break;
63                        }
64                }
65                else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
66                {
67                        char *cpy;
68                       
69                        for( cpy = s; *cpy; cpy ++ )
70                                cpy[0] = cpy[1];
71                }
72                else if( *s == q )
73                {
74                        q = *s = 0;
75                }
76        cmd[k] = NULL;
77       
78        root_command( irc, cmd );
79}
80
81#define MIN_ARGS( x, y... )                                                    \
82        do                                                                     \
83        {                                                                      \
84                int blaat;                                                     \
85                for( blaat = 0; blaat <= x; blaat ++ )                         \
86                        if( cmd[blaat] == NULL )                               \
87                        {                                                      \
88                                irc_usermsg( irc, "Not enough parameters given (need %d).", x ); \
89                                return y;                                      \
90                        }                                                      \
91        } while( 0 )
92
93void root_command( irc_t *irc, char *cmd[] )
94{       
95        int i;
96       
97        if( !cmd[0] )
98                return;
99       
100        for( i = 0; commands[i].command; i++ )
101                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
102                {
103                        MIN_ARGS( commands[i].required_parameters );
104                       
105                        commands[i].execute( irc, cmd );
106                        return;
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
112static void cmd_help( irc_t *irc, char **cmd )
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
139static void cmd_account( irc_t *irc, char **cmd );
140
141static void cmd_identify( irc_t *irc, char **cmd )
142{
143        storage_status_t status = storage_load( irc, cmd[1] );
144        char *account_on[] = { "account", "on", NULL };
145       
146        if( strchr( irc->umode, 'R' ) != NULL )
147        {
148                irc_usermsg( irc, "You're already logged in." );
149                return;
150        }
151       
152        switch (status) {
153        case STORAGE_INVALID_PASSWORD:
154                irc_usermsg( irc, "Incorrect password" );
155                break;
156        case STORAGE_NO_SUCH_USER:
157                irc_usermsg( irc, "The nick is (probably) not registered" );
158                break;
159        case STORAGE_OK:
160                irc_usermsg( irc, "Password accepted, settings and accounts loaded" );
161                irc_setpass( irc, cmd[1] );
162                irc->status |= USTATUS_IDENTIFIED;
163                irc_umode_set( irc, "+R", 1 );
164                if( set_getbool( &irc->set, "auto_connect" ) )
165                        cmd_account( irc, account_on );
166                break;
167        case STORAGE_OTHER_ERROR:
168        default:
169                irc_usermsg( irc, "Unknown error while loading configuration" );
170                break;
171        }
172}
173
174static void cmd_register( irc_t *irc, char **cmd )
175{
176        if( global.conf->authmode == AUTHMODE_REGISTERED )
177        {
178                irc_usermsg( irc, "This server does not allow registering new accounts" );
179                return;
180        }
181
182        switch( storage_save( irc, cmd[1], FALSE ) ) {
183                case STORAGE_ALREADY_EXISTS:
184                        irc_usermsg( irc, "Nick is already registered" );
185                        break;
186                       
187                case STORAGE_OK:
188                        irc_usermsg( irc, "Account successfully created" );
189                        irc_setpass( irc, cmd[1] );
190                        irc->status |= USTATUS_IDENTIFIED;
191                        irc_umode_set( irc, "+R", 1 );
192                        break;
193
194                default:
195                        irc_usermsg( irc, "Error registering" );
196                        break;
197        }
198}
199
200static void cmd_drop( irc_t *irc, char **cmd )
201{
202        storage_status_t status;
203       
204        status = storage_remove (irc->nick, cmd[1]);
205        switch (status) {
206        case STORAGE_NO_SUCH_USER:
207                irc_usermsg( irc, "That account does not exist" );
208                break;
209        case STORAGE_INVALID_PASSWORD:
210                irc_usermsg( irc, "Password invalid" );
211                break;
212        case STORAGE_OK:
213                irc_setpass( irc, NULL );
214                irc->status &= ~USTATUS_IDENTIFIED;
215                irc_umode_set( irc, "-R", 1 );
216                irc_usermsg( irc, "Account `%s' removed", irc->nick );
217                break;
218        default:
219                irc_usermsg( irc, "Error: `%d'", status );
220                break;
221        }
222}
223
224struct cmd_account_del_data
225{
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;
234       
235        for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
236       
237        if( a == NULL )
238        {
239                irc_usermsg( cad->irc, "Account already deleted" );
240        }
241        else if( a->ic )
242        {
243                irc_usermsg( cad->irc, "Account is still logged in, can't delete" );
244        }
245        else
246        {
247                account_del( cad->irc, a );
248                irc_usermsg( cad->irc, "Account deleted" );
249        }
250        g_free( data );
251}
252
253void cmd_account_del_no( void *data )
254{
255        g_free( data );
256}
257
258static void cmd_showset( irc_t *irc, set_t **head, char *key )
259{
260        char *val;
261       
262        if( ( val = set_getstr( head, key ) ) )
263                irc_usermsg( irc, "%s = `%s'", key, val );
264        else
265                irc_usermsg( irc, "%s is empty", key );
266}
267
268typedef set_t** (*cmd_set_findhead)( irc_t*, char* );
269typedef int (*cmd_set_checkflags)( irc_t*, set_t *set );
270
271static int cmd_set_real( irc_t *irc, char **cmd, cmd_set_findhead findhead, cmd_set_checkflags checkflags )
272{
273        char *set_full = NULL, *set_name = NULL, *tmp;
274        set_t **head;
275       
276        if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
277        {
278                MIN_ARGS( 2, 0 );
279                set_full = cmd[2];
280        }
281        else
282                set_full = cmd[1];
283       
284        if( findhead == NULL )
285        {
286                set_name = set_full;
287               
288                head = &irc->set;
289        }
290        else 
291        {
292                char *id;
293               
294                if( ( tmp = strchr( set_full, '/' ) ) )
295                {
296                        id = g_strndup( set_full, ( tmp - set_full ) );
297                        set_name = tmp + 1;
298                }
299                else
300                {
301                        id = g_strdup( set_full );
302                }
303               
304                if( ( head = findhead( irc, id ) ) == NULL )
305                {
306                        g_free( id );
307                        irc_usermsg( irc, "Could not find setting." );
308                        return 0;
309                }
310                g_free( id );
311        }
312       
313        if( cmd[1] && cmd[2] && set_name )
314        {
315                set_t *s = set_find( head, set_name );
316                int st;
317               
318                if( s && checkflags && checkflags( irc, s ) == 0 )
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
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
383static void cmd_account( irc_t *irc, char **cmd )
384{
385        account_t *a;
386       
387        if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) )
388        {
389                irc_usermsg( irc, "This server only accepts registered users" );
390                return;
391        }
392       
393        if( g_strcasecmp( cmd[1], "add" ) == 0 )
394        {
395                struct prpl *prpl;
396               
397                MIN_ARGS( 4 );
398               
399                prpl = find_protocol( cmd[2] );
400               
401                if( prpl == NULL )
402                {
403                        irc_usermsg( irc, "Unknown protocol" );
404                        return;
405                }
406
407                a = account_add( irc, prpl, cmd[3], cmd[4] );
408                if( cmd[5] )
409                {
410                        irc_usermsg( irc, "Warning: Passing a servername/other flags to `account add' "
411                                          "is now deprecated. Use `account set' instead." );
412                        set_setstr( &a->set, "server", cmd[5] );
413                }
414               
415                irc_usermsg( irc, "Account successfully added" );
416        }
417        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
418        {
419                MIN_ARGS( 2 );
420
421                if( !( a = account_get( irc, cmd[2] ) ) )
422                {
423                        irc_usermsg( irc, "Invalid account" );
424                }
425                else if( a->ic )
426                {
427                        irc_usermsg( irc, "Account is still logged in, can't delete" );
428                }
429                else
430                {
431                        struct cmd_account_del_data *cad;
432                        char *msg;
433                       
434                        cad = g_malloc( sizeof( struct cmd_account_del_data ) );
435                        cad->a = a;
436                        cad->irc = irc;
437                       
438                        msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will "
439                                               "also forget all your saved nicknames. If you want "
440                                               "to change your username/password, use the `account "
441                                               "set' command. Are you sure you want to delete this "
442                                               "account?", a->prpl->name, a->user );
443                        query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
444                        g_free( msg );
445                }
446        }
447        else if( g_strcasecmp( cmd[1], "list" ) == 0 )
448        {
449                int i = 0;
450               
451                if( strchr( irc->umode, 'b' ) )
452                        irc_usermsg( irc, "Account list:" );
453               
454                for( a = irc->accounts; a; a = a->next )
455                {
456                        char *con;
457                       
458                        if( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) )
459                                con = " (connected)";
460                        else if( a->ic )
461                                con = " (connecting)";
462                        else if( a->reconnect )
463                                con = " (awaiting reconnect)";
464                        else
465                                con = "";
466                       
467                        irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con );
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                        {
479                                if( a->ic )
480                                {
481                                        irc_usermsg( irc, "Account already online" );
482                                        return;
483                                }
484                                else
485                                {
486                                        account_on( irc, a );
487                                }
488                        }
489                        else
490                        {
491                                irc_usermsg( irc, "Invalid account" );
492                                return;
493                        }
494                }
495                else
496                {
497                        if ( irc->accounts ) {
498                                irc_usermsg( irc, "Trying to get all accounts connected..." );
499                       
500                                for( a = irc->accounts; a; a = a->next )
501                                        if( !a->ic && a->auto_connect )
502                                                account_on( irc, a );
503                        } 
504                        else
505                        {
506                                irc_usermsg( irc, "No accounts known. Use `account add' to add one." );
507                        }
508                }
509        }
510        else if( g_strcasecmp( cmd[1], "off" ) == 0 )
511        {
512                if( !cmd[2] )
513                {
514                        irc_usermsg( irc, "Deactivating all active (re)connections..." );
515                       
516                        for( a = irc->accounts; a; a = a->next )
517                        {
518                                if( a->ic )
519                                        account_off( irc, a );
520                                else if( a->reconnect )
521                                        cancel_auto_reconnect( a );
522                        }
523                }
524                else if( ( a = account_get( irc, cmd[2] ) ) )
525                {
526                        if( a->ic )
527                        {
528                                account_off( irc, a );
529                        }
530                        else if( a->reconnect )
531                        {
532                                cancel_auto_reconnect( a );
533                                irc_usermsg( irc, "Reconnect cancelled" );
534                        }
535                        else
536                        {
537                                irc_usermsg( irc, "Account already offline" );
538                                return;
539                        }
540                }
541                else
542                {
543                        irc_usermsg( irc, "Invalid account" );
544                        return;
545                }
546        }
547        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
548        {
549                MIN_ARGS( 2 );
550               
551                cmd_set_real( irc, cmd + 1, cmd_account_set_findhead, cmd_account_set_checkflags );
552        }
553        else
554        {
555                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[1] );
556        }
557}
558
559static void cmd_add( irc_t *irc, char **cmd )
560{
561        account_t *a;
562        int add_on_server = 1;
563       
564        if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
565        {
566                MIN_ARGS( 3 );
567                add_on_server = 0;
568                cmd ++;
569        }
570       
571        if( !( a = account_get( irc, cmd[1] ) ) )
572        {
573                irc_usermsg( irc, "Invalid account" );
574                return;
575        }
576        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
577        {
578                irc_usermsg( irc, "That account is not on-line" );
579                return;
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] );
587                        return;
588                }
589                else if( user_find( irc, cmd[3] ) )
590                {
591                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
592                        return;
593                }
594                else
595                {
596                        nick_set( a, cmd[2], cmd[3] );
597                }
598        }
599       
600        if( add_on_server )
601                a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
602        else
603                /* Yeah, officially this is a call-*back*... So if we just
604                   called add_buddy, we'll wait for the IM server to respond
605                   before we do this. */
606                imcb_add_buddy( a->ic, cmd[2], NULL );
607       
608        irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
609}
610
611static void cmd_info( irc_t *irc, char **cmd )
612{
613        struct im_connection *ic;
614        account_t *a;
615       
616        if( !cmd[2] )
617        {
618                user_t *u = user_find( irc, cmd[1] );
619                if( !u || !u->ic )
620                {
621                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
622                        return;
623                }
624                ic = u->ic;
625                cmd[2] = u->handle;
626        }
627        else if( !( a = account_get( irc, cmd[1] ) ) )
628        {
629                irc_usermsg( irc, "Invalid account" );
630                return;
631        }
632        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
633        {
634                irc_usermsg( irc, "That account is not on-line" );
635                return;
636        }
637       
638        if( !ic->acc->prpl->get_info )
639        {
640                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
641        }
642        else
643        {
644                ic->acc->prpl->get_info( ic, cmd[2] );
645        }
646}
647
648static void cmd_rename( irc_t *irc, char **cmd )
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        }
656        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
657        {
658                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
659        }
660        else if( !nick_ok( cmd[2] ) )
661        {
662                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
663        }
664        else if( !( u = user_find( irc, cmd[1] ) ) )
665        {
666                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
667        }
668        else
669        {
670                user_rename( irc, cmd[1], cmd[2] );
671                irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] );
672                if( g_strcasecmp( cmd[1], irc->mynick ) == 0 )
673                {
674                        g_free( irc->mynick );
675                        irc->mynick = g_strdup( cmd[2] );
676                       
677                        /* If we're called internally (user did "set root_nick"),
678                           let's not go O(INF). :-) */
679                        if( strcmp( cmd[0], "set_rename" ) != 0 )
680                                set_setstr( &irc->set, "root_nick", cmd[2] );
681                }
682                else if( u->send_handler == buddy_send_handler )
683                {
684                        nick_set( u->ic->acc, u->handle, cmd[2] );
685                }
686               
687                irc_usermsg( irc, "Nick successfully changed" );
688        }
689}
690
691char *set_eval_root_nick( set_t *set, char *new_nick )
692{
693        irc_t *irc = set->data;
694       
695        if( strcmp( irc->mynick, new_nick ) != 0 )
696        {
697                char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL };
698               
699                cmd_rename( irc, cmd );
700        }
701       
702        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
703}
704
705static void cmd_remove( irc_t *irc, char **cmd )
706{
707        user_t *u;
708        char *s;
709       
710        if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )
711        {
712                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
713                return;
714        }
715        s = g_strdup( u->handle );
716       
717        u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );
718        nick_del( u->ic->acc, u->handle );
719        user_del( irc, cmd[1] );
720       
721        irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
722        g_free( s );
723       
724        return;
725}
726
727static void cmd_block( irc_t *irc, char **cmd )
728{
729        struct im_connection *ic;
730        account_t *a;
731       
732        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
733        {
734                char *format;
735                GSList *l;
736               
737                if( strchr( irc->umode, 'b' ) != NULL )
738                        format = "%s\t%s";
739                else
740                        format = "%-32.32s  %-16.16s";
741               
742                irc_usermsg( irc, format, "Handle", "Nickname" );
743                for( l = a->ic->deny; l; l = l->next )
744                {
745                        user_t *u = user_findhandle( a->ic, l->data );
746                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
747                }
748                irc_usermsg( irc, "End of list." );
749               
750                return;
751        }
752        else if( !cmd[2] )
753        {
754                user_t *u = user_find( irc, cmd[1] );
755                if( !u || !u->ic )
756                {
757                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
758                        return;
759                }
760                ic = u->ic;
761                cmd[2] = u->handle;
762        }
763        else if( !( a = account_get( irc, cmd[1] ) ) )
764        {
765                irc_usermsg( irc, "Invalid account" );
766                return;
767        }
768        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
769        {
770                irc_usermsg( irc, "That account is not on-line" );
771                return;
772        }
773       
774        if( !ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit )
775        {
776                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
777        }
778        else
779        {
780                imc_rem_allow( ic, cmd[2] );
781                imc_add_block( ic, cmd[2] );
782                irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] );
783        }
784}
785
786static void cmd_allow( irc_t *irc, char **cmd )
787{
788        struct im_connection *ic;
789        account_t *a;
790       
791        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
792        {
793                char *format;
794                GSList *l;
795               
796                if( strchr( irc->umode, 'b' ) != NULL )
797                        format = "%s\t%s";
798                else
799                        format = "%-32.32s  %-16.16s";
800               
801                irc_usermsg( irc, format, "Handle", "Nickname" );
802                for( l = a->ic->permit; l; l = l->next )
803                {
804                        user_t *u = user_findhandle( a->ic, l->data );
805                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
806                }
807                irc_usermsg( irc, "End of list." );
808               
809                return;
810        }
811        else if( !cmd[2] )
812        {
813                user_t *u = user_find( irc, cmd[1] );
814                if( !u || !u->ic )
815                {
816                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
817                        return;
818                }
819                ic = u->ic;
820                cmd[2] = u->handle;
821        }
822        else if( !( a = account_get( irc, cmd[1] ) ) )
823        {
824                irc_usermsg( irc, "Invalid account" );
825                return;
826        }
827        else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) )
828        {
829                irc_usermsg( irc, "That account is not on-line" );
830                return;
831        }
832       
833        if( !ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit )
834        {
835                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
836        }
837        else
838        {
839                imc_rem_block( ic, cmd[2] );
840                imc_add_allow( ic, cmd[2] );
841               
842                irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] );
843        }
844}
845
846static void cmd_yesno( irc_t *irc, char **cmd )
847{
848        query_t *q = NULL;
849        int numq = 0;
850       
851        if( irc->queries == NULL )
852        {
853                irc_usermsg( irc, "Did I ask you something?" );
854                return;
855        }
856       
857        /* If there's an argument, the user seems to want to answer another question than the
858           first/last (depending on the query_order setting) one. */
859        if( cmd[1] )
860        {
861                if( sscanf( cmd[1], "%d", &numq ) != 1 )
862                {
863                        irc_usermsg( irc, "Invalid query number" );
864                        return;
865                }
866               
867                for( q = irc->queries; q; q = q->next, numq -- )
868                        if( numq == 0 )
869                                break;
870               
871                if( !q )
872                {
873                        irc_usermsg( irc, "Uhm, I never asked you something like that..." );
874                        return;
875                }
876        }
877       
878        if( g_strcasecmp( cmd[0], "yes" ) == 0 )
879                query_answer( irc, q, 1 );
880        else if( g_strcasecmp( cmd[0], "no" ) == 0 )
881                query_answer( irc, q, 0 );
882}
883
884static void cmd_set( irc_t *irc, char **cmd )
885{
886        cmd_set_real( irc, cmd, NULL, NULL );
887}
888
889static void cmd_save( irc_t *irc, char **cmd )
890{
891        if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
892                irc_usermsg( irc, "Please create an account first" );
893        else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
894                irc_usermsg( irc, "Configuration saved" );
895        else
896                irc_usermsg( irc, "Configuration could not be saved!" );
897}
898
899static void cmd_blist( irc_t *irc, char **cmd )
900{
901        int online = 0, away = 0, offline = 0;
902        user_t *u;
903        char s[256];
904        char *format;
905        int n_online = 0, n_away = 0, n_offline = 0;
906       
907        if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 )
908                online = offline = away = 1;
909        else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 )
910                offline = 1;
911        else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 )
912                away = 1;
913        else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 )
914                online = 1;
915        else
916                online = away = 1;
917       
918        if( strchr( irc->umode, 'b' ) != NULL )
919                format = "%s\t%s\t%s";
920        else
921                format = "%-16.16s  %-40.40s  %s";
922       
923        irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" );
924       
925        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away )
926        {
927                if( online == 1 )
928                {
929                        char st[256] = "Online";
930                       
931                        if( u->status_msg )
932                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
933                       
934                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
935                        irc_usermsg( irc, format, u->nick, s, st );
936                }
937               
938                n_online ++;
939        }
940
941        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away )
942        {
943                if( away == 1 )
944                {
945                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
946                        irc_usermsg( irc, format, u->nick, s, u->away );
947                }
948                n_away ++;
949        }
950       
951        for( u = irc->users; u; u = u->next ) if( u->ic && !u->online )
952        {
953                if( offline == 1 )
954                {
955                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
956                        irc_usermsg( irc, format, u->nick, s, "Offline" );
957                }
958                n_offline ++;
959        }
960       
961        irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );
962}
963
964static void cmd_nick( irc_t *irc, char **cmd ) 
965{
966        account_t *a;
967
968        if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )
969        {
970                irc_usermsg( irc, "Invalid account");
971        }
972        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
973        {
974                irc_usermsg( irc, "That account is not on-line" );
975        }
976        else if ( !cmd[2] ) 
977        {
978                irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );
979        }
980        else if ( !a->prpl->set_my_name ) 
981        {
982                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
983        }
984        else
985        {
986                irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );
987               
988                a->prpl->set_my_name( a->ic, cmd[2] );
989        }
990}
991
992static void cmd_qlist( irc_t *irc, char **cmd )
993{
994        query_t *q = irc->queries;
995        int num;
996       
997        if( !q )
998        {
999                irc_usermsg( irc, "There are no pending questions." );
1000                return;
1001        }
1002       
1003        irc_usermsg( irc, "Pending queries:" );
1004       
1005        for( num = 0; q; q = q->next, num ++ )
1006                if( q->ic ) /* Not necessary yet, but it might come later */
1007                        irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->acc->user, q->question );
1008                else
1009                        irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );
1010}
1011
1012static void cmd_join_chat( irc_t *irc, char **cmd )
1013{
1014        irc_usermsg( irc, "This command is now obsolete. "
1015                          "Please try the `chat' command instead." );
1016}
1017
1018static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )
1019{
1020        struct chat *c;
1021       
1022        if( ( c = chat_get( irc, id ) ) )
1023                return &c->set;
1024        else
1025                return NULL;
1026}
1027
1028static void cmd_chat( irc_t *irc, char **cmd )
1029{
1030        account_t *acc;
1031        struct chat *c;
1032       
1033        if( g_strcasecmp( cmd[1], "add" ) == 0 )
1034        {
1035                char *channel, *s;
1036               
1037                MIN_ARGS( 3 );
1038               
1039                if( !( acc = account_get( irc, cmd[2] ) ) )
1040                {
1041                        irc_usermsg( irc, "Invalid account" );
1042                        return;
1043                }
1044               
1045                if( cmd[4] == NULL )
1046                {
1047                        channel = g_strdup( cmd[3] );
1048                        if( ( s = strchr( channel, '@' ) ) )
1049                                *s = 0;
1050                }
1051                else
1052                {
1053                        channel = g_strdup( cmd[4] );
1054                }
1055               
1056                if( strchr( CTYPES, channel[0] ) == NULL )
1057                {
1058                        s = g_strdup_printf( "%c%s", CTYPES[0], channel );
1059                        g_free( channel );
1060                        channel = s;
1061                }
1062               
1063                if( ( c = chat_add( irc, acc, cmd[3], channel ) ) )
1064                        irc_usermsg( irc, "Chatroom added successfully." );
1065                else
1066                        irc_usermsg( irc, "Could not add chatroom." );
1067               
1068                g_free( channel );
1069        }
1070        else if( g_strcasecmp( cmd[1], "list" ) == 0 )
1071        {
1072                int i = 0;
1073               
1074                if( strchr( irc->umode, 'b' ) )
1075                        irc_usermsg( irc, "Chatroom list:" );
1076               
1077                for( c = irc->chatrooms; c; c = c->next )
1078                {
1079                        irc_usermsg( irc, "%2d. %s(%s) %s, %s", i, c->acc->prpl->name,
1080                                          c->acc->user, c->handle, c->channel );
1081                       
1082                        i ++;
1083                }
1084                irc_usermsg( irc, "End of chatroom list" );
1085        }
1086        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
1087        {
1088                MIN_ARGS( 2 );
1089               
1090                cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL );
1091        }
1092        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
1093        {
1094                MIN_ARGS( 2 );
1095               
1096                if( ( c = chat_get( irc, cmd[2] ) ) )
1097                {
1098                        chat_del( irc, c );
1099                }
1100                else
1101                {
1102                        irc_usermsg( irc, "Could not remove chat." );
1103                }
1104        }
1105        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
1106        {
1107                user_t *u;
1108               
1109                MIN_ARGS( 2 );
1110               
1111                if( ( u = user_find( irc, cmd[2] ) ) && u->ic && u->ic->acc->prpl->chat_with )
1112                {
1113                        if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
1114                        {
1115                                irc_usermsg( irc, "(Possible) failure while trying to open "
1116                                                  "a groupchat with %s.", u->nick );
1117                        }
1118                }
1119                else
1120                {
1121                        irc_usermsg( irc, "Can't open a groupchat with %s.", cmd[2] );
1122                }
1123        }
1124        else
1125        {
1126                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] );
1127        }
1128}
1129
1130static void cmd_transfers( irc_t *irc, char **cmd )
1131{
1132        GSList *files = irc->file_transfers;
1133        enum { LIST, REJECT, CANCEL };
1134        int subcmd = LIST;
1135        int fid;
1136
1137        if( !files )
1138        {
1139                irc_usermsg( irc, "No pending transfers" );
1140                return;
1141        }
1142
1143        if( cmd[1] && 
1144            ( strcmp( cmd[1], "reject" ) == 0 ) )
1145        {
1146                subcmd = REJECT;
1147        }
1148        else if( cmd[1] && 
1149                 ( strcmp( cmd[1], "cancel" ) == 0 ) && 
1150                 cmd[2] &&
1151                 ( fid = atoi( cmd[2] ) ) )
1152        {
1153                subcmd = CANCEL;
1154        }
1155
1156        for( ; files; files = g_slist_next( files ) )
1157        {
1158                file_transfer_t *file = files->data;
1159               
1160                switch( subcmd ) {
1161                case LIST:
1162                        if ( file->status == FT_STATUS_LISTENING )
1163                                irc_usermsg( irc, 
1164                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
1165                        else 
1166                        {
1167                                int kb_per_s = 0;
1168                                time_t diff = time( NULL ) - file->started ? : 1;
1169                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
1170                                        kb_per_s = file->bytes_transferred / 1024 / diff;
1171                                       
1172                                irc_usermsg( irc, 
1173                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, 
1174                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
1175                        }
1176                        break;
1177                case REJECT:
1178                        if( file->status == FT_STATUS_LISTENING )
1179                        {
1180                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
1181                                imcb_file_canceled( file, "Denied by user" );
1182                        }
1183                        break;
1184                case CANCEL:
1185                        if( file->local_id == fid )
1186                        {
1187                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
1188                                imcb_file_canceled( file, "Canceled by user" );
1189                        }
1190                        break;
1191                }
1192        }
1193}
1194
1195const command_t commands[] = {
1196        { "help",           0, cmd_help,           0 }, 
1197        { "identify",       1, cmd_identify,       0 },
1198        { "register",       1, cmd_register,       0 },
1199        { "drop",           1, cmd_drop,           0 },
1200        { "account",        1, cmd_account,        0 },
1201        { "add",            2, cmd_add,            0 },
1202        { "info",           1, cmd_info,           0 },
1203        { "rename",         2, cmd_rename,         0 },
1204        { "remove",         1, cmd_remove,         0 },
1205        { "block",          1, cmd_block,          0 },
1206        { "allow",          1, cmd_allow,          0 },
1207        { "save",           0, cmd_save,           0 },
1208        { "set",            0, cmd_set,            0 },
1209        { "yes",            0, cmd_yesno,          0 },
1210        { "no",             0, cmd_yesno,          0 },
1211        { "blist",          0, cmd_blist,          0 },
1212        { "nick",           1, cmd_nick,           0 },
1213        { "qlist",          0, cmd_qlist,          0 },
1214        { "join_chat",      2, cmd_join_chat,      0 },
1215        { "chat",           1, cmd_chat,           0 },
1216        { "transfers",      0, cmd_transfers,      0 },
1217        { NULL }
1218};
Note: See TracBrowser for help on using the repository browser.