changeset 25645:ced3d4ab745a

propagate from branch 'im.pidgin.pidgin' (head 8d4081da0c186c04dc75d736d688bf4f20e52676) to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head 9a25f2e3149558150e52b40d5c119965ed617e37)
author Paul Aurich <paul@darkrain42.org>
date Sun, 08 Feb 2009 03:34:25 +0000
parents 2035b8164aca (current diff) 19fa48931b9d (diff)
children 89c4edb5e545 969c89c09ad7
files libpurple/protocols/jabber/iq.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/ping.c libpurple/protocols/jabber/ping.h
diffstat 5 files changed, 100 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- 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")
--- 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)
--- 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;
 	}
--- 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;
 }
--- 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_ */