Changes in / [560d0a0:f1cea66]
- Files:
-
- 14 added
- 6 deleted
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r560d0a0 rf1cea66 10 10 11 11 # Program variables 12 objects = account.o bitlbee.o chat.o dcc.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o13 headers = account.h bitlbee.h commands.h conf.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) 13 headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h 14 14 subdirs = lib protocols 15 15 -
bitlbee.h
r560d0a0 rf1cea66 126 126 #define CONF_FILE_DEF ETCDIR "bitlbee.conf" 127 127 128 #include "bee.h" 128 129 #include "irc.h" 129 130 #include "storage.h" … … 160 161 gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); 161 162 162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags);163 void root_command_string( irc_t *irc, char *command ); 163 164 void root_command( irc_t *irc, char *command[] ); 164 165 gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); -
conf.c
r560d0a0 rf1cea66 376 376 if( g_strcasecmp( ini->section, "defaults" ) == 0 ) 377 377 { 378 set_t *s = set_find( &irc-> set, ini->key );378 set_t *s = set_find( &irc->b->set, ini->key ); 379 379 380 380 if( s ) -
configure
r560d0a0 rf1cea66 27 27 yahoo=1 28 28 twitter=1 29 twitter=1 29 30 purple=0 30 31 … … 68 69 --oscar=0/1 Disable/enable Oscar part (ICQ, AIM) $oscar 69 70 --yahoo=0/1 Disable/enable Yahoo part $yahoo 70 --twitter=0/1 71 --twitter=0/1 Disable/enable Twitter part $twitter 71 72 72 73 --purple=0/1 Disable/enable libpurple support $purple -
dcc.c
r560d0a0 rf1cea66 61 61 unsigned int receivedchunks=0, receiveddata=0; 62 62 63 staticvoid dcc_finish( file_transfer_t *file );64 staticvoid dcc_close( file_transfer_t *file );63 void dcc_finish( file_transfer_t *file ); 64 void dcc_close( file_transfer_t *file ); 65 65 gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond ); 66 int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr ); 67 gboolean dccs_recv_start( file_transfer_t *ft ); 66 int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr ); 68 67 gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond); 69 68 gboolean dccs_recv_write_request( file_transfer_t *ft ); … … 71 70 gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ); 72 71 73 /* As defined in ft.h */ 74 file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *handle, char *file_name, size_t file_size ) 75 { 76 user_t *u = user_findhandle( ic, handle ); 77 /* one could handle this more intelligent like imcb_buddy_msg. 78 * can't call it directly though cause it does some wrapping. 79 * Maybe give imcb_buddy_msg a parameter NO_WRAPPING? */ 80 if (!u) return NULL; 81 82 return dccs_send_start( ic, u->nick, file_name, file_size ); 83 }; 84 85 /* As defined in ft.h */ 86 void imcb_file_canceled( file_transfer_t *file, char *reason ) 87 { 88 if( file->canceled ) 89 file->canceled( file, reason ); 90 91 dcc_close( file ); 92 } 93 94 /* As defined in ft.h */ 95 gboolean imcb_file_recv_start( file_transfer_t *ft ) 96 { 97 return dccs_recv_start( ft ); 98 } 99 100 /* As defined in ft.h */ 101 void imcb_file_finished( file_transfer_t *file ) 102 { 103 dcc_file_transfer_t *df = file->priv; 104 105 if( file->bytes_transferred >= file->file_size ) 106 dcc_finish( file ); 107 else 108 df->proto_finished = TRUE; 109 } 110 111 dcc_file_transfer_t *dcc_alloc_transfer( char *file_name, size_t file_size, struct im_connection *ic ) 72 dcc_file_transfer_t *dcc_alloc_transfer( const char *file_name, size_t file_size, struct im_connection *ic ) 112 73 { 113 74 file_transfer_t *file = g_new0( file_transfer_t, 1 ); … … 117 78 file->file_name = g_strdup( file_name ); 118 79 file->local_id = local_transfer_id++; 119 df->ic = ic;80 file->ic = df->ic = ic; 120 81 df->ft = file; 121 82 … … 124 85 125 86 /* This is where the sending magic starts... */ 126 file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick,char *file_name, size_t file_size )87 file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size ) 127 88 { 128 89 file_transfer_t *file; 129 90 dcc_file_transfer_t *df; 91 irc_t *irc = (irc_t *) ic->bee->ui_data; 130 92 struct sockaddr_storage saddr; 131 93 char *errmsg; … … 150 112 file->status = FT_STATUS_LISTENING; 151 113 152 if( !dccs_send_request( df, user_nick, &saddr ) )114 if( !dccs_send_request( df, iu, &saddr ) ) 153 115 return NULL; 154 116 … … 156 118 df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_send_proto, df ); 157 119 158 df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, file );120 irc->file_transfers = g_slist_prepend( irc->file_transfers, file ); 159 121 160 122 df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); … … 163 125 "Accept the file transfer if you'd like the file. If you don't, " 164 126 "issue the 'transfers reject' command.", 165 user_nick, file_name, file_size / 1024 );127 iu->nick, file_name, file_size / 1024 ); 166 128 167 129 return file; … … 216 178 217 179 /* Creates the "DCC SEND" line and sends it to the server */ 218 int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr )180 int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr ) 219 181 { 220 182 char ipaddr[INET6_ADDRSTRLEN]; … … 250 212 df->ft->file_name, ipaddr, port, df->ft->file_size ); 251 213 252 if ( !irc_msgfrom( df->ic->irc, user_nick, cmd ) ) 253 return dcc_abort( df, "Couldn't send `DCC SEND' message to %s.", user_nick ); 214 irc_send_msg_raw( iu, "PRIVMSG", iu->irc->user->nick, cmd ); 254 215 255 216 g_free( cmd ); … … 496 457 * Cleans up after a transfer. 497 458 */ 498 staticvoid dcc_close( file_transfer_t *file )459 void dcc_close( file_transfer_t *file ) 499 460 { 500 461 dcc_file_transfer_t *df = file->priv; 462 irc_t *irc = (irc_t *) df->ic->bee->ui_data; 501 463 502 464 if( file->free ) … … 514 476 b_event_remove( df->progress_timeout ); 515 477 516 df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file );478 irc->file_transfers = g_slist_remove( irc->file_transfers, file ); 517 479 518 480 g_free( df ); … … 542 504 * 543 505 */ 544 file_transfer_t *dcc_request( struct im_connection *ic, char *line ) 545 { 546 char *pattern = "SEND" 547 " (([^\"][^ ]*)|\"(([^\"]|\\\")*)\")" 548 " (([0-9]*)|([^ ]*))" 549 " ([0-9]*)" 550 " ([0-9]*)\001"; 551 regmatch_t pmatch[10]; 552 regex_t re; 506 file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp ) 507 { 508 irc_t *irc = (irc_t *) ic->bee->ui_data; 553 509 file_transfer_t *ft; 554 510 dcc_file_transfer_t *df; 555 char errbuf[256]; 556 int regerrcode, gret; 557 558 if( ( regerrcode = regcomp( &re, pattern, REG_EXTENDED ) ) || 559 ( regerrcode = regexec( &re, line, 10, pmatch, 0 ) ) ) { 560 regerror( regerrcode,&re,errbuf,sizeof( errbuf ) ); 561 imcb_log( ic, 562 "DCC: error parsing 'DCC SEND': %s, line: %s", 563 errbuf, line ); 564 return NULL; 565 } 566 567 if( ( pmatch[1].rm_so > 0 ) && 568 ( pmatch[5].rm_so > 0 ) && 569 ( pmatch[8].rm_so > 0 ) && 570 ( pmatch[9].rm_so > 0 ) ) 571 { 572 char *input = g_strdup( line ); 511 int gret; 512 size_t filesize; 513 514 if( ctcp[5] != NULL && 515 sscanf( ctcp[4], "%zd", &filesize ) == 1 && /* Just int. validation. */ 516 sscanf( ctcp[5], "%zd", &filesize ) == 1 ) 517 { 573 518 char *filename, *host, *port; 574 size_t filesize;575 519 struct addrinfo hints, *rp; 576 577 /* "filename" or filename */ 578 if ( pmatch[2].rm_so > 0 ) 520 521 filename = ctcp[2]; 522 523 host = ctcp[3]; 524 while( *host && isdigit( *host ) ) host++; /* Just digits? */ 525 if( *host == '\0' ) 579 526 { 580 input[pmatch[2].rm_eo] = '\0'; 581 filename = input + pmatch[2].rm_so; 582 } else 583 { 584 input[pmatch[3].rm_eo] = '\0'; 585 filename = input + pmatch[3].rm_so; 586 } 587 588 input[pmatch[5].rm_eo] = '\0'; 589 590 /* number means ipv4, something else means ipv6 */ 591 if ( pmatch[6].rm_so > 0 ) 592 { 593 struct in_addr ipaddr = { .s_addr = htonl( strtoul( input + pmatch[5].rm_so, NULL, 10 ) ) }; 527 struct in_addr ipaddr = { .s_addr = htonl( atoll( ctcp[3] ) ) }; 594 528 host = inet_ntoa( ipaddr ); 595 529 } else 596 530 { 597 531 /* Contains non-numbers, hopefully an IPV6 address */ 598 host = input + pmatch[7].rm_so;532 host = ctcp[3]; 599 533 } 600 534 601 input[pmatch[8].rm_eo] = '\0'; 602 input[pmatch[9].rm_eo] = '\0'; 603 604 port = input + pmatch[8].rm_so; 605 filesize = atoll( input + pmatch[9].rm_so ); 535 port = ctcp[4]; 536 filesize = atoll( ctcp[5] ); 606 537 607 538 memset( &hints, 0, sizeof ( struct addrinfo ) ); … … 611 542 if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) ) 612 543 { 613 g_free( input );614 544 imcb_log( ic, "DCC: getaddrinfo() failed with %s " 615 545 "when parsing incoming 'DCC SEND': " … … 625 555 626 556 freeaddrinfo( rp ); 627 g_free( input ); 628 629 df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, ft ); 557 558 irc->file_transfers = g_slist_prepend( irc->file_transfers, ft ); 630 559 631 560 return ft; 632 561 } 633 634 imcb_log( ic, "DCC: couldnt parse 'DCC SEND' line: %s", line);562 else 563 imcb_log( ic, "DCC: couldnt parse `DCC SEND' line" ); 635 564 636 565 return NULL; 637 566 } 638 -
dcc.h
r560d0a0 rf1cea66 95 95 } dcc_file_transfer_t; 96 96 97 file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size ); 97 file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size ); 98 void dcc_canceled( file_transfer_t *file, char *reason ); 99 gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size ); 100 file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp ); 101 void dcc_finish( file_transfer_t *file ); 102 void dcc_close( file_transfer_t *file ); 103 gboolean dccs_recv_start( file_transfer_t *ft ); 98 104 99 void dcc_canceled( file_transfer_t *file, char *reason );100 101 gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size );102 103 file_transfer_t *dcc_request( struct im_connection *ic, char *line );104 105 #endif -
doc/user-guide/commands.xml
r560d0a0 rf1cea66 593 593 594 594 <bitlbee-setting name="handle_unknown" type="string" scope="global"> 595 <default> root</default>595 <default>add_channel</default> 596 596 <possible-values>root, add, add_private, add_channel, ignore</possible-values> 597 597 … … 1114 1114 1115 1115 <bitlbee-command name="identify"> 1116 <syntax>identify <password></syntax>1116 <syntax>identify [-noload|-force] <password></syntax> 1117 1117 <short-description>Identify yourself with your password</short-description> 1118 1118 … … 1124 1124 <para> 1125 1125 Once you're registered, you can change your password using <emphasis>set password <password></emphasis>. 1126 </para> 1127 1128 <para> 1129 The <emphasis>-noload</emphasis> and <emphasis>-force</emphasis> flags can be used to identify when you're logged into some IM accounts already. <emphasis>-force</emphasis> will let you identify yourself and load all saved accounts (and keep the accounts you're logged into already). 1130 </para> 1131 1132 <para> 1133 <emphasis>-noload</emphasis> will log you in but not load any accounts and settings saved under your current nickname. These will be overwritten once you save your settings (i.e. when you disconnect). 1126 1134 </para> 1127 1135 </description> -
doc/user-guide/misc.xml
r560d0a0 rf1cea66 117 117 </sect1> 118 118 119 <sect1 id="nick_changes"> 120 <title>Changing your nickname</title> 121 122 <para> 123 BitlBee now allows you to change your nickname. So far this was not possible because it made managing saved accounts more complicated. 124 </para> 125 126 <para> 127 The restriction no longer exists now though. When you change your nick (just using the <emphasis>/nick</emphasis> command), your logged-in status will be reset, which means any changes made to your settings/accounts will not be saved. 128 </para> 129 130 <para> 131 To restore your logged-in status, you need to either use the <emphasis>register</emphasis> command to create an account under the new nickname, or use <emphasis>identify -noload</emphasis> to re-identify yourself under the new nickname. The <emphasis>-noload</emphasis> flag tells the command to verify your password and log you in, but not load any new settings. See <emphasis>help identify</emphasis> for more information. 132 </para> 133 134 </sect1> 135 119 136 </chapter> -
ipc.c
r560d0a0 rf1cea66 138 138 139 139 if( strchr( irc->umode, 'w' ) ) 140 irc_write( irc, ":%s WALLOPS :%s", irc-> myhost, cmd[1] );140 irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] ); 141 141 } 142 142 … … 147 147 148 148 if( strchr( irc->umode, 's' ) ) 149 irc_write( irc, ":%s NOTICE %s :%s", irc-> myhost, irc->nick, cmd[1] );149 irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] ); 150 150 } 151 151 … … 156 156 157 157 if( strchr( irc->umode, 'o' ) ) 158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc-> myhost, irc->nick, cmd[1] );158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] ); 159 159 } 160 160 … … 176 176 return; 177 177 178 if( nick_cmp( cmd[1], irc-> nick ) != 0 )178 if( nick_cmp( cmd[1], irc->user->nick ) != 0 ) 179 179 return; /* It's not for us. */ 180 180 181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc-> mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] ); 182 182 irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); 183 183 } … … 188 188 ipc_to_master_str( "HELLO\r\n" ); 189 189 else 190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc-> host, irc->nick, irc->realname );190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 191 191 } 192 192 -
irc.c
r560d0a0 rf1cea66 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 24 24 */ 25 25 26 #define BITLBEE_CORE27 26 #include "bitlbee.h" 28 #include "sock.h"29 27 #include "ipc.h" 30 28 #include "dcc.h" 31 29 32 static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); 33 34 GSList *irc_connection_list = NULL; 35 36 static char *set_eval_password( set_t *set, char *value ) 37 { 38 irc_t *irc = set->data; 39 40 if( irc->status & USTATUS_IDENTIFIED && value ) 41 { 42 irc_setpass( irc, value ); 43 return NULL; 44 } 45 else 46 { 47 return SET_INVALID; 48 } 49 } 50 51 static char *set_eval_charset( set_t *set, char *value ) 52 { 53 irc_t *irc = set->data; 54 char *test; 55 gsize test_bytes = 0; 56 GIConv ic, oc; 57 58 if( g_strcasecmp( value, "none" ) == 0 ) 59 value = g_strdup( "utf-8" ); 60 61 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 62 { 63 return NULL; 64 } 65 66 /* Do a test iconv to see if the user picked an IRC-compatible 67 charset (for example utf-16 goes *horribly* wrong). */ 68 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 69 test_bytes > 1 ) 70 { 71 g_free( test ); 72 g_iconv_close( oc ); 73 irc_usermsg( irc, "Unsupported character set: The IRC protocol " 74 "only supports 8-bit character sets." ); 75 return NULL; 76 } 77 g_free( test ); 78 79 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 80 { 81 g_iconv_close( oc ); 82 return NULL; 83 } 84 85 if( irc->iconv != (GIConv) -1 ) 86 g_iconv_close( irc->iconv ); 87 if( irc->oconv != (GIConv) -1 ) 88 g_iconv_close( irc->oconv ); 89 90 irc->iconv = ic; 91 irc->oconv = oc; 92 93 return value; 94 } 95 96 static char *set_eval_away_status( set_t *set, char *value ) 97 { 98 irc_t *irc = set->data; 99 account_t *a; 100 101 g_free( set->value ); 102 set->value = g_strdup( value ); 103 104 for( a = irc->accounts; a; a = a->next ) 105 { 106 struct im_connection *ic = a->ic; 107 108 if( ic && ic->flags & OPT_LOGGED_IN ) 109 imc_away_send_update( ic ); 110 } 111 112 return value; 113 } 30 GSList *irc_connection_list; 31 32 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ); 33 static char *set_eval_charset( set_t *set, char *value ); 34 static char *set_eval_password( set_t *set, char *value ); 114 35 115 36 irc_t *irc_new( int fd ) … … 118 39 struct sockaddr_storage sock; 119 40 socklen_t socklen = sizeof( sock ); 41 char *host = NULL, *myhost = NULL; 42 irc_user_t *iu; 120 43 set_t *s; 44 bee_t *b; 121 45 122 46 irc = g_new0( irc_t, 1 ); … … 130 54 irc->last_pong = gettime(); 131 55 132 irc-> userhash = g_hash_table_new( g_str_hash, g_str_equal );56 irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal ); 133 57 irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); 134 135 strcpy( irc->umode, UMODE );136 irc->mynick = g_strdup( ROOT_NICK );137 irc->channel = g_strdup( ROOT_CHAN );138 58 139 59 irc->iconv = (GIConv) -1; … … 142 62 if( global.conf->hostname ) 143 63 { 144 irc->myhost = g_strdup( global.conf->hostname );64 myhost = g_strdup( global.conf->hostname ); 145 65 } 146 66 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) … … 151 71 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 152 72 { 153 irc->myhost = g_strdup( ipv6_unwrap( buf ) );73 myhost = g_strdup( ipv6_unwrap( buf ) ); 154 74 } 155 75 } … … 162 82 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 163 83 { 164 irc->host = g_strdup( ipv6_unwrap( buf ) );165 } 166 } 167 168 if( irc->host == NULL )169 irc->host = g_strdup( "localhost.localdomain" );170 if( irc->myhost == NULL )171 irc->myhost = g_strdup( "localhost.localdomain" );84 host = g_strdup( ipv6_unwrap( buf ) ); 85 } 86 } 87 88 if( host == NULL ) 89 host = g_strdup( "localhost.localdomain" ); 90 if( myhost == NULL ) 91 myhost = g_strdup( "localhost.localdomain" ); 172 92 173 93 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 174 94 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); 175 176 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );177 95 178 96 irc_connection_list = g_slist_append( irc_connection_list, irc ); 179 97 180 s = set_add( &irc->set, "away", NULL, set_eval_away_status, irc ); 98 b = irc->b = bee_new(); 99 b->ui_data = irc; 100 b->ui = &irc_ui_funcs; 101 102 s = set_add( &b->set, "away_devoice", "true", set_eval_away_devoice, irc ); 103 s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc ); 104 s = set_add( &b->set, "default_target", "root", NULL, irc ); 105 s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc ); 106 s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc ); 107 s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc ); 108 s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc ); 109 s = set_add( &b->set, "ops", "both", set_eval_irc_channel_ops, irc ); 110 s = set_add( &b->set, "paste_buffer", "false", set_eval_bool, irc ); 111 s->old_key = g_strdup( "buddy_sendbuffer" ); 112 s = set_add( &b->set, "paste_buffer_delay", "200", set_eval_int, irc ); 113 s->old_key = g_strdup( "buddy_sendbuffer_delay" ); 114 s = set_add( &b->set, "password", NULL, set_eval_password, irc ); 181 115 s->flags |= SET_NULL_OK; 182 s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); 183 s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); 184 s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc ); 185 s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc ); 186 s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); 187 s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); 188 s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); 189 s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc ); 190 s = set_add( &irc->set, "debug", "false", set_eval_bool, irc ); 191 s = set_add( &irc->set, "default_target", "root", NULL, irc ); 192 s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); 193 s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc ); 194 s = set_add( &irc->set, "handle_unknown", "root", NULL, irc ); 195 s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); 196 s = set_add( &irc->set, "ops", "both", set_eval_ops, irc ); 197 s = set_add( &irc->set, "password", NULL, set_eval_password, irc ); 198 s->flags |= SET_NULL_OK; 199 s = set_add( &irc->set, "private", "true", set_eval_bool, irc ); 200 s = set_add( &irc->set, "query_order", "lifo", NULL, irc ); 201 s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); 202 s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); 203 s = set_add( &irc->set, "show_offline", "false", set_eval_bool, irc ); 204 s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); 205 s = set_add( &irc->set, "status", NULL, set_eval_away_status, irc ); 206 s->flags |= SET_NULL_OK; 207 s = set_add( &irc->set, "strip_html", "true", NULL, irc ); 208 s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc ); 209 s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); 210 s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); 116 s = set_add( &b->set, "private", "true", set_eval_bool, irc ); 117 s = set_add( &b->set, "query_order", "lifo", NULL, irc ); 118 s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc ); 119 s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc ); 120 s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc ); 121 s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc ); 122 s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc ); 123 124 irc->root = iu = irc_user_new( irc, ROOT_NICK ); 125 iu->host = g_strdup( myhost ); 126 iu->fullname = g_strdup( ROOT_FN ); 127 iu->f = &irc_user_root_funcs; 128 129 iu = irc_user_new( irc, NS_NICK ); 130 iu->host = g_strdup( myhost ); 131 iu->fullname = g_strdup( ROOT_FN ); 132 iu->f = &irc_user_root_funcs; 133 134 irc->user = g_new0( irc_user_t, 1 ); 135 irc->user->host = g_strdup( host ); 211 136 212 137 conf_loaddefaults( irc ); 213 138 214 139 /* Evaluator sets the iconv/oconv structures. */ 215 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 140 set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) ); 141 142 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" ); 143 144 g_free( myhost ); 145 g_free( host ); 216 146 217 147 nogaim_init(); 218 148 219 return ( irc );149 return irc; 220 150 } 221 151 … … 238 168 239 169 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 240 irc-> nick ? irc->nick : "(NONE)", irc->host, reason );170 irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason ); 241 171 242 172 g_free( reason ); … … 248 178 249 179 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 250 irc-> nick ? irc->nick : "(NONE)", irc->host, "No reason given" );180 irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" ); 251 181 } 252 182 … … 269 199 } 270 200 271 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 272 { 273 g_free( key ); 274 275 return( TRUE ); 276 } 277 278 /* Because we have no garbage collection, this is quite annoying */ 201 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 202 279 203 void irc_free( irc_t * irc ) 280 204 { 281 user_t *user, *usertmp;282 283 205 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 284 206 285 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc-> set, "save_on_quit" ) )207 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) 286 208 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 287 irc_usermsg( irc, "Error while saving settings!");209 log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick ); 288 210 289 211 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 290 291 while( irc->accounts )292 {293 if( irc->accounts->ic )294 imc_logout( irc->accounts->ic, FALSE );295 else if( irc->accounts->reconnect )296 cancel_auto_reconnect( irc->accounts );297 298 if( irc->accounts->ic == NULL )299 account_del( irc, irc->accounts );300 else301 /* Nasty hack, but account_del() doesn't work in this302 case and we don't want infinite loops, do we? ;-) */303 irc->accounts = irc->accounts->next;304 }305 212 306 213 while( irc->queries != NULL ) 307 214 query_del( irc, irc->queries ); 308 215 309 while( irc->set ) 310 set_del( &irc->set, irc->set->key ); 311 312 if (irc->users != NULL) 313 { 314 user = irc->users; 315 while( user != NULL ) 316 { 317 g_free( user->nick ); 318 g_free( user->away ); 319 g_free( user->handle ); 320 if( user->user != user->nick ) g_free( user->user ); 321 if( user->host != user->nick ) g_free( user->host ); 322 if( user->realname != user->nick ) g_free( user->realname ); 323 b_event_remove( user->sendbuf_timer ); 324 325 usertmp = user; 326 user = user->next; 327 g_free( usertmp ); 328 } 329 } 216 /* This is a little bit messy: bee_free() frees all b->users which 217 calls us back to free the corresponding irc->users. So do this 218 before we clear the remaining ones ourselves. */ 219 bee_free( irc->b ); 220 221 while( irc->users ) 222 irc_user_free( irc, (irc_user_t *) irc->users->data ); 223 224 while( irc->channels ) 225 irc_channel_free( irc->channels->data ); 330 226 331 227 if( irc->ping_source_id > 0 ) … … 339 235 irc->fd = -1; 340 236 341 g_hash_table_foreach_remove( irc-> userhash, irc_free_hashkey, NULL );342 g_hash_table_destroy( irc-> userhash );237 g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL ); 238 g_hash_table_destroy( irc->nick_user_hash ); 343 239 344 240 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); … … 352 248 g_free( irc->sendbuffer ); 353 249 g_free( irc->readbuffer ); 354 355 g_free( irc->nick );356 g_free( irc->user );357 g_free( irc->host );358 g_free( irc->realname );359 250 g_free( irc->password ); 360 361 g_free( irc->myhost ); 362 g_free( irc->mynick ); 363 364 g_free( irc->channel ); 365 366 g_free( irc->last_target ); 251 g_free( irc->last_root_cmd ); 367 252 368 253 g_free( irc ); … … 376 261 } 377 262 263 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 264 { 265 g_free( key ); 266 267 return( TRUE ); 268 } 269 378 270 /* USE WITH CAUTION! 379 271 Sets pass without checking */ 380 void irc_setpass (irc_t *irc, const char *pass) 272 void irc_setpass (irc_t *irc, const char *pass) 381 273 { 382 274 g_free (irc->password); … … 389 281 } 390 282 283 static char *set_eval_password( set_t *set, char *value ) 284 { 285 irc_t *irc = set->data; 286 287 if( irc->status & USTATUS_IDENTIFIED && value ) 288 { 289 irc_setpass( irc, value ); 290 return NULL; 291 } 292 else 293 { 294 return SET_INVALID; 295 } 296 } 297 298 static char **irc_splitlines( char *buffer ); 299 391 300 void irc_process( irc_t *irc ) 392 301 { … … 396 305 if( irc->readbuffer != NULL ) 397 306 { 398 lines = irc_ tokenize( irc->readbuffer );307 lines = irc_splitlines( irc->readbuffer ); 399 308 400 309 for( i = 0; *lines[i] != '\0'; i ++ ) … … 433 342 "`help set charset' for more information. Your " 434 343 "message was ignored.", 435 set_getstr( &irc-> set, "charset" ) );344 set_getstr( &irc->b->set, "charset" ) ); 436 345 437 346 g_free( conv ); … … 440 349 else 441 350 { 442 irc_write( irc, ":%s NOTICE AUTH :%s", irc-> myhost,351 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, 443 352 "Warning: invalid characters received at login time." ); 444 353 … … 478 387 } 479 388 480 /* Splits a long string into separate lines. The array is NULL-terminated and, unless the string 481 contains an incomplete line at the end, ends with an empty string. */ 482 char **irc_tokenize( char *buffer ) 389 /* Splits a long string into separate lines. The array is NULL-terminated 390 and, unless the string contains an incomplete line at the end, ends with 391 an empty string. Could use g_strsplit() but this one does it in-place. 392 (So yes, it's destructive.) */ 393 static char **irc_splitlines( char *buffer ) 483 394 { 484 395 int i, j, n = 3; … … 611 522 } 612 523 613 void irc_reply( irc_t *irc, int code, char *format, ... )614 {615 char text[IRC_MAX_LINE];616 va_list params;617 618 va_start( params, format );619 g_vsnprintf( text, IRC_MAX_LINE, format, params );620 va_end( params );621 irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );622 623 return;624 }625 626 int irc_usermsg( irc_t *irc, char *format, ... )627 {628 char text[1024];629 va_list params;630 char is_private = 0;631 user_t *u;632 633 u = user_find( irc, irc->mynick );634 is_private = u->is_private;635 636 va_start( params, format );637 g_vsnprintf( text, sizeof( text ), format, params );638 va_end( params );639 640 return( irc_msgfrom( irc, u->nick, text ) );641 }642 643 524 void irc_write( irc_t *irc, char *format, ... ) 644 525 { … … 651 532 return; 652 533 } 534 535 void irc_write_all( int now, char *format, ... ) 536 { 537 va_list params; 538 GSList *temp; 539 540 va_start( params, format ); 541 542 temp = irc_connection_list; 543 while( temp != NULL ) 544 { 545 irc_t *irc = temp->data; 546 547 if( now ) 548 { 549 g_free( irc->sendbuffer ); 550 irc->sendbuffer = g_strdup( "\r\n" ); 551 } 552 irc_vawrite( temp->data, format, params ); 553 if( now ) 554 { 555 bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ); 556 } 557 temp = temp->next; 558 } 559 560 va_end( params ); 561 return; 562 } 653 563 654 564 void irc_vawrite( irc_t *irc, char *format, va_list params ) … … 707 617 } 708 618 709 void irc_write_all( int now, char *format, ... ) 710 { 711 va_list params; 712 GSList *temp; 713 714 va_start( params, format ); 715 716 temp = irc_connection_list; 717 while( temp != NULL ) 718 { 719 irc_t *irc = temp->data; 720 721 if( now ) 722 { 723 g_free( irc->sendbuffer ); 724 irc->sendbuffer = g_strdup( "\r\n" ); 725 } 726 irc_vawrite( temp->data, format, params ); 727 if( now ) 728 { 729 bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ); 730 } 731 temp = temp->next; 732 } 733 734 va_end( params ); 735 return; 736 } 737 738 void irc_names( irc_t *irc, char *channel ) 739 { 740 user_t *u; 741 char namelist[385] = ""; 742 struct groupchat *c = NULL; 743 char *ops = set_getstr( &irc->set, "ops" ); 744 745 /* RFCs say there is no error reply allowed on NAMES, so when the 746 channel is invalid, just give an empty reply. */ 747 748 if( g_strcasecmp( channel, irc->channel ) == 0 ) 749 { 750 for( u = irc->users; u; u = u->next ) if( u->online ) 751 { 752 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) 619 int irc_check_login( irc_t *irc ) 620 { 621 if( irc->user->user && irc->user->nick ) 622 { 623 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 624 { 625 irc_send_num( irc, 464, ":This server is password-protected." ); 626 return 0; 627 } 628 else 629 { 630 irc_channel_t *ic; 631 irc_user_t *iu = irc->user; 632 633 irc->user = irc_user_new( irc, iu->nick ); 634 irc->user->user = iu->user; 635 irc->user->host = iu->host; 636 irc->user->fullname = iu->fullname; 637 irc->user->f = &irc_user_self_funcs; 638 g_free( iu->nick ); 639 g_free( iu ); 640 641 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 642 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 643 644 irc->status |= USTATUS_LOGGED_IN; 645 646 irc_send_login( irc ); 647 648 irc->umode[0] = '\0'; 649 irc_umode_set( irc, "+" UMODE, TRUE ); 650 651 ic = irc->default_channel = irc_channel_new( irc, ROOT_CHAN ); 652 irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root ); 653 irc_channel_add_user( ic, irc->user ); 654 655 irc->last_root_cmd = g_strdup( ROOT_CHAN ); 656 657 irc_send_msg( irc->root, "PRIVMSG", ROOT_CHAN, 658 "Welcome to the BitlBee gateway!\n\n" 659 "If you've never used BitlBee before, please do read the help " 660 "information using the \x02help\x02 command. Lots of FAQs are " 661 "answered there.\n" 662 "If you already have an account on this server, just use the " 663 "\x02identify\x02 command to identify yourself.", NULL ); 664 665 /* This is for bug #209 (use PASS to identify to NickServ). */ 666 if( irc->password != NULL ) 753 667 { 754 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 755 *namelist = 0; 668 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 669 670 irc_setpass( irc, NULL ); 671 root_command( irc, send_cmd ); 672 g_free( send_cmd[1] ); 756 673 } 757 674 758 if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )759 strcat( namelist, "+" );760 else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||761 ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )762 strcat( namelist, "@" );763 764 strcat( namelist, u->nick );765 strcat( namelist, " " );766 }767 }768 else if( ( c = irc_chat_by_channel( irc, channel ) ) )769 {770 GList *l;771 772 /* root and the user aren't in the channel userlist but should773 show up in /NAMES, so list them first: */774 sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,775 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );776 777 for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )778 {779 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )780 {781 irc_reply( irc, 353, "= %s :%s", channel, namelist );782 *namelist = 0;783 }784 785 strcat( namelist, u->nick );786 strcat( namelist, " " );787 }788 }789 790 if( *namelist )791 irc_reply( irc, 353, "= %s :%s", channel, namelist );792 793 irc_reply( irc, 366, "%s :End of /NAMES list", channel );794 }795 796 int irc_check_login( irc_t *irc )797 {798 if( irc->user && irc->nick )799 {800 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )801 {802 irc_reply( irc, 464, ":This server is password-protected." );803 return 0;804 }805 else806 {807 irc_login( irc );808 675 return 1; 809 676 } … … 816 683 } 817 684 818 void irc_login( irc_t *irc ) 819 { 820 user_t *u; 821 822 irc_reply( irc, 1, ":Welcome to the BitlBee gateway, %s", irc->nick ); 823 irc_reply( irc, 2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost ); 824 irc_reply( irc, 3, ":%s", IRCD_INFO ); 825 irc_reply( irc, 4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); 826 irc_reply( irc, 5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee " 827 "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", 828 CTYPES, CMODES, MAX_NICK_LENGTH - 1 ); 829 irc_motd( irc ); 830 irc->umode[0] = '\0'; 831 irc_umode_set( irc, "+" UMODE, 1 ); 832 833 u = user_add( irc, irc->mynick ); 834 u->host = g_strdup( irc->myhost ); 835 u->realname = g_strdup( ROOT_FN ); 836 u->online = 1; 837 u->send_handler = root_command_string; 838 u->is_private = 0; /* [SH] The channel is root's personal playground. */ 839 irc_spawn( irc, u ); 840 841 u = user_add( irc, NS_NICK ); 842 u->host = g_strdup( irc->myhost ); 843 u->realname = g_strdup( ROOT_FN ); 844 u->online = 0; 845 u->send_handler = root_command_string; 846 u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */ 847 848 u = user_add( irc, irc->nick ); 849 u->user = g_strdup( irc->user ); 850 u->host = g_strdup( irc->host ); 851 u->realname = g_strdup( irc->realname ); 852 u->online = 1; 853 irc_spawn( irc, u ); 854 855 irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n" 856 "If you've never used BitlBee before, please do read the help " 857 "information using the \x02help\x02 command. Lots of FAQs are " 858 "answered there.\n" 859 "If you already have an account on this server, just use the " 860 "\x02identify\x02 command to identify yourself." ); 861 862 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 863 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 864 865 irc->status |= USTATUS_LOGGED_IN; 866 867 /* This is for bug #209 (use PASS to identify to NickServ). */ 868 if( irc->password != NULL ) 869 { 870 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 871 872 irc_setpass( irc, NULL ); 873 root_command( irc, send_cmd ); 874 g_free( send_cmd[1] ); 875 } 876 } 877 878 void irc_motd( irc_t *irc ) 879 { 880 int fd; 881 882 fd = open( global.conf->motdfile, O_RDONLY ); 883 if( fd == -1 ) 884 { 885 irc_reply( irc, 422, ":We don't need MOTDs." ); 886 } 887 else 888 { 889 char linebuf[80]; /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */ 890 char *add, max; 891 int len; 892 893 linebuf[79] = len = 0; 894 max = sizeof( linebuf ) - 1; 895 896 irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost ); 897 while( read( fd, linebuf + len, 1 ) == 1 ) 898 { 899 if( linebuf[len] == '\n' || len == max ) 900 { 901 linebuf[len] = 0; 902 irc_reply( irc, 372, ":- %s", linebuf ); 903 len = 0; 904 } 905 else if( linebuf[len] == '%' ) 906 { 907 read( fd, linebuf + len, 1 ); 908 if( linebuf[len] == 'h' ) 909 add = irc->myhost; 910 else if( linebuf[len] == 'v' ) 911 add = BITLBEE_VERSION; 912 else if( linebuf[len] == 'n' ) 913 add = irc->nick; 914 else 915 add = "%"; 916 917 strncpy( linebuf + len, add, max - len ); 918 while( linebuf[++len] ); 919 } 920 else if( len < max ) 921 { 922 len ++; 923 } 924 } 925 irc_reply( irc, 376, ":End of MOTD" ); 926 close( fd ); 927 } 928 } 929 930 void irc_topic( irc_t *irc, char *channel ) 931 { 932 struct groupchat *c = irc_chat_by_channel( irc, channel ); 933 934 if( c && c->topic ) 935 irc_reply( irc, 332, "%s :%s", channel, c->topic ); 936 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 937 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC ); 938 else 939 irc_reply( irc, 331, "%s :No topic for this channel", channel ); 940 } 941 942 void irc_umode_set( irc_t *irc, char *s, int allow_priv ) 685 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) 943 686 { 944 687 /* allow_priv: Set to 0 if s contains user input, 1 if you want 945 688 to set a "privileged" mode (+o, +R, etc). */ 946 char m[256], st = 1, *t; 689 char m[128], st = 1; 690 const char *t; 947 691 int i; 948 692 char changes[512], *p, st2 = 2; … … 952 696 953 697 for( t = irc->umode; *t; t ++ ) 954 m[(int)*t] = 1; 955 698 if( *t < sizeof( m ) ) 699 m[(int)*t] = 1; 700 956 701 p = changes; 957 702 for( t = s; *t; t ++ ) … … 959 704 if( *t == '+' || *t == '-' ) 960 705 st = *t == '+'; 961 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) 706 else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || 707 ( st == 1 && strchr( UMODES, *t ) ) || 708 ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) 962 709 { 963 710 if( m[(int)*t] != st) … … 976 723 memset( irc->umode, 0, sizeof( irc->umode ) ); 977 724 978 for( i = 0; i < 256&& strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )725 for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) 979 726 if( m[i] ) 980 727 irc->umode[strlen(irc->umode)] = i; 981 728 982 729 if( badflag ) 983 irc_reply( irc, 501, ":Unknown MODE flag" ); 984 /* Deliberately no !user@host on the prefix here */ 730 irc_send_num( irc, 501, ":Unknown MODE flag" ); 985 731 if( *changes ) 986 irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes ); 987 } 988 989 void irc_spawn( irc_t *irc, user_t *u ) 990 { 991 irc_join( irc, u, irc->channel ); 992 } 993 994 void irc_join( irc_t *irc, user_t *u, char *channel ) 995 { 996 char *nick; 997 998 if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) ) 999 irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel ); 1000 1001 if( nick_cmp( u->nick, irc->nick ) == 0 ) 1002 { 1003 irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE ); 1004 irc_names( irc, channel ); 1005 irc_topic( irc, channel ); 1006 } 1007 1008 nick = g_strdup( u->nick ); 1009 nick_lc( nick ); 1010 if( g_hash_table_lookup( irc->watches, nick ) ) 1011 { 1012 irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" ); 1013 } 1014 g_free( nick ); 1015 } 1016 1017 void irc_part( irc_t *irc, user_t *u, char *channel ) 1018 { 1019 irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" ); 1020 } 1021 1022 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ) 1023 { 1024 irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" ); 1025 } 1026 1027 void irc_kill( irc_t *irc, user_t *u ) 1028 { 1029 char *nick, *s; 1030 char reason[128]; 1031 1032 if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) ) 1033 { 1034 if( u->ic->acc->server ) 1035 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1036 u->ic->acc->server ); 1037 else if( ( s = strchr( u->ic->acc->user, '@' ) ) ) 1038 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1039 s + 1 ); 1040 else 1041 g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, 1042 u->ic->acc->prpl->name, irc->myhost ); 1043 1044 /* proto_opt might contain garbage after the : */ 1045 if( ( s = strchr( reason, ':' ) ) ) 1046 *s = 0; 1047 } 1048 else 1049 { 1050 strcpy( reason, "Leaving..." ); 1051 } 1052 1053 irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason ); 1054 1055 nick = g_strdup( u->nick ); 1056 nick_lc( nick ); 1057 if( g_hash_table_lookup( irc->watches, nick ) ) 1058 { 1059 irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" ); 1060 } 1061 g_free( nick ); 1062 } 1063 1064 int irc_send( irc_t *irc, char *nick, char *s, int flags ) 1065 { 1066 struct groupchat *c = NULL; 1067 user_t *u = NULL; 1068 1069 if( strchr( CTYPES, *nick ) ) 1070 { 1071 if( !( c = irc_chat_by_channel( irc, nick ) ) ) 1072 { 1073 irc_reply( irc, 403, "%s :Channel does not exist", nick ); 1074 return( 0 ); 1075 } 1076 } 1077 else 1078 { 1079 u = user_find( irc, nick ); 1080 1081 if( !u ) 1082 { 1083 if( irc->is_private ) 1084 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 1085 else 1086 irc_usermsg( irc, "Nick `%s' does not exist!", nick ); 1087 return( 0 ); 1088 } 1089 } 1090 1091 if( *s == 1 && s[strlen(s)-1] == 1 ) 1092 { 1093 if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 ) 1094 { 1095 if( s[7] == ' ' ) s ++; 1096 s += 3; 1097 *(s++) = '/'; 1098 *(s++) = 'm'; 1099 *(s++) = 'e'; 1100 *(s++) = ' '; 1101 s -= 4; 1102 s[strlen(s)-1] = 0; 1103 } 1104 else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 ) 1105 { 1106 u = user_find( irc, irc->mynick ); 1107 irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" ); 1108 return( 1 ); 1109 } 1110 else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 ) 1111 { 1112 u = user_find( irc, irc->mynick ); 1113 irc_privmsg( irc, u, "NOTICE", irc->nick, "", s ); 1114 return( 1 ); 1115 } 1116 else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 ) 1117 { 1118 if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 ) 1119 { 1120 time_t current_typing_notice = time( NULL ); 1121 1122 if( current_typing_notice - u->last_typing_notice >= 5 ) 1123 { 1124 u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 ); 1125 u->last_typing_notice = current_typing_notice; 1126 } 1127 } 1128 return( 1 ); 1129 } 1130 else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 ) 1131 { 1132 if( u && u->ic && u->ic->acc->prpl->transfer_request ) 1133 { 1134 file_transfer_t *ft = dcc_request( u->ic, s + 5 ); 1135 if ( ft ) 1136 u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle ); 1137 } 1138 return( 1 ); 1139 } 1140 else 1141 { 1142 irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" ); 1143 return( 0 ); 1144 } 1145 } 1146 1147 if( u ) 1148 { 1149 /* For the next message, we probably do have to send new notices... */ 1150 u->last_typing_notice = 0; 1151 u->is_private = irc->is_private; 1152 1153 if( u->is_private ) 1154 { 1155 if( !u->online ) 1156 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 1157 else if( u->away ) 1158 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 1159 } 1160 1161 if( u->send_handler ) 1162 { 1163 u->send_handler( irc, u, s, flags ); 1164 return 1; 1165 } 1166 } 1167 else if( c && c->ic && c->ic->acc && c->ic->acc->prpl ) 1168 { 1169 return( imc_chat_msg( c, s, 0 ) ); 1170 } 1171 1172 return( 0 ); 1173 } 1174 1175 static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond ) 1176 { 1177 user_t *u = data; 1178 1179 /* Shouldn't happen, but just to be sure. */ 1180 if( u->sendbuf_len < 2 ) 1181 return FALSE; 1182 1183 u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */ 1184 imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); 1185 1186 g_free( u->sendbuf ); 1187 u->sendbuf = NULL; 1188 u->sendbuf_len = 0; 1189 u->sendbuf_timer = 0; 1190 u->sendbuf_flags = 0; 1191 1192 return FALSE; 1193 } 1194 1195 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) 1196 { 1197 if( !u || !u->ic ) return; 1198 1199 if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) 1200 { 1201 int delay; 1202 1203 if( u->sendbuf_len > 0 && u->sendbuf_flags != flags) 1204 { 1205 /* Flush the buffer */ 1206 b_event_remove( u->sendbuf_timer ); 1207 buddy_send_handler_delayed( u, -1, 0 ); 1208 } 1209 1210 if( u->sendbuf_len == 0 ) 1211 { 1212 u->sendbuf_len = strlen( msg ) + 2; 1213 u->sendbuf = g_new( char, u->sendbuf_len ); 1214 u->sendbuf[0] = 0; 1215 u->sendbuf_flags = flags; 1216 } 1217 else 1218 { 1219 u->sendbuf_len += strlen( msg ) + 1; 1220 u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len ); 1221 } 1222 1223 strcat( u->sendbuf, msg ); 1224 strcat( u->sendbuf, "\n" ); 1225 1226 delay = set_getint( &irc->set, "buddy_sendbuffer_delay" ); 1227 if( delay <= 5 ) 1228 delay *= 1000; 1229 1230 if( u->sendbuf_timer > 0 ) 1231 b_event_remove( u->sendbuf_timer ); 1232 u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u ); 1233 } 1234 else 1235 { 1236 imc_buddy_msg( u->ic, u->handle, msg, flags ); 1237 } 1238 } 1239 1240 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ) 1241 { 1242 char last = 0; 1243 char *s = msg, *line = msg; 1244 1245 /* The almighty linesplitter .. woohoo!! */ 1246 while( !last ) 1247 { 1248 if( *s == '\r' && *(s+1) == '\n' ) 1249 *(s++) = 0; 1250 if( *s == '\n' ) 1251 { 1252 last = s[1] == 0; 1253 *s = 0; 1254 } 1255 else 1256 { 1257 last = s[0] == 0; 1258 } 1259 if( *s == 0 ) 1260 { 1261 if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 ) 1262 { 1263 irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host, 1264 type, to, line + 4 ); 1265 } 1266 else 1267 { 1268 irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host, 1269 type, to, prefix ? prefix : "", line ); 1270 } 1271 line = s + 1; 1272 } 1273 s ++; 1274 } 1275 1276 return( 1 ); 1277 } 1278 1279 int irc_msgfrom( irc_t *irc, char *nick, char *msg ) 1280 { 1281 user_t *u = user_find( irc, nick ); 1282 static char *prefix = NULL; 1283 1284 if( !u ) return( 0 ); 1285 if( prefix && *prefix ) g_free( prefix ); 1286 1287 if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 ) 1288 { 1289 int len = strlen( irc->nick) + 3; 1290 prefix = g_new (char, len ); 1291 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) ); 1292 prefix[len-1] = 0; 1293 } 1294 else 1295 { 1296 prefix = ""; 1297 } 1298 1299 return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) ); 1300 } 1301 1302 int irc_noticefrom( irc_t *irc, char *nick, char *msg ) 1303 { 1304 user_t *u = user_find( irc, nick ); 1305 1306 if( u ) 1307 return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) ); 1308 else 1309 return( 0 ); 732 irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, 733 irc->user->user, irc->user->host, irc->user->nick, 734 changes ); 1310 735 } 1311 736 … … 1346 771 } 1347 772 1348 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ) 1349 { 1350 struct groupchat *c; 1351 account_t *a; 1352 1353 /* This finds the connection which has a conversation which belongs to this channel */ 1354 for( a = irc->accounts; a; a = a->next ) 1355 { 1356 if( a->ic == NULL ) 1357 continue; 1358 1359 c = a->ic->groupchats; 1360 while( c ) 1361 { 1362 if( c->channel && g_strcasecmp( c->channel, channel ) == 0 ) 1363 return c; 1364 1365 c = c->next; 1366 } 1367 } 1368 1369 return NULL; 1370 } 773 static char *set_eval_charset( set_t *set, char *value ) 774 { 775 irc_t *irc = (irc_t*) set->data; 776 char *test; 777 gsize test_bytes = 0; 778 GIConv ic, oc; 779 780 if( g_strcasecmp( value, "none" ) == 0 ) 781 value = g_strdup( "utf-8" ); 782 783 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 784 { 785 return NULL; 786 } 787 788 /* Do a test iconv to see if the user picked an IRC-compatible 789 charset (for example utf-16 goes *horribly* wrong). */ 790 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 791 test_bytes > 1 ) 792 { 793 g_free( test ); 794 g_iconv_close( oc ); 795 irc_usermsg( irc, "Unsupported character set: The IRC protocol " 796 "only supports 8-bit character sets." ); 797 return NULL; 798 } 799 g_free( test ); 800 801 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 802 { 803 g_iconv_close( oc ); 804 return NULL; 805 } 806 807 if( irc->iconv != (GIConv) -1 ) 808 g_iconv_close( irc->iconv ); 809 if( irc->oconv != (GIConv) -1 ) 810 g_iconv_close( irc->oconv ); 811 812 irc->iconv = ic; 813 irc->oconv = oc; 814 815 return value; 816 } 817 818 char *set_eval_away_devoice( set_t *set, char *value ) 819 { 820 irc_t *irc = set->data; 821 822 if( !is_bool( value ) ) 823 return SET_INVALID; 824 825 /* The usual problem: The setting isn't actually changed at this 826 point and we need it to be, so do it by hand. */ 827 g_free( set->value ); 828 set->value = g_strdup( value ); 829 830 bee_irc_channel_update( irc, NULL, NULL ); 831 832 return value; 833 } -
irc.h
r560d0a0 rf1cea66 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 33 33 #define IRC_PING_STRING "PinglBee" 34 34 35 #define UMODES "abisw" 36 #define UMODES_PRIV "Ro" 37 #define CMODES "nt" 38 #define CMODE "t" 39 #define UMODE "s" 40 #define CTYPES "&#" 35 #define UMODES "abisw" /* Allowed umodes (although they mostly do nothing) */ 36 #define UMODES_PRIV "Ro" /* Allowed, but not by user directly */ 37 #define UMODES_KEEP "R" /* Don't allow unsetting using /MODE */ 38 #define CMODES "nt" /* Allowed modes */ 39 #define CMODE "t" /* Default mode */ 40 #define UMODE "s" /* Default mode */ 41 42 #define CTYPES "&#" /* Valid channel name prefixes */ 41 43 42 44 typedef enum … … 48 50 USTATUS_SHUTDOWN = 8 49 51 } irc_status_t; 52 53 struct irc_user; 50 54 51 55 typedef struct irc … … 59 63 GIConv iconv, oconv; 60 64 61 int sentbytes; 62 time_t oldtime; 63 65 struct irc_user *root; 66 struct irc_user *user; 67 68 char *last_root_cmd; 69 70 char *password; /* HACK: Used to save the user's password, but before 71 logging in, this may contain a password we should 72 send to identify after USER/NICK are received. */ 73 74 char umode[8]; 75 76 struct query *queries; 77 GSList *file_transfers; 78 79 GSList *users, *channels; 80 struct irc_channel *default_channel; 81 GHashTable *nick_user_hash; 82 GHashTable *watches; 83 84 gint r_watch_source_id; 85 gint w_watch_source_id; 86 gint ping_source_id; 87 88 struct bee *b; 89 } irc_t; 90 91 typedef enum 92 { 93 IRC_USER_PRIVATE = 1, 94 IRC_USER_AWAY = 2, 95 } irc_user_flags_t; 96 97 typedef struct irc_user 98 { 99 irc_t *irc; 100 64 101 char *nick; 65 102 char *user; 66 103 char *host; 67 char *realname; 68 char *password; /* HACK: Used to save the user's password, but before 69 logging in, this may contain a password we should 70 send to identify after USER/NICK are received. */ 71 72 char umode[8]; 73 74 char *myhost; 75 char *mynick; 76 77 char *channel; 78 int c_id; 79 80 char is_private; /* Not too nice... */ 81 char *last_target; 82 83 struct query *queries; 84 struct account *accounts; 85 GSList *file_transfers; 86 struct chat *chatrooms; 87 88 struct __USER *users; 89 GHashTable *userhash; 90 GHashTable *watches; 91 struct __NICK *nicks; 104 char *fullname; 105 106 /* Nickname in lowercase for case sensitive searches */ 107 char *key; 108 109 irc_user_flags_t flags; 110 111 GString *pastebuf; 112 guint pastebuf_timer; 113 114 struct bee_user *bu; 115 116 const struct irc_user_funcs *f; 117 } irc_user_t; 118 119 struct irc_user_funcs 120 { 121 gboolean (*privmsg)( irc_user_t *iu, const char *msg ); 122 gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp ); 123 }; 124 125 extern const struct irc_user_funcs irc_user_root_funcs; 126 extern const struct irc_user_funcs irc_user_self_funcs; 127 128 typedef enum 129 { 130 IRC_CHANNEL_JOINED = 1, 131 132 /* Hack: Set this flag right before jumping into IM when we expect 133 a call to imcb_chat_new(). */ 134 IRC_CHANNEL_CHAT_PICKME = 0x10000, 135 } irc_channel_flags_t; 136 137 typedef struct irc_channel 138 { 139 irc_t *irc; 140 char *name; 141 char mode[8]; 142 int flags; 143 144 char *topic; 145 char *topic_who; 146 time_t topic_time; 147 148 GSList *users; 92 149 struct set *set; 93 94 gint r_watch_source_id; 95 gint w_watch_source_id; 96 gint ping_source_id; 97 } irc_t; 98 99 #include "user.h" 100 150 151 GString *pastebuf; 152 guint pastebuf_timer; 153 154 const struct irc_channel_funcs *f; 155 void *data; 156 } irc_channel_t; 157 158 struct irc_channel_funcs 159 { 160 gboolean (*privmsg)( irc_channel_t *ic, const char *msg ); 161 gboolean (*join)( irc_channel_t *ic ); 162 gboolean (*part)( irc_channel_t *ic, const char *msg ); 163 gboolean (*topic)( irc_channel_t *ic, const char *new ); 164 gboolean (*invite)( irc_channel_t *ic, irc_user_t *iu ); 165 166 gboolean (*_init)( irc_channel_t *ic ); 167 gboolean (*_free)( irc_channel_t *ic ); 168 }; 169 170 typedef enum 171 { 172 IRC_CHANNEL_USER_OP = 1, 173 IRC_CHANNEL_USER_HALFOP = 2, 174 IRC_CHANNEL_USER_VOICE = 4, 175 } irc_channel_user_flags_t; 176 177 typedef struct irc_channel_user 178 { 179 irc_user_t *iu; 180 int flags; 181 } irc_channel_user_t; 182 183 typedef enum 184 { 185 IRC_CC_TYPE_DEFAULT, 186 IRC_CC_TYPE_REST, 187 IRC_CC_TYPE_GROUP, 188 IRC_CC_TYPE_ACCOUNT, 189 } irc_control_channel_type_t; 190 191 struct irc_control_channel 192 { 193 irc_control_channel_type_t type; 194 struct bee_group *group; 195 struct account *account; 196 }; 197 198 extern const struct bee_ui_funcs irc_ui_funcs; 199 200 /* irc.c */ 101 201 extern GSList *irc_connection_list; 102 202 … … 104 204 void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 105 205 void irc_free( irc_t *irc ); 106 107 void irc_exec( irc_t *irc, char **cmd ); 206 void irc_setpass (irc_t *irc, const char *pass); 207 108 208 void irc_process( irc_t *irc ); 109 209 char **irc_parse_line( char *line ); 110 210 char *irc_build_line( char **cmd ); 111 211 112 void irc_vawrite( irc_t *irc, char *format, va_list params );113 212 void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 114 213 void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 115 void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 116 G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 117 char **irc_tokenize( char *buffer ); 118 119 void irc_login( irc_t *irc ); 214 void irc_vawrite( irc_t *irc, char *format, va_list params ); 215 120 216 int irc_check_login( irc_t *irc ); 121 void irc_motd( irc_t *irc ); 122 void irc_names( irc_t *irc, char *channel ); 123 void irc_topic( irc_t *irc, char *channel ); 124 void irc_umode_set( irc_t *irc, char *s, int allow_priv ); 125 void irc_who( irc_t *irc, char *channel ); 126 void irc_spawn( irc_t *irc, user_t *u ); 127 void irc_join( irc_t *irc, user_t *u, char *channel ); 128 void irc_part( irc_t *irc, user_t *u, char *channel ); 129 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ); 130 void irc_kill( irc_t *irc, user_t *u ); 131 void irc_invite( irc_t *irc, char *nick, char *channel ); 132 void irc_whois( irc_t *irc, char *nick ); 133 void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */ 134 135 int irc_send( irc_t *irc, char *nick, char *s, int flags ); 136 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ); 137 int irc_msgfrom( irc_t *irc, char *nick, char *msg ); 138 int irc_noticefrom( irc_t *irc, char *nick, char *msg ); 139 140 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); 141 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ); 217 218 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); 219 220 /* irc_channel.c */ 221 irc_channel_t *irc_channel_new( irc_t *irc, const char *name ); 222 irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ); 223 irc_channel_t *irc_channel_get( irc_t *irc, char *id ); 224 int irc_channel_free( irc_channel_t *ic ); 225 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu ); 226 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu, gboolean silent, const char *msg ); 227 irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu ); 228 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who ); 229 void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags ); 230 void irc_channel_printf( irc_channel_t *ic, char *format, ... ); 231 gboolean irc_channel_name_ok( const char *name ); 232 void irc_channel_update_ops( irc_channel_t *ic, char *value ); 233 char *set_eval_irc_channel_ops( struct set *set, char *value ); 234 235 /* irc_commands.c */ 236 void irc_exec( irc_t *irc, char **cmd ); 237 238 /* irc_send.c */ 239 void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 240 void irc_send_login( irc_t *irc ); 241 void irc_send_motd( irc_t *irc ); 242 void irc_usermsg( irc_t *irc, char *format, ... ); 243 void irc_send_join( irc_channel_t *ic, irc_user_t *iu ); 244 void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason ); 245 void irc_send_quit( irc_user_t *iu, const char *reason ); 246 void irc_send_names( irc_channel_t *ic ); 247 void irc_send_topic( irc_channel_t *ic, gboolean topic_change ); 248 void irc_send_whois( irc_user_t *iu ); 249 void irc_send_who( irc_t *irc, GSList *l, const char *channel ); 250 void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix ); 251 void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg ); 252 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 ); 253 void irc_send_nick( irc_user_t *iu, const char *new ); 254 void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu, 255 irc_channel_user_flags_t old, irc_channel_user_flags_t new ); 256 257 /* irc_user.c */ 258 irc_user_t *irc_user_new( irc_t *irc, const char *nick ); 259 int irc_user_free( irc_t *irc, irc_user_t *iu ); 260 irc_user_t *irc_user_by_name( irc_t *irc, const char *nick ); 261 int irc_user_set_nick( irc_user_t *iu, const char *new ); 262 gint irc_user_cmp( gconstpointer a_, gconstpointer b_ ); 263 const char *irc_user_get_away( irc_user_t *iu ); 264 265 /* irc_util.c */ 266 char *set_eval_timezone( struct set *set, char *value ); 267 char *irc_format_timestamp( irc_t *irc, time_t msg_ts ); 268 269 /* irc_im.c */ 270 void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu ); 142 271 143 272 #endif -
irc_commands.c
r560d0a0 rf1cea66 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 06Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 53 53 else if( global.conf->auth_pass ) 54 54 { 55 irc_ reply( irc, 464, ":Incorrect password" );55 irc_send_num( irc, 464, ":Incorrect password" ); 56 56 } 57 57 else … … 65 65 static void irc_cmd_user( irc_t *irc, char **cmd ) 66 66 { 67 irc->user = g_strdup( cmd[1] );68 irc-> realname = g_strdup( cmd[4] );67 irc->user->user = g_strdup( cmd[1] ); 68 irc->user->fullname = g_strdup( cmd[4] ); 69 69 70 70 irc_check_login( irc ); … … 73 73 static void irc_cmd_nick( irc_t *irc, char **cmd ) 74 74 { 75 if( irc->status & USTATUS_IDENTIFIED && irc->nick ) 76 { 77 irc_reply( irc, 438, "%s %s :You can only change your nick if you're not " 78 "logged in (i.e. pre-identify)", irc->nick, cmd[1] ); 79 } 80 /* This is not clean, but for now it'll have to be like this... */ 81 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) || ( user_find( irc, cmd[1] ) != NULL ) ) 82 { 83 irc_reply( irc, 433, "%s :This nick is already in use", cmd[1] ); 75 if( irc_user_by_name( irc, cmd[1] ) ) 76 { 77 irc_send_num( irc, 433, ":This nick is already in use" ); 84 78 } 85 79 else if( !nick_ok( cmd[1] ) ) 86 80 { 87 81 /* [SH] Invalid characters. */ 88 irc_reply( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); 89 } 90 else if(irc->nick) 91 { 92 if( user_find( irc, irc->nick ) ) 93 user_rename(irc, irc->nick, cmd[1]); 94 95 irc_write( irc, ":%s!%s@%s NICK %s", irc->nick, irc->user, irc->host, cmd[1] ); 96 g_free(irc->nick); 97 irc->nick = g_strdup( cmd[1] ); 98 } 99 else 100 { 101 irc->nick = g_strdup( cmd[1] ); 82 irc_send_num( irc, 432, ":This nick contains invalid characters" ); 83 } 84 else if( irc->user->nick ) 85 { 86 if( irc->status & USTATUS_IDENTIFIED ) 87 { 88 irc_setpass( irc, NULL ); 89 irc->status &= ~USTATUS_IDENTIFIED; 90 irc_umode_set( irc, "-R", 1 ); 91 irc_usermsg( irc, "Changing nicks resets your identify status. " 92 "Re-identify or register a new account if you want " 93 "your configuration to be saved. See \x02help " 94 "nick_changes\x02." ); 95 } 96 97 irc_user_set_nick( irc->user, cmd[1] ); 98 } 99 else 100 { 101 irc->user->nick = g_strdup( cmd[1] ); 102 102 103 103 irc_check_login( irc ); … … 115 115 static void irc_cmd_ping( irc_t *irc, char **cmd ) 116 116 { 117 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost ); 118 } 119 120 static void irc_cmd_oper( irc_t *irc, char **cmd ) 121 { 122 if( global.conf->oper_pass && 123 ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? 124 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : 125 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) 126 { 127 irc_umode_set( irc, "+o", 1 ); 128 irc_reply( irc, 381, ":Password accepted" ); 129 } 130 else 131 { 132 irc_reply( irc, 432, ":Incorrect password" ); 133 } 117 irc_write( irc, ":%s PONG %s :%s", irc->root->host, 118 irc->root->host, cmd[1]?cmd[1]:irc->root->host ); 119 } 120 121 static void irc_cmd_pong( irc_t *irc, char **cmd ) 122 { 123 /* We could check the value we get back from the user, but in 124 fact we don't care, we're just happy s/he's still alive. */ 125 irc->last_pong = gettime(); 126 irc->pinging = 0; 127 } 128 129 static void irc_cmd_join( irc_t *irc, char **cmd ) 130 { 131 irc_channel_t *ic; 132 133 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 134 ic = irc_channel_new( irc, cmd[1] ); 135 136 if( ic == NULL ) 137 { 138 irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] ); 139 return; 140 } 141 142 if( ic->flags & IRC_CHANNEL_JOINED ) 143 return; /* Dude, you're already there... 144 RFC doesn't have any reply for that though? */ 145 146 if( ic->f->join && !ic->f->join( ic ) ) 147 /* The story is: FALSE either means the handler showed an error 148 message, or is doing some work before the join should be 149 confirmed. (In the latter case, the caller should take care 150 of that confirmation.) 151 TRUE means all's good, let the user join the channel right away. */ 152 return; 153 154 irc_channel_add_user( ic, irc->user ); 155 } 156 157 static void irc_cmd_names( irc_t *irc, char **cmd ) 158 { 159 irc_channel_t *ic; 160 161 if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 162 irc_send_names( ic ); 163 /* With no args, we should show /names of all chans. Make the code 164 below work well if necessary. 165 else 166 { 167 GSList *l; 168 169 for( l = irc->channels; l; l = l->next ) 170 irc_send_names( l->data ); 171 } 172 */ 173 } 174 175 static void irc_cmd_part( irc_t *irc, char **cmd ) 176 { 177 irc_channel_t *ic; 178 179 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 180 { 181 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 182 } 183 else if( irc_channel_del_user( ic, irc->user, FALSE, cmd[2] ) ) 184 { 185 if( ic->f->part ) 186 ic->f->part( ic, NULL ); 187 } 188 else 189 { 190 irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] ); 191 } 192 } 193 194 static void irc_cmd_whois( irc_t *irc, char **cmd ) 195 { 196 char *nick = cmd[1]; 197 irc_user_t *iu = irc_user_by_name( irc, nick ); 198 199 if( iu ) 200 irc_send_whois( iu ); 201 else 202 irc_send_num( irc, 401, "%s :Nick does not exist", nick ); 203 } 204 205 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 206 { 207 /* For some reason irssi tries a whowas when whois fails. We can 208 ignore this, but then the user never gets a "user not found" 209 message from irssi which is a bit annoying. So just respond 210 with not-found and irssi users will get better error messages */ 211 212 irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] ); 213 irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] ); 214 } 215 216 static void irc_cmd_motd( irc_t *irc, char **cmd ) 217 { 218 irc_send_motd( irc ); 134 219 } 135 220 136 221 static void irc_cmd_mode( irc_t *irc, char **cmd ) 137 222 { 138 if( strchr( CTYPES, *cmd[1] ) ) 139 { 140 if( cmd[2] ) 223 if( irc_channel_name_ok( cmd[1] ) ) 224 { 225 irc_channel_t *ic; 226 227 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 228 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 229 else if( cmd[2] ) 141 230 { 142 231 if( *cmd[2] == '+' || *cmd[2] == '-' ) 143 irc_ reply( irc, 477, "%s :Can't change channel modes", cmd[1] );232 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); 144 233 else if( *cmd[2] == 'b' ) 145 irc_ reply( irc, 368, "%s :No bans possible", cmd[1] );234 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] ); 146 235 } 147 236 else 148 irc_ reply( irc, 324, "%s +%s", cmd[1], CMODE);149 } 150 else 151 { 152 if( nick_cmp( cmd[1], irc-> nick ) == 0 )237 irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode ); 238 } 239 else 240 { 241 if( nick_cmp( cmd[1], irc->user->nick ) == 0 ) 153 242 { 154 243 if( cmd[2] ) 155 244 irc_umode_set( irc, cmd[2], 0 ); 156 245 else 157 irc_ reply( irc, 221, "+%s", irc->umode );246 irc_send_num( irc, 221, "+%s", irc->umode ); 158 247 } 159 248 else 160 irc_reply( irc, 502, ":Don't touch their modes" ); 161 } 162 } 163 164 static void irc_cmd_names( irc_t *irc, char **cmd ) 165 { 166 irc_names( irc, cmd[1]?cmd[1]:irc->channel ); 167 } 168 169 static void irc_cmd_part( irc_t *irc, char **cmd ) 170 { 171 struct groupchat *c; 172 173 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 174 { 175 user_t *u = user_find( irc, irc->nick ); 176 177 /* Not allowed to leave control channel */ 178 irc_part( irc, u, irc->channel ); 179 irc_join( irc, u, irc->channel ); 180 } 181 else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) ) 182 { 183 user_t *u = user_find( irc, irc->nick ); 184 185 irc_part( irc, u, c->channel ); 186 187 if( c->ic ) 188 { 189 c->joined = 0; 190 c->ic->acc->prpl->chat_leave( c ); 191 } 192 } 193 else 194 { 195 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 196 } 197 } 198 199 static void irc_cmd_join( irc_t *irc, char **cmd ) 200 { 201 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 202 ; /* Dude, you're already there... 203 RFC doesn't have any reply for that though? */ 204 else if( cmd[1] ) 205 { 206 struct chat *c; 207 208 if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 ) 209 irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] ); 210 else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic ) 211 chat_join( irc, c, cmd[2] ); 212 else 213 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 214 } 215 } 216 217 static void irc_cmd_invite( irc_t *irc, char **cmd ) 218 { 219 char *nick = cmd[1], *channel = cmd[2]; 220 struct groupchat *c = irc_chat_by_channel( irc, channel ); 221 user_t *u = user_find( irc, nick ); 222 223 if( u && c && ( u->ic == c->ic ) ) 224 if( c->ic && c->ic->acc->prpl->chat_invite ) 225 { 226 c->ic->acc->prpl->chat_invite( c, u->handle, NULL ); 227 irc_reply( irc, 341, "%s %s", nick, channel ); 228 return; 229 } 230 231 irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel ); 249 irc_send_num( irc, 502, ":Don't touch their modes" ); 250 } 251 } 252 253 static void irc_cmd_who( irc_t *irc, char **cmd ) 254 { 255 char *channel = cmd[1]; 256 irc_channel_t *ic; 257 258 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 259 irc_send_who( irc, irc->users, "**" ); 260 else if( ( ic = irc_channel_by_name( irc, channel ) ) ) 261 irc_send_who( irc, ic->users, channel ); 262 else 263 irc_send_num( irc, 403, "%s :No such channel", channel ); 232 264 } 233 265 234 266 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 235 267 { 236 if ( !cmd[2] ) 237 { 238 irc_reply( irc, 412, ":No text to send" ); 239 } 240 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 241 { 242 irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] ); 268 irc_channel_t *ic; 269 irc_user_t *iu; 270 271 if( !cmd[2] ) 272 { 273 irc_send_num( irc, 412, ":No text to send" ); 274 return; 275 } 276 277 /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ 278 if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) 279 { 280 cmd[2] += 4; 281 strcpy( cmd[2], "/me" ); 282 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 283 cmd[2][strlen(cmd[2])-1] = '\0'; 284 } 285 286 if( irc_channel_name_ok( cmd[1] ) && 287 ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 288 { 289 if( ic->f->privmsg ) 290 ic->f->privmsg( ic, cmd[2] ); 291 } 292 else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) 293 { 294 if( cmd[2][0] == '\001' ) 295 { 296 char **ctcp; 297 298 if( iu->f->ctcp == NULL ) 299 return; 300 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 301 cmd[2][strlen(cmd[2])-1] = '\0'; 302 303 ctcp = split_command_parts( cmd[2] + 1 ); 304 iu->f->ctcp( iu, ctcp ); 305 } 306 else if( iu->f->privmsg ) 307 { 308 iu->flags |= IRC_USER_PRIVATE; 309 iu->f->privmsg( iu, cmd[2] ); 310 } 311 } 312 else 313 { 314 irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); 315 } 316 317 318 #if 0 319 else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 320 { 243 321 } 244 322 else … … 281 359 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); 282 360 } 283 } 284 285 static void irc_cmd_who( irc_t *irc, char **cmd ) 286 { 287 char *channel = cmd[1]; 288 user_t *u = irc->users; 289 struct groupchat *c; 290 GList *l; 291 292 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 293 while( u ) 294 { 295 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 ); 296 u = u->next; 297 } 298 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 299 while( u ) 300 { 301 if( u->online ) 302 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 ); 303 u = u->next; 304 } 305 else if( ( c = irc_chat_by_channel( irc, channel ) ) ) 306 for( l = c->in_room; l; l = l->next ) 307 { 308 if( ( u = user_findhandle( c->ic, l->data ) ) ) 309 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 ); 310 } 311 else if( ( u = user_find( irc, channel ) ) ) 312 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 ); 313 314 irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" ); 361 #endif 362 } 363 364 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 365 { 366 /* [SH] This aliases the NickServ command to PRIVMSG root */ 367 /* [TV] This aliases the NS command to PRIVMSG root as well */ 368 root_command( irc, cmd + 1 ); 369 } 370 371 372 373 static void irc_cmd_oper( irc_t *irc, char **cmd ) 374 { 375 if( global.conf->oper_pass && 376 ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? 377 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : 378 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) 379 { 380 irc_umode_set( irc, "+o", 1 ); 381 irc_send_num( irc, 381, ":Password accepted" ); 382 } 383 else 384 { 385 irc_send_num( irc, 432, ":Incorrect password" ); 386 } 387 } 388 389 static void irc_cmd_invite( irc_t *irc, char **cmd ) 390 { 391 irc_channel_t *ic; 392 irc_user_t *iu; 393 394 if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL ) 395 { 396 irc_send_num( irc, 401, "%s :No such nick", cmd[1] ); 397 return; 398 } 399 else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL ) 400 { 401 irc_send_num( irc, 403, "%s :No such channel", cmd[2] ); 402 return; 403 } 404 405 if( !ic->f->invite || !ic->f->invite( ic, iu ) ) 406 irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] ); 315 407 } 316 408 317 409 static void irc_cmd_userhost( irc_t *irc, char **cmd ) 318 410 { 319 user_t *u;320 411 int i; 321 412 … … 327 418 328 419 for( i = 1; cmd[i]; i ++ ) 329 if( ( u = user_find( irc, cmd[i] ) ) ) 330 { 331 if( u->online && u->away ) 332 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host ); 333 else 334 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); 335 } 420 { 421 irc_user_t *iu = irc_user_by_name( irc, cmd[i] ); 422 423 if( iu ) 424 irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick, 425 irc_user_get_away( iu ) ? '-' : '+', 426 iu->user, iu->host ); 427 } 336 428 } 337 429 338 430 static void irc_cmd_ison( irc_t *irc, char **cmd ) 339 431 { 340 user_t *u;341 432 char buff[IRC_MAX_LINE]; 342 433 int lenleft, i; … … 354 445 while( *this ) 355 446 { 447 irc_user_t *iu; 448 356 449 if( ( next = strchr( this, ' ' ) ) ) 357 450 *next = 0; 358 451 359 if( ( u = user_find( irc, this ) ) && u->online ) 360 { 361 lenleft -= strlen( u->nick ) + 1; 452 if( ( iu = irc_user_by_name( irc, this ) ) && 453 iu->bu && iu->bu->flags & BEE_USER_ONLINE ) 454 { 455 lenleft -= strlen( iu->nick ) + 1; 362 456 363 457 if( lenleft < 0 ) 364 458 break; 365 459 366 strcat( buff, u->nick );460 strcat( buff, iu->nick ); 367 461 strcat( buff, " " ); 368 462 } … … 387 481 buff[strlen(buff)-1] = '\0'; 388 482 389 irc_ reply( irc, 303, ":%s", buff );483 irc_send_num( irc, 303, ":%s", buff ); 390 484 } 391 485 … … 400 494 { 401 495 char *nick; 402 user_t *u;496 irc_user_t *iu; 403 497 404 498 if( !cmd[i][0] || !cmd[i][1] ) … … 408 502 nick_lc( nick ); 409 503 410 u = user_find( irc, nick );504 iu = irc_user_by_name( irc, nick ); 411 505 412 506 if( cmd[i][0] == '+' ) … … 415 509 g_hash_table_insert( irc->watches, nick, nick ); 416 510 417 if( u && u->online ) 418 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" ); 511 if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) 512 irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, 513 iu->host, (int) time( NULL ), "is online" ); 419 514 else 420 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); 515 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", 516 (int) time( NULL ), "is offline" ); 421 517 } 422 518 else if( cmd[i][0] == '-' ) … … 429 525 g_free( okey ); 430 526 431 irc_ reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );527 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 432 528 } 433 529 } … … 437 533 static void irc_cmd_topic( irc_t *irc, char **cmd ) 438 534 { 439 char *channel = cmd[1]; 440 char *topic = cmd[2]; 441 442 if( topic ) 443 { 444 /* Send the topic */ 445 struct groupchat *c = irc_chat_by_channel( irc, channel ); 446 if( c && c->ic && c->ic->acc->prpl->chat_topic ) 447 c->ic->acc->prpl->chat_topic( c, topic ); 448 } 449 else 450 { 451 /* Get the topic */ 452 irc_topic( irc, channel ); 535 irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] ); 536 const char *new = cmd[2]; 537 538 if( ic == NULL ) 539 { 540 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 541 } 542 else if( new ) 543 { 544 if( ic->f->topic == NULL ) 545 irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name ); 546 else if( ic->f->topic( ic, new ) ) 547 irc_send_topic( ic, TRUE ); 548 } 549 else 550 { 551 irc_send_topic( ic, FALSE ); 453 552 } 454 553 } … … 456 555 static void irc_cmd_away( irc_t *irc, char **cmd ) 457 556 { 458 user_t *u = user_find( irc, irc->nick ); 459 char *away = cmd[1]; 460 461 if( !u ) return; 462 463 if( away && *away ) 464 { 557 if( cmd[1] && *cmd[1] ) 558 { 559 char away[strlen(cmd[1])+1]; 465 560 int i, j; 466 561 467 562 /* Copy away string, but skip control chars. Mainly because 468 563 Jabber really doesn't like them. */ 469 u->away = g_malloc( strlen( away ) + 1 ); 470 for( i = j = 0; away[i]; i ++ ) 471 if( ( u->away[j] = away[i] ) >= ' ' ) 564 for( i = j = 0; cmd[1][i]; i ++ ) 565 if( ( away[j] = cmd[1][i] ) >= ' ' ) 472 566 j ++; 473 u->away[j] = 0; 474 475 irc_reply( irc, 306, ":You're now away: %s", u->away ); 476 /* irc_umode_set( irc, irc->myhost, "+a" ); */ 477 } 478 else 479 { 480 if( u->away ) g_free( u->away ); 481 u->away = NULL; 482 /* irc_umode_set( irc, irc->myhost, "-a" ); */ 483 irc_reply( irc, 305, ":Welcome back" ); 484 } 485 486 set_setstr( &irc->set, "away", u->away ); 487 } 488 489 static void irc_cmd_whois( irc_t *irc, char **cmd ) 490 { 491 char *nick = cmd[1]; 492 user_t *u = user_find( irc, nick ); 493 494 if( u ) 495 { 496 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname ); 497 498 if( u->ic ) 499 irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user, 500 u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "", 501 u->ic->acc->prpl->name ); 502 else 503 irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); 504 505 if( !u->online ) 506 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 507 else if( u->away ) 508 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 509 if( u->status_msg ) 510 irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg ); 511 512 irc_reply( irc, 318, "%s :End of /WHOIS list", nick ); 513 } 514 else 515 { 516 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 517 } 518 } 519 520 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 521 { 522 /* For some reason irssi tries a whowas when whois fails. We can 523 ignore this, but then the user never gets a "user not found" 524 message from irssi which is a bit annoying. So just respond 525 with not-found and irssi users will get better error messages */ 526 527 irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] ); 528 irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] ); 529 } 530 531 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 532 { 533 /* [SH] This aliases the NickServ command to PRIVMSG root */ 534 /* [TV] This aliases the NS command to PRIVMSG root as well */ 535 root_command( irc, cmd + 1 ); 536 } 537 538 static void irc_cmd_motd( irc_t *irc, char **cmd ) 539 { 540 irc_motd( irc ); 541 } 542 543 static void irc_cmd_pong( irc_t *irc, char **cmd ) 544 { 545 /* We could check the value we get back from the user, but in 546 fact we don't care, we're just happy he's still alive. */ 547 irc->last_pong = gettime(); 548 irc->pinging = 0; 567 away[j] = '\0'; 568 569 irc_send_num( irc, 306, ":You're now away: %s", away ); 570 set_setstr( &irc->b->set, "away", away ); 571 } 572 else 573 { 574 irc_send_num( irc, 305, ":Welcome back" ); 575 set_setstr( &irc->b->set, "away", NULL ); 576 } 549 577 } 550 578 551 579 static void irc_cmd_version( irc_t *irc, char **cmd ) 552 580 { 553 irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU ); 581 irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", 582 BITLBEE_VERSION, irc->root->host, ARCH, CPU ); 554 583 } 555 584 556 585 static void irc_cmd_completions( irc_t *irc, char **cmd ) 557 586 { 558 user_t *u = user_find( irc, irc->mynick );559 587 help_t *h; 560 588 set_t *s; 561 589 int i; 562 590 563 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );591 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" ); 564 592 565 593 for( i = 0; commands[i].command; i ++ ) 566 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS", commands[i].command );594 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command ); 567 595 568 596 for( h = global.help; h; h = h->next ) 569 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help", h->title );570 571 for( s = irc-> set; s; s = s->next )572 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set", s->key );573 574 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );597 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title ); 598 599 for( s = irc->b->set; s; s = s->next ) 600 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key ); 601 602 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" ); 575 603 } 576 604 … … 582 610 ipc_to_master( cmd ); 583 611 584 irc_ reply( irc, 382, "%s :Rehashing", global.conf_file );612 irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); 585 613 } 586 614 … … 591 619 { "quit", 0, irc_cmd_quit, 0 }, 592 620 { "ping", 0, irc_cmd_ping, 0 }, 593 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 621 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 622 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN }, 623 { "names", 1, irc_cmd_names, IRC_CMD_LOGGED_IN }, 624 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN }, 625 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN }, 626 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN }, 627 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN }, 594 628 { "mode", 1, irc_cmd_mode, IRC_CMD_LOGGED_IN }, 595 { "names", 0, irc_cmd_names, IRC_CMD_LOGGED_IN }, 596 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN }, 597 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN }, 598 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 629 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 599 630 { "privmsg", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 600 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 601 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 631 { "nickserv", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 632 { "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 633 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN }, 634 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 635 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, 602 636 { "userhost", 1, irc_cmd_userhost, IRC_CMD_LOGGED_IN }, 603 637 { "ison", 1, irc_cmd_ison, IRC_CMD_LOGGED_IN }, 604 638 { "watch", 1, irc_cmd_watch, IRC_CMD_LOGGED_IN }, 639 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 640 #if 0 641 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 642 #endif 605 643 { "topic", 1, irc_cmd_topic, IRC_CMD_LOGGED_IN }, 606 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN }, 607 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN }, 608 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN }, 609 { "nickserv", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 610 { "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 611 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN }, 612 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 613 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 614 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, 644 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 615 645 { "die", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 616 646 { "deaf", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, … … 638 668 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 639 669 { 640 irc_ reply( irc, 462, ":Only allowed before logging in" );670 irc_send_num( irc, 462, ":Only allowed before logging in" ); 641 671 } 642 672 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 643 673 { 644 irc_ reply( irc, 451, ":Register first" );674 irc_send_num( irc, 451, ":Register first" ); 645 675 } 646 676 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 647 677 { 648 irc_ reply( irc, 481, ":Permission denied - You're not an IRC operator" );678 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" ); 649 679 } 650 680 else if( n_arg < irc_commands[i].required_parameters ) 651 681 { 652 irc_ reply( irc, 461, "%s :Need more parameters", cmd[0] );682 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] ); 653 683 } 654 684 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) … … 667 697 668 698 if( irc->status >= USTATUS_LOGGED_IN ) 669 irc_ reply( irc, 421, "%s :Unknown command", cmd[0] );670 } 699 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] ); 700 } -
lib/misc.c
r560d0a0 rf1cea66 647 647 return ret; 648 648 } 649 650 char **split_command_parts( char *command ) 651 { 652 static char *cmd[IRC_MAX_ARGS+1]; 653 char *s, q = 0; 654 int k; 655 656 memset( cmd, 0, sizeof( cmd ) ); 657 cmd[0] = command; 658 k = 1; 659 for( s = command; *s && k < IRC_MAX_ARGS; s ++ ) 660 if( *s == ' ' && !q ) 661 { 662 *s = 0; 663 while( *++s == ' ' ); 664 if( *s == '"' || *s == '\'' ) 665 { 666 q = *s; 667 s ++; 668 } 669 if( *s ) 670 { 671 cmd[k++] = s; 672 s --; 673 } 674 else 675 { 676 break; 677 } 678 } 679 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) 680 { 681 char *cpy; 682 683 for( cpy = s; *cpy; cpy ++ ) 684 cpy[0] = cpy[1]; 685 } 686 else if( *s == q ) 687 { 688 q = *s = 0; 689 } 690 691 /* Full zero-padding for easier argc checking. */ 692 while( k <= IRC_MAX_ARGS ) 693 cmd[k++] = NULL; 694 695 return cmd; 696 } -
lib/misc.h
r560d0a0 rf1cea66 69 69 G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); 70 70 71 G_MODULE_EXPORT char **split_command_parts( char *command ); 72 71 73 #endif -
nick.c
r560d0a0 rf1cea66 78 78 79 79 nick_strip( nick ); 80 if( set_getbool( &acc-> irc->set, "lcnicks" ) )80 if( set_getbool( &acc->bee->set, "lcnicks" ) ) 81 81 nick_lc( nick ); 82 82 } … … 92 92 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) 93 93 { 94 irc_t *irc = (irc_t*) acc->bee->ui_data; 94 95 int inf_protection = 256; 95 96 96 97 /* Now, find out if the nick is already in use at the moment, and make 97 98 subtle changes to make it unique. */ 98 while( !nick_ok( nick ) || user_find( acc->irc, nick ) )99 while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) ) 99 100 { 100 101 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) … … 112 113 int i; 113 114 114 irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! "115 116 117 118 119 120 irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );115 irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! " 116 "This used to be a fatal BitlBee bug, but we tried to fix it. " 117 "This message should *never* appear anymore. " 118 "If it does, please *do* send us a bug report! " 119 "Please send all the following lines in your report:" ); 120 121 irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); 121 122 for( i = 0; i < MAX_NICK_LENGTH; i ++ ) 122 irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );123 124 irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "125 126 123 irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); 124 125 irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " 126 "Good luck, and please don't forget to paste the lines up here " 127 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); 127 128 128 129 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); -
protocols/Makefile
r560d0a0 rf1cea66 13 13 14 14 # [SH] Program variables 15 objects = nogaim.o 15 objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o 16 16 17 17 18 # [SH] The next two lines should contain the directory name (in $(subdirs)) -
protocols/ft.h
r560d0a0 rf1cea66 107 107 */ 108 108 gpointer data; 109 struct im_connection *ic; 109 110 110 111 /* … … 168 169 * the canceled() and free() callbacks given in file will be called by this function. 169 170 */ 170 void imcb_file_canceled( file_transfer_t *file, char *reason );171 void imcb_file_canceled( struct im_connection *ic, file_transfer_t *file, char *reason ); 171 172 172 gboolean imcb_file_recv_start( file_transfer_t *ft );173 gboolean imcb_file_recv_start( struct im_connection *ic, file_transfer_t *ft ); 173 174 174 void imcb_file_finished( file_transfer_t *file );175 void imcb_file_finished( struct im_connection *ic, file_transfer_t *file ); 175 176 #endif -
protocols/jabber/conference.c
r560d0a0 rf1cea66 92 92 { 93 93 char *normalized = jabber_normalize( name ); 94 GSList *l; 94 95 struct groupchat *ret; 95 96 struct jabber_chat *jc; 96 97 97 for( ret = ic->groupchats; ret; ret = ret->next ) 98 { 98 for( l = ic->groupchats; l; l = l->next ) 99 { 100 ret = l->data; 99 101 jc = ret->data; 100 102 if( strcmp( normalized, jc->name ) == 0 ) … … 103 105 g_free( normalized ); 104 106 105 return ret;107 return l ? ret : NULL; 106 108 } 107 109 -
protocols/jabber/iq.c
r560d0a0 rf1cea66 382 382 while( ( c = xt_find_node( c, "item" ) ) ) 383 383 { 384 struct xt_node *group = xt_find_node( node->children, "group" );384 struct xt_node *group = xt_find_node( c->children, "group" ); 385 385 char *jid = xt_find_attr( c, "jid" ); 386 386 char *name = xt_find_attr( c, "name" ); … … 391 391 if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 392 392 { 393 if( initial || imcb_find_buddy( ic, jid ) == NULL ) 394 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 395 group->text : NULL ); 393 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 394 group->text : NULL ); 396 395 397 396 if( name ) … … 589 588 strcmp( s, "result" ) == 0 ) 590 589 { 591 if( imcb_find_buddy(ic, jid ) == NULL )590 if( bee_user_by_handle( ic->bee, ic, jid ) == NULL ) 592 591 imcb_add_buddy( ic, jid, NULL ); 593 592 } -
protocols/jabber/jabber.c
r560d0a0 rf1cea66 267 267 268 268 while( jd->filetransfers ) 269 imcb_file_canceled( ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );269 imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" ); 270 270 271 271 while( jd->streamhosts ) … … 282 282 283 283 while( ic->groupchats ) 284 jabber_chat_free( ic->groupchats );284 jabber_chat_free( ic->groupchats->data ); 285 285 286 286 if( jd->r_inpa >= 0 ) -
protocols/jabber/jabber_util.c
r560d0a0 rf1cea66 279 279 presence_send_request( bla->ic, bla->handle, "subscribed" ); 280 280 281 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 282 imcb_ask_add( bla->ic, bla->handle, NULL ); 281 imcb_ask_add( bla->ic, bla->handle, NULL ); 283 282 284 283 g_free( bla->handle ); … … 462 461 463 462 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && 464 ( bare_exists || imcb_find_buddy(ic, jid ) ) )463 ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) ) 465 464 { 466 465 *s = '/'; … … 483 482 if( bud == NULL ) 484 483 /* No match. Create it now? */ 485 return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? 484 return ( ( flags & GET_BUDDY_CREAT ) && 485 bee_user_by_handle( ic->bee, ic, jid_ ) ) ? 486 486 jabber_buddy_add( ic, jid_ ) : NULL; 487 487 else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) -
protocols/jabber/presence.c
r560d0a0 rf1cea66 205 205 struct jabber_data *jd = ic->proto_data; 206 206 struct xt_node *node, *cap; 207 struct groupchat *c;207 GSList *l; 208 208 int st; 209 209 … … 229 229 /* Have to send this update to all groupchats too, the server won't 230 230 do this automatically. */ 231 for( c = ic->groupchats; c && st; c = c->next ) 232 { 231 for( l = ic->groupchats; l && st; l = l->next ) 232 { 233 struct groupchat *c = l->data; 233 234 struct jabber_chat *jc = c->data; 234 235 -
protocols/jabber/s5bytestream.c
r560d0a0 rf1cea66 567 567 xt_free_node( reply ); 568 568 569 imcb_file_canceled( tf-> ft, "couldn't connect to any streamhosts" );569 imcb_file_canceled( tf->ic, tf->ft, "couldn't connect to any streamhosts" ); 570 570 571 571 bt->tf->watch_in = 0; … … 604 604 605 605 if( !jabber_write_packet( tf->ic, reply ) ) 606 imcb_file_canceled( tf-> ft, "Error transmitting bytestream response" );606 imcb_file_canceled( tf->ic, tf->ft, "Error transmitting bytestream response" ); 607 607 xt_free_node( reply ); 608 608 } … … 644 644 645 645 if( tf->bytesread >= tf->ft->file_size ) 646 imcb_file_finished( tf-> ft );646 imcb_file_finished( tf->ic, tf->ft ); 647 647 648 648 tf->ft->write( tf->ft, tf->ft->buffer, ret ); … … 660 660 if( tf->watch_in ) 661 661 { 662 imcb_file_canceled( ft, "BUG in jabber file transfer: write_request called when already watching for input" );662 imcb_file_canceled( tf->ic, ft, "BUG in jabber file transfer: write_request called when already watching for input" ); 663 663 return FALSE; 664 664 } … … 706 706 707 707 if( tf->byteswritten >= ft->file_size ) 708 imcb_file_finished( ft );708 imcb_file_finished( tf->ic, ft ); 709 709 else 710 710 bt->tf->watch_out = b_input_add( tf->fd, B_EV_IO_WRITE, jabber_bs_send_can_write, bt ); … … 1006 1006 1007 1007 if( !jabber_write_packet( tf->ic, iq ) ) 1008 imcb_file_canceled( tf-> ft, "Error transmitting bytestream request" );1008 imcb_file_canceled( tf->ic, tf->ft, "Error transmitting bytestream request" ); 1009 1009 return TRUE; 1010 1010 } … … 1021 1021 1022 1022 if( jd->streamhosts==NULL ) /* we're done here unless we have a proxy to try */ 1023 imcb_file_canceled( tf-> ft, error );1023 imcb_file_canceled( tf->ic, tf->ft, error ); 1024 1024 1025 1025 /* MUST always return FALSE! */ -
protocols/jabber/si.c
r560d0a0 rf1cea66 91 91 92 92 if( !foundft ) 93 imcb_file_canceled( tf-> ft, "Buddy's client doesn't feature file transfers" );93 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature file transfers" ); 94 94 else if( !foundbt ) 95 imcb_file_canceled( tf-> ft, "Buddy's client doesn't feature byte streams (required)" );95 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature byte streams (required)" ); 96 96 else if( !foundsi ) 97 imcb_file_canceled( tf-> ft, "Buddy's client doesn't feature stream initiation (required)" );97 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)" ); 98 98 99 99 return foundft && foundbt && foundsi; … … 109 109 110 110 /* and start the receive logic */ 111 imcb_file_recv_start( tf-> ft );111 imcb_file_recv_start( tf->ic, tf->ft ); 112 112 113 113 } … … 156 156 if( bud == NULL ) 157 157 { 158 imcb_file_canceled( ft, "Couldn't find buddy (BUG?)" );158 imcb_file_canceled( ic, ft, "Couldn't find buddy (BUG?)" ); 159 159 return; 160 160 } -
protocols/msn/Makefile
r560d0a0 rf1cea66 13 13 14 14 # [SH] Program variables 15 objects = invitation.omsn.o msn_util.o ns.o passport.o sb.o tables.o15 objects = msn.o msn_util.o ns.o passport.o sb.o tables.o 16 16 17 17 CFLAGS += -Wall -
protocols/msn/msn.c
r560d0a0 rf1cea66 79 79 if( md ) 80 80 { 81 /** Disabling MSN ft support for now. 81 82 while( md->filetransfers ) { 82 83 imcb_file_canceled( md->filetransfers->data, "Closing connection" ); 83 84 } 85 */ 84 86 85 87 if( md->fd >= 0 ) … … 221 223 { 222 224 struct msn_switchboard *sb; 225 struct groupchat *c = imcb_chat_new( ic, who ); 223 226 224 227 if( ( sb = msn_sb_by_handle( ic, who ) ) ) … … 238 241 msn_sb_write_msg( ic, m ); 239 242 240 return NULL; 241 } 242 243 return NULL; 243 return c; 244 } 244 245 } 245 246 … … 332 333 ret->send_typing = msn_send_typing; 333 334 ret->handle_cmp = g_strcasecmp; 334 ret->transfer_request = msn_ftp_transfer_request;335 //ret->transfer_request = msn_ftp_transfer_request; 335 336 336 337 register_protocol(ret); -
protocols/msn/msn_util.c
r560d0a0 rf1cea66 96 96 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); 97 97 98 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 99 imcb_ask_add( bla->ic, bla->handle, NULL ); 98 imcb_ask_add( bla->ic, bla->handle, NULL ); 100 99 101 100 g_free( bla->handle ); -
protocols/msn/sb.c
r560d0a0 rf1cea66 175 175 i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user ); 176 176 } 177 else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 ) 178 { 179 buf = g_strdup( SB_KEEPALIVE_HEADERS ); 180 i = strlen( buf ); 181 } 177 182 else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 ) 178 183 { 179 184 buf = g_strdup( text ); 180 i = strlen( buf );181 }182 else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )183 {184 buf = g_strdup( SB_KEEPALIVE_HEADERS );185 185 i = strlen( buf ); 186 186 } … … 233 233 { 234 234 struct im_connection *ic = sb->ic; 235 struct groupchat *c = NULL; 235 236 char buf[1024]; 236 237 237 238 /* Create the groupchat structure. */ 238 239 g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); 239 sb->chat = imcb_chat_new( ic, buf ); 240 if( sb->who ) 241 c = bee_chat_by_title( ic->bee, ic, sb->who ); 242 if( c && !msn_sb_by_chat( c ) ) 243 sb->chat = c; 244 else 245 sb->chat = imcb_chat_new( ic, buf ); 240 246 241 247 /* Populate the channel. */ … … 698 704 } 699 705 } 706 #if 0 707 // Disable MSN ft support for now. 700 708 else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 ) 701 709 { … … 730 738 g_free( command ); 731 739 } 740 #endif 732 741 else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) 733 742 { … … 765 774 void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ) 766 775 { 767 struct buddy *b;776 bee_user_t *bu; 768 777 769 778 if( sb && sb->who && sb->keepalive == 0 && 770 ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present && 779 ( bu = bee_user_by_handle( sb->ic->bee, sb->ic, sb->who ) ) && 780 !( bu->flags & BEE_USER_ONLINE ) && 771 781 set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) ) 772 782 { -
protocols/nogaim.c
r560d0a0 rf1cea66 38 38 #include "chat.h" 39 39 40 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );41 static char *format_timestamp( irc_t *irc, time_t msg_ts );42 43 40 GSList *connections; 44 41 … … 92 89 } 93 90 #endif 94 95 /* nogaim.c */96 91 97 92 GList *protocols = NULL; … … 129 124 } 130 125 131 /* nogaim.c */132 126 void nogaim_init() 133 127 { … … 158 152 twitter_initmodule(); 159 153 #endif 160 154 161 155 #ifdef WITH_PURPLE 162 156 purple_initmodule(); … … 170 164 GSList *get_connections() { return connections; } 171 165 172 /* multi.c */173 174 166 struct im_connection *imcb_new( account_t *acc ) 175 167 { … … 178 170 ic = g_new0( struct im_connection, 1 ); 179 171 180 ic-> irc = acc->irc;172 ic->bee = acc->bee; 181 173 ic->acc = acc; 182 174 acc->ic = ic; … … 192 184 193 185 /* Destroy the pointer to this connection from the account list */ 194 for( a = ic-> irc->accounts; a; a = a->next )186 for( a = ic->bee->accounts; a; a = a->next ) 195 187 if( a->ic == ic ) 196 188 { … … 213 205 va_end( params ); 214 206 215 if( ( g_strcasecmp( set_getstr( &ic-> irc->set, "strip_html" ), "always" ) == 0 ) ||216 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic-> irc->set, "strip_html" ) ) )207 if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || 208 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) 217 209 strip_html( text ); 218 210 219 211 /* Try to find a different connection on the same protocol. */ 220 for( a = ic-> irc->accounts; a; a = a->next )212 for( a = ic->bee->accounts; a; a = a->next ) 221 213 if( a->prpl == ic->acc->prpl && a->ic != ic ) 222 214 break; … … 224 216 /* If we found one, include the screenname in the message. */ 225 217 if( a ) 226 irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 218 /* FIXME(wilmer): ui_log callback or so */ 219 irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 227 220 else 228 irc_usermsg( ic-> irc, "%s - %s", ic->acc->prpl->name, text );221 irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text ); 229 222 230 223 g_free( text ); … … 277 270 void imcb_connected( struct im_connection *ic ) 278 271 { 279 irc_t *irc = ic->irc;280 struct chat *c;281 user_t *u;282 283 272 /* MSN servers sometimes redirect you to a different server and do 284 273 the whole login sequence again, so these "late" calls to this … … 287 276 return; 288 277 289 u = user_find( ic->irc, ic->irc->nick );290 291 278 imcb_log( ic, "Logged in" ); 292 279 … … 301 288 ic->acc->auto_reconnect_delay = 0; 302 289 290 /* 303 291 for( c = irc->chatrooms; c; c = c->next ) 304 292 { … … 309 297 chat_join( irc, c, NULL ); 310 298 } 299 */ 311 300 } 312 301 … … 316 305 317 306 a->reconnect = 0; 318 account_on( a-> irc, a );307 account_on( a->bee, a ); 319 308 320 309 return( FALSE ); /* Only have to run the timeout once */ … … 329 318 void imc_logout( struct im_connection *ic, int allow_reconnect ) 330 319 { 331 irc_t *irc = ic->irc; 332 user_t *t, *u; 320 bee_t *bee = ic->bee; 333 321 account_t *a; 322 GSList *l; 334 323 int delay; 335 324 … … 351 340 ic->away = NULL; 352 341 353 u = irc->users; 354 while( u ) 355 { 356 if( u->ic == ic ) 357 { 358 t = u->next; 359 user_del( irc, u->nick ); 360 u = t; 361 } 362 else 363 u = u->next; 364 } 365 366 query_del_by_conn( ic->irc, ic ); 367 368 for( a = irc->accounts; a; a = a->next ) 342 for( l = bee->users; l; ) 343 { 344 bee_user_t *bu = l->data; 345 GSList *next = l->next; 346 347 if( bu->ic == ic ) 348 bee_user_free( bee, bu ); 349 350 l = next; 351 } 352 353 query_del_by_conn( (irc_t*) ic->bee->ui_data, ic ); 354 355 for( a = bee->accounts; a; a = a->next ) 369 356 if( a->ic == ic ) 370 357 break; … … 374 361 /* Uhm... This is very sick. */ 375 362 } 376 else if( allow_reconnect && set_getbool( & irc->set, "auto_reconnect" ) &&363 else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) && 377 364 set_getbool( &a->set, "auto_reconnect" ) && 378 365 ( delay = account_reconnect_delay( a ) ) > 0 ) … … 385 372 } 386 373 387 388 /* dialogs.c */389 390 374 void imcb_ask( struct im_connection *ic, char *msg, void *data, 391 375 query_callback doit, query_callback dont ) 392 376 { 393 query_add( ic->irc, ic, msg, doit, dont, data ); 394 } 395 396 397 /* list.c */ 377 query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data ); 378 } 398 379 399 380 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) 400 381 { 401 user_t *u; 402 char nick[MAX_NICK_LENGTH+1], *s; 403 irc_t *irc = ic->irc; 404 405 if( user_findhandle( ic, handle ) ) 406 { 407 if( set_getbool( &irc->set, "debug" ) ) 408 imcb_log( ic, "User already exists, ignoring add request: %s", handle ); 382 bee_user_t *bu; 383 bee_t *bee = ic->bee; 384 385 if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) 386 bu = bee_user_new( bee, ic, handle, 0 ); 387 388 bu->group = bee_group_by_name( bee, group, TRUE ); 389 390 if( bee->ui->user_group ) 391 bee->ui->user_group( bee, bu ); 392 } 393 394 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname ) 395 { 396 bee_t *bee = ic->bee; 397 bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); 398 399 if( !bu || !fullname ) return; 400 401 if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 ) 402 { 403 g_free( bu->fullname ); 404 bu->fullname = g_strdup( fullname ); 409 405 410 return; 411 412 /* Buddy seems to exist already. Let's ignore this request then... 413 Eventually subsequent calls to this function *should* be possible 414 when a buddy is in multiple groups. But for now BitlBee doesn't 415 even support groups so let's silently ignore this for now. */ 416 } 417 418 memset( nick, 0, MAX_NICK_LENGTH + 1 ); 419 strcpy( nick, nick_get( ic->acc, handle ) ); 420 421 u = user_add( ic->irc, nick ); 422 423 // if( !realname || !*realname ) realname = nick; 424 // u->realname = g_strdup( realname ); 425 426 if( ( s = strchr( handle, '@' ) ) ) 427 { 428 u->host = g_strdup( s + 1 ); 429 u->user = g_strndup( handle, s - handle ); 430 } 431 else if( ic->acc->server ) 432 { 433 u->host = g_strdup( ic->acc->server ); 434 u->user = g_strdup( handle ); 435 436 /* s/ /_/ ... important for AOL screennames */ 437 for( s = u->user; *s; s ++ ) 438 if( *s == ' ' ) 439 *s = '_'; 440 } 441 else 442 { 443 u->host = g_strdup( ic->acc->prpl->name ); 444 u->user = g_strdup( handle ); 445 } 446 447 u->ic = ic; 448 u->handle = g_strdup( handle ); 449 if( group ) u->group = g_strdup( group ); 450 u->send_handler = buddy_send_handler; 451 u->last_typing_notice = 0; 452 } 453 454 struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ) 455 { 456 static struct buddy b[1]; 457 user_t *u; 458 459 u = user_findhandle( ic, handle ); 460 461 if( !u ) 462 return( NULL ); 463 464 memset( b, 0, sizeof( b ) ); 465 strncpy( b->name, handle, 80 ); 466 strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN ); 467 b->present = u->online; 468 b->ic = u->ic; 469 470 return( b ); 471 } 472 473 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ) 474 { 475 user_t *u = user_findhandle( ic, handle ); 476 char *set; 477 478 if( !u || !realname ) return; 479 480 if( g_strcasecmp( u->realname, realname ) != 0 ) 481 { 482 if( u->realname != u->nick ) g_free( u->realname ); 483 484 u->realname = g_strdup( realname ); 485 486 if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) 487 imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); 488 } 489 490 set = set_getstr( &ic->acc->set, "nick_source" ); 491 if( strcmp( set, "handle" ) != 0 ) 492 { 493 char *name = g_strdup( realname ); 494 495 if( strcmp( set, "first_name" ) == 0 ) 496 { 497 int i; 498 for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {} 499 name[i] = '\0'; 500 } 501 502 imcb_buddy_nick_hint( ic, handle, name ); 503 504 g_free( name ); 406 if( bee->ui->user_fullname ) 407 bee->ui->user_fullname( bee, bu ); 505 408 } 506 409 } … … 508 411 void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) 509 412 { 510 user_t *u; 511 512 if( ( u = user_findhandle( ic, handle ) ) ) 513 user_del( ic->irc, u->nick ); 413 bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) ); 514 414 } 515 415 … … 518 418 void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) 519 419 { 520 user_t *u = user_findhandle( ic, handle ); 521 char newnick[MAX_NICK_LENGTH+1], *orig_nick; 522 523 if( u && !u->online && !nick_saved( ic->acc, handle ) ) 524 { 525 /* Only do this if the person isn't online yet (which should 526 be the case if we just added it) and if the user hasn't 527 assigned a nickname to this buddy already. */ 528 529 strncpy( newnick, nick, MAX_NICK_LENGTH ); 530 newnick[MAX_NICK_LENGTH] = 0; 531 532 /* Some processing to make sure this string is a valid IRC nickname. */ 533 nick_strip( newnick ); 534 if( set_getbool( &ic->irc->set, "lcnicks" ) ) 535 nick_lc( newnick ); 536 537 if( strcmp( u->nick, newnick ) != 0 ) 538 { 539 /* Only do this if newnick is different from the current one. 540 If rejoining a channel, maybe we got this nick already 541 (and dedupe would only add an underscore. */ 542 nick_dedupe( ic->acc, handle, newnick ); 543 544 /* u->nick will be freed halfway the process, so it can't be 545 passed as an argument. */ 546 orig_nick = g_strdup( u->nick ); 547 user_rename( ic->irc, orig_nick, newnick ); 548 g_free( orig_nick ); 549 } 550 } 420 bee_t *bee = ic->bee; 421 bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); 422 423 if( !bu || !nick ) return; 424 425 if( bee->ui->user_nick_hint ) 426 bee->ui->user_nick_hint( bee, bu, nick ); 551 427 } 552 428 … … 593 469 data->ic = ic; 594 470 data->handle = g_strdup( handle ); 595 query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 471 query_add( (irc_t *) ic->bee->ui_data, ic, s, 472 imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 596 473 } 597 474 … … 618 495 619 496 /* TODO: Make a setting for this! */ 620 if( user_findhandle(ic, handle ) != NULL )497 if( bee_user_by_handle( ic->bee, ic, handle ) != NULL ) 621 498 return; 622 499 … … 625 502 data->ic = ic; 626 503 data->handle = g_strdup( handle ); 627 query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data ); 628 } 629 630 631 /* server.c */ 632 633 void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ) 634 { 635 user_t *u; 636 int oa, oo; 637 638 u = user_findhandle( ic, (char*) handle ); 639 640 if( !u ) 641 { 642 if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 ) 643 { 644 imcb_add_buddy( ic, (char*) handle, NULL ); 645 u = user_findhandle( ic, (char*) handle ); 646 } 647 else 648 { 649 if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) 650 { 651 imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle ); 652 imcb_log( ic, "flags = %d, state = %s, message = %s", flags, 653 state ? state : "NULL", message ? message : "NULL" ); 654 } 655 656 return; 657 } 658 } 659 660 oa = u->away != NULL; 661 oo = u->online; 662 663 g_free( u->away ); 664 g_free( u->status_msg ); 665 u->away = u->status_msg = NULL; 666 667 if( set_getbool( &ic->irc->set, "show_offline" ) && !u->online ) 668 { 669 /* always set users as online */ 670 irc_spawn( ic->irc, u ); 671 u->online = 1; 672 if( !( flags & OPT_LOGGED_IN ) ) 673 { 674 /* set away message if user isn't really online */ 675 u->away = g_strdup( "User is offline" ); 676 } 677 } 678 else if( ( flags & OPT_LOGGED_IN ) && !u->online ) 679 { 680 irc_spawn( ic->irc, u ); 681 u->online = 1; 682 } 683 else if( !( flags & OPT_LOGGED_IN ) && u->online ) 684 { 685 struct groupchat *c; 686 687 if( set_getbool( &ic->irc->set, "show_offline" ) ) 688 { 689 /* keep offline users in channel and set away message to "offline" */ 690 u->away = g_strdup( "User is offline" ); 691 692 /* Keep showing him/her in the control channel but not in groupchats. */ 693 for( c = ic->groupchats; c; c = c->next ) 694 { 695 if( remove_chat_buddy_silent( c, handle ) && c->joined ) 696 irc_part( c->ic->irc, u, c->channel ); 697 } 698 } 699 else 700 { 701 /* kill offline users */ 702 irc_kill( ic->irc, u ); 703 u->online = 0; 704 705 /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */ 706 for( c = ic->groupchats; c; c = c->next ) 707 remove_chat_buddy_silent( c, handle ); 708 } 709 } 710 711 if( flags & OPT_AWAY ) 712 { 713 if( state && message ) 714 { 715 u->away = g_strdup_printf( "%s (%s)", state, message ); 716 } 717 else if( state ) 718 { 719 u->away = g_strdup( state ); 720 } 721 else if( message ) 722 { 723 u->away = g_strdup( message ); 724 } 725 else 726 { 727 u->away = g_strdup( "Away" ); 728 } 729 } 730 else 731 { 732 u->status_msg = g_strdup( message ); 733 } 734 735 /* early if-clause for show_offline even if there is some redundant code here because this isn't LISP but C ;) */ 736 if( set_getbool( &ic->irc->set, "show_offline" ) && set_getbool( &ic->irc->set, "away_devoice" ) ) 737 { 738 char *from; 739 740 if( set_getbool( &ic->irc->set, "simulate_netsplit" ) ) 741 { 742 from = g_strdup( ic->irc->myhost ); 743 } 744 else 745 { 746 from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick, 747 ic->irc->myhost ); 748 } 749 750 /* if we use show_offline, we op online users, voice away users, and devoice/deop offline users */ 751 if( flags & OPT_LOGGED_IN ) 752 { 753 /* user is "online" (either really online or away) */ 754 irc_write( ic->irc, ":%s MODE %s %cv%co %s %s", from, ic->irc->channel, 755 u->away?'+':'-', u->away?'-':'+', u->nick, u->nick ); 756 } 757 else 758 { 759 /* user is offline */ 760 irc_write( ic->irc, ":%s MODE %s -vo %s %s", from, ic->irc->channel, u->nick, u->nick ); 761 } 762 } 763 else 764 { 765 /* LISPy... */ 766 if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ 767 ( u->online ) && /* Don't touch offline people */ 768 ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ 769 ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ 770 { 771 char *from; 772 773 if( set_getbool( &ic->irc->set, "simulate_netsplit" ) ) 774 { 775 from = g_strdup( ic->irc->myhost ); 776 } 777 else 778 { 779 from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick, 780 ic->irc->myhost ); 781 } 782 irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, 783 u->away?'-':'+', u->nick ); 784 g_free( from ); 785 } 786 } 787 } 788 789 void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at ) 790 { 791 irc_t *irc = ic->irc; 792 char *wrapped, *ts = NULL; 793 user_t *u; 794 795 u = user_findhandle( ic, handle ); 796 797 if( !u ) 798 { 799 char *h = set_getstr( &irc->set, "handle_unknown" ); 800 801 if( g_strcasecmp( h, "ignore" ) == 0 ) 802 { 803 if( set_getbool( &irc->set, "debug" ) ) 804 imcb_log( ic, "Ignoring message from unknown handle %s", handle ); 805 806 return; 807 } 808 else if( g_strncasecmp( h, "add", 3 ) == 0 ) 809 { 810 int private = set_getbool( &irc->set, "private" ); 811 812 if( h[3] ) 813 { 814 if( g_strcasecmp( h + 3, "_private" ) == 0 ) 815 private = 1; 816 else if( g_strcasecmp( h + 3, "_channel" ) == 0 ) 817 private = 0; 818 } 819 820 imcb_add_buddy( ic, handle, NULL ); 821 u = user_findhandle( ic, handle ); 822 u->is_private = private; 823 } 824 else 825 { 826 imcb_log( ic, "Message from unknown handle %s:", handle ); 827 u = user_find( irc, irc->mynick ); 828 } 829 } 830 831 if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || 832 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) 833 strip_html( msg ); 834 835 if( set_getbool( &ic->irc->set, "display_timestamps" ) && 836 ( ts = format_timestamp( irc, sent_at ) ) ) 837 { 838 char *new = g_strconcat( ts, msg, NULL ); 839 g_free( ts ); 840 ts = msg = new; 841 } 842 843 wrapped = word_wrap( msg, 425 ); 844 irc_msgfrom( irc, u->nick, wrapped ); 845 g_free( wrapped ); 846 g_free( ts ); 847 } 848 849 void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ) 850 { 851 user_t *u; 852 853 if( !set_getbool( &ic->irc->set, "typing_notice" ) ) 854 return; 855 856 if( ( u = user_findhandle( ic, handle ) ) ) 857 { 858 char buf[256]; 859 860 g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 ); 861 irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf ); 862 } 863 } 864 865 struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ) 866 { 867 struct groupchat *c; 868 869 /* This one just creates the conversation structure, user won't see anything yet */ 870 871 if( ic->groupchats ) 872 { 873 for( c = ic->groupchats; c->next; c = c->next ); 874 c = c->next = g_new0( struct groupchat, 1 ); 875 } 876 else 877 ic->groupchats = c = g_new0( struct groupchat, 1 ); 878 879 c->ic = ic; 880 c->title = g_strdup( handle ); 881 c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); 882 c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); 883 884 if( set_getbool( &ic->irc->set, "debug" ) ) 885 imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); 886 887 return c; 888 } 889 890 void imcb_chat_name_hint( struct groupchat *c, const char *name ) 891 { 892 if( !c->joined ) 893 { 894 struct im_connection *ic = c->ic; 895 char stripped[MAX_NICK_LENGTH+1], *full_name; 896 897 strncpy( stripped, name, MAX_NICK_LENGTH ); 898 stripped[MAX_NICK_LENGTH] = '\0'; 899 nick_strip( stripped ); 900 if( set_getbool( &ic->irc->set, "lcnicks" ) ) 901 nick_lc( stripped ); 902 903 full_name = g_strdup_printf( "&%s", stripped ); 904 905 if( stripped[0] && 906 nick_cmp( stripped, ic->irc->channel + 1 ) != 0 && 907 irc_chat_by_channel( ic->irc, full_name ) == NULL ) 908 { 909 g_free( c->channel ); 910 c->channel = full_name; 911 } 912 else 913 { 914 g_free( full_name ); 915 } 916 } 917 } 918 919 void imcb_chat_free( struct groupchat *c ) 920 { 921 struct im_connection *ic = c->ic; 922 struct groupchat *l; 923 GList *ir; 924 925 if( set_getbool( &ic->irc->set, "debug" ) ) 926 imcb_log( ic, "You were removed from conversation %p", c ); 927 928 if( c ) 929 { 930 if( c->joined ) 931 { 932 user_t *u, *r; 933 934 r = user_find( ic->irc, ic->irc->mynick ); 935 irc_privmsg( ic->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" ); 936 937 u = user_find( ic->irc, ic->irc->nick ); 938 irc_kick( ic->irc, u, c->channel, r ); 939 /* irc_part( ic->irc, u, c->channel ); */ 940 } 941 942 /* Find the previous chat in the linked list. */ 943 for( l = ic->groupchats; l && l->next != c; l = l->next ); 944 945 if( l ) 946 l->next = c->next; 947 else 948 ic->groupchats = c->next; 949 950 for( ir = c->in_room; ir; ir = ir->next ) 951 g_free( ir->data ); 952 g_list_free( c->in_room ); 953 g_free( c->channel ); 954 g_free( c->title ); 955 g_free( c->topic ); 956 g_free( c ); 957 } 958 } 959 960 void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at ) 961 { 962 struct im_connection *ic = c->ic; 963 char *wrapped; 964 user_t *u; 965 966 /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ 967 if( g_strcasecmp( who, ic->acc->user ) == 0 ) 968 return; 969 970 u = user_findhandle( ic, who ); 971 972 if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || 973 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) 974 strip_html( msg ); 975 976 wrapped = word_wrap( msg, 425 ); 977 if( c && u ) 978 { 979 char *ts = NULL; 980 if( set_getbool( &ic->irc->set, "display_timestamps" ) ) 981 ts = format_timestamp( ic->irc, sent_at ); 982 irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped ); 983 g_free( ts ); 984 } 985 else 986 { 987 imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped ); 988 } 989 g_free( wrapped ); 990 } 991 992 void imcb_chat_log( struct groupchat *c, char *format, ... ) 993 { 994 irc_t *irc = c->ic->irc; 995 va_list params; 996 char *text; 997 user_t *u; 998 999 va_start( params, format ); 1000 text = g_strdup_vprintf( format, params ); 1001 va_end( params ); 1002 1003 u = user_find( irc, irc->mynick ); 1004 1005 irc_privmsg( irc, u, "PRIVMSG", c->channel, "System message: ", text ); 1006 1007 g_free( text ); 1008 } 1009 1010 void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) 1011 { 1012 struct im_connection *ic = c->ic; 1013 user_t *u = NULL; 1014 1015 if( who == NULL) 1016 u = user_find( ic->irc, ic->irc->mynick ); 1017 else if( g_strcasecmp( who, ic->acc->user ) == 0 ) 1018 u = user_find( ic->irc, ic->irc->nick ); 1019 else 1020 u = user_findhandle( ic, who ); 1021 1022 if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || 1023 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) 1024 strip_html( topic ); 1025 1026 g_free( c->topic ); 1027 c->topic = g_strdup( topic ); 1028 1029 if( c->joined && u ) 1030 irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); 1031 } 1032 1033 1034 /* buddy_chat.c */ 1035 1036 void imcb_chat_add_buddy( struct groupchat *b, const char *handle ) 1037 { 1038 user_t *u = user_findhandle( b->ic, handle ); 1039 int me = 0; 1040 1041 if( set_getbool( &b->ic->irc->set, "debug" ) ) 1042 imcb_log( b->ic, "User %s added to conversation %p", handle, b ); 1043 1044 /* It might be yourself! */ 1045 if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 ) 1046 { 1047 u = user_find( b->ic->irc, b->ic->irc->nick ); 1048 if( !b->joined ) 1049 irc_join( b->ic->irc, u, b->channel ); 1050 b->joined = me = 1; 1051 } 1052 1053 /* Most protocols allow people to join, even when they're not in 1054 your contact list. Try to handle that here */ 1055 if( !u ) 1056 { 1057 imcb_add_buddy( b->ic, handle, NULL ); 1058 u = user_findhandle( b->ic, handle ); 1059 } 1060 1061 /* Add the handle to the room userlist, if it's not 'me' */ 1062 if( !me ) 1063 { 1064 if( b->joined ) 1065 irc_join( b->ic->irc, u, b->channel ); 1066 b->in_room = g_list_append( b->in_room, g_strdup( handle ) ); 1067 } 1068 } 1069 1070 /* This function is one BIG hack... :-( EREWRITE */ 1071 void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason ) 1072 { 1073 user_t *u; 1074 int me = 0; 1075 1076 if( set_getbool( &b->ic->irc->set, "debug" ) ) 1077 imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" ); 1078 1079 /* It might be yourself! */ 1080 if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) 1081 { 1082 if( b->joined == 0 ) 1083 return; 1084 1085 u = user_find( b->ic->irc, b->ic->irc->nick ); 1086 b->joined = 0; 1087 me = 1; 1088 } 1089 else 1090 { 1091 u = user_findhandle( b->ic, handle ); 1092 } 1093 1094 if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) ) 1095 irc_part( b->ic->irc, u, b->channel ); 1096 } 1097 1098 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ) 1099 { 1100 GList *i; 1101 1102 /* Find the handle in the room userlist and shoot it */ 1103 i = b->in_room; 1104 while( i ) 1105 { 1106 if( g_strcasecmp( handle, i->data ) == 0 ) 1107 { 1108 g_free( i->data ); 1109 b->in_room = g_list_remove( b->in_room, i->data ); 1110 return( 1 ); 1111 } 1112 1113 i = i->next; 1114 } 1115 1116 return( 0 ); 1117 } 1118 1119 1120 /* Misc. BitlBee stuff which shouldn't really be here */ 1121 1122 char *set_eval_away_devoice( set_t *set, char *value ) 1123 { 1124 irc_t *irc = set->data; 1125 int st; 1126 1127 if( !is_bool( value ) ) 1128 return SET_INVALID; 1129 1130 st = bool2int( value ); 1131 1132 /* Horror.... */ 1133 1134 if( st != set_getbool( &irc->set, "away_devoice" ) ) 1135 { 1136 char list[80] = ""; 1137 user_t *u = irc->users; 1138 int i = 0, count = 0; 1139 char pm; 1140 char v[80]; 1141 1142 if( st ) 1143 pm = '+'; 1144 else 1145 pm = '-'; 1146 1147 while( u ) 1148 { 1149 if( u->ic && u->online && !u->away ) 1150 { 1151 if( ( strlen( list ) + strlen( u->nick ) ) >= 79 ) 1152 { 1153 for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0; 1154 irc_write( irc, ":%s MODE %s %c%s%s", 1155 irc->myhost, 1156 irc->channel, pm, v, list ); 1157 1158 *list = 0; 1159 count = 0; 1160 } 1161 1162 sprintf( list + strlen( list ), " %s", u->nick ); 1163 count ++; 1164 } 1165 u = u->next; 1166 } 1167 1168 /* $v = 'v' x $i */ 1169 for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0; 1170 irc_write( irc, ":%s MODE %s %c%s%s", irc->myhost, 1171 irc->channel, pm, v, list ); 1172 } 1173 1174 return value; 1175 } 1176 1177 char *set_eval_timezone( set_t *set, char *value ) 1178 { 1179 char *s; 1180 1181 if( strcmp( value, "local" ) == 0 || 1182 strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 ) 1183 return value; 1184 1185 /* Otherwise: +/- at the beginning optional, then one or more numbers, 1186 possibly followed by a colon and more numbers. Don't bother bound- 1187 checking them since users are free to shoot themselves in the foot. */ 1188 s = value; 1189 if( *s == '+' || *s == '-' ) 1190 s ++; 1191 1192 /* \d+ */ 1193 if( !isdigit( *s ) ) 1194 return SET_INVALID; 1195 while( *s && isdigit( *s ) ) s ++; 1196 1197 /* EOS? */ 1198 if( *s == '\0' ) 1199 return value; 1200 1201 /* Otherwise, colon */ 1202 if( *s != ':' ) 1203 return SET_INVALID; 1204 s ++; 1205 1206 /* \d+ */ 1207 if( !isdigit( *s ) ) 1208 return SET_INVALID; 1209 while( *s && isdigit( *s ) ) s ++; 1210 1211 /* EOS */ 1212 return *s == '\0' ? value : SET_INVALID; 1213 } 1214 1215 static char *format_timestamp( irc_t *irc, time_t msg_ts ) 1216 { 1217 time_t now_ts = time( NULL ); 1218 struct tm now, msg; 1219 char *set; 1220 1221 /* If the timestamp is <= 0 or less than a minute ago, discard it as 1222 it doesn't seem to add to much useful info and/or might be noise. */ 1223 if( msg_ts <= 0 || msg_ts > now_ts - 60 ) 1224 return NULL; 1225 1226 set = set_getstr( &irc->set, "timezone" ); 1227 if( strcmp( set, "local" ) == 0 ) 1228 { 1229 localtime_r( &now_ts, &now ); 1230 localtime_r( &msg_ts, &msg ); 1231 } 1232 else 1233 { 1234 int hr, min = 0, sign = 60; 1235 1236 if( set[0] == '-' ) 1237 { 1238 sign *= -1; 1239 set ++; 1240 } 1241 else if( set[0] == '+' ) 1242 { 1243 set ++; 1244 } 1245 1246 if( sscanf( set, "%d:%d", &hr, &min ) >= 1 ) 1247 { 1248 msg_ts += sign * ( hr * 60 + min ); 1249 now_ts += sign * ( hr * 60 + min ); 1250 } 1251 1252 gmtime_r( &now_ts, &now ); 1253 gmtime_r( &msg_ts, &msg ); 1254 } 1255 1256 if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday ) 1257 return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ", 1258 msg.tm_hour, msg.tm_min, msg.tm_sec ); 1259 else 1260 return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d " 1261 "%02d:%02d:%02d\x02]\x02 ", 1262 msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday, 1263 msg.tm_hour, msg.tm_min, msg.tm_sec ); 504 query_add( (irc_t *) ic->bee->ui_data, ic, s, 505 imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data ); 506 } 507 508 struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ) 509 { 510 return bee_user_by_handle( ic->bee, ic, handle ); 1264 511 } 1265 512 1266 513 /* The plan is to not allow straight calls to prpl functions anymore, but do 1267 514 them all from some wrappers. We'll start to define some down here: */ 1268 1269 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags )1270 {1271 char *buf = NULL;1272 int st;1273 1274 if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )1275 {1276 buf = escape_html( msg );1277 msg = buf;1278 }1279 1280 st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );1281 g_free( buf );1282 1283 return st;1284 }1285 515 1286 516 int imc_chat_msg( struct groupchat *c, char *msg, int flags ) … … 1311 541 1312 542 away = set_getstr( &ic->acc->set, "away" ) ? 1313 : set_getstr( &ic-> irc->set, "away" );543 : set_getstr( &ic->bee->set, "away" ); 1314 544 if( away && *away ) 1315 545 { … … 1322 552 away = NULL; 1323 553 msg = set_getstr( &ic->acc->set, "status" ) ? 1324 : set_getstr( &ic-> irc->set, "status" );554 : set_getstr( &ic->bee->set, "status" ); 1325 555 } 1326 556 -
protocols/nogaim.h
r560d0a0 rf1cea66 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 04Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 87 87 88 88 /* BitlBee */ 89 irc_t *irc;90 91 struct groupchat *groupchats;89 bee_t *bee; 90 91 GSList *groupchats; 92 92 }; 93 93 … … 100 100 * already, for example to avoid adding somebody two times. */ 101 101 GList *in_room; 102 GList *ignored; 103 104 struct groupchat *next; 105 char *channel; 102 //GList *ignored; 103 104 //struct groupchat *next; 106 105 /* The title variable contains the ID you gave when you created the 107 106 * chat using imcb_chat_new(). */ … … 114 113 * structure for your protocol's needs. */ 115 114 void *data; 115 void *ui_data; 116 116 }; 117 117 … … 287 287 G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ); 288 288 289 /* Buddy activity */290 /* To manipulate the status of a handle.291 * - flags can be |='d with OPT_* constants. You will need at least:292 * OPT_LOGGED_IN and OPT_AWAY.293 * - 'state' and 'message' can be NULL */294 G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );295 /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );296 /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */297 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );298 289 G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ); 290 G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ); 299 291 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); 300 292 … … 322 314 /* Actions, or whatever. */ 323 315 int imc_away_send_update( struct im_connection *ic ); 324 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );325 316 int imc_chat_msg( struct groupchat *c, char *msg, int flags ); 326 317 -
protocols/oscar/oscar.c
r560d0a0 rf1cea66 254 254 255 255 u = t = g_strdup(s); 256 257 strcpy(t, s);258 256 g_strdown(t); 259 257 … … 652 650 struct im_connection *ic = sess->aux_data; 653 651 struct chat_connection *chatcon; 652 struct groupchat *c = NULL; 654 653 static int id = 1; 655 654 … … 664 663 chatcon = find_oscar_chat_by_conn(ic, fr->conn); 665 664 chatcon->id = id; 666 chatcon->cnv = imcb_chat_new(ic, chatcon->show); 665 666 c = bee_chat_by_title(ic->bee, ic, chatcon->show); 667 if (c && !c->data) 668 chatcon->cnv = c; 669 else 670 chatcon->cnv = imcb_chat_new(ic, chatcon->show); 667 671 chatcon->cnv->data = chatcon; 668 672 … … 934 938 tmp = normalize(info->sn); 935 939 imcb_buddy_status(ic, tmp, flags, state_string, NULL); 936 /* imcb_buddy_times(ic, tmp, signon, time_idle); */940 imcb_buddy_times(ic, tmp, signon, time_idle); 937 941 938 942 … … 1060 1064 aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); 1061 1065 // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); 1062 if(imcb_find_buddy(data->ic, uin) == NULL) 1063 imcb_ask_add(data->ic, uin, NULL); 1066 imcb_ask_add(data->ic, uin, NULL); 1064 1067 1065 1068 g_free(uin); … … 1822 1825 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 1823 1826 if (odata->icq) { 1827 /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back? 1824 1828 struct buddy *budlight = imcb_find_buddy(g, who); 1825 1829 if (budlight) … … 1827 1831 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) 1828 1832 aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7); 1833 */ 1829 1834 } else 1830 1835 aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); … … 1953 1958 static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { 1954 1959 struct im_connection *ic = sess->aux_data; 1955 struct aim_ssi_item *curitem ;1960 struct aim_ssi_item *curitem, *curgroup; 1956 1961 int tmp; 1957 1962 char *nrm; … … 1964 1969 switch (curitem->type) { 1965 1970 case 0x0000: /* Buddy */ 1966 if ((curitem->name) && (!imcb_ find_buddy(ic, nrm))) {1971 if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) { 1967 1972 char *realname = NULL; 1968 1973 1969 1974 if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) 1970 1975 realname = aim_gettlv_str(curitem->data, 0x0131, 1); 1971 1972 imcb_add_buddy(ic, nrm, NULL);1976 1977 imcb_add_buddy(ic, nrm, curgroup->gid == curitem->gid ? curgroup->name : NULL); 1973 1978 1974 1979 if (realname) { … … 1978 1983 } 1979 1984 } 1985 break; 1986 1987 case 0x0001: /* Group */ 1988 curgroup = curitem; 1980 1989 break; 1981 1990 … … 2520 2529 static int chat_id = 0; 2521 2530 char * chatname; 2531 struct groupchat *c; 2522 2532 2523 2533 chatname = g_strdup_printf("%s%s_%d", isdigit(*ic->acc->user) ? "icq_" : "", 2524 2534 ic->acc->user, chat_id++); 2525 2535 2536 c = imcb_chat_new(ic, chatname); 2526 2537 ret = oscar_chat_join(ic, chatname, NULL, NULL); 2527 2528 2538 aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0); 2529 2539 -
protocols/purple/ft.c
r560d0a0 rf1cea66 75 75 px->fn = mktemp( g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ) ); 76 76 px->fd = -1; 77 px->ic = purple_ic_by_pa( xfer->account ); 77 78 78 79 purple_xfer_set_local_filename( xfer, px->fn ); … … 143 144 { 144 145 purple_xfer_cancel_local( px->xfer ); 145 imcb_file_canceled( ft, "Read error" );146 imcb_file_canceled( px->ic, ft, "Read error" ); 146 147 } 147 148 } … … 150 151 { 151 152 /*purple_xfer_end( px->xfer );*/ 152 imcb_file_finished( ft );153 imcb_file_finished( px->ic, ft ); 153 154 } 154 155 … … 230 231 231 232 if( px->ft ) 232 imcb_file_canceled( px-> ft, "Canceled by remote end" );233 imcb_file_canceled( px->ic, px->ft, "Canceled by remote end" ); 233 234 else 234 235 /* px->ft == NULL for sends, because of the two stages. :-/ */ … … 301 302 { 302 303 file_transfer_t *ft = data; 304 struct prpl_xfer_data *px = ft->data; 303 305 304 306 if( ft->write == NULL ) 305 307 { 306 308 ft->write = prpl_xfer_write; 307 imcb_file_recv_start( ft );309 imcb_file_recv_start( px->ic, ft ); 308 310 } 309 311 … … 319 321 if( write( px->fd, buffer, len ) != len ) 320 322 { 321 imcb_file_canceled( ft, "Error while writing temporary file" );323 imcb_file_canceled( px->ic, ft, "Error while writing temporary file" ); 322 324 return FALSE; 323 325 } … … 329 331 330 332 purple_transfer_forward( ft ); 331 imcb_file_finished( ft );333 imcb_file_finished( px->ic, ft ); 332 334 px->ft = NULL; 333 335 } -
protocols/purple/purple.c
r560d0a0 rf1cea66 35 35 any context so this is the only way to get that. Don't want to support 36 36 libpurple in daemon mode anyway. */ 37 static irc_t *local_irc;37 static bee_t *local_bee; 38 38 39 39 static char *set_eval_display_name( set_t *set, char *value ); … … 157 157 158 158 default: 159 /** No way to talk to the user right now, invent one when 160 this becomes important. 159 161 irc_usermsg( acc->irc, "Setting with unknown type: %s (%d) Expect stuff to break..\n", 160 162 name, purple_account_option_get_type( o ) ); 163 */ 161 164 name = NULL; 162 165 } … … 251 254 PurpleAccount *pa; 252 255 253 if( local_irc != NULL && local_irc != acc->irc ) 254 { 255 irc_usermsg( acc->irc, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " 256 "Please use inetd or ForkDaemon mode instead." ); 256 if( local_bee != NULL && local_bee != acc->bee ) 257 { 258 imcb_error( ic, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " 259 "Please use inetd or ForkDaemon mode instead." ); 260 imc_logout( ic, FALSE ); 257 261 return; 258 262 } 259 local_ irc = acc->irc;263 local_bee = acc->bee; 260 264 261 265 /* For now this is needed in the _connected() handlers if using … … 683 687 imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ), 684 688 purple_status_get_attr_string( as, "message" ) ); 689 690 imcb_buddy_times( ic, bud->name, 691 purple_presence_get_login_time( bud->presence ), 692 purple_presence_get_idle_time( bud->presence ) ); 685 693 } 686 694 } … … 866 874 pqad->user_data = user_data; 867 875 876 /* TODO: IRC stuff here :-( */ 868 877 q = g_strdup_printf( "Request: %s\n\n%s\n\n%s", title, primary, secondary ); 869 pqad->bee_data = query_add( local_ irc, purple_ic_by_pa( account ), q,878 pqad->bee_data = query_add( local_bee->ui_data, purple_ic_by_pa( account ), q, 870 879 prplcb_request_action_yes, prplcb_request_action_no, pqad ); 871 880 -
protocols/twitter/twitter_lib.c
r560d0a0 rf1cea66 103 103 104 104 // Check if the buddy is allready in the buddy list. 105 if (! imcb_find_buddy(ic, name ))105 if (!bee_user_by_handle( ic->bee, ic, name )) 106 106 { 107 107 char *mode = set_getstr(&ic->acc->set, "mode"); -
protocols/yahoo/yahoo.c
r560d0a0 rf1cea66 158 158 159 159 while( ic->groupchats ) 160 imcb_chat_free( ic->groupchats );160 imcb_chat_free( ic->groupchats->data ); 161 161 162 162 for( l = yd->buddygroups; l; l = l->next ) … … 613 613 imcb_buddy_status( ic, who, flags, state_string, msg ); 614 614 615 /* Not implemented yet...616 615 if( stat == YAHOO_STATUS_IDLE ) 617 imcb_buddy_times( ic, who, 0, away ); 618 */ 616 imcb_buddy_times( ic, who, 0, idle ); 619 617 } 620 618 … … 796 794 struct byahoo_conf_invitation *inv = data; 797 795 struct groupchat *b; 798 799 for( b = inv->ic->groupchats; b; b = b->next ) 796 GSList *l; 797 798 for( l = inv->ic->groupchats; l; l = l->next ) 799 { 800 b = l->data; 800 801 if( b == inv->c ) 801 802 break; 803 } 802 804 803 805 if( b != NULL ) … … 865 867 { 866 868 struct im_connection *ic = byahoo_get_ic_by_id( id ); 867 struct groupchat *c; 868 869 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 869 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 870 870 871 871 if( c ) … … 877 877 { 878 878 struct im_connection *ic = byahoo_get_ic_by_id( id ); 879 struct groupchat *c; 880 881 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 879 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 882 880 883 881 if( c ) … … 889 887 struct im_connection *ic = byahoo_get_ic_by_id( id ); 890 888 char *m = byahoo_strip( msg ); 891 struct groupchat *c; 892 893 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 889 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 894 890 895 891 if( c ) -
query.c
r560d0a0 rf1cea66 64 64 } 65 65 66 if( g_strcasecmp( set_getstr( &irc-> set, "query_order" ), "lifo" ) == 0 || irc->queries == q )66 if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q ) 67 67 query_display( irc, q ); 68 68 … … 179 179 query_t *q; 180 180 181 if( g_strcasecmp( set_getstr( &irc-> set, "query_order" ), "fifo" ) == 0 )181 if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "fifo" ) == 0 ) 182 182 q = irc->queries; 183 183 else -
root_commands.c
r560d0a0 rf1cea66 32 32 #include <string.h> 33 33 34 void root_command_string( irc_t *irc, user_t *u, char *command, int flags ) 35 { 36 char *cmd[IRC_MAX_ARGS]; 37 char *s; 38 int k; 39 char q = 0; 40 41 memset( cmd, 0, sizeof( cmd ) ); 42 cmd[0] = command; 43 k = 1; 44 for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ ) 45 if( *s == ' ' && !q ) 46 { 47 *s = 0; 48 while( *++s == ' ' ); 49 if( *s == '"' || *s == '\'' ) 50 { 51 q = *s; 52 s ++; 53 } 54 if( *s ) 55 { 56 cmd[k++] = s; 57 s --; 58 } 59 else 60 { 61 break; 62 } 63 } 64 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) 65 { 66 char *cpy; 67 68 for( cpy = s; *cpy; cpy ++ ) 69 cpy[0] = cpy[1]; 70 } 71 else if( *s == q ) 72 { 73 q = *s = 0; 74 } 75 cmd[k] = NULL; 76 77 root_command( irc, cmd ); 34 void root_command_string( irc_t *irc, char *command ) 35 { 36 root_command( irc, split_command_parts( command ) ); 78 37 } 79 38 … … 92 51 void root_command( irc_t *irc, char *cmd[] ) 93 52 { 94 int i ;53 int i, len; 95 54 96 55 if( !cmd[0] ) 97 56 return; 98 57 58 len = strlen( cmd[0] ); 99 59 for( i = 0; commands[i].command; i++ ) 100 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) 101 { 60 if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 ) 61 { 62 if( commands[i+1].command && 63 g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 ) 64 /* Only match on the first letters if the match is unique. */ 65 break; 66 102 67 MIN_ARGS( commands[i].required_parameters ); 103 68 … … 140 105 static void cmd_identify( irc_t *irc, char **cmd ) 141 106 { 142 storage_status_t status = storage_load( irc, cmd[1] );107 storage_status_t status; 143 108 char *account_on[] = { "account", "on", NULL }; 144 145 if( strchr( irc->umode, 'R' ) != NULL ) 109 gboolean load = TRUE; 110 char *password = cmd[1]; 111 112 if( irc->status & USTATUS_IDENTIFIED ) 146 113 { 147 114 irc_usermsg( irc, "You're already logged in." ); 148 115 return; 149 116 } 117 118 if( strncmp( cmd[1], "-no", 3 ) == 0 ) 119 { 120 load = FALSE; 121 password = cmd[2]; 122 } 123 else if( strncmp( cmd[1], "-force", 6 ) == 0 ) 124 { 125 password = cmd[2]; 126 } 127 else if( irc->b->accounts != NULL ) 128 { 129 irc_usermsg( irc, 130 "You're trying to identify yourself, but already have " 131 "at least one IM account set up. " 132 "Use \x02identify -noload\x02 or \x02identify -force\x02 " 133 "instead (see \x02help identify\x02)." ); 134 return; 135 } 136 137 if( password == NULL ) 138 { 139 MIN_ARGS( 2 ); 140 } 141 142 if( load ) 143 status = storage_load( irc, password ); 144 else 145 status = storage_check_pass( irc->user->nick, password ); 150 146 151 147 switch (status) { … … 157 153 break; 158 154 case STORAGE_OK: 159 irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); 160 irc_setpass( irc, cmd[1] ); 155 irc_usermsg( irc, "Password accepted%s", 156 load ? ", settings and accounts loaded" : "" ); 157 irc_setpass( irc, password ); 161 158 irc->status |= USTATUS_IDENTIFIED; 162 159 irc_umode_set( irc, "+R", 1 ); 163 if( set_getbool( &irc->set, "auto_connect" ) )160 if( load && set_getbool( &irc->b->set, "auto_connect" ) ) 164 161 cmd_account( irc, account_on ); 165 162 break; … … 201 198 storage_status_t status; 202 199 203 status = storage_remove (irc-> nick, cmd[1]);200 status = storage_remove (irc->user->nick, cmd[1]); 204 201 switch (status) { 205 202 case STORAGE_NO_SUCH_USER: … … 213 210 irc->status &= ~USTATUS_IDENTIFIED; 214 211 irc_umode_set( irc, "-R", 1 ); 215 irc_usermsg( irc, "Account `%s' removed", irc-> nick );212 irc_usermsg( irc, "Account `%s' removed", irc->user->nick ); 216 213 break; 217 214 default: … … 221 218 } 222 219 223 struct cmd_account_del_data 224 { 225 account_t *a; 226 irc_t *irc; 227 }; 228 229 void cmd_account_del_yes( void *data ) 230 { 231 struct cmd_account_del_data *cad = data; 232 account_t *a; 233 234 for( a = cad->irc->accounts; a && a != cad->a; a = a->next ); 235 236 if( a == NULL ) 237 { 238 irc_usermsg( cad->irc, "Account already deleted" ); 239 } 240 else if( a->ic ) 241 { 242 irc_usermsg( cad->irc, "Account is still logged in, can't delete" ); 243 } 244 else 245 { 246 account_del( cad->irc, a ); 247 irc_usermsg( cad->irc, "Account deleted" ); 248 } 249 g_free( data ); 250 } 251 252 void cmd_account_del_no( void *data ) 253 { 254 g_free( data ); 220 static void cmd_save( irc_t *irc, char **cmd ) 221 { 222 if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) 223 irc_usermsg( irc, "Please create an account first" ); 224 else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) 225 irc_usermsg( irc, "Configuration saved" ); 226 else 227 irc_usermsg( irc, "Configuration could not be saved!" ); 255 228 } 256 229 … … 285 258 set_name = set_full; 286 259 287 head = &irc-> set;260 head = &irc->b->set; 288 261 } 289 262 else … … 356 329 account_t *a; 357 330 358 if( ( a = account_get( irc , id ) ) )331 if( ( a = account_get( irc->b, id ) ) ) 359 332 return &a->set; 360 333 else … … 404 377 } 405 378 406 a = account_add( irc , prpl, cmd[3], cmd[4] );379 a = account_add( irc->b, prpl, cmd[3], cmd[4] ); 407 380 if( cmd[5] ) 408 381 { … … 418 391 MIN_ARGS( 2 ); 419 392 420 if( !( a = account_get( irc , cmd[2] ) ) )393 if( !( a = account_get( irc->b, cmd[2] ) ) ) 421 394 { 422 395 irc_usermsg( irc, "Invalid account" ); … … 428 401 else 429 402 { 430 struct cmd_account_del_data *cad; 431 char *msg; 432 433 cad = g_malloc( sizeof( struct cmd_account_del_data ) ); 434 cad->a = a; 435 cad->irc = irc; 436 437 msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will " 438 "also forget all your saved nicknames. If you want " 439 "to change your username/password, use the `account " 440 "set' command. Are you sure you want to delete this " 441 "account?", a->prpl->name, a->user ); 442 query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad ); 443 g_free( msg ); 403 account_del( irc->b, a ); 404 irc_usermsg( irc, "Account deleted" ); 444 405 } 445 406 } … … 451 412 irc_usermsg( irc, "Account list:" ); 452 413 453 for( a = irc-> accounts; a; a = a->next )414 for( a = irc->b->accounts; a; a = a->next ) 454 415 { 455 416 char *con; … … 474 435 if( cmd[2] ) 475 436 { 476 if( ( a = account_get( irc , cmd[2] ) ) )437 if( ( a = account_get( irc->b, cmd[2] ) ) ) 477 438 { 478 439 if( a->ic ) … … 483 444 else 484 445 { 485 account_on( irc , a );446 account_on( irc->b, a ); 486 447 } 487 448 } … … 494 455 else 495 456 { 496 if ( irc->accounts ) { 457 if ( irc->b->accounts ) 458 { 497 459 irc_usermsg( irc, "Trying to get all accounts connected..." ); 498 460 499 for( a = irc-> accounts; a; a = a->next )461 for( a = irc->b->accounts; a; a = a->next ) 500 462 if( !a->ic && a->auto_connect ) 501 account_on( irc , a );463 account_on( irc->b, a ); 502 464 } 503 465 else … … 513 475 irc_usermsg( irc, "Deactivating all active (re)connections..." ); 514 476 515 for( a = irc-> accounts; a; a = a->next )477 for( a = irc->b->accounts; a; a = a->next ) 516 478 { 517 479 if( a->ic ) 518 account_off( irc , a );480 account_off( irc->b, a ); 519 481 else if( a->reconnect ) 520 482 cancel_auto_reconnect( a ); 521 483 } 522 484 } 523 else if( ( a = account_get( irc , cmd[2] ) ) )485 else if( ( a = account_get( irc->b, cmd[2] ) ) ) 524 486 { 525 487 if( a->ic ) 526 488 { 527 account_off( irc , a );489 account_off( irc->b, a ); 528 490 } 529 491 else if( a->reconnect ) … … 556 518 } 557 519 520 static set_t **cmd_channel_set_findhead( irc_t *irc, char *id ) 521 { 522 irc_channel_t *ic; 523 524 if( ( ic = irc_channel_get( irc, id ) ) ) 525 return &ic->set; 526 else 527 return NULL; 528 } 529 530 static void cmd_channel( irc_t *irc, char **cmd ) 531 { 532 if( g_strcasecmp( cmd[1], "set" ) == 0 ) 533 { 534 MIN_ARGS( 2 ); 535 536 cmd_set_real( irc, cmd + 1, cmd_channel_set_findhead, NULL ); 537 } 538 else if( g_strcasecmp( cmd[1], "list" ) == 0 ) 539 { 540 GSList *l; 541 int i = 0; 542 543 if( strchr( irc->umode, 'b' ) ) 544 irc_usermsg( irc, "Channel list:" ); 545 546 for( l = irc->channels; l; l = l->next ) 547 { 548 irc_channel_t *ic = l->data; 549 550 irc_usermsg( irc, "%2d. %s, %s channel%s", i, ic->name, 551 set_getstr( &ic->set, "type" ), 552 ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : "" ); 553 554 i ++; 555 } 556 irc_usermsg( irc, "End of channel list" ); 557 } 558 else if( g_strcasecmp( cmd[1], "del" ) == 0 ) 559 { 560 irc_channel_t *ic; 561 562 MIN_ARGS( 2 ); 563 564 if( ( ic = irc_channel_get( irc, cmd[2] ) ) && 565 !( ic->flags & IRC_CHANNEL_JOINED ) && 566 ic != ic->irc->default_channel ) 567 { 568 irc_usermsg( irc, "Channel %s deleted.", ic->name ); 569 irc_channel_free( ic ); 570 } 571 else 572 irc_usermsg( irc, "Couldn't remove channel (main channel %s or " 573 "channels you're still in cannot be deleted).", 574 ic->irc->default_channel->name ); 575 } 576 else 577 { 578 irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] ); 579 } 580 } 581 558 582 static void cmd_add( irc_t *irc, char **cmd ) 559 583 { … … 568 592 } 569 593 570 if( !( a = account_get( irc , cmd[1] ) ) )594 if( !( a = account_get( irc->b, cmd[1] ) ) ) 571 595 { 572 596 irc_usermsg( irc, "Invalid account" ); … … 586 610 return; 587 611 } 588 else if( user_find( irc, cmd[3] ) )612 else if( irc_user_by_name( irc, cmd[3] ) ) 589 613 { 590 614 irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); … … 600 624 a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); 601 625 else 602 /* Yeah, officially this is a call-*back*... So if we just 603 called add_buddy, we'll wait for the IM server to respond 604 before we do this. */ 605 imcb_add_buddy( a->ic, cmd[2], NULL ); 626 /* Only for add -tmp. For regular adds, this callback will 627 be called once the IM server confirms. */ 628 bee_user_new( irc->b, a->ic, cmd[2], BEE_USER_LOCAL ); 606 629 607 630 irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2] ); 631 } 632 633 static void cmd_remove( irc_t *irc, char **cmd ) 634 { 635 irc_user_t *iu; 636 bee_user_t *bu; 637 char *s; 638 639 if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) ) 640 { 641 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); 642 return; 643 } 644 s = g_strdup( bu->handle ); 645 646 bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL ); 647 nick_del( bu->ic->acc, bu->handle ); 648 //TODO(wilmer): bee_user_free() and/or let the IM mod do it? irc_user_free( irc, cmd[1] ); 649 650 irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); 651 g_free( s ); 652 653 return; 608 654 } 609 655 … … 615 661 if( !cmd[2] ) 616 662 { 617 user_t *u = user_find( irc, cmd[1] );618 if( ! u || !u->ic)663 irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); 664 if( !iu || !iu->bu ) 619 665 { 620 666 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 621 667 return; 622 668 } 623 ic = u->ic;624 cmd[2] = u->handle;625 } 626 else if( !( a = account_get( irc , cmd[1] ) ) )669 ic = iu->bu->ic; 670 cmd[2] = iu->bu->handle; 671 } 672 else if( !( a = account_get( irc->b, cmd[1] ) ) ) 627 673 { 628 674 irc_usermsg( irc, "Invalid account" ); … … 647 693 static void cmd_rename( irc_t *irc, char **cmd ) 648 694 { 649 user_t *u; 650 651 if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) 695 irc_user_t *iu; 696 697 iu = irc_user_by_name( irc, cmd[1] ); 698 699 if( iu == NULL ) 700 { 701 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 702 } 703 else if( iu == irc->user ) 652 704 { 653 705 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 654 706 } 655 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 656 { 657 if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) ) 658 { 659 u = user_find( irc, irc->nick ); 660 661 irc_part( irc, u, irc->channel ); 662 g_free( irc->channel ); 663 irc->channel = g_strdup( cmd[2] ); 664 irc_join( irc, u, irc->channel ); 665 666 if( strcmp( cmd[0], "set_rename" ) != 0 ) 667 set_setstr( &irc->set, "control_channel", cmd[2] ); 668 } 669 } 670 else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) 707 else if( !nick_ok( cmd[2] ) ) 708 { 709 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); 710 } 711 else if( irc_user_by_name( irc, cmd[2] ) ) 671 712 { 672 713 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 673 714 } 674 else if( !nick_ok( cmd[2] ) ) 675 { 676 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); 677 } 678 else if( !( u = user_find( irc, cmd[1] ) ) ) 679 { 680 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 681 } 682 else 683 { 684 user_rename( irc, cmd[1], cmd[2] ); 685 irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] ); 686 if( g_strcasecmp( cmd[1], irc->mynick ) == 0 ) 687 { 688 g_free( irc->mynick ); 689 irc->mynick = g_strdup( cmd[2] ); 690 715 else 716 { 717 if( !irc_user_set_nick( iu, cmd[2] ) ) 718 { 719 irc_usermsg( irc, "Error while changing nick" ); 720 return; 721 } 722 723 if( iu == irc->root ) 724 { 691 725 /* If we're called internally (user did "set root_nick"), 692 726 let's not go O(INF). :-) */ 693 727 if( strcmp( cmd[0], "set_rename" ) != 0 ) 694 set_setstr( &irc-> set, "root_nick", cmd[2] );695 } 696 else if( u->send_handler == buddy_send_handler)697 { 698 nick_set( u->ic->acc,u->handle, cmd[2] );728 set_setstr( &irc->b->set, "root_nick", cmd[2] ); 729 } 730 else if( iu->bu ) 731 { 732 nick_set( iu->bu->ic->acc, iu->bu->handle, cmd[2] ); 699 733 } 700 734 … … 707 741 irc_t *irc = set->data; 708 742 709 if( strcmp( irc-> mynick, new_nick ) != 0 )710 { 711 char *cmd[] = { "set_rename", irc-> mynick, new_nick, NULL };743 if( strcmp( irc->root->nick, new_nick ) != 0 ) 744 { 745 char *cmd[] = { "set_rename", irc->root->nick, new_nick, NULL }; 712 746 713 747 cmd_rename( irc, cmd ); 714 748 } 715 749 716 return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID; 717 } 718 719 char *set_eval_control_channel( set_t *set, char *new_name ) 720 { 721 irc_t *irc = set->data; 722 723 if( strcmp( irc->channel, new_name ) != 0 ) 724 { 725 char *cmd[] = { "set_rename", irc->channel, new_name, NULL }; 726 727 cmd_rename( irc, cmd ); 728 } 729 730 return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID; 731 } 732 733 static void cmd_remove( irc_t *irc, char **cmd ) 734 { 735 user_t *u; 736 char *s; 737 738 if( !( u = user_find( irc, cmd[1] ) ) || !u->ic ) 739 { 740 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); 741 return; 742 } 743 s = g_strdup( u->handle ); 744 745 u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL ); 746 nick_del( u->ic->acc, u->handle ); 747 user_del( irc, cmd[1] ); 748 749 irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); 750 g_free( s ); 751 752 return; 750 return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID; 753 751 } 754 752 … … 758 756 account_t *a; 759 757 760 if( !cmd[2] && ( a = account_get( irc , cmd[1] ) ) && a->ic )758 if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic ) 761 759 { 762 760 char *format; … … 771 769 for( l = a->ic->deny; l; l = l->next ) 772 770 { 773 user_t *u = user_findhandle( a->ic, l->data ); 774 irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); 771 bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data ); 772 irc_user_t *iu = bu ? bu->ui_data : NULL; 773 irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" ); 775 774 } 776 775 irc_usermsg( irc, "End of list." ); … … 780 779 else if( !cmd[2] ) 781 780 { 782 user_t *u = user_find( irc, cmd[1] );783 if( ! u || !u->ic)781 irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); 782 if( !iu || !iu->bu ) 784 783 { 785 784 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 786 785 return; 787 786 } 788 ic = u->ic;789 cmd[2] = u->handle;790 } 791 else if( !( a = account_get( irc , cmd[1] ) ) )787 ic = iu->bu->ic; 788 cmd[2] = iu->bu->handle; 789 } 790 else if( !( a = account_get( irc->b, cmd[1] ) ) ) 792 791 { 793 792 irc_usermsg( irc, "Invalid account" ); … … 817 816 account_t *a; 818 817 819 if( !cmd[2] && ( a = account_get( irc , cmd[1] ) ) && a->ic )818 if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic ) 820 819 { 821 820 char *format; … … 830 829 for( l = a->ic->permit; l; l = l->next ) 831 830 { 832 user_t *u = user_findhandle( a->ic, l->data ); 833 irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); 831 bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data ); 832 irc_user_t *iu = bu ? bu->ui_data : NULL; 833 irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" ); 834 834 } 835 835 irc_usermsg( irc, "End of list." ); … … 839 839 else if( !cmd[2] ) 840 840 { 841 user_t *u = user_find( irc, cmd[1] );842 if( ! u || !u->ic)841 irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); 842 if( !iu || !iu->bu ) 843 843 { 844 844 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 845 845 return; 846 846 } 847 ic = u->ic;848 cmd[2] = u->handle;849 } 850 else if( !( a = account_get( irc , cmd[1] ) ) )847 ic = iu->bu->ic; 848 cmd[2] = iu->bu->handle; 849 } 850 else if( !( a = account_get( irc->b, cmd[1] ) ) ) 851 851 { 852 852 irc_usermsg( irc, "Invalid account" ); … … 915 915 } 916 916 917 static void cmd_save( irc_t *irc, char **cmd )918 {919 if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )920 irc_usermsg( irc, "Please create an account first" );921 else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )922 irc_usermsg( irc, "Configuration saved" );923 else924 irc_usermsg( irc, "Configuration could not be saved!" );925 }926 927 917 static void cmd_blist( irc_t *irc, char **cmd ) 928 918 { 929 919 int online = 0, away = 0, offline = 0; 930 user_t *u;920 GSList *l; 931 921 char s[256]; 932 922 char *format; … … 949 939 format = "%-16.16s %-40.40s %s"; 950 940 951 irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" ); 952 953 for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away ) 954 { 941 irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" ); 942 943 for( l = irc->users; l; l = l->next ) 944 { 945 irc_user_t *iu = l->data; 946 bee_user_t *bu = iu->bu; 947 948 if( !bu || ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE ) 949 continue; 950 955 951 if( online == 1 ) 956 952 { 957 953 char st[256] = "Online"; 958 954 959 if( u->status_msg )960 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );955 if( bu->status_msg ) 956 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg ); 961 957 962 g_snprintf( s, sizeof( s ) - 1, "%s @%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name,u->ic->acc->user );963 irc_usermsg( irc, format, u->nick, s, st );958 g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user ); 959 irc_usermsg( irc, format, iu->nick, s, st ); 964 960 } 965 961 … … 967 963 } 968 964 969 for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away ) 970 { 965 for( l = irc->users; l; l = l->next ) 966 { 967 irc_user_t *iu = l->data; 968 bee_user_t *bu = iu->bu; 969 970 if( !bu || !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) ) 971 continue; 972 971 973 if( away == 1 ) 972 974 { 973 g_snprintf( s, sizeof( s ) - 1, "%s @%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name,u->ic->acc->user );974 irc_usermsg( irc, format, u->nick, s, u->away);975 g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user ); 976 irc_usermsg( irc, format, iu->nick, s, irc_user_get_away( iu ) ); 975 977 } 976 978 n_away ++; 977 979 } 978 980 979 for( u = irc->users; u; u = u->next ) if( u->ic && !u->online ) 980 { 981 for( l = irc->users; l; l = l->next ) 982 { 983 irc_user_t *iu = l->data; 984 bee_user_t *bu = iu->bu; 985 986 if( !bu || bu->flags & BEE_USER_ONLINE ) 987 continue; 988 981 989 if( offline == 1 ) 982 990 { 983 g_snprintf( s, sizeof( s ) - 1, "%s @%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name,u->ic->acc->user );984 irc_usermsg( irc, format, u->nick, s, "Offline" );991 g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user ); 992 irc_usermsg( irc, format, iu->nick, s, "Offline" ); 985 993 } 986 994 n_offline ++; … … 988 996 989 997 irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline ); 990 }991 992 static void cmd_nick( irc_t *irc, char **cmd )993 {994 account_t *a;995 996 if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )997 {998 irc_usermsg( irc, "Invalid account");999 }1000 else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )1001 {1002 irc_usermsg( irc, "That account is not on-line" );1003 }1004 else if ( !cmd[2] )1005 {1006 irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );1007 }1008 else if ( !a->prpl->set_my_name )1009 {1010 irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );1011 }1012 else1013 {1014 irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );1015 1016 a->prpl->set_my_name( a->ic, cmd[2] );1017 }1018 998 } 1019 999 … … 1038 1018 } 1039 1019 1040 static void cmd_join_chat( irc_t *irc, char **cmd )1041 {1042 irc_usermsg( irc, "This command is now obsolete. "1043 "Please try the `chat' command instead." );1044 }1045 1046 static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )1047 {1048 struct chat *c;1049 1050 if( ( c = chat_get( irc, id ) ) )1051 return &c->set;1052 else1053 return NULL;1054 }1055 1056 1020 static void cmd_chat( irc_t *irc, char **cmd ) 1057 1021 { 1058 1022 account_t *acc; 1059 struct chat *c;1060 1023 1061 1024 if( g_strcasecmp( cmd[1], "add" ) == 0 ) 1062 1025 { 1063 1026 char *channel, *s; 1027 struct irc_channel *ic; 1064 1028 1065 1029 MIN_ARGS( 3 ); 1066 1030 1067 if( !( acc = account_get( irc , cmd[2] ) ) )1031 if( !( acc = account_get( irc->b, cmd[2] ) ) ) 1068 1032 { 1069 1033 irc_usermsg( irc, "Invalid account" ); 1034 return; 1035 } 1036 else if( !acc->prpl->chat_join ) 1037 { 1038 irc_usermsg( irc, "Named chatrooms not supported on that account." ); 1070 1039 return; 1071 1040 } … … 1084 1053 if( strchr( CTYPES, channel[0] ) == NULL ) 1085 1054 { 1086 s = g_strdup_printf( " %c%s", CTYPES[0], channel );1055 s = g_strdup_printf( "#%s", channel ); 1087 1056 g_free( channel ); 1088 1057 channel = s; 1089 1058 } 1090 1059 1091 if( ( c = chat_add( irc, acc, cmd[3], channel ) ) ) 1092 irc_usermsg( irc, "Chatroom added successfully." ); 1093 else 1060 if( ( ic = irc_channel_new( irc, channel ) ) && 1061 set_setstr( &ic->set, "chat_type", "room" ) && 1062 set_setstr( &ic->set, "account", cmd[2] ) && 1063 set_setstr( &ic->set, "room", cmd[3] ) ) 1064 { 1065 irc_usermsg( irc, "Chatroom successfully added." ); 1066 } 1067 else 1068 { 1069 if( ic ) 1070 irc_channel_free( ic ); 1071 1094 1072 irc_usermsg( irc, "Could not add chatroom." ); 1095 1096 g_free( channel ); 1097 } 1098 else if( g_strcasecmp( cmd[1], "list" ) == 0 ) 1099 { 1100 int i = 0; 1101 1102 if( strchr( irc->umode, 'b' ) ) 1103 irc_usermsg( irc, "Chatroom list:" ); 1104 1105 for( c = irc->chatrooms; c; c = c->next ) 1106 { 1107 irc_usermsg( irc, "%2d. %s(%s) %s, %s", i, c->acc->prpl->name, 1108 c->acc->user, c->handle, c->channel ); 1109 1110 i ++; 1111 } 1112 irc_usermsg( irc, "End of chatroom list" ); 1113 } 1114 else if( g_strcasecmp( cmd[1], "set" ) == 0 ) 1115 { 1073 } 1074 } 1075 else if( g_strcasecmp( cmd[1], "with" ) == 0 ) 1076 { 1077 irc_user_t *iu; 1078 1116 1079 MIN_ARGS( 2 ); 1117 1080 1118 cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL ); 1119 } 1120 else if( g_strcasecmp( cmd[1], "del" ) == 0 ) 1121 { 1122 MIN_ARGS( 2 ); 1123 1124 if( ( c = chat_get( irc, cmd[2] ) ) ) 1125 { 1126 chat_del( irc, c ); 1127 } 1128 else 1129 { 1130 irc_usermsg( irc, "Could not remove chat." ); 1131 } 1132 } 1133 else if( g_strcasecmp( cmd[1], "with" ) == 0 ) 1134 { 1135 user_t *u; 1136 1137 MIN_ARGS( 2 ); 1138 1139 if( ( u = user_find( irc, cmd[2] ) ) && u->ic && u->ic->acc->prpl->chat_with ) 1140 { 1141 if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) ) 1081 if( ( iu = irc_user_by_name( irc, cmd[2] ) ) && 1082 iu->bu && iu->bu->ic->acc->prpl->chat_with ) 1083 { 1084 if( !iu->bu->ic->acc->prpl->chat_with( iu->bu->ic, iu->bu->handle ) ) 1142 1085 { 1143 1086 irc_usermsg( irc, "(Possible) failure while trying to open " 1144 "a groupchat with %s.", u->nick );1087 "a groupchat with %s.", iu->nick ); 1145 1088 } 1146 1089 } … … 1204 1147 { 1205 1148 irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name ); 1206 imcb_file_canceled( file , "Denied by user" );1149 imcb_file_canceled( file->ic, file, "Denied by user" ); 1207 1150 } 1208 1151 break; … … 1211 1154 { 1212 1155 irc_usermsg( irc, "Canceling file transfer for %s", file->file_name ); 1213 imcb_file_canceled( file , "Canceled by user" );1156 imcb_file_canceled( file->ic, file, "Canceled by user" ); 1214 1157 } 1215 1158 break; … … 1218 1161 } 1219 1162 1163 /* IMPORTANT: Keep this list sorted! The short command logic needs that. */ 1220 1164 const command_t commands[] = { 1165 { "account", 1, cmd_account, 0 }, 1166 { "add", 2, cmd_add, 0 }, 1167 { "allow", 1, cmd_allow, 0 }, 1168 { "blist", 0, cmd_blist, 0 }, 1169 { "block", 1, cmd_block, 0 }, 1170 { "channel", 1, cmd_channel, 0 }, 1171 { "chat", 1, cmd_chat, 0 }, 1172 { "drop", 1, cmd_drop, 0 }, 1173 { "ft", 0, cmd_transfer, 0 }, 1221 1174 { "help", 0, cmd_help, 0 }, 1222 1175 { "identify", 1, cmd_identify, 0 }, 1176 { "info", 1, cmd_info, 0 }, 1177 { "no", 0, cmd_yesno, 0 }, 1178 { "qlist", 0, cmd_qlist, 0 }, 1223 1179 { "register", 1, cmd_register, 0 }, 1224 { "drop", 1, cmd_drop, 0 }, 1225 { "account", 1, cmd_account, 0 }, 1226 { "add", 2, cmd_add, 0 }, 1227 { "info", 1, cmd_info, 0 }, 1180 { "remove", 1, cmd_remove, 0 }, 1228 1181 { "rename", 2, cmd_rename, 0 }, 1229 { "remove", 1, cmd_remove, 0 },1230 { "block", 1, cmd_block, 0 },1231 { "allow", 1, cmd_allow, 0 },1232 1182 { "save", 0, cmd_save, 0 }, 1233 1183 { "set", 0, cmd_set, 0 }, 1184 { "transfer", 0, cmd_transfer, 0 }, 1234 1185 { "yes", 0, cmd_yesno, 0 }, 1235 { "no", 0, cmd_yesno, 0 },1236 { "blist", 0, cmd_blist, 0 },1237 { "nick", 1, cmd_nick, 0 },1238 { "qlist", 0, cmd_qlist, 0 },1239 { "join_chat", 2, cmd_join_chat, 0 },1240 { "chat", 1, cmd_chat, 0 },1241 { "transfer", 0, cmd_transfer, 0 },1242 1186 { NULL } 1243 1187 }; -
set.c
r560d0a0 rf1cea66 69 69 while( s ) 70 70 { 71 if( g_strcasecmp( s->key, key ) == 0 ) 71 if( g_strcasecmp( s->key, key ) == 0 || 72 ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) ) 72 73 break; 73 74 s = s->next; … … 176 177 177 178 g_free( s->key ); 178 if( s->value ) g_free( s->value ); 179 if( s->def ) g_free( s->def ); 179 g_free( s->old_key ); 180 g_free( s->value ); 181 g_free( s->def ); 180 182 g_free( s ); 181 183 } … … 240 242 } 241 243 244 /* 242 245 char *set_eval_ops( set_t *set, char *value ) 243 246 { … … 261 264 return value; 262 265 } 266 */ -
set.h
r560d0a0 rf1cea66 54 54 55 55 char *key; 56 char *old_key; /* Previously known as; for smooth upgrades. */ 56 57 char *value; 57 58 char *def; /* Default value. If the set_setstr() function -
storage_xml.c
r560d0a0 rf1cea66 147 147 arc_decode( pass_cr, pass_len, &password, xd->given_pass ) ) 148 148 { 149 xd->current_account = account_add( irc , prpl, handle, password );149 xd->current_account = account_add( irc->b, prpl, handle, password ); 150 150 if( server ) 151 151 set_setstr( &xd->current_account->set, "server", server ); … … 181 181 xd->current_set_head = &xd->current_account->set; 182 182 else 183 xd->current_set_head = &xd->irc-> set;183 xd->current_set_head = &xd->irc->b->set; 184 184 185 185 xd->current_setting = g_strdup( setting ); … … 215 215 if( xd->current_account && handle && channel ) 216 216 { 217 xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );217 //xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel ); 218 218 } 219 219 else … … 353 353 static storage_status_t xml_load( irc_t *irc, const char *password ) 354 354 { 355 return xml_load_real( irc, irc-> nick, password, XML_PASS_UNKNOWN );355 return xml_load_real( irc, irc->user->nick, password, XML_PASS_UNKNOWN ); 356 356 } 357 357 … … 396 396 md5_state_t md5_state; 397 397 398 path2 = g_strdup( irc-> nick );398 path2 = g_strdup( irc->user->nick ); 399 399 nick_lc( path2 ); 400 400 g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); … … 422 422 pass_buf = base64_encode( pass_md5, 21 ); 423 423 424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc-> nick, pass_buf, XML_FORMAT_VERSION ) )424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->user->nick, pass_buf, XML_FORMAT_VERSION ) ) 425 425 goto write_error; 426 426 427 427 g_free( pass_buf ); 428 428 429 for( set = irc-> set; set; set = set->next )429 for( set = irc->b->set; set; set = set->next ) 430 430 if( set->value ) 431 431 if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 432 432 goto write_error; 433 433 434 for( acc = irc-> accounts; acc; acc = acc->next )434 for( acc = irc->b->accounts; acc; acc = acc->next ) 435 435 { 436 436 unsigned char *pass_cr; … … 470 470 goto write_error; 471 471 472 #if 0 472 473 for( c = irc->chatrooms; c; c = c->next ) 473 474 { … … 488 489 goto write_error; 489 490 } 491 #endif 490 492 491 493 if( !xml_printf( fd, 1, "</account>\n" ) )
Note: See TracChangeset
for help on using the changeset viewer.