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