Changes in irc.c [a83442a:1195cec]
Legend:
- Unmodified
- Added
- Removed
-
irc.c
ra83442a r1195cec 42 42 } 43 43 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 44 73 irc_t *irc_new( int fd ) 45 74 { … … 64 93 irc->mynick = g_strdup( ROOT_NICK ); 65 94 irc->channel = g_strdup( ROOT_CHAN ); 95 96 irc->iconv = (GIConv) -1; 97 irc->oconv = (GIConv) -1; 66 98 67 99 if( global.conf->hostname ) … … 119 151 set_add( &irc->set, "private", "true", set_eval_bool, irc ); 120 152 set_add( &irc->set, "query_order", "lifo", NULL, irc ); 153 set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); 121 154 set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); 122 155 set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); … … 127 160 conf_loaddefaults( irc ); 128 161 162 /* Evaluator sets the iconv/oconv structures. */ 163 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 164 129 165 return( irc ); 130 166 } … … 164 200 if( irc->sendbuffer && !immed ) 165 201 { 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. */ 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. */ 169 204 170 205 b_event_remove( irc->r_watch_source_id ); 171 irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc ); 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 ); 172 210 } 173 211 else … … 185 223 186 224 /* Because we have no garbage collection, this is quite annoying */ 187 void irc_free(irc_t * irc) 188 { 189 account_t *account; 225 void irc_free( irc_t * irc ) 226 { 190 227 user_t *user, *usertmp; 191 228 … … 196 233 irc_usermsg( irc, "Error while saving settings!" ); 197 234 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 206 235 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 207 236 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); 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 ); 236 246 else 237 247 /* Nasty hack, but account_del() doesn't work in this 238 248 case and we don't want infinite loops, do we? ;-) */ 239 249 irc->accounts = irc->accounts->next; 240 241 while (irc->set) 242 set_del(&irc->set, irc->set->key); 243 244 if (irc->users != NULL) { 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 { 245 260 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); 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 ); 254 270 255 271 usertmp = user; 256 272 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); 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 ); 268 315 269 316 if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) … … 286 333 void irc_process( irc_t *irc ) 287 334 { 288 char **lines, *temp, **cmd , *cs;335 char **lines, *temp, **cmd; 289 336 int i; 290 337 … … 295 342 for( i = 0; *lines[i] != '\0'; i ++ ) 296 343 { 297 char conv[IRC_MAX_LINE+1];344 char *conv = NULL; 298 345 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 */ 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. */ 302 348 if( lines[i+1] == NULL ) 303 349 { … … 309 355 } 310 356 311 if( ( cs = set_getstr( &irc->set, "charset" ) ) && g_strcasecmp( cs, "none" ) != 0 ) 312 { 313 conv[IRC_MAX_LINE] = 0; 314 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) 357 if( irc->iconv != (GIConv) -1 ) 358 { 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] ) ) 315 365 { 316 366 /* GLib can do strange things if things are not in the expected charset, … … 324 374 "expect by changing the charset setting. See " 325 375 "`help set charset' for more information. Your " 326 "message was ignored.", cs ); 327 *conv = 0; 376 "message was ignored.", 377 set_getstr( &irc->set, "charset" ) ); 378 379 g_free( conv ); 380 conv = NULL; 328 381 } 329 382 else … … 332 385 "Warning: invalid characters received at login time." ); 333 386 334 strncpy( conv, lines[i], IRC_MAX_LINE);387 conv = g_strdup( lines[i] ); 335 388 for( temp = conv; *temp; temp ++ ) 336 389 if( *temp & 0x80 ) … … 341 394 } 342 395 343 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) 344 continue; 345 irc_exec( irc, cmd ); 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 } 346 403 347 g_free( c md);404 g_free( conv ); 348 405 349 406 /* Shouldn't really happen, but just in case... */ … … 369 426 char **irc_tokenize( char *buffer ) 370 427 { 371 int i, j ;428 int i, j, n = 3; 372 429 char **lines; 373 430 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 ); 431 /* Allocate n+1 elements. */ 432 lines = g_new( char *, n + 1 ); 433 434 lines[0] = buffer; 435 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'; 445 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 } 384 458 385 459 /* 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 ); 460 lines[++j] = NULL; 461 462 return lines; 407 463 } 408 464 … … 538 594 539 595 return; 540 541 596 } 542 597 … … 544 599 { 545 600 int size; 546 char line[IRC_MAX_LINE+1] , *cs;601 char line[IRC_MAX_LINE+1]; 547 602 548 603 /* Don't try to write anything new anymore when shutting down. */ … … 550 605 return; 551 606 552 line[IRC_MAX_LINE] = 0;607 memset( line, 0, sizeof( line ) ); 553 608 g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); 554 555 609 strip_newlines( line ); 556 if( ( cs = set_getstr( &irc->set, "charset" ) ) && 557 g_strcasecmp( cs, "none" ) != 0 && g_strcasecmp( cs, "utf-8" ) != 0 ) 558 { 559 char conv[IRC_MAX_LINE+1]; 560 561 conv[IRC_MAX_LINE] = 0; 562 if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 ) 563 strcpy( line, conv ); 564 } 565 strcat( line, "\r\n" ); 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 ); 566 625 567 626 if( irc->sendbuffer != NULL ) … … 736 795 irc_spawn( irc, u ); 737 796 738 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." ); 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." ); 739 803 740 804 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) … … 742 806 743 807 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 } 744 818 } 745 819
Note: See TracChangeset
for help on using the changeset viewer.