cpw.darkrain42.xmpp.avatars: d70cdd1f: Only (re)publish XMPP avatars at login i...

paul at darkrain42.org paul at darkrain42.org
Fri Jan 23 22:28:23 EST 2009


-----------------------------------------------------------------
Revision: d70cdd1fd161f70a868170d8a72eadfbecfc966c
Ancestor: fd812d7a888de06f4277dce064bfc552b7e9069a
Author: paul at darkrain42.org
Date: 2009-01-21T20:16:22
Branch: im.pidgin.cpw.darkrain42.xmpp.avatars
URL: http://d.pidgin.im/viewmtn/revision/info/d70cdd1fd161f70a868170d8a72eadfbecfc966c

Modified 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

ChangeLog: 

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.

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/buddy.c	bfb50b6e9b69360d541061f6c9c9be615dbd6167
+++ libpurple/protocols/jabber/buddy.c	8035cd1a1fe864b3e7ac970164fb60d44ae5df30
@@ -472,7 +472,6 @@ void jabber_set_info(PurpleConnection *g
 		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 @@ void jabber_set_buddy_icon(PurpleConnect
 {
 	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(Jabbe
 
 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 @@ static void jabber_vcard_save_mine(Jabbe
 
 	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)
============================================================
--- libpurple/protocols/jabber/disco.c	15e05aeaa2b1e64bc8b77794391c734d82691a3e
+++ libpurple/protocols/jabber/disco.c	1b4fb320eab75766adc1065f181c914419739d07
@@ -23,17 +23,17 @@
 #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;
 	JabberDiscoInfoCallback *callback;
@@ -341,6 +341,8 @@ jabber_disco_finish_server_info_result_c
 	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 */
============================================================
--- libpurple/protocols/jabber/jabber.c	61d4248bdb4e553fe1766ca4a68d5259c747c729
+++ libpurple/protocols/jabber/jabber.c	f760dfac5be739853e2e2c76e815d620fd570ab5
@@ -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 @@ jabber_login(PurpleAccount *account)
 	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 @@ jabber_login(PurpleAccount *account)
 			_("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;
 
============================================================
--- libpurple/protocols/jabber/useravatar.c	3f6d2ed2616945ff8dfa2aca1db8c7f7810cf7ab
+++ libpurple/protocols/jabber/useravatar.c	40323527451da4237806afade17a7ebd7329604d
@@ -158,6 +158,37 @@ void jabber_avatar_set(JabberStream *js,
 	}
 }
 
+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;
============================================================
--- libpurple/protocols/jabber/useravatar.h	e28754135ef2cec4c7804278d58f8dec2a1b92b2
+++ libpurple/protocols/jabber/useravatar.h	1d2a306daafa10e1dfaf55383bd41257505e2477
@@ -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_ */


More information about the Commits mailing list