Mercurial > pidgin
changeset 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 | e3eda7aa0653 |
children | f19ee75947c6 |
files | ChangeLog libpurple/protocols/jabber/data.c libpurple/protocols/jabber/data.h libpurple/protocols/jabber/message.c |
diffstat | 4 files changed, 95 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Mar 22 22:23:35 2010 +0000 +++ b/ChangeLog Tue Mar 23 22:17:34 2010 +0000 @@ -55,7 +55,9 @@ rjoly for testing) * When sending data using in-band-bytestreams, interpret the block-size attribute as the size of the BASE64-encoded representation of the data. - * Validate the hash on incoming BoB data objects (for custom smileys etc.). + * Validate the hash on incoming BoB data objects (for custom smileys etc.), + cache based per JID when the CID is not a valid hash (as specified by the + BoB XEP). Yahoo: * Attempt to better handle transparent proxies interfering with HTTP-based
--- 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
--- a/libpurple/protocols/jabber/data.h Mon Mar 22 22:23:35 2010 +0000 +++ b/libpurple/protocols/jabber/data.h Tue Mar 23 22:17:34 2010 +0000 @@ -67,11 +67,13 @@ /* lookup functions */ const JabberData *jabber_data_find_local_by_alt(const gchar *alt); const JabberData *jabber_data_find_local_by_cid(const gchar *cid); -const JabberData *jabber_data_find_remote_by_cid(const gchar *cid); +const JabberData *jabber_data_find_remote_by_cid(JabberStream *js, + const gchar *who, const gchar *cid); /* store data objects */ void jabber_data_associate_local(JabberData *data, const gchar *alt); -void jabber_data_associate_remote(JabberData *data); +void jabber_data_associate_remote(JabberStream *js, const gchar *who, + JabberData *data); /* handles iq requests */ void jabber_data_parse(JabberStream *js, const char *who, JabberIqType type,
--- a/libpurple/protocols/jabber/message.c Mon Mar 22 22:23:35 2010 +0000 +++ b/libpurple/protocols/jabber/message.c Tue Mar 23 22:17:34 2010 +0000 @@ -462,21 +462,22 @@ } static void -jabber_message_add_remote_smileys(const xmlnode *message) +jabber_message_add_remote_smileys(JabberStream *js, const gchar *who, + const xmlnode *message) { xmlnode *data_tag; for (data_tag = xmlnode_get_child_with_namespace(message, "data", NS_BOB) ; data_tag ; data_tag = xmlnode_get_next_twin(data_tag)) { const gchar *cid = xmlnode_get_attrib(data_tag, "cid"); - const JabberData *data = jabber_data_find_remote_by_cid(cid); + const JabberData *data = jabber_data_find_remote_by_cid(js, who, cid); if (!data && cid != NULL) { /* we haven't cached this already, let's add it */ JabberData *new_data = jabber_data_create_from_xml(data_tag); if (new_data) { - jabber_data_associate_remote(new_data); + jabber_data_associate_remote(js, who, new_data); } } } @@ -634,7 +635,7 @@ } /* process any newly provided smileys */ - jabber_message_add_remote_smileys(packet); + jabber_message_add_remote_smileys(js, to, packet); } /* reformat xhtml so that img tags with a "cid:" src gets @@ -660,7 +661,7 @@ if (purple_conv_custom_smiley_add(conv, alt, "cid", cid, TRUE)) { const JabberData *data = - jabber_data_find_remote_by_cid(cid); + jabber_data_find_remote_by_cid(js, from, cid); /* if data is already known, we write it immediatly */ if (data) { purple_debug_info("jabber",