Changes in / [256899f:cd428e4]
- Files:
-
- 1 deleted
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/user-guide/commands.xml
r256899f rcd428e4 685 685 </bitlbee-setting> 686 686 687 <bitlbee-setting name="xmlconsole" type="boolean" scope="account">688 <default>false</default>689 690 <description>691 <para>692 The Jabber module allows you to add a buddy <emphasis>xmlconsole</emphasis> to your contact list, which will then show you the raw XMPP stream between you and the server. You can also send XMPP packets to this buddy, which will then be sent to the server.693 </para>694 <para>695 If you want to enable this XML console permanently (and at login time already), you can set this setting.696 </para>697 </description>698 </bitlbee-setting>699 700 687 <bitlbee-command name="rename"> 701 688 <short-description>Rename (renick) a buddy</short-description> -
doc/user-guide/misc.xml
r256899f rcd428e4 81 81 82 82 <para> 83 Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information.84 </para>85 86 <para>87 83 This is all you'll probably need to know. If you have any problems, please read <emphasis>help groupchats3</emphasis>. 88 84 </para> -
irc.c
r256899f rcd428e4 641 641 } 642 642 } 643 else if( ( c = irc_chat_by_channel( irc,channel ) ) )643 else if( ( c = chat_by_channel( channel ) ) ) 644 644 { 645 645 GList *l; … … 788 788 void irc_topic( irc_t *irc, char *channel ) 789 789 { 790 struct groupchat *c = irc_chat_by_channel( irc, channel ); 791 792 if( c && c->topic ) 793 irc_reply( irc, 332, "%s :%s", channel, c->topic ); 794 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 790 if( g_strcasecmp( channel, irc->channel ) == 0 ) 791 { 795 792 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC ); 793 } 796 794 else 797 irc_reply( irc, 331, "%s :No topic for this channel", channel ); 795 { 796 struct groupchat *c = chat_by_channel( channel ); 797 798 if( c ) 799 irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title ); 800 else 801 irc_reply( irc, 331, "%s :No topic for this channel", channel ); 802 } 798 803 } 799 804 … … 927 932 if( *nick == '#' || *nick == '&' ) 928 933 { 929 if( !( c = irc_chat_by_channel( irc,nick ) ) )934 if( !( c = chat_by_channel( nick ) ) ) 930 935 { 931 936 irc_reply( irc, 403, "%s :Channel does not exist", nick ); … … 1193 1198 return TRUE; 1194 1199 } 1195 1196 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )1197 {1198 struct groupchat *c;1199 account_t *a;1200 1201 /* This finds the connection which has a conversation which belongs to this channel */1202 for( a = irc->accounts; a; a = a->next )1203 {1204 if( a->ic == NULL )1205 continue;1206 1207 c = a->ic->groupchats;1208 while( c )1209 {1210 if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )1211 return c;1212 1213 c = c->next;1214 }1215 }1216 1217 return NULL;1218 } -
irc.h
r256899f rcd428e4 140 140 141 141 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); 142 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );143 142 144 143 #endif -
irc_commands.c
r256899f rcd428e4 144 144 irc_join( irc, u, irc->channel ); 145 145 } 146 else if( ( c = irc_chat_by_channel( irc,cmd[1] ) ) )146 else if( ( c = chat_by_channel( cmd[1] ) ) ) 147 147 { 148 148 user_t *u = user_find( irc, irc->nick ); … … 201 201 { 202 202 char *nick = cmd[1], *channel = cmd[2]; 203 struct groupchat *c = irc_chat_by_channel( irc,channel );203 struct groupchat *c = chat_by_channel( channel ); 204 204 user_t *u = user_find( irc, nick ); 205 205 … … 287 287 u = u->next; 288 288 } 289 else if( ( c = irc_chat_by_channel( irc,channel ) ) )289 else if( ( c = chat_by_channel( channel ) ) ) 290 290 for( l = c->in_room; l; l = l->next ) 291 291 { … … 421 421 static void irc_cmd_topic( irc_t *irc, char **cmd ) 422 422 { 423 char *channel = cmd[1]; 424 char *topic = cmd[2]; 425 426 if( topic ) 427 { 428 /* Send the topic */ 429 struct groupchat *c = irc_chat_by_channel( irc, channel ); 430 if( c && c->ic && c->ic->acc->prpl->chat_topic ) 431 c->ic->acc->prpl->chat_topic( c, topic ); 432 } 433 else 434 { 435 /* Get the topic */ 436 irc_topic( irc, channel ); 437 } 423 if( cmd[2] ) 424 irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] ); 425 else 426 irc_topic( irc, cmd[1] ); 438 427 } 439 428 -
nick.c
r256899f rcd428e4 57 57 static char nick[MAX_NICK_LENGTH+1]; 58 58 char *store_handle, *found_nick; 59 int inf_protection = 256; 59 60 60 61 memset( nick, 0, MAX_NICK_LENGTH + 1 ); … … 81 82 } 82 83 g_free( store_handle ); 83 84 /* Make sure the nick doesn't collide with an existing one by adding85 underscores and that kind of stuff, if necessary. */86 nick_dedupe( acc, handle, nick );87 88 return nick;89 }90 91 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] )92 {93 int inf_protection = 256;94 84 95 85 /* Now, find out if the nick is already in use at the moment, and make … … 130 120 } 131 121 } 122 123 return nick; 132 124 } 133 125 -
nick.h
r256899f rcd428e4 26 26 void nick_set( account_t *acc, const char *handle, const char *nick ); 27 27 char *nick_get( account_t *acc, const char *handle ); 28 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] );29 28 int nick_saved( account_t *acc, const char *handle ); 30 29 void nick_del( account_t *acc, const char *handle ); -
protocols/jabber/Makefile
r256899f rcd428e4 10 10 11 11 # [SH] Program variables 12 objects = conference.oio.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o12 objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o 13 13 14 14 CFLAGS += -Wall -
protocols/jabber/io.c
r256899f rcd428e4 44 44 struct jabber_data *jd = ic->proto_data; 45 45 gboolean ret; 46 47 if( jd->flags & JFLAG_XMLCONSOLE )48 {49 char *msg;50 51 msg = g_strdup_printf( "TX: %s", buf );52 imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 );53 g_free( msg );54 }55 46 56 47 if( jd->tx_len == 0 ) … … 436 427 { 437 428 struct im_connection *ic = data; 429 struct xt_node *c; 430 char *s, *type = NULL, *text = NULL; 438 431 int allow_reconnect = TRUE; 439 struct jabber_error *err; 440 441 err = jabber_error_parse( node, XMLNS_STREAM_ERROR ); 432 433 for( c = node->children; c; c = c->next ) 434 { 435 if( !( s = xt_find_attr( c, "xmlns" ) ) || 436 strcmp( s, XMLNS_STREAM_ERROR ) != 0 ) 437 continue; 438 439 if( strcmp( c->name, "text" ) != 0 ) 440 { 441 type = c->name; 442 } 443 /* Only use the text if it doesn't have an xml:lang attribute, 444 if it's empty or if it's set to something English. */ 445 else if( !( s = xt_find_attr( c, "xml:lang" ) ) || 446 !*s || strncmp( s, "en", 2 ) == 0 ) 447 { 448 text = c->text; 449 } 450 } 442 451 443 452 /* Tssk... */ 444 if( err->code == NULL )453 if( type == NULL ) 445 454 { 446 455 imcb_error( ic, "Unknown stream error reported by server" ); 447 456 imc_logout( ic, allow_reconnect ); 448 jabber_error_free( err );449 457 return XT_ABORT; 450 458 } … … 453 461 should turn off auto-reconnect to make sure we won't get some nasty 454 462 infinite loop! */ 455 if( strcmp( err->code, "conflict" ) == 0 )463 if( strcmp( type, "conflict" ) == 0 ) 456 464 { 457 465 imcb_error( ic, "Account and resource used from a different location" ); … … 460 468 else 461 469 { 462 imcb_error( ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "", 463 err->text ? err->text : "" ); 464 } 465 466 jabber_error_free( err ); 470 imcb_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); 471 } 472 467 473 imc_logout( ic, allow_reconnect ); 468 474 … … 470 476 } 471 477 472 static xt_status jabber_xmlconsole( struct xt_node *node, gpointer data )473 {474 struct im_connection *ic = data;475 struct jabber_data *jd = ic->proto_data;476 477 if( jd->flags & JFLAG_XMLCONSOLE )478 {479 char *msg, *pkt;480 481 pkt = xt_to_string( node );482 msg = g_strdup_printf( "RX: %s", pkt );483 imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 );484 g_free( msg );485 g_free( pkt );486 }487 488 return XT_NEXT;489 }490 491 478 static const struct xt_handler_entry jabber_handlers[] = { 492 { NULL, "stream:stream", jabber_xmlconsole },493 479 { "stream:stream", "<root>", jabber_end_of_stream }, 494 480 { "message", "stream:stream", jabber_pkt_message }, -
protocols/jabber/iq.c
r256899f rcd428e4 99 99 else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) 100 100 { 101 const char *features[] = { XMLNS_VERSION,102 XMLNS_TIME,103 XMLNS_CHATSTATES,104 XMLNS_MUC,105 NULL };106 const char **f;107 108 101 c = xt_new_node( "identity", NULL, NULL ); 109 102 xt_add_attr( c, "category", "client" ); … … 112 105 xt_add_child( reply, c ); 113 106 114 for( f = features; *f; f ++ ) 115 { 116 c = xt_new_node( "feature", NULL, NULL ); 117 xt_add_attr( c, "var", *f ); 118 xt_add_child( reply, c ); 119 } 107 c = xt_new_node( "feature", NULL, NULL ); 108 xt_add_attr( c, "var", XMLNS_VERSION ); 109 xt_add_child( reply, c ); 110 111 c = xt_new_node( "feature", NULL, NULL ); 112 xt_add_attr( c, "var", XMLNS_TIME ); 113 xt_add_child( reply, c ); 114 115 c = xt_new_node( "feature", NULL, NULL ); 116 xt_add_attr( c, "var", XMLNS_CHATSTATES ); 117 xt_add_child( reply, c ); 118 119 /* Later this can be useful to announce things like 120 MUC support. */ 120 121 } 121 122 else … … 372 373 group->text : NULL ); 373 374 374 if( name ) 375 imcb_rename_buddy( ic, jid, name ); 375 imcb_rename_buddy( ic, jid, name ); 376 376 } 377 377 else if( strcmp( sub, "remove" ) == 0 ) 378 378 { 379 /* Don't have any API call for this yet! So let's 380 just try to handle this as well as we can. */ 379 381 jabber_buddy_remove_bare( ic, jid ); 380 imcb_remove_buddy( ic, jid, NULL ); 382 imcb_buddy_status( ic, jid, 0, NULL, NULL ); 383 /* FIXME! */ 381 384 } 382 385 } -
protocols/jabber/jabber.c
r256899f rcd428e4 54 54 55 55 s = set_add( &acc->set, "tls", "try", set_eval_tls, acc ); 56 s->flags |= ACC_SET_OFFLINE_ONLY;57 58 s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );59 56 s->flags |= ACC_SET_OFFLINE_ONLY; 60 57 } … … 192 189 imc_logout( ic, TRUE ); 193 190 } 194 195 if( set_getbool( &acc->set, "xmlconsole" ) )196 {197 jd->flags |= JFLAG_XMLCONSOLE;198 /* Shouldn't really do this at this stage already, maybe. But199 I think this shouldn't break anything. */200 imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );201 }202 191 } 203 192 … … 207 196 208 197 jabber_end_stream( ic ); 209 210 while( ic->groupchats )211 jabber_chat_free( ic->groupchats );212 198 213 199 if( jd->r_inpa >= 0 ) … … 238 224 struct jabber_buddy *bud; 239 225 struct xt_node *node; 240 char *s;241 226 int st; 242 227 243 if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) 244 return jabber_write( ic, message, strlen( message ) ); 245 246 if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) ) 247 bud = jabber_buddy_by_ext_jid( ic, who, 0 ); 248 else 249 bud = jabber_buddy_by_jid( ic, who, 0 ); 228 bud = jabber_buddy_by_jid( ic, who, 0 ); 250 229 251 230 node = xt_new_node( "body", message, NULL ); … … 332 311 static void jabber_add_buddy( struct im_connection *ic, char *who, char *group ) 333 312 { 334 struct jabber_data *jd = ic->proto_data;335 336 if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 )337 {338 jd->flags |= JFLAG_XMLCONSOLE;339 imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );340 return;341 }342 343 313 if( jabber_add_to_roster( ic, who, NULL ) ) 344 314 presence_send_request( ic, who, "subscribe" ); … … 347 317 static void jabber_remove_buddy( struct im_connection *ic, char *who, char *group ) 348 318 { 349 struct jabber_data *jd = ic->proto_data;350 351 if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 )352 {353 jd->flags &= ~JFLAG_XMLCONSOLE;354 /* Not necessary for now. And for now the code isn't too355 happy if the buddy is completely gone right after calling356 this function already.357 imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );358 */359 return;360 }361 362 319 /* We should always do this part. Clean up our administration a little bit. */ 363 320 jabber_buddy_remove_bare( ic, who ); … … 365 322 if( jabber_remove_from_roster( ic, who ) ) 366 323 presence_send_request( ic, who, "unsubscribe" ); 367 }368 369 static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room, char *nick, char *password )370 {371 if( strchr( room, '@' ) == NULL )372 imcb_error( ic, "Invalid room name: %s", room );373 else if( jabber_chat_by_name( ic, room ) )374 imcb_error( ic, "Already present in chat `%s'", room );375 else376 return jabber_chat_join( ic, room, nick, password );377 378 return NULL;379 }380 381 static void jabber_chat_msg_( struct groupchat *c, char *message, int flags )382 {383 if( c && message )384 jabber_chat_msg( c, message, flags );385 }386 387 static void jabber_chat_topic_( struct groupchat *c, char *topic )388 {389 if( c && topic )390 jabber_chat_topic( c, topic );391 }392 393 static void jabber_chat_leave_( struct groupchat *c )394 {395 if( c )396 jabber_chat_leave( c, NULL );397 324 } 398 325 … … 461 388 ret->buddy_msg = jabber_buddy_msg; 462 389 ret->away_states = jabber_away_states; 390 // ret->get_status_string = jabber_get_status_string; 463 391 ret->set_away = jabber_set_away; 464 392 // ret->set_info = jabber_set_info; … … 466 394 ret->add_buddy = jabber_add_buddy; 467 395 ret->remove_buddy = jabber_remove_buddy; 468 ret->chat_msg = jabber_chat_msg_; 469 ret->chat_topic = jabber_chat_topic_; 396 // ret->chat_msg = jabber_chat_msg; 470 397 // ret->chat_invite = jabber_chat_invite; 471 ret->chat_leave = jabber_chat_leave_;472 ret->chat_join = jabber_chat_join_;398 // ret->chat_leave = jabber_chat_leave; 399 // ret->chat_open = jabber_chat_open; 473 400 ret->keepalive = jabber_keepalive; 474 401 ret->send_typing = jabber_send_typing; -
protocols/jabber/jabber.h
r256899f rcd428e4 32 32 typedef enum 33 33 { 34 JFLAG_STREAM_STARTED = 1, 34 JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream 35 35 and want to do auth. */ 36 JFLAG_AUTHENTICATED = 2, 37 JFLAG_STREAM_RESTART = 4, 36 JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ 37 JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after 38 38 SASL or TLS). */ 39 JFLAG_WAIT_SESSION = 8, 39 JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply 40 40 before we continue. */ 41 JFLAG_WAIT_BIND = 16, 42 JFLAG_WANT_TYPING = 32, 41 JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ 42 JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this 43 43 activates all XEP-85 related code. */ 44 JFLAG_XMLCONSOLE = 64, /* If the user added an xmlconsole buddy. */45 44 } jabber_flags_t; 46 45 … … 51 50 JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support 52 51 XEP85 (typing notification shite). */ 53 JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for54 groupchat state info too. */55 JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have56 have a real JID. */57 52 } jabber_buddy_flags_t; 53 54 #define JABBER_PORT_DEFAULT "5222" 55 #define JABBER_PORT_MIN 5220 56 #define JABBER_PORT_MAX 5229 58 57 59 58 struct jabber_data … … 102 101 char *resource; 103 102 104 char *ext_jid; /* The JID to use in BitlBee. The real JID if possible, */105 /* otherwise something similar to the conference JID. */106 107 103 int priority; 108 104 struct jabber_away_state *away_state; … … 114 110 struct jabber_buddy *next; 115 111 }; 116 117 struct jabber_chat118 {119 int flags;120 char *name;121 char *my_full_jid; /* Separate copy because of case sensitivity. */122 struct jabber_buddy *me;123 };124 125 #define JABBER_XMLCONSOLE_HANDLE "xmlconsole"126 127 #define JABBER_PORT_DEFAULT "5222"128 #define JABBER_PORT_MIN 5220129 #define JABBER_PORT_MAX 5229130 112 131 113 /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the … … 150 132 #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ 151 133 #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ 152 #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */153 134 #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ 154 135 #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ 155 #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */156 #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */157 136 158 137 /* iq.c */ … … 185 164 const struct jabber_away_state *jabber_away_state_by_name( char *name ); 186 165 void jabber_buddy_ask( struct im_connection *ic, char *handle ); 187 char *jabber_normalize( c onst char *orig );166 char *jabber_normalize( char *orig ); 188 167 189 168 typedef enum 190 169 { 191 170 GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */ 192 GET_BUDDY_EXACT = 2, /* Get an exact match (only makes sense with bare JIDs). */ 193 GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */ 171 GET_BUDDY_EXACT = 2, /* Get an exact message (only makes sense with bare JIDs). */ 194 172 } get_buddy_flags_t; 195 196 struct jabber_error197 {198 char *code, *text, *type;199 };200 173 201 174 struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); 202 175 struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); 203 struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags );204 176 int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); 205 177 int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); 206 struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name );207 time_t jabber_get_timestamp( struct xt_node *xt );208 struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns );209 void jabber_error_free( struct jabber_error *err );210 178 211 179 extern const struct jabber_away_state jabber_away_state_list[]; … … 225 193 gboolean sasl_supported( struct im_connection *ic ); 226 194 227 /* conference.c */228 struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password );229 void jabber_chat_free( struct groupchat *c );230 int jabber_chat_msg( struct groupchat *ic, char *message, int flags );231 int jabber_chat_topic( struct groupchat *c, char *topic );232 int jabber_chat_leave( struct groupchat *c, const char *reason );233 void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );234 void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );235 236 195 #endif -
protocols/jabber/jabber_util.c
r256899f rcd428e4 48 48 call p_s_u() now to send the new prio setting, it would 49 49 send the old setting because the set->value gets changed 50 after the (this)eval returns a non-NULL value.50 when the eval returns a non-NULL value. 51 51 52 52 So now I can choose between implementing post-set … … 129 129 /* Cache a node/packet for later use. Mainly useful for IQ packets if you need 130 130 them when you receive the response. Use this BEFORE sending the packet so 131 it'll get a new id= tag, and do NOT free() the packet after sending it! */131 it'll get a new id= tag, and do NOT free() the packet after writing it! */ 132 132 void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) 133 133 { … … 252 252 253 253 /* Returns a new string. Don't leak it! */ 254 char *jabber_normalize( c onst char *orig )254 char *jabber_normalize( char *orig ) 255 255 { 256 256 int len, i; … … 320 320 else 321 321 { 322 /* Keep in mind that full_jid currently isn't really323 a full JID... */324 322 new->bare_jid = g_strdup( full_jid ); 325 323 g_hash_table_insert( jd->buddies, new->bare_jid, new ); … … 335 333 { 336 334 /* Let's waste some more bytes of RAM instead of to make 337 memory management a total disaster here. And it saves 338 me one g_free() call in this function. :-P */ 335 memory management a total disaster here.. */ 339 336 new->full_jid = full_jid; 340 337 } … … 356 353 if( ( s = strchr( jid, '/' ) ) ) 357 354 { 358 int none_found = 0;359 360 355 *s = 0; 361 356 if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) … … 375 370 } 376 371 } 377 else 378 { 379 /* This hack is there to make sure that O_CREAT will 380 work if there's already another resouce present 381 for this JID, even if it's an unknown buddy. This 382 is done to handle conferences properly. */ 383 none_found = 1; 384 } 385 386 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) 372 373 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) ) 387 374 { 388 375 *s = '/'; … … 431 418 } 432 419 433 /* I'm keeping a separate ext_jid attribute to save a JID that makes sense434 to export to BitlBee. This is mainly for groupchats right now. It's435 a bit of a hack, but I just think having the user nickname in the hostname436 part of the hostmask doesn't look nice on IRC. Normally you can convert437 a normal JID to ext_jid by swapping the part before and after the / and438 replacing the / with a =. But there should be some stripping (@s are439 allowed in Jabber nicks...). */440 struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags )441 {442 struct jabber_buddy *bud;443 char *s, *jid;444 445 jid = jabber_normalize( jid_ );446 447 if( ( s = strchr( jid, '=' ) ) == NULL )448 return NULL;449 450 for( bud = jabber_buddy_by_jid( ic, s + 1, GET_BUDDY_FIRST ); bud; bud = bud->next )451 {452 /* Hmmm, could happen if not all people in the chat are anonymized? */453 if( bud->ext_jid == NULL )454 continue;455 456 if( strcmp( bud->ext_jid, jid ) == 0 )457 break;458 }459 460 g_free( jid );461 462 return bud;463 }464 465 420 /* Remove one specific full JID from our list. Use this when a buddy goes 466 421 off-line (because (s)he can still be online from a different location. … … 486 441 g_hash_table_remove( jd->buddies, bud->bare_jid ); 487 442 g_free( bud->bare_jid ); 488 g_free( bud->ext_jid );489 443 g_free( bud->full_jid ); 490 444 g_free( bud->away_message ); … … 519 473 g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); 520 474 521 g_free( bi->ext_jid );522 475 g_free( bi->full_jid ); 523 476 g_free( bi->away_message ); … … 542 495 specified bare JID. Use this when removing someone from the contact 543 496 list, for example. */ 544 int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid )497 int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) 545 498 { 546 499 struct jabber_data *jd = ic->proto_data; 547 500 struct jabber_buddy *bud, *next; 548 549 if( strchr( bare_jid, '/' ) ) 501 char *bare_jid; 502 503 if( strchr( bare_jid_, '/' ) ) 550 504 return 0; 551 505 552 if( ( bud = jabber_buddy_by_jid( ic, bare_jid, GET_BUDDY_FIRST ) ) ) 506 bare_jid = jabber_normalize( bare_jid_ ); 507 508 if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) 553 509 { 554 510 /* Most important: Remove the hash reference. We don't know 555 511 this buddy anymore. */ 556 512 g_hash_table_remove( jd->buddies, bud->bare_jid ); 557 g_free( bud->bare_jid );558 513 559 514 /* Deallocate the linked list of resources. */ 560 515 while( bud ) 561 516 { 562 /* ext_jid && anonymous means that this buddy is563 specific to one groupchat (the one we're564 currently cleaning up) so it can be deleted565 completely. */566 if( bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS )567 imcb_remove_buddy( ic, bud->ext_jid, NULL );568 569 517 next = bud->next; 570 g_free( bud->ext_jid );571 518 g_free( bud->full_jid ); 572 519 g_free( bud->away_message ); … … 575 522 } 576 523 524 g_free( bare_jid ); 577 525 return 1; 578 526 } 579 527 else 580 528 { 529 g_free( bare_jid ); 581 530 return 0; 582 531 } 583 532 } 584 585 struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name )586 {587 char *normalized = jabber_normalize( name );588 struct groupchat *ret;589 struct jabber_chat *jc;590 591 for( ret = ic->groupchats; ret; ret = ret->next )592 {593 jc = ret->data;594 if( strcmp( normalized, jc->name ) == 0 )595 break;596 }597 g_free( normalized );598 599 return ret;600 }601 602 time_t jabber_get_timestamp( struct xt_node *xt )603 {604 struct tm tp, utc;605 struct xt_node *c;606 time_t res, tres;607 char *s = NULL;608 609 for( c = xt->children; ( c = xt_find_node( c, "x" ) ); c = c->next )610 {611 if( ( s = xt_find_attr( c, "xmlns" ) ) && strcmp( s, XMLNS_DELAY ) == 0 )612 break;613 }614 615 if( !c || !( s = xt_find_attr( c, "stamp" ) ) )616 return 0;617 618 memset( &tp, 0, sizeof( tp ) );619 if( sscanf( s, "%4d%2d%2dT%2d:%2d:%2d", &tp.tm_year, &tp.tm_mon, &tp.tm_mday,620 &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) != 6 )621 return 0;622 623 tp.tm_year -= 1900;624 tp.tm_mon --;625 tp.tm_isdst = -1; /* GRRRRRRRRRRR */626 627 res = mktime( &tp );628 /* Problem is, mktime() just gave us the GMT timestamp for the629 given local time... While the given time WAS NOT local. So630 we should fix this now.631 632 Now I could choose between messing with environment variables633 (kludgy) or using timegm() (not portable)... Or doing the634 following, which I actually prefer... */635 gmtime_r( &res, &utc );636 utc.tm_isdst = -1; /* Once more: GRRRRRRRRRRRRRRRRRR!!! */637 if( utc.tm_hour == tp.tm_hour && utc.tm_min == tp.tm_min )638 /* Sweet! We're in UTC right now... */639 return res;640 641 tres = mktime( &utc );642 res += res - tres;643 644 /* Yes, this is a hack. And it will go wrong around DST changes.645 BUT this is more likely to be threadsafe than messing with646 environment variables, and possibly more portable... */647 648 return res;649 }650 651 struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns )652 {653 struct jabber_error *err = g_new0( struct jabber_error, 1 );654 struct xt_node *c;655 char *s;656 657 err->type = xt_find_attr( node, "type" );658 659 for( c = node->children; c; c = c->next )660 {661 if( !( s = xt_find_attr( c, "xmlns" ) ) ||662 strcmp( s, xmlns ) != 0 )663 continue;664 665 if( strcmp( c->name, "text" ) != 0 )666 {667 err->code = c->name;668 }669 /* Only use the text if it doesn't have an xml:lang attribute,670 if it's empty or if it's set to something English. */671 else if( !( s = xt_find_attr( c, "xml:lang" ) ) ||672 !*s || strncmp( s, "en", 2 ) == 0 )673 {674 err->text = c->text;675 }676 }677 678 return err;679 }680 681 void jabber_error_free( struct jabber_error *err )682 {683 g_free( err );684 } -
protocols/jabber/message.c
r256899f rcd428e4 30 30 char *type = xt_find_attr( node, "type" ); 31 31 struct xt_node *body = xt_find_node( node->children, "body" ), *c; 32 struct jabber_buddy *bud = NULL;33 32 char *s; 34 35 if( !from )36 return XT_HANDLED; /* Consider this packet corrupted. */37 38 bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT );39 33 40 34 if( type && strcmp( type, "error" ) == 0 ) … … 42 36 /* Handle type=error packet. */ 43 37 } 44 else if( type && from &&strcmp( type, "groupchat" ) == 0 )38 else if( type && strcmp( type, "groupchat" ) == 0 ) 45 39 { 46 jabber_chat_pkt_message( ic, bud, node );40 /* TODO! */ 47 41 } 48 42 else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */ 49 43 { 44 struct jabber_buddy *bud = NULL; 50 45 GString *fullmsg = g_string_new( "" ); 51 46 52 47 if( ( s = strchr( from, '/' ) ) ) 53 48 { 54 if( bud ) 55 { 49 if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) ) 56 50 bud->last_act = time( NULL ); 57 from = bud->ext_jid ? : bud->bare_jid;58 }59 51 else 60 52 *s = 0; /* We need to generate a bare JID now. */ … … 84 76 85 77 if( fullmsg->len > 0 ) 86 imcb_buddy_msg( ic, from, fullmsg->str, 87 0, jabber_get_timestamp( node ) ); 78 imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0 ); 88 79 89 80 g_string_free( fullmsg, TRUE ); 90 81 91 82 /* Handling of incoming typing notifications. */ 92 if( bud == NULL ) 93 { 94 /* Can't handle these for unknown buddies. */ 95 } 96 else if( xt_find_node( node->children, "composing" ) ) 83 if( xt_find_node( node->children, "composing" ) ) 97 84 { 98 85 bud->flags |= JBFLAG_DOES_XEP85; 99 imcb_buddy_typing( ic, from, OPT_TYPING );86 imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_TYPING ); 100 87 } 101 88 /* No need to send a "stopped typing" signal when there's a message. */ … … 103 90 { 104 91 bud->flags |= JBFLAG_DOES_XEP85; 105 imcb_buddy_typing( ic, from, 0 );92 imcb_buddy_typing( ic, bud ? bud->bare_jid : from, 0 ); 106 93 } 107 94 else if( xt_find_node( node->children, "paused" ) ) 108 95 { 109 96 bud->flags |= JBFLAG_DOES_XEP85; 110 imcb_buddy_typing( ic, from, OPT_THINKING );97 imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_THINKING ); 111 98 } 112 99 -
protocols/jabber/presence.c
r256899f rcd428e4 31 31 struct xt_node *c; 32 32 struct jabber_buddy *bud; 33 int is_chat = 0, is_away = 0;34 33 char *s; 35 34 … … 37 36 return XT_HANDLED; 38 37 39 if( ( s = strchr( from, '/' ) ) )40 {41 *s = 0;42 if( jabber_chat_by_name( ic, from ) )43 is_chat = 1;44 *s = '/';45 }46 47 38 if( type == NULL ) 48 39 { 40 int is_away = 0; 41 49 42 if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) 50 43 { … … 79 72 bud->priority = 0; 80 73 81 if( is_chat ) 82 jabber_chat_pkt_presence( ic, bud, node ); 83 else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) 74 if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) 84 75 imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, 85 76 ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, … … 88 79 else if( strcmp( type, "unavailable" ) == 0 ) 89 80 { 90 if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT )) == NULL )81 if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL ) 91 82 { 92 83 if( set_getbool( &ic->irc->set, "debug" ) ) … … 95 86 } 96 87 97 /* Handle this before we delete the JID. */98 if( is_chat )99 {100 jabber_chat_pkt_presence( ic, bud, node );101 }102 103 88 jabber_buddy_remove( ic, from ); 104 89 105 if( is_chat ) 106 { 107 /* Nothing else to do for now? */ 108 } 109 else if( ( s = strchr( from, '/' ) ) ) 90 if( ( s = strchr( from, '/' ) ) ) 110 91 { 111 92 *s = 0; 112 93 113 /* If another resource is still available, send its presence 114 information. */ 115 if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) ) 116 { 117 if( bud->away_state && ( *bud->away_state->code == 0 || 118 strcmp( bud->away_state->code, "chat" ) == 0 ) ) 119 is_away = OPT_AWAY; 120 121 imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, 122 ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, 123 bud->away_message ); 124 } 125 else 126 { 127 /* Otherwise, count him/her as offline now. */ 94 /* Only count this as offline if there's no other resource 95 available anymore. */ 96 if( jabber_buddy_by_jid( ic, from, 0 ) == NULL ) 128 97 imcb_buddy_status( ic, from, 0, NULL, NULL ); 129 }130 98 131 99 *s = '/'; … … 158 126 else if( strcmp( type, "error" ) == 0 ) 159 127 { 160 struct jabber_error *err; 161 162 if( ( c = xt_find_node( node->children, "error" ) ) ) 163 { 164 err = jabber_error_parse( c, XMLNS_STANZA_ERROR ); 165 imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name, 166 err->code, err->text ? ": " : "", 167 err->text ? err->text : "" ); 168 jabber_error_free( err ); 169 } 170 /* What else to do with it? */ 128 /* What to do with it? */ 171 129 } 172 130 … … 182 140 char *show = jd->away_state->code; 183 141 char *status = jd->away_message; 184 struct groupchat *c;185 142 int st; 186 143 … … 193 150 194 151 st = jabber_write_packet( ic, node ); 195 196 /* Have to send this update to all groupchats too, the server won't197 do this automatically. */198 for( c = ic->groupchats; c && st; c = c->next )199 {200 struct jabber_chat *jc = c->data;201 202 xt_add_attr( node, "to", jc->my_full_jid );203 st = jabber_write_packet( ic, node );204 }205 152 206 153 xt_free_node( node ); -
protocols/jabber/sasl.c
r256899f rcd428e4 332 332 struct jabber_data *jd = ic->proto_data; 333 333 334 return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != 0;335 } 334 return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL; 335 } -
protocols/jabber/xmltree.c
r256899f rcd428e4 444 444 list, not the node itself! The reason you have to do this by hand: So 445 445 that you can also use this function as a find-next. */ 446 struct xt_node *xt_find_node( struct xt_node *node, c onst char *name )446 struct xt_node *xt_find_node( struct xt_node *node, char *name ) 447 447 { 448 448 while( node ) … … 457 457 } 458 458 459 char *xt_find_attr( struct xt_node *node, c onst char *key )459 char *xt_find_attr( struct xt_node *node, char *key ) 460 460 { 461 461 int i; … … 526 526 } 527 527 528 void xt_add_attr( struct xt_node *node, c onst char *key, constchar *value )528 void xt_add_attr( struct xt_node *node, char *key, char *value ) 529 529 { 530 530 int i; … … 553 553 } 554 554 555 int xt_remove_attr( struct xt_node *node, c onst char *key )555 int xt_remove_attr( struct xt_node *node, char *key ) 556 556 { 557 557 int i, last; -
protocols/jabber/xmltree.h
r256899f rcd428e4 87 87 void xt_free_node( struct xt_node *node ); 88 88 void xt_free( struct xt_parser *xt ); 89 struct xt_node *xt_find_node( struct xt_node *node, c onst char *name );90 char *xt_find_attr( struct xt_node *node, c onst char *key );89 struct xt_node *xt_find_node( struct xt_node *node, char *name ); 90 char *xt_find_attr( struct xt_node *node, char *key ); 91 91 92 92 struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); 93 93 void xt_add_child( struct xt_node *parent, struct xt_node *child ); 94 void xt_add_attr( struct xt_node *node, c onst char *key, constchar *value );95 int xt_remove_attr( struct xt_node *node, c onst char *key );94 void xt_add_attr( struct xt_node *node, char *key, char *value ); 95 int xt_remove_attr( struct xt_node *node, char *key ); 96 96 97 97 #endif -
protocols/msn/sb.c
r256899f rcd428e4 232 232 if( sb->chat ) 233 233 { 234 imcb_chat_ free( sb->chat );234 imcb_chat_removed( sb->chat ); 235 235 } 236 236 -
protocols/nogaim.c
r256899f rcd428e4 99 99 } 100 100 101 101 102 struct prpl *find_protocol(const char *name) 102 103 { … … 288 289 { 289 290 irc_t *irc = ic->irc; 290 user_t *t, *u ;291 user_t *t, *u = irc->users; 291 292 account_t *a; 292 293 … … 305 306 b_event_remove( ic->inpa ); 306 307 307 u = irc->users;308 308 while( u ) 309 309 { … … 428 428 { 429 429 user_t *u = user_findhandle( ic, handle ); 430 char *s, newnick[MAX_NICK_LENGTH+1]; 430 431 431 432 if( !u || !realname ) return; … … 439 440 if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) 440 441 imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); 441 } 442 } 443 444 void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ) 445 { 446 user_t *u; 447 448 if( ( u = user_findhandle( ic, handle ) ) ) 449 user_del( ic->irc, u->nick ); 450 } 451 452 /* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM 453 modules to suggest a nickname for a handle. */ 454 void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) 455 { 456 user_t *u = user_findhandle( ic, handle ); 457 char newnick[MAX_NICK_LENGTH+1], *orig_nick; 458 459 if( u && !u->online && !nick_saved( ic->acc, handle ) ) 460 { 461 /* Only do this if the person isn't online yet (which should 462 be the case if we just added it) and if the user hasn't 463 assigned a nickname to this buddy already. */ 464 465 strncpy( newnick, nick, MAX_NICK_LENGTH ); 466 newnick[MAX_NICK_LENGTH] = 0; 467 468 /* Some processing to make sure this string is a valid IRC nickname. */ 469 nick_strip( newnick ); 470 if( set_getbool( &ic->irc->set, "lcnicks" ) ) 471 nick_lc( newnick ); 472 473 if( strcmp( u->nick, newnick ) != 0 ) 474 { 475 /* Only do this if newnick is different from the current one. 476 If rejoining a channel, maybe we got this nick already 477 (and dedupe would only add an underscore. */ 478 nick_dedupe( ic->acc, handle, newnick ); 442 443 if( !u->online && !nick_saved( ic->acc, handle ) ) 444 { 445 /* Detect numeric handles: */ 446 for( s = u->user; isdigit( *s ); s++ ); 479 447 480 /* u->nick will be freed halfway the process, so it can't be 481 passed as an argument. */ 482 orig_nick = g_strdup( u->nick ); 483 user_rename( ic->irc, orig_nick, newnick ); 484 g_free( orig_nick ); 485 } 486 } 487 } 448 if( *s == 0 ) 449 { 450 /* If we reached the end of the string, it only contained numbers. 451 Seems to be an ICQ# then, so hopefully realname contains 452 something more useful. */ 453 strcpy( newnick, realname ); 454 455 /* Some processing to make sure this string is a valid IRC nickname. */ 456 nick_strip( newnick ); 457 if( set_getbool( &ic->irc->set, "lcnicks" ) ) 458 nick_lc( newnick ); 459 460 u->nick = g_strdup( newnick ); 461 } 462 } 463 } 464 } 465 488 466 489 467 /* prpl.c */ … … 576 554 u->online = 0; 577 555 578 /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */579 for( c = ic-> groupchats; c; c = c->next )556 /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */ 557 for( c = ic->conversations; c; c = c->next ) 580 558 remove_chat_buddy_silent( c, handle ); 581 559 } … … 692 670 } 693 671 694 void imcb_chat_ free( struct groupchat *c )672 void imcb_chat_removed( struct groupchat *c ) 695 673 { 696 674 struct im_connection *ic = c->ic; 697 struct groupchat *l ;675 struct groupchat *l = NULL; 698 676 GList *ir; 699 677 … … 715 693 } 716 694 717 /* Find the previous chat in the linked list. */718 for( l = ic->groupchats; l && l->next != c; l = l->next );719 720 695 if( l ) 721 696 l->next = c->next; 722 697 else 723 ic-> groupchats = c->next;698 ic->conversations = c->next; 724 699 725 700 for( ir = c->in_room; ir; ir = ir->next ) … … 760 735 } 761 736 762 void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) 763 { 764 struct im_connection *ic = c->ic; 765 user_t *u = NULL; 766 767 if( who == NULL) 768 u = user_find( ic->irc, ic->irc->mynick ); 769 else if( g_strcasecmp( who, ic->acc->user ) == 0 ) 770 u = user_find( ic->irc, ic->irc->nick ); 737 struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) 738 { 739 struct groupchat *c; 740 741 /* This one just creates the conversation structure, user won't see anything yet */ 742 743 if( ic->conversations ) 744 { 745 for( c = ic->conversations; c->next; c = c->next ); 746 c = c->next = g_new0( struct groupchat, 1 ); 747 } 771 748 else 772 u = user_findhandle( ic, who ); 773 774 if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || 775 ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) 776 strip_html( topic ); 777 778 g_free( c->topic ); 779 c->topic = g_strdup( topic ); 780 781 if( c->joined && u ) 782 irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); 783 } 784 785 struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) 786 { 787 struct groupchat *c; 788 789 /* This one just creates the conversation structure, user won't see anything yet */ 790 791 if( ic->groupchats ) 792 { 793 for( c = ic->groupchats; c->next; c = c->next ); 794 c = c->next = g_new0( struct groupchat, 1 ); 795 } 796 else 797 ic->groupchats = c = g_new0( struct groupchat, 1 ); 749 ic->conversations = c = g_new0( struct groupchat, 1 ); 798 750 799 751 c->ic = ic; 800 752 c->title = g_strdup( handle ); 801 753 c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); 802 c->topic = g_strdup_printf( "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->channel, c->title );803 754 804 755 if( set_getbool( &ic->irc->set, "debug" ) ) … … 845 796 } 846 797 847 /* This function is one BIG hack... :-( EREWRITE */848 798 void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) 849 799 { … … 857 807 if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) 858 808 { 859 if( b->joined == 0 )860 return;861 862 809 u = user_find( b->ic->irc, b->ic->irc->nick ); 863 810 b->joined = 0; … … 869 816 } 870 817 871 if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) ) 872 irc_part( b->ic->irc, u, b->channel ); 818 if( remove_chat_buddy_silent( b, handle ) ) 819 if( ( b->joined || me ) && u ) 820 irc_part( b->ic->irc, u, b->channel ); 873 821 } 874 822 … … 896 844 897 845 /* Misc. BitlBee stuff which shouldn't really be here */ 846 847 struct groupchat *chat_by_channel( char *channel ) 848 { 849 struct im_connection *ic; 850 struct groupchat *c; 851 GSList *l; 852 853 /* This finds the connection which has a conversation which belongs to this channel */ 854 for( l = connections; l; l = l->next ) 855 { 856 ic = l->data; 857 for( c = ic->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); 858 if( c ) 859 return c; 860 } 861 862 return NULL; 863 } 898 864 899 865 char *set_eval_away_devoice( set_t *set, char *value ) … … 1129 1095 ic->acc->prpl->rem_deny( ic, handle ); 1130 1096 } 1131 1132 void imcb_clean_handle( struct im_connection *ic, char *handle )1133 {1134 /* Accepts a handle and does whatever is necessary to make it1135 BitlBee-friendly. Currently this means removing everything1136 outside 33-127 (ASCII printable excl spaces), @ (only one1137 is allowed) and ! and : */1138 char out[strlen(handle)+1];1139 int s, d;1140 1141 s = d = 0;1142 while( handle[s] )1143 {1144 if( handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' &&1145 ( handle[s] & 0x80 ) == 0 )1146 {1147 if( handle[s] == '@' )1148 {1149 /* See if we got an @ already? */1150 out[d] = 0;1151 if( strchr( out, '@' ) )1152 continue;1153 }1154 1155 out[d++] = handle[s];1156 }1157 s ++;1158 }1159 out[d] = handle[s];1160 1161 strcpy( handle, out );1162 } -
protocols/nogaim.h
r256899f rcd428e4 61 61 #define OPT_AWAY 0x00000004 62 62 #define OPT_DOES_HTML 0x00000010 63 #define OPT_LOCALBUDDY 0x00000020 /* For nicks local to one groupchat */64 63 #define OPT_TYPING 0x00000100 /* Some pieces of code make assumptions */ 65 64 #define OPT_THINKING 0x00000200 /* about these values... Stupid me! */ … … 92 91 irc_t *irc; 93 92 94 struct groupchat * groupchats;93 struct groupchat *conversations; 95 94 }; 96 95 … … 105 104 GList *ignored; 106 105 106 /* BitlBee */ 107 107 struct groupchat *next; 108 108 char *channel; … … 110 110 * chat using imcb_chat_new(). */ 111 111 char *title; 112 /* Use imcb_chat_topic() to change this variable otherwise the user113 * won't notice the topic change. */114 char *topic;115 112 char joined; 116 113 /* This is for you, you can add your own structure here to extend this … … 215 212 struct groupchat * 216 213 (* chat_join) (struct im_connection *, char *room, char *nick, char *password); 217 /* Change the topic, if supported. Note that BitlBee expects the IM218 server to confirm the topic change with a regular topic change219 event. If it doesn't do that, you have to fake it to make it220 visible to the user. */221 void (* chat_topic) (struct groupchat *, char *topic);222 214 223 215 /* You can tell what away states your protocol supports, so that … … 273 265 G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); 274 266 G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ); 275 G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );276 267 277 268 /* Buddy activity */ … … 285 276 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); 286 277 G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); 287 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );288 278 289 279 /* Groupchats */ … … 301 291 /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ 302 292 G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); 303 /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ 304 G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ); 305 G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); 293 G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c ); 294 struct groupchat *chat_by_channel( char *channel ); 306 295 307 296 /* Actions, or whatever. */ -
protocols/oscar/oscar.c
r256899f rcd428e4 2031 2031 2032 2032 if (realname) { 2033 imcb_buddy_nick_hint(ic, curitem->name, realname);2034 2033 imcb_rename_buddy(ic, curitem->name, realname); 2035 2034 g_free(realname); … … 2524 2523 2525 2524 /* Notify the conversation window that we've left the chat */ 2526 imcb_chat_ free(cc->cnv);2525 imcb_chat_removed(cc->cnv); 2527 2526 2528 2527 /* Destroy the chat_connection */ -
protocols/yahoo/yahoo.c
r256899f rcd428e4 145 145 GSList *l; 146 146 147 while( ic-> groupchats )148 imcb_chat_ free( ic->groupchats );147 while( ic->conversations ) 148 imcb_chat_removed( ic->conversations ); 149 149 150 150 for( l = yd->buddygroups; l; l = l->next ) … … 318 318 319 319 yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); 320 imcb_chat_ free( c );320 imcb_chat_removed( c ); 321 321 } 322 322 … … 798 798 { 799 799 yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); 800 imcb_chat_ free( inv->c );800 imcb_chat_removed( inv->c ); 801 801 g_free( inv->name ); 802 802 g_free( inv ); … … 841 841 struct groupchat *c; 842 842 843 for( c = ic-> groupchats; c && strcmp( c->title, room ) != 0; c = c->next );843 for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); 844 844 845 845 if( c ) … … 853 853 struct groupchat *c; 854 854 855 for( c = ic-> groupchats; c && strcmp( c->title, room ) != 0; c = c->next );855 for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); 856 856 857 857 if( c ) … … 865 865 struct groupchat *c; 866 866 867 for( c = ic-> groupchats; c && strcmp( c->title, room ) != 0; c = c->next );867 for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); 868 868 869 869 if( c ) -
root_commands.c
r256899f rcd428e4 930 930 if( cmd[3] ) 931 931 { 932 if( cmd[3][0] != '#' && cmd[3][0] != '&' ) 933 channel = g_strdup_printf( "&%s", cmd[3] ); 934 else 935 channel = g_strdup( cmd[3] ); 932 channel = g_strdup( cmd[3] ); 936 933 } 937 934 else … … 939 936 char *s; 940 937 941 channel = g_strdup _printf( "&%s",chat );938 channel = g_strdup( chat ); 942 939 if( ( s = strchr( channel, '@' ) ) ) 943 940 *s = 0; … … 945 942 if( cmd[3] && cmd[4] ) 946 943 nick = cmd[4]; 947 else948 nick = irc->nick;949 944 if( cmd[3] && cmd[4] && cmd[5] ) 950 945 password = cmd[5]; 951 946 952 if( !nick_ok( channel + 1 ) ) 953 { 954 irc_usermsg( irc, "Invalid channel name: %s", channel ); 955 g_free( channel ); 956 return; 957 } 958 else if( g_strcasecmp( channel, irc->channel ) == 0 || irc_chat_by_channel( irc, channel ) ) 959 { 960 irc_usermsg( irc, "Channel already exists: %s", channel ); 961 g_free( channel ); 962 return; 963 } 964 965 if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) ) 966 { 967 g_free( c->channel ); 968 c->channel = channel; 969 } 970 else 971 { 972 irc_usermsg( irc, "Tried to join chat, not sure if this was successful" ); 973 g_free( channel ); 974 } 947 c = a->prpl->chat_join( ic, chat, nick, password ); 948 949 g_free( channel ); 975 950 } 976 951 -
user.c
r256899f rcd428e4 161 161 } 162 162 163 /* DO NOT PASS u->nick FOR oldnick !!! */164 163 void user_rename( irc_t *irc, char *oldnick, char *newnick ) 165 164 {
Note: See TracChangeset
for help on using the changeset viewer.