# HG changeset patch # User grommasher@gmail.com # Date 1245790082 0 # Node ID 959e86c022f7cacaf4371cd7cb8ed191c591d28f # Parent 420850f3236ef26a52b6435ff6ad2dbe3eda5047 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 diff -r 420850f3236e -r 959e86c022f7 ChangeLog --- 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 diff -r 420850f3236e -r 959e86c022f7 libpurple/protocols/gg/gg.c --- 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 + * Some parts Copyright (C) 2009 Krzysztof Klinikowski * * 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 @@ -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: