# HG changeset patch # User Nathan Walp # Date 1051978126 0 # Node ID cfbd0cb3f18b707b5e56a09734432bb939ce6899 # Parent 92cbe9541c3b8218229eeb706571afd1ebe5a9a8 [gaim-migrate @ 5661] this implements the receiving side of JEP-0008 (User Avatars) which most Gaim users know better as Buddy Icons. Only one client I know of actually sends them, and it's on windows. This doesn't handle multiple resources right, but I'll fix that after my exam. committer: Tailor Script diff -r 92cbe9541c3b -r cfbd0cb3f18b src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Sat May 03 06:37:29 2003 +0000 +++ b/src/protocols/jabber/jabber.c Sat May 03 16:08:46 2003 +0000 @@ -1444,6 +1444,59 @@ } } +static void jabber_handleavatar(gjconn gjc, xmlnode querynode, char *from) { + char *buddy; + char *encoded; + char *icon; + int iconlen; + xmlnode data; + + if((buddy = get_realwho(gjc, from, FALSE, NULL)) == NULL) + return; + + data = xmlnode_get_tag(querynode, "data"); + + if(!data) { + g_free(buddy); + return; + } + + encoded = xmlnode_get_data(data); + + if(!encoded) { + g_free(buddy); + return; + } + + frombase64(encoded, &icon, &iconlen); + set_icon_data(GJ_GC(gjc), buddy, icon, iconlen); + g_free(icon); + g_free(buddy); +} + +static void jabber_request_buddy_avatar(struct gaim_connection *gc, char *who) { + xmlnode x; + char *id; + char *realwho; + struct jabber_data *jd = gc->proto_data; + gjconn gjc = jd->gjc; + + if((realwho = get_realwho(gjc, who, TRUE, NULL)) == NULL) + return; + + x = jutil_iqnew(JPACKET__GET, "jabber:iq:avatar"); + xmlnode_put_attrib(x, "to", realwho); + + g_free(realwho); + + id = gjab_getid(gjc); + xmlnode_put_attrib(x, "id", id); + + gjab_send(gjc, x); + + xmlnode_free(x); +} + static void jabber_handlepresence(gjconn gjc, jpacket p) { char *to, *from, *type; @@ -1506,9 +1559,6 @@ } } - if ((y = xmlnode_get_tag(p->x, "priority"))) - priority = atoi(xmlnode_get_data(y)); - /* um. we're going to check if it's a chat. if it isn't, and there are pending * chats, create the chat. if there aren't pending chats and we don't have the * buddy on our list, simply bail out. */ @@ -1534,6 +1584,29 @@ jabber_track_away(gjc, p, type); } + for(y = xmlnode_get_firstchild(p->x); y; y = xmlnode_get_nextsibling(y)) { + if(!strcmp(xmlnode_get_name(y), "priority")) { + priority = atoi(xmlnode_get_data(y)); + } else if(!strcmp(xmlnode_get_name(y), "x")) { + if(!strcmp(xmlnode_get_attrib(y, "xmlns"), "jabber:x:avatar")) { + xmlnode hash = xmlnode_get_tag(y, "hash"); + if(hash) { + char *old_hash = gaim_buddy_get_setting(b, "icon_checksum"); + char *new_hash = xmlnode_get_data(hash); + if(!old_hash || strcmp(old_hash, new_hash)) { + jabber_request_buddy_avatar(GJ_GC(gjc), from); + gaim_buddy_set_setting(b, "icon_checksum", new_hash); + gaim_blist_save(); + } + } else { + gaim_buddy_set_setting(b, "icon_checksum", NULL); + gaim_blist_save(); + } + } + } + } + + if (!cnv) { /* this is where we handle presence information for "regular" buddies */ @@ -2219,6 +2292,8 @@ } else if (vcard) { jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ jabber_handlevcard(gjc, vcard, from); + } else if(NSCHECK(querynode, "jabber:iq:avatar")) { + jabber_handleavatar(gjc, querynode, from); } else if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL) { gaim_debug(GAIM_DEBUG_MISC, "jabber", "jabber:iq:query: %s\n", xmlns); diff -r 92cbe9541c3b -r cfbd0cb3f18b src/util.c --- a/src/util.c Sat May 03 06:37:29 2003 +0000 +++ b/src/util.c Sat May 03 16:08:46 2003 +0000 @@ -430,6 +430,9 @@ tmp = 62; } else if (*c == '/') { tmp = 63; + } else if (*c == '\r' || *c == '\n') { + c++; + continue; } else if (*c == '=') { if (n == 3) { out = g_realloc(out, len + 2);