Changes in / [156bbd7:21c87a7]
- Files:
-
- 22 added
- 9 deleted
- 34 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r156bbd7 r21c87a7 10 10 11 11 # Program variables 12 objects = account.o bitlbee.o chat.o crypting.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 config.h crypting.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/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/nogaim.h 12 #objects = chat.o 13 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) 14 headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h 14 15 subdirs = lib protocols 15 16 -
bitlbee.h
r156bbd7 r21c87a7 126 126 #define CONF_FILE_DEF ETCDIR "bitlbee.conf" 127 127 128 #include "bee.h" 128 129 #include "irc.h" 129 130 #include "storage.h" … … 160 161 gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); 161 162 162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags);163 void root_command_string( irc_t *irc, char *command ); 163 164 void root_command( irc_t *irc, char *command[] ); 164 165 gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); -
conf.c
r156bbd7 r21c87a7 63 63 conf->ping_timeout = 300; 64 64 conf->user = NULL; 65 conf->ft_max_size = SIZE_MAX; 66 conf->ft_max_kbps = G_MAXUINT; 67 conf->ft_listen = NULL; 65 68 conf->protocols = NULL; 66 69 proxytype = 0; … … 315 318 conf->user = g_strdup( ini->value ); 316 319 } 320 else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 ) 321 { 322 size_t ft_max_size; 323 if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 ) 324 { 325 fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); 326 return 0; 327 } 328 conf->ft_max_size = ft_max_size; 329 } 330 else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 ) 331 { 332 if( sscanf( ini->value, "%d", &i ) != 1 ) 333 { 334 fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); 335 return 0; 336 } 337 conf->ft_max_kbps = i; 338 } 339 else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 ) 340 { 341 g_free( conf->ft_listen ); 342 conf->ft_listen = g_strdup( ini->value ); 343 } 317 344 else if( g_strcasecmp( ini->key, "protocols" ) == 0 ) 318 345 { … … 349 376 if( g_strcasecmp( ini->section, "defaults" ) == 0 ) 350 377 { 351 set_t *s = set_find( &irc-> set, ini->key );378 set_t *s = set_find( &irc->b->set, ini->key ); 352 379 353 380 if( s ) -
conf.h
r156bbd7 r21c87a7 50 50 int ping_timeout; 51 51 char *user; 52 size_t ft_max_size; 53 int ft_max_kbps; 54 char *ft_listen; 52 55 char **protocols; 53 56 } conf_t; -
configure
r156bbd7 r21c87a7 398 398 fi 399 399 400 STORAGES=" textxml"400 STORAGES="xml" 401 401 402 402 if [ "$ldap" = "auto" ]; then -
doc/user-guide/commands.xml
r156bbd7 r21c87a7 1092 1092 1093 1093 </bitlbee-command> 1094 1095 <bitlbee-command name="transfers"> 1096 <short-description>Monitor, cancel, or reject file transfers</short-description> 1097 <syntax>transfers [<cancel> id | <reject>]</syntax> 1098 1099 <description> 1100 <para> 1101 Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers <action></emphasis> for more information. 1102 </para> 1103 1104 <ircexample> 1105 <ircline nick="ulim">transfers</ircline> 1106 </ircexample> 1107 </description> 1108 1109 <bitlbee-command name="cancel"> 1110 <short-description>Cancels the file transfer with the given id</short-description> 1111 <syntax>transfers <cancel> id</syntax> 1112 1113 <description> 1114 <para>Cancels the file transfer with the given id</para> 1115 </description> 1116 1117 <ircexample> 1118 <ircline nick="ulim">transfers cancel 1</ircline> 1119 <ircline nick="root">Canceling file transfer for test</ircline> 1120 </ircexample> 1121 </bitlbee-command> 1122 1123 <bitlbee-command name="reject"> 1124 <short-description>Rejects all incoming transfers</short-description> 1125 <syntax>transfers <reject></syntax> 1126 1127 <description> 1128 <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para> 1129 </description> 1130 1131 <ircexample> 1132 <ircline nick="ulim">transfers reject</ircline> 1133 </ircexample> 1134 </bitlbee-command> 1135 </bitlbee-command> 1136 1094 1137 </chapter> -
ipc.c
r156bbd7 r21c87a7 138 138 139 139 if( strchr( irc->umode, 'w' ) ) 140 irc_write( irc, ":%s WALLOPS :%s", irc-> myhost, cmd[1] );140 irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] ); 141 141 } 142 142 … … 147 147 148 148 if( strchr( irc->umode, 's' ) ) 149 irc_write( irc, ":%s NOTICE %s :%s", irc-> myhost, irc->nick, cmd[1] );149 irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] ); 150 150 } 151 151 … … 156 156 157 157 if( strchr( irc->umode, 'o' ) ) 158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc-> myhost, irc->nick, cmd[1] );158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] ); 159 159 } 160 160 … … 176 176 return; 177 177 178 if( nick_cmp( cmd[1], irc-> nick ) != 0 )178 if( nick_cmp( cmd[1], irc->user->nick ) != 0 ) 179 179 return; /* It's not for us. */ 180 180 181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc-> mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] ); 182 182 irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); 183 183 } … … 188 188 ipc_to_master_str( "HELLO\r\n" ); 189 189 else 190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc-> host, irc->nick, irc->realname );190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 191 191 } 192 192 -
irc.c
r156bbd7 r21c87a7 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 24 24 */ 25 25 26 #define BITLBEE_CORE27 26 #include "bitlbee.h" 28 #include "sock.h"29 #include "crypting.h"30 27 #include "ipc.h" 31 28 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 } 29 GSList *irc_connection_list; 30 31 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ); 32 static char *set_eval_charset( set_t *set, char *value ); 114 33 115 34 irc_t *irc_new( int fd ) … … 118 37 struct sockaddr_storage sock; 119 38 socklen_t socklen = sizeof( sock ); 39 char *host = NULL, *myhost = NULL; 40 irc_user_t *iu; 120 41 set_t *s; 42 bee_t *b; 121 43 122 44 irc = g_new0( irc_t, 1 ); … … 130 52 irc->last_pong = gettime(); 131 53 132 irc-> userhash = g_hash_table_new( g_str_hash, g_str_equal );54 irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal ); 133 55 irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); 134 135 strcpy( irc->umode, UMODE );136 irc->mynick = g_strdup( ROOT_NICK );137 irc->channel = g_strdup( ROOT_CHAN );138 56 139 57 irc->iconv = (GIConv) -1; … … 142 60 if( global.conf->hostname ) 143 61 { 144 irc->myhost = g_strdup( global.conf->hostname );62 myhost = g_strdup( global.conf->hostname ); 145 63 } 146 64 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) … … 151 69 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 152 70 { 153 irc->myhost = g_strdup( ipv6_unwrap( buf ) );71 myhost = g_strdup( ipv6_unwrap( buf ) ); 154 72 } 155 73 } … … 162 80 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 163 81 { 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" );82 host = g_strdup( ipv6_unwrap( buf ) ); 83 } 84 } 85 86 if( host == NULL ) 87 host = g_strdup( "localhost.localdomain" ); 88 if( myhost == NULL ) 89 myhost = g_strdup( "localhost.localdomain" ); 172 90 173 91 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 174 92 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); 175 176 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );177 93 178 94 irc_connection_list = g_slist_append( irc_connection_list, irc ); 179 95 180 s = set_add( &irc->set, "away", NULL, set_eval_away_status, irc ); 181 s->flags |= SET_NULL_OK; 182 s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); 183 s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); 184 s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc ); 185 s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc ); 186 s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); 187 s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); 188 s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); 189 s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc ); 190 s = set_add( &irc->set, "debug", "false", set_eval_bool, irc ); 191 s = set_add( &irc->set, "default_target", "root", NULL, irc ); 192 s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); 193 s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc ); 194 s = set_add( &irc->set, "handle_unknown", "root", NULL, irc ); 195 s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); 196 s = set_add( &irc->set, "ops", "both", set_eval_ops, irc ); 197 s = set_add( &irc->set, "password", NULL, set_eval_password, irc ); 198 s->flags |= SET_NULL_OK; 199 s = set_add( &irc->set, "private", "true", set_eval_bool, irc ); 200 s = set_add( &irc->set, "query_order", "lifo", NULL, irc ); 201 s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); 202 s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); 203 s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); 204 s = set_add( &irc->set, "status", NULL, set_eval_away_status, irc ); 205 s->flags |= SET_NULL_OK; 206 s = set_add( &irc->set, "strip_html", "true", NULL, irc ); 207 s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc ); 208 s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); 209 s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); 96 b = irc->b = bee_new(); 97 b->ui_data = irc; 98 b->ui = &irc_ui_funcs; 99 100 s = set_add( &b->set, "away_devoice", "true", NULL/*set_eval_away_devoice*/, irc ); 101 s = set_add( &b->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); 102 s = set_add( &b->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); 103 s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc ); 104 //s = set_add( &b->set, "control_channel", irc->channel, NULL/*set_eval_control_channel*/, irc ); 105 s = set_add( &b->set, "default_target", "root", NULL, irc ); 106 s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc ); 107 s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc ); 108 s = set_add( &b->set, "handle_unknown", "root", NULL, irc ); 109 s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc ); 110 s = set_add( &b->set, "ops", "both", NULL/*set_eval_ops*/, irc ); 111 s = set_add( &b->set, "private", "true", set_eval_bool, irc ); 112 s = set_add( &b->set, "query_order", "lifo", NULL, irc ); 113 s = set_add( &b->set, "root_nick", ROOT_NICK, NULL/*set_eval_root_nick*/, irc ); 114 s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc ); 115 s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc ); 116 s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc ); 117 s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc ); 118 119 irc->root = iu = irc_user_new( irc, ROOT_NICK ); 120 iu->host = g_strdup( myhost ); 121 iu->fullname = g_strdup( ROOT_FN ); 122 iu->f = &irc_user_root_funcs; 123 124 iu = irc_user_new( irc, NS_NICK ); 125 iu->host = g_strdup( myhost ); 126 iu->fullname = g_strdup( ROOT_FN ); 127 iu->f = &irc_user_root_funcs; 128 129 irc->user = g_new0( irc_user_t, 1 ); 130 irc->user->host = g_strdup( host ); 210 131 211 132 conf_loaddefaults( irc ); 212 133 213 134 /* Evaluator sets the iconv/oconv structures. */ 214 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 215 216 return( irc ); 135 set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) ); 136 137 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" ); 138 139 g_free( myhost ); 140 g_free( host ); 141 142 return irc; 217 143 } 218 144 … … 235 161 236 162 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 237 irc-> nick ? irc->nick : "(NONE)", irc->host, reason );163 irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason ); 238 164 239 165 g_free( reason ); … … 245 171 246 172 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 247 irc-> nick ? irc->nick : "(NONE)", irc->host, "No reason given" );173 irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" ); 248 174 } 249 175 … … 266 192 } 267 193 268 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 269 { 270 g_free( key ); 271 272 return( TRUE ); 273 } 274 275 /* Because we have no garbage collection, this is quite annoying */ 194 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 195 276 196 void irc_free( irc_t * irc ) 277 197 { 278 user_t *user, *usertmp;279 280 198 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 281 199 282 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) ) 200 /* 201 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) 283 202 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 284 203 irc_usermsg( irc, "Error while saving settings!" ); 204 */ 285 205 286 206 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 287 207 288 while( irc->accounts ) 289 { 290 if( irc->accounts->ic ) 291 imc_logout( irc->accounts->ic, FALSE ); 292 else if( irc->accounts->reconnect ) 293 cancel_auto_reconnect( irc->accounts ); 294 295 if( irc->accounts->ic == NULL ) 296 account_del( irc, irc->accounts ); 297 else 298 /* Nasty hack, but account_del() doesn't work in this 299 case and we don't want infinite loops, do we? ;-) */ 300 irc->accounts = irc->accounts->next; 301 } 302 208 /* 303 209 while( irc->queries != NULL ) 304 210 query_del( irc, irc->queries ); 305 306 while( irc->set ) 307 set_del( &irc->set, irc->set->key ); 308 309 if (irc->users != NULL) 310 { 311 user = irc->users; 312 while( user != NULL ) 313 { 314 g_free( user->nick ); 315 g_free( user->away ); 316 g_free( user->handle ); 317 if( user->user != user->nick ) g_free( user->user ); 318 if( user->host != user->nick ) g_free( user->host ); 319 if( user->realname != user->nick ) g_free( user->realname ); 320 b_event_remove( user->sendbuf_timer ); 321 322 usertmp = user; 323 user = user->next; 324 g_free( usertmp ); 325 } 326 } 211 */ 212 213 while( irc->users ) 214 irc_user_free( irc, (irc_user_t *) irc->users->data ); 215 216 while( irc->channels ) 217 irc_channel_free( irc->channels->data ); 327 218 328 219 if( irc->ping_source_id > 0 ) … … 336 227 irc->fd = -1; 337 228 338 g_hash_table_foreach_remove( irc-> userhash, irc_free_hashkey, NULL );339 g_hash_table_destroy( irc-> userhash );229 g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL ); 230 g_hash_table_destroy( irc->nick_user_hash ); 340 231 341 232 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); … … 350 241 g_free( irc->readbuffer ); 351 242 352 g_free( irc->nick );353 g_free( irc->user );354 g_free( irc->host );355 g_free( irc->realname );356 243 g_free( irc->password ); 357 358 g_free( irc->myhost );359 g_free( irc->mynick );360 361 g_free( irc->channel );362 363 g_free( irc->last_target );364 244 365 245 g_free( irc ); … … 373 253 } 374 254 255 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 256 { 257 g_free( key ); 258 259 return( TRUE ); 260 } 261 375 262 /* USE WITH CAUTION! 376 263 Sets pass without checking */ 377 void irc_setpass (irc_t *irc, const char *pass) 264 void irc_setpass (irc_t *irc, const char *pass) 378 265 { 379 266 g_free (irc->password); … … 386 273 } 387 274 275 static char **irc_splitlines( char *buffer ); 276 388 277 void irc_process( irc_t *irc ) 389 278 { … … 393 282 if( irc->readbuffer != NULL ) 394 283 { 395 lines = irc_ tokenize( irc->readbuffer );284 lines = irc_splitlines( irc->readbuffer ); 396 285 397 286 for( i = 0; *lines[i] != '\0'; i ++ ) … … 430 319 "`help set charset' for more information. Your " 431 320 "message was ignored.", 432 set_getstr( &irc-> set, "charset" ) );321 set_getstr( &irc->b->set, "charset" ) ); 433 322 434 323 g_free( conv ); … … 437 326 else 438 327 { 439 irc_write( irc, ":%s NOTICE AUTH :%s", irc-> myhost,328 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, 440 329 "Warning: invalid characters received at login time." ); 441 330 … … 475 364 } 476 365 477 /* Splits a long string into separate lines. The array is NULL-terminated and, unless the string 478 contains an incomplete line at the end, ends with an empty string. */ 479 char **irc_tokenize( char *buffer ) 366 /* Splits a long string into separate lines. The array is NULL-terminated 367 and, unless the string contains an incomplete line at the end, ends with 368 an empty string. Could use g_strsplit() but this one does it in-place. 369 (So yes, it's destructive.) */ 370 static char **irc_splitlines( char *buffer ) 480 371 { 481 372 int i, j, n = 3; … … 608 499 } 609 500 610 void irc_reply( irc_t *irc, int code, char *format, ... )611 {612 char text[IRC_MAX_LINE];613 va_list params;614 615 va_start( params, format );616 g_vsnprintf( text, IRC_MAX_LINE, format, params );617 va_end( params );618 irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );619 620 return;621 }622 623 int irc_usermsg( irc_t *irc, char *format, ... )624 {625 char text[1024];626 va_list params;627 char is_private = 0;628 user_t *u;629 630 u = user_find( irc, irc->mynick );631 is_private = u->is_private;632 633 va_start( params, format );634 g_vsnprintf( text, sizeof( text ), format, params );635 va_end( params );636 637 return( irc_msgfrom( irc, u->nick, text ) );638 }639 640 501 void irc_write( irc_t *irc, char *format, ... ) 641 502 { … … 648 509 return; 649 510 } 511 512 void irc_write_all( int now, char *format, ... ) 513 { 514 va_list params; 515 GSList *temp; 516 517 va_start( params, format ); 518 519 temp = irc_connection_list; 520 while( temp != NULL ) 521 { 522 irc_t *irc = temp->data; 523 524 if( now ) 525 { 526 g_free( irc->sendbuffer ); 527 irc->sendbuffer = g_strdup( "\r\n" ); 528 } 529 irc_vawrite( temp->data, format, params ); 530 if( now ) 531 { 532 bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ); 533 } 534 temp = temp->next; 535 } 536 537 va_end( params ); 538 return; 539 } 650 540 651 541 void irc_vawrite( irc_t *irc, char *format, va_list params ) … … 704 594 } 705 595 706 void irc_write_all( int now, char *format, ... ) 707 { 708 va_list params; 709 GSList *temp; 710 711 va_start( params, format ); 712 713 temp = irc_connection_list; 714 while( temp != NULL ) 715 { 716 irc_t *irc = temp->data; 717 718 if( now ) 719 { 720 g_free( irc->sendbuffer ); 721 irc->sendbuffer = g_strdup( "\r\n" ); 722 } 723 irc_vawrite( temp->data, format, params ); 724 if( now ) 725 { 726 bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ); 727 } 728 temp = temp->next; 729 } 730 731 va_end( params ); 732 return; 733 } 734 735 void irc_names( irc_t *irc, char *channel ) 736 { 737 user_t *u; 738 char namelist[385] = ""; 739 struct groupchat *c = NULL; 740 char *ops = set_getstr( &irc->set, "ops" ); 741 742 /* RFCs say there is no error reply allowed on NAMES, so when the 743 channel is invalid, just give an empty reply. */ 744 745 if( g_strcasecmp( channel, irc->channel ) == 0 ) 746 { 747 for( u = irc->users; u; u = u->next ) if( u->online ) 748 { 749 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) 596 int irc_check_login( irc_t *irc ) 597 { 598 if( irc->user->user && irc->user->nick ) 599 { 600 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 601 { 602 irc_send_num( irc, 464, ":This server is password-protected." ); 603 return 0; 604 } 605 else 606 { 607 irc_channel_t *ic; 608 irc_user_t *iu = irc->user; 609 610 irc->user = irc_user_new( irc, iu->nick ); 611 irc->user->user = iu->user; 612 irc->user->host = iu->host; 613 irc->user->fullname = iu->fullname; 614 irc->user->f = &irc_user_self_funcs; 615 g_free( iu->nick ); 616 g_free( iu ); 617 618 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 619 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 620 621 irc->status |= USTATUS_LOGGED_IN; 622 623 /* This is for bug #209 (use PASS to identify to NickServ). */ 624 if( irc->password != NULL ) 750 625 { 751 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 752 *namelist = 0; 626 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 627 628 /*irc_setpass( irc, NULL );*/ 629 /*root_command( irc, send_cmd );*/ 630 g_free( send_cmd[1] ); 753 631 } 754 632 755 if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) ) 756 strcat( namelist, "+" ); 757 else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) || 758 ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ) 759 strcat( namelist, "@" ); 760 761 strcat( namelist, u->nick ); 762 strcat( namelist, " " ); 763 } 764 } 765 else if( ( c = irc_chat_by_channel( irc, channel ) ) ) 766 { 767 GList *l; 768 769 /* root and the user aren't in the channel userlist but should 770 show up in /NAMES, so list them first: */ 771 sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick, 772 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick ); 773 774 for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) ) 775 { 776 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) 777 { 778 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 779 *namelist = 0; 780 } 781 782 strcat( namelist, u->nick ); 783 strcat( namelist, " " ); 784 } 785 } 786 787 if( *namelist ) 788 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 789 790 irc_reply( irc, 366, "%s :End of /NAMES list", channel ); 791 } 792 793 int irc_check_login( irc_t *irc ) 794 { 795 if( irc->user && irc->nick ) 796 { 797 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 798 { 799 irc_reply( irc, 464, ":This server is password-protected." ); 800 return 0; 801 } 802 else 803 { 804 irc_login( irc ); 633 irc_send_login( irc ); 634 635 irc->umode[0] = '\0'; 636 irc_umode_set( irc, "+" UMODE, TRUE ); 637 638 ic = irc_channel_new( irc, ROOT_CHAN ); 639 irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root ); 640 irc_channel_add_user( ic, irc->user ); 641 642 irc->last_root_cmd = g_strdup( ROOT_CHAN ); 643 644 irc_send_msg( irc->root, "PRIVMSG", ROOT_CHAN, 645 "Welcome to the BitlBee gateway!\n\n" 646 "If you've never used BitlBee before, please do read the help " 647 "information using the \x02help\x02 command. Lots of FAQs are " 648 "answered there.\n" 649 "If you already have an account on this server, just use the " 650 "\x02identify\x02 command to identify yourself.", NULL ); 651 805 652 return 1; 806 653 } … … 813 660 } 814 661 815 void irc_login( irc_t *irc ) 816 { 817 user_t *u; 818 819 irc_reply( irc, 1, ":Welcome to the BitlBee gateway, %s", irc->nick ); 820 irc_reply( irc, 2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost ); 821 irc_reply( irc, 3, ":%s", IRCD_INFO ); 822 irc_reply( irc, 4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); 823 irc_reply( irc, 5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee " 824 "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", 825 CTYPES, CMODES, MAX_NICK_LENGTH - 1 ); 826 irc_motd( irc ); 827 irc->umode[0] = '\0'; 828 irc_umode_set( irc, "+" UMODE, 1 ); 829 830 u = user_add( irc, irc->mynick ); 831 u->host = g_strdup( irc->myhost ); 832 u->realname = g_strdup( ROOT_FN ); 833 u->online = 1; 834 u->send_handler = root_command_string; 835 u->is_private = 0; /* [SH] The channel is root's personal playground. */ 836 irc_spawn( irc, u ); 837 838 u = user_add( irc, NS_NICK ); 839 u->host = g_strdup( irc->myhost ); 840 u->realname = g_strdup( ROOT_FN ); 841 u->online = 0; 842 u->send_handler = root_command_string; 843 u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */ 844 845 u = user_add( irc, irc->nick ); 846 u->user = g_strdup( irc->user ); 847 u->host = g_strdup( irc->host ); 848 u->realname = g_strdup( irc->realname ); 849 u->online = 1; 850 irc_spawn( irc, u ); 851 852 irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n" 853 "If you've never used BitlBee before, please do read the help " 854 "information using the \x02help\x02 command. Lots of FAQs are " 855 "answered there.\n" 856 "If you already have an account on this server, just use the " 857 "\x02identify\x02 command to identify yourself." ); 858 859 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 860 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 861 862 irc->status |= USTATUS_LOGGED_IN; 863 864 /* This is for bug #209 (use PASS to identify to NickServ). */ 865 if( irc->password != NULL ) 866 { 867 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 868 869 irc_setpass( irc, NULL ); 870 root_command( irc, send_cmd ); 871 g_free( send_cmd[1] ); 872 } 873 } 874 875 void irc_motd( irc_t *irc ) 876 { 877 int fd; 878 879 fd = open( global.conf->motdfile, O_RDONLY ); 880 if( fd == -1 ) 881 { 882 irc_reply( irc, 422, ":We don't need MOTDs." ); 883 } 884 else 885 { 886 char linebuf[80]; /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */ 887 char *add, max; 888 int len; 889 890 linebuf[79] = len = 0; 891 max = sizeof( linebuf ) - 1; 892 893 irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost ); 894 while( read( fd, linebuf + len, 1 ) == 1 ) 895 { 896 if( linebuf[len] == '\n' || len == max ) 897 { 898 linebuf[len] = 0; 899 irc_reply( irc, 372, ":- %s", linebuf ); 900 len = 0; 901 } 902 else if( linebuf[len] == '%' ) 903 { 904 read( fd, linebuf + len, 1 ); 905 if( linebuf[len] == 'h' ) 906 add = irc->myhost; 907 else if( linebuf[len] == 'v' ) 908 add = BITLBEE_VERSION; 909 else if( linebuf[len] == 'n' ) 910 add = irc->nick; 911 else 912 add = "%"; 913 914 strncpy( linebuf + len, add, max - len ); 915 while( linebuf[++len] ); 916 } 917 else if( len < max ) 918 { 919 len ++; 920 } 921 } 922 irc_reply( irc, 376, ":End of MOTD" ); 923 close( fd ); 924 } 925 } 926 927 void irc_topic( irc_t *irc, char *channel ) 928 { 929 struct groupchat *c = irc_chat_by_channel( irc, channel ); 930 931 if( c && c->topic ) 932 irc_reply( irc, 332, "%s :%s", channel, c->topic ); 933 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 934 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC ); 935 else 936 irc_reply( irc, 331, "%s :No topic for this channel", channel ); 937 } 938 939 void irc_umode_set( irc_t *irc, char *s, int allow_priv ) 662 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) 940 663 { 941 664 /* allow_priv: Set to 0 if s contains user input, 1 if you want 942 665 to set a "privileged" mode (+o, +R, etc). */ 943 char m[256], st = 1, *t; 666 char m[128], st = 1; 667 const char *t; 944 668 int i; 945 669 char changes[512], *p, st2 = 2; … … 949 673 950 674 for( t = irc->umode; *t; t ++ ) 951 m[(int)*t] = 1; 952 675 if( *t < sizeof( m ) ) 676 m[(int)*t] = 1; 677 953 678 p = changes; 954 679 for( t = s; *t; t ++ ) … … 956 681 if( *t == '+' || *t == '-' ) 957 682 st = *t == '+'; 958 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) 683 else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || 684 ( st == 1 && strchr( UMODES, *t ) ) || 685 ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) 959 686 { 960 687 if( m[(int)*t] != st) … … 973 700 memset( irc->umode, 0, sizeof( irc->umode ) ); 974 701 975 for( i = 0; i < 256&& strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )702 for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) 976 703 if( m[i] ) 977 704 irc->umode[strlen(irc->umode)] = i; 978 705 979 706 if( badflag ) 980 irc_reply( irc, 501, ":Unknown MODE flag" ); 981 /* Deliberately no !user@host on the prefix here */ 707 irc_send_num( irc, 501, ":Unknown MODE flag" ); 982 708 if( *changes ) 983 irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes ); 984 } 985 986 void irc_spawn( irc_t *irc, user_t *u ) 987 { 988 irc_join( irc, u, irc->channel ); 989 } 990 991 void irc_join( irc_t *irc, user_t *u, char *channel ) 992 { 993 char *nick; 994 995 if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) ) 996 irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel ); 997 998 if( nick_cmp( u->nick, irc->nick ) == 0 ) 999 { 1000 irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE ); 1001 irc_names( irc, channel ); 1002 irc_topic( irc, channel ); 1003 } 1004 1005 nick = g_strdup( u->nick ); 1006 nick_lc( nick ); 1007 if( g_hash_table_lookup( irc->watches, nick ) ) 1008 { 1009 irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" ); 1010 } 1011 g_free( nick ); 1012 } 1013 1014 void irc_part( irc_t *irc, user_t *u, char *channel ) 1015 { 1016 irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" ); 1017 } 1018 1019 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ) 1020 { 1021 irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" ); 1022 } 1023 1024 void irc_kill( irc_t *irc, user_t *u ) 1025 { 1026 char *nick, *s; 1027 char reason[128]; 1028 1029 if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) ) 1030 { 1031 if( u->ic->acc->server ) 1032 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1033 u->ic->acc->server ); 1034 else if( ( s = strchr( u->ic->acc->user, '@' ) ) ) 1035 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1036 s + 1 ); 1037 else 1038 g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, 1039 u->ic->acc->prpl->name, irc->myhost ); 1040 1041 /* proto_opt might contain garbage after the : */ 1042 if( ( s = strchr( reason, ':' ) ) ) 1043 *s = 0; 1044 } 1045 else 1046 { 1047 strcpy( reason, "Leaving..." ); 1048 } 1049 1050 irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason ); 1051 1052 nick = g_strdup( u->nick ); 1053 nick_lc( nick ); 1054 if( g_hash_table_lookup( irc->watches, nick ) ) 1055 { 1056 irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" ); 1057 } 1058 g_free( nick ); 1059 } 1060 1061 int irc_send( irc_t *irc, char *nick, char *s, int flags ) 1062 { 1063 struct groupchat *c = NULL; 1064 user_t *u = NULL; 1065 1066 if( strchr( CTYPES, *nick ) ) 1067 { 1068 if( !( c = irc_chat_by_channel( irc, nick ) ) ) 1069 { 1070 irc_reply( irc, 403, "%s :Channel does not exist", nick ); 1071 return( 0 ); 1072 } 1073 } 1074 else 1075 { 1076 u = user_find( irc, nick ); 1077 1078 if( !u ) 1079 { 1080 if( irc->is_private ) 1081 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 1082 else 1083 irc_usermsg( irc, "Nick `%s' does not exist!", nick ); 1084 return( 0 ); 1085 } 1086 } 1087 1088 if( *s == 1 && s[strlen(s)-1] == 1 ) 1089 { 1090 if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 ) 1091 { 1092 if( s[7] == ' ' ) s ++; 1093 s += 3; 1094 *(s++) = '/'; 1095 *(s++) = 'm'; 1096 *(s++) = 'e'; 1097 *(s++) = ' '; 1098 s -= 4; 1099 s[strlen(s)-1] = 0; 1100 } 1101 else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 ) 1102 { 1103 u = user_find( irc, irc->mynick ); 1104 irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" ); 1105 return( 1 ); 1106 } 1107 else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 ) 1108 { 1109 u = user_find( irc, irc->mynick ); 1110 irc_privmsg( irc, u, "NOTICE", irc->nick, "", s ); 1111 return( 1 ); 1112 } 1113 else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 ) 1114 { 1115 if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 ) 1116 { 1117 time_t current_typing_notice = time( NULL ); 1118 1119 if( current_typing_notice - u->last_typing_notice >= 5 ) 1120 { 1121 u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 ); 1122 u->last_typing_notice = current_typing_notice; 1123 } 1124 } 1125 return( 1 ); 1126 } 1127 else 1128 { 1129 irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" ); 1130 return( 0 ); 1131 } 1132 } 1133 1134 if( u ) 1135 { 1136 /* For the next message, we probably do have to send new notices... */ 1137 u->last_typing_notice = 0; 1138 u->is_private = irc->is_private; 1139 1140 if( u->is_private ) 1141 { 1142 if( !u->online ) 1143 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 1144 else if( u->away ) 1145 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 1146 } 1147 1148 if( u->send_handler ) 1149 { 1150 u->send_handler( irc, u, s, flags ); 1151 return 1; 1152 } 1153 } 1154 else if( c && c->ic && c->ic->acc && c->ic->acc->prpl ) 1155 { 1156 return( imc_chat_msg( c, s, 0 ) ); 1157 } 1158 1159 return( 0 ); 1160 } 1161 1162 static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond ) 1163 { 1164 user_t *u = data; 1165 1166 /* Shouldn't happen, but just to be sure. */ 1167 if( u->sendbuf_len < 2 ) 1168 return FALSE; 1169 1170 u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */ 1171 imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); 1172 1173 g_free( u->sendbuf ); 1174 u->sendbuf = NULL; 1175 u->sendbuf_len = 0; 1176 u->sendbuf_timer = 0; 1177 u->sendbuf_flags = 0; 1178 1179 return FALSE; 1180 } 1181 1182 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) 1183 { 1184 if( !u || !u->ic ) return; 1185 1186 if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) 1187 { 1188 int delay; 1189 1190 if( u->sendbuf_len > 0 && u->sendbuf_flags != flags) 1191 { 1192 /* Flush the buffer */ 1193 b_event_remove( u->sendbuf_timer ); 1194 buddy_send_handler_delayed( u, -1, 0 ); 1195 } 1196 1197 if( u->sendbuf_len == 0 ) 1198 { 1199 u->sendbuf_len = strlen( msg ) + 2; 1200 u->sendbuf = g_new( char, u->sendbuf_len ); 1201 u->sendbuf[0] = 0; 1202 u->sendbuf_flags = flags; 1203 } 1204 else 1205 { 1206 u->sendbuf_len += strlen( msg ) + 1; 1207 u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len ); 1208 } 1209 1210 strcat( u->sendbuf, msg ); 1211 strcat( u->sendbuf, "\n" ); 1212 1213 delay = set_getint( &irc->set, "buddy_sendbuffer_delay" ); 1214 if( delay <= 5 ) 1215 delay *= 1000; 1216 1217 if( u->sendbuf_timer > 0 ) 1218 b_event_remove( u->sendbuf_timer ); 1219 u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u ); 1220 } 1221 else 1222 { 1223 imc_buddy_msg( u->ic, u->handle, msg, flags ); 1224 } 1225 } 1226 1227 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ) 1228 { 1229 char last = 0; 1230 char *s = msg, *line = msg; 1231 1232 /* The almighty linesplitter .. woohoo!! */ 1233 while( !last ) 1234 { 1235 if( *s == '\r' && *(s+1) == '\n' ) 1236 *(s++) = 0; 1237 if( *s == '\n' ) 1238 { 1239 last = s[1] == 0; 1240 *s = 0; 1241 } 1242 else 1243 { 1244 last = s[0] == 0; 1245 } 1246 if( *s == 0 ) 1247 { 1248 if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 ) 1249 { 1250 irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host, 1251 type, to, line + 4 ); 1252 } 1253 else 1254 { 1255 irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host, 1256 type, to, prefix ? prefix : "", line ); 1257 } 1258 line = s + 1; 1259 } 1260 s ++; 1261 } 1262 1263 return( 1 ); 1264 } 1265 1266 int irc_msgfrom( irc_t *irc, char *nick, char *msg ) 1267 { 1268 user_t *u = user_find( irc, nick ); 1269 static char *prefix = NULL; 1270 1271 if( !u ) return( 0 ); 1272 if( prefix && *prefix ) g_free( prefix ); 1273 1274 if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 ) 1275 { 1276 int len = strlen( irc->nick) + 3; 1277 prefix = g_new (char, len ); 1278 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) ); 1279 prefix[len-1] = 0; 1280 } 1281 else 1282 { 1283 prefix = ""; 1284 } 1285 1286 return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) ); 1287 } 1288 1289 int irc_noticefrom( irc_t *irc, char *nick, char *msg ) 1290 { 1291 user_t *u = user_find( irc, nick ); 1292 1293 if( u ) 1294 return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) ); 1295 else 1296 return( 0 ); 1297 } 709 irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, 710 irc->user->user, irc->user->host, irc->user->nick, 711 changes ); 712 } 713 1298 714 1299 715 /* Returns 0 if everything seems to be okay, a number >0 when there was a … … 1333 749 } 1334 750 1335 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ) 1336 { 1337 struct groupchat *c; 1338 account_t *a; 1339 1340 /* This finds the connection which has a conversation which belongs to this channel */ 1341 for( a = irc->accounts; a; a = a->next ) 1342 { 1343 if( a->ic == NULL ) 1344 continue; 1345 1346 c = a->ic->groupchats; 1347 while( c ) 1348 { 1349 if( c->channel && g_strcasecmp( c->channel, channel ) == 0 ) 1350 return c; 1351 1352 c = c->next; 1353 } 1354 } 1355 1356 return NULL; 1357 } 751 static char *set_eval_charset( set_t *set, char *value ) 752 { 753 irc_t *irc = (irc_t*) set->data; 754 char *test; 755 gsize test_bytes = 0; 756 GIConv ic, oc; 757 758 if( g_strcasecmp( value, "none" ) == 0 ) 759 value = g_strdup( "utf-8" ); 760 761 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 762 { 763 return NULL; 764 } 765 766 /* Do a test iconv to see if the user picked an IRC-compatible 767 charset (for example utf-16 goes *horribly* wrong). */ 768 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 769 test_bytes > 1 ) 770 { 771 g_free( test ); 772 g_iconv_close( oc ); 773 irc_usermsg( irc, "Unsupported character set: The IRC protocol " 774 "only supports 8-bit character sets." ); 775 return NULL; 776 } 777 g_free( test ); 778 779 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 780 { 781 g_iconv_close( oc ); 782 return NULL; 783 } 784 785 if( irc->iconv != (GIConv) -1 ) 786 g_iconv_close( irc->iconv ); 787 if( irc->oconv != (GIConv) -1 ) 788 g_iconv_close( irc->oconv ); 789 790 irc->iconv = ic; 791 irc->oconv = oc; 792 793 return value; 794 } -
irc.h
r156bbd7 r21c87a7 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 33 33 #define IRC_PING_STRING "PinglBee" 34 34 35 #define UMODES "abisw" 36 #define UMODES_PRIV "Ro" 37 #define CMODES "nt" 38 #define CMODE "t" 39 #define UMODE "s" 40 #define CTYPES "&#" 35 #define UMODES "abisw" /* Allowed umodes (although they mostly do nothing) */ 36 #define UMODES_PRIV "Ro" /* Allowed, but not by user directly */ 37 #define UMODES_KEEP "R" /* Don't allow unsetting using /MODE */ 38 #define CMODES "nt" /* Allowed modes */ 39 #define CMODE "t" /* Default mode */ 40 #define UMODE "s" /* Default mode */ 41 42 #define CTYPES "&#" /* Valid channel name prefixes */ 41 43 42 44 typedef enum … … 48 50 USTATUS_SHUTDOWN = 8 49 51 } irc_status_t; 52 53 struct irc_user; 50 54 51 55 typedef struct irc … … 59 63 GIConv iconv, oconv; 60 64 61 int sentbytes; 62 time_t oldtime; 63 65 struct irc_user *root; 66 struct irc_user *user; 67 68 char *last_root_cmd; 69 70 char *password; /* HACK: Used to save the user's password, but before 71 logging in, this may contain a password we should 72 send to identify after USER/NICK are received. */ 73 74 char umode[8]; 75 76 struct query *queries; 77 GSList *file_transfers; 78 79 GSList *users, *channels; 80 GHashTable *nick_user_hash; 81 GHashTable *watches; 82 83 gint r_watch_source_id; 84 gint w_watch_source_id; 85 gint ping_source_id; 86 87 struct bee *b; 88 } irc_t; 89 90 typedef enum 91 { 92 IRC_USER_PRIVATE = 1, 93 } irc_user_flags_t; 94 95 typedef struct irc_user 96 { 97 irc_t *irc; 98 64 99 char *nick; 65 100 char *user; 66 101 char *host; 67 char *realname; 68 char *password; /* HACK: Used to save the user's password, but before 69 logging in, this may contain a password we should 70 send to identify after USER/NICK are received. */ 71 72 char umode[8]; 73 74 char *myhost; 75 char *mynick; 76 77 char *channel; 78 int c_id; 79 80 char is_private; /* Not too nice... */ 81 char *last_target; 82 83 struct query *queries; 84 struct account *accounts; 85 struct chat *chatrooms; 86 87 struct __USER *users; 88 GHashTable *userhash; 89 GHashTable *watches; 90 struct __NICK *nicks; 102 char *fullname; 103 104 /* Nickname in lowercase for case sensitive searches */ 105 char *key; 106 107 irc_user_flags_t flags; 108 109 char *sendbuf; 110 int sendbuf_len; 111 guint sendbuf_timer; 112 //int sendbuf_flags; 113 114 struct bee_user *bu; 115 116 const struct irc_user_funcs *f; 117 } irc_user_t; 118 119 struct irc_user_funcs 120 { 121 gboolean (*privmsg)( irc_user_t *iu, const char *msg ); 122 gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp ); 123 }; 124 125 extern const struct irc_user_funcs irc_user_root_funcs; 126 extern const struct irc_user_funcs irc_user_self_funcs; 127 128 typedef enum 129 { 130 IRC_CHANNEL_JOINED = 1, 131 } irc_channel_flags_t; 132 133 typedef struct irc_channel 134 { 135 irc_t *irc; 136 char *name; 137 char mode[8]; 138 int flags; 139 140 char *topic; 141 char *topic_who; 142 time_t topic_time; 143 144 GSList *users; 91 145 struct set *set; 92 93 gint r_watch_source_id; 94 gint w_watch_source_id; 95 gint ping_source_id; 96 } irc_t; 97 98 #include "user.h" 99 146 147 const struct irc_channel_funcs *f; 148 } irc_channel_t; 149 150 struct irc_channel_funcs 151 { 152 gboolean (*privmsg)( irc_channel_t *iu, const char *msg ); 153 }; 154 155 extern const struct bee_ui_funcs irc_ui_funcs; 156 157 /* irc.c */ 100 158 extern GSList *irc_connection_list; 101 159 … … 103 161 void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 104 162 void irc_free( irc_t *irc ); 105 106 void irc_exec( irc_t *irc, char **cmd ); 163 void irc_setpass (irc_t *irc, const char *pass); 164 107 165 void irc_process( irc_t *irc ); 108 166 char **irc_parse_line( char *line ); 109 167 char *irc_build_line( char **cmd ); 110 168 111 void irc_vawrite( irc_t *irc, char *format, va_list params );112 169 void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 113 170 void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 114 void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 115 G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 116 char **irc_tokenize( char *buffer ); 117 118 void irc_login( irc_t *irc ); 171 void irc_vawrite( irc_t *irc, char *format, va_list params ); 172 119 173 int irc_check_login( irc_t *irc ); 120 void irc_motd( irc_t *irc ); 121 void irc_names( irc_t *irc, char *channel ); 122 void irc_topic( irc_t *irc, char *channel ); 123 void irc_umode_set( irc_t *irc, char *s, int allow_priv ); 124 void irc_who( irc_t *irc, char *channel ); 125 void irc_spawn( irc_t *irc, user_t *u ); 126 void irc_join( irc_t *irc, user_t *u, char *channel ); 127 void irc_part( irc_t *irc, user_t *u, char *channel ); 128 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ); 129 void irc_kill( irc_t *irc, user_t *u ); 130 void irc_invite( irc_t *irc, char *nick, char *channel ); 131 void irc_whois( irc_t *irc, char *nick ); 132 void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */ 133 134 int irc_send( irc_t *irc, char *nick, char *s, int flags ); 135 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ); 136 int irc_msgfrom( irc_t *irc, char *nick, char *msg ); 137 int irc_noticefrom( irc_t *irc, char *nick, char *msg ); 138 139 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); 140 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ); 174 175 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); 176 177 /* irc_channel.c */ 178 irc_channel_t *irc_channel_new( irc_t *irc, const char *name ); 179 irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ); 180 int irc_channel_free( irc_channel_t *ic ); 181 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu ); 182 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu ); 183 gboolean irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu ); 184 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who ); 185 gboolean irc_channel_name_ok( const char *name ); 186 187 /* irc_commands.c */ 188 void irc_exec( irc_t *irc, char **cmd ); 189 190 /* irc_send.c */ 191 void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 192 void irc_send_login( irc_t *irc ); 193 void irc_send_motd( irc_t *irc ); 194 void irc_usermsg( irc_t *irc, char *format, ... ); 195 void irc_send_join( irc_channel_t *ic, irc_user_t *iu ); 196 void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason ); 197 void irc_send_names( irc_channel_t *ic ); 198 void irc_send_topic( irc_channel_t *ic, gboolean topic_change ); 199 void irc_send_whois( irc_user_t *iu ); 200 void irc_send_who( irc_t *irc, GSList *l, const char *channel ); 201 void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix ); 202 void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg ); 203 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 ); 204 void irc_send_nick( irc_user_t *iu, const char *new ); 205 206 /* irc_user.c */ 207 irc_user_t *irc_user_new( irc_t *irc, const char *nick ); 208 int irc_user_free( irc_t *irc, irc_user_t *iu ); 209 irc_user_t *irc_user_by_name( irc_t *irc, const char *nick ); 210 int irc_user_set_nick( irc_user_t *iu, const char *new ); 211 gint irc_user_cmp( gconstpointer a_, gconstpointer b_ ); 212 213 /* irc_util.c */ 214 char *set_eval_timezone( struct set *set, char *value ); 215 char *irc_format_timestamp( irc_t *irc, time_t msg_ts ); 141 216 142 217 #endif -
irc_commands.c
r156bbd7 r21c87a7 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 06Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 53 53 else if( global.conf->auth_pass ) 54 54 { 55 irc_ reply( irc, 464, ":Incorrect password" );55 irc_send_num( irc, 464, ":Incorrect password" ); 56 56 } 57 57 else 58 58 { 59 59 /* Remember the password and try to identify after USER/NICK. */ 60 irc_setpass( irc, cmd[1] );60 /*irc_setpass( irc, cmd[1] ); */ 61 61 irc_check_login( irc ); 62 62 } … … 65 65 static void irc_cmd_user( irc_t *irc, char **cmd ) 66 66 { 67 irc->user = g_strdup( cmd[1] );68 irc-> realname = g_strdup( cmd[4] );67 irc->user->user = g_strdup( cmd[1] ); 68 irc->user->fullname = g_strdup( cmd[4] ); 69 69 70 70 irc_check_login( irc ); … … 73 73 static void irc_cmd_nick( irc_t *irc, char **cmd ) 74 74 { 75 if( irc->nick ) 76 { 77 irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" ); 78 } 79 /* This is not clean, but for now it'll have to be like this... */ 80 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) ) 81 { 82 irc_reply( irc, 433, ":This nick is already in use" ); 75 if( irc_user_by_name( irc, cmd[1] ) ) 76 { 77 irc_send_num( irc, 433, ":This nick is already in use" ); 83 78 } 84 79 else if( !nick_ok( cmd[1] ) ) 85 80 { 86 81 /* [SH] Invalid characters. */ 87 irc_reply( irc, 432, ":This nick contains invalid characters" ); 88 } 89 else 90 { 91 irc->nick = g_strdup( cmd[1] ); 82 irc_send_num( irc, 432, ":This nick contains invalid characters" ); 83 } 84 else if( irc->user->nick ) 85 { 86 if( irc->status & USTATUS_IDENTIFIED ) 87 { 88 irc_setpass( irc, NULL ); 89 irc->status &= ~USTATUS_IDENTIFIED; 90 irc_umode_set( irc, "-R", 1 ); 91 } 92 93 irc_user_set_nick( irc->user, cmd[1] ); 94 } 95 else 96 { 97 irc->user->nick = g_strdup( cmd[1] ); 92 98 93 99 irc_check_login( irc ); … … 105 111 static void irc_cmd_ping( irc_t *irc, char **cmd ) 106 112 { 107 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost ); 108 } 109 110 static void irc_cmd_oper( irc_t *irc, char **cmd ) 111 { 112 if( global.conf->oper_pass && 113 ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? 114 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : 115 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) 116 { 117 irc_umode_set( irc, "+o", 1 ); 118 irc_reply( irc, 381, ":Password accepted" ); 119 } 120 else 121 { 122 irc_reply( irc, 432, ":Incorrect password" ); 123 } 113 irc_write( irc, ":%s PONG %s :%s", irc->root->host, 114 irc->root->host, cmd[1]?cmd[1]:irc->root->host ); 115 } 116 117 static void irc_cmd_pong( irc_t *irc, char **cmd ) 118 { 119 /* We could check the value we get back from the user, but in 120 fact we don't care, we're just happy s/he's still alive. */ 121 irc->last_pong = gettime(); 122 irc->pinging = 0; 123 } 124 125 static void irc_cmd_join( irc_t *irc, char **cmd ) 126 { 127 irc_channel_t *ic; 128 129 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 130 ic = irc_channel_new( irc, cmd[1] ); 131 132 if( ic == NULL ) 133 { 134 irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] ); 135 return; 136 } 137 138 if( ic->flags & IRC_CHANNEL_JOINED ) 139 return; /* Dude, you're already there... 140 RFC doesn't have any reply for that though? */ 141 142 irc_channel_add_user( ic, irc->user ); 143 } 144 145 static void irc_cmd_names( irc_t *irc, char **cmd ) 146 { 147 irc_channel_t *ic; 148 149 if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 150 irc_send_names( ic ); 151 /* With no args, we should show /names of all chans. Make the code 152 below work well if necessary. 153 else 154 { 155 GSList *l; 156 157 for( l = irc->channels; l; l = l->next ) 158 irc_send_names( l->data ); 159 } 160 */ 161 } 162 163 static void irc_cmd_part( irc_t *irc, char **cmd ) 164 { 165 irc_channel_t *ic; 166 167 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 168 { 169 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 170 } 171 else if( !irc_channel_del_user( ic, irc->user ) ) 172 { 173 irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] ); 174 } 175 } 176 177 static void irc_cmd_whois( irc_t *irc, char **cmd ) 178 { 179 char *nick = cmd[1]; 180 irc_user_t *iu = irc_user_by_name( irc, nick ); 181 182 if( iu ) 183 irc_send_whois( iu ); 184 else 185 irc_send_num( irc, 401, "%s :Nick does not exist", nick ); 186 } 187 188 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 189 { 190 /* For some reason irssi tries a whowas when whois fails. We can 191 ignore this, but then the user never gets a "user not found" 192 message from irssi which is a bit annoying. So just respond 193 with not-found and irssi users will get better error messages */ 194 195 irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] ); 196 irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] ); 197 } 198 199 static void irc_cmd_motd( irc_t *irc, char **cmd ) 200 { 201 irc_send_motd( irc ); 124 202 } 125 203 126 204 static void irc_cmd_mode( irc_t *irc, char **cmd ) 127 205 { 128 if( strchr( CTYPES, *cmd[1] ) ) 129 { 130 if( cmd[2] ) 206 if( irc_channel_name_ok( cmd[1] ) ) 207 { 208 irc_channel_t *ic; 209 210 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 211 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 212 else if( cmd[2] ) 131 213 { 132 214 if( *cmd[2] == '+' || *cmd[2] == '-' ) 133 irc_ reply( irc, 477, "%s :Can't change channel modes", cmd[1] );215 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); 134 216 else if( *cmd[2] == 'b' ) 135 irc_ reply( irc, 368, "%s :No bans possible", cmd[1] );217 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] ); 136 218 } 137 219 else 138 irc_ reply( irc, 324, "%s +%s", cmd[1], CMODE);139 } 140 else 141 { 142 if( nick_cmp( cmd[1], irc-> nick ) == 0 )220 irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode ); 221 } 222 else 223 { 224 if( nick_cmp( cmd[1], irc->user->nick ) == 0 ) 143 225 { 144 226 if( cmd[2] ) 145 227 irc_umode_set( irc, cmd[2], 0 ); 146 228 else 147 irc_ reply( irc, 221, "+%s", irc->umode );229 irc_send_num( irc, 221, "+%s", irc->umode ); 148 230 } 149 231 else 150 irc_reply( irc, 502, ":Don't touch their modes" ); 151 } 152 } 153 154 static void irc_cmd_names( irc_t *irc, char **cmd ) 155 { 156 irc_names( irc, cmd[1]?cmd[1]:irc->channel ); 157 } 158 159 static void irc_cmd_part( irc_t *irc, char **cmd ) 160 { 161 struct groupchat *c; 162 163 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 164 { 165 user_t *u = user_find( irc, irc->nick ); 166 167 /* Not allowed to leave control channel */ 168 irc_part( irc, u, irc->channel ); 169 irc_join( irc, u, irc->channel ); 170 } 171 else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) ) 172 { 173 user_t *u = user_find( irc, irc->nick ); 174 175 irc_part( irc, u, c->channel ); 176 177 if( c->ic ) 178 { 179 c->joined = 0; 180 c->ic->acc->prpl->chat_leave( c ); 181 } 182 } 183 else 184 { 185 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 186 } 187 } 188 189 static void irc_cmd_join( irc_t *irc, char **cmd ) 190 { 191 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 192 ; /* Dude, you're already there... 193 RFC doesn't have any reply for that though? */ 194 else if( cmd[1] ) 195 { 196 struct chat *c; 197 198 if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 ) 199 irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] ); 200 else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic ) 201 chat_join( irc, c, cmd[2] ); 202 else 203 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 204 } 205 } 206 207 static void irc_cmd_invite( irc_t *irc, char **cmd ) 208 { 209 char *nick = cmd[1], *channel = cmd[2]; 210 struct groupchat *c = irc_chat_by_channel( irc, channel ); 211 user_t *u = user_find( irc, nick ); 212 213 if( u && c && ( u->ic == c->ic ) ) 214 if( c->ic && c->ic->acc->prpl->chat_invite ) 215 { 216 c->ic->acc->prpl->chat_invite( c, u->handle, NULL ); 217 irc_reply( irc, 341, "%s %s", nick, channel ); 218 return; 219 } 220 221 irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel ); 232 irc_send_num( irc, 502, ":Don't touch their modes" ); 233 } 234 } 235 236 static void irc_cmd_who( irc_t *irc, char **cmd ) 237 { 238 char *channel = cmd[1]; 239 irc_channel_t *ic; 240 241 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 242 irc_send_who( irc, irc->users, "**" ); 243 else if( ( ic = irc_channel_by_name( irc, channel ) ) ) 244 irc_send_who( irc, ic->users, channel ); 245 else 246 irc_send_num( irc, 403, "%s :No such channel", channel ); 222 247 } 223 248 224 249 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 225 250 { 226 if ( !cmd[2] ) 227 { 228 irc_reply( irc, 412, ":No text to send" ); 229 } 230 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 231 { 232 irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] ); 251 irc_channel_t *ic; 252 irc_user_t *iu; 253 254 if( !cmd[2] ) 255 { 256 irc_send_num( irc, 412, ":No text to send" ); 257 return; 258 } 259 260 /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ 261 if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) 262 { 263 cmd[2] += 4; 264 strcpy( cmd[2], "/me" ); 265 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 266 cmd[2][strlen(cmd[2])-1] = '\0'; 267 } 268 269 if( irc_channel_name_ok( cmd[1] ) && 270 ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 271 { 272 if( ic->f->privmsg ) 273 ic->f->privmsg( ic, cmd[2] ); 274 } 275 else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) 276 { 277 if( cmd[2][0] == '\001' ) 278 { 279 char **ctcp; 280 281 if( iu->f->ctcp == NULL ) 282 return; 283 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 284 cmd[2][strlen(cmd[2])-1] = '\0'; 285 286 ctcp = split_command_parts( cmd[2] + 1 ); 287 iu->f->ctcp( iu, ctcp ); 288 } 289 else if( iu->f->privmsg ) 290 iu->f->privmsg( iu, cmd[2] ); 291 } 292 else 293 { 294 irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); 295 } 296 297 298 #if 0 299 else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 300 { 233 301 } 234 302 else … … 271 339 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); 272 340 } 273 } 274 275 static void irc_cmd_who( irc_t *irc, char **cmd ) 276 { 277 char *channel = cmd[1]; 278 user_t *u = irc->users; 279 struct groupchat *c; 280 GList *l; 281 282 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 283 while( u ) 284 { 285 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 ); 286 u = u->next; 287 } 288 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 289 while( u ) 290 { 291 if( u->online ) 292 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 ); 293 u = u->next; 294 } 295 else if( ( c = irc_chat_by_channel( irc, channel ) ) ) 296 for( l = c->in_room; l; l = l->next ) 297 { 298 if( ( u = user_findhandle( c->ic, l->data ) ) ) 299 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 ); 300 } 301 else if( ( u = user_find( irc, channel ) ) ) 302 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 ); 303 304 irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" ); 341 #endif 342 } 343 344 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 345 { 346 /* [SH] This aliases the NickServ command to PRIVMSG root */ 347 /* [TV] This aliases the NS command to PRIVMSG root as well */ 348 root_command( irc, cmd + 1 ); 349 } 350 351 352 353 #if 0 354 static void irc_cmd_oper( irc_t *irc, char **cmd ) 355 { 356 if( global.conf->oper_pass && 357 ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? 358 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : 359 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) 360 { 361 irc_umode_set( irc, "+o", 1 ); 362 irc_send_num( irc, 381, ":Password accepted" ); 363 } 364 else 365 { 366 irc_send_num( irc, 432, ":Incorrect password" ); 367 } 368 } 369 370 static void irc_cmd_invite( irc_t *irc, char **cmd ) 371 { 372 char *nick = cmd[1], *channel = cmd[2]; 373 struct groupchat *c = irc_chat_by_channel( irc, channel ); 374 user_t *u = user_find( irc, nick ); 375 376 if( u && c && ( u->ic == c->ic ) ) 377 if( c->ic && c->ic->acc->prpl->chat_invite ) 378 { 379 c->ic->acc->prpl->chat_invite( c, u->handle, NULL ); 380 irc_send_num( irc, 341, "%s %s", nick, channel ); 381 return; 382 } 383 384 irc_send_num( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel ); 305 385 } 306 386 … … 320 400 { 321 401 if( u->online && u->away ) 322 irc_ reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );402 irc_send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host ); 323 403 else 324 irc_ reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );404 irc_send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); 325 405 } 326 406 } … … 377 457 buff[strlen(buff)-1] = '\0'; 378 458 379 irc_ reply( irc, 303, ":%s", buff );459 irc_send_num( irc, 303, ":%s", buff ); 380 460 } 381 461 … … 406 486 407 487 if( u && u->online ) 408 irc_ reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );488 irc_send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" ); 409 489 else 410 irc_ reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );490 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); 411 491 } 412 492 else if( cmd[i][0] == '-' ) … … 419 499 g_free( okey ); 420 500 421 irc_ reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );501 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 422 502 } 423 503 } … … 443 523 } 444 524 } 525 #endif 445 526 446 527 static void irc_cmd_away( irc_t *irc, char **cmd ) 447 528 { 448 user_t *u = user_find( irc, irc->nick ); 449 char *away = cmd[1]; 450 451 if( !u ) return; 452 453 if( away && *away ) 454 { 529 char *set; 530 531 if( cmd[1] && *cmd[1] ) 532 { 533 char away[strlen(cmd[1])+1]; 455 534 int i, j; 456 535 457 536 /* Copy away string, but skip control chars. Mainly because 458 537 Jabber really doesn't like them. */ 459 u->away = g_malloc( strlen( away ) + 1 ); 460 for( i = j = 0; away[i]; i ++ ) 461 if( ( u->away[j] = away[i] ) >= ' ' ) 538 for( i = j = 0; cmd[1][i]; i ++ ) 539 if( ( away[j] = cmd[1][i] ) >= ' ' ) 462 540 j ++; 463 u->away[j] = 0; 464 465 irc_reply( irc, 306, ":You're now away: %s", u->away ); 466 /* irc_umode_set( irc, irc->myhost, "+a" ); */ 467 } 468 else 469 { 470 if( u->away ) g_free( u->away ); 471 u->away = NULL; 472 /* irc_umode_set( irc, irc->myhost, "-a" ); */ 473 irc_reply( irc, 305, ":Welcome back" ); 474 } 475 476 set_setstr( &irc->set, "away", u->away ); 477 } 478 479 static void irc_cmd_whois( irc_t *irc, char **cmd ) 480 { 481 char *nick = cmd[1]; 482 user_t *u = user_find( irc, nick ); 483 484 if( u ) 485 { 486 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname ); 487 488 if( u->ic ) 489 irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user, 490 u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "", 491 u->ic->acc->prpl->name ); 492 else 493 irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); 494 495 if( !u->online ) 496 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 497 else if( u->away ) 498 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 499 if( u->status_msg ) 500 irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg ); 501 502 irc_reply( irc, 318, "%s :End of /WHOIS list", nick ); 503 } 504 else 505 { 506 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 507 } 508 } 509 510 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 511 { 512 /* For some reason irssi tries a whowas when whois fails. We can 513 ignore this, but then the user never gets a "user not found" 514 message from irssi which is a bit annoying. So just respond 515 with not-found and irssi users will get better error messages */ 516 517 irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] ); 518 irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] ); 519 } 520 521 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 522 { 523 /* [SH] This aliases the NickServ command to PRIVMSG root */ 524 /* [TV] This aliases the NS command to PRIVMSG root as well */ 525 root_command( irc, cmd + 1 ); 526 } 527 528 static void irc_cmd_motd( irc_t *irc, char **cmd ) 529 { 530 irc_motd( irc ); 531 } 532 533 static void irc_cmd_pong( irc_t *irc, char **cmd ) 534 { 535 /* We could check the value we get back from the user, but in 536 fact we don't care, we're just happy he's still alive. */ 537 irc->last_pong = gettime(); 538 irc->pinging = 0; 539 } 540 541 away[j] = '\0'; 542 543 irc_send_num( irc, 306, ":You're now away: %s", away ); 544 set = away; 545 } 546 else 547 { 548 irc_send_num( irc, 305, ":Welcome back" ); 549 set = NULL; 550 } 551 552 set_setstr( &irc->b->set, "away", set ); 553 } 554 555 #if 0 541 556 static void irc_cmd_version( irc_t *irc, char **cmd ) 542 557 { 543 irc_ reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );558 irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU ); 544 559 } 545 560 … … 572 587 ipc_to_master( cmd ); 573 588 574 irc_reply( irc, 382, "%s :Rehashing", global.conf_file ); 575 } 589 irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); 590 } 591 #endif 576 592 577 593 static const command_t irc_commands[] = { … … 581 597 { "quit", 0, irc_cmd_quit, 0 }, 582 598 { "ping", 0, irc_cmd_ping, 0 }, 599 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 600 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN }, 601 { "names", 1, irc_cmd_names, IRC_CMD_LOGGED_IN }, 602 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN }, 603 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN }, 604 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN }, 605 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN }, 606 { "mode", 1, irc_cmd_mode, IRC_CMD_LOGGED_IN }, 607 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 608 { "privmsg", 1, irc_cmd_privmsg, 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 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN }, 612 #if 0 583 613 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 584 { "mode", 1, irc_cmd_mode, IRC_CMD_LOGGED_IN },585 { "names", 0, irc_cmd_names, IRC_CMD_LOGGED_IN },586 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN },587 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN },588 614 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 589 { "privmsg", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN },590 615 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 591 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN },592 616 { "userhost", 1, irc_cmd_userhost, IRC_CMD_LOGGED_IN }, 593 617 { "ison", 1, irc_cmd_ison, IRC_CMD_LOGGED_IN }, 594 618 { "watch", 1, irc_cmd_watch, IRC_CMD_LOGGED_IN }, 595 619 { "topic", 1, irc_cmd_topic, IRC_CMD_LOGGED_IN }, 596 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN },597 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN },598 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN },599 { "nickserv", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN },600 { "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN },601 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN },602 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN },603 620 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 604 621 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, … … 610 627 { "restart", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 611 628 { "kill", 2, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 629 #endif 612 630 { NULL } 613 631 }; … … 628 646 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 629 647 { 630 irc_ reply( irc, 462, ":Only allowed before logging in" );648 irc_send_num( irc, 462, ":Only allowed before logging in" ); 631 649 } 632 650 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 633 651 { 634 irc_ reply( irc, 451, ":Register first" );652 irc_send_num( irc, 451, ":Register first" ); 635 653 } 636 654 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 637 655 { 638 irc_ reply( irc, 481, ":Permission denied - You're not an IRC operator" );656 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" ); 639 657 } 640 658 else if( n_arg < irc_commands[i].required_parameters ) 641 659 { 642 irc_ reply( irc, 461, "%s :Need more parameters", cmd[0] );660 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] ); 643 661 } 644 662 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) … … 657 675 658 676 if( irc->status >= USTATUS_LOGGED_IN ) 659 irc_ reply( irc, 421, "%s :Unknown command", cmd[0] );660 } 677 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] ); 678 } -
lib/Makefile
r156bbd7 r21c87a7 10 10 11 11 # [SH] Program variables 12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o 12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ftutil.o 13 13 14 14 CFLAGS += -Wall -
lib/misc.c
r156bbd7 r21c87a7 649 649 return ret; 650 650 } 651 652 char **split_command_parts( char *command ) 653 { 654 static char *cmd[IRC_MAX_ARGS+1]; 655 char *s, q = 0; 656 int k; 657 658 memset( cmd, 0, sizeof( cmd ) ); 659 cmd[0] = command; 660 k = 1; 661 for( s = command; *s && k < IRC_MAX_ARGS; s ++ ) 662 if( *s == ' ' && !q ) 663 { 664 *s = 0; 665 while( *++s == ' ' ); 666 if( *s == '"' || *s == '\'' ) 667 { 668 q = *s; 669 s ++; 670 } 671 if( *s ) 672 { 673 cmd[k++] = s; 674 s --; 675 } 676 else 677 { 678 break; 679 } 680 } 681 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) 682 { 683 char *cpy; 684 685 for( cpy = s; *cpy; cpy ++ ) 686 cpy[0] = cpy[1]; 687 } 688 else if( *s == q ) 689 { 690 q = *s = 0; 691 } 692 693 /* Full zero-padding for easier argc checking. */ 694 while( k <= IRC_MAX_ARGS ) 695 cmd[k++] = NULL; 696 697 return cmd; 698 } -
lib/misc.h
r156bbd7 r21c87a7 69 69 G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); 70 70 71 G_MODULE_EXPORT char **split_command_parts( char *command ); 72 71 73 #endif -
nick.c
r156bbd7 r21c87a7 78 78 79 79 nick_strip( nick ); 80 if( set_getbool( &acc-> irc->set, "lcnicks" ) )80 if( set_getbool( &acc->bee->set, "lcnicks" ) ) 81 81 nick_lc( nick ); 82 82 } … … 92 92 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) 93 93 { 94 irc_t *irc = (irc_t*) acc->bee->ui_data; 94 95 int inf_protection = 256; 95 96 96 97 /* Now, find out if the nick is already in use at the moment, and make 97 98 subtle changes to make it unique. */ 98 while( !nick_ok( nick ) || user_find( acc->irc, nick ) )99 while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) ) 99 100 { 100 101 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) … … 112 113 int i; 113 114 114 irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! "115 116 117 118 119 120 irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );115 irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! " 116 "This used to be a fatal BitlBee bug, but we tried to fix it. " 117 "This message should *never* appear anymore. " 118 "If it does, please *do* send us a bug report! " 119 "Please send all the following lines in your report:" ); 120 121 irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); 121 122 for( i = 0; i < MAX_NICK_LENGTH; i ++ ) 122 irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );123 124 irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "125 126 123 irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); 124 125 irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " 126 "Good luck, and please don't forget to paste the lines up here " 127 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); 127 128 128 129 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); -
protocols/Makefile
r156bbd7 r21c87a7 10 10 11 11 # [SH] Program variables 12 objects = nogaim.o 12 objects = account.o bee.o bee_ft.o bee_user.o nogaim.o 13 13 14 14 15 # [SH] The next two lines should contain the directory name (in $(subdirs)) -
protocols/jabber/Makefile
r156bbd7 r21c87a7 10 10 11 11 # [SH] Program variables 12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s asl.o12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o 13 13 14 14 CFLAGS += -Wall -
protocols/jabber/iq.c
r156bbd7 r21c87a7 91 91 pack = 0; 92 92 } 93 else if( strcmp( s, XMLNS_DISCO VER) == 0 )94 { 95 const char *features[] = { XMLNS_DISCO VER,93 else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 ) 94 { 95 const char *features[] = { XMLNS_DISCO_INFO, 96 96 XMLNS_VERSION, 97 97 XMLNS_TIME, … … 99 99 XMLNS_MUC, 100 100 XMLNS_PING, 101 XMLNS_SI, 102 XMLNS_BYTESTREAMS, 103 XMLNS_FILETRANSFER, 101 104 NULL }; 102 105 const char **f; … … 118 121 { 119 122 xt_free_node( reply ); 120 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );123 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); 121 124 pack = 0; 122 125 } … … 124 127 else if( strcmp( type, "set" ) == 0 ) 125 128 { 126 if( !( c = xt_find_node( node->children, "query" ) ) || 127 !( s = xt_find_attr( c, "xmlns" ) ) ) 129 if( ( c = xt_find_node( node->children, "si" ) ) && 130 ( s = xt_find_attr( c, "xmlns" ) ) && 131 ( strcmp( s, XMLNS_SI ) == 0 ) ) 132 { 133 return jabber_si_handle_request( ic, node, c ); 134 } 135 else if( !( c = xt_find_node( node->children, "query" ) ) || 136 !( s = xt_find_attr( c, "xmlns" ) ) ) 128 137 { 129 138 imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); 130 139 return XT_HANDLED; 131 140 } 132 141 else if( strcmp( s, XMLNS_ROSTER ) == 0 ) 142 { 133 143 /* This is a roster push. XMPP servers send this when someone 134 144 was added to (or removed from) the buddy list. AFAIK they're 135 145 sent even if we added this buddy in our own session. */ 136 if( strcmp( s, XMLNS_ROSTER ) == 0 )137 {138 146 int bare_len = strlen( ic->acc->user ); 139 147 … … 152 160 153 161 xt_free_node( reply ); 154 reply = jabber_make_error_packet( node, "not-allowed", "cancel" );162 reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL ); 155 163 pack = 0; 156 164 } 157 165 } 166 else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 ) 167 { 168 /* Bytestream Request (stage 2 of file transfer) */ 169 return jabber_bs_recv_request( ic, node, c ); 170 } 158 171 else 159 172 { 160 173 xt_free_node( reply ); 161 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );174 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); 162 175 pack = 0; 163 176 } … … 379 392 if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 380 393 { 381 if( initial || imcb_find_buddy(ic, jid ) == NULL )394 if( initial || bee_user_by_handle( ic->bee, ic, jid ) == NULL ) 382 395 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 383 396 group->text : NULL ); … … 577 590 strcmp( s, "result" ) == 0 ) 578 591 { 579 if( imcb_find_buddy(ic, jid ) == NULL )592 if( bee_user_by_handle( ic->bee, ic, jid ) == NULL ) 580 593 imcb_add_buddy( ic, jid, NULL ); 581 594 } … … 609 622 return st; 610 623 } 624 625 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); 626 627 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ) 628 { 629 struct xt_node *node, *query; 630 struct jabber_buddy *bud; 631 632 if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL ) 633 { 634 /* Who cares about the unknown... */ 635 imcb_log( ic, "Couldn't find buddy: %s", bare_jid); 636 return XT_HANDLED; 637 } 638 639 if( bud->features ) /* been here already */ 640 return XT_HANDLED; 641 642 node = xt_new_node( "query", NULL, NULL ); 643 xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO ); 644 645 if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) ) 646 { 647 imcb_log( ic, "WARNING: Couldn't generate feature query" ); 648 xt_free_node( node ); 649 return XT_HANDLED; 650 } 651 652 jabber_cache_add( ic, query, jabber_iq_parse_features ); 653 654 return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; 655 } 656 657 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) 658 { 659 struct xt_node *c; 660 struct jabber_buddy *bud; 661 char *feature, *xmlns, *from; 662 663 if( !( from = xt_find_attr( node, "from" ) ) || 664 !( c = xt_find_node( node->children, "query" ) ) || 665 !( xmlns = xt_find_attr( c, "xmlns" ) ) || 666 !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) ) 667 { 668 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); 669 return XT_HANDLED; 670 } 671 if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) 672 { 673 /* Who cares about the unknown... */ 674 imcb_log( ic, "Couldn't find buddy: %s", from ); 675 return XT_HANDLED; 676 } 677 678 c = c->children; 679 while( ( c = xt_find_node( c, "feature" ) ) ) 680 { 681 feature = xt_find_attr( c, "var" ); 682 if( feature ) 683 bud->features = g_slist_append( bud->features, g_strdup( feature ) ); 684 c = c->next; 685 } 686 687 return XT_HANDLED; 688 } 689 690 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); 691 692 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ) 693 { 694 struct xt_node *node, *query; 695 struct jabber_data *jd = ic->proto_data; 696 697 node = xt_new_node( "query", NULL, NULL ); 698 xt_add_attr( node, "xmlns", xmlns ); 699 700 if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) ) 701 { 702 imcb_log( ic, "WARNING: Couldn't generate server query" ); 703 xt_free_node( node ); 704 } 705 706 jd->have_streamhosts--; 707 jabber_cache_add( ic, query, jabber_iq_parse_server_features ); 708 709 return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; 710 } 711 712 /* 713 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info 714 */ 715 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) 716 { 717 struct xt_node *c; 718 struct jabber_data *jd = ic->proto_data; 719 char *xmlns, *from; 720 721 if( !( c = xt_find_node( node->children, "query" ) ) || 722 !( from = xt_find_attr( node, "from" ) ) || 723 !( xmlns = xt_find_attr( c, "xmlns" ) ) ) 724 { 725 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); 726 return XT_HANDLED; 727 } 728 729 jd->have_streamhosts++; 730 731 if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 ) 732 { 733 char *itemjid; 734 735 /* answer from server */ 736 737 c = c->children; 738 while( ( c = xt_find_node( c, "item" ) ) ) 739 { 740 itemjid = xt_find_attr( c, "jid" ); 741 742 if( itemjid ) 743 jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO ); 744 745 c = c->next; 746 } 747 } 748 else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) 749 { 750 char *category, *type; 751 752 /* answer from potential proxy */ 753 754 c = c->children; 755 while( ( c = xt_find_node( c, "identity" ) ) ) 756 { 757 category = xt_find_attr( c, "category" ); 758 type = xt_find_attr( c, "type" ); 759 760 if( type && ( strcmp( type, "bytestreams" ) == 0 ) && 761 category && ( strcmp( category, "proxy" ) == 0 ) ) 762 jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS ); 763 764 c = c->next; 765 } 766 } 767 else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 ) 768 { 769 char *host, *jid, *port_s; 770 int port; 771 772 /* answer from proxy */ 773 774 if( ( c = xt_find_node( c->children, "streamhost" ) ) && 775 ( host = xt_find_attr( c, "host" ) ) && 776 ( port_s = xt_find_attr( c, "port" ) ) && 777 ( sscanf( port_s, "%d", &port ) == 1 ) && 778 ( jid = xt_find_attr( c, "jid" ) ) ) 779 { 780 jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 ); 781 782 sh->jid = g_strdup( jid ); 783 sh->host = g_strdup( host ); 784 g_snprintf( sh->port, sizeof( sh->port ), "%u", port ); 785 786 imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port ); 787 jd->streamhosts = g_slist_append( jd->streamhosts, sh ); 788 } 789 } 790 791 if( jd->have_streamhosts == 0 ) 792 jd->have_streamhosts++; 793 794 return XT_HANDLED; 795 } -
protocols/jabber/jabber.c
r156bbd7 r21c87a7 65 65 66 66 s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); 67 68 s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc ); 67 69 68 70 s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); … … 264 266 struct jabber_data *jd = ic->proto_data; 265 267 268 while( jd->filetransfers ) 269 imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" ); 270 271 while( jd->streamhosts ) 272 { 273 jabber_streamhost_t *sh = jd->streamhosts->data; 274 jd->streamhosts = g_slist_remove( jd->streamhosts, sh ); 275 g_free( sh->jid ); 276 g_free( sh->host ); 277 g_free( sh ); 278 } 279 266 280 if( jd->fd >= 0 ) 267 281 jabber_end_stream( ic ); … … 544 558 ret->send_typing = jabber_send_typing; 545 559 ret->handle_cmp = g_strcasecmp; 560 ret->transfer_request = jabber_si_transfer_request; 546 561 547 562 register_protocol( ret ); -
protocols/jabber/jabber.h
r156bbd7 r21c87a7 61 61 } jabber_buddy_flags_t; 62 62 63 /* Stores a streamhost's (a.k.a. proxy) data */ 64 typedef struct 65 { 66 char *jid; 67 char *host; 68 char port[6]; 69 } jabber_streamhost_t; 70 63 71 typedef enum 64 72 { … … 91 99 GHashTable *node_cache; 92 100 GHashTable *buddies; 101 102 GSList *filetransfers; 103 GSList *streamhosts; 104 int have_streamhosts; 93 105 }; 94 106 … … 127 139 struct jabber_away_state *away_state; 128 140 char *away_message; 141 GSList *features; 129 142 130 143 time_t last_msg; … … 140 153 char *my_full_jid; /* Separate copy because of case sensitivity. */ 141 154 struct jabber_buddy *me; 155 }; 156 157 struct jabber_transfer 158 { 159 /* bitlbee's handle for this transfer */ 160 file_transfer_t *ft; 161 162 /* the stream's private handle */ 163 gpointer streamhandle; 164 165 /* timeout for discover queries */ 166 gint disco_timeout; 167 gint disco_timeout_fired; 168 169 struct im_connection *ic; 170 171 struct jabber_buddy *bud; 172 173 int watch_in; 174 int watch_out; 175 176 char *ini_jid; 177 char *tgt_jid; 178 char *iq_id; 179 char *sid; 180 int accepted; 181 182 size_t bytesread, byteswritten; 183 int fd; 184 struct sockaddr_storage saddr; 142 185 }; 143 186 … … 167 210 168 211 /* Some supported extensions/legacy stuff */ 169 #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ 170 #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ 171 #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ 172 #define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ 173 #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ 174 #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ 175 #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ 176 #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ 177 #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ 178 #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */ 179 #define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ 212 #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ 213 #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ 214 #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ 215 #define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ 216 #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ 217 #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ 218 #define XMLNS_XDATA "jabber:x:data" /* XEP-0004 */ 219 #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* XEP-0085 */ 220 #define XMLNS_DISCO_INFO "http://jabber.org/protocol/disco#info" /* XEP-0030 */ 221 #define XMLNS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" /* XEP-0030 */ 222 #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ 223 #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user" /* XEP-0045 */ 224 #define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ 225 #define XMLNS_FEATURE "http://jabber.org/protocol/feature-neg" /* XEP-0020 */ 226 #define XMLNS_SI "http://jabber.org/protocol/si" /* XEP-0095 */ 227 #define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */ 228 #define XMLNS_BYTESTREAMS "http://jabber.org/protocol/bytestreams" /* XEP-0065 */ 229 #define XMLNS_IBB "http://jabber.org/protocol/ibb" /* XEP-0047 */ 180 230 181 231 /* iq.c */ … … 187 237 int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ); 188 238 int jabber_remove_from_roster( struct im_connection *ic, char *handle ); 239 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ); 240 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ); 241 242 /* si.c */ 243 int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode ); 244 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); 245 void jabber_si_free_transfer( file_transfer_t *ft); 246 247 /* s5bytestream.c */ 248 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode); 249 gboolean jabber_bs_send_start( struct jabber_transfer *tf ); 250 gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len ); 189 251 190 252 /* message.c */ … … 200 262 char *set_eval_tls( set_t *set, char *value ); 201 263 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); 202 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );264 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ); 203 265 void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ); 204 266 struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); -
protocols/jabber/jabber_util.c
r156bbd7 r21c87a7 99 99 } 100 100 101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ) 102 102 { 103 103 struct xt_node *node, *c; … … 111 111 c = xt_new_node( "error", NULL, c ); 112 112 xt_add_attr( c, "type", err_type ); 113 114 /* Add the error code, if present */ 115 if (err_code) 116 xt_add_attr( c, "code", err_code ); 113 117 114 118 /* To make the actual error packet, we copy the original packet and … … 275 279 presence_send_request( bla->ic, bla->handle, "subscribed" ); 276 280 277 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 278 imcb_ask_add( bla->ic, bla->handle, NULL ); 281 imcb_ask_add( bla->ic, bla->handle, NULL ); 279 282 280 283 g_free( bla->handle ); … … 458 461 459 462 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && 460 ( bare_exists || imcb_find_buddy(ic, jid ) ) )463 ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) ) 461 464 { 462 465 *s = '/'; … … 479 482 if( bud == NULL ) 480 483 /* No match. Create it now? */ 481 return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? 484 return ( ( flags & GET_BUDDY_CREAT ) && 485 bee_user_by_handle( ic->bee, ic, jid_ ) ) ? 482 486 jabber_buddy_add( ic, jid_ ) : NULL; 483 487 else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) -
protocols/msn/msn.c
r156bbd7 r21c87a7 78 78 if( md ) 79 79 { 80 /** Disabling MSN ft support for now. 81 while( md->filetransfers ) { 82 imcb_file_canceled( md->filetransfers->data, "Closing connection" ); 83 } 84 */ 85 80 86 if( md->fd >= 0 ) 81 87 closesocket( md->fd ); … … 327 333 ret->send_typing = msn_send_typing; 328 334 ret->handle_cmp = g_strcasecmp; 335 //ret->transfer_request = msn_ftp_transfer_request; 329 336 330 337 register_protocol(ret); -
protocols/msn/msn.h
r156bbd7 r21c87a7 69 69 int sb_failures; 70 70 time_t first_sb_failure; 71 GSList *filetransfers; 71 72 72 73 const struct msn_away_state *away_state; … … 181 182 int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); 182 183 184 /* invitation.c */ 185 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); 186 183 187 #endif //_MSN_H -
protocols/msn/msn_util.c
r156bbd7 r21c87a7 96 96 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); 97 97 98 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 99 imcb_ask_add( bla->ic, bla->handle, NULL ); 98 imcb_ask_add( bla->ic, bla->handle, NULL ); 100 99 101 100 g_free( bla->handle ); -
protocols/msn/sb.c
r156bbd7 r21c87a7 29 29 #include "passport.h" 30 30 #include "md5.h" 31 #include "invitation.h" 31 32 32 33 static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); … … 168 169 169 170 /* Build the message. Convert LF to CR-LF for normal messages. */ 170 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 ) 171 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 ) 172 { 173 i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user ); 174 buf = g_new0( char, i ); 175 i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user ); 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 } 182 else 171 183 { 172 184 buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 ); … … 181 193 buf[i++] = text[j]; 182 194 } 183 }184 else185 {186 i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );187 buf = g_new0( char, i );188 i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );189 195 } 190 196 … … 685 691 } 686 692 } 693 #if 0 694 // Disable MSN ft support for now. 687 695 else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 ) 688 696 { 689 char *itype = msn_findheader( body, "Application-GUID:", blen ); 690 char buf[1024]; 697 char *command = msn_findheader( body, "Invitation-Command:", blen ); 698 char *cookie = msn_findheader( body, "Invitation-Cookie:", blen ); 699 unsigned int icookie; 691 700 692 701 g_free( ct ); 693 702 694 *buf = 0; 695 696 if( !itype ) 697 return( 1 ); 698 699 /* File transfer. */ 700 if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 ) 701 { 702 char *name = msn_findheader( body, "Application-File:", blen ); 703 char *size = msn_findheader( body, "Application-FileSize:", blen ); 704 705 if( name && size ) 706 { 707 g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n" 708 "Filetransfers are not supported by BitlBee for now...", name, size ); 709 } 710 else 711 { 712 strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" ); 713 } 714 715 if( name ) g_free( name ); 716 if( size ) g_free( size ); 717 } 718 else 719 { 720 char *iname = msn_findheader( body, "Application-Name:", blen ); 721 722 g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>", 723 itype, iname ? iname : "no name" ); 724 725 if( iname ) g_free( iname ); 726 } 727 728 g_free( itype ); 729 730 if( !*buf ) 731 return( 1 ); 732 733 if( sb->who ) 734 { 735 imcb_buddy_msg( ic, cmd[1], buf, 0, 0 ); 736 } 737 else if( sb->chat ) 738 { 739 imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 ); 740 } 741 else 742 { 743 /* PANIC! */ 744 } 703 /* Every invite should have both a Command and Cookie header */ 704 if( !command || !cookie ) { 705 g_free( command ); 706 g_free( cookie ); 707 imcb_log( ic, "Warning: No command or cookie from %s", sb->who ); 708 return 1; 709 } 710 711 icookie = strtoul( cookie, NULL, 10 ); 712 g_free( cookie ); 713 714 if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) { 715 msn_invitation_invite( sb, cmd[1], icookie, body, blen ); 716 } else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) { 717 msn_invitation_accept( sb, cmd[1], icookie, body, blen ); 718 } else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) { 719 msn_invitation_cancel( sb, cmd[1], icookie, body, blen ); 720 } else { 721 imcb_log( ic, "Warning: Received invalid invitation with " 722 "command %s from %s", command, sb->who ); 723 } 724 725 g_free( command ); 726 } 727 #endif 728 else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) 729 { 730 imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not " 731 "support msnmsgrp2p yet.", sb->who ); 732 g_free( ct ); 745 733 } 746 734 else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 ) -
protocols/nogaim.c
r156bbd7 r21c87a7 38 38 #include "chat.h" 39 39 40 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );41 static char *format_timestamp( irc_t *irc, time_t msg_ts );42 43 40 GSList *connections; 44 41 … … 92 89 } 93 90 #endif 94 95 /* nogaim.c */96 91 97 92 GList *protocols = NULL; … … 126 121 } 127 122 128 /* nogaim.c */129 123 void nogaim_init() 130 124 { … … 162 156 GSList *get_connections() { return connections; } 163 157 164 /* multi.c */165 166 158 struct im_connection *imcb_new( account_t *acc ) 167 159 { … … 170 162 ic = g_new0( struct im_connection, 1 ); 171 163 172 ic-> irc = acc->irc;164 ic->bee = acc->bee; 173 165 ic->acc = acc; 174 166 acc->ic = ic; … … 184 176 185 177 /* Destroy the pointer to this connection from the account list */ 186 for( a = ic-> irc->accounts; a; a = a->next )178 for( a = ic->bee->accounts; a; a = a->next ) 187 179 if( a->ic == ic ) 188 180 { … … 205 197 va_end( params ); 206 198 207 if( ( g_strcasecmp( set_getstr( &ic-> irc->set, "strip_html" ), "always" ) == 0 ) ||208 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic-> irc->set, "strip_html" ) ) )199 if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || 200 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) 209 201 strip_html( text ); 210 202 211 203 /* Try to find a different connection on the same protocol. */ 212 for( a = ic-> irc->accounts; a; a = a->next )204 for( a = ic->bee->accounts; a; a = a->next ) 213 205 if( a->prpl == ic->acc->prpl && a->ic != ic ) 214 206 break; … … 216 208 /* If we found one, include the screenname in the message. */ 217 209 if( a ) 218 irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 210 /* FIXME(wilmer): ui_log callback or so */ 211 irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 219 212 else 220 irc_usermsg( ic-> irc, "%s - %s", ic->acc->prpl->name, text );213 irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text ); 221 214 222 215 g_free( text ); … … 269 262 void imcb_connected( struct im_connection *ic ) 270 263 { 271 irc_t *irc = ic->irc;272 struct chat *c;273 user_t *u;274 275 264 /* MSN servers sometimes redirect you to a different server and do 276 265 the whole login sequence again, so these "late" calls to this … … 279 268 return; 280 269 281 u = user_find( ic->irc, ic->irc->nick );282 283 270 imcb_log( ic, "Logged in" ); 284 271 … … 293 280 ic->acc->auto_reconnect_delay = 0; 294 281 282 /* 295 283 for( c = irc->chatrooms; c; c = c->next ) 296 284 { … … 301 289 chat_join( irc, c, NULL ); 302 290 } 291 */ 303 292 } 304 293 … … 308 297 309 298 a->reconnect = 0; 310 account_on( a-> irc, a );299 account_on( a->bee, a ); 311 300 312 301 return( FALSE ); /* Only have to run the timeout once */ … … 321 310 void imc_logout( struct im_connection *ic, int allow_reconnect ) 322 311 { 323 irc_t *irc = ic->irc; 324 user_t *t, *u; 312 bee_t *bee = ic->bee; 325 313 account_t *a; 314 GSList *l; 326 315 int delay; 327 316 … … 343 332 ic->away = NULL; 344 333 345 u = irc->users; 346 while( u ) 347 { 348 if( u->ic == ic ) 349 { 350 t = u->next; 351 user_del( irc, u->nick ); 352 u = t; 353 } 354 else 355 u = u->next; 356 } 357 358 query_del_by_conn( ic->irc, ic ); 359 360 for( a = irc->accounts; a; a = a->next ) 334 for( l = bee->users; l; ) 335 { 336 bee_user_t *bu = l->data; 337 GSList *next = l->next; 338 339 if( bu->ic == ic ) 340 bee_user_free( bee, bu ); 341 342 l = next; 343 } 344 345 //query_del_by_conn( ic->irc, ic ); 346 347 for( a = bee->accounts; a; a = a->next ) 361 348 if( a->ic == ic ) 362 349 break; … … 366 353 /* Uhm... This is very sick. */ 367 354 } 368 else if( allow_reconnect && set_getbool( & irc->set, "auto_reconnect" ) &&355 else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) && 369 356 set_getbool( &a->set, "auto_reconnect" ) && 370 357 ( delay = account_reconnect_delay( a ) ) > 0 ) … … 377 364 } 378 365 379 380 /* dialogs.c */381 382 366 void imcb_ask( struct im_connection *ic, char *msg, void *data, 383 367 query_callback doit, query_callback dont ) 384 368 { 385 query_add( ic->irc, ic, msg, doit, dont, data ); 386 } 387 388 389 /* list.c */ 369 query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data ); 370 } 390 371 391 372 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) 392 373 { 393 user_t *u; 394 char nick[MAX_NICK_LENGTH+1], *s; 395 irc_t *irc = ic->irc; 396 397 if( user_findhandle( ic, handle ) ) 398 { 399 if( set_getbool( &irc->set, "debug" ) ) 374 bee_user_t *bu; 375 bee_t *bee = ic->bee; 376 377 if( bee_user_by_handle( bee, ic, handle ) ) 378 { 379 if( set_getbool( &bee->set, "debug" ) ) 400 380 imcb_log( ic, "User already exists, ignoring add request: %s", handle ); 401 381 … … 408 388 } 409 389 410 memset( nick, 0, MAX_NICK_LENGTH + 1 ); 411 strcpy( nick, nick_get( ic->acc, handle ) ); 412 413 u = user_add( ic->irc, nick ); 414 415 // if( !realname || !*realname ) realname = nick; 416 // u->realname = g_strdup( realname ); 417 418 if( ( s = strchr( handle, '@' ) ) ) 419 { 420 u->host = g_strdup( s + 1 ); 421 u->user = g_strndup( handle, s - handle ); 422 } 423 else if( ic->acc->server ) 424 { 425 u->host = g_strdup( ic->acc->server ); 426 u->user = g_strdup( handle ); 427 428 /* s/ /_/ ... important for AOL screennames */ 429 for( s = u->user; *s; s ++ ) 430 if( *s == ' ' ) 431 *s = '_'; 432 } 433 else 434 { 435 u->host = g_strdup( ic->acc->prpl->name ); 436 u->user = g_strdup( handle ); 437 } 438 439 u->ic = ic; 440 u->handle = g_strdup( handle ); 441 if( group ) u->group = g_strdup( group ); 442 u->send_handler = buddy_send_handler; 443 u->last_typing_notice = 0; 444 } 445 446 struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ) 447 { 448 static struct buddy b[1]; 449 user_t *u; 450 451 u = user_findhandle( ic, handle ); 452 453 if( !u ) 454 return( NULL ); 455 456 memset( b, 0, sizeof( b ) ); 457 strncpy( b->name, handle, 80 ); 458 strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN ); 459 b->present = u->online; 460 b->ic = u->ic; 461 462 return( b ); 463 } 464 465 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ) 466 { 467 user_t *u = user_findhandle( ic, handle ); 468 char *set; 469 470 if( !u || !realname ) return; 471 472 if( g_strcasecmp( u->realname, realname ) != 0 ) 473 { 474 if( u->realname != u->nick ) g_free( u->realname ); 475 476 u->realname = g_strdup( realname ); 477 478 if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) 479 imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); 480 } 481 482 set = set_getstr( &ic->acc->set, "nick_source" ); 483 if( strcmp( set, "handle" ) != 0 ) 484 { 485 char *name = g_strdup( realname ); 486 487 if( strcmp( set, "first_name" ) == 0 ) 488 { 489 int i; 490 for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {} 491 name[i] = '\0'; 492 } 493 494 imcb_buddy_nick_hint( ic, handle, name ); 495 496 g_free( name ); 390 bu = bee_user_new( bee, ic, handle ); 391 bu->group = g_strdup( group ); 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 ); 497 408 } 498 409 } … … 500 411 void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) 501 412 { 502 user_t *u; 503 504 if( ( u = user_findhandle( ic, handle ) ) ) 505 user_del( ic->irc, u->nick ); 413 bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) ); 506 414 } 507 415 … … 510 418 void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) 511 419 { 420 #if 0 512 421 user_t *u = user_findhandle( ic, handle ); 513 422 char newnick[MAX_NICK_LENGTH+1], *orig_nick; … … 524 433 /* Some processing to make sure this string is a valid IRC nickname. */ 525 434 nick_strip( newnick ); 526 if( set_getbool( &ic-> irc->set, "lcnicks" ) )435 if( set_getbool( &ic->bee->set, "lcnicks" ) ) 527 436 nick_lc( newnick ); 528 437 … … 541 450 } 542 451 } 452 #endif 543 453 } 544 454 … … 585 495 data->ic = ic; 586 496 data->handle = g_strdup( handle ); 587 query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 497 query_add( (irc_t *) ic->bee->ui_data, ic, s, 498 imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 588 499 } 589 500 … … 610 521 611 522 /* TODO: Make a setting for this! */ 612 if( user_findhandle(ic, handle ) != NULL )523 if( bee_user_by_handle( ic->bee, ic, handle ) != NULL ) 613 524 return; 614 525 … … 617 528 data->ic = ic; 618 529 data->handle = g_strdup( handle ); 619 query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data ); 620 } 621 622 623 /* server.c */ 624 625 void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ) 626 { 627 user_t *u; 628 int oa, oo; 629 630 u = user_findhandle( ic, (char*) handle ); 631 632 if( !u ) 633 { 634 if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 ) 635 { 636 imcb_add_buddy( ic, (char*) handle, NULL ); 637 u = user_findhandle( ic, (char*) handle ); 638 } 639 else 640 { 641 if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) 642 { 643 imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle ); 644 imcb_log( ic, "flags = %d, state = %s, message = %s", flags, 645 state ? state : "NULL", message ? message : "NULL" ); 646 } 647 648 return; 649 } 650 } 651 652 oa = u->away != NULL; 653 oo = u->online; 654 655 g_free( u->away ); 656 g_free( u->status_msg ); 657 u->away = u->status_msg = NULL; 658 659 if( ( flags & OPT_LOGGED_IN ) && !u->online ) 660 { 661 irc_spawn( ic->irc, u ); 662 u->online = 1; 663 } 664 else if( !( flags & OPT_LOGGED_IN ) && u->online ) 665 { 666 struct groupchat *c; 667 668 irc_kill( ic->irc, u ); 669 u->online = 0; 670 671 /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */ 672 for( c = ic->groupchats; c; c = c->next ) 673 remove_chat_buddy_silent( c, handle ); 674 } 675 676 if( flags & OPT_AWAY ) 677 { 678 if( state && message ) 679 { 680 u->away = g_strdup_printf( "%s (%s)", state, message ); 681 } 682 else if( state ) 683 { 684 u->away = g_strdup( state ); 685 } 686 else if( message ) 687 { 688 u->away = g_strdup( message ); 689 } 690 else 691 { 692 u->away = g_strdup( "Away" ); 693 } 694 } 695 else 696 { 697 u->status_msg = g_strdup( message ); 698 } 699 700 /* LISPy... */ 701 if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ 702 ( u->online ) && /* Don't touch offline people */ 703 ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ 704 ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ 705 { 706 char *from; 707 708 if( set_getbool( &ic->irc->set, "simulate_netsplit" ) ) 709 { 710 from = g_strdup( ic->irc->myhost ); 711 } 712 else 713 { 714 from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick, 715 ic->irc->myhost ); 716 } 717 irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, 718 u->away?'-':'+', u->nick ); 719 g_free( from ); 720 } 721 } 722 723 void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at ) 724 { 725 irc_t *irc = ic->irc; 726 char *wrapped, *ts = NULL; 727 user_t *u; 728 729 u = user_findhandle( ic, handle ); 730 731 if( !u ) 732 { 733 char *h = set_getstr( &irc->set, "handle_unknown" ); 734 735 if( g_strcasecmp( h, "ignore" ) == 0 ) 736 { 737 if( set_getbool( &irc->set, "debug" ) ) 738 imcb_log( ic, "Ignoring message from unknown handle %s", handle ); 739 740 return; 741 } 742 else if( g_strncasecmp( h, "add", 3 ) == 0 ) 743 { 744 int private = set_getbool( &irc->set, "private" ); 745 746 if( h[3] ) 747 { 748 if( g_strcasecmp( h + 3, "_private" ) == 0 ) 749 private = 1; 750 else if( g_strcasecmp( h + 3, "_channel" ) == 0 ) 751 private = 0; 752 } 753 754 imcb_add_buddy( ic, handle, NULL ); 755 u = user_findhandle( ic, handle ); 756 u->is_private = private; 757 } 758 else 759 { 760 imcb_log( ic, "Message from unknown handle %s:", handle ); 761 u = user_find( irc, irc->mynick ); 762 } 763 } 764 765 if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || 766 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) 767 strip_html( msg ); 768 769 if( set_getbool( &ic->irc->set, "display_timestamps" ) && 770 ( ts = format_timestamp( irc, sent_at ) ) ) 771 { 772 char *new = g_strconcat( ts, msg, NULL ); 773 g_free( ts ); 774 ts = msg = new; 775 } 776 777 wrapped = word_wrap( msg, 425 ); 778 irc_msgfrom( irc, u->nick, wrapped ); 779 g_free( wrapped ); 780 g_free( ts ); 781 } 782 783 void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ) 784 { 785 user_t *u; 786 787 if( !set_getbool( &ic->irc->set, "typing_notice" ) ) 788 return; 789 790 if( ( u = user_findhandle( ic, handle ) ) ) 791 { 792 char buf[256]; 793 794 g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 ); 795 irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf ); 796 } 530 query_add( (irc_t *) ic->bee->ui_data, ic, s, 531 imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data ); 532 } 533 534 struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ) 535 { 536 return bee_user_by_handle( ic->bee, ic, handle ); 797 537 } 798 538 799 539 struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ) 800 540 { 541 #if 0 801 542 struct groupchat *c; 802 543 … … 816 557 c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); 817 558 818 if( set_getbool( &ic-> irc->set, "debug" ) )559 if( set_getbool( &ic->bee->set, "debug" ) ) 819 560 imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); 820 561 821 562 return c; 563 #endif 564 return NULL; 822 565 } 823 566 824 567 void imcb_chat_name_hint( struct groupchat *c, const char *name ) 825 568 { 569 #if 0 826 570 if( !c->joined ) 827 571 { … … 849 593 } 850 594 } 595 #endif 851 596 } 852 597 853 598 void imcb_chat_free( struct groupchat *c ) 854 599 { 600 #if 0 855 601 struct im_connection *ic = c->ic; 856 602 struct groupchat *l; 857 603 GList *ir; 858 604 859 if( set_getbool( &ic-> irc->set, "debug" ) )605 if( set_getbool( &ic->bee->set, "debug" ) ) 860 606 imcb_log( ic, "You were removed from conversation %p", c ); 861 607 … … 890 636 g_free( c ); 891 637 } 638 #endif 892 639 } 893 640 894 641 void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at ) 895 642 { 643 #if 0 896 644 struct im_connection *ic = c->ic; 897 645 char *wrapped; … … 904 652 u = user_findhandle( ic, who ); 905 653 906 if( ( g_strcasecmp( set_getstr( &ic-> irc->set, "strip_html" ), "always" ) == 0 ) ||907 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic-> irc->set, "strip_html" ) ) )654 if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || 655 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) 908 656 strip_html( msg ); 909 657 … … 922 670 } 923 671 g_free( wrapped ); 672 #endif 924 673 } 925 674 926 675 void imcb_chat_log( struct groupchat *c, char *format, ... ) 927 676 { 677 #if 0 928 678 irc_t *irc = c->ic->irc; 929 679 va_list params; … … 940 690 941 691 g_free( text ); 692 #endif 942 693 } 943 694 944 695 void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) 945 696 { 697 #if 0 946 698 struct im_connection *ic = c->ic; 947 699 user_t *u = NULL; … … 954 706 u = user_findhandle( ic, who ); 955 707 956 if( ( g_strcasecmp( set_getstr( &ic-> irc->set, "strip_html" ), "always" ) == 0 ) ||957 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic-> irc->set, "strip_html" ) ) )708 if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || 709 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) 958 710 strip_html( topic ); 959 711 … … 963 715 if( c->joined && u ) 964 716 irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); 965 } 966 967 968 /* buddy_chat.c */ 717 #endif 718 } 969 719 970 720 void imcb_chat_add_buddy( struct groupchat *b, const char *handle ) 971 721 { 722 #if 0 972 723 user_t *u = user_findhandle( b->ic, handle ); 973 724 int me = 0; 974 725 975 if( set_getbool( &b->ic-> irc->set, "debug" ) )726 if( set_getbool( &b->ic->bee->set, "debug" ) ) 976 727 imcb_log( b->ic, "User %s added to conversation %p", handle, b ); 977 728 … … 1000 751 b->in_room = g_list_append( b->in_room, g_strdup( handle ) ); 1001 752 } 753 #endif 1002 754 } 1003 755 … … 1005 757 void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason ) 1006 758 { 759 #if 0 1007 760 user_t *u; 1008 761 int me = 0; 1009 762 1010 if( set_getbool( &b->ic-> irc->set, "debug" ) )763 if( set_getbool( &b->ic->bee->set, "debug" ) ) 1011 764 imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" ); 1012 765 … … 1028 781 if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) ) 1029 782 irc_part( b->ic->irc, u, b->channel ); 1030 } 1031 783 #endif 784 } 785 786 #if 0 1032 787 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ) 1033 788 { … … 1048 803 } 1049 804 1050 return( 0 ); 1051 } 805 return 0; 806 } 807 #endif 1052 808 1053 809 1054 810 /* Misc. BitlBee stuff which shouldn't really be here */ 1055 811 #if 0 1056 812 char *set_eval_away_devoice( set_t *set, char *value ) 1057 813 { … … 1066 822 /* Horror.... */ 1067 823 1068 if( st != set_getbool( &irc-> set, "away_devoice" ) )824 if( st != set_getbool( &irc->b->set, "away_devoice" ) ) 1069 825 { 1070 826 char list[80] = ""; … … 1108 864 return value; 1109 865 } 1110 1111 char *set_eval_timezone( set_t *set, char *value ) 1112 { 1113 char *s; 1114 1115 if( strcmp( value, "local" ) == 0 || 1116 strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 ) 1117 return value; 1118 1119 /* Otherwise: +/- at the beginning optional, then one or more numbers, 1120 possibly followed by a colon and more numbers. Don't bother bound- 1121 checking them since users are free to shoot themselves in the foot. */ 1122 s = value; 1123 if( *s == '+' || *s == '-' ) 1124 s ++; 1125 1126 /* \d+ */ 1127 if( !isdigit( *s ) ) 1128 return SET_INVALID; 1129 while( *s && isdigit( *s ) ) s ++; 1130 1131 /* EOS? */ 1132 if( *s == '\0' ) 1133 return value; 1134 1135 /* Otherwise, colon */ 1136 if( *s != ':' ) 1137 return SET_INVALID; 1138 s ++; 1139 1140 /* \d+ */ 1141 if( !isdigit( *s ) ) 1142 return SET_INVALID; 1143 while( *s && isdigit( *s ) ) s ++; 1144 1145 /* EOS */ 1146 return *s == '\0' ? value : SET_INVALID; 1147 } 1148 1149 static char *format_timestamp( irc_t *irc, time_t msg_ts ) 1150 { 1151 time_t now_ts = time( NULL ); 1152 struct tm now, msg; 1153 char *set; 1154 1155 /* If the timestamp is <= 0 or less than a minute ago, discard it as 1156 it doesn't seem to add to much useful info and/or might be noise. */ 1157 if( msg_ts <= 0 || msg_ts > now_ts - 60 ) 1158 return NULL; 1159 1160 set = set_getstr( &irc->set, "timezone" ); 1161 if( strcmp( set, "local" ) == 0 ) 1162 { 1163 localtime_r( &now_ts, &now ); 1164 localtime_r( &msg_ts, &msg ); 1165 } 1166 else 1167 { 1168 int hr, min = 0, sign = 60; 1169 1170 if( set[0] == '-' ) 1171 { 1172 sign *= -1; 1173 set ++; 1174 } 1175 else if( set[0] == '+' ) 1176 { 1177 set ++; 1178 } 1179 1180 if( sscanf( set, "%d:%d", &hr, &min ) >= 1 ) 1181 { 1182 msg_ts += sign * ( hr * 60 + min ); 1183 now_ts += sign * ( hr * 60 + min ); 1184 } 1185 1186 gmtime_r( &now_ts, &now ); 1187 gmtime_r( &msg_ts, &msg ); 1188 } 1189 1190 if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday ) 1191 return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ", 1192 msg.tm_hour, msg.tm_min, msg.tm_sec ); 1193 else 1194 return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d " 1195 "%02d:%02d:%02d\x02]\x02 ", 1196 msg.tm_year + 1900, msg.tm_mon, msg.tm_mday, 1197 msg.tm_hour, msg.tm_min, msg.tm_sec ); 1198 } 866 #endif 1199 867 1200 868 /* The plan is to not allow straight calls to prpl functions anymore, but do 1201 869 them all from some wrappers. We'll start to define some down here: */ 1202 1203 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags )1204 {1205 char *buf = NULL;1206 int st;1207 1208 if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )1209 {1210 buf = escape_html( msg );1211 msg = buf;1212 }1213 1214 st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );1215 g_free( buf );1216 1217 return st;1218 }1219 870 1220 871 int imc_chat_msg( struct groupchat *c, char *msg, int flags ) … … 1245 896 1246 897 away = set_getstr( &ic->acc->set, "away" ) ? 1247 : set_getstr( &ic-> irc->set, "away" );898 : set_getstr( &ic->bee->set, "away" ); 1248 899 if( away && *away ) 1249 900 { … … 1256 907 away = NULL; 1257 908 msg = set_getstr( &ic->acc->set, "status" ) ? 1258 : set_getstr( &ic-> irc->set, "status" );909 : set_getstr( &ic->bee->set, "status" ); 1259 910 } 1260 911 -
protocols/nogaim.h
r156bbd7 r21c87a7 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 04Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 45 45 #include "proxy.h" 46 46 #include "query.h" 47 #include "md5.h" 48 #include "ft.h" 47 49 48 50 #define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */ … … 85 87 86 88 /* BitlBee */ 87 irc_t *irc;89 bee_t *bee; 88 90 89 91 struct groupchat *groupchats; … … 228 230 void (* auth_allow) (struct im_connection *, const char *who); 229 231 void (* auth_deny) (struct im_connection *, const char *who); 232 233 /* Incoming transfer request */ 234 void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle ); 230 235 }; 231 236 … … 281 286 G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ); 282 287 283 /* Buddy activity */284 /* To manipulate the status of a handle.285 * - flags can be |='d with OPT_* constants. You will need at least:286 * OPT_LOGGED_IN and OPT_AWAY.287 * - 'state' and 'message' can be NULL */288 G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );289 /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );290 /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */291 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );292 288 G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ); 289 G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ); 293 290 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); 294 291 … … 316 313 /* Actions, or whatever. */ 317 314 int imc_away_send_update( struct im_connection *ic ); 318 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );319 315 int imc_chat_msg( struct groupchat *c, char *msg, int flags ); 320 316 … … 325 321 326 322 /* Misc. stuff */ 327 char *set_eval_timezone( set_t *set, char *value );328 323 char *set_eval_away_devoice( set_t *set, char *value ); 329 324 gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); -
protocols/oscar/oscar.c
r156bbd7 r21c87a7 1190 1190 aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); 1191 1191 // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); 1192 if(imcb_find_buddy(data->ic, uin) == NULL) 1193 imcb_ask_add(data->ic, uin, NULL); 1192 imcb_ask_add(data->ic, uin, NULL); 1194 1193 1195 1194 g_free(uin); … … 1952 1951 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 1953 1952 if (odata->icq) { 1953 /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back? 1954 1954 struct buddy *budlight = imcb_find_buddy(g, who); 1955 1955 if (budlight) … … 1957 1957 if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) 1958 1958 aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7); 1959 */ 1959 1960 } else 1960 1961 aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); … … 2094 2095 switch (curitem->type) { 2095 2096 case 0x0000: /* Buddy */ 2096 if ((curitem->name) && (!imcb_ find_buddy(ic, nrm))) {2097 if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) { 2097 2098 char *realname = NULL; 2098 2099 -
protocols/twitter/twitter_lib.c
r156bbd7 r21c87a7 103 103 104 104 // Check if the buddy is allready in the buddy list. 105 if (! imcb_find_buddy(ic, name ))105 if (!bee_user_by_handle( ic->bee, ic, name )) 106 106 { 107 107 // The buddy is not in the list, add the buddy and set the status to logged in. -
query.c
r156bbd7 r21c87a7 64 64 } 65 65 66 if( g_strcasecmp( set_getstr( &irc-> set, "query_order" ), "lifo" ) == 0 || irc->queries == q )66 if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q ) 67 67 query_display( irc, q ); 68 68 … … 179 179 query_t *q; 180 180 181 if( g_strcasecmp( set_getstr( &irc-> set, "query_order" ), "fifo" ) == 0 )181 if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "fifo" ) == 0 ) 182 182 q = irc->queries; 183 183 else -
root_commands.c
r156bbd7 r21c87a7 26 26 #define BITLBEE_CORE 27 27 #include "commands.h" 28 #include "crypting.h"29 28 #include "bitlbee.h" 30 29 #include "help.h" … … 33 32 #include <string.h> 34 33 35 void root_command_string( irc_t *irc, user_t *u, char *command, int flags ) 36 { 37 char *cmd[IRC_MAX_ARGS]; 38 char *s; 39 int k; 40 char q = 0; 41 42 memset( cmd, 0, sizeof( cmd ) ); 43 cmd[0] = command; 44 k = 1; 45 for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ ) 46 if( *s == ' ' && !q ) 47 { 48 *s = 0; 49 while( *++s == ' ' ); 50 if( *s == '"' || *s == '\'' ) 51 { 52 q = *s; 53 s ++; 54 } 55 if( *s ) 56 { 57 cmd[k++] = s; 58 s --; 59 } 60 else 61 { 62 break; 63 } 64 } 65 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) 66 { 67 char *cpy; 68 69 for( cpy = s; *cpy; cpy ++ ) 70 cpy[0] = cpy[1]; 71 } 72 else if( *s == q ) 73 { 74 q = *s = 0; 75 } 76 cmd[k] = NULL; 77 78 root_command( irc, cmd ); 34 void root_command_string( irc_t *irc, char *command ) 35 { 36 root_command( irc, split_command_parts( command ) ); 79 37 } 80 38 … … 93 51 void root_command( irc_t *irc, char *cmd[] ) 94 52 { 95 int i ;53 int i, len; 96 54 97 55 if( !cmd[0] ) 98 56 return; 99 57 58 len = strlen( cmd[0] ); 100 59 for( i = 0; commands[i].command; i++ ) 101 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) 102 { 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 103 67 MIN_ARGS( commands[i].required_parameters ); 104 68 … … 162 126 irc->status |= USTATUS_IDENTIFIED; 163 127 irc_umode_set( irc, "+R", 1 ); 164 if( set_getbool( &irc-> set, "auto_connect" ) )128 if( set_getbool( &irc->b->set, "auto_connect" ) ) 165 129 cmd_account( irc, account_on ); 166 130 break; … … 202 166 storage_status_t status; 203 167 204 status = storage_remove (irc-> nick, cmd[1]);168 status = storage_remove (irc->user->nick, cmd[1]); 205 169 switch (status) { 206 170 case STORAGE_NO_SUCH_USER: … … 214 178 irc->status &= ~USTATUS_IDENTIFIED; 215 179 irc_umode_set( irc, "-R", 1 ); 216 irc_usermsg( irc, "Account `%s' removed", irc-> nick );180 irc_usermsg( irc, "Account `%s' removed", irc->user->nick ); 217 181 break; 218 182 default: … … 222 186 } 223 187 188 static void cmd_save( irc_t *irc, char **cmd ) 189 { 190 if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) 191 irc_usermsg( irc, "Please create an account first" ); 192 else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) 193 irc_usermsg( irc, "Configuration saved" ); 194 else 195 irc_usermsg( irc, "Configuration could not be saved!" ); 196 } 197 224 198 struct cmd_account_del_data 225 199 { … … 233 207 account_t *a; 234 208 235 for( a = cad->irc-> accounts; a && a != cad->a; a = a->next );209 for( a = cad->irc->b->accounts; a && a != cad->a; a = a->next ); 236 210 237 211 if( a == NULL ) … … 245 219 else 246 220 { 247 account_del( cad->irc , a );221 account_del( cad->irc->b, a ); 248 222 irc_usermsg( cad->irc, "Account deleted" ); 249 223 } … … 286 260 set_name = set_full; 287 261 288 head = &irc-> set;262 head = &irc->b->set; 289 263 } 290 264 else … … 357 331 account_t *a; 358 332 359 if( ( a = account_get( irc , id ) ) )333 if( ( a = account_get( irc->b, id ) ) ) 360 334 return &a->set; 361 335 else … … 405 379 } 406 380 407 a = account_add( irc , prpl, cmd[3], cmd[4] );381 a = account_add( irc->b, prpl, cmd[3], cmd[4] ); 408 382 if( cmd[5] ) 409 383 { … … 419 393 MIN_ARGS( 2 ); 420 394 421 if( !( a = account_get( irc , cmd[2] ) ) )395 if( !( a = account_get( irc->b, cmd[2] ) ) ) 422 396 { 423 397 irc_usermsg( irc, "Invalid account" ); … … 441 415 "set' command. Are you sure you want to delete this " 442 416 "account?", a->prpl->name, a->user ); 443 query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );417 //query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad ); 444 418 g_free( msg ); 445 419 } … … 452 426 irc_usermsg( irc, "Account list:" ); 453 427 454 for( a = irc-> accounts; a; a = a->next )428 for( a = irc->b->accounts; a; a = a->next ) 455 429 { 456 430 char *con; … … 475 449 if( cmd[2] ) 476 450 { 477 if( ( a = account_get( irc , cmd[2] ) ) )451 if( ( a = account_get( irc->b, cmd[2] ) ) ) 478 452 { 479 453 if( a->ic ) … … 484 458 else 485 459 { 486 account_on( irc , a );460 account_on( irc->b, a ); 487 461 } 488 462 } … … 495 469 else 496 470 { 497 if ( irc->accounts ) { 471 if ( irc->b->accounts ) 472 { 498 473 irc_usermsg( irc, "Trying to get all accounts connected..." ); 499 474 500 for( a = irc-> accounts; a; a = a->next )475 for( a = irc->b->accounts; a; a = a->next ) 501 476 if( !a->ic && a->auto_connect ) 502 account_on( irc , a );477 account_on( irc->b, a ); 503 478 } 504 479 else … … 514 489 irc_usermsg( irc, "Deactivating all active (re)connections..." ); 515 490 516 for( a = irc-> accounts; a; a = a->next )491 for( a = irc->b->accounts; a; a = a->next ) 517 492 { 518 493 if( a->ic ) 519 account_off( irc , a );494 account_off( irc->b, a ); 520 495 else if( a->reconnect ) 521 496 cancel_auto_reconnect( a ); 522 497 } 523 498 } 524 else if( ( a = account_get( irc , cmd[2] ) ) )499 else if( ( a = account_get( irc->b, cmd[2] ) ) ) 525 500 { 526 501 if( a->ic ) 527 502 { 528 account_off( irc , a );503 account_off( irc->b, a ); 529 504 } 530 505 else if( a->reconnect ) … … 569 544 } 570 545 571 if( !( a = account_get( irc , cmd[1] ) ) )546 if( !( a = account_get( irc->b, cmd[1] ) ) ) 572 547 { 573 548 irc_usermsg( irc, "Invalid account" ); … … 587 562 return; 588 563 } 589 else if( user_find( irc, cmd[3] ) )564 else if( irc_user_by_name( irc, cmd[3] ) ) 590 565 { 591 566 irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); … … 601 576 a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); 602 577 else 603 /* Yeah, officially this is a call-*back*... So if we just 604 called add_buddy, we'll wait for the IM server to respond 605 before we do this. */ 606 imcb_add_buddy( a->ic, cmd[2], NULL ); 578 /* Only for add -tmp. For regular adds, this callback will 579 be called once the IM server confirms. */ 580 bee_user_new( irc->b, a->ic, cmd[2] ); 607 581 608 582 irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2] ); 583 } 584 585 static void cmd_remove( irc_t *irc, char **cmd ) 586 { 587 irc_user_t *iu; 588 bee_user_t *bu; 589 char *s; 590 591 if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) ) 592 { 593 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); 594 return; 595 } 596 s = g_strdup( bu->handle ); 597 598 bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL ); 599 nick_del( bu->ic->acc, bu->handle ); 600 //TODO(wilmer): bee_user_free() and/or let the IM mod do it? irc_user_free( irc, cmd[1] ); 601 602 irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); 603 g_free( s ); 604 605 return; 609 606 } 610 607 … … 616 613 if( !cmd[2] ) 617 614 { 618 user_t *u = user_find( irc, cmd[1] );619 if( ! u || !u->ic)615 irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); 616 if( !iu || !iu->bu ) 620 617 { 621 618 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 622 619 return; 623 620 } 624 ic = u->ic;625 cmd[2] = u->handle;626 } 627 else if( !( a = account_get( irc , cmd[1] ) ) )621 ic = iu->bu->ic; 622 cmd[2] = iu->bu->handle; 623 } 624 else if( !( a = account_get( irc->b, cmd[1] ) ) ) 628 625 { 629 626 irc_usermsg( irc, "Invalid account" ); … … 648 645 static void cmd_rename( irc_t *irc, char **cmd ) 649 646 { 650 user_t *u; 651 652 if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) 647 irc_user_t *iu; 648 649 iu = irc_user_by_name( irc, cmd[1] ); 650 651 if( iu == NULL ) 652 { 653 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 654 } 655 else if( iu == irc->user ) 653 656 { 654 657 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 655 658 } 656 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 657 { 658 if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) ) 659 { 660 u = user_find( irc, irc->nick ); 661 662 irc_part( irc, u, irc->channel ); 663 g_free( irc->channel ); 664 irc->channel = g_strdup( cmd[2] ); 665 irc_join( irc, u, irc->channel ); 666 667 if( strcmp( cmd[0], "set_rename" ) != 0 ) 668 set_setstr( &irc->set, "control_channel", cmd[2] ); 669 } 670 } 671 else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) 659 else if( !nick_ok( cmd[2] ) ) 660 { 661 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); 662 } 663 else if( irc_user_by_name( irc, cmd[2] ) ) 672 664 { 673 665 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 674 666 } 675 else if( !nick_ok( cmd[2] ) ) 676 { 677 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); 678 } 679 else if( !( u = user_find( irc, cmd[1] ) ) ) 680 { 681 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 682 } 683 else 684 { 685 user_rename( irc, cmd[1], cmd[2] ); 686 irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] ); 687 if( g_strcasecmp( cmd[1], irc->mynick ) == 0 ) 688 { 689 g_free( irc->mynick ); 690 irc->mynick = g_strdup( cmd[2] ); 691 667 else 668 { 669 if( !irc_user_set_nick( iu, cmd[2] ) ) 670 { 671 irc_usermsg( irc, "Error while changing nick" ); 672 return; 673 } 674 675 if( iu == irc->root ) 676 { 692 677 /* If we're called internally (user did "set root_nick"), 693 678 let's not go O(INF). :-) */ 694 679 if( strcmp( cmd[0], "set_rename" ) != 0 ) 695 set_setstr( &irc-> set, "root_nick", cmd[2] );696 } 697 else if( u->send_handler == buddy_send_handler)698 { 699 nick_set( u->ic->acc,u->handle, cmd[2] );680 set_setstr( &irc->b->set, "root_nick", cmd[2] ); 681 } 682 else if( iu->bu ) 683 { 684 nick_set( iu->bu->ic->acc, iu->bu->handle, cmd[2] ); 700 685 } 701 686 … … 704 689 } 705 690 691 #if 0 706 692 char *set_eval_root_nick( set_t *set, char *new_nick ) 707 693 { … … 730 716 731 717 return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID; 732 }733 734 static void cmd_remove( irc_t *irc, char **cmd )735 {736 user_t *u;737 char *s;738 739 if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )740 {741 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );742 return;743 }744 s = g_strdup( u->handle );745 746 u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );747 nick_del( u->ic->acc, u->handle );748 user_del( irc, cmd[1] );749 750 irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );751 g_free( s );752 753 return;754 718 } 755 719 … … 872 836 } 873 837 } 838 #endif 874 839 875 840 static void cmd_yesno( irc_t *irc, char **cmd ) … … 916 881 } 917 882 918 static void cmd_save( irc_t *irc, char **cmd ) 919 { 920 if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) 921 irc_usermsg( irc, "Please create an account first" ); 922 else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) 923 irc_usermsg( irc, "Configuration saved" ); 924 else 925 irc_usermsg( irc, "Configuration could not be saved!" ); 926 } 927 883 #if 0 928 884 static void cmd_blist( irc_t *irc, char **cmd ) 929 885 { … … 991 947 } 992 948 993 static void cmd_nick( irc_t *irc, char **cmd )994 {995 account_t *a;996 997 if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )998 {999 irc_usermsg( irc, "Invalid account");1000 }1001 else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )1002 {1003 irc_usermsg( irc, "That account is not on-line" );1004 }1005 else if ( !cmd[2] )1006 {1007 irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );1008 }1009 else if ( !a->prpl->set_my_name )1010 {1011 irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );1012 }1013 else1014 {1015 irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );1016 1017 a->prpl->set_my_name( a->ic, cmd[2] );1018 }1019 }1020 1021 949 static void cmd_qlist( irc_t *irc, char **cmd ) 1022 950 { … … 1037 965 else 1038 966 irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); 1039 }1040 1041 static void cmd_join_chat( irc_t *irc, char **cmd )1042 {1043 irc_usermsg( irc, "This command is now obsolete. "1044 "Please try the `chat' command instead." );1045 967 } 1046 968 … … 1157 1079 } 1158 1080 1081 static void cmd_transfer( irc_t *irc, char **cmd ) 1082 { 1083 GSList *files = irc->file_transfers; 1084 enum { LIST, REJECT, CANCEL }; 1085 int subcmd = LIST; 1086 int fid; 1087 1088 if( !files ) 1089 { 1090 irc_usermsg( irc, "No pending transfers" ); 1091 return; 1092 } 1093 1094 if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) ) 1095 { 1096 subcmd = REJECT; 1097 } 1098 else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) && 1099 cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) ) 1100 { 1101 subcmd = CANCEL; 1102 } 1103 1104 for( ; files; files = g_slist_next( files ) ) 1105 { 1106 file_transfer_t *file = files->data; 1107 1108 switch( subcmd ) { 1109 case LIST: 1110 if ( file->status == FT_STATUS_LISTENING ) 1111 irc_usermsg( irc, 1112 "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name); 1113 else 1114 { 1115 int kb_per_s = 0; 1116 time_t diff = time( NULL ) - file->started ? : 1; 1117 if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) ) 1118 kb_per_s = file->bytes_transferred / 1024 / diff; 1119 1120 irc_usermsg( irc, 1121 "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, 1122 file->bytes_transferred/1024, file->file_size/1024, kb_per_s); 1123 } 1124 break; 1125 case REJECT: 1126 if( file->status == FT_STATUS_LISTENING ) 1127 { 1128 irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name ); 1129 imcb_file_canceled( file, "Denied by user" ); 1130 } 1131 break; 1132 case CANCEL: 1133 if( file->local_id == fid ) 1134 { 1135 irc_usermsg( irc, "Canceling file transfer for %s", file->file_name ); 1136 imcb_file_canceled( file, "Canceled by user" ); 1137 } 1138 break; 1139 } 1140 } 1141 } 1142 #endif 1143 1144 /* IMPORTANT: Keep this list sorted! The short command logic needs that. */ 1159 1145 const command_t commands[] = { 1146 { "account", 1, cmd_account, 0 }, 1147 { "add", 2, cmd_add, 0 }, 1148 { "drop", 1, cmd_drop, 0 }, 1160 1149 { "help", 0, cmd_help, 0 }, 1161 1150 { "identify", 1, cmd_identify, 0 }, 1151 { "info", 1, cmd_info, 0 }, 1152 { "no", 0, cmd_yesno, 0 }, 1162 1153 { "register", 1, cmd_register, 0 }, 1163 { "drop", 1, cmd_drop, 0 }, 1164 { "account", 1, cmd_account, 0 }, 1165 { "add", 2, cmd_add, 0 }, 1166 { "info", 1, cmd_info, 0 }, 1154 { "remove", 1, cmd_remove, 0 }, 1167 1155 { "rename", 2, cmd_rename, 0 }, 1168 { "remove", 1, cmd_remove, 0 },1169 { "block", 1, cmd_block, 0 },1170 { "allow", 1, cmd_allow, 0 },1171 1156 { "save", 0, cmd_save, 0 }, 1172 1157 { "set", 0, cmd_set, 0 }, 1173 1158 { "yes", 0, cmd_yesno, 0 }, 1174 { "no", 0, cmd_yesno, 0 }, 1159 #if 0 1160 { "allow", 1, cmd_allow, 0 }, 1175 1161 { "blist", 0, cmd_blist, 0 }, 1176 { "nick", 1, cmd_nick, 0 }, 1162 { "block", 1, cmd_block, 0 }, 1163 { "chat", 1, cmd_chat, 0 }, 1164 { "ft", 0, cmd_transfer, 0 }, 1165 { "join_chat", 2, cmd_join_chat, 0 }, 1177 1166 { "qlist", 0, cmd_qlist, 0 }, 1178 { " join_chat", 2, cmd_join_chat,0 },1179 { "chat", 1, cmd_chat, 0 }, 1167 { "transfer", 0, cmd_transfer, 0 }, 1168 #endif 1180 1169 { NULL } 1181 1170 }; -
set.c
r156bbd7 r21c87a7 225 225 } 226 226 227 /* 227 228 char *set_eval_ops( set_t *set, char *value ) 228 229 { … … 246 247 return value; 247 248 } 249 */ -
storage.c
r156bbd7 r21c87a7 28 28 #define BITLBEE_CORE 29 29 #include "bitlbee.h" 30 #include "crypting.h"31 30 32 31 extern storage_t storage_text; … … 66 65 storage_t *storage; 67 66 68 register_storage_backend(&storage_text);69 67 register_storage_backend(&storage_xml); 70 68 -
storage_xml.c
r156bbd7 r21c87a7 147 147 arc_decode( pass_cr, pass_len, &password, xd->given_pass ) ) 148 148 { 149 xd->current_account = account_add( irc , prpl, handle, password );149 xd->current_account = account_add( irc->b, prpl, handle, password ); 150 150 if( server ) 151 151 set_setstr( &xd->current_account->set, "server", server ); … … 181 181 xd->current_set_head = &xd->current_account->set; 182 182 else 183 xd->current_set_head = &xd->irc-> set;183 xd->current_set_head = &xd->irc->b->set; 184 184 185 185 xd->current_setting = g_strdup( setting ); … … 215 215 if( xd->current_account && handle && channel ) 216 216 { 217 xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );217 //xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel ); 218 218 } 219 219 else … … 353 353 static storage_status_t xml_load( irc_t *irc, const char *password ) 354 354 { 355 return xml_load_real( irc, irc-> nick, password, XML_PASS_UNKNOWN );355 return xml_load_real( irc, irc->user->nick, password, XML_PASS_UNKNOWN ); 356 356 } 357 357 … … 396 396 md5_state_t md5_state; 397 397 398 path2 = g_strdup( irc-> nick );398 path2 = g_strdup( irc->user->nick ); 399 399 nick_lc( path2 ); 400 400 g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); … … 422 422 pass_buf = base64_encode( pass_md5, 21 ); 423 423 424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc-> nick, pass_buf, XML_FORMAT_VERSION ) )424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->user->nick, pass_buf, XML_FORMAT_VERSION ) ) 425 425 goto write_error; 426 426 427 427 g_free( pass_buf ); 428 428 429 for( set = irc-> set; set; set = set->next )429 for( set = irc->b->set; set; set = set->next ) 430 430 if( set->value ) 431 431 if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 432 432 goto write_error; 433 433 434 for( acc = irc-> accounts; acc; acc = acc->next )434 for( acc = irc->b->accounts; acc; acc = acc->next ) 435 435 { 436 436 unsigned char *pass_cr; … … 470 470 goto write_error; 471 471 472 #if 0 472 473 for( c = irc->chatrooms; c; c = c->next ) 473 474 { … … 488 489 goto write_error; 489 490 } 491 #endif 490 492 491 493 if( !xml_printf( fd, 1, "</account>\n" ) ) -
win32.c
r156bbd7 r21c87a7 27 27 #include "bitlbee.h" 28 28 #include "commands.h" 29 #include "crypting.h"30 29 #include "protocols/nogaim.h" 31 30 #include "help.h"
Note: See TracChangeset
for help on using the changeset viewer.