--- a/libpurple/protocols/jabber/buddy.c Sun Apr 05 03:25:00 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sun Apr 05 21:13:10 2009 +0000 @@ -155,6 +155,7 @@ jbr->jb = jb; jbr->name = g_strdup(resource); jbr->capabilities = JABBER_CAP_XHTML; + jbr->tz_off = PURPLE_NO_TZ_OFF; jb->resources = g_list_append(jb->resources, jbr); } jbr->priority = priority; @@ -794,6 +795,21 @@ purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); } } + if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { + time_t now_t; + struct tm *now; + char *timestamp; + time(&now_t); + now_t += jbr->tz_off; + now = gmtime(&now_t); + + timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), + jbr->tz_off < 0 ? '-' : '+', + abs(jbr->tz_off / (60*60)), + abs((jbr->tz_off % (60*60)) / 60)); + purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + g_free(timestamp); + } if(jbir) { if(jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); @@ -912,7 +928,7 @@ feature = _("User Gaming"); else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) feature = _("User Viewing"); - else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(feature, "urn:xmpp:ping")) feature = _("Ping"); else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) feature = _("Stanza Encryption"); @@ -964,6 +980,22 @@ } } + if (jbr->tz_off != PURPLE_NO_TZ_OFF) { + time_t now_t; + struct tm *now; + char *timestamp; + time(&now_t); + now_t += jbr->tz_off; + now = gmtime(&now_t); + + timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), + jbr->tz_off < 0 ? '-' : '+', + abs(jbr->tz_off / (60*60)), + abs((jbr->tz_off % (60*60)) / 60)); + purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + g_free(timestamp); + } + if(jbr->name && (jbir = g_hash_table_lookup(jbi->resources, jbr->name))) { if(jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); @@ -1082,7 +1114,7 @@ feature = _("User Gaming"); else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) feature = _("User Viewing"); - else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(feature, "urn:xmpp:ping")) feature = _("Ping"); else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) feature = _("Stanza Encryption"); @@ -1148,12 +1180,19 @@ } } -static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_vcard_save_mine(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *vcard; char *txt; PurpleStoredImage *img; + if (type == JABBER_IQ_ERROR) { + purple_debug_warning("jabber", "Server returned error while retrieving vCard"); + return; + } + if((vcard = xmlnode_get_child(packet, "vCard")) || (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { @@ -1184,9 +1223,10 @@ jabber_iq_send(iq); } -static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_vcard_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *id, *from; char *bare_jid; char *text; char *serverside_alias = NULL; @@ -1195,9 +1235,6 @@ JabberBuddyInfo *jbi = data; PurpleNotifyUserInfo *user_info; - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - if(!jbi) return; @@ -1547,19 +1584,16 @@ g_free(jbri); } -static void jabber_version_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_version_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberBuddyInfo *jbi = data; - const char *type, *id, *from; xmlnode *query; char *resource_name; g_return_if_fail(jbi != NULL); - type = xmlnode_get_attrib(packet, "type"); - id = xmlnode_get_attrib(packet, "id"); - from = xmlnode_get_attrib(packet, "from"); - jabber_buddy_info_remove_id(jbi, id); if(!from) @@ -1568,7 +1602,7 @@ resource_name = jabber_get_resource(from); if(resource_name) { - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if((query = xmlnode_get_child(packet, "query"))) { JabberBuddyResource *jbr = jabber_buddy_find_resource(jbi->jb, resource_name); if(jbr) { @@ -1591,19 +1625,17 @@ jabber_buddy_info_show_if_ready(jbi); } -static void jabber_last_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_last_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberBuddyInfo *jbi = data; xmlnode *query; char *resource_name; - const char *type, *id, *from, *seconds; + const char *seconds; g_return_if_fail(jbi != NULL); - type = xmlnode_get_attrib(packet, "type"); - id = xmlnode_get_attrib(packet, "id"); - from = xmlnode_get_attrib(packet, "from"); - jabber_buddy_info_remove_id(jbi, id); if(!from) @@ -1612,7 +1644,7 @@ resource_name = jabber_get_resource(from); if(resource_name) { - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if((query = xmlnode_get_child(packet, "query"))) { seconds = xmlnode_get_attrib(query, "seconds"); if(seconds) { @@ -1633,6 +1665,56 @@ jabber_buddy_info_show_if_ready(jbi); } +static void jabber_time_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberBuddyInfo *jbi = data; + JabberBuddyResource *jbr; + char *resource_name; + + g_return_if_fail(jbi != NULL); + + jabber_buddy_info_remove_id(jbi, id); + + if (!from) + return; + + resource_name = jabber_get_resource(from); + jbr = resource_name ? jabber_buddy_find_resource(jbi->jb, resource_name) : NULL; + g_free(resource_name); + if (jbr) { + if (type == JABBER_IQ_RESULT) { + xmlnode *time = xmlnode_get_child(packet, "time"); + xmlnode *tzo = time ? xmlnode_get_child(time, "tzo") : NULL; + char *tzo_data = tzo ? xmlnode_get_data(tzo) : NULL; + if (tzo_data) { + char *c = tzo_data; + int hours, minutes; + if (tzo_data[0] == 'Z' && tzo_data[1] == '\0') { + jbr->tz_off = 0; + } else { + gboolean offset_positive = (tzo_data[0] == '+'); + /* [+-]HH:MM */ + if (((*c == '+' || *c == '-') && (c = c + 1)) && + sscanf(c, "%02d:%02d", &hours, &minutes) == 2) { + jbr->tz_off = 60*60*hours + 60*minutes; + if (!offset_positive) + jbr->tz_off *= -1; + } else { + purple_debug_info("jabber", "Ignoring malformed timezone %s", + tzo_data); + } + } + + g_free(tzo_data); + } + } + } + + jabber_buddy_info_show_if_ready(jbi); +} + void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js) { if (js->pending_buddy_info_requests) @@ -1764,6 +1846,19 @@ jabber_iq_send(iq); } + if (jbr->tz_off == PURPLE_NO_TZ_OFF && + (!jbr->caps || + jabber_resource_has_capability(jbr, "urn:xmpp:time"))) { + xmlnode *child; + iq = jabber_iq_new(js, JABBER_IQ_GET); + xmlnode_set_attrib(iq->node, "to", full_jid); + child = xmlnode_new_child(iq->node, "time"); + xmlnode_set_namespace(child, "urn:xmpp:time"); + jabber_iq_set_callback(iq, jabber_time_parse, jbi); + jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); + jabber_iq_send(iq); + } + g_free(full_jid); } @@ -2160,7 +2255,9 @@ g_list_nth_data(row, 0), NULL, NULL); } -static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void user_search_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleNotifySearchResults *results; PurpleNotifySearchColumn *column; @@ -2356,15 +2453,16 @@ }; #endif -static void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void user_search_fields_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *from, *type; - if(!(from = xmlnode_get_attrib(packet, "from"))) + if (!from) return; - if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); if(!msg)