Changeset b79308b for irc.c


Ignore:
Timestamp:
2008-04-14T13:10:53Z (12 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
0cab388
Parents:
6cac643 (diff), aa31117 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merged in upstream r379 (somewhere after 1.2-3).
Just one trivial conflict in the jabber Makefile, went smoothly.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    r6cac643 rb79308b  
    4646}
    4747
     48static char *set_eval_charset( set_t *set, char *value )
     49{
     50        irc_t *irc = set->data;
     51        GIConv ic, oc;
     52
     53        if( g_strcasecmp( value, "none" ) == 0 )
     54                value = g_strdup( "utf-8" );
     55
     56        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     57        {
     58                return NULL;
     59        }
     60        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     61        {
     62                g_iconv_close( ic );
     63                return NULL;
     64        }
     65       
     66        if( irc->iconv != (GIConv) -1 )
     67                g_iconv_close( irc->iconv );
     68        if( irc->oconv != (GIConv) -1 )
     69                g_iconv_close( irc->oconv );
     70       
     71        irc->iconv = ic;
     72        irc->oconv = oc;
     73
     74        return value;
     75}
     76
    4877irc_t *irc_new( int fd )
    4978{
     
    6897        irc->mynick = g_strdup( ROOT_NICK );
    6998        irc->channel = g_strdup( ROOT_CHAN );
     99       
     100        irc->iconv = (GIConv) -1;
     101        irc->oconv = (GIConv) -1;
    70102       
    71103        if( global.conf->hostname )
     
    123155        set_add( &irc->set, "private", "true", set_eval_bool, irc );
    124156        set_add( &irc->set, "query_order", "lifo", NULL, irc );
     157        set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    125158        set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    126159        set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     
    131164        conf_loaddefaults( irc );
    132165       
     166        /* Evaluator sets the iconv/oconv structures. */
     167        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
     168       
    133169        return( irc );
    134170}
     
    168204        if( irc->sendbuffer && !immed )
    169205        {
    170                 /* We won't read from this socket anymore. Instead, we'll connect a timer
    171                    to it that should shut down the connection in a second, just in case
    172                    bitlbee_.._write doesn't do it first. */
     206                /* Set up a timeout event that should shut down the connection
     207                   in a second, just in case ..._write doesn't do it first. */
    173208               
    174209                b_event_remove( irc->r_watch_source_id );
    175                 irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
     210                irc->r_watch_source_id = 0;
     211               
     212                b_event_remove( irc->ping_source_id );
     213                irc->ping_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
    176214        }
    177215        else
     
    189227
    190228/* Because we have no garbage collection, this is quite annoying */
    191 void irc_free(irc_t * irc)
    192 {
    193         account_t *account;
     229void irc_free( irc_t * irc )
     230{
    194231        user_t *user, *usertmp;
    195232       
     
    200237                        irc_usermsg( irc, "Error while saving settings!" );
    201238       
    202         closesocket( irc->fd );
    203        
    204         if( irc->ping_source_id > 0 )
    205                 b_event_remove( irc->ping_source_id );
    206         b_event_remove( irc->r_watch_source_id );
    207         if( irc->w_watch_source_id > 0 )
    208                 b_event_remove( irc->w_watch_source_id );
    209        
    210239        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    211240       
    212         for (account = irc->accounts; account; account = account->next) {
    213                 if (account->ic) {
    214                         imc_logout(account->ic, TRUE);
    215                 } else if (account->reconnect) {
    216                         cancel_auto_reconnect(account);
    217                 }
    218         }
    219        
    220         g_free(irc->sendbuffer);
    221         g_free(irc->readbuffer);
    222        
    223         g_free(irc->nick);
    224         g_free(irc->user);
    225         g_free(irc->host);
    226         g_free(irc->realname);
    227         g_free(irc->password);
    228        
    229         g_free(irc->myhost);
    230         g_free(irc->mynick);
    231        
    232         g_free(irc->channel);
    233        
    234         while (irc->queries != NULL)
    235                 query_del(irc, irc->queries);
    236        
    237         while (irc->accounts)
    238                 if (irc->accounts->ic == NULL)
    239                         account_del(irc, irc->accounts);
     241        while( irc->accounts )
     242        {
     243                if( irc->accounts->ic )
     244                        imc_logout( irc->accounts->ic, FALSE );
     245                else if( irc->accounts->reconnect )
     246                        cancel_auto_reconnect( irc->accounts );
     247               
     248                if( irc->accounts->ic == NULL )
     249                        account_del( irc, irc->accounts );
    240250                else
    241251                        /* Nasty hack, but account_del() doesn't work in this
    242252                           case and we don't want infinite loops, do we? ;-) */
    243253                        irc->accounts = irc->accounts->next;
    244        
    245         while (irc->set)
    246                 set_del(&irc->set, irc->set->key);
    247        
    248         if (irc->users != NULL) {
     254        }
     255       
     256        while( irc->queries != NULL )
     257                query_del( irc, irc->queries );
     258       
     259        while( irc->set )
     260                set_del( &irc->set, irc->set->key );
     261       
     262        if (irc->users != NULL)
     263        {
    249264                user = irc->users;
    250                 while (user != NULL) {
    251                         g_free(user->nick);
    252                         g_free(user->away);
    253                         g_free(user->handle);
    254                         if(user->user!=user->nick) g_free(user->user);
    255                         if(user->host!=user->nick) g_free(user->host);
    256                         if(user->realname!=user->nick) g_free(user->realname);
    257                         b_event_remove(user->sendbuf_timer);
     265                while( user != NULL )
     266                {
     267                        g_free( user->nick );
     268                        g_free( user->away );
     269                        g_free( user->handle );
     270                        if( user->user != user->nick ) g_free( user->user );
     271                        if( user->host != user->nick ) g_free( user->host );
     272                        if( user->realname != user->nick ) g_free( user->realname );
     273                        b_event_remove( user->sendbuf_timer );
    258274                                       
    259275                        usertmp = user;
    260276                        user = user->next;
    261                         g_free(usertmp);
    262                 }
    263         }
    264        
    265         g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL);
    266         g_hash_table_destroy(irc->userhash);
    267        
    268         g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
    269         g_hash_table_destroy(irc->watches);
    270        
    271         g_free(irc);
     277                        g_free( usertmp );
     278                }
     279        }
     280       
     281        if( irc->ping_source_id > 0 )
     282                b_event_remove( irc->ping_source_id );
     283        if( irc->r_watch_source_id > 0 )
     284                b_event_remove( irc->r_watch_source_id );
     285        if( irc->w_watch_source_id > 0 )
     286                b_event_remove( irc->w_watch_source_id );
     287       
     288        closesocket( irc->fd );
     289        irc->fd = -1;
     290       
     291        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     292        g_hash_table_destroy( irc->userhash );
     293       
     294        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     295        g_hash_table_destroy( irc->watches );
     296       
     297        if( irc->iconv != (GIConv) -1 )
     298                g_iconv_close( irc->iconv );
     299        if( irc->oconv != (GIConv) -1 )
     300                g_iconv_close( irc->oconv );
     301       
     302        g_free( irc->sendbuffer );
     303        g_free( irc->readbuffer );
     304       
     305        g_free( irc->nick );
     306        g_free( irc->user );
     307        g_free( irc->host );
     308        g_free( irc->realname );
     309        g_free( irc->password );
     310       
     311        g_free( irc->myhost );
     312        g_free( irc->mynick );
     313       
     314        g_free( irc->channel );
     315       
     316        g_free( irc->last_target );
     317       
     318        g_free( irc );
    272319       
    273320        if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
     
    290337void irc_process( irc_t *irc )
    291338{
    292         char **lines, *temp, **cmd, *cs;
     339        char **lines, *temp, **cmd;
    293340        int i;
    294341
     
    299346                for( i = 0; *lines[i] != '\0'; i ++ )
    300347                {
    301                         char conv[IRC_MAX_LINE+1];
     348                        char *conv = NULL;
    302349                       
    303                         /* [WvG] Because irc_tokenize splits at every newline, the lines[] list
    304                             should end with an empty string. This is why this actually works.
    305                             Took me a while to figure out, Maurits. :-P */
     350                        /* [WvG] If the last line isn't empty, it's an incomplete line and we
     351                           should wait for the rest to come in before processing it. */
    306352                        if( lines[i+1] == NULL )
    307353                        {
     
    313359                        }
    314360                       
    315                         if( ( cs = set_getstr( &irc->set, "charset" ) ) )
    316                         {
    317                                 conv[IRC_MAX_LINE] = 0;
    318                                 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 )
     361                        if( irc->iconv != (GIConv) -1 )
     362                        {
     363                                gsize bytes_read, bytes_written;
     364                               
     365                                conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
     366                                                             &bytes_read, &bytes_written, NULL );
     367                               
     368                                if( conv == NULL || bytes_read != strlen( lines[i] ) )
    319369                                {
    320370                                        /* GLib can do strange things if things are not in the expected charset,
     
    328378                                                                  "expect by changing the charset setting. See "
    329379                                                                  "`help set charset' for more information. Your "
    330                                                                   "message was ignored.", cs );
    331                                                 *conv = 0;
     380                                                                  "message was ignored.",
     381                                                                  set_getstr( &irc->set, "charset" ) );
     382                                               
     383                                                g_free( conv );
     384                                                conv = NULL;
    332385                                        }
    333386                                        else
    334387                                        {
    335388                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    336                                                            "Warning: invalid (non-UTF8) characters received at login time." );
     389                                                           "Warning: invalid characters received at login time." );
    337390                                               
    338                                                 strncpy( conv, lines[i], IRC_MAX_LINE );
     391                                                conv = g_strdup( lines[i] );
    339392                                                for( temp = conv; *temp; temp ++ )
    340393                                                        if( *temp & 0x80 )
     
    345398                        }
    346399                       
    347                         if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    348                                 continue;
    349                         irc_exec( irc, cmd );
     400                        if( lines[i] )
     401                        {
     402                                if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     403                                        continue;
     404                                irc_exec( irc, cmd );
     405                                g_free( cmd );
     406                        }
    350407                       
    351                         g_free( cmd );
     408                        g_free( conv );
    352409                       
    353410                        /* Shouldn't really happen, but just in case... */
     
    373430char **irc_tokenize( char *buffer )
    374431{
    375         int i, j;
     432        int i, j, n = 3;
    376433        char **lines;
    377434
    378         /* Count the number of elements we're gonna need. */
    379         for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
    380         {
    381                 if( buffer[i] == '\n' )
    382                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    383                                 j ++;
    384         }
    385        
    386         /* Allocate j+1 elements. */
    387         lines = g_new( char *, j + 1 );
     435        /* Allocate n+1 elements. */
     436        lines = g_new( char *, n + 1 );
     437       
     438        lines[0] = buffer;
     439       
     440        /* Split the buffer in several strings, and accept any kind of line endings,
     441         * knowing that ERC on Windows may send something interesting like \r\r\n,
     442         * and surely there must be clients that think just \n is enough... */
     443        for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
     444        {
     445                if( buffer[i] == '\r' || buffer[i] == '\n' )
     446                {
     447                        while( buffer[i] == '\r' || buffer[i] == '\n' )
     448                                buffer[i++] = '\0';
     449                       
     450                        lines[++j] = buffer + i;
     451                       
     452                        if( j >= n )
     453                        {
     454                                n *= 2;
     455                                lines = g_renew( char *, lines, n + 1 );
     456                        }
     457
     458                        if( buffer[i] == '\0' )
     459                                break;
     460                }
     461        }
    388462       
    389463        /* NULL terminate our list. */
    390         lines[j] = NULL;
    391        
    392         lines[0] = buffer;
    393        
    394         /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    395          * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    396          */
    397         for( i = 0, j = 0; buffer[i] != '\0'; i ++)
    398         {
    399                 if( buffer[i] == '\n' )
    400                 {
    401                         buffer[i] = '\0';
    402                        
    403                         if( i > 0 && buffer[i-1] == '\r' )
    404                                 buffer[i-1] = '\0';
    405                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    406                                 lines[++j] = buffer + i + 1;
    407                 }
    408         }
    409        
    410         return( lines );
     464        lines[++j] = NULL;
     465       
     466        return lines;
    411467}
    412468
     
    542598
    543599        return;
    544 
    545600}
    546601
     
    548603{
    549604        int size;
    550         char line[IRC_MAX_LINE+1], *cs;
     605        char line[IRC_MAX_LINE+1];
    551606               
    552607        /* Don't try to write anything new anymore when shutting down. */
     
    554609                return;
    555610       
    556         line[IRC_MAX_LINE] = 0;
     611        memset( line, 0, sizeof( line ) );
    557612        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
    558        
    559613        strip_newlines( line );
    560         if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
    561         {
    562                 char conv[IRC_MAX_LINE+1];
    563                
    564                 conv[IRC_MAX_LINE] = 0;
    565                 if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 )
    566                         strcpy( line, conv );
    567         }
    568         strcat( line, "\r\n" );
     614       
     615        if( irc->oconv != (GIConv) -1 )
     616        {
     617                gsize bytes_read, bytes_written;
     618                char *conv;
     619               
     620                conv = g_convert_with_iconv( line, -1, irc->oconv,
     621                                             &bytes_read, &bytes_written, NULL );
     622
     623                if( bytes_read == strlen( line ) )
     624                        strncpy( line, conv, IRC_MAX_LINE - 2 );
     625               
     626                g_free( conv );
     627        }
     628        g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
    569629       
    570630        if( irc->sendbuffer != NULL )
     
    739799        irc_spawn( irc, u );
    740800       
    741         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." );
     801        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
     802                          "If you've never used BitlBee before, please do read the help "
     803                          "information using the \x02help\x02 command. Lots of FAQs are "
     804                          "answered there.\n"
     805                          "If you already have an account on this server, just use the "
     806                          "\x02identify\x02 command to identify yourself." );
    742807       
    743808        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     
    745810       
    746811        irc->status |= USTATUS_LOGGED_IN;
     812       
     813        /* This is for bug #209 (use PASS to identify to NickServ). */
     814        if( irc->password != NULL )
     815        {
     816                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     817               
     818                irc_setpass( irc, NULL );
     819                root_command( irc, send_cmd );
     820                g_free( send_cmd[1] );
     821        }
    747822}
    748823
Note: See TracChangeset for help on using the changeset viewer.