changeset 25017:26eabe8e739b

Removing short-names for features and calculating own caps hash.
author Tobias Markmann <tfar@soc.pidgin.im>
date Mon, 16 Jun 2008 13:52:45 +0000
parents adda955a8db6
children 2a6a37c7970b
files libpurple/protocols/jabber/caps.c libpurple/protocols/jabber/caps.h libpurple/protocols/jabber/disco.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.h libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/message.c libpurple/protocols/jabber/message.h libpurple/protocols/jabber/pep.c libpurple/protocols/jabber/pep.h libpurple/protocols/jabber/presence.c libpurple/protocols/jabber/usermood.c libpurple/protocols/jabber/usernick.c libpurple/protocols/jabber/usertune.c
diffstat 14 files changed, 230 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/caps.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/caps.c	Mon Jun 16 13:52:45 2008 +0000
@@ -21,7 +21,9 @@
 
 #include "internal.h"
 
+#include <glib.h>
 #include "caps.h"
+#include "cipher.h"
 #include <string.h>
 #include "internal.h"
 #include "util.h"
@@ -30,6 +32,7 @@
 #define JABBER_CAPS_FILENAME "xmpp-caps.xml"
 
 static GHashTable *capstable = NULL; /* JabberCapsKey -> JabberCapsValue */
+static gchar *caps_hash = NULL;
 
 typedef struct _JabberCapsKey {
 	char *node;
@@ -111,6 +114,7 @@
 void jabber_caps_init(void) {
 	capstable = g_hash_table_new_full(jabber_caps_hash, jabber_caps_compare, jabber_caps_destroy_key, jabber_caps_destroy_value);
 	jabber_caps_load();
+	jabber_caps_calculate_hash();
 }
 
 static void jabber_caps_load(void) {
@@ -499,7 +503,6 @@
 void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *ext, jabber_caps_get_info_cb cb, gpointer user_data) {
 	JabberCapsValue *client;
 	JabberCapsKey *key = g_new0(JabberCapsKey, 1);
-	char *originalext = g_strdup(ext);
 	jabber_caps_cbplususerdata *userdata = g_new0(jabber_caps_cbplususerdata, 1);
 	userdata->cb = cb;
 	userdata->user_data = user_data;
@@ -507,17 +510,6 @@
 	userdata->node = g_strdup(node);
 	userdata->ver = g_strdup(ver);
 
-	if(originalext) {
-		int i;
-		gchar **splat = g_strsplit(originalext, " ", 0);
-		for(i =0; splat[i]; i++) {
-			userdata->ext = g_list_append(userdata->ext, splat[i]);
-			++userdata->extOutstanding;
-		}
-		g_free(splat);
-	}
-	g_free(originalext);
-
 	key->node = (char *)node;
 	key->ver = (char *)ver;
 
@@ -570,3 +562,95 @@
 	}
 }
 
+static gint jabber_caps_jabber_identity_compare(gconstpointer a, gconstpointer b) {
+	const JabberIdentity *ac;
+	const JabberIdentity *bc;
+	gint cat_cmp;
+	
+	ac = a;
+	bc = b;
+	
+	if ((cat_cmp = strcmp(ac->category, bc->category)) == 0) {
+		return strcmp(ac->type, bc->type);
+	} else {
+		return cat_cmp;
+	}
+}
+
+static gint jabber_caps_jabber_feature_compare(gconstpointer a, gconstpointer b) {
+	const JabberFeature *ac;
+	const JabberFeature *bc;
+	
+	ac = a;
+	bc = b;
+	
+	return strcmp(ac->namespace, bc->namespace);
+}
+
+
+void jabber_caps_calculate_hash() {
+	gchar *verification = 0;
+	gchar *free_verification;
+	gchar *identity_string, *feature_string;
+	GList *identities, *features;
+	PurpleCipherContext *context;
+	guint8 checksum[20];
+	gsize checksum_size = 20;
+
+	/* sort identities */
+	jabber_identities = g_list_sort(jabber_identities, jabber_caps_jabber_identity_compare);
+	
+	/* concat identities to the verification string */
+	for(identities = jabber_identities; identities; identities = identities->next) {
+		JabberIdentity *ident = (JabberIdentity*)identities->data;
+		identity_string = g_strdup_printf("%s/%s//%s<", ident->category, ident->type, ident->name);
+		free_verification = verification;
+		if(verification == 0) verification = g_strdup(identity_string);
+		 	else verification = g_strconcat(verification, identity_string, NULL);
+		g_free(identity_string);
+		if(free_verification) g_free(free_verification);
+	}
+	
+	/* sort features */
+	jabber_features = g_list_sort(jabber_features, jabber_caps_jabber_feature_compare);
+	
+	/* concat features to the verification string */
+	for(features = jabber_features; features; features = features->next) {
+		JabberFeature *feat = (JabberFeature*)features->data;
+		feature_string = g_strdup_printf("%s<", feat->namespace);
+		free_verification = verification;
+		if(verification == 0) g_strdup(feature_string);
+			else verification = g_strconcat(verification, feature_string, NULL);
+		g_free(feature_string);
+		if(free_verification) g_free(free_verification);
+	}
+	printf("\n%s", verification);
+	
+	
+	/* generate SHA-1 hash */
+	context = purple_cipher_context_new_by_name("sha1", NULL);
+	if (context == NULL) {
+		purple_debug_error("jabber", "Could not find sha1 cipher\n");
+		return;
+	}
+	purple_cipher_context_append(context, verification, strlen(verification));
+	
+	if (!purple_cipher_context_digest(context, strlen(verification), checksum, &checksum_size)) {
+		purple_debug_error("util", "Failed to get SHA-1 digest.\n");
+	}
+	purple_cipher_context_destroy(context);
+	
+	/* apply Base64 on hash */
+	
+	g_free(verification);
+	verification = purple_base64_encode(checksum, checksum_size); // for 2.0 compability
+	printf("\n%s", verification);
+	
+	if (caps_hash != 0) g_free(caps_hash);
+	caps_hash = verification;
+}
+
+const gchar* jabber_caps_get_hash() {
+	return caps_hash;
+}
+
--- a/libpurple/protocols/jabber/caps.h	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/caps.h	Mon Jun 16 13:52:45 2008 +0000
@@ -46,4 +46,12 @@
 void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *ext, jabber_caps_get_info_cb cb, gpointer user_data);
 void jabber_caps_free_clientinfo(JabberCapsClientInfo *clientinfo);
 
+
+void jabber_caps_calculate_hash();
+
+/** Get the current caps hash.
+ * 	@ret hash
+**/
+const gchar* jabber_caps_get_hash();
+
 #endif /* _PURPLE_JABBER_CAPS_H_ */
--- a/libpurple/protocols/jabber/disco.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/disco.c	Mon Jun 16 13:52:45 2008 +0000
@@ -79,7 +79,6 @@
 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");
-
 	if(!from || !type)
 		return;
 
@@ -89,6 +88,10 @@
 
 		xmlnode *in_query;
 		const char *node = NULL;
+		const char *node_uri = NULL;
+		
+		// create custom caps node URI
+		node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_hash(), NULL);
 
 		if((in_query = xmlnode_get_child(packet, "query"))) {
 			node = xmlnode_get_attrib(in_query, "node");
@@ -106,90 +109,38 @@
 		if(node)
 			xmlnode_set_attrib(query, "node", node);
 
-		if(!node || !strcmp(node, CAPS0115_NODE "#" VERSION)) {
-			identity = xmlnode_new_child(query, "identity");
-			xmlnode_set_attrib(identity, "category", "client");
-			xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console,
-														 * handheld, pc, phone,
-														 * web */
-			xmlnode_set_attrib(identity, "name", PACKAGE);
 
-			SUPPORT_FEATURE("jabber:iq:last")
-			SUPPORT_FEATURE("jabber:iq:oob")
-			SUPPORT_FEATURE("jabber:iq:time")
-			SUPPORT_FEATURE("xmpp:urn:time")
-			SUPPORT_FEATURE("jabber:iq:version")
-			SUPPORT_FEATURE("jabber:x:conference")
-			SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams")
-			SUPPORT_FEATURE("http://jabber.org/protocol/disco#info")
-			SUPPORT_FEATURE("http://jabber.org/protocol/disco#items")
-#if 0
-				SUPPORT_FEATURE("http://jabber.org/protocol/ibb")
-#endif
-			SUPPORT_FEATURE("http://jabber.org/protocol/muc")
-			SUPPORT_FEATURE("http://jabber.org/protocol/muc#user")
-			SUPPORT_FEATURE("http://jabber.org/protocol/si")
-			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;
-				for(features = jabber_features; features; features = features->next) {
-					JabberFeature *feat = (JabberFeature*)features->data;
-					if(feat->is_enabled == NULL || feat->is_enabled(js, feat->shortname, feat->namespace) == TRUE)
-						SUPPORT_FEATURE(feat->namespace);
-				}
+		if(!node || !strcmp(node, node_uri)) {
+			GList *identities;
+			for(identities = jabber_identities; identities; identities = identities->next) {
+				JabberIdentity *ident = (JabberIdentity*)identities->data;
+				identity = xmlnode_new_child(query, "identity");
+				xmlnode_set_attrib(identity, "category", ident->category);
+				xmlnode_set_attrib(identity, "type", ident->type);
+				if (ident->name != 0) xmlnode_set_attrib(identity, "name", ident->name);
+			}
+			GList *features;
+			for(features = jabber_features; features; features = features->next) {
+				JabberFeature *feat = (JabberFeature*)features->data;
+				if(feat->is_enabled == NULL || feat->is_enabled(js, feat->namespace) == TRUE) {
+					feature = xmlnode_new_child(query, "feature");
+					xmlnode_set_attrib(feature, "var", feat->namespace);
+				}	
 			}
 		} else {
-			const char *ext = NULL;
-			unsigned pos;
-			unsigned nodelen = strlen(node);
-			unsigned capslen = strlen(CAPS0115_NODE);
-			/* do a basic plausability check */
-			if(nodelen > capslen+1) {
-				/* verify that the string is CAPS0115#<ext> and get the pointer to the ext part */
-				for(pos = 0; pos < capslen+1; ++pos) {
-					if(pos == capslen) {
-						if(node[pos] == '#')
-							ext = &node[pos+1];
-						else
-							break;
-					} else if(node[pos] != CAPS0115_NODE[pos])
-					break;
-				}
+			xmlnode *error, *inf;
 				
-				if(ext != NULL) {
-					/* look for that ext */
-					GList *features;
-					for(features = jabber_features; features; features = features->next) {
-						JabberFeature *feat = (JabberFeature*)features->data;
-						if(!strcmp(feat->shortname, ext)) {
-							SUPPORT_FEATURE(feat->namespace);
-							break;
-						}
-					}
-					if(features == NULL)
-						ext = NULL;
-				}
-			}
+			/* XXX: gross hack, implement jabber_iq_set_type or something */
+			xmlnode_set_attrib(iq->node, "type", "error");
+			iq->type = JABBER_IQ_ERROR;
 			
-			if(ext == NULL) {
-				xmlnode *error, *inf;
-				
-				/* XXX: gross hack, implement jabber_iq_set_type or something */
-				xmlnode_set_attrib(iq->node, "type", "error");
-				iq->type = JABBER_IQ_ERROR;
-				
-				error = xmlnode_new_child(query, "error");
-				xmlnode_set_attrib(error, "code", "404");
-				xmlnode_set_attrib(error, "type", "cancel");
-				inf = xmlnode_new_child(error, "item-not-found");
-				xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
-			}
+			error = xmlnode_new_child(query, "error");
+			xmlnode_set_attrib(error, "code", "404");
+			xmlnode_set_attrib(error, "type", "cancel");
+			inf = xmlnode_new_child(error, "item-not-found");
+			xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
 		}
-
+		g_free(node_uri);
 		jabber_iq_send(iq);
 	} else if(!strcmp(type, "result")) {
 		xmlnode *query = xmlnode_get_child(packet, "query");
--- a/libpurple/protocols/jabber/jabber.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Jun 16 13:52:45 2008 +0000
@@ -60,7 +60,9 @@
 #define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5)
 
 static PurplePlugin *my_protocol = NULL;
+
 GList *jabber_features = NULL;
+GList *jabber_identities = NULL;
 
 static void jabber_unregister_account_cb(JabberStream *js);
 
@@ -1394,31 +1396,27 @@
 	js->idle = idle ? time(NULL) - idle : idle;
 }
 
-void jabber_add_feature(const char *shortname, const char *namespace, JabberFeatureEnabled cb) {
+void jabber_add_feature(const char *namespace, JabberFeatureEnabled cb) {
 	JabberFeature *feat;
 
-	g_return_if_fail(shortname != NULL);
 	g_return_if_fail(namespace != NULL);
 
 	feat = g_new0(JabberFeature,1);
-	feat->shortname = g_strdup(shortname);
 	feat->namespace = g_strdup(namespace);
 	feat->is_enabled = cb;
 	
 	/* try to remove just in case it already exists in the list */
-	jabber_remove_feature(shortname);
+	jabber_remove_feature(namespace);
 	
 	jabber_features = g_list_append(jabber_features, feat);
 }
 
-void jabber_remove_feature(const char *shortname) {
+void jabber_remove_feature(const char *namespace) {
 	GList *feature;
 	for(feature = jabber_features; feature; feature = feature->next) {
 		JabberFeature *feat = (JabberFeature*)feature->data;
-		if(!strcmp(feat->shortname, shortname)) {
-			g_free(feat->shortname);
+		if(!strcmp(feat->namespace, namespace)) {
 			g_free(feat->namespace);
-			
 			g_free(feature->data);
 			jabber_features = g_list_delete_link(jabber_features, feature);
 			break;
@@ -1426,6 +1424,27 @@
 	}
 }
 
+void jabber_add_identity(const gchar *category, const gchar *type, const gchar *name) {
+	GList *identity;
+	JabberIdentity *ident;
+	/* both required according to XEP-0030 */
+	g_return_if_fail(category != NULL);
+	g_return_if_fail(type != NULL);
+	
+	for(identity = jabber_identities; identity; identity = identity->next) {
+		JabberIdentity *ident = (JabberIdentity*)identity->data;
+		if(!strcmp(ident->category, category)) {
+			if (!strcmp(ident->type, type)) return;
+		}	
+	}
+	
+	ident = g_new0(JabberIdentity, 1);
+	ident->category = g_strdup(category);
+	ident->type = g_strdup(type);
+	ident->name = g_strdup(name);
+	jabber_identities = g_list_append(jabber_identities, ident);
+}
+
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b)
 {
 	return "jabber";
@@ -2429,5 +2448,27 @@
 void
 jabber_init_plugin(PurplePlugin *plugin)
 {
-        my_protocol = plugin;
+	my_protocol = plugin;
+
+	jabber_add_identity("client", "pc", PACKAGE);
+
+	// initialize jabber_features list
+	jabber_add_feature("jabber:iq:last", 0);
+	jabber_add_feature("jabber:iq:oob", 0);
+	jabber_add_feature("jabber:iq:time", 0);
+	jabber_add_feature("xmpp:urn:time", 0);
+	jabber_add_feature("jabber:iq:version", 0);
+	jabber_add_feature("jabber:x:conference", 0);
+	jabber_add_feature("http://jabber.org/protocol/bytestreams", 0);
+	jabber_add_feature("http://jabber.org/protocol/disco#info", 0);
+	jabber_add_feature("http://jabber.org/protocol/disco#items", 0);
+#if 0
+	jabber_add_feature("http://jabber.org/protocol/ibb", 0);
+#endif
+	jabber_add_feature("http://jabber.org/protocol/muc", 0);
+	jabber_add_feature("http://jabber.org/protocol/muc#user", 0);
+	jabber_add_feature("http://jabber.org/protocol/si", 0);
+	jabber_add_feature("http://jabber.org/protocol/si/profile/file-transfer", 0);
+	jabber_add_feature("http://jabber.org/protocol/xhtml-im", 0);
+	jabber_add_feature("urn:xmpp:ping", 0);
 }
--- a/libpurple/protocols/jabber/jabber.h	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Mon Jun 16 13:52:45 2008 +0000
@@ -203,15 +203,21 @@
 	int keepalive_timeout;
 };
 
-typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *shortname, const gchar *namespace);
+typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
 
 typedef struct _JabberFeature
 {
-	gchar *shortname;
 	gchar *namespace;
 	JabberFeatureEnabled *is_enabled;
 } JabberFeature;
 
+typedef struct _JabberIdentity
+{
+	gchar *category;
+	gchar *type;
+	gchar *name;
+} JabberIdentity;
+
 typedef struct _JabberBytestreamsStreamhost {
 	char *jid;
 	char *host;
@@ -221,6 +227,7 @@
 
 /* what kind of additional features as returned from disco#info are supported? */
 extern GList *jabber_features;
+extern GList *jabber_identities;
 
 void jabber_process_packet(JabberStream *js, xmlnode **packet);
 void jabber_send(JabberStream *js, xmlnode *data);
@@ -242,8 +249,16 @@
  */
 char *jabber_parse_error(JabberStream *js, xmlnode *packet, PurpleConnectionError *reason);
 
-void jabber_add_feature(const gchar *shortname, const gchar *namespace, JabberFeatureEnabled cb); /* cb may be NULL */
-void jabber_remove_feature(const gchar *shortname);
+void jabber_add_feature(const gchar *namespace, JabberFeatureEnabled cb); /* cb may be NULL */
+void jabber_remove_feature(const gchar *namespace);
+
+/** Adds an identitiy to this jabber library instance. For list of valid values vistit the 
+ *	webiste of the XMPP Registrar ( http://www.xmpp.org/registrar/disco-categories.html#client ).
+ *  @param category the category of the identity.
+ *	@param type the type of the identity.
+ *	@param name the name of the identity.
+ */
+void jabber_add_identity(const gchar *category, const gchar *type, const gchar *name); 
 
 /** PRPL functions */
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b);
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Jun 16 13:52:45 2008 +0000
@@ -263,11 +263,13 @@
 	jabber_tune_init();
 	jabber_caps_init();
 
-	jabber_add_feature("avatarmeta", AVATARNAMESPACEMETA, jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_add_feature("avatardata", AVATARNAMESPACEDATA, jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_add_feature("buzz", "http://www.xmpp.org/extensions/xep-0224.html#ns", jabber_buzz_isenabled);
+	#warning implement adding and retrieving own features via IPC API
+
+	jabber_add_feature(AVATARNAMESPACEMETA, jabber_pep_namespace_only_when_pep_enabled_cb);
+	jabber_add_feature(AVATARNAMESPACEDATA, jabber_pep_namespace_only_when_pep_enabled_cb);
+	jabber_add_feature("http://www.xmpp.org/extensions/xep-0224.html#ns", jabber_buzz_isenabled);
 	
-	jabber_pep_register_handler("avatar", AVATARNAMESPACEMETA, jabber_buddy_avatar_update_metadata);
+	jabber_pep_register_handler(AVATARNAMESPACEMETA, jabber_buddy_avatar_update_metadata);
 }
 
 
--- a/libpurple/protocols/jabber/message.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/message.c	Mon Jun 16 13:52:45 2008 +0000
@@ -758,7 +758,7 @@
 	jabber_message_free(jm);
 }
 
-gboolean jabber_buzz_isenabled(JabberStream *js, const gchar *shortname, const gchar *namespace) {
+gboolean jabber_buzz_isenabled(JabberStream *js, const gchar *namespace) {
 	return js->allowBuzz;
 }
 
--- a/libpurple/protocols/jabber/message.h	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/message.h	Mon Jun 16 13:52:45 2008 +0000
@@ -78,6 +78,6 @@
 unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state);
 void jabber_message_conv_closed(JabberStream *js, const char *who);
 
-gboolean jabber_buzz_isenabled(JabberStream *js, const gchar *shortname, const gchar *namespace);
+gboolean jabber_buzz_isenabled(JabberStream *js, const gchar *namespace);
 
 #endif /* _PURPLE_JABBER_MESSAGE_H_ */
--- a/libpurple/protocols/jabber/pep.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/pep.c	Mon Jun 16 13:52:45 2008 +0000
@@ -45,9 +45,9 @@
 	jabber_nick_init_action(m);
 }
 
-void jabber_pep_register_handler(const char *shortname, const char *xmlns, JabberPEPHandler handlerfunc) {
+void jabber_pep_register_handler(const char *xmlns, JabberPEPHandler handlerfunc) {
 	gchar *notifyns = g_strdup_printf("%s+notify", xmlns);
-	jabber_add_feature(shortname, notifyns, NULL); /* receiving PEPs is always supported */
+	jabber_add_feature(notifyns, NULL); /* receiving PEPs is always supported */
 	g_free(notifyns);
 	g_hash_table_replace(pep_handlers, g_strdup(xmlns), handlerfunc);
 }
@@ -85,7 +85,7 @@
 	jabber_iq_send(iq);
 }
 
-gboolean jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js, const gchar *shortname, const gchar *namespace) {
+gboolean jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js, const gchar *namespace) {
 	return js->pep;
 }
 
--- a/libpurple/protocols/jabber/pep.h	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/pep.h	Mon Jun 16 13:52:45 2008 +0000
@@ -42,11 +42,10 @@
  * Registers a callback for PEP events. Also automatically announces this receiving capability via disco#info.
  * Don't forget to use jabber_add_feature when supporting the sending of PEP events of this type.
  *
- * @parameter shortname		A short name for this feature for XEP-0115. It has no semantic meaning, it just has to be unique.
- * @parameter xmlns		The namespace for this event
+ * @parameter xmlns			The namespace for this event
  * @parameter handlerfunc	The callback to be used when receiving an event with this namespace
  */
-void jabber_pep_register_handler(const char *shortname, const char *xmlns, JabberPEPHandler handlerfunc);
+void jabber_pep_register_handler(const char *xmlns, JabberPEPHandler handlerfunc);
 
 /*
  * Request a specific item from another PEP node.
@@ -64,13 +63,12 @@
 /*
  * Default callback that can be used for namespaces which should only be enabled when PEP is supported
  *
- * @parameter js	The JabberStream struct for this connection
- * @parameter shortname	The namespace's shortname (for caps), ignored.
+ * @parameter js		The JabberStream struct for this connection
  * @parameter namespace The namespace that's queried, ignored.
  *
  * @returns TRUE when PEP is enabled, FALSE otherwise
  */
-gboolean jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js, const gchar *shortname, const gchar *namespace);
+gboolean jabber_pep_namespace_only_when_pep_enabled_cb(JabberStream *js, const gchar *namespace);
 
 void jabber_handle_event(JabberMessage *jm);
 
--- a/libpurple/protocols/jabber/presence.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/presence.c	Mon Jun 16 13:52:45 2008 +0000
@@ -264,8 +264,10 @@
 	c = xmlnode_new_child(presence, "c");
 	xmlnode_set_namespace(c, "http://jabber.org/protocol/caps");
 	xmlnode_set_attrib(c, "node", CAPS0115_NODE);
-	xmlnode_set_attrib(c, "ver", VERSION);
-	
+	xmlnode_set_attrib(c, "hash", "sha-1");
+	xmlnode_set_attrib(c, "ver", jabber_caps_get_hash());
+
+#if 0
 	if(js != NULL) {
 		/* add the extensions */
 		char extlist[1024];
@@ -277,7 +279,7 @@
 			JabberFeature *feat = (JabberFeature*)feature->data;
 			unsigned featlen;
 			
-			if(feat->is_enabled != NULL && feat->is_enabled(js, feat->shortname, feat->namespace) == FALSE)
+			if(feat->is_enabled != NULL && feat->is_enabled(js, feat->namespace) == FALSE)
 				continue; /* skip this feature */
 			
 			featlen = strlen(feat->shortname);
@@ -297,7 +299,7 @@
 		if(remaining < 1023)
 			xmlnode_set_attrib(c, "ext", extlist);
 	}
-	
+#endif
 	return presence;
 }
 
--- a/libpurple/protocols/jabber/usermood.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Mon Jun 16 13:52:45 2008 +0000
@@ -141,8 +141,8 @@
 }
 
 void jabber_mood_init(void) {
-	jabber_add_feature("mood", "http://jabber.org/protocol/mood", jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_pep_register_handler("moodn", "http://jabber.org/protocol/mood", jabber_mood_cb);
+	jabber_add_feature("http://jabber.org/protocol/mood", jabber_pep_namespace_only_when_pep_enabled_cb);
+	jabber_pep_register_handler("http://jabber.org/protocol/mood", jabber_mood_cb);
 }
 
 static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) {
--- a/libpurple/protocols/jabber/usernick.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/usernick.c	Mon Jun 16 13:52:45 2008 +0000
@@ -92,8 +92,8 @@
 }
 
 void jabber_nick_init(void) {
-	jabber_add_feature("nick", "http://jabber.org/protocol/nick", jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_pep_register_handler("nickn", "http://jabber.org/protocol/nick", jabber_nick_cb);
+	jabber_add_feature("http://jabber.org/protocol/nick", jabber_pep_namespace_only_when_pep_enabled_cb);
+	jabber_pep_register_handler("http://jabber.org/protocol/nick", jabber_nick_cb);
 }
 
 void jabber_nick_init_action(GList **m) {
--- a/libpurple/protocols/jabber/usertune.c	Wed Jun 11 15:36:42 2008 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Mon Jun 16 13:52:45 2008 +0000
@@ -109,8 +109,8 @@
 }
 
 void jabber_tune_init(void) {
-	jabber_add_feature("tune", "http://jabber.org/protocol/tune", jabber_pep_namespace_only_when_pep_enabled_cb);
-	jabber_pep_register_handler("tunen", "http://jabber.org/protocol/tune", jabber_tune_cb);
+	jabber_add_feature("http://jabber.org/protocol/tune", jabber_pep_namespace_only_when_pep_enabled_cb);
+	jabber_pep_register_handler("http://jabber.org/protocol/tune", jabber_tune_cb);
 }
 
 void jabber_tune_set(PurpleConnection *gc, const PurpleJabberTuneInfo *tuneinfo) {