Mercurial > pidgin
diff libpurple/protocols/jabber/data.c @ 29633:1bde873d1b94
jabber: Cache incoming BoB object per JID (and local JID) instead of discarding
them when receiving an invalid or unrecognised hash. As per the MUC discussions.
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Tue, 23 Mar 2010 22:17:34 +0000 |
parents | 9f59abd49def |
children | 84ec9e3cbb6d 38926d6e5ae1 |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/data.c Mon Mar 22 22:23:35 2010 +0000 +++ b/libpurple/protocols/jabber/data.c Tue Mar 23 22:17:34 2010 +0000 @@ -54,58 +54,6 @@ return data; } - -static gboolean -jabber_data_has_valid_hash(const JabberData *data) -{ - const gchar *cid = jabber_data_get_cid(data); - gchar **cid_parts = g_strsplit(cid, "@", -1); - gchar **iter; - int num_parts = 0; - - purple_debug_info("jabber", "validating BoB hash %s\n", cid); - - for (iter = cid_parts; *iter != NULL ; iter++) { - num_parts++; - } - - if (num_parts == 2 && purple_strequal(cid_parts[1], "bob.xmpp.org")) { - gchar **sub_parts = g_strsplit(cid_parts[0], "+", -1); - - num_parts = 0; - for (iter = sub_parts ; *iter != NULL ; iter++) { - num_parts++; - } - - if (num_parts == 2) { - const gchar *hash_algo = sub_parts[0]; - const gchar *hash_value = sub_parts[1]; - gchar *digest = - jabber_calculate_data_hash(jabber_data_get_data(data), - jabber_data_get_size(data), hash_algo); - - purple_debug_info("jabber", "BoB expecting hash: %s\n", digest); - - if (digest) { - gboolean result = purple_strequal(digest, hash_value); - - if (!result) { - purple_debug_error("jabber", "invalid BoB hash\n"); - } - g_free(digest); - return result; - } else { - purple_debug_info("jabber", "unknown BoB hash algo\n"); - return FALSE; - } - } else { - return TRUE; - } - } else { - return TRUE; - } -} - static void jabber_data_delete(gpointer cbdata) { @@ -159,11 +107,6 @@ data->cid = g_strdup(cid); data->type = g_strdup(type); - if (!jabber_data_has_valid_hash(data)) { - jabber_data_delete(data); - return NULL; - } - return data; } @@ -233,6 +176,57 @@ return tag; } +static gboolean +jabber_data_has_valid_hash(const JabberData *data) +{ + const gchar *cid = jabber_data_get_cid(data); + gchar **cid_parts = g_strsplit(cid, "@", -1); + gchar **iter; + int num_parts = 0; + + purple_debug_info("jabber", "validating BoB hash %s\n", cid); + + for (iter = cid_parts; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2 && purple_strequal(cid_parts[1], "bob.xmpp.org")) { + gchar **sub_parts = g_strsplit(cid_parts[0], "+", -1); + + num_parts = 0; + for (iter = sub_parts ; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2) { + const gchar *hash_algo = sub_parts[0]; + const gchar *hash_value = sub_parts[1]; + gchar *digest = + jabber_calculate_data_hash(jabber_data_get_data(data), + jabber_data_get_size(data), hash_algo); + + if (digest) { + gboolean result = purple_strequal(digest, hash_value); + + purple_debug_info("jabber", "BoB expecting hash: %s\n", digest); + + if (!result) { + purple_debug_error("jabber", "invalid BoB hash\n"); + } + g_free(digest); + return result; + } else { + purple_debug_info("jabber", "unknown BoB hash algo\n"); + return FALSE; + } + } else { + return FALSE; + } + } else { + return FALSE; + } +} + typedef struct { gpointer userdata; @@ -258,17 +252,10 @@ if (data_element && type == JABBER_IQ_RESULT) { JabberData *data = jabber_data_create_from_xml(data_element); - if (data) { - if (!ephemeral) { - jabber_data_associate_remote(data); - } - cb(data, alt, userdata); - } else { - /* could not validate hash when creating data from XML */ - purple_debug_info("jabber", - "hash validation failed on requested BoB object\n"); - cb(NULL, alt, userdata); + if (!ephemeral) { + jabber_data_associate_remote(js, from, data); } + cb(data, alt, userdata); } else if (item_not_found) { purple_debug_info("jabber", "Responder didn't recognize requested data\n"); @@ -316,11 +303,23 @@ } const JabberData * -jabber_data_find_remote_by_cid(const gchar *cid) +jabber_data_find_remote_by_cid(JabberStream *js, const gchar *who, + const gchar *cid) { + const JabberData *data = g_hash_table_lookup(remote_data_by_cid, cid); purple_debug_info("jabber", "lookup remote smiley with cid = %s\n", cid); - return g_hash_table_lookup(remote_data_by_cid, cid); + if (data == NULL) { + gchar *jid_cid = + g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain, + js->user->resource, who, cid); + purple_debug_info("jabber", + "didn't find BoB object by pure CID, try including JIDs: %s\n", + jid_cid); + data = g_hash_table_lookup(remote_data_by_cid, jid_cid); + g_free(jid_cid); + } + return data; } void @@ -334,12 +333,21 @@ } void -jabber_data_associate_remote(JabberData *data) +jabber_data_associate_remote(JabberStream *js, const gchar *who, JabberData *data) { - purple_debug_info("jabber", "associating remote smiley, cid = %s\n", - jabber_data_get_cid(data)); - g_hash_table_insert(remote_data_by_cid, g_strdup(jabber_data_get_cid(data)), - data); + gchar *cid; + + if (jabber_data_has_valid_hash(data)) { + cid = g_strdup(jabber_data_get_cid(data)); + } else { + cid = g_strdup_printf("%s@%s/%s%s%s", js->user->node, js->user->domain, + js->user->resource, who, jabber_data_get_cid(data)); + } + + purple_debug_info("jabber", "associating remote BoB object with cid = %s\n", + cid); + + g_hash_table_insert(remote_data_by_cid, cid, data); } void