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