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