changeset 25817:9195955395b6

Only (re)publish XMPP avatars at login if the server's avatar differs As part of this, no longer rely on the vcard for determining a need to publish the XEP-0084 avatar; explicitly fetch and compare it. Closes #7734. References #7732. That patch needs updating to apply on top of this.
author Paul Aurich <paul@darkrain42.org>
date Wed, 21 Jan 2009 20:16:22 +0000
parents b68ac693ae2d
children 370d8eba2ce0
files libpurple/protocols/jabber/buddy.c libpurple/protocols/jabber/disco.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/useravatar.c libpurple/protocols/jabber/useravatar.h
diffstat 5 files changed, 85 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/buddy.c	Wed Jan 21 17:56:07 2009 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Wed Jan 21 20:16:22 2009 +0000
@@ -472,7 +472,6 @@
 		enc = purple_base64_encode(avatar_data, avatar_len);
 
 		js->avatar_hash = jabber_calculate_data_sha1sum(avatar_data, avatar_len);
-
 		xmlnode_insert_data(binval, enc, -1);
 		g_free(enc);
 	} else if (vc_node) {
@@ -494,7 +493,7 @@
 {
 	PurplePresence *gpresence;
 	PurpleStatus *status;
-	
+
 	jabber_avatar_set(gc->proto_data, img);
 	/* vCard avatars do not have an image type requirement so update our
 	 * vCard avatar regardless of image type for those poor older clients
@@ -1046,9 +1045,9 @@
 
 static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data)
 {
-	xmlnode *vcard;
-	char *txt;
-	PurpleStoredImage *img;
+	xmlnode *vcard, *photo, *binval;
+	char *txt, *vcard_hash = NULL;
+	const char *current_hash;
 
 	if((vcard = xmlnode_get_child(packet, "vCard")) ||
 			(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp")))
@@ -1063,10 +1062,33 @@
 
 	js->vcard_fetched = TRUE;
 
-	if(NULL != (img = purple_buddy_icons_find_account_icon(js->gc->account))) {
-		jabber_set_buddy_icon(js->gc, img);
-		purple_imgstore_unref(img);
+	if (vcard && (photo = xmlnode_get_child(vcard, "PHOTO")) &&
+	             (binval = xmlnode_get_child(photo, "BINVAL"))) {
+		gsize size;
+		char *bintext = xmlnode_get_data(binval);
+		guchar *data = purple_base64_decode(bintext, &size);
+		g_free(bintext);
+
+		if (data) {
+			vcard_hash = jabber_calculate_data_sha1sum(data, size);
+			g_free(data);
+		}
 	}
+
+	current_hash = purple_account_get_string(js->gc->account,
+	                                         "prpl-jabber_icon_checksum", "");
+
+	/* Republish our vcard if the photo is different than the server's */
+	if ((!vcard_hash && current_hash[0] != '\0') ||
+		 (vcard_hash && strcmp(vcard_hash, current_hash))) {
+		PurpleAccount *account = purple_connection_get_account(js->gc);
+		jabber_set_info(js->gc, purple_account_get_user_info(account));
+	} else if (current_hash != '\0') {
+		/* Our photo is in the vcard, so advertise vcard-temp updates */
+		js->avatar_hash = g_strdup(current_hash);
+	}
+
+	g_free(vcard_hash);
 }
 
 void jabber_vcard_fetch_mine(JabberStream *js)
--- a/libpurple/protocols/jabber/disco.c	Wed Jan 21 17:56:07 2009 +0000
+++ b/libpurple/protocols/jabber/disco.c	Wed Jan 21 20:16:22 2009 +0000
@@ -23,16 +23,16 @@
 #include "prefs.h"
 #include "debug.h"
 
+#include "adhoccommands.h"
 #include "buddy.h"
+#include "disco.h"
 #include "google.h"
 #include "iq.h"
-#include "disco.h"
 #include "jabber.h"
+#include "pep.h"
 #include "presence.h"
 #include "roster.h"
-#include "pep.h"
-#include "adhoccommands.h"
-
+#include "useravatar.h"
 
 struct _jabber_disco_info_cb_data {
 	gpointer data;
@@ -341,6 +341,8 @@
 	const char *ft_proxies;
 
 	jabber_vcard_fetch_mine(js);
+	if (js->pep)
+		jabber_avatar_fetch_mine(js);
 
 	if (!(js->server_caps & JABBER_CAP_GOOGLE_ROSTER)) {
 		/* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
--- a/libpurple/protocols/jabber/jabber.c	Wed Jan 21 17:56:07 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Jan 21 20:16:22 2009 +0000
@@ -28,6 +28,7 @@
 #include "conversation.h"
 #include "debug.h"
 #include "dnssrv.h"
+#include "imgstore.h"
 #include "message.h"
 #include "notify.h"
 #include "pluginpref.h"
@@ -701,6 +702,7 @@
 	const char *connect_server = purple_account_get_string(account,
 			"connect_server", "");
 	JabberStream *js;
+	PurpleStoredImage *image;
 	JabberBuddy *my_jb = NULL;
 
 	gc->flags |= PURPLE_CONNECTION_HTML |
@@ -736,7 +738,19 @@
 			_("Invalid XMPP ID. Domain must be set."));
 		return;
 	}
-	
+
+	/* This account setting is used to determine if we should re-sync our avatar to the
+	 * server at login. */
+	if ((image = purple_buddy_icons_find_account_icon(account))) {
+		char *checksum = jabber_calculate_data_sha1sum(purple_imgstore_get_data(image),
+					purple_imgstore_get_size(image));
+		purple_account_set_string(account, "prpl-jabber_icon_checksum", checksum);
+		g_free(checksum);
+		purple_imgstore_unref(image);
+	} else {
+		purple_account_set_string(account, "prpl-jabber_icon_checksum", "");
+	}
+
 	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
--- a/libpurple/protocols/jabber/useravatar.c	Wed Jan 21 17:56:07 2009 +0000
+++ b/libpurple/protocols/jabber/useravatar.c	Wed Jan 21 20:16:22 2009 +0000
@@ -158,6 +158,37 @@
 	}
 }
 
+static void
+do_got_own_avatar_cb(JabberStream *js, const char *from, xmlnode *items)
+{
+	xmlnode *item = NULL, *metadata = NULL, *info = NULL;
+	PurpleAccount *account = purple_connection_get_account(js->gc);
+	const char *current_hash = purple_account_get_string(account, "prpl-jabber_icon_checksum", "");
+	const char *server_hash = NULL;
+
+	if ((item = xmlnode_get_child(items, "item")) &&
+	     (metadata = xmlnode_get_child(item, "metadata")) &&
+	     (info = xmlnode_get_child(metadata, "info"))) {
+		server_hash = xmlnode_get_attrib(info, "id");
+	}
+
+	/* Publish ours if it's different than the server's */
+	if ((!server_hash && current_hash[0] != '\0') ||
+		 (server_hash && strcmp(server_hash, current_hash))) {
+		PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
+		jabber_avatar_set(js, img);
+		purple_imgstore_unref(img);
+	}
+}
+
+void jabber_avatar_fetch_mine(JabberStream *js)
+{
+	char *jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
+	jabber_pep_request_item(js, jid, AVATARNAMESPACEMETA, NULL,
+	                        do_got_own_avatar_cb);
+	g_free(jid);
+}
+
 typedef struct _JabberBuddyAvatarUpdateURLInfo {
 	JabberStream *js;
 	char *from;
--- a/libpurple/protocols/jabber/useravatar.h	Wed Jan 21 17:56:07 2009 +0000
+++ b/libpurple/protocols/jabber/useravatar.h	Wed Jan 21 20:16:22 2009 +0000
@@ -25,10 +25,13 @@
 #define _PURPLE_JABBER_USERAVATAR_H_
 
 #include "jabber.h"
+#include "imgstore.h"
 
 /* Implementation of XEP-0084 */
 
 void jabber_avatar_init(void);
 void jabber_avatar_set(JabberStream *js, PurpleStoredImage *img);
 
+void jabber_avatar_fetch_mine(JabberStream *js);
+
 #endif /* _PURPLE_JABBER_USERAVATAR_H_ */