Changeset 3ddb7477


Ignore:
Timestamp:
2010-03-26T12:14:37Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
ebaebfe
Parents:
ba7d16f
Message:

One total mess that doesn't do much yet, but reorganised some stuff and
untying the IRC and the core parts a little bit. Lots of work left to do.

Files:
11 edited
6 moved

Legend:

Unmodified
Added
Removed
  • Makefile

    rba7d16f r3ddb7477  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o chat.o dcc.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
     12#objects = bitlbee.o chat.o dcc.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS)
     13objects = bitlbee.o help.o ipc.o irc.o irc_commands.o irc_send.o irc_user.o nick.o set.o
    1314headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h
    1415subdirs = lib protocols
  • bitlbee.h

    rba7d16f r3ddb7477  
    124124#define CONF_FILE_DEF ETCDIR "bitlbee.conf"
    125125
     126#include "bee.h"
    126127#include "irc.h"
    127128#include "storage.h"
     
    158159gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond );
    159160
    160 void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
     161//void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
    161162void root_command( irc_t *irc, char *command[] );
    162163gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
  • conf.c

    rba7d16f r3ddb7477  
    369369                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
    370370                {
    371                         set_t *s = set_find( &irc->set, ini->key );
     371                        set_t *s = set_find( &irc->b->set, ini->key );
    372372                       
    373373                        if( s )
  • ipc.c

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

    rba7d16f r3ddb7477  
    55  \********************************************************************/
    66
    7 /* The big hairy IRCd part of the project                               */
     7/* The IRC-based UI (for now the only one)                              */
    88
    99/*
     
    2424*/
    2525
    26 #define BITLBEE_CORE
    2726#include "bitlbee.h"
    28 #include "sock.h"
    29 #include "ipc.h"
    30 #include "dcc.h"
    31 
    32 static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
    33 
    34 GSList *irc_connection_list = NULL;
    35 
    36 static char *set_eval_password( set_t *set, char *value )
    37 {
    38         irc_t *irc = set->data;
    39        
    40         if( irc->status & USTATUS_IDENTIFIED && value )
    41         {
    42                 irc_setpass( irc, value );
    43                 return NULL;
    44         }
    45         else
    46         {
    47                 return SET_INVALID;
    48         }
    49 }
    50 
    51 static char *set_eval_charset( set_t *set, char *value )
    52 {
    53         irc_t *irc = set->data;
    54         GIConv ic, oc;
    55 
    56         if( g_strcasecmp( value, "none" ) == 0 )
    57                 value = g_strdup( "utf-8" );
    58 
    59         if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    60         {
    61                 return NULL;
    62         }
    63         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    64         {
    65                 g_iconv_close( ic );
    66                 return NULL;
    67         }
    68        
    69         if( irc->iconv != (GIConv) -1 )
    70                 g_iconv_close( irc->iconv );
    71         if( irc->oconv != (GIConv) -1 )
    72                 g_iconv_close( irc->oconv );
    73        
    74         irc->iconv = ic;
    75         irc->oconv = oc;
    76 
    77         return value;
    78 }
    79 
    80 static char *set_eval_away_status( set_t *set, char *value )
    81 {
    82         irc_t *irc = set->data;
    83         account_t *a;
    84        
    85         g_free( set->value );
    86         set->value = g_strdup( value );
    87        
    88         for( a = irc->accounts; a; a = a->next )
    89         {
    90                 struct im_connection *ic = a->ic;
    91                
    92                 if( ic && ic->flags & OPT_LOGGED_IN )
    93                         imc_away_send_update( ic );
    94         }
    95        
    96         return value;
    97 }
     27
     28GSList *irc_connection_list;
     29
     30static char *set_eval_charset( set_t *set, char *value );
    9831
    9932irc_t *irc_new( int fd )
     
    10235        struct sockaddr_storage sock;
    10336        socklen_t socklen = sizeof( sock );
     37        char *host = NULL, *myhost = NULL;
     38        irc_user_t *iu;
    10439        set_t *s;
     40        bee_t *b;
    10541       
    10642        irc = g_new0( irc_t, 1 );
     
    11450        irc->last_pong = gettime();
    11551       
    116         irc->userhash = g_hash_table_new( g_str_hash, g_str_equal );
     52        irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );
    11753        irc->watches = g_hash_table_new( g_str_hash, g_str_equal );
    11854       
    11955        strcpy( irc->umode, UMODE );
    120         irc->mynick = g_strdup( ROOT_NICK );
    121         irc->channel = g_strdup( ROOT_CHAN );
    12256       
    12357        irc->iconv = (GIConv) -1;
     
    12660        if( global.conf->hostname )
    12761        {
    128                 irc->myhost = g_strdup( global.conf->hostname );
     62                myhost = g_strdup( global.conf->hostname );
    12963        }
    13064        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     
    13569                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    13670                {
    137                         irc->myhost = g_strdup( ipv6_unwrap( buf ) );
     71                        myhost = g_strdup( ipv6_unwrap( buf ) );
    13872                }
    13973        }
     
    14680                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    14781                {
    148                         irc->host = g_strdup( ipv6_unwrap( buf ) );
    149                 }
    150         }
    151        
    152         if( irc->host == NULL )
    153                 irc->host = g_strdup( "localhost.localdomain" );
    154         if( irc->myhost == NULL )
    155                 irc->myhost = g_strdup( "localhost.localdomain" );
    156        
    157         if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
    158                 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
    159        
    160         irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );
     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" );
     90       
     91        //if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
     92        //      irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
    16193
    16294        irc_connection_list = g_slist_append( irc_connection_list, irc );
    16395       
    164         s = set_add( &irc->set, "away", NULL,  set_eval_away_status, irc );
    165         s->flags |= SET_NULL_OK;
    166         s = set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
    167         s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
    168         s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc );
    169         s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
    170         s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
    171         s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
    172         s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
    173         s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc );
    174         s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
    175         s = set_add( &irc->set, "default_target", "root", NULL, irc );
    176         s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
    177         s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
    178         s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
    179         s = set_add( &irc->set, "ops", "both", set_eval_ops, irc );
    180         s = set_add( &irc->set, "password", NULL, set_eval_password, irc );
    181         s->flags |= SET_NULL_OK;
    182         s = set_add( &irc->set, "private", "true", set_eval_bool, irc );
    183         s = set_add( &irc->set, "query_order", "lifo", NULL, irc );
    184         s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    185         s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    186         s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
    187         s = set_add( &irc->set, "status", NULL,  set_eval_away_status, irc );
    188         s->flags |= SET_NULL_OK;
    189         s = set_add( &irc->set, "strip_html", "true", NULL, irc );
    190         s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
    191         s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
    192        
    193         conf_loaddefaults( irc );
     96        b = irc->b = bee_new();
     97       
     98        s = set_add( &b->set, "away_devoice", "true", NULL/*set_eval_away_devoice*/, irc );
     99        s = set_add( &b->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
     100        s = set_add( &b->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
     101        s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc );
     102        //s = set_add( &b->set, "control_channel", irc->channel, NULL/*set_eval_control_channel*/, irc );
     103        s = set_add( &b->set, "default_target", "root", NULL, irc );
     104        s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc );
     105        s = set_add( &b->set, "handle_unknown", "root", NULL, irc );
     106        s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
     107        s = set_add( &b->set, "ops", "both", NULL/*set_eval_ops*/, irc );
     108        s = set_add( &b->set, "private", "true", set_eval_bool, irc );
     109        s = set_add( &b->set, "query_order", "lifo", NULL, irc );
     110        s = set_add( &b->set, "root_nick", ROOT_NICK, NULL/*set_eval_root_nick*/, irc );
     111        s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc );
     112        s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc );
     113        s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc );
     114
     115        irc->root = iu = irc_user_new( irc, ROOT_NICK );
     116        iu->host = g_strdup( myhost );
     117        iu->fullname = g_strdup( ROOT_FN );
     118       
     119        iu = irc_user_new( irc, NS_NICK );
     120        iu->host = g_strdup( myhost );
     121        iu->fullname = g_strdup( ROOT_FN );
     122       
     123        irc->user = g_new0( irc_user_t, 1 );
     124        irc->user->host = g_strdup( host );
     125       
     126        conf_loaddefaults( b );
    194127       
    195128        /* Evaluator sets the iconv/oconv structures. */
    196         set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
    197        
    198         return( irc );
     129        set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) );
     130       
     131        irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" );
     132       
     133        return irc;
    199134}
    200135
     
    217152               
    218153                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    219                                    irc->nick ? irc->nick : "(NONE)", irc->host, reason );
     154                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );
    220155               
    221156                g_free( reason );
     
    227162               
    228163                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    229                                    irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" );
     164                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );
    230165        }
    231166       
     
    248183}
    249184
    250 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
    251 {
    252         g_free( key );
    253        
    254         return( TRUE );
    255 }
    256 
    257 /* Because we have no garbage collection, this is quite annoying */
     185static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data );
     186
    258187void irc_free( irc_t * irc )
    259188{
    260         user_t *user, *usertmp;
    261        
    262189        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
    263190       
    264         if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )
     191        /*
     192        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) )
    265193                if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )
    266194                        irc_usermsg( irc, "Error while saving settings!" );
     195        */
    267196       
    268197        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    269198       
    270         while( irc->accounts )
    271         {
    272                 if( irc->accounts->ic )
    273                         imc_logout( irc->accounts->ic, FALSE );
    274                 else if( irc->accounts->reconnect )
    275                         cancel_auto_reconnect( irc->accounts );
    276                
    277                 if( irc->accounts->ic == NULL )
    278                         account_del( irc, irc->accounts );
    279                 else
    280                         /* Nasty hack, but account_del() doesn't work in this
    281                            case and we don't want infinite loops, do we? ;-) */
    282                         irc->accounts = irc->accounts->next;
    283         }
    284        
     199        /*
    285200        while( irc->queries != NULL )
    286201                query_del( irc, irc->queries );
    287        
    288         while( irc->set )
    289                 set_del( &irc->set, irc->set->key );
    290        
    291         if (irc->users != NULL)
    292         {
    293                 user = irc->users;
    294                 while( user != NULL )
    295                 {
    296                         g_free( user->nick );
    297                         g_free( user->away );
    298                         g_free( user->handle );
    299                         if( user->user != user->nick ) g_free( user->user );
    300                         if( user->host != user->nick ) g_free( user->host );
    301                         if( user->realname != user->nick ) g_free( user->realname );
    302                         b_event_remove( user->sendbuf_timer );
    303                                        
    304                         usertmp = user;
    305                         user = user->next;
    306                         g_free( usertmp );
    307                 }
    308         }
     202        */
     203       
     204        while( irc->users )
     205                irc_user_free( irc, irc->users->data );
    309206       
    310207        if( irc->ping_source_id > 0 )
     
    318215        irc->fd = -1;
    319216       
    320         g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
    321         g_hash_table_destroy( irc->userhash );
     217        g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL );
     218        g_hash_table_destroy( irc->nick_user_hash );
    322219       
    323220        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     
    332229        g_free( irc->readbuffer );
    333230       
    334         g_free( irc->nick );
    335         g_free( irc->user );
    336         g_free( irc->host );
    337         g_free( irc->realname );
    338231        g_free( irc->password );
    339        
    340         g_free( irc->myhost );
    341         g_free( irc->mynick );
    342        
    343         g_free( irc->channel );
    344        
    345         g_free( irc->last_target );
    346232       
    347233        g_free( irc );
     
    355241}
    356242
    357 /* USE WITH CAUTION!
    358    Sets pass without checking */
    359 void irc_setpass (irc_t *irc, const char *pass)
    360 {
    361         g_free (irc->password);
    362        
    363         if (pass) {
    364                 irc->password = g_strdup (pass);
    365         } else {
    366                 irc->password = NULL;
    367         }
    368 }
     243static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
     244{
     245        g_free( key );
     246       
     247        return( TRUE );
     248}
     249
     250static char **irc_splitlines( char *buffer );
    369251
    370252void irc_process( irc_t *irc )
     
    375257        if( irc->readbuffer != NULL )
    376258        {
    377                 lines = irc_tokenize( irc->readbuffer );
     259                lines = irc_splitlines( irc->readbuffer );
    378260               
    379261                for( i = 0; *lines[i] != '\0'; i ++ )
     
    412294                                                                  "`help set charset' for more information. Your "
    413295                                                                  "message was ignored.",
    414                                                                   set_getstr( &irc->set, "charset" ) );
     296                                                                  set_getstr( &irc->b->set, "charset" ) );
    415297                                               
    416298                                                g_free( conv );
     
    419301                                        else
    420302                                        {
    421                                                 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
     303                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host,
    422304                                                           "Warning: invalid characters received at login time." );
    423305                                               
     
    457339}
    458340
    459 /* Splits a long string into separate lines. The array is NULL-terminated and, unless the string
    460    contains an incomplete line at the end, ends with an empty string. */
    461 char **irc_tokenize( char *buffer )
     341/* Splits a long string into separate lines. The array is NULL-terminated
     342   and, unless the string contains an incomplete line at the end, ends with
     343   an empty string. Could use g_strsplit() but this one does it in-place.
     344   (So yes, it's destructive.) */
     345static char **irc_splitlines( char *buffer )
    462346{
    463347        int i, j, n = 3;
     
    590474}
    591475
    592 void irc_reply( irc_t *irc, int code, char *format, ... )
    593 {
    594         char text[IRC_MAX_LINE];
    595         va_list params;
    596        
    597         va_start( params, format );
    598         g_vsnprintf( text, IRC_MAX_LINE, format, params );
    599         va_end( params );
    600         irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );
    601        
    602         return;
    603 }
    604 
    605 int irc_usermsg( irc_t *irc, char *format, ... )
    606 {
    607         char text[1024];
    608         va_list params;
    609         char is_private = 0;
    610         user_t *u;
    611        
    612         u = user_find( irc, irc->mynick );
    613         is_private = u->is_private;
    614        
    615         va_start( params, format );
    616         g_vsnprintf( text, sizeof( text ), format, params );
    617         va_end( params );
    618        
    619         return( irc_msgfrom( irc, u->nick, text ) );
    620 }
    621 
    622476void irc_write( irc_t *irc, char *format, ... )
    623477{
     
    630484        return;
    631485}
     486
     487void irc_write_all( int now, char *format, ... )
     488{
     489        va_list params;
     490        GSList *temp;   
     491       
     492        va_start( params, format );
     493       
     494        temp = irc_connection_list;
     495        while( temp != NULL )
     496        {
     497                irc_t *irc = temp->data;
     498               
     499                if( now )
     500                {
     501                        g_free( irc->sendbuffer );
     502                        irc->sendbuffer = g_strdup( "\r\n" );
     503                }
     504                irc_vawrite( temp->data, format, params );
     505                if( now )
     506                {
     507                        bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
     508                }
     509                temp = temp->next;
     510        }
     511       
     512        va_end( params );
     513        return;
     514}
    632515
    633516void irc_vawrite( irc_t *irc, char *format, va_list params )
     
    686569}
    687570
    688 void irc_write_all( int now, char *format, ... )
    689 {
    690         va_list params;
    691         GSList *temp;   
    692        
    693         va_start( params, format );
    694        
    695         temp = irc_connection_list;
    696         while( temp != NULL )
    697         {
    698                 irc_t *irc = temp->data;
    699                
    700                 if( now )
    701                 {
    702                         g_free( irc->sendbuffer );
    703                         irc->sendbuffer = g_strdup( "\r\n" );
    704                 }
    705                 irc_vawrite( temp->data, format, params );
    706                 if( now )
    707                 {
    708                         bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
    709                 }
    710                 temp = temp->next;
    711         }
    712        
    713         va_end( params );
    714         return;
    715 }
    716 
    717 void irc_names( irc_t *irc, char *channel )
    718 {
    719         user_t *u;
    720         char namelist[385] = "";
    721         struct groupchat *c = NULL;
    722         char *ops = set_getstr( &irc->set, "ops" );
    723        
    724         /* RFCs say there is no error reply allowed on NAMES, so when the
    725            channel is invalid, just give an empty reply. */
    726        
    727         if( g_strcasecmp( channel, irc->channel ) == 0 )
    728         {
    729                 for( u = irc->users; u; u = u->next ) if( u->online )
    730                 {
    731                         if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
    732                         {
    733                                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    734                                 *namelist = 0;
    735                         }
    736                        
    737                         if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
    738                                 strcat( namelist, "+" );
    739                         else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
    740                                  ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
    741                                 strcat( namelist, "@" );
    742                        
    743                         strcat( namelist, u->nick );
    744                         strcat( namelist, " " );
    745                 }
    746         }
    747         else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    748         {
    749                 GList *l;
    750                
    751                 /* root and the user aren't in the channel userlist but should
    752                    show up in /NAMES, so list them first: */
    753                 sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,
    754                                                  strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );
    755                
    756                 for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )
    757                 {
    758                         if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
    759                         {
    760                                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    761                                 *namelist = 0;
    762                         }
    763                        
    764                         strcat( namelist, u->nick );
    765                         strcat( namelist, " " );
    766                 }
    767         }
    768        
    769         if( *namelist )
    770                 irc_reply( irc, 353, "= %s :%s", channel, namelist );
    771        
    772         irc_reply( irc, 366, "%s :End of /NAMES list", channel );
    773 }
    774 
    775571int irc_check_login( irc_t *irc )
    776572{
    777         if( irc->user && irc->nick )
     573        if( irc->user->user && irc->user->nick )
    778574        {
    779575                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
    780576                {
    781                         irc_reply( irc, 464, ":This server is password-protected." );
     577                        irc_send_num( irc, 464, ":This server is password-protected." );
    782578                        return 0;
    783579                }
    784580                else
    785581                {
    786                         irc_login( irc );
     582                        irc_send_login( irc );
    787583                        return 1;
    788584                }
     
    795591}
    796592
    797 void irc_login( irc_t *irc )
    798 {
    799         user_t *u;
    800        
    801         irc_reply( irc,   1, ":Welcome to the BitlBee gateway, %s", irc->nick );
    802         irc_reply( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost );
    803         irc_reply( irc,   3, ":%s", IRCD_INFO );
    804         irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
    805         irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee "
    806                              "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server",
    807                              CTYPES, CMODES, MAX_NICK_LENGTH - 1 );
    808         irc_motd( irc );
    809         irc->umode[0] = '\0';
    810         irc_umode_set( irc, "+" UMODE, 1 );
    811 
    812         u = user_add( irc, irc->mynick );
    813         u->host = g_strdup( irc->myhost );
    814         u->realname = g_strdup( ROOT_FN );
    815         u->online = 1;
    816         u->send_handler = root_command_string;
    817         u->is_private = 0; /* [SH] The channel is root's personal playground. */
    818         irc_spawn( irc, u );
    819        
    820         u = user_add( irc, NS_NICK );
    821         u->host = g_strdup( irc->myhost );
    822         u->realname = g_strdup( ROOT_FN );
    823         u->online = 0;
    824         u->send_handler = root_command_string;
    825         u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */
    826        
    827         u = user_add( irc, irc->nick );
    828         u->user = g_strdup( irc->user );
    829         u->host = g_strdup( irc->host );
    830         u->realname = g_strdup( irc->realname );
    831         u->online = 1;
    832         irc_spawn( irc, u );
    833        
    834         irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
    835                           "If you've never used BitlBee before, please do read the help "
    836                           "information using the \x02help\x02 command. Lots of FAQs are "
    837                           "answered there.\n"
    838                           "If you already have an account on this server, just use the "
    839                           "\x02identify\x02 command to identify yourself." );
    840        
    841         if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
    842                 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    843        
    844         irc->status |= USTATUS_LOGGED_IN;
    845        
    846         /* This is for bug #209 (use PASS to identify to NickServ). */
    847         if( irc->password != NULL )
    848         {
    849                 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
    850                
    851                 irc_setpass( irc, NULL );
    852                 root_command( irc, send_cmd );
    853                 g_free( send_cmd[1] );
    854         }
    855 }
    856 
    857 void irc_motd( irc_t *irc )
    858 {
    859         int fd;
    860        
    861         fd = open( global.conf->motdfile, O_RDONLY );
    862         if( fd == -1 )
    863         {
    864                 irc_reply( irc, 422, ":We don't need MOTDs." );
    865         }
    866         else
    867         {
    868                 char linebuf[80];       /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */
    869                 char *add, max;
    870                 int len;
    871                
    872                 linebuf[79] = len = 0;
    873                 max = sizeof( linebuf ) - 1;
    874                
    875                 irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost );
    876                 while( read( fd, linebuf + len, 1 ) == 1 )
    877                 {
    878                         if( linebuf[len] == '\n' || len == max )
    879                         {
    880                                 linebuf[len] = 0;
    881                                 irc_reply( irc, 372, ":- %s", linebuf );
    882                                 len = 0;
    883                         }
    884                         else if( linebuf[len] == '%' )
    885                         {
    886                                 read( fd, linebuf + len, 1 );
    887                                 if( linebuf[len] == 'h' )
    888                                         add = irc->myhost;
    889                                 else if( linebuf[len] == 'v' )
    890                                         add = BITLBEE_VERSION;
    891                                 else if( linebuf[len] == 'n' )
    892                                         add = irc->nick;
    893                                 else
    894                                         add = "%";
    895                                
    896                                 strncpy( linebuf + len, add, max - len );
    897                                 while( linebuf[++len] );
    898                         }
    899                         else if( len < max )
    900                         {
    901                                 len ++;
    902                         }
    903                 }
    904                 irc_reply( irc, 376, ":End of MOTD" );
    905                 close( fd );
    906         }
    907 }
    908 
    909 void irc_topic( irc_t *irc, char *channel )
    910 {
    911         struct groupchat *c = irc_chat_by_channel( irc, channel );
    912        
    913         if( c && c->topic )
    914                 irc_reply( irc, 332, "%s :%s", channel, c->topic );
    915         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    916                 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC );
    917         else
    918                 irc_reply( irc, 331, "%s :No topic for this channel", channel );
    919 }
    920 
    921 void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    922 {
    923         /* allow_priv: Set to 0 if s contains user input, 1 if you want
    924            to set a "privileged" mode (+o, +R, etc). */
    925         char m[256], st = 1, *t;
    926         int i;
    927         char changes[512], *p, st2 = 2;
    928         char badflag = 0;
    929        
    930         memset( m, 0, sizeof( m ) );
    931        
    932         for( t = irc->umode; *t; t ++ )
    933                 m[(int)*t] = 1;
    934 
    935         p = changes;
    936         for( t = s; *t; t ++ )
    937         {
    938                 if( *t == '+' || *t == '-' )
    939                         st = *t == '+';
    940                 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) )
    941                 {
    942                         if( m[(int)*t] != st)
    943                         {
    944                                 if( st != st2 )
    945                                         st2 = st, *p++ = st ? '+' : '-';
    946                                 *p++ = *t;
    947                         }
    948                         m[(int)*t] = st;
    949                 }
    950                 else
    951                         badflag = 1;
    952         }
    953         *p = '\0';
    954        
    955         memset( irc->umode, 0, sizeof( irc->umode ) );
    956        
    957         for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
    958                 if( m[i] )
    959                         irc->umode[strlen(irc->umode)] = i;
    960        
    961         if( badflag )
    962                 irc_reply( irc, 501, ":Unknown MODE flag" );
    963         /* Deliberately no !user@host on the prefix here */
    964         if( *changes )
    965                 irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes );
    966 }
    967 
    968 void irc_spawn( irc_t *irc, user_t *u )
    969 {
    970         irc_join( irc, u, irc->channel );
    971 }
    972 
    973 void irc_join( irc_t *irc, user_t *u, char *channel )
    974 {
    975         char *nick;
    976        
    977         if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) )
    978                 irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel );
    979        
    980         if( nick_cmp( u->nick, irc->nick ) == 0 )
    981         {
    982                 irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE );
    983                 irc_names( irc, channel );
    984                 irc_topic( irc, channel );
    985         }
    986        
    987         nick = g_strdup( u->nick );
    988         nick_lc( nick );
    989         if( g_hash_table_lookup( irc->watches, nick ) )
    990         {
    991                 irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" );
    992         }
    993         g_free( nick );
    994 }
    995 
    996 void irc_part( irc_t *irc, user_t *u, char *channel )
    997 {
    998         irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" );
    999 }
    1000 
    1001 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker )
    1002 {
    1003         irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" );
    1004 }
    1005 
    1006 void irc_kill( irc_t *irc, user_t *u )
    1007 {
    1008         char *nick, *s;
    1009         char reason[128];
    1010        
    1011         if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) )
    1012         {
    1013                 if( u->ic->acc->server )
    1014                         g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
    1015                                     u->ic->acc->server );
    1016                 else if( ( s = strchr( u->ic->acc->user, '@' ) ) )
    1017                         g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
    1018                                     s + 1 );
    1019                 else
    1020                         g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
    1021                                     u->ic->acc->prpl->name, irc->myhost );
    1022                
    1023                 /* proto_opt might contain garbage after the : */
    1024                 if( ( s = strchr( reason, ':' ) ) )
    1025                         *s = 0;
    1026         }
    1027         else
    1028         {
    1029                 strcpy( reason, "Leaving..." );
    1030         }
    1031        
    1032         irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
    1033        
    1034         nick = g_strdup( u->nick );
    1035         nick_lc( nick );
    1036         if( g_hash_table_lookup( irc->watches, nick ) )
    1037         {
    1038                 irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" );
    1039         }
    1040         g_free( nick );
    1041 }
    1042 
    1043 int irc_send( irc_t *irc, char *nick, char *s, int flags )
    1044 {
    1045         struct groupchat *c = NULL;
    1046         user_t *u = NULL;
    1047        
    1048         if( strchr( CTYPES, *nick ) )
    1049         {
    1050                 if( !( c = irc_chat_by_channel( irc, nick ) ) )
    1051                 {
    1052                         irc_reply( irc, 403, "%s :Channel does not exist", nick );
    1053                         return( 0 );
    1054                 }
    1055         }
    1056         else
    1057         {
    1058                 u = user_find( irc, nick );
    1059                
    1060                 if( !u )
    1061                 {
    1062                         if( irc->is_private )
    1063                                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1064                         else
    1065                                 irc_usermsg( irc, "Nick `%s' does not exist!", nick );
    1066                         return( 0 );
    1067                 }
    1068         }
    1069        
    1070         if( *s == 1 && s[strlen(s)-1] == 1 )
    1071         {
    1072                 if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 )
    1073                 {
    1074                         if( s[7] == ' ' ) s ++;
    1075                         s += 3;
    1076                         *(s++) = '/';
    1077                         *(s++) = 'm';
    1078                         *(s++) = 'e';
    1079                         *(s++) = ' ';
    1080                         s -= 4;
    1081                         s[strlen(s)-1] = 0;
    1082                 }
    1083                 else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 )
    1084                 {
    1085                         u = user_find( irc, irc->mynick );
    1086                         irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" );
    1087                         return( 1 );
    1088                 }
    1089                 else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 )
    1090                 {
    1091                         u = user_find( irc, irc->mynick );
    1092                         irc_privmsg( irc, u, "NOTICE", irc->nick, "", s );
    1093                         return( 1 );
    1094                 }
    1095                 else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 )
    1096                 {
    1097                         if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 )
    1098                         {
    1099                                 time_t current_typing_notice = time( NULL );
    1100                                
    1101                                 if( current_typing_notice - u->last_typing_notice >= 5 )
    1102                                 {
    1103                                         u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 );
    1104                                         u->last_typing_notice = current_typing_notice;
    1105                                 }
    1106                         }
    1107                         return( 1 );
    1108                 }
    1109                 else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
    1110                 {
    1111                         if( u && u->ic && u->ic->acc->prpl->transfer_request )
    1112                         {
    1113                                 file_transfer_t *ft = dcc_request( u->ic, s + 5 );
    1114                                 if ( ft )
    1115                                         u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
    1116                         }
    1117                         return( 1 );
    1118                 }               
    1119                 else
    1120                 {
    1121                         irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
    1122                         return( 0 );
    1123                 }
    1124         }
    1125        
    1126         if( u )
    1127         {
    1128                 /* For the next message, we probably do have to send new notices... */
    1129                 u->last_typing_notice = 0;
    1130                 u->is_private = irc->is_private;
    1131                
    1132                 if( u->is_private )
    1133                 {
    1134                         if( !u->online )
    1135                                 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1136                         else if( u->away )
    1137                                 irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1138                 }
    1139                
    1140                 if( u->send_handler )
    1141                 {
    1142                         u->send_handler( irc, u, s, flags );
    1143                         return 1;
    1144                 }
    1145         }
    1146         else if( c && c->ic && c->ic->acc && c->ic->acc->prpl )
    1147         {
    1148                 return( imc_chat_msg( c, s, 0 ) );
    1149         }
    1150        
    1151         return( 0 );
    1152 }
    1153 
    1154 static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond )
    1155 {
    1156         user_t *u = data;
    1157        
    1158         /* Shouldn't happen, but just to be sure. */
    1159         if( u->sendbuf_len < 2 )
    1160                 return FALSE;
    1161        
    1162         u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */
    1163         imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags );
    1164        
    1165         g_free( u->sendbuf );
    1166         u->sendbuf = NULL;
    1167         u->sendbuf_len = 0;
    1168         u->sendbuf_timer = 0;
    1169         u->sendbuf_flags = 0;
    1170        
    1171         return FALSE;
    1172 }
    1173 
    1174 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
    1175 {
    1176         if( !u || !u->ic ) return;
    1177        
    1178         if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 )
    1179         {
    1180                 int delay;
    1181                
    1182                 if( u->sendbuf_len > 0 && u->sendbuf_flags != flags)
    1183                 {
    1184                         /* Flush the buffer */
    1185                         b_event_remove( u->sendbuf_timer );
    1186                         buddy_send_handler_delayed( u, -1, 0 );
    1187                 }
    1188 
    1189                 if( u->sendbuf_len == 0 )
    1190                 {
    1191                         u->sendbuf_len = strlen( msg ) + 2;
    1192                         u->sendbuf = g_new( char, u->sendbuf_len );
    1193                         u->sendbuf[0] = 0;
    1194                         u->sendbuf_flags = flags;
    1195                 }
    1196                 else
    1197                 {
    1198                         u->sendbuf_len += strlen( msg ) + 1;
    1199                         u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len );
    1200                 }
    1201                
    1202                 strcat( u->sendbuf, msg );
    1203                 strcat( u->sendbuf, "\n" );
    1204                
    1205                 delay = set_getint( &irc->set, "buddy_sendbuffer_delay" );
    1206                 if( delay <= 5 )
    1207                         delay *= 1000;
    1208                
    1209                 if( u->sendbuf_timer > 0 )
    1210                         b_event_remove( u->sendbuf_timer );
    1211                 u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u );
    1212         }
    1213         else
    1214         {
    1215                 imc_buddy_msg( u->ic, u->handle, msg, flags );
    1216         }
    1217 }
    1218 
    1219 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg )
    1220 {
    1221         char last = 0;
    1222         char *s = msg, *line = msg;
    1223        
    1224         /* The almighty linesplitter .. woohoo!! */
    1225         while( !last )
    1226         {
    1227                 if( *s == '\r' && *(s+1) == '\n' )
    1228                         *(s++) = 0;
    1229                 if( *s == '\n' )
    1230                 {
    1231                         last = s[1] == 0;
    1232                         *s = 0;
    1233                 }
    1234                 else
    1235                 {
    1236                         last = s[0] == 0;
    1237                 }
    1238                 if( *s == 0 )
    1239                 {
    1240                         if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 )
    1241                         {
    1242                                 irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host,
    1243                                            type, to, line + 4 );
    1244                         }
    1245                         else
    1246                         {
    1247                                 irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host,
    1248                                            type, to, prefix ? prefix : "", line );
    1249                         }
    1250                         line = s + 1;
    1251                 }
    1252                 s ++;
    1253         }
    1254        
    1255         return( 1 );
    1256 }
    1257 
    1258 int irc_msgfrom( irc_t *irc, char *nick, char *msg )
    1259 {
    1260         user_t *u = user_find( irc, nick );
    1261         static char *prefix = NULL;
    1262        
    1263         if( !u ) return( 0 );
    1264         if( prefix && *prefix ) g_free( prefix );
    1265        
    1266         if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 )
    1267         {
    1268                 int len = strlen( irc->nick) + 3;
    1269                 prefix = g_new (char, len );
    1270                 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) );
    1271                 prefix[len-1] = 0;
    1272         }
    1273         else
    1274         {
    1275                 prefix = "";
    1276         }
    1277        
    1278         return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) );
    1279 }
    1280 
    1281 int irc_noticefrom( irc_t *irc, char *nick, char *msg )
    1282 {
    1283         user_t *u = user_find( irc, nick );
    1284        
    1285         if( u )
    1286                 return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) );
    1287         else
    1288                 return( 0 );
    1289 }
    1290 
    1291 /* Returns 0 if everything seems to be okay, a number >0 when there was a
    1292    timeout. The number returned is the number of seconds we received no
    1293    pongs from the user. When not connected yet, we don't ping but drop the
    1294    connection when the user fails to connect in IRC_LOGIN_TIMEOUT secs. */
    1295 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond )
    1296 {
    1297         irc_t *irc = _irc;
    1298         int rv = 0;
    1299        
    1300         if( !( irc->status & USTATUS_LOGGED_IN ) )
    1301         {
    1302                 if( gettime() > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) )
    1303                         rv = gettime() - irc->last_pong;
    1304         }
    1305         else
    1306         {
    1307                 if( ( gettime() > ( irc->last_pong + global.conf->ping_interval ) ) && !irc->pinging )
    1308                 {
    1309                         irc_write( irc, "PING :%s", IRC_PING_STRING );
    1310                         irc->pinging = 1;
    1311                 }
    1312                 else if( gettime() > ( irc->last_pong + global.conf->ping_timeout ) )
    1313                 {
    1314                         rv = gettime() - irc->last_pong;
    1315                 }
    1316         }
    1317        
    1318         if( rv > 0 )
    1319         {
    1320                 irc_abort( irc, 0, "Ping Timeout: %d seconds", rv );
    1321                 return FALSE;
    1322         }
    1323        
    1324         return TRUE;
    1325 }
    1326 
    1327 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )
    1328 {
    1329         struct groupchat *c;
    1330         account_t *a;
    1331        
    1332         /* This finds the connection which has a conversation which belongs to this channel */
    1333         for( a = irc->accounts; a; a = a->next )
    1334         {
    1335                 if( a->ic == NULL )
    1336                         continue;
    1337                
    1338                 c = a->ic->groupchats;
    1339                 while( c )
    1340                 {
    1341                         if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )
    1342                                 return c;
    1343                        
    1344                         c = c->next;
    1345                 }
    1346         }
    1347        
    1348         return NULL;
    1349 }
     593
     594
     595static char *set_eval_charset( set_t *set, char *value )
     596{
     597        irc_t *irc = set->data;
     598        GIConv ic, oc;
     599
     600        if( g_strcasecmp( value, "none" ) == 0 )
     601                value = g_strdup( "utf-8" );
     602
     603        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     604        {
     605                return NULL;
     606        }
     607        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     608        {
     609                g_iconv_close( ic );
     610                return NULL;
     611        }
     612       
     613        if( irc->iconv != (GIConv) -1 )
     614                g_iconv_close( irc->iconv );
     615        if( irc->oconv != (GIConv) -1 )
     616                g_iconv_close( irc->oconv );
     617       
     618        irc->iconv = ic;
     619        irc->oconv = oc;
     620
     621        return value;
     622}
  • irc.h

    rba7d16f r3ddb7477  
    55  \********************************************************************/
    66
    7 /* The big hairy IRCd part of the project                               */
     7/* The IRC-based UI (for now the only one)                              */
    88
    99/*
     
    4949} irc_status_t;
    5050
     51struct irc_user;
     52
    5153typedef struct irc
    5254{
     
    5961        GIConv iconv, oconv;
    6062
    61         int sentbytes;
    62         time_t oldtime;
     63        struct irc_user *root;
     64        struct irc_user *user;
    6365
    64         char *nick;
    65         char *user;
    66         char *host;
    67         char *realname;
    6866        char *password; /* HACK: Used to save the user's password, but before
    6967                           logging in, this may contain a password we should
     
    7270        char umode[8];
    7371       
    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        
    8372        struct query *queries;
    8473        struct account *accounts;
     
    8675        struct chat *chatrooms;
    8776       
    88         struct __USER *users;
    89         GHashTable *userhash;
     77        GSList *users;
     78        GHashTable *nick_user_hash;
    9079        GHashTable *watches;
    91         struct __NICK *nicks;
    92         struct set *set;
    9380
    9481        gint r_watch_source_id;
    9582        gint w_watch_source_id;
    9683        gint ping_source_id;
     84       
     85        struct bee *b;
    9786} irc_t;
     87
     88typedef struct irc_user
     89{
     90        char *nick;
     91        char *user;
     92        char *host;
     93        char *fullname;
     94       
     95        /* Nickname in lowercase for case sensitive searches */
     96        char *key;
     97       
     98        char is_private;
     99       
     100        char *sendbuf;
     101        int sendbuf_len;
     102        guint sendbuf_timer;
     103        int sendbuf_flags;
     104       
     105        //struct user *b;
     106} irc_user_t;
    98107
    99108#include "user.h"
    100109
     110/* irc.c */
    101111extern GSList *irc_connection_list;
    102112
     
    105115void irc_free( irc_t *irc );
    106116
    107 void irc_exec( irc_t *irc, char **cmd );
    108117void irc_process( irc_t *irc );
    109118char **irc_parse_line( char *line );
    110119char *irc_build_line( char **cmd );
    111120
    112 void irc_vawrite( irc_t *irc, char *format, va_list params );
    113121void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    114122void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    115 void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    116 G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    117 char **irc_tokenize( char *buffer );
     123void irc_vawrite( irc_t *irc, char *format, va_list params );
    118124
    119 void irc_login( irc_t *irc );
    120125int irc_check_login( irc_t *irc );
    121 void irc_motd( irc_t *irc );
    122 void irc_names( irc_t *irc, char *channel );
    123 void irc_topic( irc_t *irc, char *channel );
    124 void irc_umode_set( irc_t *irc, char *s, int allow_priv );
    125 void irc_who( irc_t *irc, char *channel );
    126 void irc_spawn( irc_t *irc, user_t *u );
    127 void irc_join( irc_t *irc, user_t *u, char *channel );
    128 void irc_part( irc_t *irc, user_t *u, char *channel );
    129 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker );
    130 void irc_kill( irc_t *irc, user_t *u );
    131 void irc_invite( irc_t *irc, char *nick, char *channel );
    132 void irc_whois( irc_t *irc, char *nick );
    133 void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */
    134126
    135 int irc_send( irc_t *irc, char *nick, char *s, int flags );
    136 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg );
    137 int irc_msgfrom( irc_t *irc, char *nick, char *msg );
    138 int irc_noticefrom( irc_t *irc, char *nick, char *msg );
     127/* irc_commands.c */
     128void irc_exec( irc_t *irc, char **cmd );
    139129
    140 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
    141 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
     130/* irc_send.c */
     131void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
     132void irc_send_login( irc_t *irc );
     133void irc_send_motd( irc_t *irc );
     134int irc_usermsg( irc_t *irc, char *format, ... );
     135
     136/* irc_user.c */
     137irc_user_t *irc_user_new( irc_t *irc, const char *nick );
     138int irc_user_free( irc_t *irc, const char *nick );
     139irc_user_t *irc_user_find( irc_t *irc, const char *nick );
     140int irc_user_rename( irc_t *irc, const char *old, const char *new );
    142141
    143142#endif
  • irc_commands.c

    rba7d16f r3ddb7477  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2006 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    3939                   out we don't require it, which will break this feature.)
    4040                   Try to identify using the given password. */
    41                 return root_command( irc, send_cmd );
     41                /*return root_command( irc, send_cmd );*/
    4242        }
    4343        /* Handling in pre-logged-in state, first see if this server is
     
    5353        else if( global.conf->auth_pass )
    5454        {
    55                 irc_reply( irc, 464, ":Incorrect password" );
     55                irc_send_num( irc, 464, ":Incorrect password" );
    5656        }
    5757        else
    5858        {
    5959                /* Remember the password and try to identify after USER/NICK. */
    60                 irc_setpass( irc, cmd[1] );
     60                /*irc_setpass( irc, cmd[1] ); */
    6161                irc_check_login( irc );
    6262        }
     
    6565static void irc_cmd_user( irc_t *irc, char **cmd )
    6666{
    67         irc->user = g_strdup( cmd[1] );
    68         irc->realname = g_strdup( cmd[4] );
     67        irc->user->user = g_strdup( cmd[1] );
     68        irc->user->fullname = g_strdup( cmd[4] );
    6969       
    7070        irc_check_login( irc );
     
    7373static void irc_cmd_nick( irc_t *irc, char **cmd )
    7474{
    75         if( irc->nick )
    76         {
    77                 irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    78         }
    79         /* This is not clean, but for now it'll have to be like this... */
    80         else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    81         {
    82                 irc_reply( irc, 433, ":This nick is already in use" );
     75        if( irc->user->nick )
     76        {
     77                irc_send_num( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
     78        }
     79        else if( irc_user_find( irc, cmd[1] ) )
     80        {
     81                irc_send_num( irc, 433, ":This nick is already in use" );
    8382        }
    8483        else if( !nick_ok( cmd[1] ) )
    8584        {
    8685                /* [SH] Invalid characters. */
    87                 irc_reply( irc, 432, ":This nick contains invalid characters" );
    88         }
    89         else
    90         {
    91                 irc->nick = g_strdup( cmd[1] );
     86                irc_send_num( irc, 432, ":This nick contains invalid characters" );
     87        }
     88        else
     89        {
     90                irc->user->nick = g_strdup( cmd[1] );
    9291               
    9392                irc_check_login( irc );
     
    9594}
    9695
     96#if 0
    9797static void irc_cmd_quit( irc_t *irc, char **cmd )
    9898{
     
    116116        {
    117117                irc_umode_set( irc, "+o", 1 );
    118                 irc_reply( irc, 381, ":Password accepted" );
    119         }
    120         else
    121         {
    122                 irc_reply( irc, 432, ":Incorrect password" );
     118                irc_send_num( irc, 381, ":Password accepted" );
     119        }
     120        else
     121        {
     122                irc_send_num( irc, 432, ":Incorrect password" );
    123123        }
    124124}
     
    131131                {
    132132                        if( *cmd[2] == '+' || *cmd[2] == '-' )
    133                                 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
     133                                irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
    134134                        else if( *cmd[2] == 'b' )
    135                                 irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
     135                                irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
    136136                }
    137137                else
    138                         irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
     138                        irc_send_num( irc, 324, "%s +%s", cmd[1], CMODE );
    139139        }
    140140        else
     
    145145                                irc_umode_set( irc, cmd[2], 0 );
    146146                        else
    147                                 irc_reply( irc, 221, "+%s", irc->umode );
     147                                irc_send_num( irc, 221, "+%s", irc->umode );
    148148                }
    149149                else
    150                         irc_reply( irc, 502, ":Don't touch their modes" );
     150                        irc_send_num( irc, 502, ":Don't touch their modes" );
    151151        }
    152152}
     
    183183        else
    184184        {
    185                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
     185                irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
    186186        }
    187187}
     
    197197               
    198198                if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 )
    199                         irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] );
     199                        irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] );
    200200                else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic )
    201201                        chat_join( irc, c, cmd[2] );
    202202                else
    203                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
     203                        irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
    204204        }
    205205}
     
    215215                {
    216216                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
    217                         irc_reply( irc, 341, "%s %s", nick, channel );
     217                        irc_send_num( irc, 341, "%s %s", nick, channel );
    218218                        return;
    219219                }
    220220       
    221         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
     221        irc_send_num( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    222222}
    223223
     
    226226        if ( !cmd[2] )
    227227        {
    228                 irc_reply( irc, 412, ":No text to send" );
     228                irc_send_num( irc, 412, ":No text to send" );
    229229        }
    230230        else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
     
    283283                while( u )
    284284                {
    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 );
     285                        irc_send_num( 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 );
    286286                        u = u->next;
    287287                }
     
    290290                {
    291291                        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 );
     292                                irc_send_num( 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 );
    293293                        u = u->next;
    294294                }
     
    297297                {
    298298                        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 );
     299                                irc_send_num( 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 );
    300300                }
    301301        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:"**" );
     302                irc_send_num( 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_send_num( irc, 315, "%s :End of /WHO list", channel?channel:"**" );
    305305}
    306306
     
    320320                {
    321321                        if( u->online && u->away )
    322                                 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
     322                                irc_send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    323323                        else
    324                                 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
     324                                irc_send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    325325                }
    326326}
     
    377377                buff[strlen(buff)-1] = '\0';
    378378       
    379         irc_reply( irc, 303, ":%s", buff );
     379        irc_send_num( irc, 303, ":%s", buff );
    380380}
    381381
     
    406406                       
    407407                        if( u && u->online )
    408                                 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
     408                                irc_send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
    409409                        else
    410                                 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
     410                                irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
    411411                }
    412412                else if( cmd[i][0] == '-' )
     
    419419                                g_free( okey );
    420420                               
    421                                 irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
     421                                irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    422422                        }
    423423                }
     
    463463                u->away[j] = 0;
    464464               
    465                 irc_reply( irc, 306, ":You're now away: %s", u->away );
     465                irc_send_num( irc, 306, ":You're now away: %s", u->away );
    466466                /* irc_umode_set( irc, irc->myhost, "+a" ); */
    467467        }
     
    471471                u->away = NULL;
    472472                /* irc_umode_set( irc, irc->myhost, "-a" ); */
    473                 irc_reply( irc, 305, ":Welcome back" );
     473                irc_send_num( irc, 305, ":Welcome back" );
    474474        }
    475475       
     
    484484        if( u )
    485485        {
    486                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
     486                irc_send_num( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    487487               
    488488                if( u->ic )
    489                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user,
     489                        irc_send_num( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user,
    490490                                   u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "",
    491491                                   u->ic->acc->prpl->name );
    492492                else
    493                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
     493                        irc_send_num( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    494494               
    495495                if( !u->online )
    496                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
     496                        irc_send_num( irc, 301, "%s :%s", u->nick, "User is offline" );
    497497                else if( u->away )
    498                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
     498                        irc_send_num( irc, 301, "%s :%s", u->nick, u->away );
    499499                if( u->status_msg )
    500                         irc_reply( irc, 333, "%s :Status: %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 );
     500                        irc_send_num( irc, 333, "%s :Status: %s", u->nick, u->status_msg );
     501               
     502                irc_send_num( irc, 318, "%s :End of /WHOIS list", nick );
     503        }
     504        else
     505        {
     506                irc_send_num( irc, 401, "%s :Nick does not exist", nick );
    507507        }
    508508}
     
    515515           with not-found and irssi users will get better error messages */
    516516       
    517         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    518         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
     517        irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
     518        irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
    519519}
    520520
     
    541541static void irc_cmd_version( irc_t *irc, char **cmd )
    542542{
    543         irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
     543        irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
    544544}
    545545
     
    572572                ipc_to_master( cmd );
    573573       
    574         irc_reply( irc, 382, "%s :Rehashing", global.conf_file );
    575 }
     574        irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
     575}
     576#endif
    576577
    577578static const command_t irc_commands[] = {
     
    579580        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
    580581        { "nick",        1, irc_cmd_nick,        0 },
     582#if 0
    581583        { "quit",        0, irc_cmd_quit,        0 },
    582584        { "ping",        0, irc_cmd_ping,        0 },
     
    610612        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    611613        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
     614#endif
    612615        { NULL }
    613616};
     
    628631                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
    629632                        {
    630                                 irc_reply( irc, 462, ":Only allowed before logging in" );
     633                                irc_send_num( irc, 462, ":Only allowed before logging in" );
    631634                        }
    632635                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
    633636                        {
    634                                 irc_reply( irc, 451, ":Register first" );
     637                                irc_send_num( irc, 451, ":Register first" );
    635638                        }
    636639                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
    637640                        {
    638                                 irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" );
     641                                irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
    639642                        }
    640643                        else if( n_arg < irc_commands[i].required_parameters )
    641644                        {
    642                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     645                                irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
    643646                        }
    644647                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
     
    657660       
    658661        if( irc->status >= USTATUS_LOGGED_IN )
    659                 irc_reply( irc, 421, "%s :Unknown command", cmd[0] );
    660 }
     662                irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
     663}
  • nick.c

    rba7d16f r3ddb7477  
    7878               
    7979                nick_strip( nick );
    80                 if( set_getbool( &acc->irc->set, "lcnicks" ) )
     80                if( set_getbool( &acc->irc->b->set, "lcnicks" ) )
    8181                        nick_lc( nick );
    8282        }
     
    9696        /* Now, find out if the nick is already in use at the moment, and make
    9797           subtle changes to make it unique. */
    98         while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
     98        while( !nick_ok( nick ) || irc_user_find( acc->irc, nick ) )
    9999        {
    100100                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
  • protocols/Makefile

    rba7d16f r3ddb7477  
    1010
    1111# [SH] Program variables
    12 objects = nogaim.o
     12#objects = account.o nogaim.o user.o
     13objects = bee.o
     14
    1315
    1416# [SH] The next two lines should contain the directory name (in $(subdirs))
  • protocols/account.c

    rba7d16f r3ddb7477  
    336336int account_reconnect_delay( account_t *a )
    337337{
    338         char *setting = set_getstr( &a->irc->set, "auto_reconnect_delay" );
     338        char *setting = set_getstr( &a->irc->b->set, "auto_reconnect_delay" );
    339339        struct account_reconnect_delay p;
    340340       
  • protocols/user.c

    rba7d16f r3ddb7477  
    3737        if( user_find( irc, nick ) != NULL )
    3838                return( NULL );
    39        
    40         if( ( u = irc->users ) )
    41         {
    42                 while( u )
    43                 {
    44                         if( nick_cmp( nick, u->nick ) < 0 )
    45                                 break;
    46                        
    47                         lu = u;
    48                         u = u->next;
    49                 }
    50                
    51                 u = g_new0( user_t, 1 );
    52                 if( lu )
    53                 {
    54                         u->next = lu->next;
    55                         lu->next = u;
    56                 }
    57                 else
    58                 {
    59                         u->next = irc->users;
    60                         irc->users = u;
    61                 }
    62         }
    63         else
    64         {
    65                 irc->users = u = g_new0( user_t, 1 );
    66         }
    67        
    68         u->user = u->realname = u->host = u->nick = g_strdup( nick );
    69         u->is_private = set_getbool( &irc->set, "private" );
    70        
    71         key = g_strdup( nick );
    72         nick_lc( key );
    73         g_hash_table_insert( irc->userhash, key, u );
    7439       
    7540        return( u );
     
    11378                        g_free( u );
    11479                       
    115                         if( !g_hash_table_lookup_extended( irc->userhash, key, &okey, &ovalue ) || ovalue != u )
    116                         {
    117                                 g_free( key );
    118                                 return( 1 );    /* Although this is a severe error, the user is removed from the list... */
    119                         }
    120                         g_hash_table_remove( irc->userhash, key );
    121                         g_free( key );
    122                         g_free( okey );
    123                        
    12480                        return( 1 );
    12581                }
     
    12884       
    12985        return( 0 );
    130 }
    131 
    132 user_t *user_find( irc_t *irc, char *nick )
    133 {
    134         char key[512] = "";
    135        
    136         strncpy( key, nick, sizeof( key ) - 1 );
    137         if( nick_lc( key ) )
    138                 return( g_hash_table_lookup( irc->userhash, key ) );
    139         else
    140                 return( NULL );
    14186}
    14287
     
    160105        return NULL;
    161106}
    162 
    163 /* DO NOT PASS u->nick FOR oldnick !!! */
    164 void user_rename( irc_t *irc, char *oldnick, char *newnick )
    165 {
    166         user_t *u = user_find( irc, oldnick );
    167         gpointer okey, ovalue;
    168         char *key;
    169        
    170         if( !u ) return;        /* Should've been checked by the caller... */
    171        
    172         g_free( u->nick );
    173         if( u->nick == u->user ) u->user = NULL;
    174         if( u->nick == u->host ) u->host = NULL;
    175         if( u->nick == u->realname ) u->realname = NULL;
    176         u->nick = g_strdup( newnick );
    177         if( !u->user ) u->user = u->nick;
    178         if( !u->host ) u->host = u->nick;
    179         if( !u->realname ) u->realname = u->nick;
    180        
    181         /* Remove the old reference to this user from the hash and create a
    182            new one with the new nick. This is indeed a bit messy. */
    183         key = g_strdup( oldnick );
    184         nick_lc( key );
    185         if( !g_hash_table_lookup_extended( irc->userhash, key, &okey, &ovalue ) || ovalue != u )
    186         {
    187                 g_free( key );
    188                 return;         /* This really shouldn't happen! */     
    189         }
    190         g_hash_table_remove( irc->userhash, key );
    191         g_free( key );
    192         g_free( okey );
    193        
    194         key = g_strdup( newnick );
    195         nick_lc( key );
    196         g_hash_table_insert( irc->userhash, key, u );
    197        
    198         /* Also, let's try to keep the linked list nicely sorted. Fear this
    199            code. If my teacher would see this, she would cry. ;-) */
    200         {
    201                 user_t *u1, *lu1;
    202                
    203                 /* Remove the user from the old position in the chain. */
    204                 if( u == irc->users )
    205                 {
    206                         irc->users = u->next;
    207                 }
    208                 else
    209                 {
    210                         u1 = u;
    211                         for( lu1 = irc->users; lu1->next != u1; lu1 = lu1->next );
    212                         lu1->next = u1->next;
    213                 }
    214                
    215                 /* Search for the new position. */
    216                 for( lu1 = NULL, u1 = irc->users; u1; u1 = u1->next )
    217                 {
    218                         if( nick_cmp( newnick, u1->nick ) < 0 )
    219                                 break;
    220                        
    221                         lu1 = u1;
    222                 }
    223                
    224                 /* Insert it at this new position. */
    225                 u->next = u1;
    226                 if( lu1 )
    227                         lu1->next = u;
    228                 else
    229                         irc->users = u;
    230         }
    231 }
  • protocols/user.h

    rba7d16f r3ddb7477  
    2323  Suite 330, Boston, MA  02111-1307  USA
    2424*/
     25
    2526#ifndef __USER_H__
    2627#define __USER_H__
    2728
    28 typedef struct __USER
     29struct __USER
    2930{
    30         char *nick;
    31         char *user;
    32         char *host;
    33         char *realname;
    34        
     31        struct im_connection *ic;
     32        char *handle;
     33        char *fullname;
     34        char *group;
     35
    3536        char *away;
    36         char *status_msg; /* Non-IRC extension, but nice on IM. */
    37        
    38         char is_private;
    39         char online;
    40        
    41         char *handle;
    42         char *group;
    43         struct im_connection *ic;
    44 
    45         char *sendbuf;
    46         time_t last_typing_notice;
    47         int sendbuf_len;
    48         guint sendbuf_timer;
    49         int sendbuf_flags;
    50        
    51         void (*send_handler) ( irc_t *irc, struct __USER *u, char *msg, int flags );
    52        
    53         struct __USER *next;
     37        char *status_msg;
    5438} user_t;
    5539
    56 user_t *user_add( struct irc *irc, char *nick );
    57 int user_del( irc_t *irc, char *nick );
    58 G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick );
    59 G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, const char *handle );
    60 void user_rename( irc_t *irc, char *oldnick, char *newnick );
    61 
    6240#endif /* __USER_H__ */
  • set.c

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

    rba7d16f r3ddb7477  
    6262       
    6363        b_main_init();
    64         nogaim_init();
     64        //nogaim_init();
    6565       
    6666        srand( time( NULL ) ^ getpid() );
     
    115115        }
    116116
     117        /*
    117118        global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );
    118119        if( global.storage == NULL )
     
    121122                return( 1 );
    122123        }
     124        */
    123125       
    124126        /* Catch some signals to tell the user what's happening before quitting */
Note: See TracChangeset for help on using the changeset viewer.