From f06894d8f55b50b632c1d81ad878f8581273ba66 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 20 Sep 2006 12:18:56 +0200 Subject: Added some pretty empty files. --- protocols/jabber/jabber_util.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 protocols/jabber/jabber_util.c (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c new file mode 100644 index 00000000..ff79cb16 --- /dev/null +++ b/protocols/jabber/jabber_util.c @@ -0,0 +1,48 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, write to the Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +char *set_eval_resprio( set_t *set, char *value ) +{ + account_t *acc = set->data; + + /* Only run this stuff if the account is online ATM. */ + if( acc->gc ) + { + /* ... */ + } + + if( g_strcasecmp( set->key, "priority" ) == 0 ) + return set_eval_int( set, value ); + else + return value; +} + +char *set_eval_tls( set_t *set, char *value ) +{ + if( g_strcasecmp( value, "try" ) == 0 ) + return value; + else + return set_eval_bool( set, value ); +} -- cgit v1.2.3 From 21167d2d14c333d67445546bb69dd52dd295287d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 20 Sep 2006 21:42:27 +0200 Subject: It can send a valid (pre-XMPP) login packet. Lots of work to do, still... --- protocols/jabber/jabber_util.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index ff79cb16..46811d05 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -1,7 +1,7 @@ /***************************************************************************\ * * * BitlBee - An IRC to IM gateway * -* Jabber module - Main file * +* Jabber module - Misc. stuff * * * * Copyright 2006 Wilmer van der Gaast * * * @@ -23,6 +23,8 @@ #include "jabber.h" +static int next_id = 1; + char *set_eval_resprio( set_t *set, char *value ) { account_t *acc = set->data; @@ -46,3 +48,21 @@ char *set_eval_tls( set_t *set, char *value ) else return set_eval_bool( set, value ); } + +struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ) +{ + char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + struct xt_node *node; + + node = xt_new_node( name, NULL, children ); + + xt_add_attr( node, "id", id ); + if( type ) + xt_add_attr( node, "type", type ); + if( to ) + xt_add_attr( node, "to", to ); + + g_free( id ); + + return node; +} -- cgit v1.2.3 From fe7a55434385fd858453dffdbb425a21f41e3859 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 22 Sep 2006 20:39:31 +0200 Subject: Better detection of successful IQ authentication (using packet caching), properly working SASL authentication (although only PLAIN so far). --- protocols/jabber/jabber_util.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 46811d05..88b9e55d 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -51,18 +51,43 @@ char *set_eval_tls( set_t *set, char *value ) struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ) { - char *id = g_strdup_printf( "BeeX%04x", next_id++ ); struct xt_node *node; node = xt_new_node( name, NULL, children ); - xt_add_attr( node, "id", id ); if( type ) xt_add_attr( node, "type", type ); if( to ) xt_add_attr( node, "to", to ); + return node; +} + +/* Cache a node/packet for later use. Mainly useful for IQ packets if you need + them when you receive the response. Use this BEFORE sending the packet so + it'll get an id= tag, and do NOT free() the packet after writing it! */ +void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +{ + struct jabber_data *jd = gc->proto_data; + char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + + /* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ + + xt_add_attr( node, "id", id ); + xt_add_child( jd->node_cache, node ); g_free( id ); +} + +/* Emptying this cache is a BIG TODO! */ +struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *node; + char *s; + + for( node = jd->node_cache->children; node; node = node->next ) + if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) + break; return node; } -- cgit v1.2.3 From 5e202b09f2cd9faff5f316ae6804facb5342eace Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 23 Sep 2006 18:18:24 +0200 Subject: Implemented a list of away states, using this for a better set_away(), and got rid of the double tag sent because of presence_announce(). --- protocols/jabber/jabber_util.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 88b9e55d..21df5126 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -91,3 +91,35 @@ struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) return node; } + +const struct jabber_away_state jabber_away_state_list[] = +{ + { "away", "Away" }, + { "chat", "Free for Chat" }, + { "dnd", "Do not Disturb" }, + { "xa", "Extended Away" }, + { "", "Online" }, + { "", NULL } +}; + +const struct jabber_away_state *jabber_away_state_by_code( char *code ) +{ + int i; + + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) + if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 ) + return jabber_away_state_list + i; + + return NULL; +} + +const struct jabber_away_state *jabber_away_state_by_name( char *name ) +{ + int i; + + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) + if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 ) + return jabber_away_state_list + i; + + return NULL; +} -- cgit v1.2.3 From 172a73f1a4b37fa20d1d50496a3faccb8fe6c769 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 24 Sep 2006 12:25:41 +0200 Subject: Updated stuff to handle changing the priority setting. --- protocols/jabber/jabber_util.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 21df5126..e7a161cc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -28,17 +28,42 @@ static int next_id = 1; char *set_eval_resprio( set_t *set, char *value ) { account_t *acc = set->data; + char *ret; - /* Only run this stuff if the account is online ATM. */ - if( acc->gc ) + if( strcmp( set->key, "priority" ) == 0 ) + ret = set_eval_int( set, value ); + else + ret = value; + + /* Only run this stuff if the account is online ATM, + and if the setting seems to be acceptable. */ + if( acc->gc && ret ) { - /* ... */ + if( strcmp( set->key, "priority" ) == 0 ) + { + /* Although set_eval functions usually are very nice + and convenient, they have one disadvantage: If I + would just call p_s_u() now to send the new prio + setting, it would send the old setting because the + set->value gets changed when the eval returns a + non-NULL value. + + So now I can choose between implementing post-set + functions next to evals, or just do this little + hack: */ + g_free( set->value ); + set->value = g_strdup( ret ); + + /* (Yes, sorry, I prefer the hack. :-P) */ + + presence_send_update( acc->gc ); + } + else + { + } } - if( g_strcasecmp( set->key, "priority" ) == 0 ) - return set_eval_int( set, value ); - else - return value; + return ret; } char *set_eval_tls( set_t *set, char *value ) -- cgit v1.2.3 From 8e5e2e9a0ef549c94afc8041dc7d99358f51c9bd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 24 Sep 2006 21:25:06 +0200 Subject: Handling of incoming authorization requests, manual block/allow. (Doesn't seem to be completely like how it works on other IM networks.) --- protocols/jabber/jabber_util.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index e7a161cc..3a0d2004 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -148,3 +148,41 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name ) return NULL; } + +struct jabber_buddy_ask_data +{ + struct gaim_connection *gc; + char *handle; + char *realname; +}; + +static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) +{ + presence_send_request( bla->gc, bla->handle, "subscribed" ); + + if( find_buddy( bla->gc, bla->handle ) == NULL ) + show_got_added( bla->gc, bla->handle, NULL ); + + g_free( bla->handle ); + g_free( bla ); +} + +static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) +{ + presence_send_request( bla->gc, bla->handle, "subscribed" ); + + g_free( bla->handle ); + g_free( bla ); +} + +void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) +{ + struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 ); + char *buf; + + bla->gc = gc; + bla->handle = g_strdup( handle ); + + buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); + do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); +} -- cgit v1.2.3 From ebe7b36af555d644357efbc0e63393927162bf06 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 25 Sep 2006 12:10:14 +0200 Subject: Changing the resource string while online probably doesn't work. --- protocols/jabber/jabber_util.c | 44 ++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3a0d2004..6764e7b3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -25,42 +25,32 @@ static int next_id = 1; -char *set_eval_resprio( set_t *set, char *value ) +char *set_eval_priority( set_t *set, char *value ) { account_t *acc = set->data; char *ret; - if( strcmp( set->key, "priority" ) == 0 ) - ret = set_eval_int( set, value ); - else - ret = value; + ret = set_eval_int( set, value ); /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ if( acc->gc && ret ) { - if( strcmp( set->key, "priority" ) == 0 ) - { - /* Although set_eval functions usually are very nice - and convenient, they have one disadvantage: If I - would just call p_s_u() now to send the new prio - setting, it would send the old setting because the - set->value gets changed when the eval returns a - non-NULL value. - - So now I can choose between implementing post-set - functions next to evals, or just do this little - hack: */ - g_free( set->value ); - set->value = g_strdup( ret ); - - /* (Yes, sorry, I prefer the hack. :-P) */ - - presence_send_update( acc->gc ); - } - else - { - } + /* Although set_eval functions usually are very nice and + convenient, they have one disadvantage: If I would just + call p_s_u() now to send the new prio setting, it would + send the old setting because the set->value gets changed + when the eval returns a non-NULL value. + + So now I can choose between implementing post-set + functions next to evals, or just do this little hack: */ + + g_free( set->value ); + set->value = g_strdup( ret ); + + /* (Yes, sorry, I prefer the hack. :-P) */ + + presence_send_update( acc->gc ); } return ret; -- cgit v1.2.3 From 6266fcab664c9a907b1d32a1c94ef7fd3cfb9fba Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 2 Oct 2006 20:32:21 +0200 Subject: Fixed memory leak in jabber_buddy_ask() and added "handling" of type="error" tags. --- protocols/jabber/jabber_util.c | 1 + 1 file changed, 1 insertion(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 6764e7b3..845c2d8c 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -175,4 +175,5 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + g_free( buf ); } -- cgit v1.2.3 From 038d17f834219505cbbdae469b2b150117467dd0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 8 Oct 2006 18:11:16 +0200 Subject: Implemented a better node cache using a GLib hash, and preparing to add event handlers that can be set when sending a packet to handle the reply to this specific packet. This should allow me to make the iq handler a lot cleaner. --- protocols/jabber/jabber_util.c | 50 ++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 845c2d8c..11156258 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -81,30 +81,56 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) { struct jabber_data *jd = gc->proto_data; char *id = g_strdup_printf( "BeeX%04x", next_id++ ); - - /* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ + struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); xt_add_attr( node, "id", id ); - xt_add_child( jd->node_cache, node ); g_free( id ); + + entry->node = node; + g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } -/* Emptying this cache is a BIG TODO! */ -struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ) { struct jabber_data *jd = gc->proto_data; - struct xt_node *node; - char *s; + struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id ); - for( node = jd->node_cache->children; node; node = node->next ) - if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) - break; + return entry ? entry->node : NULL; +} + +void jabber_cache_entry_free( gpointer data ) +{ + struct jabber_cache_entry *entry = data; - return node; + xt_free_node( entry->node ); + g_free( entry ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); + +void jabber_cache_clean( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + + g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer ) +{ + struct jabber_cache_entry *entry = entry_; + struct xt_node *node = entry->node; + + if( node->flags & XT_SEEN ) + return TRUE; + else + { + node->flags |= XT_SEEN; + return FALSE; + } } const struct jabber_away_state jabber_away_state_list[] = -- cgit v1.2.3 From 861c199fb60fecf5dab96e0ed9d4b0cf0c57822f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 8 Oct 2006 20:41:11 +0200 Subject: Moved handling of all IQ packets to event handlers. Cleaned up a LOT of mess in iq.c! --- protocols/jabber/jabber_util.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 11156258..f26b9617 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -81,7 +81,7 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = gc->proto_data; char *id = g_strdup_printf( "BeeX%04x", next_id++ ); @@ -91,17 +91,10 @@ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) g_free( id ); entry->node = node; + entry->func = func; g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } -struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ) -{ - struct jabber_data *jd = gc->proto_data; - struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id ); - - return entry ? entry->node : NULL; -} - void jabber_cache_entry_free( gpointer data ) { struct jabber_cache_entry *entry = data; @@ -112,6 +105,11 @@ void jabber_cache_entry_free( gpointer data ) gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); +/* This one should be called from time to time (from keepalive, in this case) + to make sure things don't stay in the node cache forever. By marking nodes + during the first run and deleting marked nodes during a next run, every + node should be available in the cache for at least a minute (assuming the + function is indeed called every minute). */ void jabber_cache_clean( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; -- cgit v1.2.3 From 6a1128d1333cf79f1ef9fb1f55b1b8fec67caf2a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 9 Oct 2006 20:19:05 +0200 Subject: The module now keeps track of all resources available for a buddy. This means the buddy won't show up offline when one resource goes down (while there are still others available). It also remembers away state information for every separate resource. Later this system will be used to keep track of client capability information (Typing notices, yay...) and who knows what else. --- protocols/jabber/jabber_util.c | 132 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index f26b9617..f4cd40d4 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -201,3 +201,135 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } + +/* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a + FULL jid or if we already have this buddy/resource. */ +struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *new, *bi; + char *s; + + if( !( s = strchr( full_jid, '/' ) ) ) + return NULL; + + new = g_new0( struct jabber_buddy, 1 ); + + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) + { + new->handle = bud->handle; + + /* We already have another resource for this buddy, add the + new one to the list. */ + for( bi = bud; bi; bi = bi->next ) + { + /* Check for dupes. Resource seem to be case sensitive. */ + if( strcmp( bi->resource, s + 1 ) == 0 ) + { + *s = '/'; + g_free( new ); + return NULL; + } + /* Append the new item to the list. */ + else if( bi->next == NULL ) + { + bi->next = new; + break; + } + } + } + else + { + new->handle = g_strdup( full_jid ); + g_hash_table_insert( jd->buddies, new->handle, new ); + } + + *s = '/'; + new->resource = g_strdup( s + 1 ); + + return new; +} + +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud; + char *s; + + if( ( s = strchr( jid, '/' ) ) ) + { + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) + for( ; bud; bud = bud->next ) + if( strcmp( bud->resource, s + 1 ) == 0 ) + break; + } + else + { + /* TODO: Add selection. */ + return g_hash_table_lookup( jd->buddies, jid ); + } + + *s = '/'; + return bud; +} + +int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *prev, *bi; + char *s; + + if( !( s = strchr( full_jid, '/' ) ) ) + return 0; + + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) + { + /* If there's only one item in the list (and if the resource + matches), removing it is simple. (And the hash reference + should be removed too!) */ + if( bud->next == NULL && strcmp( bud->resource, s + 1 ) == 0 ) + { + g_hash_table_remove( jd->buddies, bud->handle ); + g_free( bud->handle ); + g_free( bud->resource ); + g_free( bud->away_message ); + g_free( bud ); + } + else + { + for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) + if( strcmp( bi->resource, s + 1 ) == 0 ) + break; + + if( bi ) + { + if( prev ) + prev->next = bi->next; + else + /* The hash table should point at the second + item, because we're removing the first. */ + g_hash_table_replace( jd->buddies, bi->handle, bi->next ); + + g_free( bi->resource ); + g_free( bi->away_message ); + g_free( bi ); + } + else + { + *s = '/'; + return 0; + } + } + + *s = '/'; + return 1; + } + else + { + *s = '/'; + return 0; + } +} -- cgit v1.2.3 From a21a8ac4fbd5a234bc8d31d9d487c74a81383c8a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 10 Oct 2006 14:05:42 +0200 Subject: Added resource selection (based on priority or time of last message) to budd_by_jid(), added a full_jid property to easily address that resource without having to rebuild the full JID every time and implemented typing notification shite. --- protocols/jabber/jabber_util.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index f4cd40d4..357743d3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -246,7 +246,8 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji } *s = '/'; - new->resource = g_strdup( s + 1 ); + new->full_jid = g_strdup( full_jid ); + new->resource = strchr( new->full_jid, '/' ) + 1; return new; } @@ -267,8 +268,24 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid } else { - /* TODO: Add selection. */ - return g_hash_table_lookup( jd->buddies, jid ); + struct jabber_buddy *best_prio, *best_time; + char *set; + + best_prio = best_time = bud = g_hash_table_lookup( jd->buddies, jid ); + for( ; bud; bud = bud->next ) + { + if( bud->priority > best_prio->priority ) + best_prio = bud; + if( bud->last_act > best_time->last_act ) + best_time = bud; + } + + if( ( set = set_getstr( &gc->acc->set, "resource_select" ) ) == NULL ) + return NULL; + else if( strcmp( set, "activity" ) == 0 ) + return best_time; + else /* if( strcmp( set, "priority" ) == 0 ) */ + return best_prio; } *s = '/'; @@ -294,7 +311,7 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) { g_hash_table_remove( jd->buddies, bud->handle ); g_free( bud->handle ); - g_free( bud->resource ); + g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); } @@ -313,7 +330,7 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) item, because we're removing the first. */ g_hash_table_replace( jd->buddies, bi->handle, bi->next ); - g_free( bi->resource ); + g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); } -- cgit v1.2.3 From 259edd40f5e332791a44f7547346bf799f1f7327 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 12 Oct 2006 19:48:58 +0200 Subject: Special message when the XMPP session is ended because of a concurrent login, and now sending proper error responses to IQ packets we can't handle. --- protocols/jabber/jabber_util.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 357743d3..d9a89951 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -78,7 +78,37 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ return node; } -/* Cache a node/packet for later use. Mainly useful for IQ packets if you need +struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ) +{ + struct xt_node *node, *c; + char *to; + + /* Create the "defined-condition" tag. */ + c = xt_new_node( err_cond, NULL, NULL ); + xt_add_attr( c, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); + + /* Put it in an tag. */ + c = xt_new_node( "error", NULL, c ); + xt_add_attr( c, "type", err_type ); + + /* To make the actual error packet, we copy the original packet and + add our /type="error" tag. Including the original packet + is recommended, so let's just do it. */ + node = xt_dup( orig ); + xt_add_child( node, c ); + xt_add_attr( node, "type", "error" ); + + /* Return to sender. */ + if( ( to = xt_find_attr( node, "from" ) ) ) + { + xt_add_attr( node, "to", to ); + xt_remove_attr( node, "from" ); + } + + return node; +} + +/* Cache a node/epacket for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) -- cgit v1.2.3 From 788a1afa9628aeaf9d69fc53f49131a4330253cf Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Oct 2006 22:24:01 +0200 Subject: Proper cleanup of jabber buddy structures when removing a buddy from the list, proper checking (and handling) of events related to buddies that aren't "hashed" yet, limit checks on priorityto setting, renamed JEP85 to XEP85, support for more XEP85 states. --- protocols/jabber/jabber_util.c | 57 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 5 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index d9a89951..d5d038cf 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -28,13 +28,20 @@ static int next_id = 1; char *set_eval_priority( set_t *set, char *value ) { account_t *acc = set->data; - char *ret; + int i; - ret = set_eval_int( set, value ); + if( sscanf( value, "%d", &i ) == 1 ) + { + /* Priority is a signed 8-bit integer, according to RFC 3921. */ + if( i < -128 || i > 127 ) + return NULL; + } + else + return NULL; /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ - if( acc->gc && ret ) + if( acc->gc ) { /* Although set_eval functions usually are very nice and convenient, they have one disadvantage: If I would just @@ -46,14 +53,14 @@ char *set_eval_priority( set_t *set, char *value ) functions next to evals, or just do this little hack: */ g_free( set->value ); - set->value = g_strdup( ret ); + set->value = g_strdup( value ); /* (Yes, sorry, I prefer the hack. :-P) */ presence_send_update( acc->gc ); } - return ret; + return value; } char *set_eval_tls( set_t *set, char *value ) @@ -282,6 +289,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji return new; } +/* Finds a buddy from our structures. Can find both full- and bare JIDs. When + asked for a bare JID, it uses the "resource_select" setting to see which + resource to pick. */ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) { struct jabber_data *jd = gc->proto_data; @@ -322,6 +332,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid return bud; } +/* Remove one specific full JID from our list. Use this when a buddy goes + off-line (because (s)he can still be online from a different location. */ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) { struct jabber_data *jd = gc->proto_data; @@ -380,3 +392,38 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) return 0; } } + +/* Remove a buddy completely; removes all resources that belong to the + specified bare JID. Use this when removing someone from the contact + list, for example. */ +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *next; + + if( strchr( bare_jid, '/' ) ) + return 0; + + if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) + { + /* Most important: Remove the hash reference. We don't know + this buddy anymore. */ + g_hash_table_remove( jd->buddies, bud->handle ); + + /* Deallocate the linked list of resources. */ + while( bud ) + { + next = bud->next; + g_free( bud->full_jid ); + g_free( bud->away_message ); + g_free( bud ); + bud = next; + } + + return 1; + } + else + { + return 0; + } +} -- cgit v1.2.3 From dfa41a405f0c80549f6dd5c0c111e3b62ce83b07 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 20 Oct 2006 21:12:14 +0200 Subject: Now all IQ packets get an ID and cached packets get a "special" ID. This makes it easier to find out if an event handler has to be called for a reply packet. --- protocols/jabber/jabber_util.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index d5d038cf..3f189300 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -23,7 +23,7 @@ #include "jabber.h" -static int next_id = 1; +static unsigned int next_id = 1; char *set_eval_priority( set_t *set, char *value ) { @@ -82,6 +82,17 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ if( to ) xt_add_attr( node, "to", to ); + /* IQ packets should always have an ID, so let's generate one. It + might get overwritten by jabber_cache_add() if this packet has + to be saved until we receive a response. Cached packets get + slightly different IDs so we can recognize them. */ + if( strcmp( name, "iq" ) == 0 ) + { + char *id = g_strdup_printf( "%s%05x", JABBER_PACKET_ID, ( next_id++ ) & 0xfffff ); + xt_add_attr( node, "id", id ); + g_free( id ); + } + return node; } @@ -115,13 +126,13 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, return node; } -/* Cache a node/epacket for later use. Mainly useful for IQ packets if you need +/* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so - it'll get an id= tag, and do NOT free() the packet after writing it! */ + it'll get a new id= tag, and do NOT free() the packet after writing it! */ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = gc->proto_data; - char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); xt_add_attr( node, "id", id ); -- cgit v1.2.3 From 47d3ac46306965e9db66096eef8c60c8e7985950 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 31 Oct 2006 09:25:41 +0100 Subject: Added #defines for XML namespaces. --- protocols/jabber/jabber_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3f189300..07d7a2fd 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -103,7 +103,7 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Create the "defined-condition" tag. */ c = xt_new_node( err_cond, NULL, NULL ); - xt_add_attr( c, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); + xt_add_attr( c, "xmlns", XMLNS_STANZA_ERROR ); /* Put it in an tag. */ c = xt_new_node( "error", NULL, c ); -- cgit v1.2.3 From 0d3f30f5449cf1730c006314f3dd60843e911ad1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 13 Nov 2006 00:06:08 +0100 Subject: Improved handling of JIDs: Bare JIDs are allowed (*sigh*) and case insensitivity. Probably not complete yet... --- protocols/jabber/jabber_util.c | 168 ++++++++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 42 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 07d7a2fd..7b1961e0 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -250,33 +250,63 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) g_free( buf ); } +/* Returns a new string. Don't leak it! */ +char *jabber_normalize( char *orig ) +{ + int len, i; + char *new; + + len = strlen( orig ); + new = g_new( char, len + 1 ); + for( i = 0; i < len; i ++ ) + new[i] = tolower( orig[i] ); + + new[i] = 0; + return new; +} + /* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a - FULL jid or if we already have this buddy/resource. */ -struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ) + FULL jid or if we already have this buddy/resource. XXX: No, great, actually + buddies from transports don't (usually) have resources. So we'll really have + to deal with that properly. Set their ->resource property to NULL. Do *NOT* + allow to mix this stuff, though... */ +struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *new, *bi; - char *s; + char *s, *full_jid; - if( !( s = strchr( full_jid, '/' ) ) ) - return NULL; + full_jid = jabber_normalize( full_jid_ ); + + if( ( s = strchr( full_jid, '/' ) ) ) + *s = 0; new = g_new0( struct jabber_buddy, 1 ); - *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { - new->handle = bud->handle; + /* If this is a transport buddy or whatever, it can't have more + than one instance, so this is always wrong: */ + if( s == NULL || bud->resource == NULL ) + { + if( s ) *s = '/'; + g_free( new ); + g_free( full_jid ); + return NULL; + } + + new->bare_jid = bud->bare_jid; /* We already have another resource for this buddy, add the new one to the list. */ for( bi = bud; bi; bi = bi->next ) { - /* Check for dupes. Resource seem to be case sensitive. */ - if( strcmp( bi->resource, s + 1 ) == 0 ) + /* Check for dupes. */ + if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) { *s = '/'; g_free( new ); + g_free( full_jid ); return NULL; } /* Append the new item to the list. */ @@ -289,13 +319,22 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji } else { - new->handle = g_strdup( full_jid ); - g_hash_table_insert( jd->buddies, new->handle, new ); + new->bare_jid = g_strdup( full_jid ); + g_hash_table_insert( jd->buddies, new->bare_jid, new ); } - *s = '/'; - new->full_jid = g_strdup( full_jid ); - new->resource = strchr( new->full_jid, '/' ) + 1; + if( s ) + { + *s = '/'; + new->full_jid = full_jid; + new->resource = strchr( new->full_jid, '/' ) + 1; + } + else + { + /* Let's waste some more bytes of RAM instead of to make + memory management a total disaster here.. */ + new->full_jid = full_jid; + } return new; } @@ -303,26 +342,56 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji /* Finds a buddy from our structures. Can find both full- and bare JIDs. When asked for a bare JID, it uses the "resource_select" setting to see which resource to pick. */ -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud; - char *s; + char *s, *jid; + + jid = jabber_normalize( jid_ ); if( ( s = strchr( jid, '/' ) ) ) { *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) - for( ; bud; bud = bud->next ) - if( strcmp( bud->resource, s + 1 ) == 0 ) - break; + { + /* Is this one of those no-resource buddies? */ + if( bud->resource == NULL ) + { + bud = NULL; + } + else + { + /* See if there's an exact match. */ + for( ; bud; bud = bud->next ) + if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) + break; + } + } + + *s = '/'; + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) ) + bud = jabber_buddy_add( gc, jid ); + + g_free( jid ); + return bud; } else { struct jabber_buddy *best_prio, *best_time; char *set; - best_prio = best_time = bud = g_hash_table_lookup( jd->buddies, jid ); + bud = g_hash_table_lookup( jd->buddies, jid ); + + g_free( jid ); + + /* An exact match, or only one option. */ + if( bud == NULL ) + return ( flags & GET_BUDDY_CREAT ) ? jabber_buddy_add( gc, jid ) : NULL; + else if( ( bud->resource == NULL || bud->next == NULL ) ) + return bud; + + best_prio = best_time = bud; for( ; bud; bud = bud->next ) { if( bud->priority > best_prio->priority ) @@ -338,42 +407,54 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid else /* if( strcmp( set, "priority" ) == 0 ) */ return best_prio; } - - *s = '/'; - return bud; } /* Remove one specific full JID from our list. Use this when a buddy goes - off-line (because (s)he can still be online from a different location. */ -int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) + off-line (because (s)he can still be online from a different location. + XXX: See above, we should accept bare JIDs too... */ +int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *prev, *bi; - char *s; + char *s, *full_jid; - if( !( s = strchr( full_jid, '/' ) ) ) - return 0; + full_jid = jabber_normalize( full_jid_ ); + + if( ( s = strchr( full_jid, '/' ) ) ) + *s = 0; - *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { /* If there's only one item in the list (and if the resource matches), removing it is simple. (And the hash reference should be removed too!) */ - if( bud->next == NULL && strcmp( bud->resource, s + 1 ) == 0 ) + if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) ) { - g_hash_table_remove( jd->buddies, bud->handle ); - g_free( bud->handle ); + g_hash_table_remove( jd->buddies, bud->bare_jid ); + g_free( bud->bare_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); + + g_free( full_jid ); + + return 1; + } + else if( s == NULL || bud->resource == NULL ) + { + /* Tried to remove a bare JID while this JID does seem + to have resources... (Or the opposite.) *sigh* */ + g_free( full_jid ); + return 0; } else { for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) - if( strcmp( bi->resource, s + 1 ) == 0 ) + if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) break; + g_free( full_jid ); + if( bi ) { if( prev ) @@ -381,25 +462,23 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) else /* The hash table should point at the second item, because we're removing the first. */ - g_hash_table_replace( jd->buddies, bi->handle, bi->next ); + g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); + + return 1; } else { - *s = '/'; return 0; } } - - *s = '/'; - return 1; } else { - *s = '/'; + g_free( full_jid ); return 0; } } @@ -407,19 +486,22 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *next; + char *bare_jid; - if( strchr( bare_jid, '/' ) ) + if( strchr( bare_jid_, '/' ) ) return 0; + bare_jid = jabber_normalize( bare_jid_ ); + if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) { /* Most important: Remove the hash reference. We don't know this buddy anymore. */ - g_hash_table_remove( jd->buddies, bud->handle ); + g_hash_table_remove( jd->buddies, bud->bare_jid ); /* Deallocate the linked list of resources. */ while( bud ) @@ -431,10 +513,12 @@ int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) bud = next; } + g_free( bare_jid ); return 1; } else { + g_free( bare_jid ); return 0; } } -- cgit v1.2.3 From 16b5f86a2cf909628d5b90aa5d36aaac8f869a78 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 13 Nov 2006 11:38:23 +0100 Subject: Added handling of GET_BUDDY_* flags. --- protocols/jabber/jabber_util.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 7b1961e0..5184a37e 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -358,7 +358,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ /* Is this one of those no-resource buddies? */ if( bud->resource == NULL ) { - bud = NULL; + g_free( jid ); + return NULL; } else { @@ -369,9 +370,11 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ } } - *s = '/'; - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) + { + *s = '/'; bud = jabber_buddy_add( gc, jid ); + } g_free( jid ); return bud; @@ -385,10 +388,15 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ g_free( jid ); - /* An exact match, or only one option. */ if( bud == NULL ) - return ( flags & GET_BUDDY_CREAT ) ? jabber_buddy_add( gc, jid ) : NULL; + /* No match. Create it now? */ + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) ? + jabber_buddy_add( gc, jid ) : NULL; + else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) + /* We want an exact match, so in thise case there shouldn't be a /resource. */ + return NULL; else if( ( bud->resource == NULL || bud->next == NULL ) ) + /* No need for selection if there's only one option. */ return bud; best_prio = best_time = bud; -- cgit v1.2.3 From cb6a6f437f4fb1be3f35b61f2c26e78ecacaedde Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 3 Dec 2006 18:57:17 +0100 Subject: Fixed use of already free()d variable. --- protocols/jabber/jabber_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 5184a37e..4ca0c1fc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -390,8 +390,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) ? - jabber_buddy_add( gc, jid ) : NULL; + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid_ ) ) ? + jabber_buddy_add( gc, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ return NULL; -- cgit v1.2.3 From 0da65d5fb37691ed4d31f7ab4058732f1440db6b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 30 Mar 2007 22:40:45 -0700 Subject: s/gaim_connection/im_connection/ and some other minor API changes. The rest will come tomorrow. It compiles, I'll leave the real testing up to someone else. ;-) --- protocols/jabber/jabber_util.c | 54 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 4ca0c1fc..cc237b03 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -41,7 +41,7 @@ char *set_eval_priority( set_t *set, char *value ) /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ - if( acc->gc ) + if( acc->ic ) { /* Although set_eval functions usually are very nice and convenient, they have one disadvantage: If I would just @@ -57,7 +57,7 @@ char *set_eval_priority( set_t *set, char *value ) /* (Yes, sorry, I prefer the hack. :-P) */ - presence_send_update( acc->gc ); + presence_send_update( acc->ic ); } return value; @@ -129,9 +129,9 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get a new id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) +void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); @@ -158,9 +158,9 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpo during the first run and deleting marked nodes during a next run, every node should be available in the cache for at least a minute (assuming the function is indeed called every minute). */ -void jabber_cache_clean( struct gaim_connection *gc ) +void jabber_cache_clean( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); } @@ -213,17 +213,17 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name ) struct jabber_buddy_ask_data { - struct gaim_connection *gc; + struct im_connection *ic; char *handle; char *realname; }; static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) { - presence_send_request( bla->gc, bla->handle, "subscribed" ); + presence_send_request( bla->ic, bla->handle, "subscribed" ); - if( find_buddy( bla->gc, bla->handle ) == NULL ) - show_got_added( bla->gc, bla->handle, NULL ); + if( find_buddy( bla->ic, bla->handle ) == NULL ) + show_got_added( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla ); @@ -231,22 +231,22 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) { - presence_send_request( bla->gc, bla->handle, "subscribed" ); + presence_send_request( bla->ic, bla->handle, "subscribed" ); g_free( bla->handle ); g_free( bla ); } -void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) +void jabber_buddy_ask( struct im_connection *ic, char *handle ) { struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 ); char *buf; - bla->gc = gc; + bla->ic = ic; bla->handle = g_strdup( handle ); buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); - do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + do_ask_dialog( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } @@ -270,9 +270,9 @@ char *jabber_normalize( char *orig ) buddies from transports don't (usually) have resources. So we'll really have to deal with that properly. Set their ->resource property to NULL. Do *NOT* allow to mix this stuff, though... */ -struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ ) +struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *new, *bi; char *s, *full_jid; @@ -342,9 +342,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji /* Finds a buddy from our structures. Can find both full- and bare JIDs. When asked for a bare JID, it uses the "resource_select" setting to see which resource to pick. */ -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags ) +struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; char *s, *jid; @@ -370,10 +370,10 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ } } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid ) ) { *s = '/'; - bud = jabber_buddy_add( gc, jid ); + bud = jabber_buddy_add( ic, jid ); } g_free( jid ); @@ -390,8 +390,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid_ ) ) ? - jabber_buddy_add( gc, jid_ ) : NULL; + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid_ ) ) ? + jabber_buddy_add( ic, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ return NULL; @@ -408,7 +408,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ best_time = bud; } - if( ( set = set_getstr( &gc->acc->set, "resource_select" ) ) == NULL ) + if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL ) return NULL; else if( strcmp( set, "activity" ) == 0 ) return best_time; @@ -420,9 +420,9 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ /* Remove one specific full JID from our list. Use this when a buddy goes off-line (because (s)he can still be online from a different location. XXX: See above, we should accept bare JIDs too... */ -int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) +int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *prev, *bi; char *s, *full_jid; @@ -494,9 +494,9 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ ) +int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *next; char *bare_jid; -- cgit v1.2.3 From 84b045d409f1e8da6d8bf379c6fef7236dcd9bcd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 15 Apr 2007 18:03:08 -0700 Subject: s/imc/imcb/ for callback functions. Moved things aroundin nogaim.h a little bit, grouping things by category instead of original Gaim 0.58 filename. --- protocols/jabber/jabber_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index cc237b03..949a7a4b 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -223,7 +223,7 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla presence_send_request( bla->ic, bla->handle, "subscribed" ); if( find_buddy( bla->ic, bla->handle ) == NULL ) - show_got_added( bla->ic, bla->handle, NULL ); + imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla ); @@ -246,7 +246,7 @@ void jabber_buddy_ask( struct im_connection *ic, char *handle ) bla->handle = g_strdup( handle ); buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); - do_ask_dialog( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + imcb_ask( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } -- cgit v1.2.3 From f0cb961652cbd639e89dcd88a86f20a2414146c4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 18 Apr 2007 23:03:43 -0700 Subject: More API changes: buddy list management. imcb_add_buddy() is now a *real* callback, it's only called from inside IM-modules. This makes sure a buddy only gets added to the BitlBee structures if the add was successful. This gets rid of the weirdness described in #55. Unfortunately for now this change breaks A) automatic renaming of ICQ contacts (if there are names stored in the contact list) B) add -tmp. --- protocols/jabber/jabber_util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 949a7a4b..3c0e71f4 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -222,7 +222,7 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla { presence_send_request( bla->ic, bla->handle, "subscribed" ); - if( find_buddy( bla->ic, bla->handle ) == NULL ) + if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); @@ -370,7 +370,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, } } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) ) { *s = '/'; bud = jabber_buddy_add( ic, jid ); @@ -390,7 +390,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid_ ) ) ? + return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? jabber_buddy_add( ic, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ -- cgit v1.2.3 From e35d1a121d5fb2da3698fbe4a365fe38d0097665 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 22 Apr 2007 13:44:27 -0700 Subject: Read-only support for Jabber conferences (non-anonymous rooms only). Just don't use this, you're really not going to like it. :-) --- protocols/jabber/jabber_util.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3c0e71f4..86ddf7bc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -47,7 +47,7 @@ char *set_eval_priority( set_t *set, char *value ) convenient, they have one disadvantage: If I would just call p_s_u() now to send the new prio setting, it would send the old setting because the set->value gets changed - when the eval returns a non-NULL value. + after the (this) eval returns a non-NULL value. So now I can choose between implementing post-set functions next to evals, or just do this little hack: */ @@ -128,7 +128,7 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so - it'll get a new id= tag, and do NOT free() the packet after writing it! */ + it'll get a new id= tag, and do NOT free() the packet after sending it! */ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = ic->proto_data; @@ -251,7 +251,7 @@ void jabber_buddy_ask( struct im_connection *ic, char *handle ) } /* Returns a new string. Don't leak it! */ -char *jabber_normalize( char *orig ) +char *jabber_normalize( const char *orig ) { int len, i; char *new; @@ -352,6 +352,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, if( ( s = strchr( jid, '/' ) ) ) { + int none_found = 0; + *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) { @@ -369,8 +371,16 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, break; } } + else + { + /* This hack is there to make sure that O_CREAT will + work if there's already another resouce present + for this JID, even if it's an unknown buddy. This + is done to handle conferences properly. */ + none_found = 1; + } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) { *s = '/'; bud = jabber_buddy_add( ic, jid ); @@ -530,3 +540,20 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) return 0; } } + +struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ) +{ + char *normalized = jabber_normalize( name ); + struct groupchat *ret; + struct jabber_chat *jc; + + for( ret = ic->groupchats; ret; ret = ret->next ) + { + jc = ret->data; + if( strcmp( normalized, jc->name ) == 0 ) + break; + } + g_free( normalized ); + + return ret; +} -- cgit v1.2.3 From 43671b964b636520a54e343542c5958b30e9f589 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 22 Apr 2007 16:39:37 -0700 Subject: You can send messages too now. But it's still very kludgy and doesn't work with anonymous rooms (ie about 95% of all available Jabber chatrooms?). --- protocols/jabber/jabber_util.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 86ddf7bc..091e6c7d 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -557,3 +557,52 @@ struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *nam return ret; } + +time_t jabber_get_timestamp( struct xt_node *xt ) +{ + struct tm tp, utc; + struct xt_node *c; + time_t res, tres; + char *s = NULL; + + for( c = xt->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) + { + if( ( s = xt_find_attr( c, "xmlns" ) ) && strcmp( s, XMLNS_DELAY ) == 0 ) + break; + } + + if( !c || !( s = xt_find_attr( c, "stamp" ) ) ) + return 0; + + memset( &tp, 0, sizeof( tp ) ); + if( sscanf( s, "%4d%2d%2dT%2d:%2d:%2d", &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) != 6 ) + return 0; + + tp.tm_year -= 1900; + tp.tm_mon --; + tp.tm_isdst = -1; /* GRRRRRRRRRRR */ + + res = mktime( &tp ); + /* Problem is, mktime() just gave us the GMT timestamp for the + given local time... While the given time WAS NOT local. So + we should fix this now. + + Now I could choose between messing with environment variables + (kludgy) or using timegm() (not portable)... Or doing the + following, which I actually prefer... */ + gmtime_r( &res, &utc ); + utc.tm_isdst = -1; /* Once more: GRRRRRRRRRRRRRRRRRR!!! */ + if( utc.tm_hour == tp.tm_hour && utc.tm_min == tp.tm_min ) + /* Sweet! We're in UTC right now... */ + return res; + + tres = mktime( &utc ); + res += res - tres; + + /* Yes, this is a hack. And it will go wrong around DST changes. + BUT this is more likely to be threadsafe than messing with + environment variables, and possibly more portable... */ + + return res; +} -- cgit v1.2.3 From 6286f80d6dc1dc4cb8106b4e209a8578d7cebe56 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 25 Apr 2007 21:41:34 -0700 Subject: Prepared the Jabber module for anonymous rooms, but the BitlBee core doesn't deal with it very well, and I don't really know yet how I'll solve this... :-( --- protocols/jabber/jabber_util.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 091e6c7d..4dae3287 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -450,6 +450,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) { g_hash_table_remove( jd->buddies, bud->bare_jid ); g_free( bud->bare_jid ); + g_free( bud->ext_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); @@ -482,6 +483,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) item, because we're removing the first. */ g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); + g_free( bi->ext_jid ); g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); @@ -525,6 +527,7 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) while( bud ) { next = bud->next; + g_free( bud->ext_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); -- cgit v1.2.3 From b9f8b870f7b884747b747be91ce0ac797a7c6e82 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 1 Jul 2007 17:29:21 +0100 Subject: Better handling of private messages via groupchats. --- protocols/jabber/jabber_util.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 4dae3287..53f97ff0 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -319,6 +319,8 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ } else { + /* Keep in mind that full_jid currently isn't really + a full JID... */ new->bare_jid = g_strdup( full_jid ); g_hash_table_insert( jd->buddies, new->bare_jid, new ); } @@ -332,7 +334,8 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ else { /* Let's waste some more bytes of RAM instead of to make - memory management a total disaster here.. */ + memory management a total disaster here. And it saves + me one g_free() call in this function. :-P */ new->full_jid = full_jid; } @@ -427,6 +430,38 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, } } +/* I'm keeping a separate ext_jid attribute to save a JID that makes sense + to export to BitlBee. This is mainly for groupchats right now. It's + a bit of a hack, but I just think having the user nickname in the hostname + part of the hostmask doesn't look nice on IRC. Normally you can convert + a normal JID to ext_jid by swapping the part before and after the / and + replacing the / with a =. But there should be some stripping (@s are + allowed in Jabber nicks...). */ +struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) +{ + struct jabber_buddy *bud; + char *s, *jid; + + jid = jabber_normalize( jid_ ); + + if( ( s = strchr( jid, '=' ) ) == NULL ) + return NULL; + + for( bud = jabber_buddy_by_jid( ic, s + 1, GET_BUDDY_FIRST ); bud; bud = bud->next ) + { + /* Hmmm, could happen if not all people in the chat are anonymized? */ + if( bud->ext_jid == NULL ) + continue; + + if( strcmp( bud->ext_jid, jid ) == 0 ) + break; + } + + g_free( jid ); + + return bud; +} + /* Remove one specific full JID from our list. Use this when a buddy goes off-line (because (s)he can still be online from a different location. XXX: See above, we should accept bare JIDs too... */ -- cgit v1.2.3 From 9da0bbfd42609f0f3864b5a16a3c1c378b7217c9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 2 Jul 2007 23:12:03 +0100 Subject: Added (and using) jabber_chat_free() for better memory management, fixed channel name generation code in root_commands.c and fixed one memory leak in jabber_buddy_remove_bare(). --- protocols/jabber/jabber_util.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 53f97ff0..5b91c5ed 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -541,26 +541,31 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) +int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *next; - char *bare_jid; - if( strchr( bare_jid_, '/' ) ) + if( strchr( bare_jid, '/' ) ) return 0; - bare_jid = jabber_normalize( bare_jid_ ); - - if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) + if( ( bud = jabber_buddy_by_jid( ic, bare_jid, GET_BUDDY_FIRST ) ) ) { /* Most important: Remove the hash reference. We don't know this buddy anymore. */ g_hash_table_remove( jd->buddies, bud->bare_jid ); + g_free( bud->bare_jid ); /* Deallocate the linked list of resources. */ while( bud ) { + /* ext_jid && anonymous means that this buddy is + specific to one groupchat (the one we're + currently cleaning up) so it can be deleted + completely. */ + if( bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS ) + imcb_remove_buddy( ic, bud->ext_jid, NULL ); + next = bud->next; g_free( bud->ext_jid ); g_free( bud->full_jid ); @@ -569,12 +574,10 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) bud = next; } - g_free( bare_jid ); return 1; } else { - g_free( bare_jid ); return 0; } } -- cgit v1.2.3 From 1baaef858136cd3a4799b3ccf1d9961534e0017c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 30 Jul 2007 20:12:06 +0100 Subject: Added jabber_error_parse() and using it for both stream- and stanza (only presence so far) errors. --- protocols/jabber/jabber_util.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 5b91c5ed..56491c4f 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -647,3 +647,38 @@ time_t jabber_get_timestamp( struct xt_node *xt ) return res; } + +struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ) +{ + struct jabber_error *err = g_new0( struct jabber_error, 1 ); + struct xt_node *c; + char *s; + + err->type = xt_find_attr( node, "type" ); + + for( c = node->children; c; c = c->next ) + { + if( !( s = xt_find_attr( c, "xmlns" ) ) || + strcmp( s, xmlns ) != 0 ) + continue; + + if( strcmp( c->name, "text" ) != 0 ) + { + err->code = c->name; + } + /* Only use the text if it doesn't have an xml:lang attribute, + if it's empty or if it's set to something English. */ + else if( !( s = xt_find_attr( c, "xml:lang" ) ) || + !*s || strncmp( s, "en", 2 ) == 0 ) + { + err->text = c->text; + } + } + + return err; +} + +void jabber_error_free( struct jabber_error *err ) +{ + g_free( err ); +} -- cgit v1.2.3 From 608f8cf652d0c443ef551ac979bd46096b361663 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 24 Nov 2007 18:02:39 +0000 Subject: Added some random hash to the id= for cached XMPP packets so that packets from other BitlBees won't be picked up accidentally. Might also want to randomize the per-packet IDs because they're still predictable. --- protocols/jabber/jabber_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 56491c4f..43b91fe3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -132,9 +132,10 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = ic->proto_data; - char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); + char *id; + id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff ); xt_add_attr( node, "id", id ); g_free( id ); -- cgit v1.2.3 From 4306d8b066d335cb6667414bdd6c5b2e78ccbfd5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Dec 2007 16:43:57 +0000 Subject: Removed retarded printf() (ARGH) and moved the event handling handling of IQ packets to jabber_util so I can reuse it for certain presence packets. --- protocols/jabber/jabber_util.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 43b91fe3..453e5930 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -180,6 +180,36 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullp } } +xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ) +{ + struct jabber_data *jd = ic->proto_data; + struct jabber_cache_entry *entry; + char *s; + + if( ( s = xt_find_attr( node, "id" ) ) == NULL || + strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 ) + { + /* Silently ignore it, without an ID (or a non-cache + ID) we don't know how to handle the packet and we + probably don't have to. */ + return XT_HANDLED; + } + + entry = g_hash_table_lookup( jd->node_cache, s ); + + if( entry == NULL ) + { + 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 ) + { + return entry->func( ic, node, entry->node ); + } + + return XT_HANDLED; +} + const struct jabber_away_state jabber_away_state_list[] = { { "away", "Away" }, -- cgit v1.2.3 From 5bd21df87b195af211c2280ca00391493a669895 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Dec 2007 17:25:57 +0000 Subject: Handling of presence-error packets (only useful for groupchats now), moved jabber_chat_by_jid() (with the right name) to conference.c, I don't know what it was doing in jabber_util.c. --- protocols/jabber/jabber_util.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'protocols/jabber/jabber_util.c') diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 453e5930..9d84e099 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -613,23 +613,6 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ) } } -struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ) -{ - char *normalized = jabber_normalize( name ); - struct groupchat *ret; - struct jabber_chat *jc; - - for( ret = ic->groupchats; ret; ret = ret->next ) - { - jc = ret->data; - if( strcmp( normalized, jc->name ) == 0 ) - break; - } - g_free( normalized ); - - return ret; -} - time_t jabber_get_timestamp( struct xt_node *xt ) { struct tm tp, utc; @@ -681,10 +664,14 @@ time_t jabber_get_timestamp( struct xt_node *xt ) struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ) { - struct jabber_error *err = g_new0( struct jabber_error, 1 ); + struct jabber_error *err; struct xt_node *c; char *s; + if( node == NULL ) + return NULL; + + err = g_new0( struct jabber_error, 1 ); err->type = xt_find_attr( node, "type" ); for( c = node->children; c; c = c->next ) -- 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/jabber_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols/jabber/jabber_util.c') 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 ) -- 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/jabber_util.c') 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 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_util.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'protocols/jabber/jabber_util.c') 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