- Timestamp:
- 2008-07-16T23:22:52Z (16 years ago)
- Branches:
- master
- Children:
- 9b55485
- Parents:
- 9730d72 (diff), 6a78c0e (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
irc.c
r9730d72 r6738a67 26 26 #define BITLBEE_CORE 27 27 #include "bitlbee.h" 28 #include "sock.h" 28 29 #include "crypting.h" 29 30 #include "ipc.h" … … 45 46 } 46 47 48 static 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 47 77 irc_t *irc_new( int fd ) 48 78 { … … 67 97 irc->mynick = g_strdup( ROOT_NICK ); 68 98 irc->channel = g_strdup( ROOT_CHAN ); 99 100 irc->iconv = (GIConv) -1; 101 irc->oconv = (GIConv) -1; 69 102 70 103 if( global.conf->hostname ) … … 126 159 set_add( &irc->set, "private", "true", set_eval_bool, irc ); 127 160 set_add( &irc->set, "query_order", "lifo", NULL, irc ); 161 set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); 128 162 set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); 129 163 set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); … … 137 171 irc->otr = otr_new(); 138 172 173 /* Evaluator sets the iconv/oconv structures. */ 174 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 175 139 176 return( irc ); 140 177 } … … 174 211 if( irc->sendbuffer && !immed ) 175 212 { 176 /* We won't read from this socket anymore. Instead, we'll connect a timer 177 to it that should shut down the connection in a second, just in case 178 bitlbee_.._write doesn't do it first. */ 213 /* Set up a timeout event that should shut down the connection 214 in a second, just in case ..._write doesn't do it first. */ 179 215 180 216 b_event_remove( irc->r_watch_source_id ); 181 irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc ); 217 irc->r_watch_source_id = 0; 218 219 b_event_remove( irc->ping_source_id ); 220 irc->ping_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc ); 182 221 } 183 222 else … … 195 234 196 235 /* Because we have no garbage collection, this is quite annoying */ 197 void irc_free(irc_t * irc) 198 { 199 account_t *account; 236 void irc_free( irc_t * irc ) 237 { 200 238 user_t *user, *usertmp; 201 239 … … 206 244 irc_usermsg( irc, "Error while saving settings!" ); 207 245 208 closesocket( irc->fd );209 210 if( irc->ping_source_id > 0 )211 b_event_remove( irc->ping_source_id );212 b_event_remove( irc->r_watch_source_id );213 if( irc->w_watch_source_id > 0 )214 b_event_remove( irc->w_watch_source_id );215 216 246 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 217 247 218 for (account = irc->accounts; account; account = account->next) { 219 if (account->ic) { 220 imc_logout(account->ic, TRUE); 221 } else if (account->reconnect) { 222 cancel_auto_reconnect(account); 223 } 224 } 225 226 g_free(irc->sendbuffer); 227 g_free(irc->readbuffer); 228 229 g_free(irc->nick); 230 g_free(irc->user); 231 g_free(irc->host); 232 g_free(irc->realname); 233 g_free(irc->password); 234 235 g_free(irc->myhost); 236 g_free(irc->mynick); 237 238 g_free(irc->channel); 239 240 while (irc->queries != NULL) 241 query_del(irc, irc->queries); 242 243 while (irc->accounts) 244 if (irc->accounts->ic == NULL) 245 account_del(irc, irc->accounts); 248 while( irc->accounts ) 249 { 250 if( irc->accounts->ic ) 251 imc_logout( irc->accounts->ic, FALSE ); 252 else if( irc->accounts->reconnect ) 253 cancel_auto_reconnect( irc->accounts ); 254 255 if( irc->accounts->ic == NULL ) 256 account_del( irc, irc->accounts ); 246 257 else 247 258 /* Nasty hack, but account_del() doesn't work in this 248 259 case and we don't want infinite loops, do we? ;-) */ 249 260 irc->accounts = irc->accounts->next; 250 251 while (irc->set) 252 set_del(&irc->set, irc->set->key); 253 254 if (irc->users != NULL) { 261 } 262 263 while( irc->queries != NULL ) 264 query_del( irc, irc->queries ); 265 266 while( irc->set ) 267 set_del( &irc->set, irc->set->key ); 268 269 if (irc->users != NULL) 270 { 255 271 user = irc->users; 256 while (user != NULL) { 257 g_free(user->nick); 258 g_free(user->away); 259 g_free(user->handle); 260 if(user->user!=user->nick) g_free(user->user); 261 if(user->host!=user->nick) g_free(user->host); 262 if(user->realname!=user->nick) g_free(user->realname); 263 b_event_remove(user->sendbuf_timer); 272 while( user != NULL ) 273 { 274 g_free( user->nick ); 275 g_free( user->away ); 276 g_free( user->handle ); 277 if( user->user != user->nick ) g_free( user->user ); 278 if( user->host != user->nick ) g_free( user->host ); 279 if( user->realname != user->nick ) g_free( user->realname ); 280 b_event_remove( user->sendbuf_timer ); 264 281 265 282 usertmp = user; 266 283 user = user->next; 267 g_free(usertmp); 268 } 269 } 270 271 g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL); 272 g_hash_table_destroy(irc->userhash); 273 274 g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); 275 g_hash_table_destroy(irc->watches); 284 g_free( usertmp ); 285 } 286 } 287 288 if( irc->ping_source_id > 0 ) 289 b_event_remove( irc->ping_source_id ); 290 if( irc->r_watch_source_id > 0 ) 291 b_event_remove( irc->r_watch_source_id ); 292 if( irc->w_watch_source_id > 0 ) 293 b_event_remove( irc->w_watch_source_id ); 294 295 closesocket( irc->fd ); 296 irc->fd = -1; 297 298 g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL ); 299 g_hash_table_destroy( irc->userhash ); 300 301 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); 302 g_hash_table_destroy( irc->watches ); 303 304 if( irc->iconv != (GIConv) -1 ) 305 g_iconv_close( irc->iconv ); 306 if( irc->oconv != (GIConv) -1 ) 307 g_iconv_close( irc->oconv ); 308 309 g_free( irc->sendbuffer ); 310 g_free( irc->readbuffer ); 311 312 g_free( irc->nick ); 313 g_free( irc->user ); 314 g_free( irc->host ); 315 g_free( irc->realname ); 316 g_free( irc->password ); 317 318 g_free( irc->myhost ); 319 g_free( irc->mynick ); 320 321 g_free( irc->channel ); 322 323 g_free( irc->last_target ); 276 324 277 325 otr_free(irc->otr); 278 326 279 g_free(irc); 280 281 if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) 327 g_free( irc ); 328 329 if( global.conf->runmode == RUNMODE_INETD || 330 global.conf->runmode == RUNMODE_FORKDAEMON || 331 ( global.conf->runmode == RUNMODE_DAEMON && 332 global.listen_socket == -1 && 333 irc_connection_list == NULL ) ) 282 334 b_main_quit(); 283 335 } … … 298 350 void irc_process( irc_t *irc ) 299 351 { 300 char **lines, *temp, **cmd , *cs;352 char **lines, *temp, **cmd; 301 353 int i; 302 354 … … 307 359 for( i = 0; *lines[i] != '\0'; i ++ ) 308 360 { 309 char conv[IRC_MAX_LINE+1];361 char *conv = NULL; 310 362 311 /* [WvG] Because irc_tokenize splits at every newline, the lines[] list 312 should end with an empty string. This is why this actually works. 313 Took me a while to figure out, Maurits. :-P */ 363 /* [WvG] If the last line isn't empty, it's an incomplete line and we 364 should wait for the rest to come in before processing it. */ 314 365 if( lines[i+1] == NULL ) 315 366 { … … 321 372 } 322 373 323 if( ( cs = set_getstr( &irc->set, "charset" ) ) ) 324 { 325 conv[IRC_MAX_LINE] = 0; 326 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) 374 if( irc->iconv != (GIConv) -1 ) 375 { 376 gsize bytes_read, bytes_written; 377 378 conv = g_convert_with_iconv( lines[i], -1, irc->iconv, 379 &bytes_read, &bytes_written, NULL ); 380 381 if( conv == NULL || bytes_read != strlen( lines[i] ) ) 327 382 { 328 383 /* GLib can do strange things if things are not in the expected charset, … … 336 391 "expect by changing the charset setting. See " 337 392 "`help set charset' for more information. Your " 338 "message was ignored.", cs ); 339 *conv = 0; 393 "message was ignored.", 394 set_getstr( &irc->set, "charset" ) ); 395 396 g_free( conv ); 397 conv = NULL; 340 398 } 341 399 else 342 400 { 343 401 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, 344 "Warning: invalid (non-UTF8)characters received at login time." );402 "Warning: invalid characters received at login time." ); 345 403 346 strncpy( conv, lines[i], IRC_MAX_LINE);404 conv = g_strdup( lines[i] ); 347 405 for( temp = conv; *temp; temp ++ ) 348 406 if( *temp & 0x80 ) … … 353 411 } 354 412 355 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) 356 continue; 357 irc_exec( irc, cmd ); 413 if( lines[i] ) 414 { 415 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) 416 continue; 417 irc_exec( irc, cmd ); 418 g_free( cmd ); 419 } 358 420 359 g_free( c md);421 g_free( conv ); 360 422 361 423 /* Shouldn't really happen, but just in case... */ … … 381 443 char **irc_tokenize( char *buffer ) 382 444 { 383 int i, j ;445 int i, j, n = 3; 384 446 char **lines; 385 447 386 /* Count the number of elements we're gonna need. */ 387 for( i = 0, j = 1; buffer[i] != '\0'; i ++ ) 388 { 389 if( buffer[i] == '\n' ) 390 if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) 391 j ++; 392 } 393 394 /* Allocate j+1 elements. */ 395 lines = g_new( char *, j + 1 ); 448 /* Allocate n+1 elements. */ 449 lines = g_new( char *, n + 1 ); 450 451 lines[0] = buffer; 452 453 /* Split the buffer in several strings, and accept any kind of line endings, 454 * knowing that ERC on Windows may send something interesting like \r\r\n, 455 * and surely there must be clients that think just \n is enough... */ 456 for( i = 0, j = 0; buffer[i] != '\0'; i ++ ) 457 { 458 if( buffer[i] == '\r' || buffer[i] == '\n' ) 459 { 460 while( buffer[i] == '\r' || buffer[i] == '\n' ) 461 buffer[i++] = '\0'; 462 463 lines[++j] = buffer + i; 464 465 if( j >= n ) 466 { 467 n *= 2; 468 lines = g_renew( char *, lines, n + 1 ); 469 } 470 471 if( buffer[i] == '\0' ) 472 break; 473 } 474 } 396 475 397 476 /* NULL terminate our list. */ 398 lines[j] = NULL; 399 400 lines[0] = buffer; 401 402 /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional. 403 * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too. 404 */ 405 for( i = 0, j = 0; buffer[i] != '\0'; i ++) 406 { 407 if( buffer[i] == '\n' ) 408 { 409 buffer[i] = '\0'; 410 411 if( i > 0 && buffer[i-1] == '\r' ) 412 buffer[i-1] = '\0'; 413 if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) 414 lines[++j] = buffer + i + 1; 415 } 416 } 417 418 return( lines ); 477 lines[++j] = NULL; 478 479 return lines; 419 480 } 420 481 … … 550 611 551 612 return; 552 553 613 } 554 614 … … 556 616 { 557 617 int size; 558 char line[IRC_MAX_LINE+1] , *cs;618 char line[IRC_MAX_LINE+1]; 559 619 560 620 /* Don't try to write anything new anymore when shutting down. */ … … 562 622 return; 563 623 564 line[IRC_MAX_LINE] = 0;624 memset( line, 0, sizeof( line ) ); 565 625 g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); 566 567 626 strip_newlines( line ); 568 if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) 569 { 570 char conv[IRC_MAX_LINE+1]; 571 572 conv[IRC_MAX_LINE] = 0; 573 if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 ) 574 strcpy( line, conv ); 575 } 576 strcat( line, "\r\n" ); 627 628 if( irc->oconv != (GIConv) -1 ) 629 { 630 gsize bytes_read, bytes_written; 631 char *conv; 632 633 conv = g_convert_with_iconv( line, -1, irc->oconv, 634 &bytes_read, &bytes_written, NULL ); 635 636 if( bytes_read == strlen( line ) ) 637 strncpy( line, conv, IRC_MAX_LINE - 2 ); 638 639 g_free( conv ); 640 } 641 g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 ); 577 642 578 643 if( irc->sendbuffer != NULL ) … … 753 818 irc->umode[0] = '\0'; 754 819 irc_umode_set( irc, "+" UMODE, 1 ); 755 756 u = user_add( irc, irc->mynick ); 820 u = user_add( irc, irc->mynick ); 757 821 u->host = g_strdup( irc->myhost ); 758 822 u->realname = g_strdup( ROOT_FN ); … … 782 846 783 847 irc->status |= USTATUS_LOGGED_IN; 848 849 /* This is for bug #209 (use PASS to identify to NickServ). */ 850 if( irc->password != NULL ) 851 { 852 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 853 854 irc_setpass( irc, NULL ); 855 root_command( irc, send_cmd ); 856 g_free( send_cmd[1] ); 857 } 784 858 } 785 859 … … 791 865 if( !f ) 792 866 { 793 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.\n\nOTR users please note: Private key files are owned by the user BitlBee is running as." ); 867 irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n" 868 "If you've never used BitlBee before, please do read the help " 869 "information using the \x02help\x02 command. Lots of FAQs are " 870 "answered there.\n" 871 "OTR users please note: Private key files are owned by the user " 872 "BitlBee is running as.\n" 873 "If you already have an account on this server, just use the " 874 "\x02identify\x02 command to identify yourself." ); 794 875 } 795 876 else
Note: See TracChangeset
for help on using the changeset viewer.