Changes in / [156bbd7:21c87a7]


Ignore:
Files:
22 added
9 deleted
34 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r156bbd7 r21c87a7  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o chat.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
    13 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
     12#objects = chat.o
     13objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS)
     14headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h
    1415subdirs = lib protocols
    1516
  • bitlbee.h

    r156bbd7 r21c87a7  
    126126#define CONF_FILE_DEF ETCDIR "bitlbee.conf"
    127127
     128#include "bee.h"
    128129#include "irc.h"
    129130#include "storage.h"
     
    160161gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond );
    161162
    162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
     163void root_command_string( irc_t *irc, char *command );
    163164void root_command( irc_t *irc, char *command[] );
    164165gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
  • conf.c

    r156bbd7 r21c87a7  
    6363        conf->ping_timeout = 300;
    6464        conf->user = NULL;
     65        conf->ft_max_size = SIZE_MAX;
     66        conf->ft_max_kbps = G_MAXUINT;
     67        conf->ft_listen = NULL;
    6568        conf->protocols = NULL;
    6669        proxytype = 0;
     
    315318                                conf->user = g_strdup( ini->value );
    316319                        }
     320                        else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 )
     321                        {
     322                                size_t ft_max_size;
     323                                if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 )
     324                                {
     325                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
     326                                        return 0;
     327                                }
     328                                conf->ft_max_size = ft_max_size;
     329                        }
     330                        else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 )
     331                        {
     332                                if( sscanf( ini->value, "%d", &i ) != 1 )
     333                                {
     334                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
     335                                        return 0;
     336                                }
     337                                conf->ft_max_kbps = i;
     338                        }
     339                        else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 )
     340                        {
     341                                g_free( conf->ft_listen );
     342                                conf->ft_listen = g_strdup( ini->value );
     343                        }
    317344                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
    318345                        {
     
    349376                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
    350377                {
    351                         set_t *s = set_find( &irc->set, ini->key );
     378                        set_t *s = set_find( &irc->b->set, ini->key );
    352379                       
    353380                        if( s )
  • conf.h

    r156bbd7 r21c87a7  
    5050        int ping_timeout;
    5151        char *user;
     52        size_t ft_max_size;
     53        int ft_max_kbps;
     54        char *ft_listen;
    5255        char **protocols;
    5356} conf_t;
  • configure

    r156bbd7 r21c87a7  
    398398fi
    399399
    400 STORAGES="text xml"
     400STORAGES="xml"
    401401
    402402if [ "$ldap" = "auto" ]; then
  • doc/user-guide/commands.xml

    r156bbd7 r21c87a7  
    10921092
    10931093        </bitlbee-command>
     1094       
     1095        <bitlbee-command name="transfers">
     1096                <short-description>Monitor, cancel, or reject file transfers</short-description>
     1097                <syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
     1098               
     1099                <description>
     1100                        <para>
     1101                                Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers &lt;action&gt;</emphasis> for more information.
     1102                        </para>
     1103
     1104                        <ircexample>
     1105                                <ircline nick="ulim">transfers</ircline>
     1106                        </ircexample>
     1107                </description>
     1108               
     1109                <bitlbee-command name="cancel">
     1110                        <short-description>Cancels the file transfer with the given id</short-description>
     1111                        <syntax>transfers &lt;cancel&gt; id</syntax>
     1112
     1113                        <description>
     1114                                <para>Cancels the file transfer with the given id</para>
     1115                        </description>
     1116
     1117                        <ircexample>
     1118                                <ircline nick="ulim">transfers cancel 1</ircline>
     1119                                <ircline nick="root">Canceling file transfer for test</ircline>
     1120                        </ircexample>
     1121                </bitlbee-command>
     1122
     1123                <bitlbee-command name="reject">
     1124                        <short-description>Rejects all incoming transfers</short-description>
     1125                        <syntax>transfers &lt;reject&gt;</syntax>
     1126
     1127                        <description>
     1128                                <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para>
     1129                        </description>
     1130
     1131                        <ircexample>
     1132                                <ircline nick="ulim">transfers reject</ircline>
     1133                        </ircexample>
     1134                </bitlbee-command>
     1135        </bitlbee-command>
     1136       
    10941137</chapter>
  • ipc.c

    r156bbd7 r21c87a7  
    138138       
    139139        if( strchr( irc->umode, 'w' ) )
    140                 irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] );
     140                irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] );
    141141}
    142142
     
    147147       
    148148        if( strchr( irc->umode, 's' ) )
    149                 irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] );
     149                irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] );
    150150}
    151151
     
    156156       
    157157        if( strchr( irc->umode, 'o' ) )
    158                 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->myhost, irc->nick, cmd[1] );
     158                irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] );
    159159}
    160160
     
    176176                return;
    177177       
    178         if( nick_cmp( cmd[1], irc->nick ) != 0 )
     178        if( nick_cmp( cmd[1], irc->user->nick ) != 0 )
    179179                return;         /* It's not for us. */
    180180       
    181         irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );
     181        irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] );
    182182        irc_abort( irc, 0, "Killed by operator: %s", cmd[2] );
    183183}
     
    188188                ipc_to_master_str( "HELLO\r\n" );
    189189        else
    190                 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
     190                ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
    191191}
    192192
  • irc.c

    r156bbd7 r21c87a7  
    55  \********************************************************************/
    66
    7 /* The big hairy IRCd part of the project                               */
     7/* The IRC-based UI (for now the only one)                              */
    88
    99/*
     
    2424*/
    2525
    26 #define BITLBEE_CORE
    2726#include "bitlbee.h"
    28 #include "sock.h"
    29 #include "crypting.h"
    3027#include "ipc.h"
    3128
    32 static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
    33 
    34 GSList *irc_connection_list = NULL;
    35 
    36 static char *set_eval_password( set_t *set, char *value )
    37 {
    38         irc_t *irc = set->data;
    39        
    40         if( irc->status & USTATUS_IDENTIFIED && value )
    41         {
    42                 irc_setpass( irc, value );
    43                 return NULL;
    44         }
    45         else
    46         {
    47                 return SET_INVALID;
    48         }
    49 }
    50 
    51 static char *set_eval_charset( set_t *set, char *value )
    52 {
    53         irc_t *irc = set->data;
    54         char *test;
    55         gsize test_bytes = 0;
    56         GIConv ic, oc;
    57 
    58         if( g_strcasecmp( value, "none" ) == 0 )
    59                 value = g_strdup( "utf-8" );
    60 
    61         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    62         {
    63                 return NULL;
    64         }
    65        
    66         /* Do a test iconv to see if the user picked an IRC-compatible
    67            charset (for example utf-16 goes *horribly* wrong). */
    68         if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
    69             test_bytes > 1 )
    70         {
    71                 g_free( test );
    72                 g_iconv_close( oc );
    73                 irc_usermsg( irc, "Unsupported character set: The IRC protocol "
    74                                   "only supports 8-bit character sets." );
    75                 return NULL;
    76         }
    77         g_free( test );
    78        
    79         if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    80         {
    81                 g_iconv_close( oc );
    82                 return NULL;
    83         }
    84        
    85         if( irc->iconv != (GIConv) -1 )
    86                 g_iconv_close( irc->iconv );
    87         if( irc->oconv != (GIConv) -1 )
    88                 g_iconv_close( irc->oconv );
    89        
    90         irc->iconv = ic;
    91         irc->oconv = oc;
    92 
    93         return value;
    94 }
    95 
    96 static char *set_eval_away_status( set_t *set, char *value )
    97 {
    98         irc_t *irc = set->data;
    99         account_t *a;
    100        
    101         g_free( set->value );
    102         set->value = g_strdup( value );
    103        
    104         for( a = irc->accounts; a; a = a->next )
    105         {
    106                 struct im_connection *ic = a->ic;
    107                
    108                 if( ic && ic->flags & OPT_LOGGED_IN )
    109                         imc_away_send_update( ic );
    110         }
    111        
    112         return value;
    113 }
     29GSList *irc_connection_list;
     30
     31static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond );
     32static char *set_eval_charset( set_t *set, char *value );
    11433
    11534irc_t *irc_new( int fd )
     
    11837        struct sockaddr_storage sock;
    11938        socklen_t socklen = sizeof( sock );
     39        char *host = NULL, *myhost = NULL;
     40        irc_user_t *iu;
    12041        set_t *s;
     42        bee_t *b;
    12143       
    12244        irc = g_new0( irc_t, 1 );
     
    13052        irc->last_pong = gettime();
    13153       
    132         irc->userhash = g_hash_table_new( g_str_hash, g_str_equal );
     54        irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );
    13355        irc->watches = g_hash_table_new( g_str_hash, g_str_equal );
    134        
    135         strcpy( irc->umode, UMODE );
    136         irc->mynick = g_strdup( ROOT_NICK );
    137         irc->channel = g_strdup( ROOT_CHAN );
    13856       
    13957        irc->iconv = (GIConv) -1;
     
    14260        if( global.conf->hostname )
    14361        {
    144                 irc->myhost = g_strdup( global.conf->hostname );
     62                myhost = g_strdup( global.conf->hostname );
    14563        }
    14664        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     
    15169                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    15270                {
    153                         irc->myhost = g_strdup( ipv6_unwrap( buf ) );
     71                        myhost = g_strdup( ipv6_unwrap( buf ) );
    15472                }
    15573        }
     
    16280                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    16381                {
    164                         irc->host = g_strdup( ipv6_unwrap( buf ) );
    165                 }
    166         }
    167        
    168         if( irc->host == NULL )
    169                 irc->host = g_strdup( "localhost.localdomain" );
    170         if( irc->myhost == NULL )
    171                 irc->myhost = g_strdup( "localhost.localdomain" );
     82                        host = g_strdup( ipv6_unwrap( buf ) );
     83                }
     84        }
     85       
     86        if( host == NULL )
     87                host = g_strdup( "localhost.localdomain" );
     88        if( myhost == NULL )
     89                myhost = g_strdup( "localhost.localdomain" );
    17290       
    17391        if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
    17492                irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
    175        
    176         irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );
    17793
    17894        irc_connection_list = g_slist_append( irc_connection_list, irc );
    17995       
    180         s = set_add( &irc->set, "away", NULL,  set_eval_away_status, irc );
    181         s->flags |= SET_NULL_OK;
    182         s = set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
    183         s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
    184         s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc );
    185         s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
    186         s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
    187         s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
    188         s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
    189         s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc );
    190         s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
    191         s = set_add( &irc->set, "default_target", "root", NULL, irc );
    192         s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
    193         s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc );
    194         s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
    195         s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
    196         s = set_add( &irc->set, "ops", "both", set_eval_ops, irc );
    197         s = set_add( &irc->set, "password", NULL, set_eval_password, irc );
    198         s->flags |= SET_NULL_OK;
    199         s = set_add( &irc->set, "private", "true", set_eval_bool, irc );
    200         s = set_add( &irc->set, "query_order", "lifo", NULL, irc );
    201         s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    202         s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    203         s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
    204         s = set_add( &irc->set, "status", NULL,  set_eval_away_status, irc );
    205         s->flags |= SET_NULL_OK;
    206         s = set_add( &irc->set, "strip_html", "true", NULL, irc );
    207         s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc );
    208         s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
    209         s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
     96        b = irc->b = bee_new();
     97        b->ui_data = irc;
     98        b->ui = &irc_ui_funcs;
     99       
     100        s = set_add( &b->set, "away_devoice", "true", NULL/*set_eval_away_devoice*/, irc );
     101        s = set_add( &b->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
     102        s = set_add( &b->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
     103        s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc );
     104        //s = set_add( &b->set, "control_channel", irc->channel, NULL/*set_eval_control_channel*/, irc );
     105        s = set_add( &b->set, "default_target", "root", NULL, irc );
     106        s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc );
     107        s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc );
     108        s = set_add( &b->set, "handle_unknown", "root", NULL, irc );
     109        s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
     110        s = set_add( &b->set, "ops", "both", NULL/*set_eval_ops*/, irc );
     111        s = set_add( &b->set, "private", "true", set_eval_bool, irc );
     112        s = set_add( &b->set, "query_order", "lifo", NULL, irc );
     113        s = set_add( &b->set, "root_nick", ROOT_NICK, NULL/*set_eval_root_nick*/, irc );
     114        s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc );
     115        s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc );
     116        s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc );
     117        s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc );
     118
     119        irc->root = iu = irc_user_new( irc, ROOT_NICK );
     120        iu->host = g_strdup( myhost );
     121        iu->fullname = g_strdup( ROOT_FN );
     122        iu->f = &irc_user_root_funcs;
     123       
     124        iu = irc_user_new( irc, NS_NICK );
     125        iu->host = g_strdup( myhost );
     126        iu->fullname = g_strdup( ROOT_FN );
     127        iu->f = &irc_user_root_funcs;
     128       
     129        irc->user = g_new0( irc_user_t, 1 );
     130        irc->user->host = g_strdup( host );
    210131       
    211132        conf_loaddefaults( irc );
    212133       
    213134        /* Evaluator sets the iconv/oconv structures. */
    214         set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
    215        
    216         return( irc );
     135        set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) );
     136       
     137        irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" );
     138       
     139        g_free( myhost );
     140        g_free( host );
     141       
     142        return irc;
    217143}
    218144
     
    235161               
    236162                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    237                                    irc->nick ? irc->nick : "(NONE)", irc->host, reason );
     163                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );
    238164               
    239165                g_free( reason );
     
    245171               
    246172                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    247                                    irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" );
     173                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );
    248174        }
    249175       
     
    266192}
    267193
    268 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
    269 {
    270         g_free( key );
    271        
    272         return( TRUE );
    273 }
    274 
    275 /* Because we have no garbage collection, this is quite annoying */
     194static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data );
     195
    276196void irc_free( irc_t * irc )
    277197{
    278         user_t *user, *usertmp;
    279        
    280198        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
    281199       
    282         if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )
     200        /*
     201        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) )
    283202                if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )
    284203                        irc_usermsg( irc, "Error while saving settings!" );
     204        */
    285205       
    286206        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    287207       
    288         while( irc->accounts )
    289         {
    290                 if( irc->accounts->ic )
    291                         imc_logout( irc->accounts->ic, FALSE );
    292                 else if( irc->accounts->reconnect )
    293                         cancel_auto_reconnect( irc->accounts );
    294                
    295                 if( irc->accounts->ic == NULL )
    296                         account_del( irc, irc->accounts );
    297                 else
    298                         /* Nasty hack, but account_del() doesn't work in this
    299                            case and we don't want infinite loops, do we? ;-) */
    300                         irc->accounts = irc->accounts->next;
    301         }
    302        
     208        /*
    303209        while( irc->queries != NULL )
    304210                query_del( irc, irc->queries );
    305        
    306         while( irc->set )
    307                 set_del( &irc->set, irc->set->key );
    308        
    309         if (irc->users != NULL)
    310         {
    311                 user = irc->users;
    312                 while( user != NULL )
    313                 {
    314                         g_free( user->nick );
    315                         g_free( user->away );
    316                         g_free( user->handle );
    317                         if( user->user != user->nick ) g_free( user->user );
    318                         if( user->host != user->nick ) g_free( user->host );
    319                         if( user->realname != user->nick ) g_free( user->realname );
    320                         b_event_remove( user->sendbuf_timer );
    321                                        
    322                         usertmp = user;
    323                         user = user->next;
    324                         g_free( usertmp );
    325                 }
    326         }
     211        */
     212       
     213        while( irc->users )
     214                irc_user_free( irc, (irc_user_t *) irc->users->data );
     215       
     216        while( irc->channels )
     217                irc_channel_free( irc->channels->data );
    327218       
    328219        if( irc->ping_source_id > 0 )
     
    336227        irc->fd = -1;
    337228       
    338         g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
    339         g_hash_table_destroy( irc->userhash );
     229        g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL );
     230        g_hash_table_destroy( irc->nick_user_hash );
    340231       
    341232        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     
    350241        g_free( irc->readbuffer );
    351242       
    352         g_free( irc->nick );
    353         g_free( irc->user );
    354         g_free( irc->host );
    355         g_free( irc->realname );
    356243        g_free( irc->password );
    357        
    358         g_free( irc->myhost );
    359         g_free( irc->mynick );
    360        
    361         g_free( irc->channel );
    362        
    363         g_free( irc->last_target );
    364244       
    365245        g_free( irc );
     
    373253}
    374254
     255static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
     256{
     257        g_free( key );
     258       
     259        return( TRUE );
     260}
     261
    375262/* USE WITH CAUTION!
    376263   Sets pass without checking */
    377 void irc_setpass (irc_t *irc, const char *pass) 
     264void irc_setpass (irc_t *irc, const char *pass)
    378265{
    379266        g_free (irc->password);
     
    386273}
    387274
     275static char **irc_splitlines( char *buffer );
     276
    388277void irc_process( irc_t *irc )
    389278{
     
    393282        if( irc->readbuffer != NULL )
    394283        {
    395                 lines = irc_tokenize( irc->readbuffer );
     284                lines = irc_splitlines( irc->readbuffer );
    396285               
    397286                for( i = 0; *lines[i] != '\0'; i ++ )
     
    430319                                                                  "`help set charset' for more information. Your "
    431320                                                                  "message was ignored.",
    432                                                                   set_getstr( &irc->set, "charset" ) );
     321                                                                  set_getstr( &irc->b->set, "charset" ) );
    433322                                               
    434323                                                g_free( conv );
     
    437326                                        else
    438327                                        {
    439                                                 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
     328                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host,
    440329                                                           "Warning: invalid characters received at login time." );
    441330                                               
     
    475364}
    476365
    477 /* Splits a long string into separate lines. The array is NULL-terminated and, unless the string
    478    contains an incomplete line at the end, ends with an empty string. */
    479 char **irc_tokenize( char *buffer )
     366/* Splits a long string into separate lines. The array is NULL-terminated
     367   and, unless the string contains an incomplete line at the end, ends with
     368   an empty string. Could use g_strsplit() but this one does it in-place.
     369   (So yes, it's destructive.) */
     370static char **irc_splitlines( char *buffer )
    480371{
    481372        int i, j, n = 3;
     
    608499}
    609500
    610 void irc_reply( irc_t *irc, int code, char *format, ... )
    611 {
    612         char text[IRC_MAX_LINE];
    613         va_list params;
    614        
    615         va_start( params, format );
    616         g_vsnprintf( text, IRC_MAX_LINE, format, params );
    617         va_end( params );
    618         irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );
    619        
    620         return;
    621 }
    622 
    623 int irc_usermsg( irc_t *irc, char *format, ... )
    624 {
    625         char text[1024];
    626         va_list params;
    627         char is_private = 0;
    628         user_t *u;
    629        
    630         u = user_find( irc, irc->mynick );
    631         is_private = u->is_private;
    632        
    633         va_start( params, format );
    634         g_vsnprintf( text, sizeof( text ), format, params );
    635         va_end( params );
    636        
    637         return( irc_msgfrom( irc, u->nick, text ) );
    638 }
    639 
    640501void irc_write( irc_t *irc, char *format, ... )
    641502{
     
    648509        return;
    649510}
     511
     512void irc_write_all( int now, char *format, ... )
     513{
     514        va_list params;
     515        GSList *temp;   
     516       
     517        va_start( params, format );
     518       
     519        temp = irc_connection_list;
     520        while( temp != NULL )
     521        {
     522                irc_t *irc = temp->data;
     523               
     524                if( now )
     525                {
     526                        g_free( irc->sendbuffer );
     527                        irc->sendbuffer = g_strdup( "\r\n" );
     528                }
     529                irc_vawrite( temp->data, format, params );
     530                if( now )
     531                {
     532                        bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
     533                }
     534                temp = temp->next;
     535        }
     536       
     537        va_end( params );
     538        return;
     539}
    650540
    651541void irc_vawrite( irc_t *irc, char *format, va_list params )
     
    704594}
    705595
    706 void irc_write_all( int now, char *format, ... )
    707 {
    708         va_list params;
    709         GSList *temp;   
    710        
    711         va_start( params, format );
    712        
    713         temp = irc_connection_list;
    714         while( temp != NULL )
    715         {
    716                 irc_t *irc = temp->data;
    717                
    718                 if( now )
    719                 {
    720                         g_free( irc->sendbuffer );
    721                         irc->sendbuffer = g_strdup( "\r\n" );
    722                 }
    723                 irc_vawrite( temp->data, format, params );
    724                 if( now )
    725                 {
    726                         bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
    727                 }
    728                 temp = temp->next;
    729         }
    730        
    731         va_end( params );
    732         return;
    733 }
    734 
    735 void irc_names( irc_t *irc, char *channel )
    736 {
    737         user_t *u;
    738         char namelist[385] = "";
    739         struct groupchat *c = NULL;
    740         char *ops = set_getstr( &irc->set, "ops" );
    741        
    742         /* RFCs say there is no error reply allowed on NAMES, so when the
    743            channel is invalid, just give an empty reply. */
    744        
    745         if( g_strcasecmp( channel, irc->channel ) == 0 )
    746         {
    747                 for( u = irc->users; u; u = u->next ) if( u->online )
    748                 {
    749                         if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
     596int irc_check_login( irc_t *irc )
     597{
     598        if( irc->user->user && irc->user->nick )
     599        {
     600                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
     601                {
     602                        irc_send_num( irc, 464, ":This server is password-protected." );
     603                        return 0;
     604                }
     605                else
     606                {
     607                        irc_channel_t *ic;
     608                        irc_user_t *iu = irc->user;
     609                       
     610                        irc->user = irc_user_new( irc, iu->nick );
     611                        irc->user->user = iu->user;
     612                        irc->user->host = iu->host;
     613                        irc->user->fullname = iu->fullname;
     614                        irc->user->f = &irc_user_self_funcs;
     615                        g_free( iu->nick );
     616                        g_free( iu );
     617                       
     618                        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     619                                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
     620                       
     621                        irc->status |= USTATUS_LOGGED_IN;
     622                       
     623                        /* This is for bug #209 (use PASS to identify to NickServ). */
     624                        if( irc->password != NULL )
    750625                        {
    751                                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    752                                 *namelist = 0;
     626                                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     627                               
     628                                /*irc_setpass( irc, NULL );*/
     629                                /*root_command( irc, send_cmd );*/
     630                                g_free( send_cmd[1] );
    753631                        }
    754632                       
    755                         if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
    756                                 strcat( namelist, "+" );
    757                         else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
    758                                  ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
    759                                 strcat( namelist, "@" );
    760                        
    761                         strcat( namelist, u->nick );
    762                         strcat( namelist, " " );
    763                 }
    764         }
    765         else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    766         {
    767                 GList *l;
    768                
    769                 /* root and the user aren't in the channel userlist but should
    770                    show up in /NAMES, so list them first: */
    771                 sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,
    772                                                  strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );
    773                
    774                 for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )
    775                 {
    776                         if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
    777                         {
    778                                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    779                                 *namelist = 0;
    780                         }
    781                        
    782                         strcat( namelist, u->nick );
    783                         strcat( namelist, " " );
    784                 }
    785         }
    786        
    787         if( *namelist )
    788                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    789        
    790         irc_reply( irc, 366, "%s :End of /NAMES list", channel );
    791 }
    792 
    793 int irc_check_login( irc_t *irc )
    794 {
    795         if( irc->user && irc->nick )
    796         {
    797                 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
    798                 {
    799                         irc_reply( irc, 464, ":This server is password-protected." );
    800                         return 0;
    801                 }
    802                 else
    803                 {
    804                         irc_login( irc );
     633                        irc_send_login( irc );
     634                       
     635                        irc->umode[0] = '\0';
     636                        irc_umode_set( irc, "+" UMODE, TRUE );
     637                       
     638                        ic = irc_channel_new( irc, ROOT_CHAN );
     639                        irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root );
     640                        irc_channel_add_user( ic, irc->user );
     641                       
     642                        irc->last_root_cmd = g_strdup( ROOT_CHAN );
     643                       
     644                        irc_send_msg( irc->root, "PRIVMSG", ROOT_CHAN,
     645                                      "Welcome to the BitlBee gateway!\n\n"
     646                                      "If you've never used BitlBee before, please do read the help "
     647                                      "information using the \x02help\x02 command. Lots of FAQs are "
     648                                      "answered there.\n"
     649                                      "If you already have an account on this server, just use the "
     650                                      "\x02identify\x02 command to identify yourself.", NULL );
     651                       
    805652                        return 1;
    806653                }
     
    813660}
    814661
    815 void irc_login( irc_t *irc )
    816 {
    817         user_t *u;
    818        
    819         irc_reply( irc,   1, ":Welcome to the BitlBee gateway, %s", irc->nick );
    820         irc_reply( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost );
    821         irc_reply( irc,   3, ":%s", IRCD_INFO );
    822         irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
    823         irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee "
    824                              "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server",
    825                              CTYPES, CMODES, MAX_NICK_LENGTH - 1 );
    826         irc_motd( irc );
    827         irc->umode[0] = '\0';
    828         irc_umode_set( irc, "+" UMODE, 1 );
    829 
    830         u = user_add( irc, irc->mynick );
    831         u->host = g_strdup( irc->myhost );
    832         u->realname = g_strdup( ROOT_FN );
    833         u->online = 1;
    834         u->send_handler = root_command_string;
    835         u->is_private = 0; /* [SH] The channel is root's personal playground. */
    836         irc_spawn( irc, u );
    837        
    838         u = user_add( irc, NS_NICK );
    839         u->host = g_strdup( irc->myhost );
    840         u->realname = g_strdup( ROOT_FN );
    841         u->online = 0;
    842         u->send_handler = root_command_string;
    843         u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */
    844        
    845         u = user_add( irc, irc->nick );
    846         u->user = g_strdup( irc->user );
    847         u->host = g_strdup( irc->host );
    848         u->realname = g_strdup( irc->realname );
    849         u->online = 1;
    850         irc_spawn( irc, u );
    851        
    852         irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
    853                           "If you've never used BitlBee before, please do read the help "
    854                           "information using the \x02help\x02 command. Lots of FAQs are "
    855                           "answered there.\n"
    856                           "If you already have an account on this server, just use the "
    857                           "\x02identify\x02 command to identify yourself." );
    858        
    859         if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
    860                 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    861        
    862         irc->status |= USTATUS_LOGGED_IN;
    863        
    864         /* This is for bug #209 (use PASS to identify to NickServ). */
    865         if( irc->password != NULL )
    866         {
    867                 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
    868                
    869                 irc_setpass( irc, NULL );
    870                 root_command( irc, send_cmd );
    871                 g_free( send_cmd[1] );
    872         }
    873 }
    874 
    875 void irc_motd( irc_t *irc )
    876 {
    877         int fd;
    878        
    879         fd = open( global.conf->motdfile, O_RDONLY );
    880         if( fd == -1 )
    881         {
    882                 irc_reply( irc, 422, ":We don't need MOTDs." );
    883         }
    884         else
    885         {
    886                 char linebuf[80];       /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */
    887                 char *add, max;
    888                 int len;
    889                
    890                 linebuf[79] = len = 0;
    891                 max = sizeof( linebuf ) - 1;
    892                
    893                 irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost );
    894                 while( read( fd, linebuf + len, 1 ) == 1 )
    895                 {
    896                         if( linebuf[len] == '\n' || len == max )
    897                         {
    898                                 linebuf[len] = 0;
    899                                 irc_reply( irc, 372, ":- %s", linebuf );
    900                                 len = 0;
    901                         }
    902                         else if( linebuf[len] == '%' )
    903                         {
    904                                 read( fd, linebuf + len, 1 );
    905                                 if( linebuf[len] == 'h' )
    906                                         add = irc->myhost;
    907                                 else if( linebuf[len] == 'v' )
    908                                         add = BITLBEE_VERSION;
    909                                 else if( linebuf[len] == 'n' )
    910                                         add = irc->nick;
    911                                 else
    912                                         add = "%";
    913                                
    914                                 strncpy( linebuf + len, add, max - len );
    915                                 while( linebuf[++len] );
    916                         }
    917                         else if( len < max )
    918                         {
    919                                 len ++;
    920                         }
    921                 }
    922                 irc_reply( irc, 376, ":End of MOTD" );
    923                 close( fd );
    924         }
    925 }
    926 
    927 void irc_topic( irc_t *irc, char *channel )
    928 {
    929         struct groupchat *c = irc_chat_by_channel( irc, channel );
    930        
    931         if( c && c->topic )
    932                 irc_reply( irc, 332, "%s :%s", channel, c->topic );
    933         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    934                 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC );
    935         else
    936                 irc_reply( irc, 331, "%s :No topic for this channel", channel );
    937 }
    938 
    939 void irc_umode_set( irc_t *irc, char *s, int allow_priv )
     662void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv )
    940663{
    941664        /* allow_priv: Set to 0 if s contains user input, 1 if you want
    942665           to set a "privileged" mode (+o, +R, etc). */
    943         char m[256], st = 1, *t;
     666        char m[128], st = 1;
     667        const char *t;
    944668        int i;
    945669        char changes[512], *p, st2 = 2;
     
    949673       
    950674        for( t = irc->umode; *t; t ++ )
    951                 m[(int)*t] = 1;
    952 
     675                if( *t < sizeof( m ) )
     676                        m[(int)*t] = 1;
     677       
    953678        p = changes;
    954679        for( t = s; *t; t ++ )
     
    956681                if( *t == '+' || *t == '-' )
    957682                        st = *t == '+';
    958                 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) )
     683                else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) ||
     684                         ( st == 1 && strchr( UMODES, *t ) ) ||
     685                         ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) )
    959686                {
    960687                        if( m[(int)*t] != st)
     
    973700        memset( irc->umode, 0, sizeof( irc->umode ) );
    974701       
    975         for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
     702        for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
    976703                if( m[i] )
    977704                        irc->umode[strlen(irc->umode)] = i;
    978705       
    979706        if( badflag )
    980                 irc_reply( irc, 501, ":Unknown MODE flag" );
    981         /* Deliberately no !user@host on the prefix here */
     707                irc_send_num( irc, 501, ":Unknown MODE flag" );
    982708        if( *changes )
    983                 irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes );
    984 }
    985 
    986 void irc_spawn( irc_t *irc, user_t *u )
    987 {
    988         irc_join( irc, u, irc->channel );
    989 }
    990 
    991 void irc_join( irc_t *irc, user_t *u, char *channel )
    992 {
    993         char *nick;
    994        
    995         if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) )
    996                 irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel );
    997        
    998         if( nick_cmp( u->nick, irc->nick ) == 0 )
    999         {
    1000                 irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE );
    1001                 irc_names( irc, channel );
    1002                 irc_topic( irc, channel );
    1003         }
    1004        
    1005         nick = g_strdup( u->nick );
    1006         nick_lc( nick );
    1007         if( g_hash_table_lookup( irc->watches, nick ) )
    1008         {
    1009                 irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" );
    1010         }
    1011         g_free( nick );
    1012 }
    1013 
    1014 void irc_part( irc_t *irc, user_t *u, char *channel )
    1015 {
    1016         irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" );
    1017 }
    1018 
    1019 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker )
    1020 {
    1021         irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" );
    1022 }
    1023 
    1024 void irc_kill( irc_t *irc, user_t *u )
    1025 {
    1026         char *nick, *s;
    1027         char reason[128];
    1028        
    1029         if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) )
    1030         {
    1031                 if( u->ic->acc->server )
    1032                         g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
    1033                                     u->ic->acc->server );
    1034                 else if( ( s = strchr( u->ic->acc->user, '@' ) ) )
    1035                         g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
    1036                                     s + 1 );
    1037                 else
    1038                         g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
    1039                                     u->ic->acc->prpl->name, irc->myhost );
    1040                
    1041                 /* proto_opt might contain garbage after the : */
    1042                 if( ( s = strchr( reason, ':' ) ) )
    1043                         *s = 0;
    1044         }
    1045         else
    1046         {
    1047                 strcpy( reason, "Leaving..." );
    1048         }
    1049        
    1050         irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
    1051        
    1052         nick = g_strdup( u->nick );
    1053         nick_lc( nick );
    1054         if( g_hash_table_lookup( irc->watches, nick ) )
    1055         {
    1056                 irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" );
    1057         }
    1058         g_free( nick );
    1059 }
    1060 
    1061 int irc_send( irc_t *irc, char *nick, char *s, int flags )
    1062 {
    1063         struct groupchat *c = NULL;
    1064         user_t *u = NULL;
    1065        
    1066         if( strchr( CTYPES, *nick ) )
    1067         {
    1068                 if( !( c = irc_chat_by_channel( irc, nick ) ) )
    1069                 {
    1070                         irc_reply( irc, 403, "%s :Channel does not exist", nick );
    1071                         return( 0 );
    1072                 }
    1073         }
    1074         else
    1075         {
    1076                 u = user_find( irc, nick );
    1077                
    1078                 if( !u )
    1079                 {
    1080                         if( irc->is_private )
    1081                                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1082                         else
    1083                                 irc_usermsg( irc, "Nick `%s' does not exist!", nick );
    1084                         return( 0 );
    1085                 }
    1086         }
    1087        
    1088         if( *s == 1 && s[strlen(s)-1] == 1 )
    1089         {
    1090                 if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 )
    1091                 {
    1092                         if( s[7] == ' ' ) s ++;
    1093                         s += 3;
    1094                         *(s++) = '/';
    1095                         *(s++) = 'm';
    1096                         *(s++) = 'e';
    1097                         *(s++) = ' ';
    1098                         s -= 4;
    1099                         s[strlen(s)-1] = 0;
    1100                 }
    1101                 else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 )
    1102                 {
    1103                         u = user_find( irc, irc->mynick );
    1104                         irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" );
    1105                         return( 1 );
    1106                 }
    1107                 else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 )
    1108                 {
    1109                         u = user_find( irc, irc->mynick );
    1110                         irc_privmsg( irc, u, "NOTICE", irc->nick, "", s );
    1111                         return( 1 );
    1112                 }
    1113                 else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 )
    1114                 {
    1115                         if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 )
    1116                         {
    1117                                 time_t current_typing_notice = time( NULL );
    1118                                
    1119                                 if( current_typing_notice - u->last_typing_notice >= 5 )
    1120                                 {
    1121                                         u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 );
    1122                                         u->last_typing_notice = current_typing_notice;
    1123                                 }
    1124                         }
    1125                         return( 1 );
    1126                 }
    1127                 else
    1128                 {
    1129                         irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
    1130                         return( 0 );
    1131                 }
    1132         }
    1133        
    1134         if( u )
    1135         {
    1136                 /* For the next message, we probably do have to send new notices... */
    1137                 u->last_typing_notice = 0;
    1138                 u->is_private = irc->is_private;
    1139                
    1140                 if( u->is_private )
    1141                 {
    1142                         if( !u->online )
    1143                                 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1144                         else if( u->away )
    1145                                 irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1146                 }
    1147                
    1148                 if( u->send_handler )
    1149                 {
    1150                         u->send_handler( irc, u, s, flags );
    1151                         return 1;
    1152                 }
    1153         }
    1154         else if( c && c->ic && c->ic->acc && c->ic->acc->prpl )
    1155         {
    1156                 return( imc_chat_msg( c, s, 0 ) );
    1157         }
    1158        
    1159         return( 0 );
    1160 }
    1161 
    1162 static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond )
    1163 {
    1164         user_t *u = data;
    1165        
    1166         /* Shouldn't happen, but just to be sure. */
    1167         if( u->sendbuf_len < 2 )
    1168                 return FALSE;
    1169        
    1170         u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */
    1171         imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags );
    1172        
    1173         g_free( u->sendbuf );
    1174         u->sendbuf = NULL;
    1175         u->sendbuf_len = 0;
    1176         u->sendbuf_timer = 0;
    1177         u->sendbuf_flags = 0;
    1178        
    1179         return FALSE;
    1180 }
    1181 
    1182 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
    1183 {
    1184         if( !u || !u->ic ) return;
    1185        
    1186         if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 )
    1187         {
    1188                 int delay;
    1189                
    1190                 if( u->sendbuf_len > 0 && u->sendbuf_flags != flags)
    1191                 {
    1192                         /* Flush the buffer */
    1193                         b_event_remove( u->sendbuf_timer );
    1194                         buddy_send_handler_delayed( u, -1, 0 );
    1195                 }
    1196 
    1197                 if( u->sendbuf_len == 0 )
    1198                 {
    1199                         u->sendbuf_len = strlen( msg ) + 2;
    1200                         u->sendbuf = g_new( char, u->sendbuf_len );
    1201                         u->sendbuf[0] = 0;
    1202                         u->sendbuf_flags = flags;
    1203                 }
    1204                 else
    1205                 {
    1206                         u->sendbuf_len += strlen( msg ) + 1;
    1207                         u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len );
    1208                 }
    1209                
    1210                 strcat( u->sendbuf, msg );
    1211                 strcat( u->sendbuf, "\n" );
    1212                
    1213                 delay = set_getint( &irc->set, "buddy_sendbuffer_delay" );
    1214                 if( delay <= 5 )
    1215                         delay *= 1000;
    1216                
    1217                 if( u->sendbuf_timer > 0 )
    1218                         b_event_remove( u->sendbuf_timer );
    1219                 u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u );
    1220         }
    1221         else
    1222         {
    1223                 imc_buddy_msg( u->ic, u->handle, msg, flags );
    1224         }
    1225 }
    1226 
    1227 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg )
    1228 {
    1229         char last = 0;
    1230         char *s = msg, *line = msg;
    1231        
    1232         /* The almighty linesplitter .. woohoo!! */
    1233         while( !last )
    1234         {
    1235                 if( *s == '\r' && *(s+1) == '\n' )
    1236                         *(s++) = 0;
    1237                 if( *s == '\n' )
    1238                 {
    1239                         last = s[1] == 0;
    1240                         *s = 0;
    1241                 }
    1242                 else
    1243                 {
    1244                         last = s[0] == 0;
    1245                 }
    1246                 if( *s == 0 )
    1247                 {
    1248                         if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 )
    1249                         {
    1250                                 irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host,
    1251                                            type, to, line + 4 );
    1252                         }
    1253                         else
    1254                         {
    1255                                 irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host,
    1256                                            type, to, prefix ? prefix : "", line );
    1257                         }
    1258                         line = s + 1;
    1259                 }
    1260                 s ++;
    1261         }
    1262        
    1263         return( 1 );
    1264 }
    1265 
    1266 int irc_msgfrom( irc_t *irc, char *nick, char *msg )
    1267 {
    1268         user_t *u = user_find( irc, nick );
    1269         static char *prefix = NULL;
    1270        
    1271         if( !u ) return( 0 );
    1272         if( prefix && *prefix ) g_free( prefix );
    1273        
    1274         if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 )
    1275         {
    1276                 int len = strlen( irc->nick) + 3;
    1277                 prefix = g_new (char, len );
    1278                 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) );
    1279                 prefix[len-1] = 0;
    1280         }
    1281         else
    1282         {
    1283                 prefix = "";
    1284         }
    1285        
    1286         return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) );
    1287 }
    1288 
    1289 int irc_noticefrom( irc_t *irc, char *nick, char *msg )
    1290 {
    1291         user_t *u = user_find( irc, nick );
    1292        
    1293         if( u )
    1294                 return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) );
    1295         else
    1296                 return( 0 );
    1297 }
     709                irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick,
     710                           irc->user->user, irc->user->host, irc->user->nick,
     711                           changes );
     712}
     713
    1298714
    1299715/* Returns 0 if everything seems to be okay, a number >0 when there was a
     
    1333749}
    1334750
    1335 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )
    1336 {
    1337         struct groupchat *c;
    1338         account_t *a;
    1339        
    1340         /* This finds the connection which has a conversation which belongs to this channel */
    1341         for( a = irc->accounts; a; a = a->next )
    1342         {
    1343                 if( a->ic == NULL )
    1344                         continue;
    1345                
    1346                 c = a->ic->groupchats;
    1347                 while( c )
    1348                 {
    1349                         if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )
    1350                                 return c;
    1351                        
    1352                         c = c->next;
    1353                 }
    1354         }
    1355        
    1356         return NULL;
    1357 }
     751static char *set_eval_charset( set_t *set, char *value )
     752{
     753        irc_t *irc = (irc_t*) set->data;
     754        char *test;
     755        gsize test_bytes = 0;
     756        GIConv ic, oc;
     757
     758        if( g_strcasecmp( value, "none" ) == 0 )
     759                value = g_strdup( "utf-8" );
     760
     761        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     762        {
     763                return NULL;
     764        }
     765       
     766        /* Do a test iconv to see if the user picked an IRC-compatible
     767           charset (for example utf-16 goes *horribly* wrong). */
     768        if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
     769            test_bytes > 1 )
     770        {
     771                g_free( test );
     772                g_iconv_close( oc );
     773                irc_usermsg( irc, "Unsupported character set: The IRC protocol "
     774                                  "only supports 8-bit character sets." );
     775                return NULL;
     776        }
     777        g_free( test );
     778       
     779        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     780        {
     781                g_iconv_close( oc );
     782                return NULL;
     783        }
     784       
     785        if( irc->iconv != (GIConv) -1 )
     786                g_iconv_close( irc->iconv );
     787        if( irc->oconv != (GIConv) -1 )
     788                g_iconv_close( irc->oconv );
     789       
     790        irc->iconv = ic;
     791        irc->oconv = oc;
     792
     793        return value;
     794}
  • irc.h

    r156bbd7 r21c87a7  
    55  \********************************************************************/
    66
    7 /* The big hairy IRCd part of the project                               */
     7/* The IRC-based UI (for now the only one)                              */
    88
    99/*
     
    3333#define IRC_PING_STRING "PinglBee"
    3434
    35 #define UMODES "abisw"
    36 #define UMODES_PRIV "Ro"
    37 #define CMODES "nt"
    38 #define CMODE "t"
    39 #define UMODE "s"
    40 #define CTYPES "&#"
     35#define UMODES "abisw"     /* Allowed umodes (although they mostly do nothing) */
     36#define UMODES_PRIV "Ro"   /* Allowed, but not by user directly */
     37#define UMODES_KEEP "R"    /* Don't allow unsetting using /MODE */
     38#define CMODES "nt"        /* Allowed modes */
     39#define CMODE "t"          /* Default mode */
     40#define UMODE "s"          /* Default mode */
     41
     42#define CTYPES "&#"        /* Valid channel name prefixes */
    4143
    4244typedef enum
     
    4850        USTATUS_SHUTDOWN = 8
    4951} irc_status_t;
     52
     53struct irc_user;
    5054
    5155typedef struct irc
     
    5963        GIConv iconv, oconv;
    6064
    61         int sentbytes;
    62         time_t oldtime;
    63 
     65        struct irc_user *root;
     66        struct irc_user *user;
     67       
     68        char *last_root_cmd;
     69
     70        char *password; /* HACK: Used to save the user's password, but before
     71                           logging in, this may contain a password we should
     72                           send to identify after USER/NICK are received. */
     73
     74        char umode[8];
     75       
     76        struct query *queries;
     77        GSList *file_transfers;
     78       
     79        GSList *users, *channels;
     80        GHashTable *nick_user_hash;
     81        GHashTable *watches;
     82
     83        gint r_watch_source_id;
     84        gint w_watch_source_id;
     85        gint ping_source_id;
     86       
     87        struct bee *b;
     88} irc_t;
     89
     90typedef enum
     91{
     92        IRC_USER_PRIVATE = 1,
     93} irc_user_flags_t;
     94
     95typedef struct irc_user
     96{
     97        irc_t *irc;
     98       
    6499        char *nick;
    65100        char *user;
    66101        char *host;
    67         char *realname;
    68         char *password; /* HACK: Used to save the user's password, but before
    69                            logging in, this may contain a password we should
    70                            send to identify after USER/NICK are received. */
    71 
    72         char umode[8];
    73        
    74         char *myhost;
    75         char *mynick;
    76 
    77         char *channel;
    78         int c_id;
    79 
    80         char is_private;                /* Not too nice... */
    81         char *last_target;
    82        
    83         struct query *queries;
    84         struct account *accounts;
    85         struct chat *chatrooms;
    86        
    87         struct __USER *users;
    88         GHashTable *userhash;
    89         GHashTable *watches;
    90         struct __NICK *nicks;
     102        char *fullname;
     103       
     104        /* Nickname in lowercase for case sensitive searches */
     105        char *key;
     106       
     107        irc_user_flags_t flags;
     108       
     109        char *sendbuf;
     110        int sendbuf_len;
     111        guint sendbuf_timer;
     112        //int sendbuf_flags;
     113       
     114        struct bee_user *bu;
     115       
     116        const struct irc_user_funcs *f;
     117} irc_user_t;
     118
     119struct irc_user_funcs
     120{
     121        gboolean (*privmsg)( irc_user_t *iu, const char *msg );
     122        gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp );
     123};
     124
     125extern const struct irc_user_funcs irc_user_root_funcs;
     126extern const struct irc_user_funcs irc_user_self_funcs;
     127
     128typedef enum
     129{
     130        IRC_CHANNEL_JOINED = 1,
     131} irc_channel_flags_t;
     132
     133typedef struct irc_channel
     134{
     135        irc_t *irc;
     136        char *name;
     137        char mode[8];
     138        int flags;
     139       
     140        char *topic;
     141        char *topic_who;
     142        time_t topic_time;
     143       
     144        GSList *users;
    91145        struct set *set;
    92 
    93         gint r_watch_source_id;
    94         gint w_watch_source_id;
    95         gint ping_source_id;
    96 } irc_t;
    97 
    98 #include "user.h"
    99 
     146       
     147        const struct irc_channel_funcs *f;
     148} irc_channel_t;
     149
     150struct irc_channel_funcs
     151{
     152        gboolean (*privmsg)( irc_channel_t *iu, const char *msg );
     153};
     154
     155extern const struct bee_ui_funcs irc_ui_funcs;
     156
     157/* irc.c */
    100158extern GSList *irc_connection_list;
    101159
     
    103161void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    104162void irc_free( irc_t *irc );
    105 
    106 void irc_exec( irc_t *irc, char **cmd );
     163void irc_setpass (irc_t *irc, const char *pass);
     164
    107165void irc_process( irc_t *irc );
    108166char **irc_parse_line( char *line );
    109167char *irc_build_line( char **cmd );
    110168
    111 void irc_vawrite( irc_t *irc, char *format, va_list params );
    112169void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    113170void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    114 void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    115 G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    116 char **irc_tokenize( char *buffer );
    117 
    118 void irc_login( irc_t *irc );
     171void irc_vawrite( irc_t *irc, char *format, va_list params );
     172
    119173int irc_check_login( irc_t *irc );
    120 void irc_motd( irc_t *irc );
    121 void irc_names( irc_t *irc, char *channel );
    122 void irc_topic( irc_t *irc, char *channel );
    123 void irc_umode_set( irc_t *irc, char *s, int allow_priv );
    124 void irc_who( irc_t *irc, char *channel );
    125 void irc_spawn( irc_t *irc, user_t *u );
    126 void irc_join( irc_t *irc, user_t *u, char *channel );
    127 void irc_part( irc_t *irc, user_t *u, char *channel );
    128 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker );
    129 void irc_kill( irc_t *irc, user_t *u );
    130 void irc_invite( irc_t *irc, char *nick, char *channel );
    131 void irc_whois( irc_t *irc, char *nick );
    132 void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */
    133 
    134 int irc_send( irc_t *irc, char *nick, char *s, int flags );
    135 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg );
    136 int irc_msgfrom( irc_t *irc, char *nick, char *msg );
    137 int irc_noticefrom( irc_t *irc, char *nick, char *msg );
    138 
    139 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
    140 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
     174
     175void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv );
     176
     177/* irc_channel.c */
     178irc_channel_t *irc_channel_new( irc_t *irc, const char *name );
     179irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name );
     180int irc_channel_free( irc_channel_t *ic );
     181int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu );
     182int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu );
     183gboolean irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
     184int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who );
     185gboolean irc_channel_name_ok( const char *name );
     186
     187/* irc_commands.c */
     188void irc_exec( irc_t *irc, char **cmd );
     189
     190/* irc_send.c */
     191void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
     192void irc_send_login( irc_t *irc );
     193void irc_send_motd( irc_t *irc );
     194void irc_usermsg( irc_t *irc, char *format, ... );
     195void irc_send_join( irc_channel_t *ic, irc_user_t *iu );
     196void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason );
     197void irc_send_names( irc_channel_t *ic );
     198void irc_send_topic( irc_channel_t *ic, gboolean topic_change );
     199void irc_send_whois( irc_user_t *iu );
     200void irc_send_who( irc_t *irc, GSList *l, const char *channel );
     201void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix );
     202void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg );
     203void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 );
     204void irc_send_nick( irc_user_t *iu, const char *new );
     205
     206/* irc_user.c */
     207irc_user_t *irc_user_new( irc_t *irc, const char *nick );
     208int irc_user_free( irc_t *irc, irc_user_t *iu );
     209irc_user_t *irc_user_by_name( irc_t *irc, const char *nick );
     210int irc_user_set_nick( irc_user_t *iu, const char *new );
     211gint irc_user_cmp( gconstpointer a_, gconstpointer b_ );
     212
     213/* irc_util.c */
     214char *set_eval_timezone( struct set *set, char *value );
     215char *irc_format_timestamp( irc_t *irc, time_t msg_ts );
    141216
    142217#endif
  • irc_commands.c

    r156bbd7 r21c87a7  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2006 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    5353        else if( global.conf->auth_pass )
    5454        {
    55                 irc_reply( irc, 464, ":Incorrect password" );
     55                irc_send_num( irc, 464, ":Incorrect password" );
    5656        }
    5757        else
    5858        {
    5959                /* Remember the password and try to identify after USER/NICK. */
    60                 irc_setpass( irc, cmd[1] );
     60                /*irc_setpass( irc, cmd[1] ); */
    6161                irc_check_login( irc );
    6262        }
     
    6565static void irc_cmd_user( irc_t *irc, char **cmd )
    6666{
    67         irc->user = g_strdup( cmd[1] );
    68         irc->realname = g_strdup( cmd[4] );
     67        irc->user->user = g_strdup( cmd[1] );
     68        irc->user->fullname = g_strdup( cmd[4] );
    6969       
    7070        irc_check_login( irc );
     
    7373static void irc_cmd_nick( irc_t *irc, char **cmd )
    7474{
    75         if( irc->nick )
    76         {
    77                 irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    78         }
    79         /* This is not clean, but for now it'll have to be like this... */
    80         else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    81         {
    82                 irc_reply( irc, 433, ":This nick is already in use" );
     75        if( irc_user_by_name( irc, cmd[1] ) )
     76        {
     77                irc_send_num( irc, 433, ":This nick is already in use" );
    8378        }
    8479        else if( !nick_ok( cmd[1] ) )
    8580        {
    8681                /* [SH] Invalid characters. */
    87                 irc_reply( irc, 432, ":This nick contains invalid characters" );
    88         }
    89         else
    90         {
    91                 irc->nick = g_strdup( cmd[1] );
     82                irc_send_num( irc, 432, ":This nick contains invalid characters" );
     83        }
     84        else if( irc->user->nick )
     85        {
     86                if( irc->status & USTATUS_IDENTIFIED )
     87                {
     88                        irc_setpass( irc, NULL );
     89                        irc->status &= ~USTATUS_IDENTIFIED;
     90                        irc_umode_set( irc, "-R", 1 );
     91                }
     92               
     93                irc_user_set_nick( irc->user, cmd[1] );
     94        }
     95        else
     96        {
     97                irc->user->nick = g_strdup( cmd[1] );
    9298               
    9399                irc_check_login( irc );
     
    105111static void irc_cmd_ping( irc_t *irc, char **cmd )
    106112{
    107         irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
    108 }
    109 
    110 static void irc_cmd_oper( irc_t *irc, char **cmd )
    111 {
    112         if( global.conf->oper_pass &&
    113             ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
    114                 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
    115                 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
    116         {
    117                 irc_umode_set( irc, "+o", 1 );
    118                 irc_reply( irc, 381, ":Password accepted" );
    119         }
    120         else
    121         {
    122                 irc_reply( irc, 432, ":Incorrect password" );
    123         }
     113        irc_write( irc, ":%s PONG %s :%s", irc->root->host,
     114                   irc->root->host, cmd[1]?cmd[1]:irc->root->host );
     115}
     116
     117static void irc_cmd_pong( irc_t *irc, char **cmd )
     118{
     119        /* We could check the value we get back from the user, but in
     120           fact we don't care, we're just happy s/he's still alive. */
     121        irc->last_pong = gettime();
     122        irc->pinging = 0;
     123}
     124
     125static void irc_cmd_join( irc_t *irc, char **cmd )
     126{
     127        irc_channel_t *ic;
     128       
     129        if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
     130                ic = irc_channel_new( irc, cmd[1] );
     131       
     132        if( ic == NULL )
     133        {
     134                irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] );
     135                return;
     136        }
     137       
     138        if( ic->flags & IRC_CHANNEL_JOINED )
     139                return; /* Dude, you're already there...
     140                           RFC doesn't have any reply for that though? */
     141       
     142        irc_channel_add_user( ic, irc->user );
     143}
     144
     145static void irc_cmd_names( irc_t *irc, char **cmd )
     146{
     147        irc_channel_t *ic;
     148       
     149        if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
     150                irc_send_names( ic );
     151        /* With no args, we should show /names of all chans. Make the code
     152           below work well if necessary.
     153        else
     154        {
     155                GSList *l;
     156               
     157                for( l = irc->channels; l; l = l->next )
     158                        irc_send_names( l->data );
     159        }
     160        */
     161}
     162
     163static void irc_cmd_part( irc_t *irc, char **cmd )
     164{
     165        irc_channel_t *ic;
     166       
     167        if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
     168        {
     169                irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
     170        }
     171        else if( !irc_channel_del_user( ic, irc->user ) )
     172        {
     173                irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] );
     174        }
     175}
     176
     177static void irc_cmd_whois( irc_t *irc, char **cmd )
     178{
     179        char *nick = cmd[1];
     180        irc_user_t *iu = irc_user_by_name( irc, nick );
     181       
     182        if( iu )
     183                irc_send_whois( iu );
     184        else
     185                irc_send_num( irc, 401, "%s :Nick does not exist", nick );
     186}
     187
     188static void irc_cmd_whowas( irc_t *irc, char **cmd )
     189{
     190        /* For some reason irssi tries a whowas when whois fails. We can
     191           ignore this, but then the user never gets a "user not found"
     192           message from irssi which is a bit annoying. So just respond
     193           with not-found and irssi users will get better error messages */
     194       
     195        irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
     196        irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
     197}
     198
     199static void irc_cmd_motd( irc_t *irc, char **cmd )
     200{
     201        irc_send_motd( irc );
    124202}
    125203
    126204static void irc_cmd_mode( irc_t *irc, char **cmd )
    127205{
    128         if( strchr( CTYPES, *cmd[1] ) )
    129         {
    130                 if( cmd[2] )
     206        if( irc_channel_name_ok( cmd[1] ) )
     207        {
     208                irc_channel_t *ic;
     209               
     210                if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
     211                        irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
     212                else if( cmd[2] )
    131213                {
    132214                        if( *cmd[2] == '+' || *cmd[2] == '-' )
    133                                 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
     215                                irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
    134216                        else if( *cmd[2] == 'b' )
    135                                 irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
     217                                irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
    136218                }
    137219                else
    138                         irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
    139         }
    140         else
    141         {
    142                 if( nick_cmp( cmd[1], irc->nick ) == 0 )
     220                        irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );
     221        }
     222        else
     223        {
     224                if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
    143225                {
    144226                        if( cmd[2] )
    145227                                irc_umode_set( irc, cmd[2], 0 );
    146228                        else
    147                                 irc_reply( irc, 221, "+%s", irc->umode );
     229                                irc_send_num( irc, 221, "+%s", irc->umode );
    148230                }
    149231                else
    150                         irc_reply( irc, 502, ":Don't touch their modes" );
    151         }
    152 }
    153 
    154 static void irc_cmd_names( irc_t *irc, char **cmd )
    155 {
    156         irc_names( irc, cmd[1]?cmd[1]:irc->channel );
    157 }
    158 
    159 static void irc_cmd_part( irc_t *irc, char **cmd )
    160 {
    161         struct groupchat *c;
    162        
    163         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    164         {
    165                 user_t *u = user_find( irc, irc->nick );
    166                
    167                 /* Not allowed to leave control channel */
    168                 irc_part( irc, u, irc->channel );
    169                 irc_join( irc, u, irc->channel );
    170         }
    171         else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) )
    172         {
    173                 user_t *u = user_find( irc, irc->nick );
    174                
    175                 irc_part( irc, u, c->channel );
    176                
    177                 if( c->ic )
    178                 {
    179                         c->joined = 0;
    180                         c->ic->acc->prpl->chat_leave( c );
    181                 }
    182         }
    183         else
    184         {
    185                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    186         }
    187 }
    188 
    189 static void irc_cmd_join( irc_t *irc, char **cmd )
    190 {
    191         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    192                 ; /* Dude, you're already there...
    193                      RFC doesn't have any reply for that though? */
    194         else if( cmd[1] )
    195         {
    196                 struct chat *c;
    197                
    198                 if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 )
    199                         irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] );
    200                 else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic )
    201                         chat_join( irc, c, cmd[2] );
    202                 else
    203                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    204         }
    205 }
    206 
    207 static void irc_cmd_invite( irc_t *irc, char **cmd )
    208 {
    209         char *nick = cmd[1], *channel = cmd[2];
    210         struct groupchat *c = irc_chat_by_channel( irc, channel );
    211         user_t *u = user_find( irc, nick );
    212        
    213         if( u && c && ( u->ic == c->ic ) )
    214                 if( c->ic && c->ic->acc->prpl->chat_invite )
    215                 {
    216                         c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
    217                         irc_reply( irc, 341, "%s %s", nick, channel );
    218                         return;
    219                 }
    220        
    221         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
     232                        irc_send_num( irc, 502, ":Don't touch their modes" );
     233        }
     234}
     235
     236static void irc_cmd_who( irc_t *irc, char **cmd )
     237{
     238        char *channel = cmd[1];
     239        irc_channel_t *ic;
     240       
     241        if( !channel || *channel == '0' || *channel == '*' || !*channel )
     242                irc_send_who( irc, irc->users, "**" );
     243        else if( ( ic = irc_channel_by_name( irc, channel ) ) )
     244                irc_send_who( irc, ic->users, channel );
     245        else
     246                irc_send_num( irc, 403, "%s :No such channel", channel );
    222247}
    223248
    224249static void irc_cmd_privmsg( irc_t *irc, char **cmd )
    225250{
    226         if ( !cmd[2] )
    227         {
    228                 irc_reply( irc, 412, ":No text to send" );
    229         }
    230         else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    231         {
    232                 irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
     251        irc_channel_t *ic;
     252        irc_user_t *iu;
     253       
     254        if( !cmd[2] )
     255        {
     256                irc_send_num( irc, 412, ":No text to send" );
     257                return;
     258        }
     259       
     260        /* Don't treat CTCP actions as real CTCPs, just convert them right now. */
     261        if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 )
     262        {
     263                cmd[2] += 4;
     264                strcpy( cmd[2], "/me" );
     265                if( cmd[2][strlen(cmd[2])-1] == '\001' )
     266                        cmd[2][strlen(cmd[2])-1] = '\0';
     267        }
     268       
     269        if( irc_channel_name_ok( cmd[1] ) &&
     270            ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
     271        {
     272                if( ic->f->privmsg )
     273                        ic->f->privmsg( ic, cmd[2] );
     274        }
     275        else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) )
     276        {
     277                if( cmd[2][0] == '\001' )
     278                {
     279                        char **ctcp;
     280                       
     281                        if( iu->f->ctcp == NULL )
     282                                return;
     283                        if( cmd[2][strlen(cmd[2])-1] == '\001' )
     284                                cmd[2][strlen(cmd[2])-1] = '\0';
     285                       
     286                        ctcp = split_command_parts( cmd[2] + 1 );
     287                        iu->f->ctcp( iu, ctcp );
     288                }
     289                else if( iu->f->privmsg )
     290                        iu->f->privmsg( iu, cmd[2] );
     291        }
     292        else
     293        {
     294                irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
     295        }
     296
     297
     298#if 0
     299        else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
     300        {
    233301        }
    234302        else
     
    271339                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
    272340        }
    273 }
    274 
    275 static void irc_cmd_who( irc_t *irc, char **cmd )
    276 {
    277         char *channel = cmd[1];
    278         user_t *u = irc->users;
    279         struct groupchat *c;
    280         GList *l;
    281        
    282         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    283                 while( u )
    284                 {
    285                         irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
    286                         u = u->next;
    287                 }
    288         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    289                 while( u )
    290                 {
    291                         if( u->online )
    292                                 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
    293                         u = u->next;
    294                 }
    295         else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    296                 for( l = c->in_room; l; l = l->next )
    297                 {
    298                         if( ( u = user_findhandle( c->ic, l->data ) ) )
    299                                 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
    300                 }
    301         else if( ( u = user_find( irc, channel ) ) )
    302                 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
    303        
    304         irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" );
     341#endif
     342}
     343
     344static void irc_cmd_nickserv( irc_t *irc, char **cmd )
     345{
     346        /* [SH] This aliases the NickServ command to PRIVMSG root */
     347        /* [TV] This aliases the NS command to PRIVMSG root as well */
     348        root_command( irc, cmd + 1 );
     349}
     350
     351
     352
     353#if 0
     354static void irc_cmd_oper( irc_t *irc, char **cmd )
     355{
     356        if( global.conf->oper_pass &&
     357            ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
     358                md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
     359                strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
     360        {
     361                irc_umode_set( irc, "+o", 1 );
     362                irc_send_num( irc, 381, ":Password accepted" );
     363        }
     364        else
     365        {
     366                irc_send_num( irc, 432, ":Incorrect password" );
     367        }
     368}
     369
     370static void irc_cmd_invite( irc_t *irc, char **cmd )
     371{
     372        char *nick = cmd[1], *channel = cmd[2];
     373        struct groupchat *c = irc_chat_by_channel( irc, channel );
     374        user_t *u = user_find( irc, nick );
     375       
     376        if( u && c && ( u->ic == c->ic ) )
     377                if( c->ic && c->ic->acc->prpl->chat_invite )
     378                {
     379                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
     380                        irc_send_num( irc, 341, "%s %s", nick, channel );
     381                        return;
     382                }
     383       
     384        irc_send_num( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    305385}
    306386
     
    320400                {
    321401                        if( u->online && u->away )
    322                                 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
     402                                irc_send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    323403                        else
    324                                 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
     404                                irc_send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    325405                }
    326406}
     
    377457                buff[strlen(buff)-1] = '\0';
    378458       
    379         irc_reply( irc, 303, ":%s", buff );
     459        irc_send_num( irc, 303, ":%s", buff );
    380460}
    381461
     
    406486                       
    407487                        if( u && u->online )
    408                                 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
     488                                irc_send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
    409489                        else
    410                                 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
     490                                irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
    411491                }
    412492                else if( cmd[i][0] == '-' )
     
    419499                                g_free( okey );
    420500                               
    421                                 irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
     501                                irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    422502                        }
    423503                }
     
    443523        }
    444524}
     525#endif
    445526
    446527static void irc_cmd_away( irc_t *irc, char **cmd )
    447528{
    448         user_t *u = user_find( irc, irc->nick );
    449         char *away = cmd[1];
    450        
    451         if( !u ) return;
    452        
    453         if( away && *away )
    454         {
     529        char *set;
     530       
     531        if( cmd[1] && *cmd[1] )
     532        {
     533                char away[strlen(cmd[1])+1];
    455534                int i, j;
    456535               
    457536                /* Copy away string, but skip control chars. Mainly because
    458537                   Jabber really doesn't like them. */
    459                 u->away = g_malloc( strlen( away ) + 1 );
    460                 for( i = j = 0; away[i]; i ++ )
    461                         if( ( u->away[j] = away[i] ) >= ' ' )
     538                for( i = j = 0; cmd[1][i]; i ++ )
     539                        if( ( away[j] = cmd[1][i] ) >= ' ' )
    462540                                j ++;
    463                 u->away[j] = 0;
    464                
    465                 irc_reply( irc, 306, ":You're now away: %s", u->away );
    466                 /* irc_umode_set( irc, irc->myhost, "+a" ); */
    467         }
    468         else
    469         {
    470                 if( u->away ) g_free( u->away );
    471                 u->away = NULL;
    472                 /* irc_umode_set( irc, irc->myhost, "-a" ); */
    473                 irc_reply( irc, 305, ":Welcome back" );
    474         }
    475        
    476         set_setstr( &irc->set, "away", u->away );
    477 }
    478 
    479 static void irc_cmd_whois( irc_t *irc, char **cmd )
    480 {
    481         char *nick = cmd[1];
    482         user_t *u = user_find( irc, nick );
    483        
    484         if( u )
    485         {
    486                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    487                
    488                 if( u->ic )
    489                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user,
    490                                    u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "",
    491                                    u->ic->acc->prpl->name );
    492                 else
    493                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    494                
    495                 if( !u->online )
    496                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    497                 else if( u->away )
    498                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    499                 if( u->status_msg )
    500                         irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg );
    501                
    502                 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
    503         }
    504         else
    505         {
    506                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    507         }
    508 }
    509 
    510 static void irc_cmd_whowas( irc_t *irc, char **cmd )
    511 {
    512         /* For some reason irssi tries a whowas when whois fails. We can
    513            ignore this, but then the user never gets a "user not found"
    514            message from irssi which is a bit annoying. So just respond
    515            with not-found and irssi users will get better error messages */
    516        
    517         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    518         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
    519 }
    520 
    521 static void irc_cmd_nickserv( irc_t *irc, char **cmd )
    522 {
    523         /* [SH] This aliases the NickServ command to PRIVMSG root */
    524         /* [TV] This aliases the NS command to PRIVMSG root as well */
    525         root_command( irc, cmd + 1 );
    526 }
    527 
    528 static void irc_cmd_motd( irc_t *irc, char **cmd )
    529 {
    530         irc_motd( irc );
    531 }
    532 
    533 static void irc_cmd_pong( irc_t *irc, char **cmd )
    534 {
    535         /* We could check the value we get back from the user, but in
    536            fact we don't care, we're just happy he's still alive. */
    537         irc->last_pong = gettime();
    538         irc->pinging = 0;
    539 }
    540 
     541                away[j] = '\0';
     542               
     543                irc_send_num( irc, 306, ":You're now away: %s", away );
     544                set = away;
     545        }
     546        else
     547        {
     548                irc_send_num( irc, 305, ":Welcome back" );
     549                set = NULL;
     550        }
     551       
     552        set_setstr( &irc->b->set, "away", set );
     553}
     554
     555#if 0
    541556static void irc_cmd_version( irc_t *irc, char **cmd )
    542557{
    543         irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
     558        irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
    544559}
    545560
     
    572587                ipc_to_master( cmd );
    573588       
    574         irc_reply( irc, 382, "%s :Rehashing", global.conf_file );
    575 }
     589        irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
     590}
     591#endif
    576592
    577593static const command_t irc_commands[] = {
     
    581597        { "quit",        0, irc_cmd_quit,        0 },
    582598        { "ping",        0, irc_cmd_ping,        0 },
     599        { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
     600        { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
     601        { "names",       1, irc_cmd_names,       IRC_CMD_LOGGED_IN },
     602        { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
     603        { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
     604        { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
     605        { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
     606        { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
     607        { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
     608        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
     609        { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
     610        { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
     611        { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
     612#if 0
    583613        { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
    584         { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
    585         { "names",       0, irc_cmd_names,       IRC_CMD_LOGGED_IN },
    586         { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
    587         { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
    588614        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
    589         { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    590615        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    591         { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
    592616        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
    593617        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
    594618        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
    595619        { "topic",       1, irc_cmd_topic,       IRC_CMD_LOGGED_IN },
    596         { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
    597         { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
    598         { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
    599         { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
    600         { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
    601         { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
    602         { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
    603620        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
    604621        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
     
    610627        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    611628        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
     629#endif
    612630        { NULL }
    613631};
     
    628646                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
    629647                        {
    630                                 irc_reply( irc, 462, ":Only allowed before logging in" );
     648                                irc_send_num( irc, 462, ":Only allowed before logging in" );
    631649                        }
    632650                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
    633651                        {
    634                                 irc_reply( irc, 451, ":Register first" );
     652                                irc_send_num( irc, 451, ":Register first" );
    635653                        }
    636654                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
    637655                        {
    638                                 irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" );
     656                                irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
    639657                        }
    640658                        else if( n_arg < irc_commands[i].required_parameters )
    641659                        {
    642                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     660                                irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
    643661                        }
    644662                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
     
    657675       
    658676        if( irc->status >= USTATUS_LOGGED_IN )
    659                 irc_reply( irc, 421, "%s :Unknown command", cmd[0] );
    660 }
     677                irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
     678}
  • lib/Makefile

    r156bbd7 r21c87a7  
    1010
    1111# [SH] Program variables
    12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
     12objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ftutil.o
    1313
    1414CFLAGS += -Wall
  • lib/misc.c

    r156bbd7 r21c87a7  
    649649        return ret;
    650650}
     651
     652char **split_command_parts( char *command )
     653{
     654        static char *cmd[IRC_MAX_ARGS+1];
     655        char *s, q = 0;
     656        int k;
     657       
     658        memset( cmd, 0, sizeof( cmd ) );
     659        cmd[0] = command;
     660        k = 1;
     661        for( s = command; *s && k < IRC_MAX_ARGS; s ++ )
     662                if( *s == ' ' && !q )
     663                {
     664                        *s = 0;
     665                        while( *++s == ' ' );
     666                        if( *s == '"' || *s == '\'' )
     667                        {
     668                                q = *s;
     669                                s ++;
     670                        }
     671                        if( *s )
     672                        {
     673                                cmd[k++] = s;
     674                                s --;
     675                        }
     676                        else
     677                        {
     678                                break;
     679                        }
     680                }
     681                else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
     682                {
     683                        char *cpy;
     684                       
     685                        for( cpy = s; *cpy; cpy ++ )
     686                                cpy[0] = cpy[1];
     687                }
     688                else if( *s == q )
     689                {
     690                        q = *s = 0;
     691                }
     692       
     693        /* Full zero-padding for easier argc checking. */
     694        while( k <= IRC_MAX_ARGS )
     695                cmd[k++] = NULL;
     696       
     697        return cmd;
     698}
  • lib/misc.h

    r156bbd7 r21c87a7  
    6969G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
    7070
     71G_MODULE_EXPORT char **split_command_parts( char *command );
     72
    7173#endif
  • nick.c

    r156bbd7 r21c87a7  
    7878               
    7979                nick_strip( nick );
    80                 if( set_getbool( &acc->irc->set, "lcnicks" ) )
     80                if( set_getbool( &acc->bee->set, "lcnicks" ) )
    8181                        nick_lc( nick );
    8282        }
     
    9292void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] )
    9393{
     94        irc_t *irc = (irc_t*) acc->bee->ui_data;
    9495        int inf_protection = 256;
    9596       
    9697        /* Now, find out if the nick is already in use at the moment, and make
    9798           subtle changes to make it unique. */
    98         while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
     99        while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) )
    99100        {
    100101                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
     
    112113                        int i;
    113114                       
    114                         irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! "
    115                                                "This used to be a fatal BitlBee bug, but we tried to fix it. "
    116                                                "This message should *never* appear anymore. "
    117                                                "If it does, please *do* send us a bug report! "
    118                                                "Please send all the following lines in your report:" );
    119                        
    120                         irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );
     115                        irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! "
     116                                          "This used to be a fatal BitlBee bug, but we tried to fix it. "
     117                                          "This message should *never* appear anymore. "
     118                                          "If it does, please *do* send us a bug report! "
     119                                          "Please send all the following lines in your report:" );
     120                       
     121                        irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle );
    121122                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
    122                                 irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );
    123                        
    124                         irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "
    125                                                "Good luck, and please don't forget to paste the lines up here "
    126                                                "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
     123                                irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] );
     124                       
     125                        irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. "
     126                                          "Good luck, and please don't forget to paste the lines up here "
     127                                          "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
    127128                       
    128129                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
  • protocols/Makefile

    r156bbd7 r21c87a7  
    1010
    1111# [SH] Program variables
    12 objects = nogaim.o
     12objects = account.o bee.o bee_ft.o bee_user.o nogaim.o
     13
    1314
    1415# [SH] The next two lines should contain the directory name (in $(subdirs))
  • protocols/jabber/Makefile

    r156bbd7 r21c87a7  
    1010
    1111# [SH] Program variables
    12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/iq.c

    r156bbd7 r21c87a7  
    9191                        pack = 0;
    9292                }
    93                 else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
    94                 {
    95                         const char *features[] = { XMLNS_DISCOVER,
     93                else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
     94                {
     95                        const char *features[] = { XMLNS_DISCO_INFO,
    9696                                                   XMLNS_VERSION,
    9797                                                   XMLNS_TIME,
     
    9999                                                   XMLNS_MUC,
    100100                                                   XMLNS_PING,
     101                                                   XMLNS_SI,
     102                                                   XMLNS_BYTESTREAMS,
     103                                                   XMLNS_FILETRANSFER,
    101104                                                   NULL };
    102105                        const char **f;
     
    118121                {
    119122                        xt_free_node( reply );
    120                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     123                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    121124                        pack = 0;
    122125                }
     
    124127        else if( strcmp( type, "set" ) == 0 )
    125128        {
    126                 if( !( c = xt_find_node( node->children, "query" ) ) ||
    127                     !( s = xt_find_attr( c, "xmlns" ) ) )
     129                if( ( c = xt_find_node( node->children, "si" ) ) &&
     130                    ( s = xt_find_attr( c, "xmlns" ) ) &&
     131                    ( strcmp( s, XMLNS_SI ) == 0 ) )
     132                {
     133                        return jabber_si_handle_request( ic, node, c );
     134                }
     135                else if( !( c = xt_find_node( node->children, "query" ) ) ||
     136                         !( s = xt_find_attr( c, "xmlns" ) ) )
    128137                {
    129138                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    130139                        return XT_HANDLED;
    131140                }
    132                
     141                else if( strcmp( s, XMLNS_ROSTER ) == 0 )
     142                {
    133143                /* This is a roster push. XMPP servers send this when someone
    134144                   was added to (or removed from) the buddy list. AFAIK they're
    135145                   sent even if we added this buddy in our own session. */
    136                 if( strcmp( s, XMLNS_ROSTER ) == 0 )
    137                 {
    138146                        int bare_len = strlen( ic->acc->user );
    139147                       
     
    152160                               
    153161                                xt_free_node( reply );
    154                                 reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
     162                                reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
    155163                                pack = 0;
    156164                        }
    157165                }
     166                else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 )
     167                {
     168                        /* Bytestream Request (stage 2 of file transfer) */
     169                        return jabber_bs_recv_request( ic, node, c );
     170                }
    158171                else
    159172                {
    160173                        xt_free_node( reply );
    161                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     174                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    162175                        pack = 0;
    163176                }
     
    379392                        if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
    380393                        {
    381                                 if( initial || imcb_find_buddy( ic, jid ) == NULL )
     394                                if( initial || bee_user_by_handle( ic->bee, ic, jid ) == NULL )
    382395                                        imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
    383396                                                                   group->text : NULL );
     
    577590            strcmp( s, "result" ) == 0 )
    578591        {
    579                 if( imcb_find_buddy( ic, jid ) == NULL )
     592                if( bee_user_by_handle( ic->bee, ic, jid ) == NULL )
    580593                        imcb_add_buddy( ic, jid, NULL );
    581594        }
     
    609622        return st;
    610623}
     624
     625xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     626
     627xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
     628{
     629        struct xt_node *node, *query;
     630        struct jabber_buddy *bud;
     631       
     632        if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
     633        {
     634                /* Who cares about the unknown... */
     635                imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
     636                return XT_HANDLED;
     637        }
     638       
     639        if( bud->features ) /* been here already */
     640                return XT_HANDLED;
     641       
     642        node = xt_new_node( "query", NULL, NULL );
     643        xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
     644       
     645        if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
     646        {
     647                imcb_log( ic, "WARNING: Couldn't generate feature query" );
     648                xt_free_node( node );
     649                return XT_HANDLED;
     650        }
     651
     652        jabber_cache_add( ic, query, jabber_iq_parse_features );
     653
     654        return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
     655}
     656
     657xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     658{
     659        struct xt_node *c;
     660        struct jabber_buddy *bud;
     661        char *feature, *xmlns, *from;
     662
     663        if( !( from = xt_find_attr( node, "from" ) ) ||
     664            !( c = xt_find_node( node->children, "query" ) ) ||
     665            !( xmlns = xt_find_attr( c, "xmlns" ) ) ||
     666            !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) )
     667        {
     668                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     669                return XT_HANDLED;
     670        }
     671        if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
     672        {
     673                /* Who cares about the unknown... */
     674                imcb_log( ic, "Couldn't find buddy: %s", from );
     675                return XT_HANDLED;
     676        }
     677       
     678        c = c->children;
     679        while( ( c = xt_find_node( c, "feature" ) ) )
     680        {
     681                feature = xt_find_attr( c, "var" );
     682                if( feature )
     683                        bud->features = g_slist_append( bud->features, g_strdup( feature ) );
     684                c = c->next;
     685        }
     686
     687        return XT_HANDLED;
     688}
     689
     690xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     691
     692xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
     693{
     694        struct xt_node *node, *query;
     695        struct jabber_data *jd = ic->proto_data;
     696       
     697        node = xt_new_node( "query", NULL, NULL );
     698        xt_add_attr( node, "xmlns", xmlns );
     699       
     700        if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
     701        {
     702                imcb_log( ic, "WARNING: Couldn't generate server query" );
     703                xt_free_node( node );
     704        }
     705
     706        jd->have_streamhosts--;
     707        jabber_cache_add( ic, query, jabber_iq_parse_server_features );
     708
     709        return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
     710}
     711
     712/*
     713 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
     714 */
     715xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     716{
     717        struct xt_node *c;
     718        struct jabber_data *jd = ic->proto_data;
     719        char *xmlns, *from;
     720
     721        if( !( c = xt_find_node( node->children, "query" ) ) ||
     722            !( from = xt_find_attr( node, "from" ) ) ||
     723            !( xmlns = xt_find_attr( c, "xmlns" ) ) )
     724        {
     725                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     726                return XT_HANDLED;
     727        }
     728
     729        jd->have_streamhosts++;
     730
     731        if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 )
     732        {
     733                char *itemjid;
     734
     735                /* answer from server */
     736       
     737                c = c->children;
     738                while( ( c = xt_find_node( c, "item" ) ) )
     739                {
     740                        itemjid = xt_find_attr( c, "jid" );
     741                       
     742                        if( itemjid )
     743                                jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
     744
     745                        c = c->next;
     746                }
     747        }
     748        else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 )
     749        {
     750                char *category, *type;
     751
     752                /* answer from potential proxy */
     753
     754                c = c->children;
     755                while( ( c = xt_find_node( c, "identity" ) ) )
     756                {
     757                        category = xt_find_attr( c, "category" );
     758                        type = xt_find_attr( c, "type" );
     759
     760                        if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
     761                            category && ( strcmp( category, "proxy" ) == 0 ) )
     762                                jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS );
     763
     764                        c = c->next;
     765                }
     766        }
     767        else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 )
     768        {
     769                char *host, *jid, *port_s;
     770                int port;
     771
     772                /* answer from proxy */
     773
     774                if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
     775                    ( host = xt_find_attr( c, "host" ) ) &&
     776                    ( port_s = xt_find_attr( c, "port" ) ) &&
     777                    ( sscanf( port_s, "%d", &port ) == 1 ) &&
     778                    ( jid = xt_find_attr( c, "jid" ) ) )
     779                {
     780                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     781                       
     782                        sh->jid = g_strdup( jid );
     783                        sh->host = g_strdup( host );
     784                        g_snprintf( sh->port, sizeof( sh->port ), "%u", port );
     785
     786                        imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
     787                        jd->streamhosts = g_slist_append( jd->streamhosts, sh );
     788                }
     789        }
     790
     791        if( jd->have_streamhosts == 0 )
     792                jd->have_streamhosts++;
     793
     794        return XT_HANDLED;
     795}
  • protocols/jabber/jabber.c

    r156bbd7 r21c87a7  
    6565       
    6666        s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
     67
     68        s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
    6769       
    6870        s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
     
    264266        struct jabber_data *jd = ic->proto_data;
    265267       
     268        while( jd->filetransfers )
     269                imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );
     270
     271        while( jd->streamhosts )
     272        {
     273                jabber_streamhost_t *sh = jd->streamhosts->data;
     274                jd->streamhosts = g_slist_remove( jd->streamhosts, sh );
     275                g_free( sh->jid );
     276                g_free( sh->host );
     277                g_free( sh );
     278        }
     279
    266280        if( jd->fd >= 0 )
    267281                jabber_end_stream( ic );
     
    544558        ret->send_typing = jabber_send_typing;
    545559        ret->handle_cmp = g_strcasecmp;
     560        ret->transfer_request = jabber_si_transfer_request;
    546561
    547562        register_protocol( ret );
  • protocols/jabber/jabber.h

    r156bbd7 r21c87a7  
    6161} jabber_buddy_flags_t;
    6262
     63/* Stores a streamhost's (a.k.a. proxy) data */
     64typedef struct
     65{
     66        char *jid;
     67        char *host;
     68        char port[6];
     69} jabber_streamhost_t;
     70
    6371typedef enum
    6472{
     
    9199        GHashTable *node_cache;
    92100        GHashTable *buddies;
     101
     102        GSList *filetransfers;
     103        GSList *streamhosts;
     104        int have_streamhosts;
    93105};
    94106
     
    127139        struct jabber_away_state *away_state;
    128140        char *away_message;
     141        GSList *features;
    129142       
    130143        time_t last_msg;
     
    140153        char *my_full_jid; /* Separate copy because of case sensitivity. */
    141154        struct jabber_buddy *me;
     155};
     156
     157struct jabber_transfer
     158{
     159        /* bitlbee's handle for this transfer */
     160        file_transfer_t *ft;
     161
     162        /* the stream's private handle */
     163        gpointer streamhandle;
     164
     165        /* timeout for discover queries */
     166        gint disco_timeout;
     167        gint disco_timeout_fired;
     168
     169        struct im_connection *ic;
     170
     171        struct jabber_buddy *bud;
     172
     173        int watch_in;
     174        int watch_out;
     175
     176        char *ini_jid;
     177        char *tgt_jid;
     178        char *iq_id;
     179        char *sid;
     180        int accepted;
     181
     182        size_t bytesread, byteswritten;
     183        int fd;
     184        struct sockaddr_storage saddr;
    142185};
    143186
     
    167210
    168211/* Some supported extensions/legacy stuff */
    169 #define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
    170 #define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
    171 #define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
    172 #define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
    173 #define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
    174 #define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
    175 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
    176 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
    177 #define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
    178 #define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
    179 #define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
     212#define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
     213#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
     214#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
     215#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
     216#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
     217#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
     218#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
     219#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
     220#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     221#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
     222#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
     223#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     224#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
     225#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
     226#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
     227#define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
     228#define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
     229#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    180230
    181231/* iq.c */
     
    187237int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    188238int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     239xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     240xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
     241
     242/* si.c */
     243int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
     244void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     245void jabber_si_free_transfer( file_transfer_t *ft);
     246
     247/* s5bytestream.c */
     248int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     249gboolean jabber_bs_send_start( struct jabber_transfer *tf );
     250gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    189251
    190252/* message.c */
     
    200262char *set_eval_tls( set_t *set, char *value );
    201263struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    202 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
     264struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
    203265void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    204266struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    r156bbd7 r21c87a7  
    9999}
    100100
    101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
     101struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
    102102{
    103103        struct xt_node *node, *c;
     
    111111        c = xt_new_node( "error", NULL, c );
    112112        xt_add_attr( c, "type", err_type );
     113       
     114        /* Add the error code, if present */
     115        if (err_code)
     116                xt_add_attr( c, "code", err_code );
    113117       
    114118        /* To make the actual error packet, we copy the original packet and
     
    275279        presence_send_request( bla->ic, bla->handle, "subscribed" );
    276280       
    277         if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
    278                 imcb_ask_add( bla->ic, bla->handle, NULL );
     281        imcb_ask_add( bla->ic, bla->handle, NULL );
    279282       
    280283        g_free( bla->handle );
     
    458461               
    459462                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
    460                     ( bare_exists || imcb_find_buddy( ic, jid ) ) )
     463                    ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) )
    461464                {
    462465                        *s = '/';
     
    479482                if( bud == NULL )
    480483                        /* No match. Create it now? */
    481                         return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ?
     484                        return ( ( flags & GET_BUDDY_CREAT ) &&
     485                                 bee_user_by_handle( ic->bee, ic, jid_ ) ) ?
    482486                                   jabber_buddy_add( ic, jid_ ) : NULL;
    483487                else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
  • protocols/msn/msn.c

    r156bbd7 r21c87a7  
    7878        if( md )
    7979        {
     80                /** Disabling MSN ft support for now.
     81                while( md->filetransfers ) {
     82                        imcb_file_canceled( md->filetransfers->data, "Closing connection" );
     83                }
     84                */
     85               
    8086                if( md->fd >= 0 )
    8187                        closesocket( md->fd );
     
    327333        ret->send_typing = msn_send_typing;
    328334        ret->handle_cmp = g_strcasecmp;
     335        //ret->transfer_request = msn_ftp_transfer_request;
    329336
    330337        register_protocol(ret);
  • protocols/msn/msn.h

    r156bbd7 r21c87a7  
    6969        int sb_failures;
    7070        time_t first_sb_failure;
     71        GSList *filetransfers;
    7172       
    7273        const struct msn_away_state *away_state;
     
    181182int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
    182183
     184/* invitation.c */
     185void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     186
    183187#endif //_MSN_H
  • protocols/msn/msn_util.c

    r156bbd7 r21c87a7  
    9696        msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname );
    9797       
    98         if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
    99                 imcb_ask_add( bla->ic, bla->handle, NULL );
     98        imcb_ask_add( bla->ic, bla->handle, NULL );
    10099       
    101100        g_free( bla->handle );
  • protocols/msn/sb.c

    r156bbd7 r21c87a7  
    2929#include "passport.h"
    3030#include "md5.h"
     31#include "invitation.h"
    3132
    3233static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
     
    168169               
    169170                /* Build the message. Convert LF to CR-LF for normal messages. */
    170                 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
     171                if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
     172                {
     173                        i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
     174                        buf = g_new0( char, i );
     175                        i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
     176                }
     177                else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )
     178                {
     179                        buf = g_strdup( text );
     180                        i = strlen( buf );
     181                }
     182                else
    171183                {
    172184                        buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
     
    181193                                buf[i++] = text[j];
    182194                        }
    183                 }
    184                 else
    185                 {
    186                         i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
    187                         buf = g_new0( char, i );
    188                         i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
    189195                }
    190196               
     
    685691                        }
    686692                }
     693#if 0
     694                // Disable MSN ft support for now.
    687695                else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
    688696                {
    689                         char *itype = msn_findheader( body, "Application-GUID:", blen );
    690                         char buf[1024];
     697                        char *command = msn_findheader( body, "Invitation-Command:", blen );
     698                        char *cookie = msn_findheader( body, "Invitation-Cookie:", blen );
     699                        unsigned int icookie;
    691700                       
    692701                        g_free( ct );
    693702                       
    694                         *buf = 0;
    695                        
    696                         if( !itype )
    697                                 return( 1 );
    698                        
    699                         /* File transfer. */
    700                         if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 )
    701                         {
    702                                 char *name = msn_findheader( body, "Application-File:", blen );
    703                                 char *size = msn_findheader( body, "Application-FileSize:", blen );
    704                                
    705                                 if( name && size )
    706                                 {
    707                                         g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n"
    708                                                     "Filetransfers are not supported by BitlBee for now...", name, size );
    709                                 }
    710                                 else
    711                                 {
    712                                         strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" );
    713                                 }
    714                                
    715                                 if( name ) g_free( name );
    716                                 if( size ) g_free( size );
    717                         }
    718                         else
    719                         {
    720                                 char *iname = msn_findheader( body, "Application-Name:", blen );
    721                                
    722                                 g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>",
    723                                                                 itype, iname ? iname : "no name" );
    724                                
    725                                 if( iname ) g_free( iname );
    726                         }
    727                        
    728                         g_free( itype );
    729                        
    730                         if( !*buf )
    731                                 return( 1 );
    732                        
    733                         if( sb->who )
    734                         {
    735                                 imcb_buddy_msg( ic, cmd[1], buf, 0, 0 );
    736                         }
    737                         else if( sb->chat )
    738                         {
    739                                 imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 );
    740                         }
    741                         else
    742                         {
    743                                 /* PANIC! */
    744                         }
     703                        /* Every invite should have both a Command and Cookie header */
     704                        if( !command || !cookie ) {
     705                                g_free( command );
     706                                g_free( cookie );
     707                                imcb_log( ic, "Warning: No command or cookie from %s", sb->who );
     708                                return 1;
     709                        }
     710                       
     711                        icookie = strtoul( cookie, NULL, 10 );
     712                        g_free( cookie );
     713                       
     714                        if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) {
     715                                msn_invitation_invite( sb, cmd[1], icookie, body, blen );
     716                        } else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) {
     717                                msn_invitation_accept( sb, cmd[1], icookie, body, blen );
     718                        } else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) {
     719                                msn_invitation_cancel( sb, cmd[1], icookie, body, blen );
     720                        } else {
     721                                imcb_log( ic, "Warning: Received invalid invitation with "
     722                                                "command %s from %s", command, sb->who );
     723                        }
     724                       
     725                        g_free( command );
     726                }
     727#endif
     728                else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 )
     729                {
     730                        imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not "
     731                                        "support msnmsgrp2p yet.", sb->who );
     732                        g_free( ct );
    745733                }
    746734                else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
  • protocols/nogaim.c

    r156bbd7 r21c87a7  
    3838#include "chat.h"
    3939
    40 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
    41 static char *format_timestamp( irc_t *irc, time_t msg_ts );
    42 
    4340GSList *connections;
    4441
     
    9289}
    9390#endif
    94 
    95 /* nogaim.c */
    9691
    9792GList *protocols = NULL;
     
    126121}
    127122
    128 /* nogaim.c */
    129123void nogaim_init()
    130124{
     
    162156GSList *get_connections() { return connections; }
    163157
    164 /* multi.c */
    165 
    166158struct im_connection *imcb_new( account_t *acc )
    167159{
     
    170162        ic = g_new0( struct im_connection, 1 );
    171163       
    172         ic->irc = acc->irc;
     164        ic->bee = acc->bee;
    173165        ic->acc = acc;
    174166        acc->ic = ic;
     
    184176       
    185177        /* Destroy the pointer to this connection from the account list */
    186         for( a = ic->irc->accounts; a; a = a->next )
     178        for( a = ic->bee->accounts; a; a = a->next )
    187179                if( a->ic == ic )
    188180                {
     
    205197        va_end( params );
    206198
    207         if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
    208             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     199        if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
     200            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
    209201                strip_html( text );
    210202       
    211203        /* Try to find a different connection on the same protocol. */
    212         for( a = ic->irc->accounts; a; a = a->next )
     204        for( a = ic->bee->accounts; a; a = a->next )
    213205                if( a->prpl == ic->acc->prpl && a->ic != ic )
    214206                        break;
     
    216208        /* If we found one, include the screenname in the message. */
    217209        if( a )
    218                 irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
     210                /* FIXME(wilmer): ui_log callback or so */
     211                irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
    219212        else
    220                 irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text );
     213                irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text );
    221214       
    222215        g_free( text );
     
    269262void imcb_connected( struct im_connection *ic )
    270263{
    271         irc_t *irc = ic->irc;
    272         struct chat *c;
    273         user_t *u;
    274        
    275264        /* MSN servers sometimes redirect you to a different server and do
    276265           the whole login sequence again, so these "late" calls to this
     
    279268                return;
    280269       
    281         u = user_find( ic->irc, ic->irc->nick );
    282        
    283270        imcb_log( ic, "Logged in" );
    284271       
     
    293280        ic->acc->auto_reconnect_delay = 0;
    294281       
     282        /*
    295283        for( c = irc->chatrooms; c; c = c->next )
    296284        {
     
    301289                        chat_join( irc, c, NULL );
    302290        }
     291        */
    303292}
    304293
     
    308297       
    309298        a->reconnect = 0;
    310         account_on( a->irc, a );
     299        account_on( a->bee, a );
    311300       
    312301        return( FALSE );        /* Only have to run the timeout once */
     
    321310void imc_logout( struct im_connection *ic, int allow_reconnect )
    322311{
    323         irc_t *irc = ic->irc;
    324         user_t *t, *u;
     312        bee_t *bee = ic->bee;
    325313        account_t *a;
     314        GSList *l;
    326315        int delay;
    327316       
     
    343332        ic->away = NULL;
    344333       
    345         u = irc->users;
    346         while( u )
    347         {
    348                 if( u->ic == ic )
    349                 {
    350                         t = u->next;
    351                         user_del( irc, u->nick );
    352                         u = t;
    353                 }
    354                 else
    355                         u = u->next;
    356         }
    357        
    358         query_del_by_conn( ic->irc, ic );
    359        
    360         for( a = irc->accounts; a; a = a->next )
     334        for( l = bee->users; l; )
     335        {
     336                bee_user_t *bu = l->data;
     337                GSList *next = l->next;
     338               
     339                if( bu->ic == ic )
     340                        bee_user_free( bee, bu );
     341               
     342                l = next;
     343        }
     344       
     345        //query_del_by_conn( ic->irc, ic );
     346       
     347        for( a = bee->accounts; a; a = a->next )
    361348                if( a->ic == ic )
    362349                        break;
     
    366353                /* Uhm... This is very sick. */
    367354        }
    368         else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) &&
     355        else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) &&
    369356                 set_getbool( &a->set, "auto_reconnect" ) &&
    370357                 ( delay = account_reconnect_delay( a ) ) > 0 )
     
    377364}
    378365
    379 
    380 /* dialogs.c */
    381 
    382366void imcb_ask( struct im_connection *ic, char *msg, void *data,
    383367               query_callback doit, query_callback dont )
    384368{
    385         query_add( ic->irc, ic, msg, doit, dont, data );
    386 }
    387 
    388 
    389 /* list.c */
     369        query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data );
     370}
    390371
    391372void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
    392373{
    393         user_t *u;
    394         char nick[MAX_NICK_LENGTH+1], *s;
    395         irc_t *irc = ic->irc;
    396        
    397         if( user_findhandle( ic, handle ) )
    398         {
    399                 if( set_getbool( &irc->set, "debug" ) )
     374        bee_user_t *bu;
     375        bee_t *bee = ic->bee;
     376       
     377        if( bee_user_by_handle( bee, ic, handle ) )
     378        {
     379                if( set_getbool( &bee->set, "debug" ) )
    400380                        imcb_log( ic, "User already exists, ignoring add request: %s", handle );
    401381               
     
    408388        }
    409389       
    410         memset( nick, 0, MAX_NICK_LENGTH + 1 );
    411         strcpy( nick, nick_get( ic->acc, handle ) );
    412        
    413         u = user_add( ic->irc, nick );
    414        
    415 //      if( !realname || !*realname ) realname = nick;
    416 //      u->realname = g_strdup( realname );
    417        
    418         if( ( s = strchr( handle, '@' ) ) )
    419         {
    420                 u->host = g_strdup( s + 1 );
    421                 u->user = g_strndup( handle, s - handle );
    422         }
    423         else if( ic->acc->server )
    424         {
    425                 u->host = g_strdup( ic->acc->server );
    426                 u->user = g_strdup( handle );
    427                
    428                 /* s/ /_/ ... important for AOL screennames */
    429                 for( s = u->user; *s; s ++ )
    430                         if( *s == ' ' )
    431                                 *s = '_';
    432         }
    433         else
    434         {
    435                 u->host = g_strdup( ic->acc->prpl->name );
    436                 u->user = g_strdup( handle );
    437         }
    438        
    439         u->ic = ic;
    440         u->handle = g_strdup( handle );
    441         if( group ) u->group = g_strdup( group );
    442         u->send_handler = buddy_send_handler;
    443         u->last_typing_notice = 0;
    444 }
    445 
    446 struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )
    447 {
    448         static struct buddy b[1];
    449         user_t *u;
    450        
    451         u = user_findhandle( ic, handle );
    452        
    453         if( !u )
    454                 return( NULL );
    455        
    456         memset( b, 0, sizeof( b ) );
    457         strncpy( b->name, handle, 80 );
    458         strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN );
    459         b->present = u->online;
    460         b->ic = u->ic;
    461        
    462         return( b );
    463 }
    464 
    465 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
    466 {
    467         user_t *u = user_findhandle( ic, handle );
    468         char *set;
    469        
    470         if( !u || !realname ) return;
    471        
    472         if( g_strcasecmp( u->realname, realname ) != 0 )
    473         {
    474                 if( u->realname != u->nick ) g_free( u->realname );
    475                
    476                 u->realname = g_strdup( realname );
    477                
    478                 if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )
    479                         imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
    480         }
    481        
    482         set = set_getstr( &ic->acc->set, "nick_source" );
    483         if( strcmp( set, "handle" ) != 0 )
    484         {
    485                 char *name = g_strdup( realname );
    486                
    487                 if( strcmp( set, "first_name" ) == 0 )
    488                 {
    489                         int i;
    490                         for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
    491                         name[i] = '\0';
    492                 }
    493                
    494                 imcb_buddy_nick_hint( ic, handle, name );
    495                
    496                 g_free( name );
     390        bu = bee_user_new( bee, ic, handle );
     391        bu->group = g_strdup( group );
     392}
     393
     394void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname )
     395{
     396        bee_t *bee = ic->bee;
     397        bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
     398       
     399        if( !bu || !fullname ) return;
     400       
     401        if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 )
     402        {
     403                g_free( bu->fullname );
     404                bu->fullname = g_strdup( fullname );
     405               
     406                if( bee->ui->user_fullname )
     407                        bee->ui->user_fullname( bee, bu );
    497408        }
    498409}
     
    500411void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
    501412{
    502         user_t *u;
    503        
    504         if( ( u = user_findhandle( ic, handle ) ) )
    505                 user_del( ic->irc, u->nick );
     413        bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) );
    506414}
    507415
     
    510418void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
    511419{
     420#if 0
    512421        user_t *u = user_findhandle( ic, handle );
    513422        char newnick[MAX_NICK_LENGTH+1], *orig_nick;
     
    524433                /* Some processing to make sure this string is a valid IRC nickname. */
    525434                nick_strip( newnick );
    526                 if( set_getbool( &ic->irc->set, "lcnicks" ) )
     435                if( set_getbool( &ic->bee->set, "lcnicks" ) )
    527436                        nick_lc( newnick );
    528437               
     
    541450                }
    542451        }
     452#endif
    543453}
    544454
     
    585495        data->ic = ic;
    586496        data->handle = g_strdup( handle );
    587         query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
     497        query_add( (irc_t *) ic->bee->ui_data, ic, s,
     498                   imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
    588499}
    589500
     
    610521       
    611522        /* TODO: Make a setting for this! */
    612         if( user_findhandle( ic, handle ) != NULL )
     523        if( bee_user_by_handle( ic->bee, ic, handle ) != NULL )
    613524                return;
    614525       
     
    617528        data->ic = ic;
    618529        data->handle = g_strdup( handle );
    619         query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
    620 }
    621 
    622 
    623 /* server.c */                   
    624 
    625 void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message )
    626 {
    627         user_t *u;
    628         int oa, oo;
    629        
    630         u = user_findhandle( ic, (char*) handle );
    631        
    632         if( !u )
    633         {
    634                 if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 )
    635                 {
    636                         imcb_add_buddy( ic, (char*) handle, NULL );
    637                         u = user_findhandle( ic, (char*) handle );
    638                 }
    639                 else
    640                 {
    641                         if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 )
    642                         {
    643                                 imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle );
    644                                 imcb_log( ic, "flags = %d, state = %s, message = %s", flags,
    645                                           state ? state : "NULL", message ? message : "NULL" );
    646                         }
    647                        
    648                         return;
    649                 }
    650         }
    651        
    652         oa = u->away != NULL;
    653         oo = u->online;
    654        
    655         g_free( u->away );
    656         g_free( u->status_msg );
    657         u->away = u->status_msg = NULL;
    658        
    659         if( ( flags & OPT_LOGGED_IN ) && !u->online )
    660         {
    661                 irc_spawn( ic->irc, u );
    662                 u->online = 1;
    663         }
    664         else if( !( flags & OPT_LOGGED_IN ) && u->online )
    665         {
    666                 struct groupchat *c;
    667                
    668                 irc_kill( ic->irc, u );
    669                 u->online = 0;
    670                
    671                 /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
    672                 for( c = ic->groupchats; c; c = c->next )
    673                         remove_chat_buddy_silent( c, handle );
    674         }
    675        
    676         if( flags & OPT_AWAY )
    677         {
    678                 if( state && message )
    679                 {
    680                         u->away = g_strdup_printf( "%s (%s)", state, message );
    681                 }
    682                 else if( state )
    683                 {
    684                         u->away = g_strdup( state );
    685                 }
    686                 else if( message )
    687                 {
    688                         u->away = g_strdup( message );
    689                 }
    690                 else
    691                 {
    692                         u->away = g_strdup( "Away" );
    693                 }
    694         }
    695         else
    696         {
    697                 u->status_msg = g_strdup( message );
    698         }
    699        
    700         /* LISPy... */
    701         if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&         /* Don't do a thing when user doesn't want it */
    702             ( u->online ) &&                                            /* Don't touch offline people */
    703             ( ( ( u->online != oo ) && !u->away ) ||                    /* Voice joining people */
    704               ( ( u->online == oo ) && ( oa == !u->away ) ) ) )         /* (De)voice people changing state */
    705         {
    706                 char *from;
    707                
    708                 if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
    709                 {
    710                         from = g_strdup( ic->irc->myhost );
    711                 }
    712                 else
    713                 {
    714                         from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
    715                                                             ic->irc->myhost );
    716                 }
    717                 irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
    718                                                           u->away?'-':'+', u->nick );
    719                 g_free( from );
    720         }
    721 }
    722 
    723 void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
    724 {
    725         irc_t *irc = ic->irc;
    726         char *wrapped, *ts = NULL;
    727         user_t *u;
    728        
    729         u = user_findhandle( ic, handle );
    730        
    731         if( !u )
    732         {
    733                 char *h = set_getstr( &irc->set, "handle_unknown" );
    734                
    735                 if( g_strcasecmp( h, "ignore" ) == 0 )
    736                 {
    737                         if( set_getbool( &irc->set, "debug" ) )
    738                                 imcb_log( ic, "Ignoring message from unknown handle %s", handle );
    739                        
    740                         return;
    741                 }
    742                 else if( g_strncasecmp( h, "add", 3 ) == 0 )
    743                 {
    744                         int private = set_getbool( &irc->set, "private" );
    745                        
    746                         if( h[3] )
    747                         {
    748                                 if( g_strcasecmp( h + 3, "_private" ) == 0 )
    749                                         private = 1;
    750                                 else if( g_strcasecmp( h + 3, "_channel" ) == 0 )
    751                                         private = 0;
    752                         }
    753                        
    754                         imcb_add_buddy( ic, handle, NULL );
    755                         u = user_findhandle( ic, handle );
    756                         u->is_private = private;
    757                 }
    758                 else
    759                 {
    760                         imcb_log( ic, "Message from unknown handle %s:", handle );
    761                         u = user_find( irc, irc->mynick );
    762                 }
    763         }
    764        
    765         if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
    766             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
    767                 strip_html( msg );
    768        
    769         if( set_getbool( &ic->irc->set, "display_timestamps" ) &&
    770             ( ts = format_timestamp( irc, sent_at ) ) )
    771         {
    772                 char *new = g_strconcat( ts, msg, NULL );
    773                 g_free( ts );
    774                 ts = msg = new;
    775         }
    776        
    777         wrapped = word_wrap( msg, 425 );
    778         irc_msgfrom( irc, u->nick, wrapped );
    779         g_free( wrapped );
    780         g_free( ts );
    781 }
    782 
    783 void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags )
    784 {
    785         user_t *u;
    786        
    787         if( !set_getbool( &ic->irc->set, "typing_notice" ) )
    788                 return;
    789        
    790         if( ( u = user_findhandle( ic, handle ) ) )
    791         {
    792                 char buf[256];
    793                
    794                 g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 );
    795                 irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf );
    796         }
     530        query_add( (irc_t *) ic->bee->ui_data, ic, s,
     531                   imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
     532}
     533
     534struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle )
     535{
     536        return bee_user_by_handle( ic->bee, ic, handle );
    797537}
    798538
    799539struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
    800540{
     541#if 0
    801542        struct groupchat *c;
    802543       
     
    816557        c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
    817558       
    818         if( set_getbool( &ic->irc->set, "debug" ) )
     559        if( set_getbool( &ic->bee->set, "debug" ) )
    819560                imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle );
    820561       
    821562        return c;
     563#endif
     564        return NULL;
    822565}
    823566
    824567void imcb_chat_name_hint( struct groupchat *c, const char *name )
    825568{
     569#if 0
    826570        if( !c->joined )
    827571        {
     
    849593                }
    850594        }
     595#endif
    851596}
    852597
    853598void imcb_chat_free( struct groupchat *c )
    854599{
     600#if 0
    855601        struct im_connection *ic = c->ic;
    856602        struct groupchat *l;
    857603        GList *ir;
    858604       
    859         if( set_getbool( &ic->irc->set, "debug" ) )
     605        if( set_getbool( &ic->bee->set, "debug" ) )
    860606                imcb_log( ic, "You were removed from conversation %p", c );
    861607       
     
    890636                g_free( c );
    891637        }
     638#endif
    892639}
    893640
    894641void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
    895642{
     643#if 0
    896644        struct im_connection *ic = c->ic;
    897645        char *wrapped;
     
    904652        u = user_findhandle( ic, who );
    905653       
    906         if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
    907             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     654        if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
     655            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
    908656                strip_html( msg );
    909657       
     
    922670        }
    923671        g_free( wrapped );
     672#endif
    924673}
    925674
    926675void imcb_chat_log( struct groupchat *c, char *format, ... )
    927676{
     677#if 0
    928678        irc_t *irc = c->ic->irc;
    929679        va_list params;
     
    940690       
    941691        g_free( text );
     692#endif
    942693}
    943694
    944695void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at )
    945696{
     697#if 0
    946698        struct im_connection *ic = c->ic;
    947699        user_t *u = NULL;
     
    954706                u = user_findhandle( ic, who );
    955707       
    956         if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
    957             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     708        if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
     709            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
    958710                strip_html( topic );
    959711       
     
    963715        if( c->joined && u )
    964716                irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic );
    965 }
    966 
    967 
    968 /* buddy_chat.c */
     717#endif
     718}
    969719
    970720void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
    971721{
     722#if 0
    972723        user_t *u = user_findhandle( b->ic, handle );
    973724        int me = 0;
    974725       
    975         if( set_getbool( &b->ic->irc->set, "debug" ) )
     726        if( set_getbool( &b->ic->bee->set, "debug" ) )
    976727                imcb_log( b->ic, "User %s added to conversation %p", handle, b );
    977728       
     
    1000751                b->in_room = g_list_append( b->in_room, g_strdup( handle ) );
    1001752        }
     753#endif
    1002754}
    1003755
     
    1005757void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
    1006758{
     759#if 0
    1007760        user_t *u;
    1008761        int me = 0;
    1009762       
    1010         if( set_getbool( &b->ic->irc->set, "debug" ) )
     763        if( set_getbool( &b->ic->bee->set, "debug" ) )
    1011764                imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" );
    1012765       
     
    1028781        if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
    1029782                irc_part( b->ic->irc, u, b->channel );
    1030 }
    1031 
     783#endif
     784}
     785
     786#if 0
    1032787static int remove_chat_buddy_silent( struct groupchat *b, const char *handle )
    1033788{
     
    1048803        }
    1049804       
    1050         return( 0 );
    1051 }
     805        return 0;
     806}
     807#endif
    1052808
    1053809
    1054810/* Misc. BitlBee stuff which shouldn't really be here */
    1055 
     811#if 0
    1056812char *set_eval_away_devoice( set_t *set, char *value )
    1057813{
     
    1066822        /* Horror.... */
    1067823       
    1068         if( st != set_getbool( &irc->set, "away_devoice" ) )
     824        if( st != set_getbool( &irc->b->set, "away_devoice" ) )
    1069825        {
    1070826                char list[80] = "";
     
    1108864        return value;
    1109865}
    1110 
    1111 char *set_eval_timezone( set_t *set, char *value )
    1112 {
    1113         char *s;
    1114        
    1115         if( strcmp( value, "local" ) == 0 ||
    1116             strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
    1117                 return value;
    1118        
    1119         /* Otherwise: +/- at the beginning optional, then one or more numbers,
    1120            possibly followed by a colon and more numbers. Don't bother bound-
    1121            checking them since users are free to shoot themselves in the foot. */
    1122         s = value;
    1123         if( *s == '+' || *s == '-' )
    1124                 s ++;
    1125        
    1126         /* \d+ */
    1127         if( !isdigit( *s ) )
    1128                 return SET_INVALID;
    1129         while( *s && isdigit( *s ) ) s ++;
    1130        
    1131         /* EOS? */
    1132         if( *s == '\0' )
    1133                 return value;
    1134        
    1135         /* Otherwise, colon */
    1136         if( *s != ':' )
    1137                 return SET_INVALID;
    1138         s ++;
    1139        
    1140         /* \d+ */
    1141         if( !isdigit( *s ) )
    1142                 return SET_INVALID;
    1143         while( *s && isdigit( *s ) ) s ++;
    1144        
    1145         /* EOS */
    1146         return *s == '\0' ? value : SET_INVALID;
    1147 }
    1148 
    1149 static char *format_timestamp( irc_t *irc, time_t msg_ts )
    1150 {
    1151         time_t now_ts = time( NULL );
    1152         struct tm now, msg;
    1153         char *set;
    1154        
    1155         /* If the timestamp is <= 0 or less than a minute ago, discard it as
    1156            it doesn't seem to add to much useful info and/or might be noise. */
    1157         if( msg_ts <= 0 || msg_ts > now_ts - 60 )
    1158                 return NULL;
    1159        
    1160         set = set_getstr( &irc->set, "timezone" );
    1161         if( strcmp( set, "local" ) == 0 )
    1162         {
    1163                 localtime_r( &now_ts, &now );
    1164                 localtime_r( &msg_ts, &msg );
    1165         }
    1166         else
    1167         {
    1168                 int hr, min = 0, sign = 60;
    1169                
    1170                 if( set[0] == '-' )
    1171                 {
    1172                         sign *= -1;
    1173                         set ++;
    1174                 }
    1175                 else if( set[0] == '+' )
    1176                 {
    1177                         set ++;
    1178                 }
    1179                
    1180                 if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
    1181                 {
    1182                         msg_ts += sign * ( hr * 60 + min );
    1183                         now_ts += sign * ( hr * 60 + min );
    1184                 }
    1185                
    1186                 gmtime_r( &now_ts, &now );
    1187                 gmtime_r( &msg_ts, &msg );
    1188         }
    1189        
    1190         if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
    1191                 return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
    1192                                         msg.tm_hour, msg.tm_min, msg.tm_sec );
    1193         else
    1194                 return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
    1195                                         "%02d:%02d:%02d\x02]\x02 ",
    1196                                         msg.tm_year + 1900, msg.tm_mon, msg.tm_mday,
    1197                                         msg.tm_hour, msg.tm_min, msg.tm_sec );
    1198 }
     866#endif
    1199867
    1200868/* The plan is to not allow straight calls to prpl functions anymore, but do
    1201869   them all from some wrappers. We'll start to define some down here: */
    1202 
    1203 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags )
    1204 {
    1205         char *buf = NULL;
    1206         int st;
    1207        
    1208         if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
    1209         {
    1210                 buf = escape_html( msg );
    1211                 msg = buf;
    1212         }
    1213        
    1214         st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );
    1215         g_free( buf );
    1216        
    1217         return st;
    1218 }
    1219870
    1220871int imc_chat_msg( struct groupchat *c, char *msg, int flags )
     
    1245896       
    1246897        away = set_getstr( &ic->acc->set, "away" ) ?
    1247              : set_getstr( &ic->irc->set, "away" );
     898             : set_getstr( &ic->bee->set, "away" );
    1248899        if( away && *away )
    1249900        {
     
    1256907                away = NULL;
    1257908                msg = set_getstr( &ic->acc->set, "status" ) ?
    1258                     : set_getstr( &ic->irc->set, "status" );
     909                    : set_getstr( &ic->bee->set, "status" );
    1259910        }
    1260911       
  • protocols/nogaim.h

    r156bbd7 r21c87a7  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    4545#include "proxy.h"
    4646#include "query.h"
     47#include "md5.h"
     48#include "ft.h"
    4749
    4850#define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */
     
    8587       
    8688        /* BitlBee */
    87         irc_t *irc;
     89        bee_t *bee;
    8890       
    8991        struct groupchat *groupchats;
     
    228230        void (* auth_allow)     (struct im_connection *, const char *who);
    229231        void (* auth_deny)      (struct im_connection *, const char *who);
     232
     233        /* Incoming transfer request */
     234        void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    230235};
    231236
     
    281286G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
    282287
    283 /* Buddy activity */
    284 /* To manipulate the status of a handle.
    285  * - flags can be |='d with OPT_* constants. You will need at least:
    286  *   OPT_LOGGED_IN and OPT_AWAY.
    287  * - 'state' and 'message' can be NULL */
    288 G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );
    289 /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
    290 /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
    291 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
    292288G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
     289G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle );
    293290G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
    294291
     
    316313/* Actions, or whatever. */
    317314int imc_away_send_update( struct im_connection *ic );
    318 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );
    319315int imc_chat_msg( struct groupchat *c, char *msg, int flags );
    320316
     
    325321
    326322/* Misc. stuff */
    327 char *set_eval_timezone( set_t *set, char *value );
    328323char *set_eval_away_devoice( set_t *set, char *value );
    329324gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
  • protocols/oscar/oscar.c

    r156bbd7 r21c87a7  
    11901190        aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
    11911191        // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
    1192         if(imcb_find_buddy(data->ic, uin) == NULL)
    1193                 imcb_ask_add(data->ic, uin, NULL);
     1192        imcb_ask_add(data->ic, uin, NULL);
    11941193       
    11951194        g_free(uin);
     
    19521951        struct oscar_data *odata = (struct oscar_data *)g->proto_data;
    19531952        if (odata->icq) {
     1953                /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back?
    19541954                struct buddy *budlight = imcb_find_buddy(g, who);
    19551955                if (budlight)
     
    19571957                                if (budlight->caps & AIM_CAPS_ICQSERVERRELAY)
    19581958                                        aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7);
     1959                */
    19591960        } else
    19601961                aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE);
     
    20942095                switch (curitem->type) {
    20952096                        case 0x0000: /* Buddy */
    2096                                 if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) {
     2097                                if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) {
    20972098                                        char *realname = NULL;
    20982099
  • protocols/twitter/twitter_lib.c

    r156bbd7 r21c87a7  
    103103
    104104        // Check if the buddy is allready in the buddy list.
    105         if (!imcb_find_buddy( ic, name ))
     105        if (!bee_user_by_handle( ic->bee, ic, name ))
    106106        {
    107107                // The buddy is not in the list, add the buddy and set the status to logged in.
  • query.c

    r156bbd7 r21c87a7  
    6464        }
    6565       
    66         if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )
     66        if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )
    6767                query_display( irc, q );
    6868       
     
    179179        query_t *q;
    180180       
    181         if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 )
     181        if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "fifo" ) == 0 )
    182182                q = irc->queries;
    183183        else
  • root_commands.c

    r156bbd7 r21c87a7  
    2626#define BITLBEE_CORE
    2727#include "commands.h"
    28 #include "crypting.h"
    2928#include "bitlbee.h"
    3029#include "help.h"
     
    3332#include <string.h>
    3433
    35 void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
    36 {
    37         char *cmd[IRC_MAX_ARGS];
    38         char *s;
    39         int k;
    40         char q = 0;
    41        
    42         memset( cmd, 0, sizeof( cmd ) );
    43         cmd[0] = command;
    44         k = 1;
    45         for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ )
    46                 if( *s == ' ' && !q )
    47                 {
    48                         *s = 0;
    49                         while( *++s == ' ' );
    50                         if( *s == '"' || *s == '\'' )
    51                         {
    52                                 q = *s;
    53                                 s ++;
    54                         }
    55                         if( *s )
    56                         {
    57                                 cmd[k++] = s;
    58                                 s --;
    59                         }
    60                         else
    61                         {
    62                                 break;
    63                         }
    64                 }
    65                 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
    66                 {
    67                         char *cpy;
    68                        
    69                         for( cpy = s; *cpy; cpy ++ )
    70                                 cpy[0] = cpy[1];
    71                 }
    72                 else if( *s == q )
    73                 {
    74                         q = *s = 0;
    75                 }
    76         cmd[k] = NULL;
    77        
    78         root_command( irc, cmd );
     34void root_command_string( irc_t *irc, char *command )
     35{
     36        root_command( irc, split_command_parts( command ) );
    7937}
    8038
     
    9351void root_command( irc_t *irc, char *cmd[] )
    9452{       
    95         int i;
     53        int i, len;
    9654       
    9755        if( !cmd[0] )
    9856                return;
    9957       
     58        len = strlen( cmd[0] );
    10059        for( i = 0; commands[i].command; i++ )
    101                 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
    102                 {
     60                if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 )
     61                {
     62                        if( commands[i+1].command &&
     63                            g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 )
     64                                /* Only match on the first letters if the match is unique. */
     65                                break;
     66                       
    10367                        MIN_ARGS( commands[i].required_parameters );
    10468                       
     
    162126                irc->status |= USTATUS_IDENTIFIED;
    163127                irc_umode_set( irc, "+R", 1 );
    164                 if( set_getbool( &irc->set, "auto_connect" ) )
     128                if( set_getbool( &irc->b->set, "auto_connect" ) )
    165129                        cmd_account( irc, account_on );
    166130                break;
     
    202166        storage_status_t status;
    203167       
    204         status = storage_remove (irc->nick, cmd[1]);
     168        status = storage_remove (irc->user->nick, cmd[1]);
    205169        switch (status) {
    206170        case STORAGE_NO_SUCH_USER:
     
    214178                irc->status &= ~USTATUS_IDENTIFIED;
    215179                irc_umode_set( irc, "-R", 1 );
    216                 irc_usermsg( irc, "Account `%s' removed", irc->nick );
     180                irc_usermsg( irc, "Account `%s' removed", irc->user->nick );
    217181                break;
    218182        default:
     
    222186}
    223187
     188static void cmd_save( irc_t *irc, char **cmd )
     189{
     190        if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
     191                irc_usermsg( irc, "Please create an account first" );
     192        else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
     193                irc_usermsg( irc, "Configuration saved" );
     194        else
     195                irc_usermsg( irc, "Configuration could not be saved!" );
     196}
     197
    224198struct cmd_account_del_data
    225199{
     
    233207        account_t *a;
    234208       
    235         for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
     209        for( a = cad->irc->b->accounts; a && a != cad->a; a = a->next );
    236210       
    237211        if( a == NULL )
     
    245219        else
    246220        {
    247                 account_del( cad->irc, a );
     221                account_del( cad->irc->b, a );
    248222                irc_usermsg( cad->irc, "Account deleted" );
    249223        }
     
    286260                set_name = set_full;
    287261               
    288                 head = &irc->set;
     262                head = &irc->b->set;
    289263        }
    290264        else
     
    357331        account_t *a;
    358332       
    359         if( ( a = account_get( irc, id ) ) )
     333        if( ( a = account_get( irc->b, id ) ) )
    360334                return &a->set;
    361335        else
     
    405379                }
    406380
    407                 a = account_add( irc, prpl, cmd[3], cmd[4] );
     381                a = account_add( irc->b, prpl, cmd[3], cmd[4] );
    408382                if( cmd[5] )
    409383                {
     
    419393                MIN_ARGS( 2 );
    420394
    421                 if( !( a = account_get( irc, cmd[2] ) ) )
     395                if( !( a = account_get( irc->b, cmd[2] ) ) )
    422396                {
    423397                        irc_usermsg( irc, "Invalid account" );
     
    441415                                               "set' command. Are you sure you want to delete this "
    442416                                               "account?", a->prpl->name, a->user );
    443                         query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
     417                        //query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
    444418                        g_free( msg );
    445419                }
     
    452426                        irc_usermsg( irc, "Account list:" );
    453427               
    454                 for( a = irc->accounts; a; a = a->next )
     428                for( a = irc->b->accounts; a; a = a->next )
    455429                {
    456430                        char *con;
     
    475449                if( cmd[2] )
    476450                {
    477                         if( ( a = account_get( irc, cmd[2] ) ) )
     451                        if( ( a = account_get( irc->b, cmd[2] ) ) )
    478452                        {
    479453                                if( a->ic )
     
    484458                                else
    485459                                {
    486                                         account_on( irc, a );
     460                                        account_on( irc->b, a );
    487461                                }
    488462                        }
     
    495469                else
    496470                {
    497                         if ( irc->accounts ) {
     471                        if ( irc->b->accounts )
     472                        {
    498473                                irc_usermsg( irc, "Trying to get all accounts connected..." );
    499474                       
    500                                 for( a = irc->accounts; a; a = a->next )
     475                                for( a = irc->b->accounts; a; a = a->next )
    501476                                        if( !a->ic && a->auto_connect )
    502                                                 account_on( irc, a );
     477                                                account_on( irc->b, a );
    503478                        }
    504479                        else
     
    514489                        irc_usermsg( irc, "Deactivating all active (re)connections..." );
    515490                       
    516                         for( a = irc->accounts; a; a = a->next )
     491                        for( a = irc->b->accounts; a; a = a->next )
    517492                        {
    518493                                if( a->ic )
    519                                         account_off( irc, a );
     494                                        account_off( irc->b, a );
    520495                                else if( a->reconnect )
    521496                                        cancel_auto_reconnect( a );
    522497                        }
    523498                }
    524                 else if( ( a = account_get( irc, cmd[2] ) ) )
     499                else if( ( a = account_get( irc->b, cmd[2] ) ) )
    525500                {
    526501                        if( a->ic )
    527502                        {
    528                                 account_off( irc, a );
     503                                account_off( irc->b, a );
    529504                        }
    530505                        else if( a->reconnect )
     
    569544        }
    570545       
    571         if( !( a = account_get( irc, cmd[1] ) ) )
     546        if( !( a = account_get( irc->b, cmd[1] ) ) )
    572547        {
    573548                irc_usermsg( irc, "Invalid account" );
     
    587562                        return;
    588563                }
    589                 else if( user_find( irc, cmd[3] ) )
     564                else if( irc_user_by_name( irc, cmd[3] ) )
    590565                {
    591566                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
     
    601576                a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
    602577        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 );
     578                /* Only for add -tmp. For regular adds, this callback will
     579                   be called once the IM server confirms. */
     580                bee_user_new( irc->b, a->ic, cmd[2] );
    607581       
    608582        irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
     583}
     584
     585static void cmd_remove( irc_t *irc, char **cmd )
     586{
     587        irc_user_t *iu;
     588        bee_user_t *bu;
     589        char *s;
     590       
     591        if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) )
     592        {
     593                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
     594                return;
     595        }
     596        s = g_strdup( bu->handle );
     597       
     598        bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL );
     599        nick_del( bu->ic->acc, bu->handle );
     600        //TODO(wilmer): bee_user_free() and/or let the IM mod do it? irc_user_free( irc, cmd[1] );
     601       
     602        irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
     603        g_free( s );
     604       
     605        return;
    609606}
    610607
     
    616613        if( !cmd[2] )
    617614        {
    618                 user_t *u = user_find( irc, cmd[1] );
    619                 if( !u || !u->ic )
     615                irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
     616                if( !iu || !iu->bu )
    620617                {
    621618                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    622619                        return;
    623620                }
    624                 ic = u->ic;
    625                 cmd[2] = u->handle;
    626         }
    627         else if( !( a = account_get( irc, cmd[1] ) ) )
     621                ic = iu->bu->ic;
     622                cmd[2] = iu->bu->handle;
     623        }
     624        else if( !( a = account_get( irc->b, cmd[1] ) ) )
    628625        {
    629626                irc_usermsg( irc, "Invalid account" );
     
    648645static void cmd_rename( irc_t *irc, char **cmd )
    649646{
    650         user_t *u;
    651        
    652         if( g_strcasecmp( cmd[1], irc->nick ) == 0 )
     647        irc_user_t *iu;
     648       
     649        iu = irc_user_by_name( irc, cmd[1] );
     650       
     651        if( iu == NULL )
     652        {
     653                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
     654        }
     655        else if( iu == irc->user )
    653656        {
    654657                irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    655658        }
    656         else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    657         {
    658                 if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
    659                 {
    660                         u = user_find( irc, irc->nick );
    661                        
    662                         irc_part( irc, u, irc->channel );
    663                         g_free( irc->channel );
    664                         irc->channel = g_strdup( cmd[2] );
    665                         irc_join( irc, u, irc->channel );
    666                        
    667                         if( strcmp( cmd[0], "set_rename" ) != 0 )
    668                                 set_setstr( &irc->set, "control_channel", cmd[2] );
    669                 }
    670         }
    671         else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
     659        else if( !nick_ok( cmd[2] ) )
     660        {
     661                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
     662        }
     663        else if( irc_user_by_name( irc, cmd[2] ) )
    672664        {
    673665                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
    674666        }
    675         else if( !nick_ok( cmd[2] ) )
    676         {
    677                 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
    678         }
    679         else if( !( u = user_find( irc, cmd[1] ) ) )
    680         {
    681                 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    682         }
    683         else
    684         {
    685                 user_rename( irc, cmd[1], cmd[2] );
    686                 irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] );
    687                 if( g_strcasecmp( cmd[1], irc->mynick ) == 0 )
    688                 {
    689                         g_free( irc->mynick );
    690                         irc->mynick = g_strdup( cmd[2] );
    691                        
     667        else
     668        {
     669                if( !irc_user_set_nick( iu, cmd[2] ) )
     670                {
     671                        irc_usermsg( irc, "Error while changing nick" );
     672                        return;
     673                }
     674               
     675                if( iu == irc->root )
     676                {
    692677                        /* If we're called internally (user did "set root_nick"),
    693678                           let's not go O(INF). :-) */
    694679                        if( strcmp( cmd[0], "set_rename" ) != 0 )
    695                                 set_setstr( &irc->set, "root_nick", cmd[2] );
    696                 }
    697                 else if( u->send_handler == buddy_send_handler )
    698                 {
    699                         nick_set( u->ic->acc, u->handle, cmd[2] );
     680                                set_setstr( &irc->b->set, "root_nick", cmd[2] );
     681                }
     682                else if( iu->bu )
     683                {
     684                        nick_set( iu->bu->ic->acc, iu->bu->handle, cmd[2] );
    700685                }
    701686               
     
    704689}
    705690
     691#if 0
    706692char *set_eval_root_nick( set_t *set, char *new_nick )
    707693{
     
    730716       
    731717        return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
    732 }
    733 
    734 static void cmd_remove( irc_t *irc, char **cmd )
    735 {
    736         user_t *u;
    737         char *s;
    738        
    739         if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )
    740         {
    741                 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
    742                 return;
    743         }
    744         s = g_strdup( u->handle );
    745        
    746         u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );
    747         nick_del( u->ic->acc, u->handle );
    748         user_del( irc, cmd[1] );
    749        
    750         irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
    751         g_free( s );
    752        
    753         return;
    754718}
    755719
     
    872836        }
    873837}
     838#endif
    874839
    875840static void cmd_yesno( irc_t *irc, char **cmd )
     
    916881}
    917882
    918 static void cmd_save( irc_t *irc, char **cmd )
    919 {
    920         if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
    921                 irc_usermsg( irc, "Please create an account first" );
    922         else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
    923                 irc_usermsg( irc, "Configuration saved" );
    924         else
    925                 irc_usermsg( irc, "Configuration could not be saved!" );
    926 }
    927 
     883#if 0
    928884static void cmd_blist( irc_t *irc, char **cmd )
    929885{
     
    991947}
    992948
    993 static void cmd_nick( irc_t *irc, char **cmd )
    994 {
    995         account_t *a;
    996 
    997         if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )
    998         {
    999                 irc_usermsg( irc, "Invalid account");
    1000         }
    1001         else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
    1002         {
    1003                 irc_usermsg( irc, "That account is not on-line" );
    1004         }
    1005         else if ( !cmd[2] )
    1006         {
    1007                 irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );
    1008         }
    1009         else if ( !a->prpl->set_my_name )
    1010         {
    1011                 irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
    1012         }
    1013         else
    1014         {
    1015                 irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );
    1016                
    1017                 a->prpl->set_my_name( a->ic, cmd[2] );
    1018         }
    1019 }
    1020 
    1021949static void cmd_qlist( irc_t *irc, char **cmd )
    1022950{
     
    1037965                else
    1038966                        irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );
    1039 }
    1040 
    1041 static void cmd_join_chat( irc_t *irc, char **cmd )
    1042 {
    1043         irc_usermsg( irc, "This command is now obsolete. "
    1044                           "Please try the `chat' command instead." );
    1045967}
    1046968
     
    11571079}
    11581080
     1081static void cmd_transfer( irc_t *irc, char **cmd )
     1082{
     1083        GSList *files = irc->file_transfers;
     1084        enum { LIST, REJECT, CANCEL };
     1085        int subcmd = LIST;
     1086        int fid;
     1087
     1088        if( !files )
     1089        {
     1090                irc_usermsg( irc, "No pending transfers" );
     1091                return;
     1092        }
     1093
     1094        if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) )
     1095        {
     1096                subcmd = REJECT;
     1097        }
     1098        else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) &&
     1099                 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) )
     1100        {
     1101                subcmd = CANCEL;
     1102        }
     1103
     1104        for( ; files; files = g_slist_next( files ) )
     1105        {
     1106                file_transfer_t *file = files->data;
     1107               
     1108                switch( subcmd ) {
     1109                case LIST:
     1110                        if ( file->status == FT_STATUS_LISTENING )
     1111                                irc_usermsg( irc,
     1112                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
     1113                        else
     1114                        {
     1115                                int kb_per_s = 0;
     1116                                time_t diff = time( NULL ) - file->started ? : 1;
     1117                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
     1118                                        kb_per_s = file->bytes_transferred / 1024 / diff;
     1119                                       
     1120                                irc_usermsg( irc,
     1121                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
     1122                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
     1123                        }
     1124                        break;
     1125                case REJECT:
     1126                        if( file->status == FT_STATUS_LISTENING )
     1127                        {
     1128                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
     1129                                imcb_file_canceled( file, "Denied by user" );
     1130                        }
     1131                        break;
     1132                case CANCEL:
     1133                        if( file->local_id == fid )
     1134                        {
     1135                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
     1136                                imcb_file_canceled( file, "Canceled by user" );
     1137                        }
     1138                        break;
     1139                }
     1140        }
     1141}
     1142#endif
     1143
     1144/* IMPORTANT: Keep this list sorted! The short command logic needs that. */
    11591145const command_t commands[] = {
     1146        { "account",        1, cmd_account,        0 },
     1147        { "add",            2, cmd_add,            0 },
     1148        { "drop",           1, cmd_drop,           0 },
    11601149        { "help",           0, cmd_help,           0 },
    11611150        { "identify",       1, cmd_identify,       0 },
     1151        { "info",           1, cmd_info,           0 },
     1152        { "no",             0, cmd_yesno,          0 },
    11621153        { "register",       1, cmd_register,       0 },
    1163         { "drop",           1, cmd_drop,           0 },
    1164         { "account",        1, cmd_account,        0 },
    1165         { "add",            2, cmd_add,            0 },
    1166         { "info",           1, cmd_info,           0 },
     1154        { "remove",         1, cmd_remove,         0 },
    11671155        { "rename",         2, cmd_rename,         0 },
    1168         { "remove",         1, cmd_remove,         0 },
    1169         { "block",          1, cmd_block,          0 },
    1170         { "allow",          1, cmd_allow,          0 },
    11711156        { "save",           0, cmd_save,           0 },
    11721157        { "set",            0, cmd_set,            0 },
    11731158        { "yes",            0, cmd_yesno,          0 },
    1174         { "no",             0, cmd_yesno,          0 },
     1159#if 0
     1160        { "allow",          1, cmd_allow,          0 },
    11751161        { "blist",          0, cmd_blist,          0 },
    1176         { "nick",           1, cmd_nick,           0 },
     1162        { "block",          1, cmd_block,          0 },
     1163        { "chat",           1, cmd_chat,           0 },
     1164        { "ft",             0, cmd_transfer,       0 },
     1165        { "join_chat",      2, cmd_join_chat,      0 },
    11771166        { "qlist",          0, cmd_qlist,          0 },
    1178         { "join_chat",      2, cmd_join_chat,      0 },
    1179         { "chat",           1, cmd_chat,           0 },
     1167        { "transfer",       0, cmd_transfer,       0 },
     1168#endif
    11801169        { NULL }
    11811170};
  • set.c

    r156bbd7 r21c87a7  
    225225}
    226226
     227/*
    227228char *set_eval_ops( set_t *set, char *value )
    228229{
     
    246247        return value;
    247248}
     249*/
  • storage.c

    r156bbd7 r21c87a7  
    2828#define BITLBEE_CORE
    2929#include "bitlbee.h"
    30 #include "crypting.h"
    3130
    3231extern storage_t storage_text;
     
    6665        storage_t *storage;
    6766       
    68         register_storage_backend(&storage_text);
    6967        register_storage_backend(&storage_xml);
    7068       
  • storage_xml.c

    r156bbd7 r21c87a7  
    147147                                         arc_decode( pass_cr, pass_len, &password, xd->given_pass ) )
    148148                {
    149                         xd->current_account = account_add( irc, prpl, handle, password );
     149                        xd->current_account = account_add( irc->b, prpl, handle, password );
    150150                        if( server )
    151151                                set_setstr( &xd->current_account->set, "server", server );
     
    181181                                xd->current_set_head = &xd->current_account->set;
    182182                        else
    183                                 xd->current_set_head = &xd->irc->set;
     183                                xd->current_set_head = &xd->irc->b->set;
    184184                       
    185185                        xd->current_setting = g_strdup( setting );
     
    215215                if( xd->current_account && handle && channel )
    216216                {
    217                         xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );
     217                        //xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );
    218218                }
    219219                else
     
    353353static storage_status_t xml_load( irc_t *irc, const char *password )
    354354{
    355         return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN );
     355        return xml_load_real( irc, irc->user->nick, password, XML_PASS_UNKNOWN );
    356356}
    357357
     
    396396        md5_state_t md5_state;
    397397       
    398         path2 = g_strdup( irc->nick );
     398        path2 = g_strdup( irc->user->nick );
    399399        nick_lc( path2 );
    400400        g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" );
     
    422422        pass_buf = base64_encode( pass_md5, 21 );
    423423       
    424         if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )
     424        if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->user->nick, pass_buf, XML_FORMAT_VERSION ) )
    425425                goto write_error;
    426426       
    427427        g_free( pass_buf );
    428428       
    429         for( set = irc->set; set; set = set->next )
     429        for( set = irc->b->set; set; set = set->next )
    430430                if( set->value )
    431431                        if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
    432432                                goto write_error;
    433433       
    434         for( acc = irc->accounts; acc; acc = acc->next )
     434        for( acc = irc->b->accounts; acc; acc = acc->next )
    435435        {
    436436                unsigned char *pass_cr;
     
    470470                        goto write_error;
    471471               
     472#if 0
    472473                for( c = irc->chatrooms; c; c = c->next )
    473474                {
     
    488489                                goto write_error;
    489490                }
     491#endif
    490492               
    491493                if( !xml_printf( fd, 1, "</account>\n" ) )
  • win32.c

    r156bbd7 r21c87a7  
    2727#include "bitlbee.h"
    2828#include "commands.h"
    29 #include "crypting.h"
    3029#include "protocols/nogaim.h"
    3130#include "help.h"
Note: See TracChangeset for help on using the changeset viewer.