Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    rc84e31a rfa75134  
    4242}
    4343
     44static 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
    4473irc_t *irc_new( int fd )
    4574{
     
    6493        irc->mynick = g_strdup( ROOT_NICK );
    6594        irc->channel = g_strdup( ROOT_CHAN );
     95       
     96        irc->iconv = (GIConv) -1;
     97        irc->oconv = (GIConv) -1;
    6698       
    6799        if( global.conf->hostname )
     
    127159        conf_loaddefaults( irc );
    128160       
     161        /* Evaluator sets the iconv/oconv structures. */
     162        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
     163       
    129164        return( irc );
    130165}
     
    185220
    186221/* Because we have no garbage collection, this is quite annoying */
    187 void irc_free(irc_t * irc)
    188 {
    189         account_t *account;
     222void irc_free( irc_t * irc )
     223{
    190224        user_t *user, *usertmp;
    191225       
     
    196230                        irc_usermsg( irc, "Error while saving settings!" );
    197231       
    198         closesocket( irc->fd );
     232        irc_connection_list = g_slist_remove( irc_connection_list, irc );
     233       
     234        while( irc->accounts )
     235        {
     236                if( irc->accounts->ic )
     237                        imc_logout( irc->accounts->ic, FALSE );
     238                else if( irc->accounts->reconnect )
     239                        cancel_auto_reconnect( irc->accounts );
     240               
     241                if( irc->accounts->ic == NULL )
     242                        account_del( irc, irc->accounts );
     243                else
     244                        /* Nasty hack, but account_del() doesn't work in this
     245                           case and we don't want infinite loops, do we? ;-) */
     246                        irc->accounts = irc->accounts->next;
     247        }
     248       
     249        while( irc->queries != NULL )
     250                query_del( irc, irc->queries );
     251       
     252        while( irc->set )
     253                set_del( &irc->set, irc->set->key );
     254       
     255        if (irc->users != NULL)
     256        {
     257                user = irc->users;
     258                while( user != NULL )
     259                {
     260                        g_free( user->nick );
     261                        g_free( user->away );
     262                        g_free( user->handle );
     263                        if( user->user != user->nick ) g_free( user->user );
     264                        if( user->host != user->nick ) g_free( user->host );
     265                        if( user->realname != user->nick ) g_free( user->realname );
     266                        b_event_remove( user->sendbuf_timer );
     267                                       
     268                        usertmp = user;
     269                        user = user->next;
     270                        g_free( usertmp );
     271                }
     272        }
    199273       
    200274        if( irc->ping_source_id > 0 )
     
    204278                b_event_remove( irc->w_watch_source_id );
    205279       
    206         irc_connection_list = g_slist_remove( irc_connection_list, irc );
    207        
    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);
    236                 else
    237                         /* Nasty hack, but account_del() doesn't work in this
    238                            case and we don't want infinite loops, do we? ;-) */
    239                         irc->accounts = irc->accounts->next;
    240        
    241         while (irc->set)
    242                 set_del(&irc->set, irc->set->key);
    243        
    244         if (irc->users != NULL) {
    245                 user = irc->users;
    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);
    254                                        
    255                         usertmp = user;
    256                         user = user->next;
    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);
     280        closesocket( irc->fd );
     281        irc->fd = -1;
     282       
     283        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     284        g_hash_table_destroy( irc->userhash );
     285       
     286        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     287        g_hash_table_destroy( irc->watches );
     288       
     289        if( irc->iconv != (GIConv) -1 )
     290                g_iconv_close( irc->iconv );
     291        if( irc->oconv != (GIConv) -1 )
     292                g_iconv_close( irc->oconv );
     293       
     294        g_free( irc->sendbuffer );
     295        g_free( irc->readbuffer );
     296       
     297        g_free( irc->nick );
     298        g_free( irc->user );
     299        g_free( irc->host );
     300        g_free( irc->realname );
     301        g_free( irc->password );
     302       
     303        g_free( irc->myhost );
     304        g_free( irc->mynick );
     305       
     306        g_free( irc->channel );
     307       
     308        g_free( irc->last_target );
     309       
     310        g_free( irc );
    268311       
    269312        if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
     
    286329void irc_process( irc_t *irc )
    287330{
    288         char **lines, *temp, **cmd, *cs;
     331        char **lines, *temp, **cmd;
    289332        int i;
    290333
     
    295338                for( i = 0; *lines[i] != '\0'; i ++ )
    296339                {
    297                         char conv[IRC_MAX_LINE+1];
     340                        char *conv = NULL;
    298341                       
    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 */
     342                        /* [WvG] If the last line isn't empty, it's an incomplete line and we
     343                           should wait for the rest to come in before processing it. */
    302344                        if( lines[i+1] == NULL )
    303345                        {
     
    309351                        }
    310352                       
    311                         if( ( cs = set_getstr( &irc->set, "charset" ) ) )
    312                         {
    313                                 conv[IRC_MAX_LINE] = 0;
    314                                 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 )
     353                        if( irc->iconv != (GIConv) -1 )
     354                        {
     355                                gsize bytes_read, bytes_written;
     356                               
     357                                conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
     358                                                             &bytes_read, &bytes_written, NULL );
     359                               
     360                                if( conv == NULL || bytes_read != strlen( lines[i] ) )
    315361                                {
    316362                                        /* GLib can do strange things if things are not in the expected charset,
     
    324370                                                                  "expect by changing the charset setting. See "
    325371                                                                  "`help set charset' for more information. Your "
    326                                                                   "message was ignored.", cs );
    327                                                 *conv = 0;
     372                                                                  "message was ignored.",
     373                                                                  set_getstr( &irc->set, "charset" ) );
     374                                               
     375                                                g_free( conv );
     376                                                conv = NULL;
    328377                                        }
    329378                                        else
    330379                                        {
    331380                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    332                                                            "Warning: invalid (non-UTF8) characters received at login time." );
     381                                                           "Warning: invalid characters received at login time." );
    333382                                               
    334                                                 strncpy( conv, lines[i], IRC_MAX_LINE );
     383                                                conv = g_strdup( lines[i] );
    335384                                                for( temp = conv; *temp; temp ++ )
    336385                                                        if( *temp & 0x80 )
     
    341390                        }
    342391                       
    343                         if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    344                                 continue;
    345                         irc_exec( irc, cmd );
     392                        if( lines[i] )
     393                        {
     394                                if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     395                                        continue;
     396                                irc_exec( irc, cmd );
     397                                g_free( cmd );
     398                        }
    346399                       
    347                         g_free( cmd );
     400                        g_free( conv );
    348401                       
    349402                        /* Shouldn't really happen, but just in case... */
     
    369422char **irc_tokenize( char *buffer )
    370423{
    371         int i, j;
     424        int i, j, n = 3;
    372425        char **lines;
    373426
    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 );
     427        /* Allocate n+1 elements. */
     428        lines = g_new( char *, n + 1 );
     429       
     430        lines[0] = buffer;
     431       
     432        /* Split the buffer in several strings, and accept any kind of line endings,
     433         * knowing that ERC on Windows may send something interesting like \r\r\n,
     434         * and surely there must be clients that think just \n is enough... */
     435        for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
     436        {
     437                if( buffer[i] == '\r' || buffer[i] == '\n' )
     438                {
     439                        while( buffer[i] == '\r' || buffer[i] == '\n' )
     440                                buffer[i++] = '\0';
     441                       
     442                        lines[++j] = buffer + i;
     443                       
     444                        if( j >= n )
     445                        {
     446                                n *= 2;
     447                                lines = g_renew( char *, lines, n + 1 );
     448                        }
     449
     450                        if( buffer[i] == '\0' )
     451                                break;
     452                }
     453        }
    384454       
    385455        /* NULL terminate our list. */
    386         lines[j] = NULL;
    387        
    388         lines[0] = buffer;
    389        
    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';
    398                        
    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 );
     456        lines[++j] = NULL;
     457       
     458        return lines;
    407459}
    408460
     
    538590
    539591        return;
    540 
    541592}
    542593
     
    544595{
    545596        int size;
    546         char line[IRC_MAX_LINE+1], *cs;
     597        char line[IRC_MAX_LINE+1];
    547598               
    548599        /* Don't try to write anything new anymore when shutting down. */
     
    550601                return;
    551602       
    552         line[IRC_MAX_LINE] = 0;
     603        memset( line, 0, sizeof( line ) );
    553604        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
    554        
    555605        strip_newlines( line );
    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" );
     606       
     607        if( irc->oconv != (GIConv) -1 )
     608        {
     609                gsize bytes_read, bytes_written;
     610                char *conv;
     611               
     612                conv = g_convert_with_iconv( line, -1, irc->oconv,
     613                                             &bytes_read, &bytes_written, NULL );
     614
     615                if( bytes_read == strlen( line ) )
     616                        strncpy( line, conv, IRC_MAX_LINE - 2 );
     617               
     618                g_free( conv );
     619        }
     620        g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
    565621       
    566622        if( irc->sendbuffer != NULL )
     
    735791        irc_spawn( irc, u );
    736792       
    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." );
     793        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
     794                          "If you've never used BitlBee before, please do read the help "
     795                          "information using the \x02help\x02 command. Lots of FAQs are "
     796                          "answered there.\n"
     797                          "If you already have an account on this server, just use the "
     798                          "\x02identify\x02 command to identify yourself." );
    738799       
    739800        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     
    741802       
    742803        irc->status |= USTATUS_LOGGED_IN;
     804       
     805        /* This is for bug #209 (use PASS to identify to NickServ). */
     806        if( irc->password != NULL )
     807        {
     808                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     809               
     810                irc_setpass( irc, NULL );
     811                root_command( irc, send_cmd );
     812                g_free( send_cmd[1] );
     813        }
    743814}
    744815
Note: See TracChangeset for help on using the changeset viewer.