changeset 27164:959e86c022f7

Support fetching Gadu-Gadu avatars. Closes #9371. Patch from Krzysztof "kkszysiu" Klinikowski (with some updates to libpurple 2.6.0 API from me). committer: Paul Aurich <paul@darkrain42.org>
author grommasher@gmail.com
date Tue, 23 Jun 2009 20:48:02 +0000
parents 420850f3236e
children 1a971a264c3e
files ChangeLog libpurple/protocols/gg/gg.c
diffstat 2 files changed, 148 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jun 23 19:06:28 2009 +0000
+++ b/ChangeLog	Tue Jun 23 20:48:02 2009 +0000
@@ -18,8 +18,13 @@
 	  from you on MSN.
 	* DNS servers are re-read when DNS queries fail in case the system has
 	  moved to a new network and the old servers are not accessible.
-	* Gadu-Gadu accounts can specify a server to which to connect.
+
+	Gadu-Gadu:
+	* Accounts can specify a server to which to connect.
 	  (Krzysztof "kreez" Tobola)
+	* Correctly show tooltip status for contacts with status messages.
+	  (Krzysztof "kkszysiu" Klinikowski)
+	* Support for fetching buddy icons.  (Krzysztof "kkszysiu" Klinikowski)
 
 	XMPP:
 	* Voice & Video support with Jingle (XEP-0166, 0167, 0176, & 0177), voice
--- a/libpurple/protocols/gg/gg.c	Tue Jun 23 19:06:28 2009 +0000
+++ b/libpurple/protocols/gg/gg.c	Tue Jun 23 20:48:02 2009 +0000
@@ -7,6 +7,7 @@
  *
  * Some parts of the code are adapted or taken from the previous implementation
  * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
+ * Some parts Copyright (C) 2009  Krzysztof Klinikowski <grommasher@gmail.com>
  *
  * Thanks to Google's Summer of Code Program.
  *
@@ -36,6 +37,7 @@
 #include "debug.h"
 #include "util.h"
 #include "request.h"
+#include "xmlnode.h"
 
 #include <libgadu.h>
 
@@ -858,6 +860,133 @@
 static void ggp_set_status(PurpleAccount *account, PurpleStatus *status);
 static int ggp_to_gg_status(PurpleStatus *status, char **msg);
 
+struct gg_fetch_avatar_data
+{
+	PurpleConnection *gc;
+	gchar *uin;
+	gchar *avatar_url;
+};
+
+
+static void gg_fetch_avatar_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+               const gchar *data, size_t len, const gchar *error_message) {
+	struct gg_fetch_avatar_data *d = user_data;
+	PurpleAccount *account;
+	PurpleBuddy *buddy;
+	gpointer buddy_icon_data;
+
+	/* FIXME: This shouldn't be necessary */
+	if (!PURPLE_CONNECTION_IS_VALID(d->gc)) {
+		g_free(d->uin);
+		g_free(d->avatar_url);
+		g_free(d);
+		g_return_if_reached();
+	}
+
+	account = purple_connection_get_account(d->gc);
+	buddy = purple_find_buddy(account, d->uin);
+
+	if (buddy == NULL)
+		goto out;
+
+	buddy_icon_data = g_memdup(data, len);
+
+	purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
+			buddy_icon_data, len, d->avatar_url);
+	purple_debug_info("gg", "UIN: %s should have avatar now\n", d->uin);
+
+out:
+	g_free(d->uin);
+	g_free(d->avatar_url);
+	g_free(d);
+}
+
+static void gg_get_avatar_url_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+               const gchar *url_text, size_t len, const gchar *error_message) {
+	struct gg_fetch_avatar_data *data;
+	PurpleConnection *gc = user_data;
+	PurpleAccount *account;
+	PurpleBuddy *buddy;
+	const char *uin;
+	const char *is_blank;
+	const char *checksum;
+
+	gchar *bigavatar = NULL;
+	xmlnode *xml = NULL;
+	xmlnode *xmlnode_users;
+	xmlnode *xmlnode_user;
+	xmlnode *xmlnode_avatars;
+	xmlnode *xmlnode_avatar;
+	xmlnode *xmlnode_bigavatar;
+
+	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
+	account = purple_connection_get_account(gc);
+
+	if (error_message != NULL)
+		purple_debug_error("gg", "gg_get_avatars_cb error: %s\n", error_message);
+	else if (len > 0 && url_text && *url_text) {
+		xml = xmlnode_from_str(url_text, -1);
+		if (xml == NULL)
+			goto out;
+
+		xmlnode_users = xmlnode_get_child(xml, "users");
+		if (xmlnode_users == NULL)
+			goto out;
+
+		xmlnode_user = xmlnode_get_child(xmlnode_users, "user");
+		if (xmlnode_user == NULL)
+			goto out;
+
+		uin = xmlnode_get_attrib(xmlnode_user, "uin");
+
+		xmlnode_avatars = xmlnode_get_child(xmlnode_user, "avatars");
+		if (xmlnode_avatars == NULL)
+			goto out;
+
+		xmlnode_avatar = xmlnode_get_child(xmlnode_avatars, "avatar");
+		if (xmlnode_avatar == NULL)
+			goto out;
+
+		xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "bigAvatar");
+		if (xmlnode_bigavatar == NULL)
+			goto out;
+
+		is_blank = xmlnode_get_attrib(xmlnode_avatar, "blank");
+		bigavatar = xmlnode_get_data(xmlnode_bigavatar);
+
+		purple_debug_info("gg", "gg_get_avatar_url_cb: UIN %s, IS_BLANK %s, "
+		                        "URL %s\n",
+		                  uin ? uin : "(null)", is_blank ? is_blank : "(null)",
+		                  bigavatar ? bigavatar : "(null)");
+
+		if (uin != NULL && bigavatar != NULL) {
+			buddy = purple_find_buddy(account, uin);
+			if (buddy == NULL)
+				goto out;
+
+			checksum = purple_buddy_icons_get_checksum_for_user(buddy);
+
+			if (purple_strequal(is_blank, "1")) {
+				purple_buddy_icons_set_for_user(account,
+						purple_buddy_get_name(buddy), NULL, 0, NULL);
+			} else if (!purple_strequal(checksum, bigavatar)) {
+				data = g_new0(struct gg_fetch_avatar_data, 1);
+				data->gc = gc;
+				data->uin = g_strdup(uin);
+				data->avatar_url = g_strdup(bigavatar);
+
+				url_data = purple_util_fetch_url_request_len_with_account(account,
+						bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
+						FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
+			}
+		}
+	}
+
+out:
+	if (xml)
+		xmlnode_free(xml);
+	g_free(bigavatar);
+}
 
 /**
  * Handle change of the status of the buddy.
@@ -873,8 +1002,19 @@
 	gchar *from;
 	const char *st;
 	gchar *msg;
-
-	from = g_strdup_printf("%ld", (unsigned long int)uin);
+	gchar *avatarurl;
+	PurpleUtilFetchUrlData *url_data;
+
+	from = g_strdup_printf("%u", uin);
+	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%s/0.xml", from);
+
+	url_data = purple_util_fetch_url_request_len_with_account(
+			purple_connection_get_account(gc), avatarurl, TRUE,
+			"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
+			gg_get_avatar_url_cb, gc);
+
+	g_free(avatarurl);
+
 	switch (status) {
 		case GG_STATUS_NOT_AVAIL:
 		case GG_STATUS_NOT_AVAIL_DESCR: