Changes in / [fc50d48:55ec2d6]
- Files:
-
- 3 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
rfc50d48 r55ec2d6 10 10 11 11 # Program variables 12 objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o i rc.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o12 objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o 13 13 subdirs = protocols 14 14 -
bitlbee.c
rfc50d48 r55ec2d6 29 29 #include "protocols/nogaim.h" 30 30 #include "help.h" 31 #include "ipc.h" 31 32 #include <signal.h> 32 33 #include <stdio.h> 33 34 #include <errno.h> 34 35 35 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data ) 36 { 37 size_t size = sizeof( struct sockaddr_in ); 38 struct sockaddr_in conn_info; 39 int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size ); 40 pid_t client_pid = 0; 41 42 if( global.conf->runmode == RUNMODE_FORKDAEMON ) 43 client_pid = fork(); 44 45 if( client_pid == 0 ) 46 { 47 log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); 48 irc_new( new_socket ); 49 50 if( global.conf->runmode == RUNMODE_FORKDAEMON ) 51 { 52 /* Close the listening socket, we're a client. */ 53 close( global.listen_socket ); 54 g_source_remove( global.listen_watch_source_id ); 55 } 56 } 57 else 58 { 59 /* We don't need this one, only the client does. */ 60 close( new_socket ); 61 62 /* Or maybe we didn't even get a child process... */ 63 if( client_pid == -1 ) 64 log_message( LOGLVL_ERROR, "Failed to fork() subprocess for client: %s", strerror( errno ) ); 65 } 66 67 return TRUE; 68 } 69 70 36 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data ); 71 37 72 38 int bitlbee_daemon_init() … … 89 55 return( -1 ); 90 56 } 57 58 /* TIME_WAIT (?) sucks.. */ 59 i = 1; 60 setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); 91 61 92 62 #ifdef IPV6 … … 257 227 } 258 228 229 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data ) 230 { 231 size_t size = sizeof( struct sockaddr_in ); 232 struct sockaddr_in conn_info; 233 int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size ); 234 pid_t client_pid = 0; 235 236 if( global.conf->runmode == RUNMODE_FORKDAEMON ) 237 { 238 int fds[2]; 239 240 if( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 ) 241 { 242 log_message( LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror( errno ) ); 243 fds[0] = fds[1] = -1; 244 } 245 246 sock_make_nonblocking( fds[0] ); 247 sock_make_nonblocking( fds[1] ); 248 249 client_pid = fork(); 250 251 if( client_pid > 0 && fds[0] != -1 ) 252 { 253 struct bitlbee_child *child; 254 255 child = g_new0( struct bitlbee_child, 1 ); 256 child->pid = client_pid; 257 child->ipc_fd = fds[0]; 258 child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); 259 child_list = g_slist_append( child_list, child ); 260 261 log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid ); 262 263 /* Close some things we don't need in the parent process. */ 264 close( new_socket ); 265 close( fds[1] ); 266 } 267 else if( client_pid == 0 ) 268 { 269 irc_t *irc; 270 271 /* Close the listening socket, we're a client. */ 272 close( global.listen_socket ); 273 g_source_remove( global.listen_watch_source_id ); 274 275 /* Make the connection. */ 276 irc = irc_new( new_socket ); 277 278 /* We can store the IPC fd there now. */ 279 global.listen_socket = fds[1]; 280 global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc ); 281 282 close( fds[0] ); 283 284 ipc_master_free_all(); 285 } 286 } 287 else 288 { 289 log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); 290 irc_new( new_socket ); 291 } 292 293 return TRUE; 294 } 295 259 296 void bitlbee_shutdown( gpointer data ) 260 297 { -
bitlbee.h
rfc50d48 r55ec2d6 112 112 #include "sock.h" 113 113 114 typedef struct global_t { 114 typedef struct global { 115 /* In forked mode, child processes store the fd of the IPC socket here. */ 115 116 int listen_socket; 116 117 gint listen_watch_source_id; -
commands.c
rfc50d48 r55ec2d6 32 32 #include <string.h> 33 33 34 const command_t commands[] = {35 { "help", 0, cmd_help },36 { "identify", 1, cmd_identify },37 { "register", 1, cmd_register },38 { "drop", 1, cmd_drop },39 { "account", 1, cmd_account },40 { "add", 2, cmd_add },41 { "info", 1, cmd_info },42 { "rename", 2, cmd_rename },43 { "remove", 1, cmd_remove },44 { "block", 1, cmd_block },45 { "allow", 1, cmd_allow },46 { "save", 0, cmd_save },47 { "set", 0, cmd_set },48 { "yes", 0, cmd_yesno },49 { "no", 0, cmd_yesno },50 { "blist", 0, cmd_blist },51 { "nick", 1, cmd_nick },52 { "import_buddies", 1, cmd_import_buddies },53 { "qlist", 0, cmd_qlist },54 { NULL }55 };56 57 34 int root_command_string( irc_t *irc, user_t *u, char *command, int flags ) 58 35 { … … 114 91 } 115 92 116 int cmd_help( irc_t *irc, char **cmd )93 static int cmd_help( irc_t *irc, char **cmd ) 117 94 { 118 95 char param[80]; … … 143 120 } 144 121 145 int cmd_identify( irc_t *irc, char **cmd )122 static int cmd_identify( irc_t *irc, char **cmd ) 146 123 { 147 124 storage_status_t status = storage_load( irc->nick, cmd[1], irc ); … … 166 143 } 167 144 168 int cmd_register( irc_t *irc, char **cmd )145 static int cmd_register( irc_t *irc, char **cmd ) 169 146 { 170 147 if( global.conf->authmode == AUTHMODE_REGISTERED ) … … 193 170 } 194 171 195 int cmd_drop( irc_t *irc, char **cmd )172 static int cmd_drop( irc_t *irc, char **cmd ) 196 173 { 197 174 storage_status_t status; … … 217 194 } 218 195 219 int cmd_account( irc_t *irc, char **cmd )196 static int cmd_account( irc_t *irc, char **cmd ) 220 197 { 221 198 account_t *a; … … 377 354 } 378 355 379 int cmd_add( irc_t *irc, char **cmd )356 static int cmd_add( irc_t *irc, char **cmd ) 380 357 { 381 358 account_t *a; … … 417 394 } 418 395 419 int cmd_info( irc_t *irc, char **cmd )396 static int cmd_info( irc_t *irc, char **cmd ) 420 397 { 421 398 struct gaim_connection *gc; … … 454 431 } 455 432 456 int cmd_rename( irc_t *irc, char **cmd )433 static int cmd_rename( irc_t *irc, char **cmd ) 457 434 { 458 435 user_t *u; … … 495 472 } 496 473 497 int cmd_remove( irc_t *irc, char **cmd )474 static int cmd_remove( irc_t *irc, char **cmd ) 498 475 { 499 476 user_t *u; … … 517 494 } 518 495 519 int cmd_block( irc_t *irc, char **cmd )496 static int cmd_block( irc_t *irc, char **cmd ) 520 497 { 521 498 struct gaim_connection *gc; … … 558 535 } 559 536 560 int cmd_allow( irc_t *irc, char **cmd )537 static int cmd_allow( irc_t *irc, char **cmd ) 561 538 { 562 539 struct gaim_connection *gc; … … 600 577 } 601 578 602 int cmd_yesno( irc_t *irc, char **cmd )579 static int cmd_yesno( irc_t *irc, char **cmd ) 603 580 { 604 581 query_t *q = NULL; … … 640 617 } 641 618 642 int cmd_set( irc_t *irc, char **cmd )619 static int cmd_set( irc_t *irc, char **cmd ) 643 620 { 644 621 if( cmd[1] && cmd[2] ) … … 666 643 } 667 644 668 int cmd_save( irc_t *irc, char **cmd )645 static int cmd_save( irc_t *irc, char **cmd ) 669 646 { 670 647 if( storage_save( irc, TRUE ) == STORAGE_OK ) … … 676 653 } 677 654 678 int cmd_blist( irc_t *irc, char **cmd )655 static int cmd_blist( irc_t *irc, char **cmd ) 679 656 { 680 657 int online = 0, away = 0, offline = 0; … … 722 699 } 723 700 724 int cmd_nick( irc_t *irc, char **cmd )701 static int cmd_nick( irc_t *irc, char **cmd ) 725 702 { 726 703 account_t *a; … … 758 735 } 759 736 760 int cmd_qlist( irc_t *irc, char **cmd )737 static int cmd_qlist( irc_t *irc, char **cmd ) 761 738 { 762 739 query_t *q = irc->queries; … … 780 757 } 781 758 782 int cmd_import_buddies( irc_t *irc, char **cmd )759 static int cmd_import_buddies( irc_t *irc, char **cmd ) 783 760 { 784 761 struct gaim_connection *gc; … … 832 809 return( 0 ); 833 810 } 811 812 const command_t commands[] = { 813 { "help", 0, cmd_help, 0 }, 814 { "identify", 1, cmd_identify, 0 }, 815 { "register", 1, cmd_register, 0 }, 816 { "drop", 1, cmd_drop, 0 }, 817 { "account", 1, cmd_account, 0 }, 818 { "add", 2, cmd_add, 0 }, 819 { "info", 1, cmd_info, 0 }, 820 { "rename", 2, cmd_rename, 0 }, 821 { "remove", 1, cmd_remove, 0 }, 822 { "block", 1, cmd_block, 0 }, 823 { "allow", 1, cmd_allow, 0 }, 824 { "save", 0, cmd_save, 0 }, 825 { "set", 0, cmd_set, 0 }, 826 { "yes", 0, cmd_yesno, 0 }, 827 { "no", 0, cmd_yesno, 0 }, 828 { "blist", 0, cmd_blist, 0 }, 829 { "nick", 1, cmd_nick, 0 }, 830 { "import_buddies", 1, cmd_import_buddies, 0 }, 831 { "qlist", 0, cmd_qlist, 0 }, 832 { NULL } 833 }; -
commands.h
rfc50d48 r55ec2d6 29 29 #include "bitlbee.h" 30 30 31 typedef struct command _t31 typedef struct command 32 32 { 33 33 char *command; 34 34 int required_parameters; 35 35 int (*execute)(irc_t *, char **args); 36 int flags; 36 37 } command_t; 37 38 int cmd_account( irc_t *irc, char **cmd );39 int cmd_help( irc_t *irc, char **args);40 int cmd_info( irc_t *irc, char **args);41 int cmd_add( irc_t *irc, char **args) ;42 int cmd_rename( irc_t *irc, char **args );43 int cmd_remove( irc_t *irc, char **args );44 int cmd_block( irc_t *irc, char **args );45 int cmd_allow( irc_t *irc, char **args );46 int cmd_save( irc_t *irc, char **args );47 int cmd_set( irc_t *irc, char **args );48 int cmd_yesno( irc_t *irc, char **args );49 int cmd_identify( irc_t *irc, char **args );50 int cmd_register( irc_t *irc, char **args );51 int cmd_drop( irc_t *irc, char **args );52 int cmd_blist( irc_t *irc, char **cmd );53 int cmd_nick( irc_t *irc, char **cmd );54 int cmd_qlist( irc_t *irc, char **cmd );55 int cmd_import_buddies( irc_t *irc, char **cmd );56 int cmd_dump( irc_t *irc, char **cmd );57 38 58 39 extern const command_t commands[]; 59 40 41 #define IRC_CMD_PRE_LOGIN 1 42 #define IRC_CMD_LOGGED_IN 2 43 #define IRC_CMD_OPER_ONLY 4 44 #define IRC_CMD_TO_MASTER 8 45 46 #define IPC_CMD_TO_CHILDREN 1 47 60 48 #endif -
conf.c
rfc50d48 r55ec2d6 64 64 conf->ping_interval = 180; 65 65 conf->ping_timeout = 300; 66 proxytype = 0; 66 67 67 68 i = conf_loadini( conf, CONF_FILE ); … … 76 77 } 77 78 78 while( ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 ) 79 while( argc > 0 && ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 ) 80 /* ^^^^ Just to make sure we skip this step from the REHASH handler. */ 79 81 { 80 82 if( opt == 'i' ) … … 92 94 } 93 95 else if( opt == 'n' ) 94 conf->nofork =1;96 conf->nofork = 1; 95 97 else if( opt == 'v' ) 96 conf->verbose =1;98 conf->verbose = 1; 97 99 else if( opt == 'I' ) 98 conf->runmode =RUNMODE_INETD;100 conf->runmode = RUNMODE_INETD; 99 101 else if( opt == 'D' ) 100 conf->runmode =RUNMODE_DAEMON;102 conf->runmode = RUNMODE_DAEMON; 101 103 else if( opt == 'F' ) 102 conf->runmode =RUNMODE_FORKDAEMON;104 conf->runmode = RUNMODE_FORKDAEMON; 103 105 else if( opt == 'c' ) 104 106 { … … 108 110 CONF_FILE = g_strdup( optarg ); 109 111 g_free( conf ); 112 /* Re-evaluate arguments. Don't use this option twice, 113 you'll end up in an infinite loop! Hope this trick 114 works with all libcs BTW.. */ 115 optind = 1; 110 116 return( conf_load( argc, argv ) ); 111 117 } -
irc.c
rfc50d48 r55ec2d6 27 27 #include "bitlbee.h" 28 28 #include "crypting.h" 29 #include "ipc.h" 29 30 30 31 static gboolean irc_userping( gpointer _irc ); … … 204 205 205 206 /* Because we have no garbage collection, this is quite annoying */ 206 void irc_free( irc_t * irc)207 void irc_free(irc_t * irc) 207 208 { 208 209 account_t *account, *accounttmp; … … 217 218 if( storage_save( irc, TRUE ) != STORAGE_OK ) 218 219 irc_usermsg( irc, "Error while saving settings!" ); 220 221 closesocket( irc->fd ); 219 222 220 223 if( irc->ping_source_id > 0 ) … … 338 341 int irc_process( irc_t *irc ) 339 342 { 340 char **lines, *temp ;343 char **lines, *temp, **cmd; 341 344 int i; 342 345 343 if( irc->readbuffer != NULL ) { 344 lines = irc_tokenize(irc->readbuffer ); 345 for( i = 0; *lines[i] != '\0'; i++ ) { 346 if( lines[i+1] == NULL ) { 346 if( irc->readbuffer != NULL ) 347 { 348 lines = irc_tokenize( irc->readbuffer ); 349 350 for( i = 0; *lines[i] != '\0'; i ++ ) 351 { 352 if( lines[i+1] == NULL ) 353 { 347 354 temp = g_strdup( lines[i] ); 348 355 g_free( irc->readbuffer ); 349 356 irc->readbuffer = temp; 350 i ++;357 i ++; 351 358 break; 352 359 } 353 if (!irc_process_line(irc, lines[i])) { 360 361 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) 362 continue; 363 if( !irc_exec( irc, cmd ) ) 364 { 365 g_free( cmd ); 354 366 g_free( lines ); 355 367 return 0; 356 368 } 357 } 358 if(lines[i]!=NULL) { 359 g_free(irc->readbuffer); 360 irc->readbuffer=NULL; 361 } 369 370 g_free( cmd ); 371 } 372 373 if( lines[i] != NULL ) 374 { 375 g_free( irc->readbuffer ); 376 irc->readbuffer = NULL; 377 } 378 362 379 g_free( lines ); 363 380 } 381 364 382 return 1; 365 383 } … … 371 389 372 390 /* Count the number of elements we're gonna need. */ 373 for(i=0, j=1; buffer[i]!='\0'; i++ ) { 374 if(buffer[i]=='\n' ) 375 if(buffer[i+1]!='\r' && buffer[i+1]!='\n') 376 j++; 391 for( i = 0, j = 1; buffer[i] != '\0'; i ++ ) 392 { 393 if( buffer[i] == '\n' ) 394 if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) 395 j ++; 377 396 } 378 397 379 398 /* Allocate j+1 elements. */ 380 lines =g_new (char *, j+1);399 lines = g_new( char *, j + 1 ); 381 400 382 401 /* NULL terminate our list. */ 383 lines[j] =NULL;384 385 lines[0] =buffer;402 lines[j] = NULL; 403 404 lines[0] = buffer; 386 405 387 406 /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional. 388 407 * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too. 389 408 */ 390 for( i=0, j=0; buffer[i]!='\0'; i++) { 391 if(buffer[i]=='\n') { 392 buffer[i]='\0'; 393 394 /* We dont want to read 1 byte before our buffer 395 * and (in rare cases) generate a SIGSEGV. 396 */ 397 if(i!=0) 398 if(buffer[i-1]=='\r') 399 buffer[i-1]='\0'; 400 if(buffer[i+1]!='\r'&&buffer[i+1]!='\n') 401 lines[++j]=buffer+i+1; 402 } 403 } 404 405 return(lines); 406 } 407 408 int irc_process_line( irc_t *irc, char *line ) 409 for( i = 0, j = 0; buffer[i] != '\0'; i ++) 410 { 411 if( buffer[i] == '\n' ) 412 { 413 buffer[i] = '\0'; 414 415 if( i > 0 && buffer[i-1] == '\r' ) 416 buffer[i-1] = '\0'; 417 if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) 418 lines[++j] = buffer + i + 1; 419 } 420 } 421 422 return( lines ); 423 } 424 425 char **irc_parse_line( char *line ) 409 426 { 410 427 int i, j; … … 412 429 413 430 /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */ 414 if(line[0]==':') { 415 for(i=0; line[i]!=32; i++); 416 line=line+i; 417 } 418 for(i=0; line[i]==32; i++); 419 line=line+i; 420 431 if( line[0] == ':' ) 432 { 433 for( i = 0; line[i] != ' '; i ++ ); 434 line = line + i; 435 } 436 for( i = 0; line[i] == ' '; i ++ ); 437 line = line + i; 438 421 439 /* If we're already at the end of the line, return. If not, we're going to need at least one element. */ 422 if(line[0]=='\0') 423 return 1; 424 else 425 j=1; 426 427 /* Count the number of char **cmd elements we're going to need. */ 428 for(i=0; line[i]!='\0'; i++) { 429 if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':')) 430 j++; 431 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) { 432 j++; 433 break; 434 } 440 if( line[0] == '\0') 441 return NULL; 442 443 /* Count the number of char **cmd elements we're going to need. */ 444 j = 1; 445 for( i = 0; line[i] != '\0'; i ++ ) 446 { 447 if( line[i] == ' ' ) 448 { 449 j ++; 435 450 451 if( line[i+1] == ':' ) 452 break; 453 } 436 454 } 437 455 438 456 /* Allocate the space we need. */ 439 cmd =g_new(char *, j+1);440 cmd[j] =NULL;457 cmd = g_new( char *, j + 1 ); 458 cmd[j] = NULL; 441 459 442 460 /* Do the actual line splitting, format is: … … 445 463 */ 446 464 447 cmd[0]=line; 448 for(i=0, j=0; line[i]!='\0'; i++) { 449 if((line[i]==32)) { 450 line[i]='\0'; 451 if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':')) 452 cmd[++j]=line+i+1; 453 } 454 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) { 455 cmd[++j]=line+i+1; 456 break; 457 } 458 } 459 460 i=irc_exec(irc, cmd); 461 g_free(cmd); 462 463 return(i); 464 } 465 466 int irc_exec( irc_t *irc, char **cmd ) 467 { 468 int i; 469 470 if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED ) 471 { 472 if( g_strcasecmp( cmd[0], "PASS" ) == 0 ) 473 { 474 if( !cmd[1] ) 465 cmd[0] = line; 466 for( i = 0, j = 0; line[i] != '\0'; i ++ ) 467 { 468 if( line[i] == ' ' ) 469 { 470 line[i] = '\0'; 471 cmd[++j] = line + i + 1; 472 473 if( line[i+1] == ':' ) 475 474 { 476 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 475 cmd[j] ++; 476 break; 477 477 } 478 else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 ) 479 { 480 irc->status = USTATUS_AUTHORIZED; 481 } 482 else 483 { 484 irc_reply( irc, 464, ":Nope, maybe you should try it again..." ); 485 } 486 } 487 else 488 { 489 irc_reply( irc, 464, ":Uhh, fine, but I want the password first." ); 490 } 491 492 return( 1 ); 493 } 494 495 if( g_strcasecmp( cmd[0], "USER" ) == 0 ) 496 { 497 if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) ) 498 { 499 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 500 } 501 else if( irc->user ) 502 { 503 irc_reply( irc, 462, ":You can't change your nick/userinfo" ); 504 } 505 else 506 { 507 irc->user = g_strdup( cmd[1] ); 508 irc->realname = g_strdup( cmd[4] ); 509 if( irc->nick ) irc_login( irc ); 510 } 511 return( 1 ); 512 } 513 else if( g_strcasecmp( cmd[0], "NICK" ) == 0 ) 514 { 515 if( !cmd[1] ) 516 { 517 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 518 } 519 else if( irc->nick ) 520 { 521 irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" ); 522 } 523 /* This is not clean, but for now it'll have to be like this... */ 524 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) ) 525 { 526 irc_reply( irc, 433, ":This nick is already in use" ); 527 } 528 else if( !nick_ok( cmd[1] ) ) 529 { 530 /* [SH] Invalid characters. */ 531 irc_reply( irc, 432, ":This nick contains invalid characters" ); 532 } 533 else 534 { 535 irc->nick = g_strdup( cmd[1] ); 536 if( irc->user ) irc_login( irc ); 537 } 538 return( 1 ); 539 } 540 else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 ) 541 { 542 irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" ); 543 /* g_io_channel_close( irc->io_channel ); */ 544 return( 0 ); 545 } 546 547 if( !irc->user || !irc->nick ) 548 { 549 irc_reply( irc, 451, ":Register first" ); 550 return( 1 ); 551 } 552 553 if( g_strcasecmp( cmd[0], "PING" ) == 0 ) 554 { 555 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost ); 556 } 557 else if( g_strcasecmp( cmd[0], "OPER" ) == 0 ) 558 { 559 if( !cmd[2] ) 560 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 561 else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 ) 562 irc_umode_set( irc, "+o", 1 ); 563 // else 564 /* FIXME/TODO: Find out which reply to send now. */ 565 } 566 else if( g_strcasecmp( cmd[0], "MODE" ) == 0 ) 567 { 568 if( !cmd[1] ) 569 { 570 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 571 } 572 else if( *cmd[1] == '#' || *cmd[1] == '&' ) 573 { 574 if( cmd[2] ) 575 { 576 if( *cmd[2] == '+' || *cmd[2] == '-' ) 577 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] ); 578 else if( *cmd[2] == 'b' ) 579 irc_reply( irc, 368, "%s :No bans possible", cmd[1] ); 580 } 581 else 582 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE ); 583 } 584 else 585 { 586 if( nick_cmp( cmd[1], irc->nick ) == 0 ) 587 { 588 if( cmd[2] ) 589 irc_umode_set( irc, cmd[2], 0 ); 590 } 591 else 592 irc_reply( irc, 502, ":Don't touch their modes" ); 593 } 594 } 595 else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 ) 596 { 597 irc_names( irc, cmd[1]?cmd[1]:irc->channel ); 598 } 599 else if( g_strcasecmp( cmd[0], "PART" ) == 0 ) 600 { 601 struct conversation *c; 602 603 if( !cmd[1] ) 604 { 605 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 606 } 607 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 608 { 609 user_t *u = user_find( irc, irc->nick ); 610 611 /* Not allowed to leave control channel */ 612 irc_part( irc, u, irc->channel ); 613 irc_join( irc, u, irc->channel ); 614 } 615 else if( ( c = conv_findchannel( cmd[1] ) ) ) 616 { 617 user_t *u = user_find( irc, irc->nick ); 618 619 irc_part( irc, u, c->channel ); 620 621 if( c->gc && c->gc->prpl ) 622 { 623 c->joined = 0; 624 c->gc->prpl->chat_leave( c->gc, c->id ); 625 } 626 } 627 else 628 { 629 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 630 } 631 } 632 else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 ) 633 { 634 if( !cmd[1] ) 635 { 636 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 637 } 638 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 639 ; /* Dude, you're already there... 640 RFC doesn't have any reply for that though? */ 641 else if( cmd[1] ) 642 { 643 if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] ) 644 { 645 user_t *u = user_find( irc, cmd[1] + 1 ); 646 647 if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open ) 648 { 649 irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] ); 650 651 if( !u->gc->prpl->chat_open( u->gc, u->handle ) ) 652 { 653 irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick ); 654 } 655 } 656 else 657 { 658 irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 ); 659 } 660 } 661 else 662 { 663 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 664 } 665 } 666 } 667 else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 ) 668 { 669 if( cmd[1] && cmd[2] ) 670 irc_invite( irc, cmd[1], cmd[2] ); 671 else 672 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 673 } 674 else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) 675 { 676 if( !cmd[1] ) 677 { 678 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 679 } 680 else if ( !cmd[2] ) 681 { 682 irc_reply( irc, 412, ":No text to send" ); 683 } 684 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 685 { 686 irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] ); 687 } 688 else 689 { 690 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 691 { 692 unsigned int i; 693 char *t = set_getstr( irc, "default_target" ); 694 695 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target ) 696 cmd[1] = irc->last_target; 697 else if( g_strcasecmp( t, "root" ) == 0 ) 698 cmd[1] = irc->mynick; 699 700 for( i = 0; i < strlen( cmd[2] ); i ++ ) 701 { 702 if( cmd[2][i] == ' ' ) break; 703 if( cmd[2][i] == ':' || cmd[2][i] == ',' ) 704 { 705 cmd[1] = cmd[2]; 706 cmd[2] += i; 707 *cmd[2] = 0; 708 while( *(++cmd[2]) == ' ' ); 709 break; 710 } 711 } 712 713 irc->is_private = 0; 714 715 if( cmd[1] != irc->last_target ) 716 { 717 if( irc->last_target ) 718 g_free( irc->last_target ); 719 irc->last_target = g_strdup( cmd[1] ); 720 } 721 } 722 else 723 { 724 irc->is_private = 1; 725 } 726 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 ); 727 } 728 } 729 else if( g_strcasecmp( cmd[0], "WHO" ) == 0 ) 730 { 731 irc_who( irc, cmd[1] ); 732 } 733 else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 ) 734 { 735 user_t *u; 736 737 if( !cmd[1] ) 738 { 739 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 740 } 741 /* [TV] Usable USERHOST-implementation according to 742 RFC1459. Without this, mIRC shows an error 743 while connecting, and the used way of rejecting 744 breaks standards. 745 */ 746 747 for( i = 1; cmd[i]; i ++ ) 748 if( ( u = user_find( irc, cmd[i] ) ) ) 749 { 750 if( u->online && u->away ) 751 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host ); 752 else 753 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); 754 } 755 } 756 else if( g_strcasecmp( cmd[0], "ISON" ) == 0 ) 757 { 758 user_t *u; 759 char buff[IRC_MAX_LINE]; 760 int lenleft; 761 762 buff[0] = '\0'; 763 764 /* [SH] Leave room for : and \0 */ 765 lenleft = IRC_MAX_LINE - 2; 766 767 for( i = 1; cmd[i]; i ++ ) 768 { 769 if( ( u = user_find( irc, cmd[i] ) ) && u->online ) 770 { 771 /* [SH] Make sure we don't use too much buffer space. */ 772 lenleft -= strlen( u->nick ) + 1; 773 774 if( lenleft < 0 ) 775 { 776 break; 777 } 778 779 /* [SH] Add the nick to the buffer. Note 780 * that an extra space is always added. Even 781 * if it's the last nick in the list. Who 782 * cares? 783 */ 784 785 strcat( buff, u->nick ); 786 strcat( buff, " " ); 787 } 788 } 789 790 /* [WvG] Well, maybe someone cares, so why not remove it? */ 791 if( strlen( buff ) > 0 ) 792 buff[strlen(buff)-1] = '\0'; 793 794 /* [SH] By the way, that really *was* WvG talking. */ 795 /* [WvG] Really? */ 796 /* [SH] Yeah... But *this* is WvG talking too. ;-P */ 797 /* [WvG] *sigh* */ 798 799 irc_reply( irc, 303, ":%s", buff ); 800 } 801 else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 ) 802 { 803 /* Obviously we could also mark a user structure as being 804 watched, but what if the WATCH command is sent right 805 after connecting? The user won't exist yet then... */ 806 for( i = 1; cmd[i]; i ++ ) 807 { 808 char *nick; 809 user_t *u; 810 811 if( !cmd[i][0] || !cmd[i][1] ) 812 break; 813 814 nick = g_strdup( cmd[i] + 1 ); 815 nick_lc( nick ); 816 817 u = user_find( irc, nick ); 818 819 if( cmd[i][0] == '+' ) 820 { 821 if( !g_hash_table_lookup( irc->watches, nick ) ) 822 g_hash_table_insert( irc->watches, nick, nick ); 823 824 if( u && u->online ) 825 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" ); 826 else 827 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" ); 828 } 829 else if( cmd[i][0] == '-' ) 830 { 831 gpointer okey, ovalue; 832 833 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) ) 834 { 835 g_free( okey ); 836 g_hash_table_remove( irc->watches, okey ); 837 838 irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 839 } 840 } 841 } 842 } 843 else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 ) 844 { 845 if( cmd[1] && cmd[2] ) 846 irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] ); 847 else if( cmd[1] ) 848 irc_topic( irc, cmd[1] ); 849 else 850 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 851 } 852 else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 ) 853 { 854 irc_away( irc, cmd[1] ); 855 } 856 else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 ) 857 { 858 if( cmd[1] ) 859 { 860 irc_whois( irc, cmd[1] ); 861 } 862 else 863 { 864 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 865 } 866 } 867 else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 ) 868 { 869 /* For some reason irssi tries a whowas when whois fails. We can 870 ignore this, but then the user never gets a "user not found" 871 message from irssi which is a bit annoying. So just respond 872 with not-found and irssi users will get better error messages */ 873 874 if( cmd[1] ) 875 { 876 irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] ); 877 irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] ); 878 } 879 else 880 { 881 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 882 } 883 } 884 else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) ) 885 { 886 /* [SH] This aliases the NickServ command to PRIVMSG root */ 887 /* [TV] This aliases the NS command to PRIVMSG root as well */ 888 root_command( irc, cmd + 1 ); 889 } 890 else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 ) 891 { 892 irc_motd( irc ); 893 } 894 else if( g_strcasecmp( cmd[0], "PONG" ) == 0 ) 895 { 896 /* We could check the value we get back from the user, but in 897 fact we don't care, we're just happy he's still alive. */ 898 irc->last_pong = gettime(); 899 irc->pinging = 0; 900 } 901 else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 ) 902 { 903 user_t *u = user_find( irc, irc->mynick ); 904 help_t *h; 905 set_t *s; 906 int i; 907 908 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" ); 909 910 for( i = 0; commands[i].command; i ++ ) 911 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command ); 912 913 for( h = global.help; h; h = h->next ) 914 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string ); 915 916 for( s = irc->set; s; s = s->next ) 917 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key ); 918 919 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" ); 920 } 921 else if( set_getint( irc, "debug" ) ) 922 { 923 irc_usermsg( irc, "\002--- Unknown command:" ); 924 for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] ); 925 irc_usermsg( irc, "\002--------------------" ); 926 } 927 928 return( 1 ); 478 } 479 } 480 481 return cmd; 482 } 483 484 char *irc_build_line( char **cmd ) 485 { 486 int i, len; 487 char *s; 488 489 if( cmd[0] == NULL ) 490 return NULL; 491 492 len = 1; 493 for( i = 0; cmd[i]; i ++ ) 494 len += strlen( cmd[i] ) + 1; 495 496 if( strchr( cmd[i-1], ' ' ) != NULL ) 497 len ++; 498 499 s = g_new0( char, len + 1 ); 500 for( i = 0; cmd[i]; i ++ ) 501 { 502 if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL ) 503 strcat( s, ":" ); 504 505 strcat( s, cmd[i] ); 506 507 if( cmd[i+1] ) 508 strcat( s, " " ); 509 } 510 strcat( s, "\r\n" ); 511 512 return s; 929 513 } 930 514 … … 1085 669 } 1086 670 1087 void irc_who( irc_t *irc, char *channel ) 1088 { 1089 user_t *u = irc->users; 1090 struct conversation *c; 1091 GList *l; 1092 1093 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 1094 while( u ) 1095 { 1096 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname ); 1097 u = u->next; 1098 } 1099 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 1100 while( u ) 1101 { 1102 if( u->online ) 1103 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); 1104 u = u->next; 1105 } 1106 else if( ( c = conv_findchannel( channel ) ) ) 1107 for( l = c->in_room; l; l = l->next ) 1108 { 1109 if( ( u = user_findhandle( c->gc, l->data ) ) ) 1110 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); 1111 } 1112 else if( ( u = user_find( irc, channel ) ) ) 1113 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname ); 1114 1115 irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" ); 671 int irc_check_login( irc_t *irc ) 672 { 673 if( irc->user && irc->nick ) 674 { 675 if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED ) 676 { 677 irc_reply( irc, 464, ":This server is password-protected." ); 678 return 0; 679 } 680 else 681 { 682 irc_login( irc ); 683 return 1; 684 } 685 } 686 else 687 { 688 /* More information needed. */ 689 return 0; 690 } 1116 691 } 1117 692 … … 1148 723 u->realname = g_strdup( irc->realname ); 1149 724 u->online = 1; 1150 // u->send_handler = msg_echo;1151 725 irc_spawn( irc, u ); 1152 726 1153 727 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 FAQ's are answered there." ); 728 729 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 730 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 1154 731 1155 732 irc->status = USTATUS_LOGGED_IN; … … 1225 802 } 1226 803 1227 void irc_whois( irc_t *irc, char *nick )1228 {1229 user_t *u = user_find( irc, nick );1230 1231 if( u )1232 {1233 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );1234 1235 if( u->gc )1236 irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,1237 *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );1238 else1239 irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );1240 1241 if( !u->online )1242 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );1243 else if( u->away )1244 irc_reply( irc, 301, "%s :%s", u->nick, u->away );1245 1246 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );1247 }1248 else1249 {1250 irc_reply( irc, 401, "%s :Nick does not exist", nick );1251 }1252 }1253 1254 1255 804 void irc_umode_set( irc_t *irc, char *s, int allow_priv ) 1256 805 { … … 1282 831 } 1283 832 1284 int irc_away( irc_t *irc, char *away )1285 {1286 user_t *u = user_find( irc, irc->nick );1287 GSList *c = get_connections();1288 1289 if( !u ) return( 0 );1290 1291 if( away && *away )1292 {1293 int i, j;1294 1295 /* Copy away string, but skip control chars. Mainly because1296 Jabber really doesn't like them. */1297 u->away = g_malloc( strlen( away ) + 1 );1298 for( i = j = 0; away[i]; i ++ )1299 if( ( u->away[j] = away[i] ) >= ' ' )1300 j ++;1301 u->away[j] = 0;1302 1303 irc_reply( irc, 306, ":You're now away: %s", u->away );1304 /* irc_umode_set( irc, irc->myhost, "+a" ); */1305 }1306 else1307 {1308 if( u->away ) g_free( u->away );1309 u->away = NULL;1310 /* irc_umode_set( irc, irc->myhost, "-a" ); */1311 irc_reply( irc, 305, ":Welcome back" );1312 }1313 1314 while( c )1315 {1316 if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )1317 proto_away( c->data, u->away );1318 1319 c = c->next;1320 }1321 1322 return( 1 );1323 }1324 1325 833 void irc_spawn( irc_t *irc, user_t *u ) 1326 834 { … … 1374 882 } 1375 883 g_free( nick ); 1376 }1377 1378 void irc_invite( irc_t *irc, char *nick, char *channel )1379 {1380 struct conversation *c = conv_findchannel( channel );1381 user_t *u = user_find( irc, nick );1382 1383 if( u && c && ( u->gc == c->gc ) )1384 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )1385 {1386 c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );1387 irc_reply( irc, 341, "%s %s", nick, channel );1388 return;1389 }1390 1391 irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );1392 884 } 1393 885 -
irc.h
rfc50d48 r55ec2d6 33 33 #define IRC_PING_STRING "PinglBee" 34 34 35 #define UMODES "ias "35 #define UMODES "iasw" 36 36 #define UMODES_PRIV "Ro" 37 37 #define CMODES "nt" … … 41 41 typedef enum 42 42 { 43 USTATUS_OFFLINE ,43 USTATUS_OFFLINE = 0, 44 44 USTATUS_AUTHORIZED, 45 45 USTATUS_LOGGED_IN, 46 46 USTATUS_IDENTIFIED, 47 USTATUS_SHUTDOWN 47 USTATUS_SHUTDOWN = -1 48 48 } irc_status_t; 49 49 … … 110 110 int irc_exec( irc_t *irc, char **cmd ); 111 111 int irc_process( irc_t *irc ); 112 int irc_process_line( irc_t *irc, char *line ); 112 char **irc_parse_line( char *line ); 113 char *irc_build_line( char **cmd ); 113 114 114 115 void irc_vawrite( irc_t *irc, char *format, va_list params ); … … 120 121 121 122 void irc_login( irc_t *irc ); 123 int irc_check_login( irc_t *irc ); 122 124 void irc_motd( irc_t *irc ); 123 125 void irc_names( irc_t *irc, char *channel ); -
url.c
rfc50d48 r55ec2d6 40 40 else 41 41 { 42 if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) 42 if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) 43 url->proto = PROTO_HTTP; 44 else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) 43 45 url->proto = PROTO_HTTPS; 44 else if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )45 url->proto = PROTO_HTTP;46 46 else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 ) 47 47 url->proto = PROTO_SOCKS4;
Note: See TracChangeset
for help on using the changeset viewer.