From c058ff976bbbbf43ef11c262f21440e61244f73e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 9 Dec 2007 23:19:35 +0000 Subject: Added /invite support for Jabber chatrooms (and fixed the argument order to chat_invite). --- protocols/jabber/conference.c | 21 +++++++++++++++++++++ protocols/jabber/jabber.c | 16 +++++++++++++++- protocols/jabber/jabber.h | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index c5bc0e68..074412ec 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -175,6 +175,27 @@ int jabber_chat_leave( struct groupchat *c, const char *reason ) return 1; } +void jabber_chat_invite( struct groupchat *c, char *who, char *message ) +{ + struct xt_node *node; + struct im_connection *ic = c->ic; + struct jabber_chat *jc = c->data; + + node = xt_new_node( "reason", message, NULL ); + + node = xt_new_node( "invite", NULL, node ); + xt_add_attr( node, "to", who ); + + node = xt_new_node( "x", NULL, node ); + xt_add_attr( node, "xmlns", XMLNS_MUC_USER ); + + node = jabber_make_packet( "message", NULL, jc->name, node ); + + jabber_write_packet( ic, node ); + + xt_free_node( node ); +} + /* Not really the same syntax as the normal pkt_ functions, but this isn't called by the xmltree parser directly and this way I can add some extra parameters so we won't have to repeat too many things done by the caller diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e2a3a27a..4c89ab5c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -426,6 +426,20 @@ static void jabber_chat_leave_( struct groupchat *c ) jabber_chat_leave( c, NULL ); } +static void jabber_chat_invite_( struct groupchat *c, char *who, char *msg ) +{ + struct jabber_chat *jc = c->data; + gchar *msg_alt = NULL; + + if( msg == NULL ) + msg_alt = g_strdup_printf( "%s invited you to %s", c->ic->acc->user, jc->name ); + + if( c && who ) + jabber_chat_invite( c, who, msg ? msg : msg_alt ); + + g_free( msg_alt ); +} + static void jabber_keepalive( struct im_connection *ic ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ @@ -497,7 +511,7 @@ void jabber_initmodule() ret->remove_buddy = jabber_remove_buddy; ret->chat_msg = jabber_chat_msg_; ret->chat_topic = jabber_chat_topic_; -// ret->chat_invite = jabber_chat_invite; + ret->chat_invite = jabber_chat_invite_; ret->chat_leave = jabber_chat_leave_; ret->chat_join = jabber_chat_join_; ret->keepalive = jabber_keepalive; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 94d017d6..56056534 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -236,5 +236,6 @@ int jabber_chat_topic( struct groupchat *c, char *topic ); int jabber_chat_leave( struct groupchat *c, const char *reason ); void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); +void jabber_chat_invite( struct groupchat *c, char *who, char *message ); #endif -- cgit v1.2.3 From d52111a7b05657e4a4fa8417e6655389a50769cf Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 12 Dec 2007 21:36:33 +0000 Subject: Fixed sockerr_again() usage in Jabber module to (hopefully) fix a 100% CPU usage bug. --- protocols/jabber/io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 61cd142e..29561b86 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -119,7 +119,7 @@ static gboolean jabber_write_queue( struct im_connection *ic ) return TRUE; } - else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) { /* Set fd to -1 to make sure we won't write to it anymore. */ closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ @@ -230,7 +230,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } } } - else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) { closesocket( jd->fd ); jd->fd = -1; -- cgit v1.2.3 From 529078a3e7f701c7b85201380b2d2097ac676ec6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Dec 2007 16:35:38 +0000 Subject: Implemented XEP-0199 (patch from misc@mandriva.org). --- protocols/jabber/iq.c | 12 +++++++++++- protocols/jabber/jabber.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 3dae39f6..069e3af3 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -49,7 +49,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( type, "get" ) == 0 ) { - if( !( c = xt_find_node( node->children, "query" ) ) || + if( !( ( c = xt_find_node( node->children, "query" ) ) || + ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just ????? */ !( s = xt_find_attr( c, "xmlns" ) ) ) { imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); @@ -80,12 +81,21 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); } + else if( strcmp( s, XMLNS_PING ) == 0 ) + { + xt_free_node( reply ); + reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), NULL ); + if( ( s = xt_find_attr( node, "id" ) ) ) + xt_add_attr( reply, "id", s ); + pack = 0; + } else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { const char *features[] = { XMLNS_VERSION, XMLNS_TIME, XMLNS_CHATSTATES, XMLNS_MUC, + XMLNS_PING, NULL }; const char **f; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 56056534..f673ee0d 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -151,6 +151,7 @@ struct jabber_chat #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ +#define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ -- cgit v1.2.3 From fb4ebcc5e3cffc4683cd3f38d7aba6cd86dbcd50 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 28 Dec 2007 23:26:44 +0000 Subject: Added missing return in jabber_login(). --- protocols/jabber/jabber.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'protocols/jabber') diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 4c89ab5c..264a0308 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -196,6 +196,8 @@ static void jabber_login( account_t *acc ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); + + return; } if( set_getbool( &acc->set, "xmlconsole" ) ) -- cgit v1.2.3 From 434627083613f016d432462fce73f728dd77172e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 6 Jan 2008 12:37:55 +0000 Subject: More consistency in error/warning errors. Until now "WARNING:" was usually in upper case while "Error:" wasn't .... that doesn't really make sense. --- protocols/jabber/iq.c | 12 ++++++------ protocols/jabber/jabber_util.c | 2 +- protocols/jabber/presence.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 069e3af3..e1bab29e 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -53,7 +53,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just ????? */ !( s = xt_find_attr( c, "xmlns" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -124,7 +124,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -146,7 +146,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else { - imcb_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); + imcb_log( ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -211,7 +211,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no if( !( query = xt_find_node( node->children, "query" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -269,7 +269,7 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node if( !( type = xt_find_attr( node, "type" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -345,7 +345,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * if( !( query = xt_find_node( node->children, "query" ) ) ) { - imcb_log( ic, "WARNING: Received NULL roster packet" ); + imcb_log( ic, "Warning: Received NULL roster packet" ); return XT_HANDLED; } diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 9d84e099..b84be49b 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -199,7 +199,7 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node * if( entry == NULL ) { - imcb_log( ic, "WARNING: Received %s-%s packet with unknown/expired ID %s!", + imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!", node->name, xt_find_attr( node, "type" ) ? : "(no type)", s ); } else if( entry->func ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index c3d7dced..f2dca26c 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -49,7 +49,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); + imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -90,7 +90,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); + imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } -- cgit v1.2.3 From e7f8838951c81ba7edf6c6567cf68075de42be6e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 11 Jan 2008 13:17:11 +0000 Subject: Fixing bug #344, now away states should always be correct, even when people do complicated things with multiple resources. (There were two bugs and some duplicated code, so I moved things around a bit.) --- protocols/jabber/presence.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index f2dca26c..3bfc83ff 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -29,8 +29,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; - struct jabber_buddy *bud; - int is_chat = 0, is_away = 0; + struct jabber_buddy *bud, *send_presence = NULL; + int is_chat = 0; char *s; if( !from ) @@ -62,8 +62,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) { bud->away_state = (void*) jabber_away_state_by_code( c->text ); - if( strcmp( c->text, "chat" ) != 0 ) - is_away = OPT_AWAY; } else { @@ -80,10 +78,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( is_chat ) jabber_chat_pkt_presence( ic, bud, node ); - else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) - imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, - bud->away_message ); + else + send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 ); } else if( strcmp( type, "unavailable" ) == 0 ) { @@ -118,17 +114,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* If another resource is still available, send its presence information. */ - if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) ) - { - if( bud->away_state && ( *bud->away_state->code == 0 || - strcmp( bud->away_state->code, "chat" ) == 0 ) ) - is_away = OPT_AWAY; - - imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, - bud->away_message ); - } - else + if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) { /* Otherwise, count him/her as offline now. */ imcb_buddy_status( ic, from, 0, NULL, NULL ); @@ -176,6 +162,20 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) jabber_error_free( err ); } */ } + + if( send_presence ) + { + int is_away; + + if( send_presence->away_state && !( *send_presence->away_state->code == 0 || + strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) + is_away = OPT_AWAY; + + imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, + ( is_away && send_presence->away_state ) ? + send_presence->away_state->full_name : NULL, + send_presence->away_message ); + } return XT_HANDLED; } -- cgit v1.2.3 From dded27d9a58237036b23f152eb6dfeaad3ae762d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 13 Jan 2008 14:48:32 +0000 Subject: Fixed "Conditional jump or move depends on uninitialised value(s)" at jabber_pkt_presence (presence.c:174). Valgrind-Wilmer: 1-0. --- protocols/jabber/presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 3bfc83ff..2c49b800 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -165,7 +165,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( send_presence ) { - int is_away; + int is_away = 0; if( send_presence->away_state && !( *send_presence->away_state->code == 0 || strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) -- cgit v1.2.3 From 13857c648210a16448619c65e33f9918bfe27cbe Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 13 Jan 2008 17:13:45 +0000 Subject: Fixed handing of failed groupchat joins. --- protocols/jabber/conference.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 074412ec..466cb323 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -72,17 +72,16 @@ static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_no char *room; room = xt_find_attr( orig, "to" ); - if( ( bud = jabber_buddy_by_jid( ic, room, 0 ) ) ) - jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); - + bud = jabber_buddy_by_jid( ic, room, 0 ); err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR ); if( err ) { - imcb_error( ic, "Error joining groupchat %s: %s%s%s", - bud->bare_jid, err->code, err->text ? ": " : "", - err->text ? err->text : "" ); + imcb_error( ic, "Error joining groupchat %s: %s%s%s", room, err->code, + err->text ? ": " : "", err->text ? err->text : "" ); jabber_error_free( err ); } + if( bud ) + jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); return XT_HANDLED; } -- cgit v1.2.3 From 0adce2151fc2a4f517e558663e5afe010b86a39a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 20 Jan 2008 00:01:31 +0000 Subject: GET_BUDDY_FIRST wasn't actually implemented, even though it was in use already. I don't want to know how long it took me to find out... --- protocols/jabber/jabber_util.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index b84be49b..794a1040 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -391,19 +391,26 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) { + /* Just return the first one for this bare JID. */ + if( flags & GET_BUDDY_FIRST ) + { + *s = '/'; + g_free( jid ); + return bud; + } + /* Is this one of those no-resource buddies? */ if( bud->resource == NULL ) { + *s = '/'; g_free( jid ); return NULL; } - else - { - /* See if there's an exact match. */ - for( ; bud; bud = bud->next ) - if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) - break; - } + + /* See if there's an exact match. */ + for( ; bud; bud = bud->next ) + if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) + break; } else { @@ -412,6 +419,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, for this JID, even if it's an unknown buddy. This is done to handle conferences properly. */ none_found = 1; + /* TODO(wilmer): Find out what I was thinking when I + wrote this??? And then fix it. This makes me sad... */ } if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) @@ -442,6 +451,9 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, else if( ( bud->resource == NULL || bud->next == NULL ) ) /* No need for selection if there's only one option. */ return bud; + else if( flags & GET_BUDDY_FIRST ) + /* Looks like the caller doesn't care about details. */ + return bud; best_prio = best_time = bud; for( ; bud; bud = bud->next ) -- cgit v1.2.3 From a882d6c1eec55fb9a00ce61acd6d776884d0c84a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 20 Jan 2008 11:15:40 +0000 Subject: The Jabber module now uses imcb_chat_log() instead of imcb_log() where possible. --- protocols/jabber/conference.c | 46 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 466cb323..515194fc 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -294,18 +294,54 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud { struct xt_node *subject = xt_find_node( node->children, "subject" ); struct xt_node *body = xt_find_node( node->children, "body" ); - struct groupchat *chat; + struct groupchat *chat = NULL; char *s; if( bud == NULL ) { + char *nick; + + if( body == NULL || body->text_len == 0 ) + /* Meh. Empty messages aren't very interesting, no matter + how much some servers love to send them. */ + return; + s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */ - if( strchr( s, '/' ) == NULL ) + nick = strchr( s, '/' ); + if( nick ) + { + /* If this message included a resource/nick we don't know, + we might still know the groupchat itself. */ + *nick = 0; + chat = jabber_chat_by_jid( ic, s ); + *nick = '/'; + + nick ++; + } + else + { + /* message.c uses the EXACT_JID option, so bud should + always be NULL here for bare JIDs. */ + chat = jabber_chat_by_jid( ic, s ); + } + + if( nick == NULL ) + { /* This is fine, the groupchat itself isn't in jd->buddies. */ - imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" ); + if( chat ) + imcb_chat_log( chat, "From conference server: %s", body->text ); + else + imcb_log( ic, "System message from unknown groupchat %s: %s", s, body->text ); + } else - /* This, however, isn't fine! */ - imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" ); + { + /* This can happen too, at least when receiving a backlog when + just joining a channel. */ + if( chat ) + imcb_chat_log( chat, "Message from unknown participant %s: %s", nick, body->text ); + else + imcb_log( ic, "Groupchat message from unknown JID %s: %s", s, body->text ); + } return; } -- cgit v1.2.3 From b5c8a34aeff244ffe7a9f4bd5edf827495d0deea Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 24 Jan 2008 22:49:47 +0000 Subject: Keeping track of valid Jabber connections so _connected() events will be ignored if the connection's dead already. Necessary if using GLib for event handling for now. :-/ --- protocols/jabber/io.c | 10 +++++++++- protocols/jabber/jabber.c | 9 +++++++++ protocols/jabber/jabber.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 29561b86..86c216ef 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -248,6 +248,9 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c { struct im_connection *ic = data; + if( g_slist_find( jabber_connections, ic ) == NULL ) + return FALSE; + if( source == -1 ) { imcb_error( ic, "Could not connect to server" ); @@ -263,7 +266,12 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ) { struct im_connection *ic = data; - struct jabber_data *jd = ic->proto_data; + struct jabber_data *jd; + + if( g_slist_find( jabber_connections, ic ) == NULL ) + return FALSE; + + jd = ic->proto_data; if( source == NULL ) { diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 264a0308..243ed7fd 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -34,6 +34,8 @@ #include "md5.h" #include "base64.h" +GSList *jabber_connections; + static void jabber_init( account_t *acc ) { set_t *s; @@ -70,6 +72,11 @@ static void jabber_login( account_t *acc ) struct ns_srv_reply *srv = NULL; char *connect_to, *s; + /* For now this is needed in the _connected() handlers if using + GLib event handling, to make sure we're not handling events + on dead connections. */ + jabber_connections = g_slist_prepend( jabber_connections, ic ); + jd->ic = ic; ic->proto_data = jd; @@ -262,6 +269,8 @@ static void jabber_logout( struct im_connection *ic ) g_free( jd->away_message ); g_free( jd->username ); g_free( jd ); + + jabber_connections = g_slist_remove( jabber_connections, ic ); } static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index f673ee0d..cf0f8e6a 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -29,6 +29,8 @@ #include "xmltree.h" #include "bitlbee.h" +extern GSList *jabber_connections; + typedef enum { JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream -- cgit v1.2.3 From 979cfb448cc233e29ceb6cd43f99fb4104728be6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 3 Feb 2008 13:54:19 +0000 Subject: Saner garbage collection of cached packets in the Jabber module. Now cached packets are removed after about ten minues instead of something between one and two minutes. Closes one issue in #354. --- protocols/jabber/jabber.h | 5 +++++ protocols/jabber/jabber_util.c | 16 ++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index cf0f8e6a..5132d45f 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -94,6 +94,7 @@ typedef xt_status (*jabber_cache_event) ( struct im_connection *ic, struct xt_no struct jabber_cache_entry { + time_t saved_at; struct xt_node *node; jabber_cache_event func; }; @@ -140,6 +141,10 @@ struct jabber_chat #define JABBER_PACKET_ID "BeeP" #define JABBER_CACHED_ID "BeeC" +/* The number of seconds to keep cached packets before garbage collecting + them. This gc is done on every keepalive (every minute). */ +#define JABBER_CACHE_MAX_AGE 600 + /* RFC 392[01] stuff */ #define XMLNS_TLS "urn:ietf:params:xml:ns:xmpp-tls" #define XMLNS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 794a1040..6e872040 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -141,6 +141,7 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca entry->node = node; entry->func = func; + entry->saved_at = time( NULL ); g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } @@ -162,22 +163,17 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpo void jabber_cache_clean( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; + time_t threshold = time( NULL ) - JABBER_CACHE_MAX_AGE; - g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); + g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, &threshold ); } -gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer ) +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer threshold_ ) { struct jabber_cache_entry *entry = entry_; - struct xt_node *node = entry->node; + time_t *threshold = threshold_; - if( node->flags & XT_SEEN ) - return TRUE; - else - { - node->flags |= XT_SEEN; - return FALSE; - } + return entry->saved_at < *threshold; } xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ) -- cgit v1.2.3 From 8c1eb8025f493ce22b4cc58da1ecfd4afa416816 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 3 Feb 2008 16:59:39 +0000 Subject: Implemented XEP-0115. This adds some info to the tags so clients interested in capabilities can cache discovery info, so they don't have to ask about it every time you/they log in. --- protocols/jabber/iq.c | 3 ++- protocols/jabber/jabber.h | 1 + protocols/jabber/presence.c | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e1bab29e..c88bc0b0 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -91,7 +91,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { - const char *features[] = { XMLNS_VERSION, + const char *features[] = { XMLNS_DISCOVER, + XMLNS_VERSION, XMLNS_TIME, XMLNS_CHATSTATES, XMLNS_MUC, diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 5132d45f..44655409 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -165,6 +165,7 @@ struct jabber_chat #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */ +#define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 2c49b800..6fc360b7 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -28,7 +28,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) struct im_connection *ic = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ - struct xt_node *c; + struct xt_node *c, *cap; struct jabber_buddy *bud, *send_presence = NULL; int is_chat = 0; char *s; @@ -76,6 +76,26 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; + if( bud && ( cap = xt_find_node( node->children, "c" ) ) && + ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 ) + { + /* This stanza includes an XEP-0115 + capabilities part. Not too interesting, but we can + see if it has an ext= attribute. */ + s = xt_find_attr( cap, "ext" ); + if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) ) + bud->flags |= JBFLAG_DOES_XEP85; + + /* This field can contain more information like xhtml + support, but we don't support that ourselves. + Officially the ext= tag was deprecated, but enough + clients do send it. + + (I'm aware that this is not the right way to use + this field.) See for an explanation of ext=: + http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/ + } + if( is_chat ) jabber_chat_pkt_presence( ic, bud, node ); else @@ -185,7 +205,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) int presence_send_update( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; - struct xt_node *node; + struct xt_node *node, *cap; char *show = jd->away_state->code; char *status = jd->away_message; struct groupchat *c; @@ -198,6 +218,16 @@ int presence_send_update( struct im_connection *ic ) if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); + /* This makes the packet slightly bigger, but clients interested in + capabilities can now cache the discovery info. This reduces the + usual post-login iq-flood. See XEP-0115. At least libpurple and + Trillian seem to do this right. */ + cap = xt_new_node( "c", NULL, NULL ); + xt_add_attr( cap, "xmlns", XMLNS_CAPS ); + xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" ); + xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */ + xt_add_child( node, cap ); + st = jabber_write_packet( ic, node ); /* Have to send this update to all groupchats too, the server won't -- cgit v1.2.3 From 63075d7345355dde6e490ad00a886a1b165dbe17 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 3 Feb 2008 23:33:18 +0000 Subject: Messages from the user are also included in backlogs when joining a Jabber chatroom. Until now they were ignored, which might make backlogs a little bit confusing. --- protocols/jabber/conference.c | 9 ++++++--- protocols/jabber/jabber.h | 14 ++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'protocols/jabber') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 515194fc..f206e084 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -122,6 +122,8 @@ int jabber_chat_msg( struct groupchat *c, char *message, int flags ) struct jabber_chat *jc = c->data; struct xt_node *node; + jc->flags |= JCFLAG_MESSAGE_SENT; + node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "groupchat", jc->name, node ); @@ -294,10 +296,11 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud { struct xt_node *subject = xt_find_node( node->children, "subject" ); struct xt_node *body = xt_find_node( node->children, "body" ); - struct groupchat *chat = NULL; + struct groupchat *chat = bud ? jabber_chat_by_jid( ic, bud->bare_jid ) : NULL; + struct jabber_chat *jc = chat ? chat->data : NULL; char *s; - if( bud == NULL ) + if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) ) { char *nick; @@ -345,7 +348,7 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud return; } - else if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL ) + else if( chat == NULL ) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 44655409..1ff0e8dd 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -48,16 +48,22 @@ typedef enum typedef enum { - JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make + JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make sure it gets sent only once. */ - JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support + JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support XEP85 (typing notification shite). */ - JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for + JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for groupchat state info too. */ - JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have + JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have have a real JID. */ } jabber_buddy_flags_t; +typedef enum +{ + JCFLAG_MESSAGE_SENT = 1, /* Set this after sending the first message, so + we can detect echoes/backlogs. */ +} jabber_chat_flags_t; + struct jabber_data { struct im_connection *ic; -- cgit v1.2.3 From 3038e476a93b2be057581b831749eac931a06559 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 10 Feb 2008 17:11:06 +0000 Subject: Added support for password-protected Jabber chatrooms. --- protocols/jabber/conference.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'protocols/jabber') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index f206e084..79fdd053 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -36,6 +36,8 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * node = xt_new_node( "x", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_MUC ); node = jabber_make_packet( "presence", NULL, roomjid, node ); + if( password ) + xt_add_child( node, xt_new_node( "password", password, NULL ) ); jabber_cache_add( ic, node, jabber_chat_join_failed ); if( !jabber_write_packet( ic, node ) ) -- cgit v1.2.3