# HG changeset patch # User Paul Aurich # Date 1233795598 0 # Node ID cbbafb072285d06f5899f410c461523a85776077 # Parent 49d51dbcb7994753f6d5647c362c3f425b420c1c# Parent 5011b11d322b72d023ba29c0af4fb3ad4c825b62 propagate from branch 'im.pidgin.pidgin' (head 0bfcaf78ec07efb71812fff2c8b738b4532aac7f) to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head 43136a2c50fd1b1adb089d7c47e12ad2152fe747) diff -r 49d51dbcb799 -r cbbafb072285 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Wed Feb 04 22:46:45 2009 +0000 +++ b/libpurple/protocols/jabber/disco.c Thu Feb 05 00:59:58 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 49d51dbcb799 -r cbbafb072285 libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Wed Feb 04 22:46:45 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Thu Feb 05 00:59:58 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,23 @@ 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) + continue; + break; + } + type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); @@ -353,7 +347,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 +356,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 +393,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 49d51dbcb799 -r cbbafb072285 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Wed Feb 04 22:46:45 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Thu Feb 05 00:59:58 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 49d51dbcb799 -r cbbafb072285 libpurple/protocols/jabber/ping.c --- a/libpurple/protocols/jabber/ping.c Wed Feb 04 22:46:45 2009 +0000 +++ b/libpurple/protocols/jabber/ping.c Thu Feb 05 00:59:58 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 49d51dbcb799 -r cbbafb072285 libpurple/protocols/jabber/ping.h --- a/libpurple/protocols/jabber/ping.h Wed Feb 04 22:46:45 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Thu Feb 05 00:59:58 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_ */