Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    r1195cec rc84e31a  
    4242}
    4343
    44 static char *set_eval_charset( set_t *set, char *value )
    45 {
    46         irc_t *irc = set->data;
    47         GIConv ic, oc;
    48 
    49         if( g_strcasecmp( value, "none" ) == 0 )
    50                 value = g_strdup( "utf-8" );
    51 
    52         if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    53         {
    54                 return NULL;
    55         }
    56         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    57         {
    58                 g_iconv_close( ic );
    59                 return NULL;
    60         }
    61        
    62         if( irc->iconv != (GIConv) -1 )
    63                 g_iconv_close( irc->iconv );
    64         if( irc->oconv != (GIConv) -1 )
    65                 g_iconv_close( irc->oconv );
    66        
    67         irc->iconv = ic;
    68         irc->oconv = oc;
    69 
    70         return value;
    71 }
    72 
    7344irc_t *irc_new( int fd )
    7445{
     
    9364        irc->mynick = g_strdup( ROOT_NICK );
    9465        irc->channel = g_strdup( ROOT_CHAN );
    95        
    96         irc->iconv = (GIConv) -1;
    97         irc->oconv = (GIConv) -1;
    9866       
    9967        if( global.conf->hostname )
     
    151119        set_add( &irc->set, "private", "true", set_eval_bool, irc );
    152120        set_add( &irc->set, "query_order", "lifo", NULL, irc );
    153         set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    154121        set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    155122        set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     
    160127        conf_loaddefaults( irc );
    161128       
    162         /* Evaluator sets the iconv/oconv structures. */
    163         set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
    164        
    165129        return( irc );
    166130}
     
    200164        if( irc->sendbuffer && !immed )
    201165        {
    202                 /* Set up a timeout event that should shut down the connection
    203                    in a second, just in case ..._write doesn't do it first. */
     166                /* We won't read from this socket anymore. Instead, we'll connect a timer
     167                   to it that should shut down the connection in a second, just in case
     168                   bitlbee_.._write doesn't do it first. */
    204169               
    205170                b_event_remove( irc->r_watch_source_id );
    206                 irc->r_watch_source_id = 0;
    207                
    208                 b_event_remove( irc->ping_source_id );
    209                 irc->ping_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
     171                irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
    210172        }
    211173        else
     
    223185
    224186/* Because we have no garbage collection, this is quite annoying */
    225 void irc_free( irc_t * irc )
    226 {
     187void irc_free(irc_t * irc)
     188{
     189        account_t *account;
    227190        user_t *user, *usertmp;
    228191       
     
    233196                        irc_usermsg( irc, "Error while saving settings!" );
    234197       
     198        closesocket( irc->fd );
     199       
     200        if( irc->ping_source_id > 0 )
     201                b_event_remove( irc->ping_source_id );
     202        b_event_remove( irc->r_watch_source_id );
     203        if( irc->w_watch_source_id > 0 )
     204                b_event_remove( irc->w_watch_source_id );
     205       
    235206        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    236207       
    237         while( irc->accounts )
    238         {
    239                 if( irc->accounts->ic )
    240                         imc_logout( irc->accounts->ic, FALSE );
    241                 else if( irc->accounts->reconnect )
    242                         cancel_auto_reconnect( irc->accounts );
    243                
    244                 if( irc->accounts->ic == NULL )
    245                         account_del( irc, irc->accounts );
     208        for (account = irc->accounts; account; account = account->next) {
     209                if (account->ic) {
     210                        imc_logout(account->ic, TRUE);
     211                } else if (account->reconnect) {
     212                        cancel_auto_reconnect(account);
     213                }
     214        }
     215       
     216        g_free(irc->sendbuffer);
     217        g_free(irc->readbuffer);
     218       
     219        g_free(irc->nick);
     220        g_free(irc->user);
     221        g_free(irc->host);
     222        g_free(irc->realname);
     223        g_free(irc->password);
     224       
     225        g_free(irc->myhost);
     226        g_free(irc->mynick);
     227       
     228        g_free(irc->channel);
     229       
     230        while (irc->queries != NULL)
     231                query_del(irc, irc->queries);
     232       
     233        while (irc->accounts)
     234                if (irc->accounts->ic == NULL)
     235                        account_del(irc, irc->accounts);
    246236                else
    247237                        /* Nasty hack, but account_del() doesn't work in this
    248238                           case and we don't want infinite loops, do we? ;-) */
    249239                        irc->accounts = irc->accounts->next;
    250         }
    251        
    252         while( irc->queries != NULL )
    253                 query_del( irc, irc->queries );
    254        
    255         while( irc->set )
    256                 set_del( &irc->set, irc->set->key );
    257        
    258         if (irc->users != NULL)
    259         {
     240       
     241        while (irc->set)
     242                set_del(&irc->set, irc->set->key);
     243       
     244        if (irc->users != NULL) {
    260245                user = irc->users;
    261                 while( user != NULL )
    262                 {
    263                         g_free( user->nick );
    264                         g_free( user->away );
    265                         g_free( user->handle );
    266                         if( user->user != user->nick ) g_free( user->user );
    267                         if( user->host != user->nick ) g_free( user->host );
    268                         if( user->realname != user->nick ) g_free( user->realname );
    269                         b_event_remove( user->sendbuf_timer );
     246                while (user != NULL) {
     247                        g_free(user->nick);
     248                        g_free(user->away);
     249                        g_free(user->handle);
     250                        if(user->user!=user->nick) g_free(user->user);
     251                        if(user->host!=user->nick) g_free(user->host);
     252                        if(user->realname!=user->nick) g_free(user->realname);
     253                        b_event_remove(user->sendbuf_timer);
    270254                                       
    271255                        usertmp = user;
    272256                        user = user->next;
    273                         g_free( usertmp );
    274                 }
    275         }
    276        
    277         if( irc->ping_source_id > 0 )
    278                 b_event_remove( irc->ping_source_id );
    279         if( irc->r_watch_source_id > 0 )
    280                 b_event_remove( irc->r_watch_source_id );
    281         if( irc->w_watch_source_id > 0 )
    282                 b_event_remove( irc->w_watch_source_id );
    283        
    284         closesocket( irc->fd );
    285         irc->fd = -1;
    286        
    287         g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
    288         g_hash_table_destroy( irc->userhash );
    289        
    290         g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
    291         g_hash_table_destroy( irc->watches );
    292        
    293         if( irc->iconv != (GIConv) -1 )
    294                 g_iconv_close( irc->iconv );
    295         if( irc->oconv != (GIConv) -1 )
    296                 g_iconv_close( irc->oconv );
    297        
    298         g_free( irc->sendbuffer );
    299         g_free( irc->readbuffer );
    300        
    301         g_free( irc->nick );
    302         g_free( irc->user );
    303         g_free( irc->host );
    304         g_free( irc->realname );
    305         g_free( irc->password );
    306        
    307         g_free( irc->myhost );
    308         g_free( irc->mynick );
    309        
    310         g_free( irc->channel );
    311        
    312         g_free( irc->last_target );
    313        
    314         g_free( irc );
     257                        g_free(usertmp);
     258                }
     259        }
     260       
     261        g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL);
     262        g_hash_table_destroy(irc->userhash);
     263       
     264        g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
     265        g_hash_table_destroy(irc->watches);
     266       
     267        g_free(irc);
    315268       
    316269        if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
     
    333286void irc_process( irc_t *irc )
    334287{
    335         char **lines, *temp, **cmd;
     288        char **lines, *temp, **cmd, *cs;
    336289        int i;
    337290
     
    342295                for( i = 0; *lines[i] != '\0'; i ++ )
    343296                {
    344                         char *conv = NULL;
     297                        char conv[IRC_MAX_LINE+1];
    345298                       
    346                         /* [WvG] If the last line isn't empty, it's an incomplete line and we
    347                            should wait for the rest to come in before processing it. */
     299                        /* [WvG] Because irc_tokenize splits at every newline, the lines[] list
     300                            should end with an empty string. This is why this actually works.
     301                            Took me a while to figure out, Maurits. :-P */
    348302                        if( lines[i+1] == NULL )
    349303                        {
     
    355309                        }
    356310                       
    357                         if( irc->iconv != (GIConv) -1 )
     311                        if( ( cs = set_getstr( &irc->set, "charset" ) ) )
    358312                        {
    359                                 gsize bytes_read, bytes_written;
    360                                
    361                                 conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
    362                                                              &bytes_read, &bytes_written, NULL );
    363                                
    364                                 if( conv == NULL || bytes_read != strlen( lines[i] ) )
     313                                conv[IRC_MAX_LINE] = 0;
     314                                if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 )
    365315                                {
    366316                                        /* GLib can do strange things if things are not in the expected charset,
     
    374324                                                                  "expect by changing the charset setting. See "
    375325                                                                  "`help set charset' for more information. Your "
    376                                                                   "message was ignored.",
    377                                                                   set_getstr( &irc->set, "charset" ) );
    378                                                
    379                                                 g_free( conv );
    380                                                 conv = NULL;
     326                                                                  "message was ignored.", cs );
     327                                                *conv = 0;
    381328                                        }
    382329                                        else
    383330                                        {
    384331                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    385                                                            "Warning: invalid characters received at login time." );
     332                                                           "Warning: invalid (non-UTF8) characters received at login time." );
    386333                                               
    387                                                 conv = g_strdup( lines[i] );
     334                                                strncpy( conv, lines[i], IRC_MAX_LINE );
    388335                                                for( temp = conv; *temp; temp ++ )
    389336                                                        if( *temp & 0x80 )
     
    394341                        }
    395342                       
    396                         if( lines[i] )
    397                         {
    398                                 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    399                                         continue;
    400                                 irc_exec( irc, cmd );
    401                                 g_free( cmd );
    402                         }
     343                        if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     344                                continue;
     345                        irc_exec( irc, cmd );
    403346                       
    404                         g_free( conv );
     347                        g_free( cmd );
    405348                       
    406349                        /* Shouldn't really happen, but just in case... */
     
    426369char **irc_tokenize( char *buffer )
    427370{
    428         int i, j, n = 3;
     371        int i, j;
    429372        char **lines;
    430373
    431         /* Allocate n+1 elements. */
    432         lines = g_new( char *, n + 1 );
     374        /* Count the number of elements we're gonna need. */
     375        for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
     376        {
     377                if( buffer[i] == '\n' )
     378                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     379                                j ++;
     380        }
     381       
     382        /* Allocate j+1 elements. */
     383        lines = g_new( char *, j + 1 );
     384       
     385        /* NULL terminate our list. */
     386        lines[j] = NULL;
    433387       
    434388        lines[0] = buffer;
    435389       
    436         /* Split the buffer in several strings, and accept any kind of line endings,
    437          * knowing that ERC on Windows may send something interesting like \r\r\n,
    438          * and surely there must be clients that think just \n is enough... */
    439         for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
    440         {
    441                 if( buffer[i] == '\r' || buffer[i] == '\n' )
    442                 {
    443                         while( buffer[i] == '\r' || buffer[i] == '\n' )
    444                                 buffer[i++] = '\0';
     390        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
     391         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
     392         */
     393        for( i = 0, j = 0; buffer[i] != '\0'; i ++)
     394        {
     395                if( buffer[i] == '\n' )
     396                {
     397                        buffer[i] = '\0';
    445398                       
    446                         lines[++j] = buffer + i;
    447                        
    448                         if( j >= n )
    449                         {
    450                                 n *= 2;
    451                                 lines = g_renew( char *, lines, n + 1 );
    452                         }
    453 
    454                         if( buffer[i] == '\0' )
    455                                 break;
    456                 }
    457         }
    458        
    459         /* NULL terminate our list. */
    460         lines[++j] = NULL;
    461        
    462         return lines;
     399                        if( i > 0 && buffer[i-1] == '\r' )
     400                                buffer[i-1] = '\0';
     401                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     402                                lines[++j] = buffer + i + 1;
     403                }
     404        }
     405       
     406        return( lines );
    463407}
    464408
     
    594538
    595539        return;
     540
    596541}
    597542
     
    599544{
    600545        int size;
    601         char line[IRC_MAX_LINE+1];
     546        char line[IRC_MAX_LINE+1], *cs;
    602547               
    603548        /* Don't try to write anything new anymore when shutting down. */
     
    605550                return;
    606551       
    607         memset( line, 0, sizeof( line ) );
     552        line[IRC_MAX_LINE] = 0;
    608553        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
     554       
    609555        strip_newlines( line );
    610        
    611         if( irc->oconv != (GIConv) -1 )
    612         {
    613                 gsize bytes_read, bytes_written;
    614                 char *conv;
    615                
    616                 conv = g_convert_with_iconv( line, -1, irc->oconv,
    617                                              &bytes_read, &bytes_written, NULL );
    618 
    619                 if( bytes_read == strlen( line ) )
    620                         strncpy( line, conv, IRC_MAX_LINE - 2 );
    621                
    622                 g_free( conv );
    623         }
    624         g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
     556        if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
     557        {
     558                char conv[IRC_MAX_LINE+1];
     559               
     560                conv[IRC_MAX_LINE] = 0;
     561                if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 )
     562                        strcpy( line, conv );
     563        }
     564        strcat( line, "\r\n" );
    625565       
    626566        if( irc->sendbuffer != NULL )
     
    795735        irc_spawn( irc, u );
    796736       
    797         irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
    798                           "If you've never used BitlBee before, please do read the help "
    799                           "information using the \x02help\x02 command. Lots of FAQs are "
    800                           "answered there.\n"
    801                           "If you already have an account on this server, just use the "
    802                           "\x02identify\x02 command to identify yourself." );
     737        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQs are answered there." );
    803738       
    804739        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     
    806741       
    807742        irc->status |= USTATUS_LOGGED_IN;
    808        
    809         /* This is for bug #209 (use PASS to identify to NickServ). */
    810         if( irc->password != NULL )
    811         {
    812                 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
    813                
    814                 irc_setpass( irc, NULL );
    815                 root_command( irc, send_cmd );
    816                 g_free( send_cmd[1] );
    817         }
    818743}
    819744
Note: See TracChangeset for help on using the changeset viewer.