# HG changeset patch # User Paul Aurich # Date 1234064065 0 # Node ID ced3d4ab745a561c7fe41617f86309a6be3c60f3 # Parent 2035b8164acad2180265ed6bbf193364c065cc02# Parent 19fa48931b9d6ffc17e0777c41a8e0b1193ad349 propagate from branch 'im.pidgin.pidgin' (head 8d4081da0c186c04dc75d736d688bf4f20e52676) to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head 9a25f2e3149558150e52b40d5c119965ed617e37) diff -r 2035b8164aca -r ced3d4ab745a libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Sun Feb 08 00:23:43 2009 +0000 +++ b/libpurple/protocols/jabber/disco.c Sun Feb 08 03:34:25 2009 +0000 @@ -126,7 +126,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") diff -r 2035b8164aca -r ced3d4ab745a libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Sun Feb 08 00:23:43 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Sun Feb 08 03:34:25 2009 +0000 @@ -174,7 +174,7 @@ { const char *type, *from, *id, *xmlns; JabberIq *iq; - xmlnode *query; + xmlnode *child; time_t now_t; struct tm *now; @@ -185,64 +185,47 @@ from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); - /* 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); + if ((child = xmlnode_get_child(packet, "query"))) { + xmlns = "jabber:iq:time"; + } else if ((child = xmlnode_get_child(packet, "time"))) { + xmlns = "urn:xmpp:time"; + } else { + purple_debug_warning("jabber", "Malformed IQ time packet\n"); + return; + } if(type && !strcmp(type, "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"); - - 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); + 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, 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); + 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); + 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); + xmlnode_insert_data(utc, date, -1); + + display = purple_utf8_strftime("%d %b %Y %T", now); + 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) { JabberIq *iq; @@ -309,12 +292,22 @@ 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; - query = xmlnode_get_child(packet, "query"); + /* + * 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; + } + type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); @@ -353,7 +346,6 @@ } /* 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); @@ -363,36 +355,15 @@ } /* Apparently not, so lets see if we have a pre-defined handler */ - - if(query && (xmlns = xmlnode_get_namespace(query))) { + if(child && (xmlns = xmlnode_get_namespace(child))) { if((jih = g_hash_table_lookup(iq_handlers, xmlns))) { jih(js, packet); return; } } - 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 we get here, send the default error reply mandated by XMPP-CORE */ if(!strcmp(type, "set") || !strcmp(type, "get")) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); @@ -421,17 +392,20 @@ { 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("google:mail:notify", jabber_gmail_poke); 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("http://jabber.org/protocol/si", jabber_si_parse); + jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse); + jabber_iq_register_handler("jabber:iq:oob", jabber_oob_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("jabber:iq:roster", jabber_roster_parse); + jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse); + jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse); + jabber_iq_register_handler(XEP_0231_NAMESPACE, jabber_data_parse); + jabber_iq_register_handler("urn:xmpp:ping", jabber_ping_parse); + jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse); } void jabber_iq_uninit(void) diff -r 2035b8164aca -r ced3d4ab745a libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sun Feb 08 00:23:43 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Feb 08 03:34:25 2009 +0000 @@ -439,17 +439,11 @@ 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, - _("Ping timeout")); + _("Ping timeout")); js->keepalive_timeout = -1; return FALSE; } @@ -459,14 +453,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); } } @@ -2421,10 +2410,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(pc->proto_data, args[0])) { *error = g_strdup_printf(_("Unable to ping user %s"), args[0]); return PURPLE_CMD_RET_FAILED; } diff -r 2035b8164aca -r ced3d4ab745a libpurple/protocols/jabber/ping.c --- a/libpurple/protocols/jabber/ping.c Sun Feb 08 00:23:43 2009 +0000 +++ b/libpurple/protocols/jabber/ping.c Sun Feb 08 03:34:25 2009 +0000 @@ -23,34 +23,59 @@ #include "internal.h" #include "debug.h" -#include "xmlnode.h" #include "jabber.h" #include "ping.h" #include "iq.h" +static void jabber_keepalive_pong_cb(JabberStream *js) +{ + purple_timeout_remove(js->keepalive_timeout); + js->keepalive_timeout = -1; +} + void jabber_ping_parse(JabberStream *js, xmlnode *packet) { - JabberIq *iq; + const char *type, *id, *from; + + type = xmlnode_get_attrib(packet, "type"); + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + if (!type) { + purple_debug_warning("jabber", "jabber_ping with no type\n"); + return; + } + 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") ); + if (!strcmp(type, "get")) { + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_set_attrib(iq->node, "id", id); - jabber_iq_send(iq); + jabber_iq_send(iq); + } else if (!strcmp(type, "set")) { + /* XXX: error */ + } } static void jabber_ping_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) + gpointer data) { const char *type = xmlnode_get_attrib(packet, "type"); + const char *from = xmlnode_get_attrib(packet, "from"); purple_debug_info("jabber", "jabber_ping_result_cb\n"); + + if (!from || !strcmp(from, js->user->domain)) { + /* If the pong is from our server, treat it as a return from the + * keepalive functions */ + jabber_keepalive_pong_cb(js); + } + if(type && !strcmp(type, "result")) { purple_debug_info("jabber", "PONG!\n"); } else { @@ -58,15 +83,16 @@ } } -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 +100,5 @@ jabber_iq_set_callback(iq, jabber_ping_result_cb, NULL); jabber_iq_send(iq); - - return TRUE; } diff -r 2035b8164aca -r ced3d4ab745a libpurple/protocols/jabber/ping.h --- a/libpurple/protocols/jabber/ping.h Sun Feb 08 00:23:43 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Sun Feb 08 03:34:25 2009 +0000 @@ -23,13 +23,9 @@ #define _PURPLE_JABBER_PING_H_ #include "jabber.h" -#include "conversation.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, xmlnode *packet); +gboolean jabber_ping_jid(JabberStream *js, const char *jid); #endif /* _PURPLE_JABBER_PING_H_ */