changeset 28760:0f7025534fc5

jabber: Roster Versioning support.
author Paul Aurich <paul@darkrain42.org>
date Sun, 06 Dec 2009 00:52:10 +0000
parents f267c1608102
children 516e53916962
files ChangeLog libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.h libpurple/protocols/jabber/namespaces.h libpurple/protocols/jabber/roster.c
diffstat 5 files changed, 51 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Dec 06 00:36:59 2009 +0000
+++ b/ChangeLog	Sun Dec 06 00:52:10 2009 +0000
@@ -5,12 +5,13 @@
 	* Build-time fixes for Solaris.  (Paul Townsend)
 
 	XMPP:
-	* Added support for the SCRAM-SHA-1 SASL mechanism.  This support is only
+	* Added support for the SCRAM-SHA-1 SASL mechanism.  This is only
 	  available when built without Cyrus SASL support.
 	* When getting info on a domain-only (server) JID, show uptime
 	  (when given by the result of the "last query") and don't show status as
 	  offline.
 	* Do not crash when attempting to register for a new account on Windows.
+	* Added support for Roster Versioning (XEP-0237).
 
 version 2.6.4 (11/29/2009):
 	libpurple:
--- a/libpurple/protocols/jabber/jabber.c	Sun Dec 06 00:36:59 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sun Dec 06 00:52:10 2009 +0000
@@ -229,6 +229,8 @@
 		jabber_iq_set_callback(iq, jabber_bind_result_cb, NULL);
 
 		jabber_iq_send(iq);
+	} else if (xmlnode_get_child_with_namespace(packet, "ver", NS_ROSTER_VERSIONING)) {
+		js->server_caps |= JABBER_CAP_ROSTER_VERSIONING;
 	} else /* if(xmlnode_get_child_with_namespace(packet, "auth")) */ {
 		/* If we get an empty stream:features packet, or we explicitly get
 		 * an auth feature with namespace http://jabber.org/features/iq-auth
--- a/libpurple/protocols/jabber/jabber.h	Sun Dec 06 00:36:59 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Sun Dec 06 00:52:10 2009 +0000
@@ -47,6 +47,7 @@
 	JABBER_CAP_BLOCKING       = 1 << 13,
 
 	JABBER_CAP_ITEMS          = 1 << 14,
+	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
 
 	JABBER_CAP_RETRIEVED      = 1 << 31
 } JabberCapabilities;
--- a/libpurple/protocols/jabber/namespaces.h	Sun Dec 06 00:36:59 2009 +0000
+++ b/libpurple/protocols/jabber/namespaces.h	Sun Dec 06 00:52:10 2009 +0000
@@ -85,6 +85,9 @@
 /* XEP-0231 BoB (Bits of Binary) */
 #define NS_BOB "urn:xmpp:bob"
 
+/* XEP-0237 Roster Versioning */
+#define NS_ROSTER_VERSIONING "urn:xmpp:features:rosterver"
+
 /* Google extensions */
 #define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
 #define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
--- a/libpurple/protocols/jabber/roster.c	Sun Dec 06 00:36:59 2009 +0000
+++ b/libpurple/protocols/jabber/roster.c	Sun Dec 06 00:52:10 2009 +0000
@@ -47,11 +47,47 @@
 	return g_string_free(out, FALSE);
 }
 
+static void roster_request_cb(JabberStream *js, const char *from,
+                              JabberIqType type, const char *id,
+                              xmlnode *packet, gpointer data)
+{
+	xmlnode *query;
+
+	if (type == JABBER_IQ_ERROR) {
+		/*
+		 * This shouldn't happen in any real circumstances and
+		 * likely constitutes a server-side misconfiguration (i.e.
+		 * explicitly not loading mod_roster...)
+		 */
+		purple_debug_error("jabber", "Error retrieving roster!?\n");
+		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
+		return;
+	}
+
+	query = xmlnode_get_child(packet, "query");
+	if (query == NULL) {
+		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
+		return;
+	}
+
+	jabber_roster_parse(js, from, type, id, query);
+	jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
+}
+
 void jabber_roster_request(JabberStream *js)
 {
+	PurpleAccount *account;
+	const char *ver;
 	JabberIq *iq;
+	xmlnode *query;
+
+	account = purple_connection_get_account(js->gc);
+	ver = purple_account_get_string(account, "roster_ver", "");
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
+	query = xmlnode_get_child(iq->node, "query");
+	xmlnode_set_attrib(query, "ver", ver);
+	jabber_iq_set_callback(iq, roster_request_cb, NULL);
 
 	jabber_iq_send(iq);
 }
@@ -155,6 +191,7 @@
                          JabberIqType type, const char *id, xmlnode *query)
 {
 	xmlnode *item, *group;
+	const char *ver;
 
 	if (!jabber_is_own_account(js, from)) {
 		purple_debug_warning("jabber", "Received bogon roster push from %s\n",
@@ -227,13 +264,13 @@
 		}
 	}
 
-	js->currently_parsing_roster_push = FALSE;
+	ver = xmlnode_get_attrib(query, "ver");
+	if (ver) {
+		 PurpleAccount *account = purple_connection_get_account(js->gc);
+		 purple_account_set_string(account, "roster_ver", ver);
+	}
 
-	/* if we're just now parsing the roster for the first time,
-	 * then now would be the time to declare ourselves connected.
-	 */
-	if (js->state != JABBER_STREAM_CONNECTED)
-		jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
+	js->currently_parsing_roster_push = FALSE;
 }
 
 /* jabber_roster_update frees the GSList* passed in */