# HG changeset patch # User Paul Aurich # Date 1238828913 0 # Node ID 8399b545925c4f65e0cb55b7e9fead96da307e40 # Parent c08719989149ff17cc0e03dc079365a957c6c2bf# Parent 50ff0162fe26bd155bd735ace98680221ca99124 propagate from branch 'im.pidgin.pidgin' (head 58b2ba106e563fcd0984b9438aa427f1d61e25e9) to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head a7d6ab07b988776e830ffb6befb18179ff46e24e) diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/adhoccommands.c --- a/libpurple/protocols/jabber/adhoccommands.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Sat Apr 04 07:08:33 2009 +0000 @@ -39,16 +39,17 @@ GList *actionslist; } JabberAdHocActionInfo; -void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); +void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ const char *node; xmlnode *query, *item; JabberID *jabberid; JabberBuddy *jb; JabberBuddyResource *jbr = NULL; - if(strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items"); @@ -95,7 +96,10 @@ } } -static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data); +static void jabber_adhoc_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); + static void do_adhoc_action_cb(JabberStream *js, xmlnode *result, const char *actionhandle, gpointer user_data) { xmlnode *command; @@ -131,13 +135,16 @@ jabber_iq_send(iq); } -static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_adhoc_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *command = xmlnode_get_child_with_namespace(packet, "command", "http://jabber.org/protocol/commands"); const char *status = xmlnode_get_attrib(command,"status"); xmlnode *xdata = xmlnode_get_child_with_namespace(command,"x","jabber:x:data"); - const char *type = xmlnode_get_attrib(packet,"type"); - if(type && !strcmp(type,"error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown Error")); @@ -147,8 +154,6 @@ g_free(msg); return; } - if(!type || strcmp(type,"result")) - return; if(!status) return; @@ -159,7 +164,7 @@ if(note) { char *data = xmlnode_get_data(note); - purple_notify_info(NULL, xmlnode_get_attrib(packet, "from"), data, NULL); + purple_notify_info(NULL, from, data, NULL); g_free(data); } @@ -199,7 +204,7 @@ actionInfo = g_new0(JabberAdHocActionInfo, 1); actionInfo->sessionid = g_strdup(xmlnode_get_attrib(command,"sessionid")); - actionInfo->who = g_strdup(xmlnode_get_attrib(packet,"from")); + actionInfo->who = g_strdup(from); actionInfo->node = g_strdup(xmlnode_get_attrib(command,"node")); actionInfo->actionslist = actionslist; @@ -218,7 +223,11 @@ } } -static void jabber_adhoc_server_got_list_cb(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_adhoc_server_got_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#items"); xmlnode *item; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/adhoccommands.h --- a/libpurple/protocols/jabber/adhoccommands.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.h Sat Apr 04 07:08:33 2009 +0000 @@ -26,7 +26,9 @@ /* Implementation of XEP-0050 */ -void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data); +void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); void jabber_adhoc_execute(JabberStream *js, JabberAdHocCommands *cmd); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/auth.c Sat Apr 04 07:08:33 2009 +0000 @@ -36,8 +36,9 @@ #include "iq.h" #include "notify.h" -static void auth_old_result_cb(JabberStream *js, xmlnode *packet, - gpointer data); +static void auth_old_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); gboolean jabber_process_starttls(JabberStream *js, xmlnode *packet) @@ -566,11 +567,11 @@ #endif } -static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void auth_old_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); } else { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; @@ -593,24 +594,20 @@ } } -static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void auth_old_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIq *iq; xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); const char *pw = purple_connection_get_password(js->gc); - if(!type) { - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Invalid response from server.")); - return; - } else if(!strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); purple_connection_error_reason (js->gc, reason, msg); g_free(msg); - } else if(!strcmp(type, "result")) { + } else if (type == JABBER_IQ_RESULT) { query = xmlnode_get_child(packet, "query"); if(js->stream_id && xmlnode_get_child(query, "digest")) { char *s, *hash; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sat Apr 04 07:08:33 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; @@ -797,6 +798,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); @@ -915,7 +931,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"); @@ -967,6 +983,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); @@ -1085,7 +1117,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"); @@ -1151,12 +1183,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"))) { @@ -1187,9 +1226,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; @@ -1198,9 +1238,6 @@ JabberBuddyInfo *jbi = data; PurpleNotifyUserInfo *user_info; - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - if(!jbi) return; @@ -1550,19 +1587,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) @@ -1571,7 +1605,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) { @@ -1594,19 +1628,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) @@ -1615,7 +1647,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) { @@ -1636,6 +1668,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) @@ -1767,6 +1849,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); } @@ -2163,7 +2258,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; @@ -2359,15 +2456,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) diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/buddy.h --- a/libpurple/protocols/jabber/buddy.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.h Sat Apr 04 07:08:33 2009 +0000 @@ -81,6 +81,8 @@ char *name; char *os; } client; + /* tz_off == PURPLE_NO_TZ_OFF when unset */ + long tz_off; JabberCapsClientInfo *caps; GList *commands; } JabberBuddyResource; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/caps.c --- a/libpurple/protocols/jabber/caps.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/caps.c Sat Apr 04 07:08:33 2009 +0000 @@ -369,7 +369,10 @@ } } -static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer data) { +static void jabber_caps_ext_iqcb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ /* collect data and fetch all exts */ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info"); jabber_ext_userdata *extuserdata = data; @@ -433,7 +436,10 @@ jabber_caps_get_info_check_completion(userdata); } -static void jabber_caps_client_iqcb(JabberStream *js, xmlnode *packet, gpointer data) { +static void jabber_caps_client_iqcb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ /* collect data and fetch all exts */ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info"); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Sat Apr 04 07:08:33 2009 +0000 @@ -376,21 +376,19 @@ jabber_iq_send(iq); } -static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_room_configure_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); - const char *from = xmlnode_get_attrib(packet, "from"); char *msg; JabberChat *chat; JabberID *jid; - if(!type || !from) + if (!from) return; - - - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jid = jabber_id_new(from); if(!jid) @@ -416,7 +414,7 @@ return; } } - } else if(!strcmp(type, "error")) { + } else if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg); @@ -486,11 +484,12 @@ g_free(room_jid); } -static void jabber_chat_register_x_data_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void +jabber_chat_register_x_data_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -521,19 +520,19 @@ jabber_iq_send(iq); } -static void jabber_chat_register_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_register_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); - const char *from = xmlnode_get_attrib(packet, "from"); char *msg; JabberChat *chat; JabberID *jid; - if(!type || !from) + if (!from) return; - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jid = jabber_id_new(from); if(!jid) @@ -559,7 +558,7 @@ return; } } - } else if(!strcmp(type, "error")) { + } else if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -690,16 +689,17 @@ g_free(room_jid); } -static void roomlist_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void roomlist_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query; xmlnode *item; - const char *type; if(!js->roomlist) return; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { + if (type == JABBER_IQ_ERROR) { char *err = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error"), _("Error retrieving room list"), err); @@ -988,13 +988,17 @@ return TRUE; } -static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_disco_traffic_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberChat *chat; - /*xmlnode *query;*/ - int id = GPOINTER_TO_INT(data); +#if 0 + xmlnode *query, *x; +#endif + int chat_id = GPOINTER_TO_INT(data); - if(!(chat = jabber_chat_find_by_id(js, id))) + if(!(chat = jabber_chat_find_by_id(js, chat_id))) return; /* defaults, in case the conference server doesn't @@ -1002,8 +1006,9 @@ chat->xhtml = TRUE; /* disabling this until more MUC servers support - * announcing this - if(xmlnode_get_child(packet, "error")) { + * announcing this */ +#if 0 + if (type == JABBER_IQ_ERROR) { return; } @@ -1019,7 +1024,7 @@ chat->xhtml = TRUE; } } - */ +#endif } void jabber_chat_disco_traffic(JabberChat *chat) diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/data.c --- a/libpurple/protocols/jabber/data.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/data.c Sat Apr 04 07:08:33 2009 +0000 @@ -200,25 +200,26 @@ } void -jabber_data_parse(JabberStream *js, xmlnode *packet) +jabber_data_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *data_node) { JabberIq *result = NULL; - const char *who = xmlnode_get_attrib(packet, "from"); - xmlnode *data_node = xmlnode_get_child(packet, "data"); - const JabberData *data = - jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid")); + const char *cid = xmlnode_get_attrib(data_node, "cid"); + const JabberData *data = cid ? jabber_data_find_local_by_cid(cid) : NULL; if (!data) { xmlnode *item_not_found = xmlnode_new("item-not-found"); result = jabber_iq_new(js, JABBER_IQ_ERROR); - xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + if (who) + xmlnode_set_attrib(result->node, "to", who); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, item_not_found); } else { result = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + if (who) + xmlnode_set_attrib(result->node, "to", who); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, jabber_data_get_xml_definition(data)); } diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/data.h --- a/libpurple/protocols/jabber/data.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/data.h Sat Apr 04 07:08:33 2009 +0000 @@ -65,7 +65,8 @@ void jabber_data_associate_remote(JabberData *data); /* handles iq requests */ -void jabber_data_parse(JabberStream *js, xmlnode *packet); +void jabber_data_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *data_node); void jabber_data_init(void); void jabber_data_uninit(void); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/disco.c Sat Apr 04 07:08:33 2009 +0000 @@ -46,9 +46,11 @@ } static void -jabber_disco_bytestream_server_cb(JabberStream *js, xmlnode *packet, gpointer data) { +jabber_disco_bytestream_server_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ JabberBytestreamsStreamhost *sh = data; - const char *from = xmlnode_get_attrib(packet, "from"); xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/bytestreams"); @@ -86,29 +88,22 @@ } -void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); +void jabber_disco_info_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *in_query) { - if(!from || !type) + if(!from) return; - if(!strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { xmlnode *query, *identity, *feature; JabberIq *iq; - - xmlnode *in_query; - const char *node = NULL; - - if((in_query = xmlnode_get_child(packet, "query"))) { - node = xmlnode_get_attrib(in_query, "node"); - } - + const char *node = xmlnode_get_attrib(in_query, "node"); iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "http://jabber.org/protocol/disco#info"); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(iq, id); xmlnode_set_attrib(iq->node, "to", from); query = xmlnode_get_child(iq->node, "query"); @@ -127,7 +122,7 @@ SUPPORT_FEATURE("jabber:iq:last") SUPPORT_FEATURE("jabber:iq:oob") SUPPORT_FEATURE("jabber:iq:time") - SUPPORT_FEATURE("xmpp:urn:time") + SUPPORT_FEATURE("urn:xmpp:time") SUPPORT_FEATURE("jabber:iq:version") SUPPORT_FEATURE("jabber:x:conference") SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") @@ -140,7 +135,6 @@ SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") SUPPORT_FEATURE("urn:xmpp:ping") - SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns") if(!node) { /* non-caps disco#info, add all enabled extensions */ GList *features; @@ -209,8 +203,7 @@ } jabber_iq_send(iq); - } else if(!strcmp(type, "result")) { - xmlnode *query = xmlnode_get_child(packet, "query"); + } else if(type == JABBER_IQ_RESULT) { xmlnode *child; JabberID *jid; JabberBuddy *jb; @@ -227,7 +220,7 @@ if(jbr) capabilities = jbr->capabilities; - for(child = query->child; child; child = child->next) { + for(child = in_query->child; child; child = child->next) { if(child->type != XMLNODE_TYPE_TAG) continue; @@ -277,7 +270,7 @@ capabilities |= JABBER_CAP_IQ_SEARCH; else if(!strcmp(var, "jabber:iq:register")) capabilities |= JABBER_CAP_IQ_REGISTER; - else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(var, "urn:xmpp:ping")) capabilities |= JABBER_CAP_PING; else if(!strcmp(var, "http://jabber.org/protocol/commands")) { capabilities |= JABBER_CAP_ADHOC; @@ -298,7 +291,7 @@ jdicd->callback(js, from, capabilities, jdicd->data); g_hash_table_remove(js->disco_callbacks, from); } - } else if(!strcmp(type, "error")) { + } else if(type == JABBER_IQ_ERROR) { JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr = NULL; @@ -322,28 +315,23 @@ } } -void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "get")) { +void jabber_disco_items_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *query) { + if(type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "http://jabber.org/protocol/disco#items"); /* preserve node */ - xmlnode *iq_query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items"); - if(iq_query) { - xmlnode *query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items"); - if(query) { - const char *node = xmlnode_get_attrib(query,"node"); - if(node) - xmlnode_set_attrib(iq_query,"node",node); - } - } + xmlnode *iq_query = xmlnode_get_child(iq->node, "query"); + const char *node = xmlnode_get_attrib(query, "node"); + if(node) + xmlnode_set_attrib(iq_query,"node",node); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); jabber_iq_send(iq); } } @@ -408,19 +396,18 @@ } static void -jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_disco_server_info_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *child; - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - if((!from || !type) || - (strcmp(from, js->user->domain))) { + if (!from || strcmp(from, js->user->domain)) { jabber_disco_finish_server_info_result_cb(js); return; } - if(strcmp(type, "result")) { + if (type == JABBER_IQ_ERROR) { /* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */ jabber_disco_finish_server_info_result_cb(js); return; @@ -486,19 +473,16 @@ } static void -jabber_disco_server_items_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_disco_server_items_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *child; - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - if(!from || !type) + if (!from || strcmp(from, js->user->domain) != 0) return; - if(strcmp(from, js->user->domain)) - return; - - if(strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; while(js->chat_servers) { diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/disco.h --- a/libpurple/protocols/jabber/disco.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/disco.h Sat Apr 04 07:08:33 2009 +0000 @@ -27,8 +27,10 @@ typedef void (JabberDiscoInfoCallback)(JabberStream *js, const char *who, JabberCapabilities capabilities, gpointer data); -void jabber_disco_info_parse(JabberStream *js, xmlnode *packet); -void jabber_disco_items_parse(JabberStream *js, xmlnode *packet); +void jabber_disco_info_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *in_query); +void jabber_disco_items_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_disco_items_server(JabberStream *js); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Sat Apr 04 07:08:33 2009 +0000 @@ -613,13 +613,13 @@ #endif /* USE_VV */ static void -jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul) +jabber_gmail_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer nul) { - const char *type = xmlnode_get_attrib(packet, "type"); xmlnode *child; - xmlnode *message, *sender_node, *subject_node; - const char *from, *to, *url, *tid; - char *subject; + xmlnode *message; + const char *to, *url; const char *in_str; char *to_name; char *default_tos[1]; @@ -629,7 +629,7 @@ const char **tos, **froms, **urls; char **subjects; - if (strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; child = xmlnode_get_child(packet, "mailbox"); @@ -670,6 +670,10 @@ message= xmlnode_get_child(child, "mail-thread-info"); for (i=0; message; message = xmlnode_get_next_twin(message), i++) { + xmlnode *sender_node, *subject_node; + const char *from, *tid; + char *subject; + subject_node = xmlnode_get_child(message, "subject"); sender_node = xmlnode_get_child(message, "senders"); sender_node = xmlnode_get_child(sender_node, "sender"); @@ -727,9 +731,9 @@ } void -jabber_gmail_poke(JabberStream *js, xmlnode *packet) +jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *new_mail) { - const char *type; xmlnode *query; JabberIq *iq; @@ -737,11 +741,8 @@ if (!purple_account_get_check_mail(js->gc->account)) return; - type = xmlnode_get_attrib(packet, "type"); - - /* Is this an initial incoming mail notification? If so, send a request for more info */ - if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail")) + if (type != JABBER_IQ_SET) return; purple_debug(PURPLE_DEBUG_MISC, "jabber", @@ -1159,48 +1160,77 @@ } static void -jabber_google_jingle_info_cb(JabberStream *js, xmlnode *result, - gpointer nullus) -{ - if (result) { - const xmlnode *query = - xmlnode_get_child_with_namespace(result, "query", - GOOGLE_JINGLE_INFO_NAMESPACE); +jabber_google_jingle_info_common(JabberStream *js, const char *from, + JabberIqType type, xmlnode *query) +{ + const xmlnode *stun = xmlnode_get_child(query, "stun"); + gchar *my_bare_jid; - if (query) { - const xmlnode *stun = xmlnode_get_child(query, "stun"); + /* + * Make sure that random people aren't sending us STUN servers. Per + * http://code.google.com/apis/talk/jep_extensions/jingleinfo.html, these + * stanzas are stamped from our bare JID. + */ + if (from) { + my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); + if (!purple_strequal(from, my_bare_jid)) { + purple_debug_warning("jabber", "got google:jingleinfo with invalid from (%s)\n", + from); + g_free(my_bare_jid); + return; + } - purple_debug_info("jabber", "got google:jingleinfo\n"); - - if (stun) { - xmlnode *server = xmlnode_get_child(stun, "server"); + g_free(my_bare_jid); + } - if (server) { - const gchar *host = xmlnode_get_attrib(server, "host"); - const gchar *udp = xmlnode_get_attrib(server, "udp"); + if (type == JABBER_IQ_ERROR || type == JABBER_IQ_GET) + return; + + purple_debug_info("jabber", "got google:jingleinfo\n"); + + if (stun) { + xmlnode *server = xmlnode_get_child(stun, "server"); - if (host && udp) { - int port = atoi(udp); - /* if there, would already be an ongoing query, - cancel it */ - if (js->stun_query) - purple_dnsquery_destroy(js->stun_query); + if (server) { + const gchar *host = xmlnode_get_attrib(server, "host"); + const gchar *udp = xmlnode_get_attrib(server, "udp"); - js->stun_query = purple_dnsquery_a(host, port, - jabber_google_stun_lookup_cb, js); - } - } + if (host && udp) { + int port = atoi(udp); + /* if there, would already be an ongoing query, + cancel it */ + if (js->stun_query) + purple_dnsquery_destroy(js->stun_query); + + js->stun_query = purple_dnsquery_a(host, port, + jabber_google_stun_lookup_cb, js); } - /* should perhaps handle relays later on, or maybe wait until - Google supports a common standard... */ } } + /* should perhaps handle relays later on, or maybe wait until + Google supports a common standard... */ +} + +static void +jabber_google_jingle_info_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", + GOOGLE_JINGLE_INFO_NAMESPACE); + + if (query) + jabber_google_jingle_info_common(js, from, type, query); + else + purple_debug_warning("jabber", "Got invalid google:jingleinfo\n"); } void -jabber_google_handle_jingle_info(JabberStream *js, xmlnode *packet) +jabber_google_handle_jingle_info(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child) { - jabber_google_jingle_info_cb(js, packet, NULL); + jabber_google_jingle_info_common(js, from, type, child); } void diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/google.h Sat Apr 04 07:08:33 2009 +0000 @@ -31,7 +31,8 @@ #define GOOGLE_JINGLE_INFO_NAMESPACE "google:jingleinfo" void jabber_gmail_init(JabberStream *js); -void jabber_gmail_poke(JabberStream *js, xmlnode *node); +void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *new_mail); void jabber_google_roster_init(JabberStream *js); void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item); @@ -52,7 +53,9 @@ gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type); void jabber_google_session_parse(JabberStream *js, xmlnode *node); -void jabber_google_handle_jingle_info(JabberStream *js, xmlnode *packet); +void jabber_google_handle_jingle_info(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child); void jabber_google_send_jingle_info(JabberStream *js); #endif /* _PURPLE_GOOGLE_H_ */ diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/ibb.c --- a/libpurple/protocols/jabber/ibb.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/ibb.c Sat Apr 04 07:08:33 2009 +0000 @@ -46,12 +46,10 @@ } JabberIBBSession * -jabber_ibb_session_create_from_xmlnode(JabberStream *js, xmlnode *packet, - gpointer user_data) +jabber_ibb_session_create_from_xmlnode(JabberStream *js, const char *from, + const char *id, xmlnode *open, gpointer user_data) { JabberIBBSession *sess = NULL; - xmlnode *open = xmlnode_get_child_with_namespace(packet, "open", - XEP_0047_NAMESPACE); const gchar *sid = xmlnode_get_attrib(open, "sid"); const gchar *block_size = xmlnode_get_attrib(open, "block-size"); @@ -66,9 +64,8 @@ return NULL; } - sess = jabber_ibb_session_create(js, sid, - xmlnode_get_attrib(packet, "from"), user_data); - sess->id = g_strdup(xmlnode_get_attrib(packet, "id")); + sess = jabber_ibb_session_create(js, sid, from, user_data); + sess->id = g_strdup(id); sess->block_size = atoi(block_size); /* if we create a session from an incoming request, it means the session is immediatly open... */ @@ -198,11 +195,13 @@ } static void -jabber_ibb_session_opened_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_ibb_session_opened_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIBBSession *sess = (JabberIBBSession *) data; - if (strcmp(xmlnode_get_attrib(packet, "type"), "error") == 0) { + if (type == JABBER_IQ_ERROR) { sess->state = JABBER_IBB_SESSION_ERROR; } else { sess->state = JABBER_IBB_SESSION_OPENED; @@ -274,10 +273,11 @@ } static void -jabber_ibb_session_send_acknowledge_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_ibb_session_send_acknowledge_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIBBSession *sess = (JabberIBBSession *) data; - xmlnode *error = xmlnode_get_child(packet, "error"); if (sess) { /* reset callback */ @@ -286,7 +286,7 @@ sess->last_iq_id = NULL; } - if (error) { + if (type == JABBER_IQ_ERROR) { jabber_ibb_session_close(sess); sess->state = JABBER_IBB_SESSION_ERROR; @@ -351,7 +351,7 @@ } static void -jabber_ibb_send_error_response(JabberStream *js, xmlnode *packet) +jabber_ibb_send_error_response(JabberStream *js, const char *to, const char *id) { JabberIq *result = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode *error = xmlnode_new("error"); @@ -361,9 +361,8 @@ "urn:ietf:params:xml:ns:xmpp-stanzas"); xmlnode_set_attrib(error, "code", "440"); xmlnode_set_attrib(error, "type", "cancel"); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); + jabber_iq_set_id(result, id); + xmlnode_set_attrib(result->node, "to", to); xmlnode_insert_child(error, item_not_found); xmlnode_insert_child(result->node, error); @@ -371,20 +370,17 @@ } void -jabber_ibb_parse(JabberStream *js, xmlnode *packet) +jabber_ibb_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *child) { - xmlnode *data = xmlnode_get_child_with_namespace(packet, "data", - XEP_0047_NAMESPACE); - xmlnode *close = xmlnode_get_child_with_namespace(packet, "close", - XEP_0047_NAMESPACE); - xmlnode *open = xmlnode_get_child_with_namespace(packet, "open", - XEP_0047_NAMESPACE); - const gchar *sid = - data ? xmlnode_get_attrib(data, "sid") : - close ? xmlnode_get_attrib(close, "sid") : NULL; + const char *name = child->name; + gboolean data = g_str_equal(name, "data"); + gboolean close = g_str_equal(name, "close"); + gboolean open = g_str_equal(name, "open"); + const gchar *sid = (data || close) ? + xmlnode_get_attrib(child, "sid") : NULL; JabberIBBSession *sess = sid ? g_hash_table_lookup(jabber_ibb_sessions, sid) : NULL; - const gchar *who = xmlnode_get_attrib(packet, "from"); if (sess) { @@ -394,7 +390,7 @@ purple_debug_error("jabber", "Got IBB iq from wrong JID, ignoring\n"); } else if (data) { - const gchar *seq_attr = xmlnode_get_attrib(data, "seq"); + const gchar *seq_attr = xmlnode_get_attrib(child, "seq"); guint16 seq = (seq_attr ? atoi(seq_attr) : 0); /* reject the data, and set the session in error if we get an @@ -403,12 +399,11 @@ /* sequence # is the expected... */ JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); + jabber_iq_set_id(result, id); + xmlnode_set_attrib(result->node, "to", who); if (sess->data_received_cb) { - gchar *base64 = xmlnode_get_data(data); + gchar *base64 = xmlnode_get_data(child); gsize size; gpointer rawdata = purple_base64_decode(base64, &size); @@ -475,20 +470,19 @@ iterator = g_list_next(iterator)) { JabberIBBOpenHandler *handler = iterator->data; - if (handler(js, packet)) { + if (handler(js, who, id, child)) { result = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); + xmlnode_set_attrib(result->node, "to", who); + jabber_iq_set_id(result, id); jabber_iq_send(result); return; } } /* no open callback returned success, reject */ - jabber_ibb_send_error_response(js, packet); + jabber_ibb_send_error_response(js, who, id); } else { /* send error reply */ - jabber_ibb_send_error_response(js, packet); + jabber_ibb_send_error_response(js, who, id); } } diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/ibb.h --- a/libpurple/protocols/jabber/ibb.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/ibb.h Sat Apr 04 07:08:33 2009 +0000 @@ -32,7 +32,8 @@ typedef void (JabberIBBErrorCallback)(JabberIBBSession *); typedef void (JabberIBBSentCallback)(JabberIBBSession *); -typedef gboolean (JabberIBBOpenHandler)(JabberStream *js, xmlnode *packet); +typedef gboolean (JabberIBBOpenHandler)(JabberStream *js, const char *from, + const char *id, xmlnode *open); typedef enum { JABBER_IBB_SESSION_NOT_OPENED, @@ -71,7 +72,7 @@ JabberIBBSession *jabber_ibb_session_create(JabberStream *js, const gchar *sid, const gchar *who, gpointer user_data); JabberIBBSession *jabber_ibb_session_create_from_xmlnode(JabberStream *js, - xmlnode *packet, gpointer user_data); + const gchar *from, const gchar *id, xmlnode *open, gpointer user_data); void jabber_ibb_session_destroy(JabberIBBSession *sess); @@ -107,7 +108,8 @@ gpointer jabber_ibb_session_get_user_data(JabberIBBSession *sess); /* handle incoming packet */ -void jabber_ibb_parse(JabberStream *js, xmlnode *packet); +void jabber_ibb_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *child); /* add a handler for open session */ void jabber_ibb_register_open_handler(JabberIBBOpenHandler *cb); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Sat Apr 04 07:08:33 2009 +0000 @@ -144,23 +144,19 @@ g_free(iq); } -static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_last_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet) { JabberIq *iq; - const char *type; - const char *from; - const char *id; xmlnode *query; char *idle_time; - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); query = xmlnode_get_child(iq->node, "query"); @@ -172,88 +168,67 @@ } } -static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_time_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child) { - const char *type, *from, *id, *xmlns; + const char *xmlns; JabberIq *iq; - xmlnode *query; time_t now_t; + struct tm now_local; + struct tm now_utc; struct tm *now; time(&now_t); now = localtime(&now_t); - - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); + memcpy(&now_local, now, sizeof(struct tm)); + now = gmtime(&now_t); + memcpy(&now_utc, now, sizeof(struct tm)); - /* we're gonna throw this away in a moment, but we need it - * to get the xmlns, so we can figure out if this is - * jabber:iq:time or urn:xmpp:time */ - query = xmlnode_get_child(packet, "query"); - xmlns = xmlnode_get_namespace(query); + xmlns = xmlnode_get_namespace(child); - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { xmlnode *utc; - const char *date; + const char *date, *tz, *display; - iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, xmlns); + iq = jabber_iq_new(js, JABBER_IQ_RESULT); jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); - - query = xmlnode_get_child(iq->node, "query"); + if (from) + xmlnode_set_attrib(iq->node, "to", from); - date = purple_utf8_strftime("%Y%m%dT%T", now); - utc = xmlnode_new_child(query, "utc"); - xmlnode_insert_data(utc, date, -1); + child = xmlnode_new_child(iq->node, child->name); + xmlnode_set_namespace(child, xmlns); + utc = xmlnode_new_child(child, "utc"); if(!strcmp("urn:xmpp:time", xmlns)) { - xmlnode_insert_data(utc, "Z", 1); /* of COURSE the thing that is the same is different */ + tz = purple_get_tzoff_str(&now_local, TRUE); + xmlnode_insert_data(xmlnode_new_child(child, "tzo"), tz, -1); - date = purple_get_tzoff_str(now, TRUE); - xmlnode_insert_data(xmlnode_new_child(query, "tzo"), date, -1); + date = purple_utf8_strftime("%FT%TZ", &now_utc); + xmlnode_insert_data(utc, date, -1); } else { /* jabber:iq:time */ - date = purple_utf8_strftime("%Z", now); - xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1); + tz = purple_utf8_strftime("%Z", &now_local); + xmlnode_insert_data(xmlnode_new_child(child, "tz"), tz, -1); - date = purple_utf8_strftime("%d %b %Y %T", now); - xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); + date = purple_utf8_strftime("%Y%m%dT%T", &now_utc); + xmlnode_insert_data(utc, date, -1); + + display = purple_utf8_strftime("%d %b %Y %T", &now_local); + xmlnode_insert_data(xmlnode_new_child(child, "display"), display, -1); } jabber_iq_send(iq); } } -static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet) -{ - const char *type, *id, *from; - JabberIq *iq; - - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - - if(type && !strcmp(type, "get")) { - iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping"); - - jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); - - jabber_iq_send(iq); - } else { - /* XXX: error */ - } -} - -static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_version_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet) { JabberIq *iq; - const char *type, *from, *id; xmlnode *query; - type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { GHashTable *ui_info; const char *ui_name = NULL, *ui_version = NULL; #if 0 @@ -266,11 +241,10 @@ osinfo.machine); } #endif - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); jabber_iq_set_id(iq, id); query = xmlnode_get_child(iq->node, "query"); @@ -311,33 +285,56 @@ void jabber_iq_parse(JabberStream *js, xmlnode *packet) { JabberCallbackData *jcd; - xmlnode *query, *error, *x; + xmlnode *child, *error, *x; const char *xmlns; - const char *type, *id, *from; - JabberIqHandler *jih; + const char *iq_type, *id, *from; + JabberIqType type = JABBER_IQ_NONE; - query = xmlnode_get_child(packet, "query"); - type = xmlnode_get_attrib(packet, "type"); + /* + * child will be either the first tag child or NULL if there is no child. + * Historically, we used just the 'query' subchild, but newer XEPs use + * differently named children. Grabbing the first child is (for the time + * being) sufficient. + */ + for (child = packet->child; child; child = child->next) { + if (child->type == XMLNODE_TYPE_TAG) + break; + } + + iq_type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); - if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set") - || !strcmp(type, "result") || !strcmp(type, "error"))) { + if (iq_type) { + if (!strcmp(iq_type, "get")) + type = JABBER_IQ_GET; + else if (!strcmp(iq_type, "set")) + type = JABBER_IQ_SET; + else if (!strcmp(iq_type, "result")) + type = JABBER_IQ_RESULT; + else if (!strcmp(iq_type, "error")) + type = JABBER_IQ_ERROR; + } + + if (type == JABBER_IQ_NONE) { purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", - type ? type : "(null)"); + iq_type ? iq_type : "(null)"); return; } /* All IQs must have an ID, so send an error for a set/get that doesn't */ if(!id || !*id) { - if(!strcmp(type, "set") || !strcmp(type, "get")) { + if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); - xmlnode_set_attrib(iq->node, "to", from); - xmlnode_remove_attrib(iq->node, "from"); + if (from) { + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_remove_attrib(iq->node, "from"); + } + xmlnode_set_attrib(iq->node, "type", "error"); /* This id is clearly not useful, but we must put something there for a valid stanza */ iq->id = jabber_get_next_id(js); @@ -349,79 +346,46 @@ jabber_iq_send(iq); } else - purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type); + purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", + iq_type); return; } /* First, lets see if a special callback got registered */ - - if(!strcmp(type, "result") || !strcmp(type, "error")) { - if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { - jcd->callback(js, packet, jcd->data); + if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) { + if((jcd = g_hash_table_lookup(js->iq_callbacks, id))) { + jcd->callback(js, from, type, id, packet, jcd->data); jabber_iq_remove_callback_by_id(js, id); return; } } /* Apparently not, so lets see if we have a pre-defined handler */ + if(child && (xmlns = xmlnode_get_namespace(child))) { + char *key = g_strdup_printf("%s %s", child->name, xmlns); + JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key); + g_free(key); - if(query && (xmlns = xmlnode_get_namespace(query))) { - if((jih = g_hash_table_lookup(iq_handlers, xmlns))) { - jih(js, packet); + if(jih) { + jih(js, from, type, id, child); return; } } -#ifdef USE_VV - if (xmlnode_get_child_with_namespace(packet, "session", "http://www.google.com/session")) { - jabber_google_session_parse(js, packet); - return; - } -#endif - - if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { - jabber_si_parse(js, packet); - return; - } - - if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { - jabber_gmail_poke(js, packet); - return; - } - purple_debug_info("jabber", "jabber_iq_parse\n"); - if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { - jabber_ping_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) { - jabber_data_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "data", XEP_0047_NAMESPACE) - || xmlnode_get_child_with_namespace(packet, "close", XEP_0047_NAMESPACE) - || xmlnode_get_child_with_namespace(packet, "open", XEP_0047_NAMESPACE)) { - jabber_ibb_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "jingle", JINGLE)) { - jingle_parse(js, packet); - return; - } - /* If we get here, send the default error reply mandated by XMPP-CORE */ - if(!strcmp(type, "set") || !strcmp(type, "get")) { + if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); - xmlnode_set_attrib(iq->node, "to", from); - xmlnode_remove_attrib(iq->node, "from"); + if (from) { + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_remove_attrib(iq->node, "from"); + } + xmlnode_set_attrib(iq->node, "type", "error"); error = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(error, "type", "cancel"); @@ -433,30 +397,43 @@ } } -void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *handlerfunc) +void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc) { - g_hash_table_replace(iq_handlers, g_strdup(xmlns), handlerfunc); + /* + * This is valid because nodes nor namespaces cannot have spaces in them + * (see http://www.w3.org/TR/2006/REC-xml-20060816/ and + * http://www.w3.org/TR/REC-xml-names/) + */ + char *key = g_strdup_printf("%s %s", node, xmlns); + g_hash_table_replace(iq_handlers, key, handlerfunc); } void jabber_iq_init(void) { iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - jabber_iq_register_handler("jabber:iq:roster", jabber_roster_parse); - jabber_iq_register_handler("jabber:iq:oob", jabber_oob_parse); - jabber_iq_register_handler("http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse); - jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse); - jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse); - jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse); - jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse); - jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse); - jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse); - jabber_iq_register_handler("jabber:iq:register", jabber_register_parse); - jabber_iq_register_handler("urn:xmpp:ping", urn_xmpp_ping_parse); - jabber_iq_register_handler(JINGLE, jingle_parse); + jabber_iq_register_handler("mailbox", "google:mail:notify", jabber_gmail_poke); + jabber_iq_register_handler("new-mail", "google:mail:notify", jabber_gmail_poke); + jabber_iq_register_handler("query", "http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse); + jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#info", jabber_disco_info_parse); + jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#items", jabber_disco_items_parse); + jabber_iq_register_handler("si", "http://jabber.org/protocol/si", jabber_si_parse); + jabber_iq_register_handler("query", "jabber:iq:last", jabber_iq_last_parse); + jabber_iq_register_handler("query", "jabber:iq:oob", jabber_oob_parse); + jabber_iq_register_handler("query", "jabber:iq:register", jabber_register_parse); + jabber_iq_register_handler("query", "jabber:iq:roster", jabber_roster_parse); + jabber_iq_register_handler("query", "jabber:iq:time", jabber_iq_time_parse); + jabber_iq_register_handler("query", "jabber:iq:version", jabber_iq_version_parse); + jabber_iq_register_handler("data", XEP_0231_NAMESPACE, jabber_data_parse); + jabber_iq_register_handler("ping", "urn:xmpp:ping", jabber_ping_parse); + jabber_iq_register_handler("time", "urn:xmpp:time", jabber_iq_time_parse); - /* handle Google jingleinfo */ - jabber_iq_register_handler(GOOGLE_JINGLE_INFO_NAMESPACE, + jabber_iq_register_handler("data", XEP_0047_NAMESPACE, jabber_ibb_parse); + jabber_iq_register_handler("close", XEP_0047_NAMESPACE, jabber_ibb_parse); + jabber_iq_register_handler("open", XEP_0047_NAMESPACE, jabber_ibb_parse); + + jabber_iq_register_handler("jingle", JINGLE, jingle_parse); + jabber_iq_register_handler("query", GOOGLE_JINGLE_INFO_NAMESPACE, jabber_google_handle_jingle_info); } @@ -465,4 +442,3 @@ g_hash_table_destroy(iq_handlers); iq_handlers = NULL; } - diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/iq.h --- a/libpurple/protocols/jabber/iq.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/iq.h Sat Apr 04 07:08:33 2009 +0000 @@ -22,10 +22,6 @@ #ifndef _PURPLE_JABBER_IQ_H_ #define _PURPLE_JABBER_IQ_H_ -#include "jabber.h" - -typedef struct _JabberIq JabberIq; - typedef enum { JABBER_IQ_SET, JABBER_IQ_GET, @@ -34,9 +30,17 @@ JABBER_IQ_NONE } JabberIqType; -typedef void (JabberIqHandler)(JabberStream *js, xmlnode *packet); +#include "jabber.h" + +typedef struct _JabberIq JabberIq; -typedef void (JabberIqCallback)(JabberStream *js, xmlnode *packet, gpointer data); +typedef void (JabberIqHandler)(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child); + +typedef void (JabberIqCallback)(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); struct _JabberIq { JabberIqType type; @@ -65,6 +69,7 @@ void jabber_iq_init(void); void jabber_iq_uninit(void); -void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *func); +void jabber_iq_register_handler(const char *node, const char *xmlns, + JabberIqHandler *func); #endif /* _PURPLE_JABBER_IQ_H_ */ diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Apr 04 07:08:33 2009 +0000 @@ -87,10 +87,11 @@ } static void -jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_session_initialized_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); if(js->unregistration) jabber_unregister_account_cb(js); @@ -114,13 +115,13 @@ jabber_iq_send(iq); } -static void jabber_bind_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +static void jabber_bind_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); xmlnode *bind; - if(type && !strcmp(type, "result") && + if (type == JABBER_IQ_RESULT && (bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) { xmlnode *jid; char *full_jid; @@ -448,13 +449,7 @@ g_free(txt); } -static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) -{ - purple_timeout_remove(js->keepalive_timeout); - js->keepalive_timeout = -1; -} - -static gboolean jabber_pong_timeout(PurpleConnection *gc) +static gboolean jabber_keepalive_timeout(PurpleConnection *gc) { JabberStream *js = gc->proto_data; purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, @@ -468,14 +463,9 @@ JabberStream *js = gc->proto_data; if (js->keepalive_timeout == -1) { - JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET); - - xmlnode *ping = xmlnode_new_child(iq->node, "ping"); - xmlnode_set_namespace(ping, "urn:xmpp:ping"); - - js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc); - jabber_iq_set_callback(iq, jabber_pong_cb, NULL); - jabber_iq_send(iq); + jabber_ping_jid(js, NULL); + js->keepalive_timeout = purple_timeout_add_seconds(120, + (GSourceFunc)(jabber_keepalive_timeout), gc); } } @@ -802,14 +792,15 @@ } static void -jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_registration_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if(js->registration) { buf = g_strdup_printf(_("Registration of %s@%s successful"), js->user->node, js->user->domain); @@ -837,13 +828,14 @@ } g_free(to); if(js->registration) - jabber_connection_schedule_close(js); + jabber_connection_schedule_close(js); } static void -jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_unregistration_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; @@ -851,7 +843,7 @@ * the server, so there should always be a 'to' address. */ g_return_if_fail(to != NULL); - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { buf = g_strdup_printf(_("Registration from %s successfully removed"), to); purple_notify_info(NULL, _("Unregistration Successful"), @@ -1000,31 +992,30 @@ jabber_iq_send(iq); } -void jabber_register_parse(JabberStream *js, xmlnode *packet) +void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *query) { PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type; - const char *from; PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; - xmlnode *query, *x, *y; + xmlnode *x, *y; char *instructions; JabberRegisterCBData *cbdata; gboolean registered = FALSE; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) + if (type != JABBER_IQ_RESULT) return; - from = xmlnode_get_attrib(packet, "from"); + if (!from) + from = js->serverFQDN; + g_return_if_fail(from != NULL); if(js->registration) { /* get rid of the login thingy */ purple_connection_set_state(js->gc, PURPLE_CONNECTED); } - query = xmlnode_get_child(packet, "query"); - if(xmlnode_get_child(query, "registered")) { registered = TRUE; @@ -1262,10 +1253,14 @@ } } -static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_unregister_account_iq_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type = xmlnode_get_attrib(packet,"type"); - if(!strcmp(type,"error")) { + + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error unregistering account"), @@ -1273,7 +1268,7 @@ g_free(msg); if(js->unregistration_cb) js->unregistration_cb(account, FALSE, js->unregistration_user_data); - } else if(!strcmp(type,"result")) { + } else { purple_notify_info(js->gc, _("Account successfully unregistered"), _("Account successfully unregistered"), NULL); if(js->unregistration_cb) @@ -1514,7 +1509,9 @@ js->idle = idle ? time(NULL) - idle : idle; } -static void jabber_blocklist_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_blocklist_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *blocklist, *item; PurpleAccount *account; @@ -1938,14 +1935,11 @@ } static void -jabber_password_change_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +jabber_password_change_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type; - - type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), _("Your password has been changed.")); @@ -2477,10 +2471,16 @@ static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { + PurpleAccount *account; + PurpleConnection *pc; + if(!args || !args[0]) return PURPLE_CMD_RET_FAILED; - if(!jabber_ping_jid(conv, args[0])) { + account = purple_conversation_get_account(conv); + pc = purple_account_get_connection(account); + + if(!jabber_ping_jid(purple_connection_get_protocol_data(pc), args[0])) { *error = g_strdup_printf(_("Unable to ping user %s"), args[0]); return PURPLE_CMD_RET_FAILED; } diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Sat Apr 04 07:08:33 2009 +0000 @@ -60,6 +60,7 @@ #include "sslconn.h" #include "dnsquery.h" +#include "iq.h" #include "jutil.h" #include "xmlnode.h" #include "buddy.h" @@ -281,7 +282,8 @@ void jabber_stream_set_state(JabberStream *js, JabberStreamState state); -void jabber_register_parse(JabberStream *js, xmlnode *packet); +void jabber_register_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_register_start(JabberStream *js); char *jabber_get_next_id(JabberStream *js); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/jingle/jingle.c --- a/libpurple/protocols/jabber/jingle/jingle.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.c Sat Apr 04 07:08:33 2009 +0000 @@ -359,28 +359,21 @@ } void -jingle_parse(JabberStream *js, xmlnode *packet) +jingle_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *jingle) { - const gchar *type = xmlnode_get_attrib(packet, "type"); - xmlnode *jingle; const gchar *action; const gchar *sid; JingleActionType action_type; JingleSession *session; - if (!type || strcmp(type, "set")) { - /* send iq error here */ - return; - } - - /* is this a Jingle package? */ - if (!(jingle = xmlnode_get_child(packet, "jingle"))) { - /* send iq error here */ + if (type != JABBER_IQ_SET) { + /* TODO: send iq error here */ return; } if (!(action = xmlnode_get_attrib(jingle, "action"))) { - /* send iq error here */ + /* TODO: send iq error here */ return; } @@ -409,9 +402,10 @@ /* send iq error */ return; } else { - session = jingle_session_create(js, sid, - xmlnode_get_attrib(packet, "to"), - xmlnode_get_attrib(packet, "from"), FALSE); + char *own_jid = g_strdup_printf("%s@%s/%s", js->user->node, + js->user->domain, js->user->resource); + session = jingle_session_create(js, sid, own_jid, from, FALSE); + g_free(own_jid); } } diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/jingle/jingle.h --- a/libpurple/protocols/jabber/jingle/jingle.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.h Sat Apr 04 07:08:33 2009 +0000 @@ -69,7 +69,8 @@ GType jingle_get_type(const gchar *type); -void jingle_parse(JabberStream *js, xmlnode *packet); +void jingle_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *child); void jingle_terminate_sessions(JabberStream *js); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/jingle/rtp.c --- a/libpurple/protocols/jabber/jingle/rtp.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.c Sat Apr 04 07:08:33 2009 +0000 @@ -438,12 +438,13 @@ } static void -jingle_rtp_initiate_ack_cb(JabberStream *js, xmlnode *packet, gpointer data) +jingle_rtp_initiate_ack_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JingleSession *session = data; - if (!strcmp(xmlnode_get_attrib(packet, "type"), "error") || - xmlnode_get_child(packet, "error")) { + if (type == JABBER_IQ_ERROR || xmlnode_get_child(packet, "error")) { purple_media_end(jingle_rtp_get_media(session), NULL, NULL); g_object_unref(session); return; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Sat Apr 04 07:08:33 2009 +0000 @@ -477,7 +477,9 @@ } JabberDataRef; static void -jabber_message_get_data_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_message_get_data_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberDataRef *ref = (JabberDataRef *) data; PurpleConversation *conv = ref->conv; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/oob.c --- a/libpurple/protocols/jabber/oob.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/oob.c Sat Apr 04 07:08:33 2009 +0000 @@ -187,18 +187,18 @@ jabber_oob_xfer_recv_error(xfer, "404"); } -void jabber_oob_parse(JabberStream *js, xmlnode *packet) { +void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *querynode) { JabberOOBXfer *jox; PurpleXfer *xfer; char *filename; char *url; - const char *type; - xmlnode *querynode, *urlnode; + xmlnode *urlnode; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set")) + if(type != JABBER_IQ_SET) return; - if(!(querynode = xmlnode_get_child(packet, "query"))) + if(!from) return; if(!(urlnode = xmlnode_get_child(querynode, "url"))) @@ -211,10 +211,9 @@ g_free(url); jox->js = js; jox->headers = g_string_new(""); - jox->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jox->iq_id = g_strdup(id); - xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, - xmlnode_get_attrib(packet, "from")); + xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); if (xfer) { xfer->data = jox; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/oob.h --- a/libpurple/protocols/jabber/oob.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/oob.h Sat Apr 04 07:08:33 2009 +0000 @@ -22,6 +22,9 @@ #ifndef _PURPLE_JABBER_OOB_H_ #define _PURPLE_JABBER_OOB_H_ -void jabber_oob_parse(JabberStream *js, xmlnode *packet); +#include "jabber.h" + +void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *querynode); #endif /* _PURPLE_JABBER_OOB_H_ */ diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/pep.c --- a/libpurple/protocols/jabber/pep.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/pep.c Sat Apr 04 07:08:33 2009 +0000 @@ -52,8 +52,11 @@ g_hash_table_replace(pep_handlers, g_strdup(xmlns), handlerfunc); } -static void do_pep_iq_request_item_callback(JabberStream *js, xmlnode *packet, gpointer data) { - const char *from = xmlnode_get_attrib(packet,"from"); +static void +do_pep_iq_request_item_callback(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub"); xmlnode *items = NULL; JabberPEPHandler *cb = data; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/ping.c --- a/libpurple/protocols/jabber/ping.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/ping.c Sat Apr 04 07:08:33 2009 +0000 @@ -23,50 +23,63 @@ #include "internal.h" #include "debug.h" -#include "xmlnode.h" #include "jabber.h" #include "ping.h" #include "iq.h" -void -jabber_ping_parse(JabberStream *js, xmlnode *packet) +static void jabber_keepalive_pong_cb(JabberStream *js) { - JabberIq *iq; - - purple_debug_info("jabber", "jabber_ping_parse\n"); - - iq = jabber_iq_new(js, JABBER_IQ_RESULT); - - xmlnode_set_attrib(iq->node, "to", xmlnode_get_attrib(packet, "from") ); - - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); - - jabber_iq_send(iq); + purple_timeout_remove(js->keepalive_timeout); + js->keepalive_timeout = -1; } -static void jabber_ping_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +void +jabber_ping_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *ping) { - const char *type = xmlnode_get_attrib(packet, "type"); + if (type == JABBER_IQ_GET) { + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_RESULT); + + if (from) + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_set_attrib(iq->node, "id", id); + + jabber_iq_send(iq); + } else if (type == JABBER_IQ_SET) { + /* XXX: error */ + } +} - purple_debug_info("jabber", "jabber_ping_result_cb\n"); - if(type && !strcmp(type, "result")) { +static void jabber_ping_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + char *own_bare_jid = g_strdup_printf("%s@%s", js->user->node, + js->user->domain); + + if (!from || !strcmp(from, own_bare_jid)) { + /* If the pong is from our bare JID, treat it as a return from the + * keepalive functions */ + jabber_keepalive_pong_cb(js); + } + g_free(own_bare_jid); + + if (type == JABBER_IQ_RESULT) { purple_debug_info("jabber", "PONG!\n"); } else { purple_debug_info("jabber", "(not supported)\n"); } } -gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid) +gboolean jabber_ping_jid(JabberStream *js, const char *jid) { JabberIq *iq; xmlnode *ping; - purple_debug_info("jabber", "jabber_ping_jid\n"); - - iq = jabber_iq_new(conv->account->gc->proto_data, JABBER_IQ_GET); - xmlnode_set_attrib(iq->node, "to", jid); + iq = jabber_iq_new(js, JABBER_IQ_GET); + if (jid) + xmlnode_set_attrib(iq->node, "to", jid); ping = xmlnode_new_child(iq->node, "ping"); xmlnode_set_namespace(ping, "urn:xmpp:ping"); @@ -74,7 +87,5 @@ jabber_iq_set_callback(iq, jabber_ping_result_cb, NULL); jabber_iq_send(iq); - - return TRUE; } diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/ping.h --- a/libpurple/protocols/jabber/ping.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Sat Apr 04 07:08:33 2009 +0000 @@ -23,13 +23,11 @@ #define _PURPLE_JABBER_PING_H_ #include "jabber.h" -#include "conversation.h" +#include "iq.h" +#include "xmlnode.h" -void jabber_ping_parse(JabberStream *js, - xmlnode *packet); - - -gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid); - +void jabber_ping_parse(JabberStream *js, const char *from, + JabberIqType, const char *id, xmlnode *child); +gboolean jabber_ping_jid(JabberStream *js, const char *jid); #endif /* _PURPLE_JABBER_PING_H_ */ diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Sat Apr 04 07:08:33 2009 +0000 @@ -330,14 +330,16 @@ g_free(jap); } -static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah) +static void +jabber_vcard_parse_avatar(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer blah) { JabberBuddy *jb = NULL; xmlnode *vcard, *photo, *binval; char *text; guchar *data; gsize size; - const char *from = xmlnode_get_attrib(packet, "from"); if(!from) return; diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/roster.c --- a/libpurple/protocols/jabber/roster.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/roster.c Sat Apr 04 07:08:33 2009 +0000 @@ -145,10 +145,10 @@ g_slist_free(buddies); } -void jabber_roster_parse(JabberStream *js, xmlnode *packet) +void jabber_roster_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query) { - xmlnode *query, *item, *group; - const char *from = xmlnode_get_attrib(packet, "from"); + xmlnode *item, *group; if(from) { char *from_norm; @@ -169,10 +169,6 @@ return; } - query = xmlnode_get_child(packet, "query"); - if(!query) - return; - js->currently_parsing_roster_push = TRUE; for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/roster.h --- a/libpurple/protocols/jabber/roster.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/roster.h Sat Apr 04 07:08:33 2009 +0000 @@ -26,7 +26,8 @@ void jabber_roster_request(JabberStream *js); -void jabber_roster_parse(JabberStream *js, xmlnode *packet); +void jabber_roster_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/si.c Sat Apr 04 07:08:33 2009 +0000 @@ -311,20 +311,18 @@ } } -void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet) +void jabber_bytestreams_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query) { PurpleXfer *xfer; JabberSIXfer *jsx; - xmlnode *query, *streamhost; - const char *sid, *from, *type; + xmlnode *streamhost; + const char *sid; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set")) + if(type != JABBER_IQ_SET) return; - if(!(from = xmlnode_get_attrib(packet, "from"))) - return; - - if(!(query = xmlnode_get_child(packet, "query"))) + if(!from) return; if(!(sid = xmlnode_get_attrib(query, "sid"))) @@ -340,7 +338,7 @@ if(jsx->iq_id) g_free(jsx->iq_id); - jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jsx->iq_id = g_strdup(id); for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost; streamhost = xmlnode_get_next_twin(streamhost)) { @@ -685,13 +683,14 @@ } static void -jabber_si_connect_proxy_cb(JabberStream *js, xmlnode *packet, - gpointer data) +jabber_si_connect_proxy_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleXfer *xfer = data; JabberSIXfer *jsx; xmlnode *query, *streamhost_used; - const char *from, *type, *jid; + const char *jid; GList *matched; /* TODO: This need to send errors if we don't see what we're looking for */ @@ -708,37 +707,34 @@ jsx = xfer->data; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { - purple_debug_info("jabber", - "jabber_si_xfer_connect_proxy_cb: type = %s\n", - type); - if (type && !strcmp(type, "error")) { - /* if IBB is available, open IBB session */ - purple_debug_info("jabber", - "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n", - jsx->stream_method); - if (jsx->stream_method & STREAM_METHOD_IBB) { - purple_debug_info("jabber", "IBB is possible, try it\n"); - /* if we are the sender and haven't already opened an IBB - session, do so now (we might already have failed to open - the bytestream proxy ourselves when receiving this */ - if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND - && !jsx->ibb_session) { - jabber_si_xfer_ibb_send_init(js, xfer); - } else { - jsx->ibb_timeout_handle = purple_timeout_add_seconds(30, - jabber_si_bytestreams_ibb_timeout_cb, xfer); - } - /* if we are receiver, just wait for IBB open stanza, callback - is already set up */ + if(type != JABBER_IQ_RESULT) { + purple_debug_info("jabber", + "jabber_si_xfer_connect_proxy_cb: type = error\n"); + /* if IBB is available, open IBB session */ + purple_debug_info("jabber", + "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n", + jsx->stream_method); + if (jsx->stream_method & STREAM_METHOD_IBB) { + purple_debug_info("jabber", "IBB is possible, try it\n"); + /* if we are the sender and haven't already opened an IBB + session, do so now (we might already have failed to open + the bytestream proxy ourselves when receiving this */ + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND + && !jsx->ibb_session) { + jabber_si_xfer_ibb_send_init(js, xfer); } else { - purple_xfer_cancel_remote(xfer); + jsx->ibb_timeout_handle = purple_timeout_add_seconds(30, + jabber_si_bytestreams_ibb_timeout_cb, xfer); } + /* if we are receiver, just wait for IBB open stanza, callback + is already set up */ + } else { + purple_xfer_cancel_remote(xfer); } return; } - if(!(from = xmlnode_get_attrib(packet, "from"))) + if (!from) return; if(!(query = xmlnode_get_child(packet, "query"))) @@ -1019,16 +1015,15 @@ } static gboolean -jabber_si_xfer_ibb_open_cb(JabberStream *js, xmlnode *packet) +jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id, + xmlnode *open) { - const gchar *who = xmlnode_get_attrib(packet, "from"); - xmlnode *open = xmlnode_get_child(packet, "open"); const gchar *sid = xmlnode_get_attrib(open, "sid"); PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); if (xfer) { JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; JabberIBBSession *sess = - jabber_ibb_session_create_from_xmlnode(js, packet, xfer); + jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); const char *filename; jabber_si_bytestreams_ibb_timeout_remove(jsx); @@ -1183,8 +1178,9 @@ } } -static void jabber_si_xfer_send_method_cb(JabberStream *js, xmlnode *packet, - gpointer data) +static void jabber_si_xfer_send_method_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleXfer *xfer = data; xmlnode *si, *feature, *x, *field, *value; @@ -1585,17 +1581,15 @@ purple_xfer_request(xfer); } -void jabber_si_parse(JabberStream *js, xmlnode *packet) +void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *si) { JabberSIXfer *jsx; PurpleXfer *xfer; - xmlnode *si, *file, *feature, *x, *field, *option, *value; - const char *stream_id, *filename, *filesize_c, *profile, *from; + xmlnode *file, *feature, *x, *field, *option, *value; + const char *stream_id, *filename, *filesize_c, *profile; size_t filesize = 0; - if(!(si = xmlnode_get_child(packet, "si"))) - return; - if(!(profile = xmlnode_get_attrib(si, "profile")) || strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) return; @@ -1618,7 +1612,7 @@ if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) return; - if(!(from = xmlnode_get_attrib(packet, "from"))) + if(!from) return; /* if they've already sent us this file transfer with the same damn id @@ -1659,7 +1653,7 @@ jsx->js = js; jsx->stream_id = g_strdup(stream_id); - jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jsx->iq_id = g_strdup(id); xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); g_return_if_fail(xfer != NULL); diff -r c08719989149 -r 8399b545925c libpurple/protocols/jabber/si.h --- a/libpurple/protocols/jabber/si.h Sat Apr 04 02:55:39 2009 +0000 +++ b/libpurple/protocols/jabber/si.h Sat Apr 04 07:08:33 2009 +0000 @@ -26,8 +26,10 @@ #include "jabber.h" -void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet); -void jabber_si_parse(JabberStream *js, xmlnode *packet); +void jabber_bytestreams_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); +void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *si); PurpleXfer *jabber_si_new_xfer(PurpleConnection *gc, const char *who); void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file); void jabber_si_init(void);