# HG changeset patch # User Paul Aurich # Date 1232568982 0 # Node ID 9195955395b6cc83f8b6b06e60d79d563663b5dd # Parent b68ac693ae2d7284e5ad769640144567cf363d49 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. diff -r b68ac693ae2d -r 9195955395b6 libpurple/protocols/jabber/buddy.c --- 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) diff -r b68ac693ae2d -r 9195955395b6 libpurple/protocols/jabber/disco.c --- 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 */ diff -r b68ac693ae2d -r 9195955395b6 libpurple/protocols/jabber/jabber.c --- 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; diff -r b68ac693ae2d -r 9195955395b6 libpurple/protocols/jabber/useravatar.c --- 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; diff -r b68ac693ae2d -r 9195955395b6 libpurple/protocols/jabber/useravatar.h --- 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_ */