diff src/protocols/jabber/buddy.c @ 10189:4e7249591251

[gaim-migrate @ 11304] this would appear to be jabber buddy icon support no, this isn't a standard yet, but those nice folks over at apple decided to put jabber into iChat, and this is how they do things committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Mon, 15 Nov 2004 06:15:53 +0000
parents a9fb4493ae22
children 132e8767b2f6
line wrap: on
line diff
--- a/src/protocols/jabber/buddy.c	Mon Nov 15 03:53:56 2004 +0000
+++ b/src/protocols/jabber/buddy.c	Mon Nov 15 06:15:53 2004 +0000
@@ -32,6 +32,7 @@
 #include "jabber.h"
 #include "iq.h"
 #include "presence.h"
+#include "sha.h"
 
 
 void jabber_buddy_free(JabberBuddy *jb)
@@ -360,16 +361,51 @@
 	JabberIq *iq;
 	JabberStream *js = gc->proto_data;
 	xmlnode *vc_node;
+	const char *avatar_file = NULL;
 
+	if(js->avatar_hash)
+		g_free(js->avatar_hash);
+	js->avatar_hash = NULL;
 
 	/*
 	 * Send only if there's actually any *information* to send
 	 */
 	vc_node = xmlnode_from_str(info, -1);
+	avatar_file = gaim_account_get_buddy_icon(gc->account);
+
+	if(!vc_node && avatar_file) {
+		vc_node = xmlnode_new("vCard");
+	}
 
 	if(vc_node) {
 		if (vc_node->name &&
-				!g_ascii_strncasecmp(vc_node->name, "vcard", 5)) {
+				!g_ascii_strncasecmp(vc_node->name, "vCard", 5)) {
+			GError *error = NULL;
+			char *avatar_data;
+			gsize avatar_len;
+
+			if(avatar_file && g_file_get_contents(avatar_file, &avatar_data, &avatar_len, &error)) {
+				xmlnode *photo;
+				char *enc;
+				int i;
+				unsigned char hashval[20];
+				char *p, hash[41];
+
+				photo = xmlnode_new_child(vc_node, "PHOTO");
+				enc = gaim_base64_encode(avatar_data, avatar_len);
+				shaBlock((unsigned char *)avatar_data, avatar_len, hashval);
+				p = hash;
+				for(i=0; i<20; i++, p+=2)
+					snprintf(p, 3, "%02x", hashval[i]);
+				js->avatar_hash = g_strdup(hash);
+
+				xmlnode_insert_data(photo, enc, -1);
+				g_free(enc);
+				g_free(avatar_data);
+			} else {
+				g_error_free(error);
+			}
+
 			iq = jabber_iq_new(js, JABBER_IQ_SET);
 			xmlnode_insert_child(iq->node, vc_node);
 			jabber_iq_send(iq);
@@ -379,6 +415,18 @@
 	}
 }
 
+void jabber_set_buddy_icon(GaimConnection *gc, const char *iconfile)
+{
+	GaimPresence *gpresence;
+	GaimStatus *status;
+
+	jabber_set_info(gc, gaim_account_get_user_info(gc->account));
+
+	gpresence = gaim_account_get_presence(gc->account);
+	status = gaim_presence_get_active_status(gpresence);
+	jabber_presence_send(gc, status);
+}
+
 /*
  * This is the callback from the "ok clicked" for "set vCard"
  *
@@ -540,6 +588,7 @@
 	char *text;
 	xmlnode *vcard;
 	GaimBuddy *b;
+	GSList *imgids = NULL;
 
 	if(!from)
 		return;
@@ -589,9 +638,9 @@
 	}
 
 	g_free(resource_name);
-	g_free(bare_jid);
 
-	if((vcard = xmlnode_get_child(packet, "vCard"))) {
+	if((vcard = xmlnode_get_child(packet, "vCard")) ||
+			(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) {
 		xmlnode *child;
 		for(child = vcard->child; child; child = child->next)
 		{
@@ -750,23 +799,29 @@
 						_("Description"), text);
 			} else if(!strcmp(child->name, "PHOTO") ||
 					!strcmp(child->name, "LOGO")) {
-				if((child2 = xmlnode_get_child(child, "BINVAL"))) {
-					char *data, *text2;
-					int size, imgid;
-					if((text2 = xmlnode_get_data(child2))) {
-						gaim_base64_decode(text2, &data, &size);
+				int size, i;
+				unsigned char hashval[20];
+				char *data, *p, hash[41];
+				gboolean photo = (strcmp(child->name, "PHOTO") == 0);
+
+				gaim_base64_decode(text, &data, &size);
 
-						imgid = gaim_imgstore_add(data, size, "logo.png");
-						g_string_append_printf(info_text,
-								"<b>%s:</b> <img id='%d'><br/>",
-								strcmp(child->name, "PHOTO")  == 0 ?
-								_("Photo") : _("Logo"),
-								imgid);
+				imgids = g_slist_prepend(imgids, GINT_TO_POINTER(gaim_imgstore_add(data, size, "logo.png")));
+				g_string_append_printf(info_text,
+						"<b>%s:</b> <img id='%d'><br/>",
+						photo ? _("Photo") : _("Logo"),
+						GPOINTER_TO_INT(imgids->data));
 
-						g_free(data);
-						g_free(text2);
-					}
-				}
+				gaim_buddy_icons_set_for_user(js->gc->account, bare_jid,
+						data, size);
+
+				shaBlock((unsigned char *)data, size, hashval);
+				p = hash;
+				for(i=0; i<20; i++, p+=2)
+					snprintf(p, 3, "%02x", hashval[i]);
+				gaim_blist_node_set_string((GaimBlistNode*)b, "avatar_hash", hash);
+
+				g_free(data);
 			}
 			g_free(text);
 		}
@@ -779,20 +834,24 @@
 	gaim_notify_userinfo(js->gc, from, title, _("Jabber Profile"),
 			NULL, text, NULL, NULL);
 
+	while(imgids) {
+		gaim_imgstore_unref(GPOINTER_TO_INT(imgids->data));
+		imgids = g_slist_delete_link(imgids, imgids);
+	}
 	g_free(title);
 	g_string_free(info_text, TRUE);
 	g_free(text);
+	g_free(bare_jid);
 }
 
-void jabber_buddy_get_info(GaimConnection *gc, const char *who)
+static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *full_jid)
 {
-	JabberStream *js = gc->proto_data;
 	JabberIq *iq;
 	xmlnode *vcard;
 
 	iq = jabber_iq_new(js, JABBER_IQ_GET);
 
-	xmlnode_set_attrib(iq->node, "to", who);
+	xmlnode_set_attrib(iq->node, "to", full_jid);
 	vcard = xmlnode_new_child(iq->node, "vCard");
 	xmlnode_set_attrib(vcard, "xmlns", "vcard-temp");
 
@@ -801,6 +860,17 @@
 	jabber_iq_send(iq);
 }
 
+void jabber_buddy_get_info(GaimConnection *gc, const char *who)
+{
+	JabberStream *js = gc->proto_data;
+	char *bare_jid = jabber_get_bare_jid(who);
+
+	if(bare_jid) {
+		jabber_buddy_get_info_for_jid(js, bare_jid);
+		g_free(bare_jid);
+	}
+}
+
 void jabber_buddy_get_info_chat(GaimConnection *gc, int id,
 		const char *resource)
 {
@@ -812,7 +882,7 @@
 		return;
 
 	full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, resource);
-	jabber_buddy_get_info(gc, full_jid);
+	jabber_buddy_get_info_for_jid(js, full_jid);
 	g_free(full_jid);
 }