Changes in / [21c87a7:156bbd7]
- Files:
-
- 9 added
- 22 deleted
- 34 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r21c87a7 r156bbd7 10 10 11 11 # Program variables 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 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 15 14 subdirs = lib protocols 16 15 -
bitlbee.h
r21c87a7 r156bbd7 126 126 #define CONF_FILE_DEF ETCDIR "bitlbee.conf" 127 127 128 #include "bee.h"129 128 #include "irc.h" 130 129 #include "storage.h" … … 161 160 gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); 162 161 163 void root_command_string( irc_t *irc, char *command);162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags ); 164 163 void root_command( irc_t *irc, char *command[] ); 165 164 gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); -
conf.c
r21c87a7 r156bbd7 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;68 65 conf->protocols = NULL; 69 66 proxytype = 0; … … 318 315 conf->user = g_strdup( ini->value ); 319 316 } 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 }344 317 else if( g_strcasecmp( ini->key, "protocols" ) == 0 ) 345 318 { … … 376 349 if( g_strcasecmp( ini->section, "defaults" ) == 0 ) 377 350 { 378 set_t *s = set_find( &irc-> b->set, ini->key );351 set_t *s = set_find( &irc->set, ini->key ); 379 352 380 353 if( s ) -
conf.h
r21c87a7 r156bbd7 50 50 int ping_timeout; 51 51 char *user; 52 size_t ft_max_size;53 int ft_max_kbps;54 char *ft_listen;55 52 char **protocols; 56 53 } conf_t; -
configure
r21c87a7 r156bbd7 398 398 fi 399 399 400 STORAGES=" xml"400 STORAGES="text xml" 401 401 402 402 if [ "$ldap" = "auto" ]; then -
doc/user-guide/commands.xml
r21c87a7 r156bbd7 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 1137 1094 </chapter> -
ipc.c
r21c87a7 r156bbd7 138 138 139 139 if( strchr( irc->umode, 'w' ) ) 140 irc_write( irc, ":%s WALLOPS :%s", irc-> root->host, cmd[1] );140 irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] ); 141 141 } 142 142 … … 147 147 148 148 if( strchr( irc->umode, 's' ) ) 149 irc_write( irc, ":%s NOTICE %s :%s", irc-> root->host, irc->user->nick, cmd[1] );149 irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] ); 150 150 } 151 151 … … 156 156 157 157 if( strchr( irc->umode, 'o' ) ) 158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc-> root->host, irc->user->nick, cmd[1] );158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->myhost, irc->nick, cmd[1] ); 159 159 } 160 160 … … 176 176 return; 177 177 178 if( nick_cmp( cmd[1], irc-> user->nick ) != 0 )178 if( nick_cmp( cmd[1], irc->nick ) != 0 ) 179 179 return; /* It's not for us. */ 180 180 181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc-> root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] );181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] ); 182 182 irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); 183 183 } … … 188 188 ipc_to_master_str( "HELLO\r\n" ); 189 189 else 190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc-> user->host, irc->user->nick, irc->user->fullname );190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 191 191 } 192 192 -
irc.c
r21c87a7 r156bbd7 5 5 \********************************************************************/ 6 6 7 /* The IRC-based UI (for now the only one)*/7 /* The big hairy IRCd part of the project */ 8 8 9 9 /* … … 24 24 */ 25 25 26 #define BITLBEE_CORE 26 27 #include "bitlbee.h" 28 #include "sock.h" 29 #include "crypting.h" 27 30 #include "ipc.h" 28 31 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 ); 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 } 33 114 34 115 irc_t *irc_new( int fd ) … … 37 118 struct sockaddr_storage sock; 38 119 socklen_t socklen = sizeof( sock ); 39 char *host = NULL, *myhost = NULL;40 irc_user_t *iu;41 120 set_t *s; 42 bee_t *b;43 121 44 122 irc = g_new0( irc_t, 1 ); … … 52 130 irc->last_pong = gettime(); 53 131 54 irc-> nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );132 irc->userhash = g_hash_table_new( g_str_hash, g_str_equal ); 55 133 irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); 134 135 strcpy( irc->umode, UMODE ); 136 irc->mynick = g_strdup( ROOT_NICK ); 137 irc->channel = g_strdup( ROOT_CHAN ); 56 138 57 139 irc->iconv = (GIConv) -1; … … 60 142 if( global.conf->hostname ) 61 143 { 62 myhost = g_strdup( global.conf->hostname );144 irc->myhost = g_strdup( global.conf->hostname ); 63 145 } 64 146 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) … … 69 151 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 70 152 { 71 myhost = g_strdup( ipv6_unwrap( buf ) );153 irc->myhost = g_strdup( ipv6_unwrap( buf ) ); 72 154 } 73 155 } … … 80 162 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 81 163 { 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" );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" ); 90 172 91 173 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 92 174 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); 175 176 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" ); 93 177 94 178 irc_connection_list = g_slist_append( irc_connection_list, irc ); 95 179 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 ); 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 ); 131 210 132 211 conf_loaddefaults( irc ); 133 212 134 213 /* Evaluator sets the iconv/oconv structures. */ 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; 214 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 215 216 return( irc ); 143 217 } 144 218 … … 161 235 162 236 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 163 irc-> user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );237 irc->nick ? irc->nick : "(NONE)", irc->host, reason ); 164 238 165 239 g_free( reason ); … … 171 245 172 246 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 173 irc-> user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );247 irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" ); 174 248 } 175 249 … … 192 266 } 193 267 194 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 195 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 */ 196 276 void irc_free( irc_t * irc ) 197 277 { 278 user_t *user, *usertmp; 279 198 280 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 199 281 200 /* 201 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) 282 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) ) 202 283 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 203 284 irc_usermsg( irc, "Error while saving settings!" ); 204 */205 285 206 286 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 207 287 208 /* 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 209 303 while( irc->queries != NULL ) 210 304 query_del( irc, irc->queries ); 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 ); 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 } 218 327 219 328 if( irc->ping_source_id > 0 ) … … 227 336 irc->fd = -1; 228 337 229 g_hash_table_foreach_remove( irc-> nick_user_hash, irc_free_hashkey, NULL );230 g_hash_table_destroy( irc-> nick_user_hash );338 g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL ); 339 g_hash_table_destroy( irc->userhash ); 231 340 232 341 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); … … 241 350 g_free( irc->readbuffer ); 242 351 352 g_free( irc->nick ); 353 g_free( irc->user ); 354 g_free( irc->host ); 355 g_free( irc->realname ); 243 356 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 ); 244 364 245 365 g_free( irc ); … … 253 373 } 254 374 255 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )256 {257 g_free( key );258 259 return( TRUE );260 }261 262 375 /* USE WITH CAUTION! 263 376 Sets pass without checking */ 264 void irc_setpass (irc_t *irc, const char *pass) 377 void irc_setpass (irc_t *irc, const char *pass) 265 378 { 266 379 g_free (irc->password); … … 273 386 } 274 387 275 static char **irc_splitlines( char *buffer );276 277 388 void irc_process( irc_t *irc ) 278 389 { … … 282 393 if( irc->readbuffer != NULL ) 283 394 { 284 lines = irc_ splitlines( irc->readbuffer );395 lines = irc_tokenize( irc->readbuffer ); 285 396 286 397 for( i = 0; *lines[i] != '\0'; i ++ ) … … 319 430 "`help set charset' for more information. Your " 320 431 "message was ignored.", 321 set_getstr( &irc-> b->set, "charset" ) );432 set_getstr( &irc->set, "charset" ) ); 322 433 323 434 g_free( conv ); … … 326 437 else 327 438 { 328 irc_write( irc, ":%s NOTICE AUTH :%s", irc-> root->host,439 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, 329 440 "Warning: invalid characters received at login time." ); 330 441 … … 364 475 } 365 476 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 ) 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 ) 371 480 { 372 481 int i, j, n = 3; … … 499 608 } 500 609 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 501 640 void irc_write( irc_t *irc, char *format, ... ) 502 641 { … … 509 648 return; 510 649 } 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 }540 650 541 651 void irc_vawrite( irc_t *irc, char *format, va_list params ) … … 594 704 } 595 705 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 ) 750 { 751 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 752 *namelist = 0; 753 } 754 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 596 793 int irc_check_login( irc_t *irc ) 597 794 { 598 if( irc->user ->user && irc->user->nick )795 if( irc->user && irc->nick ) 599 796 { 600 797 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 601 798 { 602 irc_ send_num( irc, 464, ":This server is password-protected." );799 irc_reply( irc, 464, ":This server is password-protected." ); 603 800 return 0; 604 801 } 605 802 else 606 803 { 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 ) 625 { 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] ); 631 } 632 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 804 irc_login( irc ); 652 805 return 1; 653 806 } … … 660 813 } 661 814 662 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) 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 ) 663 940 { 664 941 /* allow_priv: Set to 0 if s contains user input, 1 if you want 665 942 to set a "privileged" mode (+o, +R, etc). */ 666 char m[128], st = 1; 667 const char *t; 943 char m[256], st = 1, *t; 668 944 int i; 669 945 char changes[512], *p, st2 = 2; … … 673 949 674 950 for( t = irc->umode; *t; t ++ ) 675 if( *t < sizeof( m ) ) 676 m[(int)*t] = 1; 677 951 m[(int)*t] = 1; 952 678 953 p = changes; 679 954 for( t = s; *t; t ++ ) … … 681 956 if( *t == '+' || *t == '-' ) 682 957 st = *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 ) ) ) 958 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) 686 959 { 687 960 if( m[(int)*t] != st) … … 700 973 memset( irc->umode, 0, sizeof( irc->umode ) ); 701 974 702 for( i = 'A'; i <= 'z'&& strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )975 for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) 703 976 if( m[i] ) 704 977 irc->umode[strlen(irc->umode)] = i; 705 978 706 979 if( badflag ) 707 irc_send_num( irc, 501, ":Unknown MODE flag" ); 980 irc_reply( irc, 501, ":Unknown MODE flag" ); 981 /* Deliberately no !user@host on the prefix here */ 708 982 if( *changes ) 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 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 } 714 1298 715 1299 /* Returns 0 if everything seems to be okay, a number >0 when there was a … … 749 1333 } 750 1334 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 } 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 } -
irc.h
r21c87a7 r156bbd7 5 5 \********************************************************************/ 6 6 7 /* The IRC-based UI (for now the only one)*/7 /* The big hairy IRCd part of the project */ 8 8 9 9 /* … … 33 33 #define IRC_PING_STRING "PinglBee" 34 34 35 #define UMODES "abisw" /* Allowed umodes (although they mostly do nothing) */ 36 #define UMODES_PRIV "Ro" /* Allowed, but not by user directly */ 37 #define UMODES_KEEP "R" /* Don't allow unsetting using /MODE */ 38 #define CMODES "nt" /* Allowed modes */ 39 #define CMODE "t" /* Default mode */ 40 #define UMODE "s" /* Default mode */ 41 42 #define CTYPES "&#" /* Valid channel name prefixes */ 35 #define UMODES "abisw" 36 #define UMODES_PRIV "Ro" 37 #define CMODES "nt" 38 #define CMODE "t" 39 #define UMODE "s" 40 #define CTYPES "&#" 43 41 44 42 typedef enum … … 50 48 USTATUS_SHUTDOWN = 8 51 49 } irc_status_t; 52 53 struct irc_user;54 50 55 51 typedef struct irc … … 63 59 GIConv iconv, oconv; 64 60 65 struct irc_user *root; 66 struct irc_user *user; 67 68 char *last_root_cmd; 61 int sentbytes; 62 time_t oldtime; 69 63 64 char *nick; 65 char *user; 66 char *host; 67 char *realname; 70 68 char *password; /* HACK: Used to save the user's password, but before 71 69 logging in, this may contain a password we should … … 74 72 char umode[8]; 75 73 74 char *myhost; 75 char *mynick; 76 77 char *channel; 78 int c_id; 79 80 char is_private; /* Not too nice... */ 81 char *last_target; 82 76 83 struct query *queries; 77 GSList *file_transfers; 84 struct account *accounts; 85 struct chat *chatrooms; 78 86 79 GSList *users, *channels;80 GHashTable * nick_user_hash;87 struct __USER *users; 88 GHashTable *userhash; 81 89 GHashTable *watches; 90 struct __NICK *nicks; 91 struct set *set; 82 92 83 93 gint r_watch_source_id; 84 94 gint w_watch_source_id; 85 95 gint ping_source_id; 86 87 struct bee *b;88 96 } irc_t; 89 97 90 typedef enum 91 { 92 IRC_USER_PRIVATE = 1, 93 } irc_user_flags_t; 98 #include "user.h" 94 99 95 typedef struct irc_user96 {97 irc_t *irc;98 99 char *nick;100 char *user;101 char *host;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_funcs120 {121 gboolean (*privmsg)( irc_user_t *iu, const char *msg );122 gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp );123 };124 125 extern const struct irc_user_funcs irc_user_root_funcs;126 extern const struct irc_user_funcs irc_user_self_funcs;127 128 typedef enum129 {130 IRC_CHANNEL_JOINED = 1,131 } irc_channel_flags_t;132 133 typedef struct irc_channel134 {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;145 struct set *set;146 147 const struct irc_channel_funcs *f;148 } irc_channel_t;149 150 struct irc_channel_funcs151 {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 */158 100 extern GSList *irc_connection_list; 159 101 … … 161 103 void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 162 104 void irc_free( irc_t *irc ); 163 void irc_setpass (irc_t *irc, const char *pass);164 105 106 void irc_exec( irc_t *irc, char **cmd ); 165 107 void irc_process( irc_t *irc ); 166 108 char **irc_parse_line( char *line ); 167 109 char *irc_build_line( char **cmd ); 168 110 111 void irc_vawrite( irc_t *irc, char *format, va_list params ); 169 112 void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 170 113 void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 171 void irc_vawrite( irc_t *irc, char *format, va_list params ); 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 ); 172 117 118 void irc_login( irc_t *irc ); 173 119 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! */ 174 133 175 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); 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 ); 176 138 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 ); 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 ); 216 141 217 142 #endif -
irc_commands.c
r21c87a7 r156bbd7 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2006 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 53 53 else if( global.conf->auth_pass ) 54 54 { 55 irc_ send_num( irc, 464, ":Incorrect password" );55 irc_reply( irc, 464, ":Incorrect password" ); 56 56 } 57 57 else 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 ->user= g_strdup( cmd[1] );68 irc-> user->fullname = g_strdup( cmd[4] );67 irc->user = g_strdup( cmd[1] ); 68 irc->realname = g_strdup( cmd[4] ); 69 69 70 70 irc_check_login( irc ); … … 73 73 static void irc_cmd_nick( irc_t *irc, char **cmd ) 74 74 { 75 if( irc_user_by_name( irc, cmd[1] ) ) 76 { 77 irc_send_num( irc, 433, ":This nick is already in use" ); 75 if( irc->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" ); 78 83 } 79 84 else if( !nick_ok( cmd[1] ) ) 80 85 { 81 86 /* [SH] Invalid characters. */ 82 irc_send_num( irc, 432, ":This nick contains invalid characters" ); 83 } 84 else if( irc->user->nick ) 85 { 86 if( irc->status & USTATUS_IDENTIFIED ) 87 { 88 irc_setpass( irc, NULL ); 89 irc->status &= ~USTATUS_IDENTIFIED; 90 irc_umode_set( irc, "-R", 1 ); 91 } 92 93 irc_user_set_nick( irc->user, cmd[1] ); 94 } 95 else 96 { 97 irc->user->nick = g_strdup( cmd[1] ); 87 irc_reply( irc, 432, ":This nick contains invalid characters" ); 88 } 89 else 90 { 91 irc->nick = g_strdup( cmd[1] ); 98 92 99 93 irc_check_login( irc ); … … 111 105 static void irc_cmd_ping( irc_t *irc, char **cmd ) 112 106 { 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 ); 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 } 202 124 } 203 125 204 126 static void irc_cmd_mode( irc_t *irc, char **cmd ) 205 127 { 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] ) 128 if( strchr( CTYPES, *cmd[1] ) ) 129 { 130 if( cmd[2] ) 213 131 { 214 132 if( *cmd[2] == '+' || *cmd[2] == '-' ) 215 irc_ send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );133 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] ); 216 134 else if( *cmd[2] == 'b' ) 217 irc_ send_num( irc, 368, "%s :No bans possible", cmd[1] );135 irc_reply( irc, 368, "%s :No bans possible", cmd[1] ); 218 136 } 219 137 else 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 )138 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE ); 139 } 140 else 141 { 142 if( nick_cmp( cmd[1], irc->nick ) == 0 ) 225 143 { 226 144 if( cmd[2] ) 227 145 irc_umode_set( irc, cmd[2], 0 ); 228 146 else 229 irc_ send_num( irc, 221, "+%s", irc->umode );147 irc_reply( irc, 221, "+%s", irc->umode ); 230 148 } 231 149 else 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 ); 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 ); 247 222 } 248 223 249 224 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 250 225 { 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 { 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] ); 301 233 } 302 234 else … … 339 271 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); 340 272 } 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 ); 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:"**" ); 385 305 } 386 306 … … 400 320 { 401 321 if( u->online && u->away ) 402 irc_ send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );322 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host ); 403 323 else 404 irc_ send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );324 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); 405 325 } 406 326 } … … 457 377 buff[strlen(buff)-1] = '\0'; 458 378 459 irc_ send_num( irc, 303, ":%s", buff );379 irc_reply( irc, 303, ":%s", buff ); 460 380 } 461 381 … … 486 406 487 407 if( u && u->online ) 488 irc_ send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );408 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" ); 489 409 else 490 irc_ send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );410 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); 491 411 } 492 412 else if( cmd[i][0] == '-' ) … … 499 419 g_free( okey ); 500 420 501 irc_ send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );421 irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 502 422 } 503 423 } … … 523 443 } 524 444 } 525 #endif526 445 527 446 static void irc_cmd_away( irc_t *irc, char **cmd ) 528 447 { 529 char *set; 530 531 if( cmd[1] && *cmd[1] ) 532 { 533 char away[strlen(cmd[1])+1]; 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 { 534 455 int i, j; 535 456 536 457 /* Copy away string, but skip control chars. Mainly because 537 458 Jabber really doesn't like them. */ 538 for( i = j = 0; cmd[1][i]; i ++ ) 539 if( ( away[j] = cmd[1][i] ) >= ' ' ) 459 u->away = g_malloc( strlen( away ) + 1 ); 460 for( i = j = 0; away[i]; i ++ ) 461 if( ( u->away[j] = away[i] ) >= ' ' ) 540 462 j ++; 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 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 556 541 static void irc_cmd_version( irc_t *irc, char **cmd ) 557 542 { 558 irc_ send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );543 irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU ); 559 544 } 560 545 … … 587 572 ipc_to_master( cmd ); 588 573 589 irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); 590 } 591 #endif 574 irc_reply( irc, 382, "%s :Rehashing", global.conf_file ); 575 } 592 576 593 577 static const command_t irc_commands[] = { … … 597 581 { "quit", 0, irc_cmd_quit, 0 }, 598 582 { "ping", 0, irc_cmd_ping, 0 }, 599 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 583 { "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 }, 600 587 { "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 }, 588 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 589 { "privmsg", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 590 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 607 591 { "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 0613 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN },614 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN },615 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN },616 592 { "userhost", 1, irc_cmd_userhost, IRC_CMD_LOGGED_IN }, 617 593 { "ison", 1, irc_cmd_ison, IRC_CMD_LOGGED_IN }, 618 594 { "watch", 1, irc_cmd_watch, IRC_CMD_LOGGED_IN }, 619 595 { "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 }, 620 603 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 621 604 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, … … 627 610 { "restart", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 628 611 { "kill", 2, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 629 #endif630 612 { NULL } 631 613 }; … … 646 628 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 647 629 { 648 irc_ send_num( irc, 462, ":Only allowed before logging in" );630 irc_reply( irc, 462, ":Only allowed before logging in" ); 649 631 } 650 632 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 651 633 { 652 irc_ send_num( irc, 451, ":Register first" );634 irc_reply( irc, 451, ":Register first" ); 653 635 } 654 636 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 655 637 { 656 irc_ send_num( irc, 481, ":Permission denied - You're not an IRC operator" );638 irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" ); 657 639 } 658 640 else if( n_arg < irc_commands[i].required_parameters ) 659 641 { 660 irc_ send_num( irc, 461, "%s :Need more parameters", cmd[0] );642 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); 661 643 } 662 644 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) … … 675 657 676 658 if( irc->status >= USTATUS_LOGGED_IN ) 677 irc_ send_num( irc, 421, "%s :Unknown command", cmd[0] );678 } 659 irc_reply( irc, 421, "%s :Unknown command", cmd[0] ); 660 } -
lib/Makefile
r21c87a7 r156bbd7 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 ftutil.o12 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 13 13 14 14 CFLAGS += -Wall -
lib/misc.c
r21c87a7 r156bbd7 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 else677 {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
r21c87a7 r156bbd7 69 69 G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); 70 70 71 G_MODULE_EXPORT char **split_command_parts( char *command );72 73 71 #endif -
nick.c
r21c87a7 r156bbd7 78 78 79 79 nick_strip( nick ); 80 if( set_getbool( &acc-> bee->set, "lcnicks" ) )80 if( set_getbool( &acc->irc->set, "lcnicks" ) ) 81 81 nick_lc( nick ); 82 82 } … … 92 92 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) 93 93 { 94 irc_t *irc = (irc_t*) acc->bee->ui_data;95 94 int inf_protection = 256; 96 95 97 96 /* Now, find out if the nick is already in use at the moment, and make 98 97 subtle changes to make it unique. */ 99 while( !nick_ok( nick ) || irc_user_by_name(irc, nick ) )98 while( !nick_ok( nick ) || user_find( acc->irc, nick ) ) 100 99 { 101 100 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) … … 113 112 int i; 114 113 115 irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! "116 "This used to be a fatal BitlBee bug, but we tried to fix it. "117 "This message should *never* appear anymore. "118 "If it does, please *do* send us a bug report! "119 "Please send all the following lines in your report:" );120 121 irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle );114 irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! " 115 "This used to be a fatal BitlBee bug, but we tried to fix it. " 116 "This message should *never* appear anymore. " 117 "If it does, please *do* send us a bug report! " 118 "Please send all the following lines in your report:" ); 119 120 irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle ); 122 121 for( i = 0; i < MAX_NICK_LENGTH; i ++ ) 123 irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] );124 125 irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. "126 "Good luck, and please don't forget to paste the lines up here "127 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );122 irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] ); 123 124 irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. " 125 "Good luck, and please don't forget to paste the lines up here " 126 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); 128 127 129 128 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); -
protocols/Makefile
r21c87a7 r156bbd7 10 10 11 11 # [SH] Program variables 12 objects = account.o bee.o bee_ft.o bee_user.o nogaim.o 13 12 objects = nogaim.o 14 13 15 14 # [SH] The next two lines should contain the directory name (in $(subdirs)) -
protocols/jabber/Makefile
r21c87a7 r156bbd7 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 5bytestream.o sasl.o si.o12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o 13 13 14 14 CFLAGS += -Wall -
protocols/jabber/iq.c
r21c87a7 r156bbd7 91 91 pack = 0; 92 92 } 93 else if( strcmp( s, XMLNS_DISCO _INFO) == 0 )94 { 95 const char *features[] = { XMLNS_DISCO _INFO,93 else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) 94 { 95 const char *features[] = { XMLNS_DISCOVER, 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,104 101 NULL }; 105 102 const char **f; … … 121 118 { 122 119 xt_free_node( reply ); 123 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" , NULL);120 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); 124 121 pack = 0; 125 122 } … … 127 124 else if( strcmp( type, "set" ) == 0 ) 128 125 { 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" ) ) ) 126 if( !( c = xt_find_node( node->children, "query" ) ) || 127 !( s = xt_find_attr( c, "xmlns" ) ) ) 137 128 { 138 129 imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); 139 130 return XT_HANDLED; 140 131 } 141 else if( strcmp( s, XMLNS_ROSTER ) == 0 ) 142 { 132 143 133 /* This is a roster push. XMPP servers send this when someone 144 134 was added to (or removed from) the buddy list. AFAIK they're 145 135 sent even if we added this buddy in our own session. */ 136 if( strcmp( s, XMLNS_ROSTER ) == 0 ) 137 { 146 138 int bare_len = strlen( ic->acc->user ); 147 139 … … 160 152 161 153 xt_free_node( reply ); 162 reply = jabber_make_error_packet( node, "not-allowed", "cancel" , NULL);154 reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); 163 155 pack = 0; 164 156 } 165 157 } 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 }171 158 else 172 159 { 173 160 xt_free_node( reply ); 174 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" , NULL);161 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); 175 162 pack = 0; 176 163 } … … 392 379 if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 393 380 { 394 if( initial || bee_user_by_handle( ic->bee,ic, jid ) == NULL )381 if( initial || imcb_find_buddy( ic, jid ) == NULL ) 395 382 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 396 383 group->text : NULL ); … … 590 577 strcmp( s, "result" ) == 0 ) 591 578 { 592 if( bee_user_by_handle( ic->bee,ic, jid ) == NULL )579 if( imcb_find_buddy( ic, jid ) == NULL ) 593 580 imcb_add_buddy( ic, jid, NULL ); 594 581 } … … 622 609 return st; 623 610 } 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 info714 */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
r21c87a7 r156bbd7 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 );69 67 70 68 s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); … … 266 264 struct jabber_data *jd = ic->proto_data; 267 265 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 280 266 if( jd->fd >= 0 ) 281 267 jabber_end_stream( ic ); … … 558 544 ret->send_typing = jabber_send_typing; 559 545 ret->handle_cmp = g_strcasecmp; 560 ret->transfer_request = jabber_si_transfer_request;561 546 562 547 register_protocol( ret ); -
protocols/jabber/jabber.h
r21c87a7 r156bbd7 61 61 } jabber_buddy_flags_t; 62 62 63 /* Stores a streamhost's (a.k.a. proxy) data */64 typedef struct65 {66 char *jid;67 char *host;68 char port[6];69 } jabber_streamhost_t;70 71 63 typedef enum 72 64 { … … 99 91 GHashTable *node_cache; 100 92 GHashTable *buddies; 101 102 GSList *filetransfers;103 GSList *streamhosts;104 int have_streamhosts;105 93 }; 106 94 … … 139 127 struct jabber_away_state *away_state; 140 128 char *away_message; 141 GSList *features;142 129 143 130 time_t last_msg; … … 153 140 char *my_full_jid; /* Separate copy because of case sensitivity. */ 154 141 struct jabber_buddy *me; 155 };156 157 struct jabber_transfer158 {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;185 142 }; 186 143 … … 210 167 211 168 /* Some supported extensions/legacy stuff */ 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 */ 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 */ 230 180 231 181 /* iq.c */ … … 237 187 int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ); 238 188 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 );251 189 252 190 /* message.c */ … … 262 200 char *set_eval_tls( set_t *set, char *value ); 263 201 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); 264 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type , char *err_code);202 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ); 265 203 void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ); 266 204 struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); -
protocols/jabber/jabber_util.c
r21c87a7 r156bbd7 99 99 } 100 100 101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type , char *err_code)101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ) 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 );117 113 118 114 /* To make the actual error packet, we copy the original packet and … … 279 275 presence_send_request( bla->ic, bla->handle, "subscribed" ); 280 276 281 imcb_ask_add( bla->ic, bla->handle, NULL ); 277 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 278 imcb_ask_add( bla->ic, bla->handle, NULL ); 282 279 283 280 g_free( bla->handle ); … … 461 458 462 459 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && 463 ( bare_exists || bee_user_by_handle( ic->bee,ic, jid ) ) )460 ( bare_exists || imcb_find_buddy( ic, jid ) ) ) 464 461 { 465 462 *s = '/'; … … 482 479 if( bud == NULL ) 483 480 /* No match. Create it now? */ 484 return ( ( flags & GET_BUDDY_CREAT ) && 485 bee_user_by_handle( ic->bee, ic, jid_ ) ) ? 481 return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? 486 482 jabber_buddy_add( ic, jid_ ) : NULL; 487 483 else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) -
protocols/msn/msn.c
r21c87a7 r156bbd7 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 86 80 if( md->fd >= 0 ) 87 81 closesocket( md->fd ); … … 333 327 ret->send_typing = msn_send_typing; 334 328 ret->handle_cmp = g_strcasecmp; 335 //ret->transfer_request = msn_ftp_transfer_request;336 329 337 330 register_protocol(ret); -
protocols/msn/msn.h
r21c87a7 r156bbd7 69 69 int sb_failures; 70 70 time_t first_sb_failure; 71 GSList *filetransfers;72 71 73 72 const struct msn_away_state *away_state; … … 182 181 int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); 183 182 184 /* invitation.c */185 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );186 187 183 #endif //_MSN_H -
protocols/msn/msn_util.c
r21c87a7 r156bbd7 96 96 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); 97 97 98 imcb_ask_add( bla->ic, bla->handle, NULL ); 98 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 99 imcb_ask_add( bla->ic, bla->handle, NULL ); 99 100 100 101 g_free( bla->handle ); -
protocols/msn/sb.c
r21c87a7 r156bbd7 29 29 #include "passport.h" 30 30 #include "md5.h" 31 #include "invitation.h"32 31 33 32 static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); … … 169 168 170 169 /* Build the message. Convert LF to CR-LF for normal messages. */ 171 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 ) 170 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 ) 171 { 172 buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 ); 173 i = strlen( MSN_MESSAGE_HEADERS ); 174 175 strcpy( buf, MSN_MESSAGE_HEADERS ); 176 for( j = 0; text[j]; j ++ ) 177 { 178 if( text[j] == '\n' ) 179 buf[i++] = '\r'; 180 181 buf[i++] = text[j]; 182 } 183 } 184 else 172 185 { 173 186 i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user ); 174 187 buf = g_new0( char, i ); 175 188 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 else183 {184 buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );185 i = strlen( MSN_MESSAGE_HEADERS );186 187 strcpy( buf, MSN_MESSAGE_HEADERS );188 for( j = 0; text[j]; j ++ )189 {190 if( text[j] == '\n' )191 buf[i++] = '\r';192 193 buf[i++] = text[j];194 }195 189 } 196 190 … … 691 685 } 692 686 } 693 #if 0694 // Disable MSN ft support for now.695 687 else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 ) 696 688 { 697 char *command = msn_findheader( body, "Invitation-Command:", blen ); 698 char *cookie = msn_findheader( body, "Invitation-Cookie:", blen ); 699 unsigned int icookie; 689 char *itype = msn_findheader( body, "Application-GUID:", blen ); 690 char buf[1024]; 700 691 701 692 g_free( ct ); 702 693 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 ); 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 } 733 745 } 734 746 else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 ) -
protocols/nogaim.c
r21c87a7 r156bbd7 38 38 #include "chat.h" 39 39 40 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ); 41 static char *format_timestamp( irc_t *irc, time_t msg_ts ); 42 40 43 GSList *connections; 41 44 … … 89 92 } 90 93 #endif 94 95 /* nogaim.c */ 91 96 92 97 GList *protocols = NULL; … … 121 126 } 122 127 128 /* nogaim.c */ 123 129 void nogaim_init() 124 130 { … … 156 162 GSList *get_connections() { return connections; } 157 163 164 /* multi.c */ 165 158 166 struct im_connection *imcb_new( account_t *acc ) 159 167 { … … 162 170 ic = g_new0( struct im_connection, 1 ); 163 171 164 ic-> bee = acc->bee;172 ic->irc = acc->irc; 165 173 ic->acc = acc; 166 174 acc->ic = ic; … … 176 184 177 185 /* Destroy the pointer to this connection from the account list */ 178 for( a = ic-> bee->accounts; a; a = a->next )186 for( a = ic->irc->accounts; a; a = a->next ) 179 187 if( a->ic == ic ) 180 188 { … … 197 205 va_end( params ); 198 206 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" ) ) )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" ) ) ) 201 209 strip_html( text ); 202 210 203 211 /* Try to find a different connection on the same protocol. */ 204 for( a = ic-> bee->accounts; a; a = a->next )212 for( a = ic->irc->accounts; a; a = a->next ) 205 213 if( a->prpl == ic->acc->prpl && a->ic != ic ) 206 214 break; … … 208 216 /* If we found one, include the screenname in the message. */ 209 217 if( a ) 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 ); 218 irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); 212 219 else 213 irc_usermsg( ic-> bee->ui_data, "%s - %s", ic->acc->prpl->name, text );220 irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text ); 214 221 215 222 g_free( text ); … … 262 269 void imcb_connected( struct im_connection *ic ) 263 270 { 271 irc_t *irc = ic->irc; 272 struct chat *c; 273 user_t *u; 274 264 275 /* MSN servers sometimes redirect you to a different server and do 265 276 the whole login sequence again, so these "late" calls to this … … 268 279 return; 269 280 281 u = user_find( ic->irc, ic->irc->nick ); 282 270 283 imcb_log( ic, "Logged in" ); 271 284 … … 280 293 ic->acc->auto_reconnect_delay = 0; 281 294 282 /*283 295 for( c = irc->chatrooms; c; c = c->next ) 284 296 { … … 289 301 chat_join( irc, c, NULL ); 290 302 } 291 */292 303 } 293 304 … … 297 308 298 309 a->reconnect = 0; 299 account_on( a-> bee, a );310 account_on( a->irc, a ); 300 311 301 312 return( FALSE ); /* Only have to run the timeout once */ … … 310 321 void imc_logout( struct im_connection *ic, int allow_reconnect ) 311 322 { 312 bee_t *bee = ic->bee; 323 irc_t *irc = ic->irc; 324 user_t *t, *u; 313 325 account_t *a; 314 GSList *l;315 326 int delay; 316 327 … … 332 343 ic->away = NULL; 333 344 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 ) 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 ) 348 361 if( a->ic == ic ) 349 362 break; … … 353 366 /* Uhm... This is very sick. */ 354 367 } 355 else if( allow_reconnect && set_getbool( & bee->set, "auto_reconnect" ) &&368 else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) && 356 369 set_getbool( &a->set, "auto_reconnect" ) && 357 370 ( delay = account_reconnect_delay( a ) ) > 0 ) … … 364 377 } 365 378 379 380 /* dialogs.c */ 381 366 382 void imcb_ask( struct im_connection *ic, char *msg, void *data, 367 383 query_callback doit, query_callback dont ) 368 384 { 369 query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data ); 370 } 385 query_add( ic->irc, ic, msg, doit, dont, data ); 386 } 387 388 389 /* list.c */ 371 390 372 391 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) 373 392 { 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" ) ) 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" ) ) 380 400 imcb_log( ic, "User already exists, ignoring add request: %s", handle ); 381 401 … … 388 408 } 389 409 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 ); 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 ); 408 497 } 409 498 } … … 411 500 void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) 412 501 { 413 bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) ); 502 user_t *u; 503 504 if( ( u = user_findhandle( ic, handle ) ) ) 505 user_del( ic->irc, u->nick ); 414 506 } 415 507 … … 418 510 void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) 419 511 { 420 #if 0421 512 user_t *u = user_findhandle( ic, handle ); 422 513 char newnick[MAX_NICK_LENGTH+1], *orig_nick; … … 433 524 /* Some processing to make sure this string is a valid IRC nickname. */ 434 525 nick_strip( newnick ); 435 if( set_getbool( &ic-> bee->set, "lcnicks" ) )526 if( set_getbool( &ic->irc->set, "lcnicks" ) ) 436 527 nick_lc( newnick ); 437 528 … … 450 541 } 451 542 } 452 #endif453 543 } 454 544 … … 495 585 data->ic = ic; 496 586 data->handle = g_strdup( handle ); 497 query_add( (irc_t *) ic->bee->ui_data, ic, s, 498 imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 587 query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data ); 499 588 } 500 589 … … 521 610 522 611 /* TODO: Make a setting for this! */ 523 if( bee_user_by_handle( ic->bee,ic, handle ) != NULL )612 if( user_findhandle( ic, handle ) != NULL ) 524 613 return; 525 614 … … 528 617 data->ic = ic; 529 618 data->handle = g_strdup( handle ); 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 ); 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 } 537 797 } 538 798 539 799 struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ) 540 800 { 541 #if 0542 801 struct groupchat *c; 543 802 … … 557 816 c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); 558 817 559 if( set_getbool( &ic-> bee->set, "debug" ) )818 if( set_getbool( &ic->irc->set, "debug" ) ) 560 819 imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); 561 820 562 821 return c; 563 #endif564 return NULL;565 822 } 566 823 567 824 void imcb_chat_name_hint( struct groupchat *c, const char *name ) 568 825 { 569 #if 0570 826 if( !c->joined ) 571 827 { … … 593 849 } 594 850 } 595 #endif596 851 } 597 852 598 853 void imcb_chat_free( struct groupchat *c ) 599 854 { 600 #if 0601 855 struct im_connection *ic = c->ic; 602 856 struct groupchat *l; 603 857 GList *ir; 604 858 605 if( set_getbool( &ic-> bee->set, "debug" ) )859 if( set_getbool( &ic->irc->set, "debug" ) ) 606 860 imcb_log( ic, "You were removed from conversation %p", c ); 607 861 … … 636 890 g_free( c ); 637 891 } 638 #endif639 892 } 640 893 641 894 void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at ) 642 895 { 643 #if 0644 896 struct im_connection *ic = c->ic; 645 897 char *wrapped; … … 652 904 u = user_findhandle( ic, who ); 653 905 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" ) ) )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" ) ) ) 656 908 strip_html( msg ); 657 909 … … 670 922 } 671 923 g_free( wrapped ); 672 #endif673 924 } 674 925 675 926 void imcb_chat_log( struct groupchat *c, char *format, ... ) 676 927 { 677 #if 0678 928 irc_t *irc = c->ic->irc; 679 929 va_list params; … … 690 940 691 941 g_free( text ); 692 #endif693 942 } 694 943 695 944 void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) 696 945 { 697 #if 0698 946 struct im_connection *ic = c->ic; 699 947 user_t *u = NULL; … … 706 954 u = user_findhandle( ic, who ); 707 955 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" ) ) )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" ) ) ) 710 958 strip_html( topic ); 711 959 … … 715 963 if( c->joined && u ) 716 964 irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); 717 #endif 718 } 965 } 966 967 968 /* buddy_chat.c */ 719 969 720 970 void imcb_chat_add_buddy( struct groupchat *b, const char *handle ) 721 971 { 722 #if 0723 972 user_t *u = user_findhandle( b->ic, handle ); 724 973 int me = 0; 725 974 726 if( set_getbool( &b->ic-> bee->set, "debug" ) )975 if( set_getbool( &b->ic->irc->set, "debug" ) ) 727 976 imcb_log( b->ic, "User %s added to conversation %p", handle, b ); 728 977 … … 751 1000 b->in_room = g_list_append( b->in_room, g_strdup( handle ) ); 752 1001 } 753 #endif754 1002 } 755 1003 … … 757 1005 void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason ) 758 1006 { 759 #if 0760 1007 user_t *u; 761 1008 int me = 0; 762 1009 763 if( set_getbool( &b->ic-> bee->set, "debug" ) )1010 if( set_getbool( &b->ic->irc->set, "debug" ) ) 764 1011 imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" ); 765 1012 … … 781 1028 if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) ) 782 1029 irc_part( b->ic->irc, u, b->channel ); 783 #endif 784 } 785 786 #if 0 1030 } 1031 787 1032 static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ) 788 1033 { … … 803 1048 } 804 1049 805 return 0; 806 } 807 #endif 1050 return( 0 ); 1051 } 808 1052 809 1053 810 1054 /* Misc. BitlBee stuff which shouldn't really be here */ 811 #if 0 1055 812 1056 char *set_eval_away_devoice( set_t *set, char *value ) 813 1057 { … … 822 1066 /* Horror.... */ 823 1067 824 if( st != set_getbool( &irc-> b->set, "away_devoice" ) )1068 if( st != set_getbool( &irc->set, "away_devoice" ) ) 825 1069 { 826 1070 char list[80] = ""; … … 864 1108 return value; 865 1109 } 866 #endif 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 } 867 1199 868 1200 /* The plan is to not allow straight calls to prpl functions anymore, but do 869 1201 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 } 870 1219 871 1220 int imc_chat_msg( struct groupchat *c, char *msg, int flags ) … … 896 1245 897 1246 away = set_getstr( &ic->acc->set, "away" ) ? 898 : set_getstr( &ic-> bee->set, "away" );1247 : set_getstr( &ic->irc->set, "away" ); 899 1248 if( away && *away ) 900 1249 { … … 907 1256 away = NULL; 908 1257 msg = set_getstr( &ic->acc->set, "status" ) ? 909 : set_getstr( &ic-> bee->set, "status" );1258 : set_getstr( &ic->irc->set, "status" ); 910 1259 } 911 1260 -
protocols/nogaim.h
r21c87a7 r156bbd7 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 45 45 #include "proxy.h" 46 46 #include "query.h" 47 #include "md5.h"48 #include "ft.h"49 47 50 48 #define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */ … … 87 85 88 86 /* BitlBee */ 89 bee_t *bee;87 irc_t *irc; 90 88 91 89 struct groupchat *groupchats; … … 230 228 void (* auth_allow) (struct im_connection *, const char *who); 231 229 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 );235 230 }; 236 231 … … 286 281 G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ); 287 282 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 ); 288 292 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 );290 293 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); 291 294 … … 313 316 /* Actions, or whatever. */ 314 317 int imc_away_send_update( struct im_connection *ic ); 318 int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); 315 319 int imc_chat_msg( struct groupchat *c, char *msg, int flags ); 316 320 … … 321 325 322 326 /* Misc. stuff */ 327 char *set_eval_timezone( set_t *set, char *value ); 323 328 char *set_eval_away_devoice( set_t *set, char *value ); 324 329 gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); -
protocols/oscar/oscar.c
r21c87a7 r156bbd7 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 imcb_ask_add(data->ic, uin, NULL); 1192 if(imcb_find_buddy(data->ic, uin) == NULL) 1193 imcb_ask_add(data->ic, uin, NULL); 1193 1194 1194 1195 g_free(uin); … … 1951 1952 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 1952 1953 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 */1960 1959 } else 1961 1960 aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); … … 2095 2094 switch (curitem->type) { 2096 2095 case 0x0000: /* Buddy */ 2097 if ((curitem->name) && (!imcb_ buddy_by_handle(ic, nrm))) {2096 if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) { 2098 2097 char *realname = NULL; 2099 2098 -
protocols/twitter/twitter_lib.c
r21c87a7 r156bbd7 103 103 104 104 // Check if the buddy is allready in the buddy list. 105 if (! bee_user_by_handle( ic->bee,ic, name ))105 if (!imcb_find_buddy( ic, name )) 106 106 { 107 107 // The buddy is not in the list, add the buddy and set the status to logged in. -
query.c
r21c87a7 r156bbd7 64 64 } 65 65 66 if( g_strcasecmp( set_getstr( &irc-> b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )66 if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "lifo" ) == 0 || irc->queries == q ) 67 67 query_display( irc, q ); 68 68 … … 179 179 query_t *q; 180 180 181 if( g_strcasecmp( set_getstr( &irc-> b->set, "query_order" ), "fifo" ) == 0 )181 if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 ) 182 182 q = irc->queries; 183 183 else -
root_commands.c
r21c87a7 r156bbd7 26 26 #define BITLBEE_CORE 27 27 #include "commands.h" 28 #include "crypting.h" 28 29 #include "bitlbee.h" 29 30 #include "help.h" … … 32 33 #include <string.h> 33 34 34 void root_command_string( irc_t *irc, char *command ) 35 { 36 root_command( irc, split_command_parts( command ) ); 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 ); 37 79 } 38 80 … … 51 93 void root_command( irc_t *irc, char *cmd[] ) 52 94 { 53 int i , len;95 int i; 54 96 55 97 if( !cmd[0] ) 56 98 return; 57 99 58 len = strlen( cmd[0] );59 100 for( i = 0; commands[i].command; i++ ) 60 if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 ) 61 { 62 if( commands[i+1].command && 63 g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 ) 64 /* Only match on the first letters if the match is unique. */ 65 break; 66 101 if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) 102 { 67 103 MIN_ARGS( commands[i].required_parameters ); 68 104 … … 126 162 irc->status |= USTATUS_IDENTIFIED; 127 163 irc_umode_set( irc, "+R", 1 ); 128 if( set_getbool( &irc-> b->set, "auto_connect" ) )164 if( set_getbool( &irc->set, "auto_connect" ) ) 129 165 cmd_account( irc, account_on ); 130 166 break; … … 166 202 storage_status_t status; 167 203 168 status = storage_remove (irc-> user->nick, cmd[1]);204 status = storage_remove (irc->nick, cmd[1]); 169 205 switch (status) { 170 206 case STORAGE_NO_SUCH_USER: … … 178 214 irc->status &= ~USTATUS_IDENTIFIED; 179 215 irc_umode_set( irc, "-R", 1 ); 180 irc_usermsg( irc, "Account `%s' removed", irc-> user->nick );216 irc_usermsg( irc, "Account `%s' removed", irc->nick ); 181 217 break; 182 218 default: … … 186 222 } 187 223 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 else195 irc_usermsg( irc, "Configuration could not be saved!" );196 }197 198 224 struct cmd_account_del_data 199 225 { … … 207 233 account_t *a; 208 234 209 for( a = cad->irc-> b->accounts; a && a != cad->a; a = a->next );235 for( a = cad->irc->accounts; a && a != cad->a; a = a->next ); 210 236 211 237 if( a == NULL ) … … 219 245 else 220 246 { 221 account_del( cad->irc ->b, a );247 account_del( cad->irc, a ); 222 248 irc_usermsg( cad->irc, "Account deleted" ); 223 249 } … … 260 286 set_name = set_full; 261 287 262 head = &irc-> b->set;288 head = &irc->set; 263 289 } 264 290 else … … 331 357 account_t *a; 332 358 333 if( ( a = account_get( irc ->b, id ) ) )359 if( ( a = account_get( irc, id ) ) ) 334 360 return &a->set; 335 361 else … … 379 405 } 380 406 381 a = account_add( irc ->b, prpl, cmd[3], cmd[4] );407 a = account_add( irc, prpl, cmd[3], cmd[4] ); 382 408 if( cmd[5] ) 383 409 { … … 393 419 MIN_ARGS( 2 ); 394 420 395 if( !( a = account_get( irc ->b, cmd[2] ) ) )421 if( !( a = account_get( irc, cmd[2] ) ) ) 396 422 { 397 423 irc_usermsg( irc, "Invalid account" ); … … 415 441 "set' command. Are you sure you want to delete this " 416 442 "account?", a->prpl->name, a->user ); 417 //query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );443 query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad ); 418 444 g_free( msg ); 419 445 } … … 426 452 irc_usermsg( irc, "Account list:" ); 427 453 428 for( a = irc-> b->accounts; a; a = a->next )454 for( a = irc->accounts; a; a = a->next ) 429 455 { 430 456 char *con; … … 449 475 if( cmd[2] ) 450 476 { 451 if( ( a = account_get( irc ->b, cmd[2] ) ) )477 if( ( a = account_get( irc, cmd[2] ) ) ) 452 478 { 453 479 if( a->ic ) … … 458 484 else 459 485 { 460 account_on( irc ->b, a );486 account_on( irc, a ); 461 487 } 462 488 } … … 469 495 else 470 496 { 471 if ( irc->b->accounts ) 472 { 497 if ( irc->accounts ) { 473 498 irc_usermsg( irc, "Trying to get all accounts connected..." ); 474 499 475 for( a = irc-> b->accounts; a; a = a->next )500 for( a = irc->accounts; a; a = a->next ) 476 501 if( !a->ic && a->auto_connect ) 477 account_on( irc ->b, a );502 account_on( irc, a ); 478 503 } 479 504 else … … 489 514 irc_usermsg( irc, "Deactivating all active (re)connections..." ); 490 515 491 for( a = irc-> b->accounts; a; a = a->next )516 for( a = irc->accounts; a; a = a->next ) 492 517 { 493 518 if( a->ic ) 494 account_off( irc ->b, a );519 account_off( irc, a ); 495 520 else if( a->reconnect ) 496 521 cancel_auto_reconnect( a ); 497 522 } 498 523 } 499 else if( ( a = account_get( irc ->b, cmd[2] ) ) )524 else if( ( a = account_get( irc, cmd[2] ) ) ) 500 525 { 501 526 if( a->ic ) 502 527 { 503 account_off( irc ->b, a );528 account_off( irc, a ); 504 529 } 505 530 else if( a->reconnect ) … … 544 569 } 545 570 546 if( !( a = account_get( irc ->b, cmd[1] ) ) )571 if( !( a = account_get( irc, cmd[1] ) ) ) 547 572 { 548 573 irc_usermsg( irc, "Invalid account" ); … … 562 587 return; 563 588 } 564 else if( irc_user_by_name( irc, cmd[3] ) )589 else if( user_find( irc, cmd[3] ) ) 565 590 { 566 591 irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); … … 576 601 a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); 577 602 else 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] ); 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 ); 581 607 582 608 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;606 609 } 607 610 … … 613 616 if( !cmd[2] ) 614 617 { 615 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );616 if( ! iu || !iu->bu)618 user_t *u = user_find( irc, cmd[1] ); 619 if( !u || !u->ic ) 617 620 { 618 621 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 619 622 return; 620 623 } 621 ic = iu->bu->ic;622 cmd[2] = iu->bu->handle;623 } 624 else if( !( a = account_get( irc ->b, cmd[1] ) ) )624 ic = u->ic; 625 cmd[2] = u->handle; 626 } 627 else if( !( a = account_get( irc, cmd[1] ) ) ) 625 628 { 626 629 irc_usermsg( irc, "Invalid account" ); … … 645 648 static void cmd_rename( irc_t *irc, char **cmd ) 646 649 { 647 irc_user_t *iu; 648 649 iu = irc_user_by_name( irc, cmd[1] ); 650 651 if( iu == NULL ) 650 user_t *u; 651 652 if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) 653 { 654 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 655 } 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 ) ) 672 { 673 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 674 } 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] ) ) ) 652 680 { 653 681 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 654 682 } 655 else if( iu == irc->user ) 656 { 657 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 658 } 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] ) ) 664 { 665 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 666 } 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 { 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 677 692 /* If we're called internally (user did "set root_nick"), 678 693 let's not go O(INF). :-) */ 679 694 if( strcmp( cmd[0], "set_rename" ) != 0 ) 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] );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] ); 685 700 } 686 701 … … 689 704 } 690 705 691 #if 0692 706 char *set_eval_root_nick( set_t *set, char *new_nick ) 693 707 { … … 716 730 717 731 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; 718 754 } 719 755 … … 836 872 } 837 873 } 838 #endif839 874 840 875 static void cmd_yesno( irc_t *irc, char **cmd ) … … 881 916 } 882 917 883 #if 0 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 884 928 static void cmd_blist( irc_t *irc, char **cmd ) 885 929 { … … 947 991 } 948 992 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 else 1014 { 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 949 1021 static void cmd_qlist( irc_t *irc, char **cmd ) 950 1022 { … … 965 1037 else 966 1038 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." ); 967 1045 } 968 1046 … … 1079 1157 } 1080 1158 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 else1114 {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 #endif1143 1144 /* IMPORTANT: Keep this list sorted! The short command logic needs that. */1145 1159 const command_t commands[] = { 1160 { "help", 0, cmd_help, 0 }, 1161 { "identify", 1, cmd_identify, 0 }, 1162 { "register", 1, cmd_register, 0 }, 1163 { "drop", 1, cmd_drop, 0 }, 1146 1164 { "account", 1, cmd_account, 0 }, 1147 1165 { "add", 2, cmd_add, 0 }, 1148 { "drop", 1, cmd_drop, 0 },1149 { "help", 0, cmd_help, 0 },1150 { "identify", 1, cmd_identify, 0 },1151 1166 { "info", 1, cmd_info, 0 }, 1152 { "no", 0, cmd_yesno, 0 }, 1153 { "register", 1, cmd_register, 0 }, 1167 { "rename", 2, cmd_rename, 0 }, 1154 1168 { "remove", 1, cmd_remove, 0 }, 1155 { "rename", 2, cmd_rename, 0 }, 1169 { "block", 1, cmd_block, 0 }, 1170 { "allow", 1, cmd_allow, 0 }, 1156 1171 { "save", 0, cmd_save, 0 }, 1157 1172 { "set", 0, cmd_set, 0 }, 1158 1173 { "yes", 0, cmd_yesno, 0 }, 1159 #if 0 1160 { "allow", 1, cmd_allow, 0 }, 1174 { "no", 0, cmd_yesno, 0 }, 1161 1175 { "blist", 0, cmd_blist, 0 }, 1162 { "block", 1, cmd_block, 0 }, 1176 { "nick", 1, cmd_nick, 0 }, 1177 { "qlist", 0, cmd_qlist, 0 }, 1178 { "join_chat", 2, cmd_join_chat, 0 }, 1163 1179 { "chat", 1, cmd_chat, 0 }, 1164 { "ft", 0, cmd_transfer, 0 },1165 { "join_chat", 2, cmd_join_chat, 0 },1166 { "qlist", 0, cmd_qlist, 0 },1167 { "transfer", 0, cmd_transfer, 0 },1168 #endif1169 1180 { NULL } 1170 1181 }; -
set.c
r21c87a7 r156bbd7 225 225 } 226 226 227 /*228 227 char *set_eval_ops( set_t *set, char *value ) 229 228 { … … 247 246 return value; 248 247 } 249 */ -
storage.c
r21c87a7 r156bbd7 28 28 #define BITLBEE_CORE 29 29 #include "bitlbee.h" 30 #include "crypting.h" 30 31 31 32 extern storage_t storage_text; … … 65 66 storage_t *storage; 66 67 68 register_storage_backend(&storage_text); 67 69 register_storage_backend(&storage_xml); 68 70 -
storage_xml.c
r21c87a7 r156bbd7 147 147 arc_decode( pass_cr, pass_len, &password, xd->given_pass ) ) 148 148 { 149 xd->current_account = account_add( irc ->b, prpl, handle, password );149 xd->current_account = account_add( irc, prpl, handle, password ); 150 150 if( server ) 151 151 set_setstr( &xd->current_account->set, "server", server ); … … 181 181 xd->current_set_head = &xd->current_account->set; 182 182 else 183 xd->current_set_head = &xd->irc-> b->set;183 xd->current_set_head = &xd->irc->set; 184 184 185 185 xd->current_setting = g_strdup( setting ); … … 215 215 if( xd->current_account && handle && channel ) 216 216 { 217 //xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );217 xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel ); 218 218 } 219 219 else … … 353 353 static storage_status_t xml_load( irc_t *irc, const char *password ) 354 354 { 355 return xml_load_real( irc, irc-> user->nick, password, XML_PASS_UNKNOWN );355 return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN ); 356 356 } 357 357 … … 396 396 md5_state_t md5_state; 397 397 398 path2 = g_strdup( irc-> user->nick );398 path2 = g_strdup( irc->nick ); 399 399 nick_lc( path2 ); 400 400 g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); … … 422 422 pass_buf = base64_encode( pass_md5, 21 ); 423 423 424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc-> user->nick, pass_buf, XML_FORMAT_VERSION ) )424 if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) ) 425 425 goto write_error; 426 426 427 427 g_free( pass_buf ); 428 428 429 for( set = irc-> b->set; set; set = set->next )429 for( set = irc->set; set; set = set->next ) 430 430 if( set->value ) 431 431 if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 432 432 goto write_error; 433 433 434 for( acc = irc-> b->accounts; acc; acc = acc->next )434 for( acc = irc->accounts; acc; acc = acc->next ) 435 435 { 436 436 unsigned char *pass_cr; … … 470 470 goto write_error; 471 471 472 #if 0473 472 for( c = irc->chatrooms; c; c = c->next ) 474 473 { … … 489 488 goto write_error; 490 489 } 491 #endif492 490 493 491 if( !xml_printf( fd, 1, "</account>\n" ) ) -
win32.c
r21c87a7 r156bbd7 27 27 #include "bitlbee.h" 28 28 #include "commands.h" 29 #include "crypting.h" 29 30 #include "protocols/nogaim.h" 30 31 #include "help.h"
Note: See TracChangeset
for help on using the changeset viewer.