Changes in / [21c87a7:156bbd7]


Ignore:
Files:
9 added
22 deleted
34 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r21c87a7 r156bbd7  
    1010
    1111# Program variables
    12 #objects = chat.o
    13 objects = 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)
    14 headers = 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
     12objects = 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
     13headers = 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
    1514subdirs = lib protocols
    1615
  • bitlbee.h

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

    r21c87a7 r156bbd7  
    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;
    6865        conf->protocols = NULL;
    6966        proxytype = 0;
     
    318315                                conf->user = g_strdup( ini->value );
    319316                        }
    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                         }
    344317                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
    345318                        {
     
    376349                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
    377350                {
    378                         set_t *s = set_find( &irc->b->set, ini->key );
     351                        set_t *s = set_find( &irc->set, ini->key );
    379352                       
    380353                        if( s )
  • conf.h

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

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

    r21c87a7 r156bbd7  
    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        
    11371094</chapter>
  • ipc.c

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

    r21c87a7 r156bbd7  
    55  \********************************************************************/
    66
    7 /* The IRC-based UI (for now the only one)                              */
     7/* The big hairy IRCd part of the project                               */
    88
    99/*
     
    2424*/
    2525
     26#define BITLBEE_CORE
    2627#include "bitlbee.h"
     28#include "sock.h"
     29#include "crypting.h"
    2730#include "ipc.h"
    2831
    29 GSList *irc_connection_list;
    30 
    31 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond );
    32 static char *set_eval_charset( set_t *set, char *value );
     32static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     33
     34GSList *irc_connection_list = NULL;
     35
     36static 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
     51static 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
     96static 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}
    33114
    34115irc_t *irc_new( int fd )
     
    37118        struct sockaddr_storage sock;
    38119        socklen_t socklen = sizeof( sock );
    39         char *host = NULL, *myhost = NULL;
    40         irc_user_t *iu;
    41120        set_t *s;
    42         bee_t *b;
    43121       
    44122        irc = g_new0( irc_t, 1 );
     
    52130        irc->last_pong = gettime();
    53131       
    54         irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );
     132        irc->userhash = g_hash_table_new( g_str_hash, g_str_equal );
    55133        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 );
    56138       
    57139        irc->iconv = (GIConv) -1;
     
    60142        if( global.conf->hostname )
    61143        {
    62                 myhost = g_strdup( global.conf->hostname );
     144                irc->myhost = g_strdup( global.conf->hostname );
    63145        }
    64146        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     
    69151                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    70152                {
    71                         myhost = g_strdup( ipv6_unwrap( buf ) );
     153                        irc->myhost = g_strdup( ipv6_unwrap( buf ) );
    72154                }
    73155        }
     
    80162                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    81163                {
    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" );
     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" );
    90172       
    91173        if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
    92174                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" );
    93177
    94178        irc_connection_list = g_slist_append( irc_connection_list, irc );
    95179       
    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 );
     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 );
    131210       
    132211        conf_loaddefaults( irc );
    133212       
    134213        /* Evaluator sets the iconv/oconv structures. */
    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;
     214        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
     215       
     216        return( irc );
    143217}
    144218
     
    161235               
    162236                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    163                                    irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );
     237                                   irc->nick ? irc->nick : "(NONE)", irc->host, reason );
    164238               
    165239                g_free( reason );
     
    171245               
    172246                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    173                                    irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );
     247                                   irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" );
    174248        }
    175249       
     
    192266}
    193267
    194 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data );
    195 
     268static 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 */
    196276void irc_free( irc_t * irc )
    197277{
     278        user_t *user, *usertmp;
     279       
    198280        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
    199281       
    200         /*
    201         if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) )
     282        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )
    202283                if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )
    203284                        irc_usermsg( irc, "Error while saving settings!" );
    204         */
    205285       
    206286        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    207287       
    208         /*
     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       
    209303        while( irc->queries != NULL )
    210304                query_del( irc, irc->queries );
    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 );
     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        }
    218327       
    219328        if( irc->ping_source_id > 0 )
     
    227336        irc->fd = -1;
    228337       
    229         g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL );
    230         g_hash_table_destroy( irc->nick_user_hash );
     338        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     339        g_hash_table_destroy( irc->userhash );
    231340       
    232341        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     
    241350        g_free( irc->readbuffer );
    242351       
     352        g_free( irc->nick );
     353        g_free( irc->user );
     354        g_free( irc->host );
     355        g_free( irc->realname );
    243356        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 );
    244364       
    245365        g_free( irc );
     
    253373}
    254374
    255 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
    256 {
    257         g_free( key );
    258        
    259         return( TRUE );
    260 }
    261 
    262375/* USE WITH CAUTION!
    263376   Sets pass without checking */
    264 void irc_setpass (irc_t *irc, const char *pass)
     377void irc_setpass (irc_t *irc, const char *pass) 
    265378{
    266379        g_free (irc->password);
     
    273386}
    274387
    275 static char **irc_splitlines( char *buffer );
    276 
    277388void irc_process( irc_t *irc )
    278389{
     
    282393        if( irc->readbuffer != NULL )
    283394        {
    284                 lines = irc_splitlines( irc->readbuffer );
     395                lines = irc_tokenize( irc->readbuffer );
    285396               
    286397                for( i = 0; *lines[i] != '\0'; i ++ )
     
    319430                                                                  "`help set charset' for more information. Your "
    320431                                                                  "message was ignored.",
    321                                                                   set_getstr( &irc->b->set, "charset" ) );
     432                                                                  set_getstr( &irc->set, "charset" ) );
    322433                                               
    323434                                                g_free( conv );
     
    326437                                        else
    327438                                        {
    328                                                 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host,
     439                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    329440                                                           "Warning: invalid characters received at login time." );
    330441                                               
     
    364475}
    365476
    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.) */
    370 static char **irc_splitlines( char *buffer )
     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. */
     479char **irc_tokenize( char *buffer )
    371480{
    372481        int i, j, n = 3;
     
    499608}
    500609
     610void 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
     623int 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
    501640void irc_write( irc_t *irc, char *format, ... )
    502641{
     
    509648        return;
    510649}
    511 
    512 void 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 }
    540650
    541651void irc_vawrite( irc_t *irc, char *format, va_list params )
     
    594704}
    595705
     706void 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
     735void 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 )
     750                        {
     751                                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     752                                *namelist = 0;
     753                        }
     754                       
     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
    596793int irc_check_login( irc_t *irc )
    597794{
    598         if( irc->user->user && irc->user->nick )
     795        if( irc->user && irc->nick )
    599796        {
    600797                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
    601798                {
    602                         irc_send_num( irc, 464, ":This server is password-protected." );
     799                        irc_reply( irc, 464, ":This server is password-protected." );
    603800                        return 0;
    604801                }
    605802                else
    606803                {
    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 )
    625                         {
    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] );
    631                         }
    632                        
    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                        
     804                        irc_login( irc );
    652805                        return 1;
    653806                }
     
    660813}
    661814
    662 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv )
     815void 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
     875void 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
     927void 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
     939void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    663940{
    664941        /* allow_priv: Set to 0 if s contains user input, 1 if you want
    665942           to set a "privileged" mode (+o, +R, etc). */
    666         char m[128], st = 1;
    667         const char *t;
     943        char m[256], st = 1, *t;
    668944        int i;
    669945        char changes[512], *p, st2 = 2;
     
    673949       
    674950        for( t = irc->umode; *t; t ++ )
    675                 if( *t < sizeof( m ) )
    676                         m[(int)*t] = 1;
    677        
     951                m[(int)*t] = 1;
     952
    678953        p = changes;
    679954        for( t = s; *t; t ++ )
     
    681956                if( *t == '+' || *t == '-' )
    682957                        st = *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 ) ) )
     958                else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) )
    686959                {
    687960                        if( m[(int)*t] != st)
     
    700973        memset( irc->umode, 0, sizeof( irc->umode ) );
    701974       
    702         for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
     975        for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
    703976                if( m[i] )
    704977                        irc->umode[strlen(irc->umode)] = i;
    705978       
    706979        if( badflag )
    707                 irc_send_num( irc, 501, ":Unknown MODE flag" );
     980                irc_reply( irc, 501, ":Unknown MODE flag" );
     981        /* Deliberately no !user@host on the prefix here */
    708982        if( *changes )
    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 
     983                irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes );
     984}
     985
     986void irc_spawn( irc_t *irc, user_t *u )
     987{
     988        irc_join( irc, u, irc->channel );
     989}
     990
     991void 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
     1014void 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
     1019void 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
     1024void 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
     1061int 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
     1162static 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
     1182void 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
     1227int 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
     1266int 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
     1289int 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}
    7141298
    7151299/* Returns 0 if everything seems to be okay, a number >0 when there was a
     
    7491333}
    7501334
    751 static 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 }
     1335struct 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}
  • irc.h

    r21c87a7 r156bbd7  
    55  \********************************************************************/
    66
    7 /* The IRC-based UI (for now the only one)                              */
     7/* The big hairy IRCd part of the project                               */
    88
    99/*
     
    3333#define IRC_PING_STRING "PinglBee"
    3434
    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 */
     35#define UMODES "abisw"
     36#define UMODES_PRIV "Ro"
     37#define CMODES "nt"
     38#define CMODE "t"
     39#define UMODE "s"
     40#define CTYPES "&#"
    4341
    4442typedef enum
     
    5048        USTATUS_SHUTDOWN = 8
    5149} irc_status_t;
    52 
    53 struct irc_user;
    5450
    5551typedef struct irc
     
    6359        GIConv iconv, oconv;
    6460
    65         struct irc_user *root;
    66         struct irc_user *user;
    67        
    68         char *last_root_cmd;
     61        int sentbytes;
     62        time_t oldtime;
    6963
     64        char *nick;
     65        char *user;
     66        char *host;
     67        char *realname;
    7068        char *password; /* HACK: Used to save the user's password, but before
    7169                           logging in, this may contain a password we should
     
    7472        char umode[8];
    7573       
     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       
    7683        struct query *queries;
    77         GSList *file_transfers;
     84        struct account *accounts;
     85        struct chat *chatrooms;
    7886       
    79         GSList *users, *channels;
    80         GHashTable *nick_user_hash;
     87        struct __USER *users;
     88        GHashTable *userhash;
    8189        GHashTable *watches;
     90        struct __NICK *nicks;
     91        struct set *set;
    8292
    8393        gint r_watch_source_id;
    8494        gint w_watch_source_id;
    8595        gint ping_source_id;
    86        
    87         struct bee *b;
    8896} irc_t;
    8997
    90 typedef enum
    91 {
    92         IRC_USER_PRIVATE = 1,
    93 } irc_user_flags_t;
     98#include "user.h"
    9499
    95 typedef struct irc_user
    96 {
    97         irc_t *irc;
    98        
    99         char *nick;
    100         char *user;
    101         char *host;
    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 
    119 struct 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 
    125 extern const struct irc_user_funcs irc_user_root_funcs;
    126 extern const struct irc_user_funcs irc_user_self_funcs;
    127 
    128 typedef enum
    129 {
    130         IRC_CHANNEL_JOINED = 1,
    131 } irc_channel_flags_t;
    132 
    133 typedef 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;
    145         struct set *set;
    146        
    147         const struct irc_channel_funcs *f;
    148 } irc_channel_t;
    149 
    150 struct irc_channel_funcs
    151 {
    152         gboolean (*privmsg)( irc_channel_t *iu, const char *msg );
    153 };
    154 
    155 extern const struct bee_ui_funcs irc_ui_funcs;
    156 
    157 /* irc.c */
    158100extern GSList *irc_connection_list;
    159101
     
    161103void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    162104void irc_free( irc_t *irc );
    163 void irc_setpass (irc_t *irc, const char *pass);
    164105
     106void irc_exec( irc_t *irc, char **cmd );
    165107void irc_process( irc_t *irc );
    166108char **irc_parse_line( char *line );
    167109char *irc_build_line( char **cmd );
    168110
     111void irc_vawrite( irc_t *irc, char *format, va_list params );
    169112void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    170113void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    171 void irc_vawrite( irc_t *irc, char *format, va_list params );
     114void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
     115G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
     116char **irc_tokenize( char *buffer );
    172117
     118void irc_login( irc_t *irc );
    173119int irc_check_login( irc_t *irc );
     120void irc_motd( irc_t *irc );
     121void irc_names( irc_t *irc, char *channel );
     122void irc_topic( irc_t *irc, char *channel );
     123void irc_umode_set( irc_t *irc, char *s, int allow_priv );
     124void irc_who( irc_t *irc, char *channel );
     125void irc_spawn( irc_t *irc, user_t *u );
     126void irc_join( irc_t *irc, user_t *u, char *channel );
     127void irc_part( irc_t *irc, user_t *u, char *channel );
     128void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker );
     129void irc_kill( irc_t *irc, user_t *u );
     130void irc_invite( irc_t *irc, char *nick, char *channel );
     131void irc_whois( irc_t *irc, char *nick );
     132void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */
    174133
    175 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv );
     134int irc_send( irc_t *irc, char *nick, char *s, int flags );
     135int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg );
     136int irc_msgfrom( irc_t *irc, char *nick, char *msg );
     137int irc_noticefrom( irc_t *irc, char *nick, char *msg );
    176138
    177 /* irc_channel.c */
    178 irc_channel_t *irc_channel_new( irc_t *irc, const char *name );
    179 irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name );
    180 int irc_channel_free( irc_channel_t *ic );
    181 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu );
    182 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu );
    183 gboolean irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
    184 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who );
    185 gboolean irc_channel_name_ok( const char *name );
    186 
    187 /* irc_commands.c */
    188 void irc_exec( irc_t *irc, char **cmd );
    189 
    190 /* irc_send.c */
    191 void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    192 void irc_send_login( irc_t *irc );
    193 void irc_send_motd( irc_t *irc );
    194 void irc_usermsg( irc_t *irc, char *format, ... );
    195 void irc_send_join( irc_channel_t *ic, irc_user_t *iu );
    196 void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason );
    197 void irc_send_names( irc_channel_t *ic );
    198 void irc_send_topic( irc_channel_t *ic, gboolean topic_change );
    199 void irc_send_whois( irc_user_t *iu );
    200 void irc_send_who( irc_t *irc, GSList *l, const char *channel );
    201 void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix );
    202 void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg );
    203 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 );
    204 void irc_send_nick( irc_user_t *iu, const char *new );
    205 
    206 /* irc_user.c */
    207 irc_user_t *irc_user_new( irc_t *irc, const char *nick );
    208 int irc_user_free( irc_t *irc, irc_user_t *iu );
    209 irc_user_t *irc_user_by_name( irc_t *irc, const char *nick );
    210 int irc_user_set_nick( irc_user_t *iu, const char *new );
    211 gint irc_user_cmp( gconstpointer a_, gconstpointer b_ );
    212 
    213 /* irc_util.c */
    214 char *set_eval_timezone( struct set *set, char *value );
    215 char *irc_format_timestamp( irc_t *irc, time_t msg_ts );
     139void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
     140struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
    216141
    217142#endif
  • irc_commands.c

    r21c87a7 r156bbd7  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2006 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    5353        else if( global.conf->auth_pass )
    5454        {
    55                 irc_send_num( irc, 464, ":Incorrect password" );
     55                irc_reply( 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->user = g_strdup( cmd[1] );
    68         irc->user->fullname = g_strdup( cmd[4] );
     67        irc->user = g_strdup( cmd[1] );
     68        irc->realname = g_strdup( cmd[4] );
    6969       
    7070        irc_check_login( irc );
     
    7373static void irc_cmd_nick( irc_t *irc, char **cmd )
    7474{
    75         if( irc_user_by_name( irc, cmd[1] ) )
    76         {
    77                 irc_send_num( irc, 433, ":This nick is already in use" );
     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" );
    7883        }
    7984        else if( !nick_ok( cmd[1] ) )
    8085        {
    8186                /* [SH] Invalid characters. */
    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] );
     87                irc_reply( irc, 432, ":This nick contains invalid characters" );
     88        }
     89        else
     90        {
     91                irc->nick = g_strdup( cmd[1] );
    9892               
    9993                irc_check_login( irc );
     
    111105static void irc_cmd_ping( irc_t *irc, char **cmd )
    112106{
    113         irc_write( irc, ":%s PONG %s :%s", irc->root->host,
    114                    irc->root->host, cmd[1]?cmd[1]:irc->root->host );
    115 }
    116 
    117 static 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 
    125 static 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 
    145 static 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 
    163 static 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 
    177 static 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 
    188 static 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 
    199 static void irc_cmd_motd( irc_t *irc, char **cmd )
    200 {
    201         irc_send_motd( irc );
     107        irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
     108}
     109
     110static 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        }
    202124}
    203125
    204126static void irc_cmd_mode( irc_t *irc, char **cmd )
    205127{
    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] )
     128        if( strchr( CTYPES, *cmd[1] ) )
     129        {
     130                if( cmd[2] )
    213131                {
    214132                        if( *cmd[2] == '+' || *cmd[2] == '-' )
    215                                 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
     133                                irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
    216134                        else if( *cmd[2] == 'b' )
    217                                 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
     135                                irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
    218136                }
    219137                else
    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 )
     138                        irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
     139        }
     140        else
     141        {
     142                if( nick_cmp( cmd[1], irc->nick ) == 0 )
    225143                {
    226144                        if( cmd[2] )
    227145                                irc_umode_set( irc, cmd[2], 0 );
    228146                        else
    229                                 irc_send_num( irc, 221, "+%s", irc->umode );
     147                                irc_reply( irc, 221, "+%s", irc->umode );
    230148                }
    231149                else
    232                         irc_send_num( irc, 502, ":Don't touch their modes" );
    233         }
    234 }
    235 
    236 static 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 );
     150                        irc_reply( irc, 502, ":Don't touch their modes" );
     151        }
     152}
     153
     154static void irc_cmd_names( irc_t *irc, char **cmd )
     155{
     156        irc_names( irc, cmd[1]?cmd[1]:irc->channel );
     157}
     158
     159static 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
     189static 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
     207static 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 );
    247222}
    248223
    249224static void irc_cmd_privmsg( irc_t *irc, char **cmd )
    250225{
    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         {
     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] );
    301233        }
    302234        else
     
    339271                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
    340272        }
    341 #endif
    342 }
    343 
    344 static 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
    354 static 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 
    370 static 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 );
     273}
     274
     275static 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:"**" );
    385305}
    386306
     
    400320                {
    401321                        if( u->online && u->away )
    402                                 irc_send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
     322                                irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    403323                        else
    404                                 irc_send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
     324                                irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    405325                }
    406326}
     
    457377                buff[strlen(buff)-1] = '\0';
    458378       
    459         irc_send_num( irc, 303, ":%s", buff );
     379        irc_reply( irc, 303, ":%s", buff );
    460380}
    461381
     
    486406                       
    487407                        if( u && u->online )
    488                                 irc_send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
     408                                irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
    489409                        else
    490                                 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
     410                                irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
    491411                }
    492412                else if( cmd[i][0] == '-' )
     
    499419                                g_free( okey );
    500420                               
    501                                 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
     421                                irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    502422                        }
    503423                }
     
    523443        }
    524444}
    525 #endif
    526445
    527446static void irc_cmd_away( irc_t *irc, char **cmd )
    528447{
    529         char *set;
    530        
    531         if( cmd[1] && *cmd[1] )
    532         {
    533                 char away[strlen(cmd[1])+1];
     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        {
    534455                int i, j;
    535456               
    536457                /* Copy away string, but skip control chars. Mainly because
    537458                   Jabber really doesn't like them. */
    538                 for( i = j = 0; cmd[1][i]; i ++ )
    539                         if( ( away[j] = cmd[1][i] ) >= ' ' )
     459                u->away = g_malloc( strlen( away ) + 1 );
     460                for( i = j = 0; away[i]; i ++ )
     461                        if( ( u->away[j] = away[i] ) >= ' ' )
    540462                                j ++;
    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
     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
     479static 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
     510static 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
     521static 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
     528static void irc_cmd_motd( irc_t *irc, char **cmd )
     529{
     530        irc_motd( irc );
     531}
     532
     533static 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
    556541static void irc_cmd_version( irc_t *irc, char **cmd )
    557542{
    558         irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
     543        irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
    559544}
    560545
     
    587572                ipc_to_master( cmd );
    588573       
    589         irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
    590 }
    591 #endif
     574        irc_reply( irc, 382, "%s :Rehashing", global.conf_file );
     575}
    592576
    593577static const command_t irc_commands[] = {
     
    597581        { "quit",        0, irc_cmd_quit,        0 },
    598582        { "ping",        0, irc_cmd_ping,        0 },
    599         { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
     583        { "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 },
    600587        { "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 },
     588        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
     589        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
     590        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    607591        { "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
    613         { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
    614         { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
    615         { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    616592        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
    617593        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
    618594        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
    619595        { "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 },
    620603        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
    621604        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
     
    627610        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    628611        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    629 #endif
    630612        { NULL }
    631613};
     
    646628                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
    647629                        {
    648                                 irc_send_num( irc, 462, ":Only allowed before logging in" );
     630                                irc_reply( irc, 462, ":Only allowed before logging in" );
    649631                        }
    650632                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
    651633                        {
    652                                 irc_send_num( irc, 451, ":Register first" );
     634                                irc_reply( irc, 451, ":Register first" );
    653635                        }
    654636                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
    655637                        {
    656                                 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
     638                                irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" );
    657639                        }
    658640                        else if( n_arg < irc_commands[i].required_parameters )
    659641                        {
    660                                 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
     642                                irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    661643                        }
    662644                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
     
    675657       
    676658        if( irc->status >= USTATUS_LOGGED_IN )
    677                 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
    678 }
     659                irc_reply( irc, 421, "%s :Unknown command", cmd[0] );
     660}
  • lib/Makefile

    r21c87a7 r156bbd7  
    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 ftutil.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
    1313
    1414CFLAGS += -Wall
  • lib/misc.c

    r21c87a7 r156bbd7  
    649649        return ret;
    650650}
    651 
    652 char **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

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

    r21c87a7 r156bbd7  
    7878               
    7979                nick_strip( nick );
    80                 if( set_getbool( &acc->bee->set, "lcnicks" ) )
     80                if( set_getbool( &acc->irc->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;
    9594        int inf_protection = 256;
    9695       
    9796        /* Now, find out if the nick is already in use at the moment, and make
    9897           subtle changes to make it unique. */
    99         while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) )
     98        while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
    10099        {
    101100                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
     
    113112                        int i;
    114113                       
    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 );
     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 );
    122121                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
    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" );
     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" );
    128127                       
    129128                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
  • protocols/Makefile

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

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

    r21c87a7 r156bbd7  
    9191                        pack = 0;
    9292                }
    93                 else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
    94                 {
    95                         const char *features[] = { XMLNS_DISCO_INFO,
     93                else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
     94                {
     95                        const char *features[] = { XMLNS_DISCOVER,
    9696                                                   XMLNS_VERSION,
    9797                                                   XMLNS_TIME,
     
    9999                                                   XMLNS_MUC,
    100100                                                   XMLNS_PING,
    101                                                    XMLNS_SI,
    102                                                    XMLNS_BYTESTREAMS,
    103                                                    XMLNS_FILETRANSFER,
    104101                                                   NULL };
    105102                        const char **f;
     
    121118                {
    122119                        xt_free_node( reply );
    123                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
     120                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
    124121                        pack = 0;
    125122                }
     
    127124        else if( strcmp( type, "set" ) == 0 )
    128125        {
    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" ) ) )
     126                if( !( c = xt_find_node( node->children, "query" ) ) ||
     127                    !( s = xt_find_attr( c, "xmlns" ) ) )
    137128                {
    138129                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    139130                        return XT_HANDLED;
    140131                }
    141                 else if( strcmp( s, XMLNS_ROSTER ) == 0 )
    142                 {
     132               
    143133                /* This is a roster push. XMPP servers send this when someone
    144134                   was added to (or removed from) the buddy list. AFAIK they're
    145135                   sent even if we added this buddy in our own session. */
     136                if( strcmp( s, XMLNS_ROSTER ) == 0 )
     137                {
    146138                        int bare_len = strlen( ic->acc->user );
    147139                       
     
    160152                               
    161153                                xt_free_node( reply );
    162                                 reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
     154                                reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
    163155                                pack = 0;
    164156                        }
    165157                }
    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                 }
    171158                else
    172159                {
    173160                        xt_free_node( reply );
    174                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
     161                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
    175162                        pack = 0;
    176163                }
     
    392379                        if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
    393380                        {
    394                                 if( initial || bee_user_by_handle( ic->bee, ic, jid ) == NULL )
     381                                if( initial || imcb_find_buddy( ic, jid ) == NULL )
    395382                                        imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
    396383                                                                   group->text : NULL );
     
    590577            strcmp( s, "result" ) == 0 )
    591578        {
    592                 if( bee_user_by_handle( ic->bee, ic, jid ) == NULL )
     579                if( imcb_find_buddy( ic, jid ) == NULL )
    593580                        imcb_add_buddy( ic, jid, NULL );
    594581        }
     
    622609        return st;
    623610}
    624 
    625 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    626 
    627 xt_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 
    657 xt_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 
    690 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    691 
    692 xt_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  */
    715 xt_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

    r21c87a7 r156bbd7  
    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 );
    6967       
    7068        s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
     
    266264        struct jabber_data *jd = ic->proto_data;
    267265       
    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 
    280266        if( jd->fd >= 0 )
    281267                jabber_end_stream( ic );
     
    558544        ret->send_typing = jabber_send_typing;
    559545        ret->handle_cmp = g_strcasecmp;
    560         ret->transfer_request = jabber_si_transfer_request;
    561546
    562547        register_protocol( ret );
  • protocols/jabber/jabber.h

    r21c87a7 r156bbd7  
    6161} jabber_buddy_flags_t;
    6262
    63 /* Stores a streamhost's (a.k.a. proxy) data */
    64 typedef struct
    65 {
    66         char *jid;
    67         char *host;
    68         char port[6];
    69 } jabber_streamhost_t;
    70 
    7163typedef enum
    7264{
     
    9991        GHashTable *node_cache;
    10092        GHashTable *buddies;
    101 
    102         GSList *filetransfers;
    103         GSList *streamhosts;
    104         int have_streamhosts;
    10593};
    10694
     
    139127        struct jabber_away_state *away_state;
    140128        char *away_message;
    141         GSList *features;
    142129       
    143130        time_t last_msg;
     
    153140        char *my_full_jid; /* Separate copy because of case sensitivity. */
    154141        struct jabber_buddy *me;
    155 };
    156 
    157 struct 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;
    185142};
    186143
     
    210167
    211168/* Some supported extensions/legacy stuff */
    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 */
     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 */
    230180
    231181/* iq.c */
     
    237187int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    238188int jabber_remove_from_roster( struct im_connection *ic, char *handle );
    239 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
    240 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
    241 
    242 /* si.c */
    243 int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
    244 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
    245 void jabber_si_free_transfer( file_transfer_t *ft);
    246 
    247 /* s5bytestream.c */
    248 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
    249 gboolean jabber_bs_send_start( struct jabber_transfer *tf );
    250 gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    251189
    252190/* message.c */
     
    262200char *set_eval_tls( set_t *set, char *value );
    263201struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    264 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
     202struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
    265203void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    266204struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    r21c87a7 r156bbd7  
    9999}
    100100
    101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
     101struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
    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 );
    117113       
    118114        /* To make the actual error packet, we copy the original packet and
     
    279275        presence_send_request( bla->ic, bla->handle, "subscribed" );
    280276       
    281         imcb_ask_add( bla->ic, bla->handle, NULL );
     277        if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
     278                imcb_ask_add( bla->ic, bla->handle, NULL );
    282279       
    283280        g_free( bla->handle );
     
    461458               
    462459                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
    463                     ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) )
     460                    ( bare_exists || imcb_find_buddy( ic, jid ) ) )
    464461                {
    465462                        *s = '/';
     
    482479                if( bud == NULL )
    483480                        /* No match. Create it now? */
    484                         return ( ( flags & GET_BUDDY_CREAT ) &&
    485                                  bee_user_by_handle( ic->bee, ic, jid_ ) ) ?
     481                        return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ?
    486482                                   jabber_buddy_add( ic, jid_ ) : NULL;
    487483                else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
  • protocols/msn/msn.c

    r21c87a7 r156bbd7  
    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                
    8680                if( md->fd >= 0 )
    8781                        closesocket( md->fd );
     
    333327        ret->send_typing = msn_send_typing;
    334328        ret->handle_cmp = g_strcasecmp;
    335         //ret->transfer_request = msn_ftp_transfer_request;
    336329
    337330        register_protocol(ret);
  • protocols/msn/msn.h

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

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

    r21c87a7 r156bbd7  
    2929#include "passport.h"
    3030#include "md5.h"
    31 #include "invitation.h"
    3231
    3332static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
     
    169168               
    170169                /* Build the message. Convert LF to CR-LF for normal messages. */
    171                 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
     170                if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
     171                {
     172                        buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
     173                        i = strlen( MSN_MESSAGE_HEADERS );
     174                       
     175                        strcpy( buf, MSN_MESSAGE_HEADERS );
     176                        for( j = 0; text[j]; j ++ )
     177                        {
     178                                if( text[j] == '\n' )
     179                                        buf[i++] = '\r';
     180                               
     181                                buf[i++] = text[j];
     182                        }
     183                }
     184                else
    172185                {
    173186                        i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
    174187                        buf = g_new0( char, i );
    175188                        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
    183                 {
    184                         buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
    185                         i = strlen( MSN_MESSAGE_HEADERS );
    186                        
    187                         strcpy( buf, MSN_MESSAGE_HEADERS );
    188                         for( j = 0; text[j]; j ++ )
    189                         {
    190                                 if( text[j] == '\n' )
    191                                         buf[i++] = '\r';
    192                                
    193                                 buf[i++] = text[j];
    194                         }
    195189                }
    196190               
     
    691685                        }
    692686                }
    693 #if 0
    694                 // Disable MSN ft support for now.
    695687                else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
    696688                {
    697                         char *command = msn_findheader( body, "Invitation-Command:", blen );
    698                         char *cookie = msn_findheader( body, "Invitation-Cookie:", blen );
    699                         unsigned int icookie;
     689                        char *itype = msn_findheader( body, "Application-GUID:", blen );
     690                        char buf[1024];
    700691                       
    701692                        g_free( ct );
    702693                       
    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 );
     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                        }
    733745                }
    734746                else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
  • protocols/nogaim.c

    r21c87a7 r156bbd7  
    3838#include "chat.h"
    3939
     40static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
     41static char *format_timestamp( irc_t *irc, time_t msg_ts );
     42
    4043GSList *connections;
    4144
     
    8992}
    9093#endif
     94
     95/* nogaim.c */
    9196
    9297GList *protocols = NULL;
     
    121126}
    122127
     128/* nogaim.c */
    123129void nogaim_init()
    124130{
     
    156162GSList *get_connections() { return connections; }
    157163
     164/* multi.c */
     165
    158166struct im_connection *imcb_new( account_t *acc )
    159167{
     
    162170        ic = g_new0( struct im_connection, 1 );
    163171       
    164         ic->bee = acc->bee;
     172        ic->irc = acc->irc;
    165173        ic->acc = acc;
    166174        acc->ic = ic;
     
    176184       
    177185        /* Destroy the pointer to this connection from the account list */
    178         for( a = ic->bee->accounts; a; a = a->next )
     186        for( a = ic->irc->accounts; a; a = a->next )
    179187                if( a->ic == ic )
    180188                {
     
    197205        va_end( params );
    198206
    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" ) ) )
     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" ) ) )
    201209                strip_html( text );
    202210       
    203211        /* Try to find a different connection on the same protocol. */
    204         for( a = ic->bee->accounts; a; a = a->next )
     212        for( a = ic->irc->accounts; a; a = a->next )
    205213                if( a->prpl == ic->acc->prpl && a->ic != ic )
    206214                        break;
     
    208216        /* If we found one, include the screenname in the message. */
    209217        if( a )
    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 );
     218                irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
    212219        else
    213                 irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text );
     220                irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text );
    214221       
    215222        g_free( text );
     
    262269void imcb_connected( struct im_connection *ic )
    263270{
     271        irc_t *irc = ic->irc;
     272        struct chat *c;
     273        user_t *u;
     274       
    264275        /* MSN servers sometimes redirect you to a different server and do
    265276           the whole login sequence again, so these "late" calls to this
     
    268279                return;
    269280       
     281        u = user_find( ic->irc, ic->irc->nick );
     282       
    270283        imcb_log( ic, "Logged in" );
    271284       
     
    280293        ic->acc->auto_reconnect_delay = 0;
    281294       
    282         /*
    283295        for( c = irc->chatrooms; c; c = c->next )
    284296        {
     
    289301                        chat_join( irc, c, NULL );
    290302        }
    291         */
    292303}
    293304
     
    297308       
    298309        a->reconnect = 0;
    299         account_on( a->bee, a );
     310        account_on( a->irc, a );
    300311       
    301312        return( FALSE );        /* Only have to run the timeout once */
     
    310321void imc_logout( struct im_connection *ic, int allow_reconnect )
    311322{
    312         bee_t *bee = ic->bee;
     323        irc_t *irc = ic->irc;
     324        user_t *t, *u;
    313325        account_t *a;
    314         GSList *l;
    315326        int delay;
    316327       
     
    332343        ic->away = NULL;
    333344       
    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 )
     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 )
    348361                if( a->ic == ic )
    349362                        break;
     
    353366                /* Uhm... This is very sick. */
    354367        }
    355         else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) &&
     368        else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) &&
    356369                 set_getbool( &a->set, "auto_reconnect" ) &&
    357370                 ( delay = account_reconnect_delay( a ) ) > 0 )
     
    364377}
    365378
     379
     380/* dialogs.c */
     381
    366382void imcb_ask( struct im_connection *ic, char *msg, void *data,
    367383               query_callback doit, query_callback dont )
    368384{
    369         query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data );
    370 }
     385        query_add( ic->irc, ic, msg, doit, dont, data );
     386}
     387
     388
     389/* list.c */
    371390
    372391void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
    373392{
    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" ) )
     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" ) )
    380400                        imcb_log( ic, "User already exists, ignoring add request: %s", handle );
    381401               
     
    388408        }
    389409       
    390         bu = bee_user_new( bee, ic, handle );
    391         bu->group = g_strdup( group );
    392 }
    393 
    394 void 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 );
     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
     446struct 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
     465void 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 );
    408497        }
    409498}
     
    411500void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
    412501{
    413         bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) );
     502        user_t *u;
     503       
     504        if( ( u = user_findhandle( ic, handle ) ) )
     505                user_del( ic->irc, u->nick );
    414506}
    415507
     
    418510void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
    419511{
    420 #if 0
    421512        user_t *u = user_findhandle( ic, handle );
    422513        char newnick[MAX_NICK_LENGTH+1], *orig_nick;
     
    433524                /* Some processing to make sure this string is a valid IRC nickname. */
    434525                nick_strip( newnick );
    435                 if( set_getbool( &ic->bee->set, "lcnicks" ) )
     526                if( set_getbool( &ic->irc->set, "lcnicks" ) )
    436527                        nick_lc( newnick );
    437528               
     
    450541                }
    451542        }
    452 #endif
    453543}
    454544
     
    495585        data->ic = ic;
    496586        data->handle = g_strdup( handle );
    497         query_add( (irc_t *) ic->bee->ui_data, ic, s,
    498                    imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
     587        query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
    499588}
    500589
     
    521610       
    522611        /* TODO: Make a setting for this! */
    523         if( bee_user_by_handle( ic->bee, ic, handle ) != NULL )
     612        if( user_findhandle( ic, handle ) != NULL )
    524613                return;
    525614       
     
    528617        data->ic = ic;
    529618        data->handle = g_strdup( handle );
    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 
    534 struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle )
    535 {
    536         return bee_user_by_handle( ic->bee, ic, 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
     625void 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
     723void 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
     783void 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        }
    537797}
    538798
    539799struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
    540800{
    541 #if 0
    542801        struct groupchat *c;
    543802       
     
    557816        c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
    558817       
    559         if( set_getbool( &ic->bee->set, "debug" ) )
     818        if( set_getbool( &ic->irc->set, "debug" ) )
    560819                imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle );
    561820       
    562821        return c;
    563 #endif
    564         return NULL;
    565822}
    566823
    567824void imcb_chat_name_hint( struct groupchat *c, const char *name )
    568825{
    569 #if 0
    570826        if( !c->joined )
    571827        {
     
    593849                }
    594850        }
    595 #endif
    596851}
    597852
    598853void imcb_chat_free( struct groupchat *c )
    599854{
    600 #if 0
    601855        struct im_connection *ic = c->ic;
    602856        struct groupchat *l;
    603857        GList *ir;
    604858       
    605         if( set_getbool( &ic->bee->set, "debug" ) )
     859        if( set_getbool( &ic->irc->set, "debug" ) )
    606860                imcb_log( ic, "You were removed from conversation %p", c );
    607861       
     
    636890                g_free( c );
    637891        }
    638 #endif
    639892}
    640893
    641894void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
    642895{
    643 #if 0
    644896        struct im_connection *ic = c->ic;
    645897        char *wrapped;
     
    652904        u = user_findhandle( ic, who );
    653905       
    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" ) ) )
     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" ) ) )
    656908                strip_html( msg );
    657909       
     
    670922        }
    671923        g_free( wrapped );
    672 #endif
    673924}
    674925
    675926void imcb_chat_log( struct groupchat *c, char *format, ... )
    676927{
    677 #if 0
    678928        irc_t *irc = c->ic->irc;
    679929        va_list params;
     
    690940       
    691941        g_free( text );
    692 #endif
    693942}
    694943
    695944void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at )
    696945{
    697 #if 0
    698946        struct im_connection *ic = c->ic;
    699947        user_t *u = NULL;
     
    706954                u = user_findhandle( ic, who );
    707955       
    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" ) ) )
     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" ) ) )
    710958                strip_html( topic );
    711959       
     
    715963        if( c->joined && u )
    716964                irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic );
    717 #endif
    718 }
     965}
     966
     967
     968/* buddy_chat.c */
    719969
    720970void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
    721971{
    722 #if 0
    723972        user_t *u = user_findhandle( b->ic, handle );
    724973        int me = 0;
    725974       
    726         if( set_getbool( &b->ic->bee->set, "debug" ) )
     975        if( set_getbool( &b->ic->irc->set, "debug" ) )
    727976                imcb_log( b->ic, "User %s added to conversation %p", handle, b );
    728977       
     
    7511000                b->in_room = g_list_append( b->in_room, g_strdup( handle ) );
    7521001        }
    753 #endif
    7541002}
    7551003
     
    7571005void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
    7581006{
    759 #if 0
    7601007        user_t *u;
    7611008        int me = 0;
    7621009       
    763         if( set_getbool( &b->ic->bee->set, "debug" ) )
     1010        if( set_getbool( &b->ic->irc->set, "debug" ) )
    7641011                imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" );
    7651012       
     
    7811028        if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
    7821029                irc_part( b->ic->irc, u, b->channel );
    783 #endif
    784 }
    785 
    786 #if 0
     1030}
     1031
    7871032static int remove_chat_buddy_silent( struct groupchat *b, const char *handle )
    7881033{
     
    8031048        }
    8041049       
    805         return 0;
    806 }
    807 #endif
     1050        return( 0 );
     1051}
    8081052
    8091053
    8101054/* Misc. BitlBee stuff which shouldn't really be here */
    811 #if 0
     1055
    8121056char *set_eval_away_devoice( set_t *set, char *value )
    8131057{
     
    8221066        /* Horror.... */
    8231067       
    824         if( st != set_getbool( &irc->b->set, "away_devoice" ) )
     1068        if( st != set_getbool( &irc->set, "away_devoice" ) )
    8251069        {
    8261070                char list[80] = "";
     
    8641108        return value;
    8651109}
    866 #endif
     1110
     1111char *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
     1149static 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}
    8671199
    8681200/* The plan is to not allow straight calls to prpl functions anymore, but do
    8691201   them all from some wrappers. We'll start to define some down here: */
     1202
     1203int 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}
    8701219
    8711220int imc_chat_msg( struct groupchat *c, char *msg, int flags )
     
    8961245       
    8971246        away = set_getstr( &ic->acc->set, "away" ) ?
    898              : set_getstr( &ic->bee->set, "away" );
     1247             : set_getstr( &ic->irc->set, "away" );
    8991248        if( away && *away )
    9001249        {
     
    9071256                away = NULL;
    9081257                msg = set_getstr( &ic->acc->set, "status" ) ?
    909                     : set_getstr( &ic->bee->set, "status" );
     1258                    : set_getstr( &ic->irc->set, "status" );
    9101259        }
    9111260       
  • protocols/nogaim.h

    r21c87a7 r156bbd7  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    4545#include "proxy.h"
    4646#include "query.h"
    47 #include "md5.h"
    48 #include "ft.h"
    4947
    5048#define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */
     
    8785       
    8886        /* BitlBee */
    89         bee_t *bee;
     87        irc_t *irc;
    9088       
    9189        struct groupchat *groupchats;
     
    230228        void (* auth_allow)     (struct im_connection *, const char *who);
    231229        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 );
    235230};
    236231
     
    286281G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
    287282
     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 */
     288G_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. */
     291G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
    288292G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
    289 G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle );
    290293G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
    291294
     
    313316/* Actions, or whatever. */
    314317int imc_away_send_update( struct im_connection *ic );
     318int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );
    315319int imc_chat_msg( struct groupchat *c, char *msg, int flags );
    316320
     
    321325
    322326/* Misc. stuff */
     327char *set_eval_timezone( set_t *set, char *value );
    323328char *set_eval_away_devoice( set_t *set, char *value );
    324329gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
  • protocols/oscar/oscar.c

    r21c87a7 r156bbd7  
    11901190        aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
    11911191        // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
    1192         imcb_ask_add(data->ic, uin, NULL);
     1192        if(imcb_find_buddy(data->ic, uin) == NULL)
     1193                imcb_ask_add(data->ic, uin, NULL);
    11931194       
    11941195        g_free(uin);
     
    19511952        struct oscar_data *odata = (struct oscar_data *)g->proto_data;
    19521953        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                 */
    19601959        } else
    19611960                aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE);
     
    20952094                switch (curitem->type) {
    20962095                        case 0x0000: /* Buddy */
    2097                                 if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) {
     2096                                if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) {
    20982097                                        char *realname = NULL;
    20992098
  • protocols/twitter/twitter_lib.c

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

    r21c87a7 r156bbd7  
    6464        }
    6565       
    66         if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )
     66        if( g_strcasecmp( set_getstr( &irc->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->b->set, "query_order" ), "fifo" ) == 0 )
     181        if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 )
    182182                q = irc->queries;
    183183        else
  • root_commands.c

    r21c87a7 r156bbd7  
    2626#define BITLBEE_CORE
    2727#include "commands.h"
     28#include "crypting.h"
    2829#include "bitlbee.h"
    2930#include "help.h"
     
    3233#include <string.h>
    3334
    34 void root_command_string( irc_t *irc, char *command )
    35 {
    36         root_command( irc, split_command_parts( command ) );
     35void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
     36{
     37        char *cmd[IRC_MAX_ARGS];
     38        char *s;
     39        int k;
     40        char q = 0;
     41       
     42        memset( cmd, 0, sizeof( cmd ) );
     43        cmd[0] = command;
     44        k = 1;
     45        for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ )
     46                if( *s == ' ' && !q )
     47                {
     48                        *s = 0;
     49                        while( *++s == ' ' );
     50                        if( *s == '"' || *s == '\'' )
     51                        {
     52                                q = *s;
     53                                s ++;
     54                        }
     55                        if( *s )
     56                        {
     57                                cmd[k++] = s;
     58                                s --;
     59                        }
     60                        else
     61                        {
     62                                break;
     63                        }
     64                }
     65                else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
     66                {
     67                        char *cpy;
     68                       
     69                        for( cpy = s; *cpy; cpy ++ )
     70                                cpy[0] = cpy[1];
     71                }
     72                else if( *s == q )
     73                {
     74                        q = *s = 0;
     75                }
     76        cmd[k] = NULL;
     77       
     78        root_command( irc, cmd );
    3779}
    3880
     
    5193void root_command( irc_t *irc, char *cmd[] )
    5294{       
    53         int i, len;
     95        int i;
    5496       
    5597        if( !cmd[0] )
    5698                return;
    5799       
    58         len = strlen( cmd[0] );
    59100        for( i = 0; commands[i].command; i++ )
    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                        
     101                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
     102                {
    67103                        MIN_ARGS( commands[i].required_parameters );
    68104                       
     
    126162                irc->status |= USTATUS_IDENTIFIED;
    127163                irc_umode_set( irc, "+R", 1 );
    128                 if( set_getbool( &irc->b->set, "auto_connect" ) )
     164                if( set_getbool( &irc->set, "auto_connect" ) )
    129165                        cmd_account( irc, account_on );
    130166                break;
     
    166202        storage_status_t status;
    167203       
    168         status = storage_remove (irc->user->nick, cmd[1]);
     204        status = storage_remove (irc->nick, cmd[1]);
    169205        switch (status) {
    170206        case STORAGE_NO_SUCH_USER:
     
    178214                irc->status &= ~USTATUS_IDENTIFIED;
    179215                irc_umode_set( irc, "-R", 1 );
    180                 irc_usermsg( irc, "Account `%s' removed", irc->user->nick );
     216                irc_usermsg( irc, "Account `%s' removed", irc->nick );
    181217                break;
    182218        default:
     
    186222}
    187223
    188 static 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 
    198224struct cmd_account_del_data
    199225{
     
    207233        account_t *a;
    208234       
    209         for( a = cad->irc->b->accounts; a && a != cad->a; a = a->next );
     235        for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
    210236       
    211237        if( a == NULL )
     
    219245        else
    220246        {
    221                 account_del( cad->irc->b, a );
     247                account_del( cad->irc, a );
    222248                irc_usermsg( cad->irc, "Account deleted" );
    223249        }
     
    260286                set_name = set_full;
    261287               
    262                 head = &irc->b->set;
     288                head = &irc->set;
    263289        }
    264290        else
     
    331357        account_t *a;
    332358       
    333         if( ( a = account_get( irc->b, id ) ) )
     359        if( ( a = account_get( irc, id ) ) )
    334360                return &a->set;
    335361        else
     
    379405                }
    380406
    381                 a = account_add( irc->b, prpl, cmd[3], cmd[4] );
     407                a = account_add( irc, prpl, cmd[3], cmd[4] );
    382408                if( cmd[5] )
    383409                {
     
    393419                MIN_ARGS( 2 );
    394420
    395                 if( !( a = account_get( irc->b, cmd[2] ) ) )
     421                if( !( a = account_get( irc, cmd[2] ) ) )
    396422                {
    397423                        irc_usermsg( irc, "Invalid account" );
     
    415441                                               "set' command. Are you sure you want to delete this "
    416442                                               "account?", a->prpl->name, a->user );
    417                         //query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
     443                        query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
    418444                        g_free( msg );
    419445                }
     
    426452                        irc_usermsg( irc, "Account list:" );
    427453               
    428                 for( a = irc->b->accounts; a; a = a->next )
     454                for( a = irc->accounts; a; a = a->next )
    429455                {
    430456                        char *con;
     
    449475                if( cmd[2] )
    450476                {
    451                         if( ( a = account_get( irc->b, cmd[2] ) ) )
     477                        if( ( a = account_get( irc, cmd[2] ) ) )
    452478                        {
    453479                                if( a->ic )
     
    458484                                else
    459485                                {
    460                                         account_on( irc->b, a );
     486                                        account_on( irc, a );
    461487                                }
    462488                        }
     
    469495                else
    470496                {
    471                         if ( irc->b->accounts )
    472                         {
     497                        if ( irc->accounts ) {
    473498                                irc_usermsg( irc, "Trying to get all accounts connected..." );
    474499                       
    475                                 for( a = irc->b->accounts; a; a = a->next )
     500                                for( a = irc->accounts; a; a = a->next )
    476501                                        if( !a->ic && a->auto_connect )
    477                                                 account_on( irc->b, a );
     502                                                account_on( irc, a );
    478503                        }
    479504                        else
     
    489514                        irc_usermsg( irc, "Deactivating all active (re)connections..." );
    490515                       
    491                         for( a = irc->b->accounts; a; a = a->next )
     516                        for( a = irc->accounts; a; a = a->next )
    492517                        {
    493518                                if( a->ic )
    494                                         account_off( irc->b, a );
     519                                        account_off( irc, a );
    495520                                else if( a->reconnect )
    496521                                        cancel_auto_reconnect( a );
    497522                        }
    498523                }
    499                 else if( ( a = account_get( irc->b, cmd[2] ) ) )
     524                else if( ( a = account_get( irc, cmd[2] ) ) )
    500525                {
    501526                        if( a->ic )
    502527                        {
    503                                 account_off( irc->b, a );
     528                                account_off( irc, a );
    504529                        }
    505530                        else if( a->reconnect )
     
    544569        }
    545570       
    546         if( !( a = account_get( irc->b, cmd[1] ) ) )
     571        if( !( a = account_get( irc, cmd[1] ) ) )
    547572        {
    548573                irc_usermsg( irc, "Invalid account" );
     
    562587                        return;
    563588                }
    564                 else if( irc_user_by_name( irc, cmd[3] ) )
     589                else if( user_find( irc, cmd[3] ) )
    565590                {
    566591                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
     
    576601                a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
    577602        else
    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] );
     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 );
    581607       
    582608        irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
    583 }
    584 
    585 static 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;
    606609}
    607610
     
    613616        if( !cmd[2] )
    614617        {
    615                 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
    616                 if( !iu || !iu->bu )
     618                user_t *u = user_find( irc, cmd[1] );
     619                if( !u || !u->ic )
    617620                {
    618621                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    619622                        return;
    620623                }
    621                 ic = iu->bu->ic;
    622                 cmd[2] = iu->bu->handle;
    623         }
    624         else if( !( a = account_get( irc->b, cmd[1] ) ) )
     624                ic = u->ic;
     625                cmd[2] = u->handle;
     626        }
     627        else if( !( a = account_get( irc, cmd[1] ) ) )
    625628        {
    626629                irc_usermsg( irc, "Invalid account" );
     
    645648static void cmd_rename( irc_t *irc, char **cmd )
    646649{
    647         irc_user_t *iu;
    648        
    649         iu = irc_user_by_name( irc, cmd[1] );
    650        
    651         if( iu == NULL )
     650        user_t *u;
     651       
     652        if( g_strcasecmp( cmd[1], irc->nick ) == 0 )
     653        {
     654                irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
     655        }
     656        else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     657        {
     658                if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
     659                {
     660                        u = user_find( irc, irc->nick );
     661                       
     662                        irc_part( irc, u, irc->channel );
     663                        g_free( irc->channel );
     664                        irc->channel = g_strdup( cmd[2] );
     665                        irc_join( irc, u, irc->channel );
     666                       
     667                        if( strcmp( cmd[0], "set_rename" ) != 0 )
     668                                set_setstr( &irc->set, "control_channel", cmd[2] );
     669                }
     670        }
     671        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
     672        {
     673                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
     674        }
     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] ) ) )
    652680        {
    653681                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    654682        }
    655         else if( iu == irc->user )
    656         {
    657                 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    658         }
    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] ) )
    664         {
    665                 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
    666         }
    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                 {
     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                       
    677692                        /* If we're called internally (user did "set root_nick"),
    678693                           let's not go O(INF). :-) */
    679694                        if( strcmp( cmd[0], "set_rename" ) != 0 )
    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] );
     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] );
    685700                }
    686701               
     
    689704}
    690705
    691 #if 0
    692706char *set_eval_root_nick( set_t *set, char *new_nick )
    693707{
     
    716730       
    717731        return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
     732}
     733
     734static 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;
    718754}
    719755
     
    836872        }
    837873}
    838 #endif
    839874
    840875static void cmd_yesno( irc_t *irc, char **cmd )
     
    881916}
    882917
    883 #if 0
     918static 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
    884928static void cmd_blist( irc_t *irc, char **cmd )
    885929{
     
    947991}
    948992
     993static 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
    9491021static void cmd_qlist( irc_t *irc, char **cmd )
    9501022{
     
    9651037                else
    9661038                        irc_usermsg( irc, "%d, BitlBee: %s", num, q->question );
     1039}
     1040
     1041static 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." );
    9671045}
    9681046
     
    10791157}
    10801158
    1081 static 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. */
    11451159const command_t commands[] = {
     1160        { "help",           0, cmd_help,           0 },
     1161        { "identify",       1, cmd_identify,       0 },
     1162        { "register",       1, cmd_register,       0 },
     1163        { "drop",           1, cmd_drop,           0 },
    11461164        { "account",        1, cmd_account,        0 },
    11471165        { "add",            2, cmd_add,            0 },
    1148         { "drop",           1, cmd_drop,           0 },
    1149         { "help",           0, cmd_help,           0 },
    1150         { "identify",       1, cmd_identify,       0 },
    11511166        { "info",           1, cmd_info,           0 },
    1152         { "no",             0, cmd_yesno,          0 },
    1153         { "register",       1, cmd_register,       0 },
     1167        { "rename",         2, cmd_rename,         0 },
    11541168        { "remove",         1, cmd_remove,         0 },
    1155         { "rename",         2, cmd_rename,         0 },
     1169        { "block",          1, cmd_block,          0 },
     1170        { "allow",          1, cmd_allow,          0 },
    11561171        { "save",           0, cmd_save,           0 },
    11571172        { "set",            0, cmd_set,            0 },
    11581173        { "yes",            0, cmd_yesno,          0 },
    1159 #if 0
    1160         { "allow",          1, cmd_allow,          0 },
     1174        { "no",             0, cmd_yesno,          0 },
    11611175        { "blist",          0, cmd_blist,          0 },
    1162         { "block",          1, cmd_block,          0 },
     1176        { "nick",           1, cmd_nick,           0 },
     1177        { "qlist",          0, cmd_qlist,          0 },
     1178        { "join_chat",      2, cmd_join_chat,      0 },
    11631179        { "chat",           1, cmd_chat,           0 },
    1164         { "ft",             0, cmd_transfer,       0 },
    1165         { "join_chat",      2, cmd_join_chat,      0 },
    1166         { "qlist",          0, cmd_qlist,          0 },
    1167         { "transfer",       0, cmd_transfer,       0 },
    1168 #endif
    11691180        { NULL }
    11701181};
  • set.c

    r21c87a7 r156bbd7  
    225225}
    226226
    227 /*
    228227char *set_eval_ops( set_t *set, char *value )
    229228{
     
    247246        return value;
    248247}
    249 */
  • storage.c

    r21c87a7 r156bbd7  
    2828#define BITLBEE_CORE
    2929#include "bitlbee.h"
     30#include "crypting.h"
    3031
    3132extern storage_t storage_text;
     
    6566        storage_t *storage;
    6667       
     68        register_storage_backend(&storage_text);
    6769        register_storage_backend(&storage_xml);
    6870       
  • storage_xml.c

    r21c87a7 r156bbd7  
    147147                                         arc_decode( pass_cr, pass_len, &password, xd->given_pass ) )
    148148                {
    149                         xd->current_account = account_add( irc->b, prpl, handle, password );
     149                        xd->current_account = account_add( irc, 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->b->set;
     183                                xd->current_set_head = &xd->irc->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->user->nick, password, XML_PASS_UNKNOWN );
     355        return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN );
    356356}
    357357
     
    396396        md5_state_t md5_state;
    397397       
    398         path2 = g_strdup( irc->user->nick );
     398        path2 = g_strdup( irc->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->user->nick, pass_buf, XML_FORMAT_VERSION ) )
     424        if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )
    425425                goto write_error;
    426426       
    427427        g_free( pass_buf );
    428428       
    429         for( set = irc->b->set; set; set = set->next )
     429        for( set = irc->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->b->accounts; acc; acc = acc->next )
     434        for( acc = irc->accounts; acc; acc = acc->next )
    435435        {
    436436                unsigned char *pass_cr;
     
    470470                        goto write_error;
    471471               
    472 #if 0
    473472                for( c = irc->chatrooms; c; c = c->next )
    474473                {
     
    489488                                goto write_error;
    490489                }
    491 #endif
    492490               
    493491                if( !xml_printf( fd, 1, "</account>\n" ) )
  • win32.c

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