Changes in / [f1cea66:560d0a0]
- Files:
-
- 6 added
- 14 deleted
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
rf1cea66 r560d0a0 10 10 11 11 # Program variables 12 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.hhelp.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 = 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.o 13 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.h 14 14 subdirs = lib protocols 15 15 -
bitlbee.h
rf1cea66 r560d0a0 126 126 #define CONF_FILE_DEF ETCDIR "bitlbee.conf" 127 127 128 #include "bee.h"129 128 #include "irc.h" 130 129 #include "storage.h" … … 161 160 gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); 162 161 163 void root_command_string( irc_t *irc, char *command);162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags ); 164 163 void root_command( irc_t *irc, char *command[] ); 165 164 gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); -
conf.c
rf1cea66 r560d0a0 376 376 if( g_strcasecmp( ini->section, "defaults" ) == 0 ) 377 377 { 378 set_t *s = set_find( &irc-> b->set, ini->key );378 set_t *s = set_find( &irc->set, ini->key ); 379 379 380 380 if( s ) -
configure
rf1cea66 r560d0a0 27 27 yahoo=1 28 28 twitter=1 29 twitter=130 29 purple=0 31 30 … … 69 68 --oscar=0/1 Disable/enable Oscar part (ICQ, AIM) $oscar 70 69 --yahoo=0/1 Disable/enable Yahoo part $yahoo 71 --twitter=0/1 70 --twitter=0/1 Disable/enable Twitter part $twitter 72 71 73 72 --purple=0/1 Disable/enable libpurple support $purple -
dcc.c
rf1cea66 r560d0a0 61 61 unsigned int receivedchunks=0, receiveddata=0; 62 62 63 void dcc_finish( file_transfer_t *file );64 void dcc_close( file_transfer_t *file );63 static void dcc_finish( file_transfer_t *file ); 64 static 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, irc_user_t *iu, struct sockaddr_storage *saddr ); 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 ); 67 68 gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond); 68 69 gboolean dccs_recv_write_request( file_transfer_t *ft ); … … 70 71 gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ); 71 72 72 dcc_file_transfer_t *dcc_alloc_transfer( const char *file_name, size_t file_size, struct im_connection *ic ) 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 ) 73 112 { 74 113 file_transfer_t *file = g_new0( file_transfer_t, 1 ); … … 78 117 file->file_name = g_strdup( file_name ); 79 118 file->local_id = local_transfer_id++; 80 file->ic =df->ic = ic;119 df->ic = ic; 81 120 df->ft = file; 82 121 … … 85 124 86 125 /* This is where the sending magic starts... */ 87 file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, constchar *file_name, size_t file_size )126 file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size ) 88 127 { 89 128 file_transfer_t *file; 90 129 dcc_file_transfer_t *df; 91 irc_t *irc = (irc_t *) ic->bee->ui_data;92 130 struct sockaddr_storage saddr; 93 131 char *errmsg; … … 112 150 file->status = FT_STATUS_LISTENING; 113 151 114 if( !dccs_send_request( df, iu, &saddr ) )152 if( !dccs_send_request( df, user_nick, &saddr ) ) 115 153 return NULL; 116 154 … … 118 156 df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_send_proto, df ); 119 157 120 irc->file_transfers = g_slist_prepend(irc->file_transfers, file );158 df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, file ); 121 159 122 160 df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); … … 125 163 "Accept the file transfer if you'd like the file. If you don't, " 126 164 "issue the 'transfers reject' command.", 127 iu->nick, file_name, file_size / 1024 );165 user_nick, file_name, file_size / 1024 ); 128 166 129 167 return file; … … 178 216 179 217 /* Creates the "DCC SEND" line and sends it to the server */ 180 int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr )218 int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr ) 181 219 { 182 220 char ipaddr[INET6_ADDRSTRLEN]; … … 212 250 df->ft->file_name, ipaddr, port, df->ft->file_size ); 213 251 214 irc_send_msg_raw( iu, "PRIVMSG", iu->irc->user->nick, cmd ); 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 ); 215 254 216 255 g_free( cmd ); … … 457 496 * Cleans up after a transfer. 458 497 */ 459 void dcc_close( file_transfer_t *file )498 static void dcc_close( file_transfer_t *file ) 460 499 { 461 500 dcc_file_transfer_t *df = file->priv; 462 irc_t *irc = (irc_t *) df->ic->bee->ui_data;463 501 464 502 if( file->free ) … … 476 514 b_event_remove( df->progress_timeout ); 477 515 478 irc->file_transfers = g_slist_remove(irc->file_transfers, file );516 df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file ); 479 517 480 518 g_free( df ); … … 504 542 * 505 543 */ 506 file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp ) 507 { 508 irc_t *irc = (irc_t *) ic->bee->ui_data; 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; 509 553 file_transfer_t *ft; 510 554 dcc_file_transfer_t *df; 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 { 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 ); 518 573 char *filename, *host, *port; 574 size_t filesize; 519 575 struct addrinfo hints, *rp; 520 521 filename = ctcp[2]; 522 523 host = ctcp[3]; 524 while( *host && isdigit( *host ) ) host++; /* Just digits? */ 525 if( *host == '\0' ) 576 577 /* "filename" or filename */ 578 if ( pmatch[2].rm_so > 0 ) 526 579 { 527 struct in_addr ipaddr = { .s_addr = htonl( atoll( ctcp[3] ) ) }; 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 ) ) }; 528 594 host = inet_ntoa( ipaddr ); 529 595 } else 530 596 { 531 597 /* Contains non-numbers, hopefully an IPV6 address */ 532 host = ctcp[3];598 host = input + pmatch[7].rm_so; 533 599 } 534 600 535 port = ctcp[4]; 536 filesize = atoll( ctcp[5] ); 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 ); 537 606 538 607 memset( &hints, 0, sizeof ( struct addrinfo ) ); … … 542 611 if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) ) 543 612 { 613 g_free( input ); 544 614 imcb_log( ic, "DCC: getaddrinfo() failed with %s " 545 615 "when parsing incoming 'DCC SEND': " … … 555 625 556 626 freeaddrinfo( rp ); 557 558 irc->file_transfers = g_slist_prepend( irc->file_transfers, ft ); 627 g_free( input ); 628 629 df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, ft ); 559 630 560 631 return ft; 561 632 } 562 else 563 imcb_log( ic, "DCC: couldnt parse `DCC SEND' line");633 634 imcb_log( ic, "DCC: couldnt parse 'DCC SEND' line: %s", line ); 564 635 565 636 return NULL; 566 637 } 638 -
dcc.h
rf1cea66 r560d0a0 95 95 } dcc_file_transfer_t; 96 96 97 file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size ); 97 file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size ); 98 98 99 void dcc_canceled( file_transfer_t *file, char *reason ); 100 99 101 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 );104 102 103 file_transfer_t *dcc_request( struct im_connection *ic, char *line ); 105 104 #endif -
doc/user-guide/commands.xml
rf1cea66 r560d0a0 593 593 594 594 <bitlbee-setting name="handle_unknown" type="string" scope="global"> 595 <default> add_channel</default>595 <default>root</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 [-noload|-force]<password></syntax>1116 <syntax>identify <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).1134 1126 </para> 1135 1127 </description> -
doc/user-guide/misc.xml
rf1cea66 r560d0a0 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 136 119 </chapter> -
ipc.c
rf1cea66 r560d0a0 138 138 139 139 if( strchr( irc->umode, 'w' ) ) 140 irc_write( irc, ":%s WALLOPS :%s", irc-> root->host, cmd[1] );140 irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] ); 141 141 } 142 142 … … 147 147 148 148 if( strchr( irc->umode, 's' ) ) 149 irc_write( irc, ":%s NOTICE %s :%s", irc-> root->host, irc->user->nick, cmd[1] );149 irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->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-> root->host, irc->user->nick, cmd[1] );158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->myhost, irc->nick, cmd[1] ); 159 159 } 160 160 … … 176 176 return; 177 177 178 if( nick_cmp( cmd[1], irc-> user->nick ) != 0 )178 if( nick_cmp( cmd[1], irc->nick ) != 0 ) 179 179 return; /* It's not for us. */ 180 180 181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc-> root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] );181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->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-> user->host, irc->user->nick, irc->user->fullname );190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 191 191 } 192 192 -
irc.c
rf1cea66 r560d0a0 5 5 \********************************************************************/ 6 6 7 /* The IRC-based UI (for now the only one)*/7 /* The big hairy IRCd part of the project */ 8 8 9 9 /* … … 24 24 */ 25 25 26 #define BITLBEE_CORE 26 27 #include "bitlbee.h" 28 #include "sock.h" 27 29 #include "ipc.h" 28 30 #include "dcc.h" 29 31 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 ); 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 } 35 114 36 115 irc_t *irc_new( int fd ) … … 39 118 struct sockaddr_storage sock; 40 119 socklen_t socklen = sizeof( sock ); 41 char *host = NULL, *myhost = NULL;42 irc_user_t *iu;43 120 set_t *s; 44 bee_t *b;45 121 46 122 irc = g_new0( irc_t, 1 ); … … 54 130 irc->last_pong = gettime(); 55 131 56 irc-> nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );132 irc->userhash = g_hash_table_new( g_str_hash, g_str_equal ); 57 133 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 ); 58 138 59 139 irc->iconv = (GIConv) -1; … … 62 142 if( global.conf->hostname ) 63 143 { 64 myhost = g_strdup( global.conf->hostname );144 irc->myhost = g_strdup( global.conf->hostname ); 65 145 } 66 146 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) … … 71 151 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 72 152 { 73 myhost = g_strdup( ipv6_unwrap( buf ) );153 irc->myhost = g_strdup( ipv6_unwrap( buf ) ); 74 154 } 75 155 } … … 82 162 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 83 163 { 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" );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" ); 92 172 93 173 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 94 174 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" ); 95 177 96 178 irc_connection_list = g_slist_append( irc_connection_list, irc ); 97 179 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 ); 180 s = set_add( &irc->set, "away", NULL, set_eval_away_status, irc ); 115 181 s->flags |= SET_NULL_OK; 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 ); 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 ); 136 211 137 212 conf_loaddefaults( irc ); 138 213 139 214 /* Evaluator sets the iconv/oconv structures. */ 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 ); 215 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 146 216 147 217 nogaim_init(); 148 218 149 return irc;219 return( irc ); 150 220 } 151 221 … … 168 238 169 239 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 170 irc-> user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );240 irc->nick ? irc->nick : "(NONE)", irc->host, reason ); 171 241 172 242 g_free( reason ); … … 178 248 179 249 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 180 irc-> user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );250 irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" ); 181 251 } 182 252 … … 199 269 } 200 270 201 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 202 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 */ 203 279 void irc_free( irc_t * irc ) 204 280 { 281 user_t *user, *usertmp; 282 205 283 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 206 284 207 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc-> b->set, "save_on_quit" ) )285 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) ) 208 286 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 209 log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick);287 irc_usermsg( irc, "Error while saving settings!" ); 210 288 211 289 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 else 301 /* Nasty hack, but account_del() doesn't work in this 302 case and we don't want infinite loops, do we? ;-) */ 303 irc->accounts = irc->accounts->next; 304 } 212 305 213 306 while( irc->queries != NULL ) 214 307 query_del( irc, irc->queries ); 215 308 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 ); 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 } 226 330 227 331 if( irc->ping_source_id > 0 ) … … 235 339 irc->fd = -1; 236 340 237 g_hash_table_foreach_remove( irc-> nick_user_hash, irc_free_hashkey, NULL );238 g_hash_table_destroy( irc-> nick_user_hash );341 g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL ); 342 g_hash_table_destroy( irc->userhash ); 239 343 240 344 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); … … 248 352 g_free( irc->sendbuffer ); 249 353 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 ); 250 359 g_free( irc->password ); 251 g_free( irc->last_root_cmd ); 360 361 g_free( irc->myhost ); 362 g_free( irc->mynick ); 363 364 g_free( irc->channel ); 365 366 g_free( irc->last_target ); 252 367 253 368 g_free( irc ); … … 261 376 } 262 377 263 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )264 {265 g_free( key );266 267 return( TRUE );268 }269 270 378 /* USE WITH CAUTION! 271 379 Sets pass without checking */ 272 void irc_setpass (irc_t *irc, const char *pass) 380 void irc_setpass (irc_t *irc, const char *pass) 273 381 { 274 382 g_free (irc->password); … … 281 389 } 282 390 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 else293 {294 return SET_INVALID;295 }296 }297 298 static char **irc_splitlines( char *buffer );299 300 391 void irc_process( irc_t *irc ) 301 392 { … … 305 396 if( irc->readbuffer != NULL ) 306 397 { 307 lines = irc_ splitlines( irc->readbuffer );398 lines = irc_tokenize( irc->readbuffer ); 308 399 309 400 for( i = 0; *lines[i] != '\0'; i ++ ) … … 342 433 "`help set charset' for more information. Your " 343 434 "message was ignored.", 344 set_getstr( &irc-> b->set, "charset" ) );435 set_getstr( &irc->set, "charset" ) ); 345 436 346 437 g_free( conv ); … … 349 440 else 350 441 { 351 irc_write( irc, ":%s NOTICE AUTH :%s", irc-> root->host,442 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, 352 443 "Warning: invalid characters received at login time." ); 353 444 … … 387 478 } 388 479 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 ) 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 ) 394 483 { 395 484 int i, j, n = 3; … … 522 611 } 523 612 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 524 643 void irc_write( irc_t *irc, char *format, ... ) 525 644 { … … 532 651 return; 533 652 } 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 }563 653 564 654 void irc_vawrite( irc_t *irc, char *format, va_list params ) … … 617 707 } 618 708 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 ) 753 { 754 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 755 *namelist = 0; 756 } 757 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 should 773 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 619 796 int irc_check_login( irc_t *irc ) 620 797 { 621 if( irc->user ->user && irc->user->nick )798 if( irc->user && irc->nick ) 622 799 { 623 800 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 624 801 { 625 irc_ send_num( irc, 464, ":This server is password-protected." );802 irc_reply( irc, 464, ":This server is password-protected." ); 626 803 return 0; 627 804 } 628 805 else 629 806 { 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 ) 667 { 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] ); 673 } 674 807 irc_login( irc ); 675 808 return 1; 676 809 } … … 683 816 } 684 817 685 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) 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 ) 686 943 { 687 944 /* allow_priv: Set to 0 if s contains user input, 1 if you want 688 945 to set a "privileged" mode (+o, +R, etc). */ 689 char m[128], st = 1; 690 const char *t; 946 char m[256], st = 1, *t; 691 947 int i; 692 948 char changes[512], *p, st2 = 2; … … 696 952 697 953 for( t = irc->umode; *t; t ++ ) 698 if( *t < sizeof( m ) ) 699 m[(int)*t] = 1; 700 954 m[(int)*t] = 1; 955 701 956 p = changes; 702 957 for( t = s; *t; t ++ ) … … 704 959 if( *t == '+' || *t == '-' ) 705 960 st = *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 ) ) ) 961 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) 709 962 { 710 963 if( m[(int)*t] != st) … … 723 976 memset( irc->umode, 0, sizeof( irc->umode ) ); 724 977 725 for( i = 'A'; i <= 'z'&& strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )978 for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) 726 979 if( m[i] ) 727 980 irc->umode[strlen(irc->umode)] = i; 728 981 729 982 if( badflag ) 730 irc_send_num( irc, 501, ":Unknown MODE flag" ); 983 irc_reply( irc, 501, ":Unknown MODE flag" ); 984 /* Deliberately no !user@host on the prefix here */ 731 985 if( *changes ) 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 ); 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 ); 735 1310 } 736 1311 … … 771 1346 } 772 1347 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 } 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 } -
irc.h
rf1cea66 r560d0a0 5 5 \********************************************************************/ 6 6 7 /* The IRC-based UI (for now the only one)*/7 /* The big hairy IRCd part of the project */ 8 8 9 9 /* … … 33 33 #define IRC_PING_STRING "PinglBee" 34 34 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 */ 35 #define UMODES "abisw" 36 #define UMODES_PRIV "Ro" 37 #define CMODES "nt" 38 #define CMODE "t" 39 #define UMODE "s" 40 #define CTYPES "&#" 43 41 44 42 typedef enum … … 50 48 USTATUS_SHUTDOWN = 8 51 49 } irc_status_t; 52 53 struct irc_user;54 50 55 51 typedef struct irc … … 63 59 GIConv iconv, oconv; 64 60 65 struct irc_user *root; 66 struct irc_user *user; 67 68 char *last_root_cmd; 61 int sentbytes; 62 time_t oldtime; 69 63 64 char *nick; 65 char *user; 66 char *host; 67 char *realname; 70 68 char *password; /* HACK: Used to save the user's password, but before 71 69 logging in, this may contain a password we should … … 74 72 char umode[8]; 75 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 76 83 struct query *queries; 84 struct account *accounts; 77 85 GSList *file_transfers; 86 struct chat *chatrooms; 78 87 79 GSList *users, *channels; 80 struct irc_channel *default_channel; 81 GHashTable *nick_user_hash; 88 struct __USER *users; 89 GHashTable *userhash; 82 90 GHashTable *watches; 91 struct __NICK *nicks; 92 struct set *set; 83 93 84 94 gint r_watch_source_id; 85 95 gint w_watch_source_id; 86 96 gint ping_source_id; 87 88 struct bee *b;89 97 } irc_t; 90 98 91 typedef enum 92 { 93 IRC_USER_PRIVATE = 1, 94 IRC_USER_AWAY = 2, 95 } irc_user_flags_t; 99 #include "user.h" 96 100 97 typedef struct irc_user98 {99 irc_t *irc;100 101 char *nick;102 char *user;103 char *host;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_funcs120 {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 enum129 {130 IRC_CHANNEL_JOINED = 1,131 132 /* Hack: Set this flag right before jumping into IM when we expect133 a call to imcb_chat_new(). */134 IRC_CHANNEL_CHAT_PICKME = 0x10000,135 } irc_channel_flags_t;136 137 typedef struct irc_channel138 {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;149 struct set *set;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_funcs159 {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 enum171 {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_user178 {179 irc_user_t *iu;180 int flags;181 } irc_channel_user_t;182 183 typedef enum184 {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_channel192 {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 */201 101 extern GSList *irc_connection_list; 202 102 … … 204 104 void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 205 105 void irc_free( irc_t *irc ); 206 void irc_setpass (irc_t *irc, const char *pass);207 106 107 void irc_exec( irc_t *irc, char **cmd ); 208 108 void irc_process( irc_t *irc ); 209 109 char **irc_parse_line( char *line ); 210 110 char *irc_build_line( char **cmd ); 211 111 112 void irc_vawrite( irc_t *irc, char *format, va_list params ); 212 113 void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 213 114 void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 214 void irc_vawrite( irc_t *irc, char *format, va_list params ); 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 ); 215 118 119 void irc_login( irc_t *irc ); 216 120 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! */ 217 134 218 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); 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 ); 219 139 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 ); 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 ); 271 142 272 143 #endif -
irc_commands.c
rf1cea66 r560d0a0 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2006 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 53 53 else if( global.conf->auth_pass ) 54 54 { 55 irc_ send_num( irc, 464, ":Incorrect password" );55 irc_reply( 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 ->user= g_strdup( cmd[1] );68 irc-> user->fullname = g_strdup( cmd[4] );67 irc->user = g_strdup( cmd[1] ); 68 irc->realname = 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_user_by_name( irc, cmd[1] ) ) 76 { 77 irc_send_num( irc, 433, ":This nick is already in use" ); 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] ); 78 84 } 79 85 else if( !nick_ok( cmd[1] ) ) 80 86 { 81 87 /* [SH] Invalid characters. */ 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] ); 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] ); 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->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 ); 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 } 219 134 } 220 135 221 136 static void irc_cmd_mode( irc_t *irc, char **cmd ) 222 137 { 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] ) 138 if( strchr( CTYPES, *cmd[1] ) ) 139 { 140 if( cmd[2] ) 230 141 { 231 142 if( *cmd[2] == '+' || *cmd[2] == '-' ) 232 irc_ send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );143 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] ); 233 144 else if( *cmd[2] == 'b' ) 234 irc_ send_num( irc, 368, "%s :No bans possible", cmd[1] );145 irc_reply( irc, 368, "%s :No bans possible", cmd[1] ); 235 146 } 236 147 else 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 )148 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE ); 149 } 150 else 151 { 152 if( nick_cmp( cmd[1], irc->nick ) == 0 ) 242 153 { 243 154 if( cmd[2] ) 244 155 irc_umode_set( irc, cmd[2], 0 ); 245 156 else 246 irc_ send_num( irc, 221, "+%s", irc->umode );157 irc_reply( irc, 221, "+%s", irc->umode ); 247 158 } 248 159 else 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 ); 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 ); 264 232 } 265 233 266 234 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 267 235 { 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 { 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] ); 321 243 } 322 244 else … … 359 281 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); 360 282 } 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] ); 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:"**" ); 407 315 } 408 316 409 317 static void irc_cmd_userhost( irc_t *irc, char **cmd ) 410 318 { 319 user_t *u; 411 320 int i; 412 321 … … 418 327 419 328 for( i = 1; cmd[i]; i ++ ) 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 } 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 } 428 336 } 429 337 430 338 static void irc_cmd_ison( irc_t *irc, char **cmd ) 431 339 { 340 user_t *u; 432 341 char buff[IRC_MAX_LINE]; 433 342 int lenleft, i; … … 445 354 while( *this ) 446 355 { 447 irc_user_t *iu;448 449 356 if( ( next = strchr( this, ' ' ) ) ) 450 357 *next = 0; 451 358 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; 359 if( ( u = user_find( irc, this ) ) && u->online ) 360 { 361 lenleft -= strlen( u->nick ) + 1; 456 362 457 363 if( lenleft < 0 ) 458 364 break; 459 365 460 strcat( buff, iu->nick );366 strcat( buff, u->nick ); 461 367 strcat( buff, " " ); 462 368 } … … 481 387 buff[strlen(buff)-1] = '\0'; 482 388 483 irc_ send_num( irc, 303, ":%s", buff );389 irc_reply( irc, 303, ":%s", buff ); 484 390 } 485 391 … … 494 400 { 495 401 char *nick; 496 irc_user_t *iu;402 user_t *u; 497 403 498 404 if( !cmd[i][0] || !cmd[i][1] ) … … 502 408 nick_lc( nick ); 503 409 504 iu = irc_user_by_name( irc, nick );410 u = user_find( irc, nick ); 505 411 506 412 if( cmd[i][0] == '+' ) … … 509 415 g_hash_table_insert( irc->watches, nick, nick ); 510 416 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" ); 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" ); 514 419 else 515 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", 516 (int) time( NULL ), "is offline" ); 420 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); 517 421 } 518 422 else if( cmd[i][0] == '-' ) … … 525 429 g_free( okey ); 526 430 527 irc_ send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );431 irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 528 432 } 529 433 } … … 533 437 static void irc_cmd_topic( irc_t *irc, char **cmd ) 534 438 { 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 ); 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 ); 552 453 } 553 454 } … … 555 456 static void irc_cmd_away( irc_t *irc, char **cmd ) 556 457 { 557 if( cmd[1] && *cmd[1] ) 558 { 559 char away[strlen(cmd[1])+1]; 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 { 560 465 int i, j; 561 466 562 467 /* Copy away string, but skip control chars. Mainly because 563 468 Jabber really doesn't like them. */ 564 for( i = j = 0; cmd[1][i]; i ++ ) 565 if( ( away[j] = cmd[1][i] ) >= ' ' ) 469 u->away = g_malloc( strlen( away ) + 1 ); 470 for( i = j = 0; away[i]; i ++ ) 471 if( ( u->away[j] = away[i] ) >= ' ' ) 566 472 j ++; 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 } 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; 577 549 } 578 550 579 551 static void irc_cmd_version( irc_t *irc, char **cmd ) 580 552 { 581 irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", 582 BITLBEE_VERSION, irc->root->host, ARCH, CPU ); 553 irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU ); 583 554 } 584 555 585 556 static void irc_cmd_completions( irc_t *irc, char **cmd ) 586 557 { 558 user_t *u = user_find( irc, irc->mynick ); 587 559 help_t *h; 588 560 set_t *s; 589 561 int i; 590 562 591 irc_ send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONSOK" );563 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" ); 592 564 593 565 for( i = 0; commands[i].command; i ++ ) 594 irc_ send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command );566 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command ); 595 567 596 568 for( h = global.help; h; h = h->next ) 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, "COMPLETIONSEND" );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" ); 603 575 } 604 576 … … 610 582 ipc_to_master( cmd ); 611 583 612 irc_ send_num( irc, 382, "%s :Rehashing", global.conf_file );584 irc_reply( irc, 382, "%s :Rehashing", global.conf_file ); 613 585 } 614 586 … … 619 591 { "quit", 0, irc_cmd_quit, 0 }, 620 592 { "ping", 0, irc_cmd_ping, 0 }, 621 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 593 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 594 { "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 }, 622 597 { "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 }, 628 { "mode", 1, irc_cmd_mode, IRC_CMD_LOGGED_IN }, 598 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 599 { "privmsg", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 600 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 629 601 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 630 { "privmsg", 1, irc_cmd_privmsg, 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 },636 602 { "userhost", 1, irc_cmd_userhost, IRC_CMD_LOGGED_IN }, 637 603 { "ison", 1, irc_cmd_ison, IRC_CMD_LOGGED_IN }, 638 604 { "watch", 1, irc_cmd_watch, IRC_CMD_LOGGED_IN }, 639 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN },640 #if 0641 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN },642 #endif643 605 { "topic", 1, irc_cmd_topic, IRC_CMD_LOGGED_IN }, 644 { "oper", 2, irc_cmd_oper, 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 }, 645 615 { "die", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 646 616 { "deaf", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, … … 668 638 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 669 639 { 670 irc_ send_num( irc, 462, ":Only allowed before logging in" );640 irc_reply( irc, 462, ":Only allowed before logging in" ); 671 641 } 672 642 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 673 643 { 674 irc_ send_num( irc, 451, ":Register first" );644 irc_reply( irc, 451, ":Register first" ); 675 645 } 676 646 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 677 647 { 678 irc_ send_num( irc, 481, ":Permission denied - You're not an IRC operator" );648 irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" ); 679 649 } 680 650 else if( n_arg < irc_commands[i].required_parameters ) 681 651 { 682 irc_ send_num( irc, 461, "%s :Need more parameters", cmd[0] );652 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 683 653 } 684 654 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) … … 697 667 698 668 if( irc->status >= USTATUS_LOGGED_IN ) 699 irc_ send_num( irc, 421, "%s :Unknown command", cmd[0] );700 } 669 irc_reply( irc, 421, "%s :Unknown command", cmd[0] ); 670 } -
lib/misc.c
rf1cea66 r560d0a0 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 else675 {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
rf1cea66 r560d0a0 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 73 71 #endif -
nick.c
rf1cea66 r560d0a0 78 78 79 79 nick_strip( nick ); 80 if( set_getbool( &acc-> bee->set, "lcnicks" ) )80 if( set_getbool( &acc->irc->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;95 94 int inf_protection = 256; 96 95 97 96 /* Now, find out if the nick is already in use at the moment, and make 98 97 subtle changes to make it unique. */ 99 while( !nick_ok( nick ) || irc_user_by_name(irc, nick ) )98 while( !nick_ok( nick ) || user_find( acc->irc, nick ) ) 100 99 { 101 100 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) … … 113 112 int i; 114 113 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 );114 irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! " 115 "This used to be a fatal BitlBee bug, but we tried to fix it. " 116 "This message should *never* appear anymore. " 117 "If it does, please *do* send us a bug report! " 118 "Please send all the following lines in your report:" ); 119 120 irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle ); 122 121 for( i = 0; i < MAX_NICK_LENGTH; i ++ ) 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" );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 "Good luck, and please don't forget to paste the lines up here " 126 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); 128 127 129 128 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); -
protocols/Makefile
rf1cea66 r560d0a0 13 13 14 14 # [SH] Program variables 15 objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o 16 15 objects = nogaim.o 17 16 18 17 # [SH] The next two lines should contain the directory name (in $(subdirs)) -
protocols/ft.h
rf1cea66 r560d0a0 107 107 */ 108 108 gpointer data; 109 struct im_connection *ic;110 109 111 110 /* … … 169 168 * the canceled() and free() callbacks given in file will be called by this function. 170 169 */ 171 void imcb_file_canceled( struct im_connection *ic,file_transfer_t *file, char *reason );170 void imcb_file_canceled( file_transfer_t *file, char *reason ); 172 171 173 gboolean imcb_file_recv_start( struct im_connection *ic,file_transfer_t *ft );172 gboolean imcb_file_recv_start( file_transfer_t *ft ); 174 173 175 void imcb_file_finished( struct im_connection *ic,file_transfer_t *file );174 void imcb_file_finished( file_transfer_t *file ); 176 175 #endif -
protocols/jabber/conference.c
rf1cea66 r560d0a0 92 92 { 93 93 char *normalized = jabber_normalize( name ); 94 GSList *l;95 94 struct groupchat *ret; 96 95 struct jabber_chat *jc; 97 96 98 for( l = ic->groupchats; l; l = l->next ) 99 { 100 ret = l->data; 97 for( ret = ic->groupchats; ret; ret = ret->next ) 98 { 101 99 jc = ret->data; 102 100 if( strcmp( normalized, jc->name ) == 0 ) … … 105 103 g_free( normalized ); 106 104 107 return l ? ret : NULL;105 return ret; 108 106 } 109 107 -
protocols/jabber/iq.c
rf1cea66 r560d0a0 382 382 while( ( c = xt_find_node( c, "item" ) ) ) 383 383 { 384 struct xt_node *group = xt_find_node( c->children, "group" );384 struct xt_node *group = xt_find_node( node->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 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 394 group->text : NULL ); 393 if( initial || imcb_find_buddy( ic, jid ) == NULL ) 394 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 395 group->text : NULL ); 395 396 396 397 if( name ) … … 588 589 strcmp( s, "result" ) == 0 ) 589 590 { 590 if( bee_user_by_handle( ic->bee,ic, jid ) == NULL )591 if( imcb_find_buddy( ic, jid ) == NULL ) 591 592 imcb_add_buddy( ic, jid, NULL ); 592 593 } -
protocols/jabber/jabber.c
rf1cea66 r560d0a0 267 267 268 268 while( jd->filetransfers ) 269 imcb_file_canceled( ic,( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );269 imcb_file_canceled( ( ( 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 ->data);284 jabber_chat_free( ic->groupchats ); 285 285 286 286 if( jd->r_inpa >= 0 ) -
protocols/jabber/jabber_util.c
rf1cea66 r560d0a0 279 279 presence_send_request( bla->ic, bla->handle, "subscribed" ); 280 280 281 imcb_ask_add( bla->ic, bla->handle, NULL ); 281 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 282 imcb_ask_add( bla->ic, bla->handle, NULL ); 282 283 283 284 g_free( bla->handle ); … … 461 462 462 463 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && 463 ( bare_exists || bee_user_by_handle( ic->bee,ic, jid ) ) )464 ( bare_exists || imcb_find_buddy( ic, jid ) ) ) 464 465 { 465 466 *s = '/'; … … 482 483 if( bud == NULL ) 483 484 /* No match. Create it now? */ 484 return ( ( flags & GET_BUDDY_CREAT ) && 485 bee_user_by_handle( ic->bee, ic, jid_ ) ) ? 485 return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? 486 486 jabber_buddy_add( ic, jid_ ) : NULL; 487 487 else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) -
protocols/jabber/presence.c
rf1cea66 r560d0a0 205 205 struct jabber_data *jd = ic->proto_data; 206 206 struct xt_node *node, *cap; 207 GSList *l;207 struct groupchat *c; 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( l = ic->groupchats; l && st; l = l->next ) 232 { 233 struct groupchat *c = l->data; 231 for( c = ic->groupchats; c && st; c = c->next ) 232 { 234 233 struct jabber_chat *jc = c->data; 235 234 -
protocols/jabber/s5bytestream.c
rf1cea66 r560d0a0 567 567 xt_free_node( reply ); 568 568 569 imcb_file_canceled( tf-> ic, tf->ft, "couldn't connect to any streamhosts" );569 imcb_file_canceled( 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-> ic, tf->ft, "Error transmitting bytestream response" );606 imcb_file_canceled( 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-> ic, tf->ft );646 imcb_file_finished( 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( tf->ic,ft, "BUG in jabber file transfer: write_request called when already watching for input" );662 imcb_file_canceled( 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( tf->ic,ft );708 imcb_file_finished( 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-> ic, tf->ft, "Error transmitting bytestream request" );1008 imcb_file_canceled( 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-> ic, tf->ft, error );1023 imcb_file_canceled( tf->ft, error ); 1024 1024 1025 1025 /* MUST always return FALSE! */ -
protocols/jabber/si.c
rf1cea66 r560d0a0 91 91 92 92 if( !foundft ) 93 imcb_file_canceled( tf-> ic, tf->ft, "Buddy's client doesn't feature file transfers" );93 imcb_file_canceled( tf->ft, "Buddy's client doesn't feature file transfers" ); 94 94 else if( !foundbt ) 95 imcb_file_canceled( tf-> ic, tf->ft, "Buddy's client doesn't feature byte streams (required)" );95 imcb_file_canceled( tf->ft, "Buddy's client doesn't feature byte streams (required)" ); 96 96 else if( !foundsi ) 97 imcb_file_canceled( tf-> ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)" );97 imcb_file_canceled( 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-> ic, tf->ft );111 imcb_file_recv_start( tf->ft ); 112 112 113 113 } … … 156 156 if( bud == NULL ) 157 157 { 158 imcb_file_canceled( ic,ft, "Couldn't find buddy (BUG?)" );158 imcb_file_canceled( ft, "Couldn't find buddy (BUG?)" ); 159 159 return; 160 160 } -
protocols/msn/Makefile
rf1cea66 r560d0a0 13 13 14 14 # [SH] Program variables 15 objects = msn.o msn_util.o ns.o passport.o sb.o tables.o15 objects = invitation.o msn.o msn_util.o ns.o passport.o sb.o tables.o 16 16 17 17 CFLAGS += -Wall -
protocols/msn/msn.c
rf1cea66 r560d0a0 79 79 if( md ) 80 80 { 81 /** Disabling MSN ft support for now.82 81 while( md->filetransfers ) { 83 82 imcb_file_canceled( md->filetransfers->data, "Closing connection" ); 84 83 } 85 */86 84 87 85 if( md->fd >= 0 ) … … 223 221 { 224 222 struct msn_switchboard *sb; 225 struct groupchat *c = imcb_chat_new( ic, who );226 223 227 224 if( ( sb = msn_sb_by_handle( ic, who ) ) ) … … 241 238 msn_sb_write_msg( ic, m ); 242 239 243 return c; 244 } 240 return NULL; 241 } 242 243 return NULL; 245 244 } 246 245 … … 333 332 ret->send_typing = msn_send_typing; 334 333 ret->handle_cmp = g_strcasecmp; 335 //ret->transfer_request = msn_ftp_transfer_request;334 ret->transfer_request = msn_ftp_transfer_request; 336 335 337 336 register_protocol(ret); -
protocols/msn/msn_util.c
rf1cea66 r560d0a0 96 96 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); 97 97 98 imcb_ask_add( bla->ic, bla->handle, NULL ); 98 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 99 imcb_ask_add( bla->ic, bla->handle, NULL ); 99 100 100 101 g_free( bla->handle ); -
protocols/msn/sb.c
rf1cea66 r560d0a0 175 175 i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user ); 176 176 } 177 else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 ) 178 { 179 buf = g_strdup( text ); 180 i = strlen( buf ); 181 } 177 182 else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 ) 178 183 { 179 184 buf = g_strdup( SB_KEEPALIVE_HEADERS ); 180 i = strlen( buf );181 }182 else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )183 {184 buf = g_strdup( text );185 185 i = strlen( buf ); 186 186 } … … 233 233 { 234 234 struct im_connection *ic = sb->ic; 235 struct groupchat *c = NULL;236 235 char buf[1024]; 237 236 238 237 /* Create the groupchat structure. */ 239 238 g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); 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 ); 239 sb->chat = imcb_chat_new( ic, buf ); 246 240 247 241 /* Populate the channel. */ … … 704 698 } 705 699 } 706 #if 0707 // Disable MSN ft support for now.708 700 else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 ) 709 701 { … … 738 730 g_free( command ); 739 731 } 740 #endif741 732 else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) 742 733 { … … 774 765 void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ) 775 766 { 776 bee_user_t *bu;767 struct buddy *b; 777 768 778 769 if( sb && sb->who && sb->keepalive == 0 && 779 ( bu = bee_user_by_handle( sb->ic->bee, sb->ic, sb->who ) ) && 780 !( bu->flags & BEE_USER_ONLINE ) && 770 ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present && 781 771 set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) ) 782 772 { -
protocols/nogaim.c
rf1cea66 r560d0a0 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 40 43 GSList *connections; 41 44 … … 89 92 } 90 93 #endif 94 95 /* nogaim.c */ 91 96 92 97 GList *protocols = NULL; … … 124 129 } 125 130 131 /* nogaim.c */ 126 132 void nogaim_init() 127 133 { … … 152 158 twitter_initmodule(); 153 159 #endif 154 160 155 161 #ifdef WITH_PURPLE 156 162 purple_initmodule(); … … 164 170 GSList *get_connections() { return connections; } 165 171 172 /* multi.c */ 173 166 174 struct im_connection *imcb_new( account_t *acc ) 167 175 { … … 170 178 ic = g_new0( struct im_connection, 1 ); 171 179 172 ic-> bee = acc->bee;180 ic->irc = acc->irc; 173 181 ic->acc = acc; 174 182 acc->ic = ic; … … 184 192 185 193 /* Destroy the pointer to this connection from the account list */ 186 for( a = ic-> bee->accounts; a; a = a->next )194 for( a = ic->irc->accounts; a; a = a->next ) 187 195 if( a->ic == ic ) 188 196 { … … 205 213 va_end( params ); 206 214 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" ) ) )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" ) ) ) 209 217 strip_html( text ); 210 218 211 219 /* Try to find a different connection on the same protocol. */ 212 for( a = ic-> bee->accounts; a; a = a->next )220 for( a = ic->irc->accounts; a; a = a->next ) 213 221 if( a->prpl == ic->acc->prpl && a->ic != ic ) 214 222 break; … … 216 224 /* If we found one, include the screenname in the message. */ 217 225 if( a ) 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 ); 226 irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 220 227 else 221 irc_usermsg( ic-> bee->ui_data, "%s - %s", ic->acc->prpl->name, text );228 irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text ); 222 229 223 230 g_free( text ); … … 270 277 void imcb_connected( struct im_connection *ic ) 271 278 { 279 irc_t *irc = ic->irc; 280 struct chat *c; 281 user_t *u; 282 272 283 /* MSN servers sometimes redirect you to a different server and do 273 284 the whole login sequence again, so these "late" calls to this … … 276 287 return; 277 288 289 u = user_find( ic->irc, ic->irc->nick ); 290 278 291 imcb_log( ic, "Logged in" ); 279 292 … … 288 301 ic->acc->auto_reconnect_delay = 0; 289 302 290 /*291 303 for( c = irc->chatrooms; c; c = c->next ) 292 304 { … … 297 309 chat_join( irc, c, NULL ); 298 310 } 299 */300 311 } 301 312 … … 305 316 306 317 a->reconnect = 0; 307 account_on( a-> bee, a );318 account_on( a->irc, a ); 308 319 309 320 return( FALSE ); /* Only have to run the timeout once */ … … 318 329 void imc_logout( struct im_connection *ic, int allow_reconnect ) 319 330 { 320 bee_t *bee = ic->bee; 331 irc_t *irc = ic->irc; 332 user_t *t, *u; 321 333 account_t *a; 322 GSList *l;323 334 int delay; 324 335 … … 340 351 ic->away = NULL; 341 352 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 ) 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 ) 356 369 if( a->ic == ic ) 357 370 break; … … 361 374 /* Uhm... This is very sick. */ 362 375 } 363 else if( allow_reconnect && set_getbool( & bee->set, "auto_reconnect" ) &&376 else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) && 364 377 set_getbool( &a->set, "auto_reconnect" ) && 365 378 ( delay = account_reconnect_delay( a ) ) > 0 ) … … 372 385 } 373 386 387 388 /* dialogs.c */ 389 374 390 void imcb_ask( struct im_connection *ic, char *msg, void *data, 375 391 query_callback doit, query_callback dont ) 376 392 { 377 query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data ); 378 } 393 query_add( ic->irc, ic, msg, doit, dont, data ); 394 } 395 396 397 /* list.c */ 379 398 380 399 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) 381 400 { 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 ); 405 406 if( bee->ui->user_fullname ) 407 bee->ui->user_fullname( bee, bu ); 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 ); 409 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 ); 408 505 } 409 506 } … … 411 508 void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) 412 509 { 413 bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) ); 510 user_t *u; 511 512 if( ( u = user_findhandle( ic, handle ) ) ) 513 user_del( ic->irc, u->nick ); 414 514 } 415 515 … … 418 518 void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) 419 519 { 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 ); 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 } 427 551 } 428 552 … … 469 593 data->ic = ic; 470 594 data->handle = g_strdup( handle ); 471 query_add( (irc_t *) ic->bee->ui_data, ic, s, 472 imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 595 query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 473 596 } 474 597 … … 495 618 496 619 /* TODO: Make a setting for this! */ 497 if( bee_user_by_handle( ic->bee,ic, handle ) != NULL )620 if( user_findhandle( ic, handle ) != NULL ) 498 621 return; 499 622 … … 502 625 data->ic = ic; 503 626 data->handle = g_strdup( handle ); 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 ); 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 ); 511 1264 } 512 1265 513 1266 /* The plan is to not allow straight calls to prpl functions anymore, but do 514 1267 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 } 515 1285 516 1286 int imc_chat_msg( struct groupchat *c, char *msg, int flags ) … … 541 1311 542 1312 away = set_getstr( &ic->acc->set, "away" ) ? 543 : set_getstr( &ic-> bee->set, "away" );1313 : set_getstr( &ic->irc->set, "away" ); 544 1314 if( away && *away ) 545 1315 { … … 552 1322 away = NULL; 553 1323 msg = set_getstr( &ic->acc->set, "status" ) ? 554 : set_getstr( &ic-> bee->set, "status" );1324 : set_getstr( &ic->irc->set, "status" ); 555 1325 } 556 1326 -
protocols/nogaim.h
rf1cea66 r560d0a0 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 87 87 88 88 /* BitlBee */ 89 bee_t *bee;90 91 GSList *groupchats;89 irc_t *irc; 90 91 struct groupchat *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; 102 GList *ignored; 103 104 struct groupchat *next; 105 char *channel; 105 106 /* The title variable contains the ID you gave when you created the 106 107 * chat using imcb_chat_new(). */ … … 113 114 * structure for your protocol's needs. */ 114 115 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 ); 289 298 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 );291 299 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); 292 300 … … 314 322 /* Actions, or whatever. */ 315 323 int imc_away_send_update( struct im_connection *ic ); 324 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); 316 325 int imc_chat_msg( struct groupchat *c, char *msg, int flags ); 317 326 -
protocols/oscar/oscar.c
rf1cea66 r560d0a0 254 254 255 255 u = t = g_strdup(s); 256 257 strcpy(t, s); 256 258 g_strdown(t); 257 259 … … 650 652 struct im_connection *ic = sess->aux_data; 651 653 struct chat_connection *chatcon; 652 struct groupchat *c = NULL;653 654 static int id = 1; 654 655 … … 663 664 chatcon = find_oscar_chat_by_conn(ic, fr->conn); 664 665 chatcon->id = id; 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); 666 chatcon->cnv = imcb_chat_new(ic, chatcon->show); 671 667 chatcon->cnv->data = chatcon; 672 668 … … 938 934 tmp = normalize(info->sn); 939 935 imcb_buddy_status(ic, tmp, flags, state_string, NULL); 940 imcb_buddy_times(ic, tmp, signon, time_idle);936 /* imcb_buddy_times(ic, tmp, signon, time_idle); */ 941 937 942 938 … … 1064 1060 aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); 1065 1061 // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); 1066 imcb_ask_add(data->ic, uin, NULL); 1062 if(imcb_find_buddy(data->ic, uin) == NULL) 1063 imcb_ask_add(data->ic, uin, NULL); 1067 1064 1068 1065 g_free(uin); … … 1825 1822 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 1826 1823 if (odata->icq) { 1827 /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back?1828 1824 struct buddy *budlight = imcb_find_buddy(g, who); 1829 1825 if (budlight) … … 1831 1827 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) 1832 1828 aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7); 1833 */1834 1829 } else 1835 1830 aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); … … 1958 1953 static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { 1959 1954 struct im_connection *ic = sess->aux_data; 1960 struct aim_ssi_item *curitem , *curgroup;1955 struct aim_ssi_item *curitem; 1961 1956 int tmp; 1962 1957 char *nrm; … … 1969 1964 switch (curitem->type) { 1970 1965 case 0x0000: /* Buddy */ 1971 if ((curitem->name) && (!imcb_ buddy_by_handle(ic, nrm))) {1966 if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) { 1972 1967 char *realname = NULL; 1973 1968 1974 1969 if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) 1975 1970 realname = aim_gettlv_str(curitem->data, 0x0131, 1); 1976 1977 imcb_add_buddy(ic, nrm, curgroup->gid == curitem->gid ? curgroup->name :NULL);1971 1972 imcb_add_buddy(ic, nrm, NULL); 1978 1973 1979 1974 if (realname) { … … 1983 1978 } 1984 1979 } 1985 break;1986 1987 case 0x0001: /* Group */1988 curgroup = curitem;1989 1980 break; 1990 1981 … … 2529 2520 static int chat_id = 0; 2530 2521 char * chatname; 2531 struct groupchat *c;2532 2522 2533 2523 chatname = g_strdup_printf("%s%s_%d", isdigit(*ic->acc->user) ? "icq_" : "", 2534 2524 ic->acc->user, chat_id++); 2535 2536 c = imcb_chat_new(ic, chatname); 2525 2537 2526 ret = oscar_chat_join(ic, chatname, NULL, NULL); 2527 2538 2528 aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0); 2539 2529 -
protocols/purple/ft.c
rf1cea66 r560d0a0 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 );78 77 79 78 purple_xfer_set_local_filename( xfer, px->fn ); … … 144 143 { 145 144 purple_xfer_cancel_local( px->xfer ); 146 imcb_file_canceled( px->ic,ft, "Read error" );145 imcb_file_canceled( ft, "Read error" ); 147 146 } 148 147 } … … 151 150 { 152 151 /*purple_xfer_end( px->xfer );*/ 153 imcb_file_finished( px->ic,ft );152 imcb_file_finished( ft ); 154 153 } 155 154 … … 231 230 232 231 if( px->ft ) 233 imcb_file_canceled( px-> ic, px->ft, "Canceled by remote end" );232 imcb_file_canceled( px->ft, "Canceled by remote end" ); 234 233 else 235 234 /* px->ft == NULL for sends, because of the two stages. :-/ */ … … 302 301 { 303 302 file_transfer_t *ft = data; 304 struct prpl_xfer_data *px = ft->data;305 303 306 304 if( ft->write == NULL ) 307 305 { 308 306 ft->write = prpl_xfer_write; 309 imcb_file_recv_start( px->ic,ft );307 imcb_file_recv_start( ft ); 310 308 } 311 309 … … 321 319 if( write( px->fd, buffer, len ) != len ) 322 320 { 323 imcb_file_canceled( px->ic,ft, "Error while writing temporary file" );321 imcb_file_canceled( ft, "Error while writing temporary file" ); 324 322 return FALSE; 325 323 } … … 331 329 332 330 purple_transfer_forward( ft ); 333 imcb_file_finished( px->ic,ft );331 imcb_file_finished( ft ); 334 332 px->ft = NULL; 335 333 } -
protocols/purple/purple.c
rf1cea66 r560d0a0 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 bee_t *local_bee;37 static irc_t *local_irc; 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 when160 this becomes important.161 159 irc_usermsg( acc->irc, "Setting with unknown type: %s (%d) Expect stuff to break..\n", 162 160 name, purple_account_option_get_type( o ) ); 163 */164 161 name = NULL; 165 162 } … … 254 251 PurpleAccount *pa; 255 252 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 ); 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." ); 261 257 return; 262 258 } 263 local_ bee = acc->bee;259 local_irc = acc->irc; 264 260 265 261 /* For now this is needed in the _connected() handlers if using … … 687 683 imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ), 688 684 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 ) );693 685 } 694 686 } … … 874 866 pqad->user_data = user_data; 875 867 876 /* TODO: IRC stuff here :-( */877 868 q = g_strdup_printf( "Request: %s\n\n%s\n\n%s", title, primary, secondary ); 878 pqad->bee_data = query_add( local_ bee->ui_data, purple_ic_by_pa( account ), q,869 pqad->bee_data = query_add( local_irc, purple_ic_by_pa( account ), q, 879 870 prplcb_request_action_yes, prplcb_request_action_no, pqad ); 880 871 -
protocols/twitter/twitter_lib.c
rf1cea66 r560d0a0 103 103 104 104 // Check if the buddy is allready in the buddy list. 105 if (! bee_user_by_handle( ic->bee,ic, name ))105 if (!imcb_find_buddy( ic, name )) 106 106 { 107 107 char *mode = set_getstr(&ic->acc->set, "mode"); -
protocols/yahoo/yahoo.c
rf1cea66 r560d0a0 158 158 159 159 while( ic->groupchats ) 160 imcb_chat_free( ic->groupchats ->data);160 imcb_chat_free( ic->groupchats ); 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... 615 616 if( stat == YAHOO_STATUS_IDLE ) 616 imcb_buddy_times( ic, who, 0, idle ); 617 imcb_buddy_times( ic, who, 0, away ); 618 */ 617 619 } 618 620 … … 794 796 struct byahoo_conf_invitation *inv = data; 795 797 struct groupchat *b; 796 GSList *l; 797 798 for( l = inv->ic->groupchats; l; l = l->next ) 799 { 800 b = l->data; 798 799 for( b = inv->ic->groupchats; b; b = b->next ) 801 800 if( b == inv->c ) 802 801 break; 803 }804 802 805 803 if( b != NULL ) … … 867 865 { 868 866 struct im_connection *ic = byahoo_get_ic_by_id( id ); 869 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 867 struct groupchat *c; 868 869 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 870 870 871 871 if( c ) … … 877 877 { 878 878 struct im_connection *ic = byahoo_get_ic_by_id( id ); 879 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 879 struct groupchat *c; 880 881 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 880 882 881 883 if( c ) … … 887 889 struct im_connection *ic = byahoo_get_ic_by_id( id ); 888 890 char *m = byahoo_strip( msg ); 889 struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); 891 struct groupchat *c; 892 893 for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); 890 894 891 895 if( c ) -
query.c
rf1cea66 r560d0a0 64 64 } 65 65 66 if( g_strcasecmp( set_getstr( &irc-> b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )66 if( g_strcasecmp( set_getstr( &irc->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-> b->set, "query_order" ), "fifo" ) == 0 )181 if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 ) 182 182 q = irc->queries; 183 183 else -
root_commands.c
rf1cea66 r560d0a0 32 32 #include <string.h> 33 33 34 void root_command_string( irc_t *irc, char *command ) 35 { 36 root_command( irc, split_command_parts( command ) ); 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 ); 37 78 } 38 79 … … 51 92 void root_command( irc_t *irc, char *cmd[] ) 52 93 { 53 int i , len;94 int i; 54 95 55 96 if( !cmd[0] ) 56 97 return; 57 98 58 len = strlen( cmd[0] );59 99 for( i = 0; commands[i].command; i++ ) 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 100 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) 101 { 67 102 MIN_ARGS( commands[i].required_parameters ); 68 103 … … 105 140 static void cmd_identify( irc_t *irc, char **cmd ) 106 141 { 107 storage_status_t status ;142 storage_status_t status = storage_load( irc, cmd[1] ); 108 143 char *account_on[] = { "account", "on", NULL }; 109 gboolean load = TRUE; 110 char *password = cmd[1]; 111 112 if( irc->status & USTATUS_IDENTIFIED ) 144 145 if( strchr( irc->umode, 'R' ) != NULL ) 113 146 { 114 147 irc_usermsg( irc, "You're already logged in." ); 115 148 return; 116 149 } 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 else145 status = storage_check_pass( irc->user->nick, password );146 150 147 151 switch (status) { … … 153 157 break; 154 158 case STORAGE_OK: 155 irc_usermsg( irc, "Password accepted%s", 156 load ? ", settings and accounts loaded" : "" ); 157 irc_setpass( irc, password ); 159 irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); 160 irc_setpass( irc, cmd[1] ); 158 161 irc->status |= USTATUS_IDENTIFIED; 159 162 irc_umode_set( irc, "+R", 1 ); 160 if( load && set_getbool( &irc->b->set, "auto_connect" ) )163 if( set_getbool( &irc->set, "auto_connect" ) ) 161 164 cmd_account( irc, account_on ); 162 165 break; … … 198 201 storage_status_t status; 199 202 200 status = storage_remove (irc-> user->nick, cmd[1]);203 status = storage_remove (irc->nick, cmd[1]); 201 204 switch (status) { 202 205 case STORAGE_NO_SUCH_USER: … … 210 213 irc->status &= ~USTATUS_IDENTIFIED; 211 214 irc_umode_set( irc, "-R", 1 ); 212 irc_usermsg( irc, "Account `%s' removed", irc-> user->nick );215 irc_usermsg( irc, "Account `%s' removed", irc->nick ); 213 216 break; 214 217 default: … … 218 221 } 219 222 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!" ); 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 ); 228 255 } 229 256 … … 258 285 set_name = set_full; 259 286 260 head = &irc-> b->set;287 head = &irc->set; 261 288 } 262 289 else … … 329 356 account_t *a; 330 357 331 if( ( a = account_get( irc ->b, id ) ) )358 if( ( a = account_get( irc, id ) ) ) 332 359 return &a->set; 333 360 else … … 377 404 } 378 405 379 a = account_add( irc ->b, prpl, cmd[3], cmd[4] );406 a = account_add( irc, prpl, cmd[3], cmd[4] ); 380 407 if( cmd[5] ) 381 408 { … … 391 418 MIN_ARGS( 2 ); 392 419 393 if( !( a = account_get( irc ->b, cmd[2] ) ) )420 if( !( a = account_get( irc, cmd[2] ) ) ) 394 421 { 395 422 irc_usermsg( irc, "Invalid account" ); … … 401 428 else 402 429 { 403 account_del( irc->b, a ); 404 irc_usermsg( irc, "Account deleted" ); 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 ); 405 444 } 406 445 } … … 412 451 irc_usermsg( irc, "Account list:" ); 413 452 414 for( a = irc-> b->accounts; a; a = a->next )453 for( a = irc->accounts; a; a = a->next ) 415 454 { 416 455 char *con; … … 435 474 if( cmd[2] ) 436 475 { 437 if( ( a = account_get( irc ->b, cmd[2] ) ) )476 if( ( a = account_get( irc, cmd[2] ) ) ) 438 477 { 439 478 if( a->ic ) … … 444 483 else 445 484 { 446 account_on( irc ->b, a );485 account_on( irc, a ); 447 486 } 448 487 } … … 455 494 else 456 495 { 457 if ( irc->b->accounts ) 458 { 496 if ( irc->accounts ) { 459 497 irc_usermsg( irc, "Trying to get all accounts connected..." ); 460 498 461 for( a = irc-> b->accounts; a; a = a->next )499 for( a = irc->accounts; a; a = a->next ) 462 500 if( !a->ic && a->auto_connect ) 463 account_on( irc ->b, a );501 account_on( irc, a ); 464 502 } 465 503 else … … 475 513 irc_usermsg( irc, "Deactivating all active (re)connections..." ); 476 514 477 for( a = irc-> b->accounts; a; a = a->next )515 for( a = irc->accounts; a; a = a->next ) 478 516 { 479 517 if( a->ic ) 480 account_off( irc ->b, a );518 account_off( irc, a ); 481 519 else if( a->reconnect ) 482 520 cancel_auto_reconnect( a ); 483 521 } 484 522 } 485 else if( ( a = account_get( irc ->b, cmd[2] ) ) )523 else if( ( a = account_get( irc, cmd[2] ) ) ) 486 524 { 487 525 if( a->ic ) 488 526 { 489 account_off( irc ->b, a );527 account_off( irc, a ); 490 528 } 491 529 else if( a->reconnect ) … … 515 553 { 516 554 irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[1] ); 517 }518 }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 else527 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 else572 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 else577 {578 irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] );579 555 } 580 556 } … … 592 568 } 593 569 594 if( !( a = account_get( irc ->b, cmd[1] ) ) )570 if( !( a = account_get( irc, cmd[1] ) ) ) 595 571 { 596 572 irc_usermsg( irc, "Invalid account" ); … … 610 586 return; 611 587 } 612 else if( irc_user_by_name( irc, cmd[3] ) )588 else if( user_find( irc, cmd[3] ) ) 613 589 { 614 590 irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); … … 624 600 a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); 625 601 else 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 ); 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 ); 629 606 630 607 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;654 608 } 655 609 … … 661 615 if( !cmd[2] ) 662 616 { 663 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );664 if( ! iu || !iu->bu)617 user_t *u = user_find( irc, cmd[1] ); 618 if( !u || !u->ic ) 665 619 { 666 620 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 667 621 return; 668 622 } 669 ic = iu->bu->ic;670 cmd[2] = iu->bu->handle;671 } 672 else if( !( a = account_get( irc ->b, cmd[1] ) ) )623 ic = u->ic; 624 cmd[2] = u->handle; 625 } 626 else if( !( a = account_get( irc, cmd[1] ) ) ) 673 627 { 674 628 irc_usermsg( irc, "Invalid account" ); … … 693 647 static void cmd_rename( irc_t *irc, char **cmd ) 694 648 { 695 irc_user_t *iu; 696 697 iu = irc_user_by_name( irc, cmd[1] ); 698 699 if( iu == NULL ) 649 user_t *u; 650 651 if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) 652 { 653 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 654 } 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 ) ) 671 { 672 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 673 } 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] ) ) ) 700 679 { 701 680 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 702 681 } 703 else if( iu == irc->user ) 704 { 705 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 706 } 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] ) ) 712 { 713 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 714 } 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 { 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 725 691 /* If we're called internally (user did "set root_nick"), 726 692 let's not go O(INF). :-) */ 727 693 if( strcmp( cmd[0], "set_rename" ) != 0 ) 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] );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] ); 733 699 } 734 700 … … 741 707 irc_t *irc = set->data; 742 708 743 if( strcmp( irc-> root->nick, new_nick ) != 0 )744 { 745 char *cmd[] = { "set_rename", irc-> root->nick, new_nick, NULL };709 if( strcmp( irc->mynick, new_nick ) != 0 ) 710 { 711 char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL }; 746 712 747 713 cmd_rename( irc, cmd ); 748 714 } 749 715 750 return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID; 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; 751 753 } 752 754 … … 756 758 account_t *a; 757 759 758 if( !cmd[2] && ( a = account_get( irc ->b, cmd[1] ) ) && a->ic )760 if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic ) 759 761 { 760 762 char *format; … … 769 771 for( l = a->ic->deny; l; l = l->next ) 770 772 { 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)" ); 773 user_t *u = user_findhandle( a->ic, l->data ); 774 irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); 774 775 } 775 776 irc_usermsg( irc, "End of list." ); … … 779 780 else if( !cmd[2] ) 780 781 { 781 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );782 if( ! iu || !iu->bu)782 user_t *u = user_find( irc, cmd[1] ); 783 if( !u || !u->ic ) 783 784 { 784 785 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 785 786 return; 786 787 } 787 ic = iu->bu->ic;788 cmd[2] = iu->bu->handle;789 } 790 else if( !( a = account_get( irc ->b, cmd[1] ) ) )788 ic = u->ic; 789 cmd[2] = u->handle; 790 } 791 else if( !( a = account_get( irc, cmd[1] ) ) ) 791 792 { 792 793 irc_usermsg( irc, "Invalid account" ); … … 816 817 account_t *a; 817 818 818 if( !cmd[2] && ( a = account_get( irc ->b, cmd[1] ) ) && a->ic )819 if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic ) 819 820 { 820 821 char *format; … … 829 830 for( l = a->ic->permit; l; l = l->next ) 830 831 { 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)" ); 832 user_t *u = user_findhandle( a->ic, l->data ); 833 irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); 834 834 } 835 835 irc_usermsg( irc, "End of list." ); … … 839 839 else if( !cmd[2] ) 840 840 { 841 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );842 if( ! iu || !iu->bu)841 user_t *u = user_find( irc, cmd[1] ); 842 if( !u || !u->ic ) 843 843 { 844 844 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 845 845 return; 846 846 } 847 ic = iu->bu->ic;848 cmd[2] = iu->bu->handle;849 } 850 else if( !( a = account_get( irc ->b, cmd[1] ) ) )847 ic = u->ic; 848 cmd[2] = u->handle; 849 } 850 else if( !( a = account_get( irc, 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 else 924 irc_usermsg( irc, "Configuration could not be saved!" ); 925 } 926 917 927 static void cmd_blist( irc_t *irc, char **cmd ) 918 928 { 919 929 int online = 0, away = 0, offline = 0; 920 GSList *l;930 user_t *u; 921 931 char s[256]; 922 932 char *format; … … 939 949 format = "%-16.16s %-40.40s %s"; 940 950 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 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 { 951 955 if( online == 1 ) 952 956 { 953 957 char st[256] = "Online"; 954 958 955 if( bu->status_msg )956 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg );957 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 );959 if( u->status_msg ) 960 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg ); 961 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 ); 960 964 } 961 965 … … 963 967 } 964 968 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 969 for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away ) 970 { 973 971 if( away == 1 ) 974 972 { 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 ));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 ); 977 975 } 978 976 n_away ++; 979 977 } 980 978 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 979 for( u = irc->users; u; u = u->next ) if( u->ic && !u->online ) 980 { 989 981 if( offline == 1 ) 990 982 { 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" );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" ); 993 985 } 994 986 n_offline ++; … … 996 988 997 989 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 else 1013 { 1014 irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); 1015 1016 a->prpl->set_my_name( a->ic, cmd[2] ); 1017 } 998 1018 } 999 1019 … … 1018 1038 } 1019 1039 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 else 1053 return NULL; 1054 } 1055 1020 1056 static void cmd_chat( irc_t *irc, char **cmd ) 1021 1057 { 1022 1058 account_t *acc; 1059 struct chat *c; 1023 1060 1024 1061 if( g_strcasecmp( cmd[1], "add" ) == 0 ) 1025 1062 { 1026 1063 char *channel, *s; 1027 struct irc_channel *ic;1028 1064 1029 1065 MIN_ARGS( 3 ); 1030 1066 1031 if( !( acc = account_get( irc ->b, cmd[2] ) ) )1067 if( !( acc = account_get( irc, cmd[2] ) ) ) 1032 1068 { 1033 1069 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." );1039 1070 return; 1040 1071 } … … 1053 1084 if( strchr( CTYPES, channel[0] ) == NULL ) 1054 1085 { 1055 s = g_strdup_printf( " #%s", channel );1086 s = g_strdup_printf( "%c%s", CTYPES[0], channel ); 1056 1087 g_free( channel ); 1057 1088 channel = s; 1058 1089 } 1059 1090 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 1091 if( ( c = chat_add( irc, acc, cmd[3], channel ) ) ) 1092 irc_usermsg( irc, "Chatroom added successfully." ); 1093 else 1072 1094 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 { 1116 MIN_ARGS( 2 ); 1117 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." ); 1073 1131 } 1074 1132 } 1075 1133 else if( g_strcasecmp( cmd[1], "with" ) == 0 ) 1076 1134 { 1077 irc_user_t *iu;1135 user_t *u; 1078 1136 1079 1137 MIN_ARGS( 2 ); 1080 1138 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 ) ) 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 ) ) 1085 1142 { 1086 1143 irc_usermsg( irc, "(Possible) failure while trying to open " 1087 "a groupchat with %s.", iu->nick );1144 "a groupchat with %s.", u->nick ); 1088 1145 } 1089 1146 } … … 1147 1204 { 1148 1205 irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name ); 1149 imcb_file_canceled( file ->ic, file, "Denied by user" );1206 imcb_file_canceled( file, "Denied by user" ); 1150 1207 } 1151 1208 break; … … 1154 1211 { 1155 1212 irc_usermsg( irc, "Canceling file transfer for %s", file->file_name ); 1156 imcb_file_canceled( file ->ic, file, "Canceled by user" );1213 imcb_file_canceled( file, "Canceled by user" ); 1157 1214 } 1158 1215 break; … … 1161 1218 } 1162 1219 1163 /* IMPORTANT: Keep this list sorted! The short command logic needs that. */1164 1220 const command_t commands[] = { 1221 { "help", 0, cmd_help, 0 }, 1222 { "identify", 1, cmd_identify, 0 }, 1223 { "register", 1, cmd_register, 0 }, 1224 { "drop", 1, cmd_drop, 0 }, 1165 1225 { "account", 1, cmd_account, 0 }, 1166 1226 { "add", 2, cmd_add, 0 }, 1227 { "info", 1, cmd_info, 0 }, 1228 { "rename", 2, cmd_rename, 0 }, 1229 { "remove", 1, cmd_remove, 0 }, 1230 { "block", 1, cmd_block, 0 }, 1167 1231 { "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 },1174 { "help", 0, cmd_help, 0 },1175 { "identify", 1, cmd_identify, 0 },1176 { "info", 1, cmd_info, 0 },1177 { "no", 0, cmd_yesno, 0 },1178 { "qlist", 0, cmd_qlist, 0 },1179 { "register", 1, cmd_register, 0 },1180 { "remove", 1, cmd_remove, 0 },1181 { "rename", 2, cmd_rename, 0 },1182 1232 { "save", 0, cmd_save, 0 }, 1183 1233 { "set", 0, cmd_set, 0 }, 1234 { "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 }, 1184 1241 { "transfer", 0, cmd_transfer, 0 }, 1185 { "yes", 0, cmd_yesno, 0 },1186 1242 { NULL } 1187 1243 }; -
set.c
rf1cea66 r560d0a0 69 69 while( s ) 70 70 { 71 if( g_strcasecmp( s->key, key ) == 0 || 72 ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) ) 71 if( g_strcasecmp( s->key, key ) == 0 ) 73 72 break; 74 73 s = s->next; … … 177 176 178 177 g_free( s->key ); 179 g_free( s->old_key ); 180 g_free( s->value ); 181 g_free( s->def ); 178 if( s->value ) g_free( s->value ); 179 if( s->def ) g_free( s->def ); 182 180 g_free( s ); 183 181 } … … 242 240 } 243 241 244 /*245 242 char *set_eval_ops( set_t *set, char *value ) 246 243 { … … 264 261 return value; 265 262 } 266 */ -
set.h
rf1cea66 r560d0a0 54 54 55 55 char *key; 56 char *old_key; /* Previously known as; for smooth upgrades. */57 56 char *value; 58 57 char *def; /* Default value. If the set_setstr() function -
storage_xml.c
rf1cea66 r560d0a0 147 147 arc_decode( pass_cr, pass_len, &password, xd->given_pass ) ) 148 148 { 149 xd->current_account = account_add( irc ->b, prpl, handle, password );149 xd->current_account = account_add( irc, 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-> b->set;183 xd->current_set_head = &xd->irc->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-> user->nick, password, XML_PASS_UNKNOWN );355 return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN ); 356 356 } 357 357 … … 396 396 md5_state_t md5_state; 397 397 398 path2 = g_strdup( irc-> user->nick );398 path2 = g_strdup( irc->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-> user->nick, pass_buf, XML_FORMAT_VERSION ) )424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->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-> b->set; set; set = set->next )429 for( set = irc->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-> b->accounts; acc; acc = acc->next )434 for( acc = irc->accounts; acc; acc = acc->next ) 435 435 { 436 436 unsigned char *pass_cr; … … 470 470 goto write_error; 471 471 472 #if 0473 472 for( c = irc->chatrooms; c; c = c->next ) 474 473 { … … 489 488 goto write_error; 490 489 } 491 #endif492 490 493 491 if( !xml_printf( fd, 1, "</account>\n" ) )
Note: See TracChangeset
for help on using the changeset viewer.