changeset 30690:7c5f2e776ceb

merge of '188465fa1e8064c35ae348b4c71cee7fb4c7c755' and '278c9cea4265f5e7877b2eaa47e5b44c049cf7f7'
author Paul Aurich <paul@darkrain42.org>
date Sat, 10 Jul 2010 02:10:19 +0000
parents 116ca888e77d (diff) 681cb0147153 (current diff)
children 28d5f60910c9
files
diffstat 7 files changed, 128 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/caps.c	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/protocols/jabber/caps.c	Sat Jul 10 02:10:19 2010 +0000
@@ -29,6 +29,7 @@
 #include "iq.h"
 #include "presence.h"
 #include "util.h"
+#include "xdata.h"
 
 #define JABBER_CAPS_FILENAME "xmpp-caps.xml"
 
@@ -45,8 +46,10 @@
 static void
 free_string_glist(GList *list)
 {
-	g_list_foreach(list, (GFunc)g_free, NULL);
-	g_list_free(list);
+	while (list) {
+		g_free(list->data);
+		list = g_list_delete_link(list, list);
+	}
 }
 
 static JabberCapsNodeExts*
@@ -230,15 +233,15 @@
 	if(!capsdata)
 		return;
 
-	if (strcmp(capsdata->name, "capabilities") != 0) {
+	if (!g_str_equal(capsdata->name, "capabilities")) {
 		xmlnode_free(capsdata);
 		return;
 	}
 
-	for(client = capsdata->child; client; client = client->next) {
-		if(client->type != XMLNODE_TYPE_TAG)
+	for (client = capsdata->child; client; client = client->next) {
+		if (client->type != XMLNODE_TYPE_TAG)
 			continue;
-		if(!strcmp(client->name, "client")) {
+		if (g_str_equal(client->name, "client")) {
 			JabberCapsClientInfo *value = g_new0(JabberCapsClientInfo, 1);
 			JabberCapsTuple *key = (JabberCapsTuple*)&value->tuple;
 			xmlnode *child;
@@ -251,15 +254,15 @@
 			if (key->hash == NULL)
 				exts = jabber_caps_find_exts_by_node(key->node);
 
-			for(child = client->child; child; child = child->next) {
-				if(child->type != XMLNODE_TYPE_TAG)
+			for (child = client->child; child; child = child->next) {
+				if (child->type != XMLNODE_TYPE_TAG)
 					continue;
-				if(!strcmp(child->name,"feature")) {
+				if (g_str_equal(child->name, "feature")) {
 					const char *var = xmlnode_get_attrib(child, "var");
 					if(!var)
 						continue;
 					value->features = g_list_append(value->features,g_strdup(var));
-				} else if(!strcmp(child->name,"identity")) {
+				} else if (g_str_equal(child->name, "identity")) {
 					const char *category = xmlnode_get_attrib(child, "category");
 					const char *type = xmlnode_get_attrib(child, "type");
 					const char *name = xmlnode_get_attrib(child, "name");
@@ -276,15 +279,15 @@
 					id->lang = g_strdup(lang);
 
 					value->identities = g_list_append(value->identities,id);
-				} else if(!strcmp(child->name,"x")) {
+				} else if (g_str_equal(child->name, "x")) {
 					/* TODO: See #7814 -- this might cause problems if anyone
 					 * ever actually specifies forms. In fact, for this to
 					 * work properly, that bug needs to be fixed in
 					 * xmlnode_from_str, not the output version... */
 					value->forms = g_list_append(value->forms, xmlnode_copy(child));
-				} else if (!strcmp(child->name, "ext") && key->hash != NULL) {
+				} else if (g_str_equal(child->name, "ext") && key->hash != NULL) {
 					purple_debug_warning("jabber", "Ignoring exts when reading new-style caps\n");
-				} else if (!strcmp(child->name, "ext")) {
+				} else if (g_str_equal(child->name, "ext")) {
 					/* TODO: Do we care about reading in the identities listed here? */
 					const char *identifier = xmlnode_get_attrib(child, "identifier");
 					xmlnode *node;
@@ -296,7 +299,7 @@
 					for (node = child->child; node; node = node->next) {
 						if (node->type != XMLNODE_TYPE_TAG)
 							continue;
-						if (!strcmp(node->name, "feature")) {
+						if (g_str_equal(node->name, "feature")) {
 							const char *var = xmlnode_get_attrib(node, "var");
 							if (!var)
 								continue;
@@ -455,13 +458,13 @@
 		 * size in jabber_caps_calculate_hash is large enough. The cipher API
 		 * doesn't seem to offer a "Get the hash size" function(?).
 		 */
-		if (!strcmp(userdata->hash, "sha-1")) {
+		if (g_str_equal(userdata->hash, "sha-1")) {
 			hash = jabber_caps_calculate_hash(info, "sha1");
-		} else if (!strcmp(userdata->hash, "md5")) {
+		} else if (g_str_equal(userdata->hash, "md5")) {
 			hash = jabber_caps_calculate_hash(info, "md5");
 		}
 
-		if (!hash || strcmp(hash, userdata->ver)) {
+		if (!hash || !g_str_equal(hash, userdata->ver)) {
 			purple_debug_warning("jabber", "Could not validate caps info from "
 			                     "%s. Expected %s, got %s\n",
 			                     xmlnode_get_attrib(packet, "from"),
@@ -701,44 +704,6 @@
 }
 
 static gint
-jabber_identity_compare(gconstpointer a, gconstpointer b)
-{
-	const JabberIdentity *ac;
-	const JabberIdentity *bc;
-	gint cat_cmp;
-	gint typ_cmp;
-
-	ac = a;
-	bc = b;
-
-	if ((cat_cmp = strcmp(ac->category, bc->category)) == 0) {
-		if ((typ_cmp = strcmp(ac->type, bc->type)) == 0) {
-			if (!ac->lang && !bc->lang) {
-				return 0;
-			} else if (ac->lang && !bc->lang) {
-				return 1;
-			} else if (!ac->lang && bc->lang) {
-				return -1;
-			} else {
-				return strcmp(ac->lang, bc->lang);
-			}
-		} else {
-			return typ_cmp;
-		}
-	} else {
-		return cat_cmp;
-	}
-}
-
-static gchar *jabber_caps_get_formtype(const xmlnode *x) {
-	xmlnode *formtypefield;
-	formtypefield = xmlnode_get_child(x, "field");
-	while (formtypefield && strcmp(xmlnode_get_attrib(formtypefield, "var"), "FORM_TYPE")) formtypefield = xmlnode_get_next_twin(formtypefield);
-	formtypefield = xmlnode_get_child(formtypefield, "value");
-	return xmlnode_get_data(formtypefield);;
-}
-
-static gint
 jabber_xdata_compare(gconstpointer a, gconstpointer b)
 {
 	const xmlnode *aformtypefield = a;
@@ -747,8 +712,8 @@
 	char *bformtype;
 	int result;
 
-	aformtype = jabber_caps_get_formtype(aformtypefield);
-	bformtype = jabber_caps_get_formtype(bformtypefield);
+	aformtype = jabber_x_data_get_formtype(aformtypefield);
+	bformtype = jabber_x_data_get_formtype(bformtypefield);
 
 	result = strcmp(aformtype, bformtype);
 	g_free(aformtype);
@@ -770,7 +735,7 @@
 	for(child = query->child; child; child = child->next) {
 		if (child->type != XMLNODE_TYPE_TAG)
 			continue;
-		if (!strcmp(child->name,"identity")) {
+		if (g_str_equal(child->name, "identity")) {
 			/* parse identity */
 			const char *category = xmlnode_get_attrib(child, "category");
 			const char *type = xmlnode_get_attrib(child, "type");
@@ -788,13 +753,13 @@
 			id->lang = g_strdup(lang);
 
 			info->identities = g_list_append(info->identities, id);
-		} else if (!strcmp(child->name, "feature")) {
+		} else if (g_str_equal(child->name, "feature")) {
 			/* parse feature */
 			const char *var = xmlnode_get_attrib(child, "var");
 			if (var)
 				info->features = g_list_prepend(info->features, g_strdup(var));
-		} else if (!strcmp(child->name, "x")) {
-			if (child->xmlns && !strcmp(child->xmlns, "jabber:x:data")) {
+		} else if (g_str_equal(child->name, "x")) {
+			if (purple_strequal(child->xmlns, "jabber:x:data")) {
 				/* x-data form */
 				xmlnode *dataform = xmlnode_copy(child);
 				info->forms = g_list_append(info->forms, dataform);
@@ -900,7 +865,7 @@
 	/* concat x-data forms to the verification string */
 	for(node = info->forms; node; node = node->next) {
 		xmlnode *data = (xmlnode *)node->data;
-		gchar *formtype = jabber_caps_get_formtype(data);
+		gchar *formtype = jabber_x_data_get_formtype(data);
 		GList *fields = jabber_caps_xdata_get_fields(data);
 
 		/* append FORM_TYPE's field value to the verification string */
@@ -961,6 +926,10 @@
 	}
 
 	info.features = features;
+	/* TODO: This copy can go away, I think, since jabber_identities
+	 * is pre-sorted, so the sort in calculate_hash should be idempotent.
+	 * However, I want to test that. --darkrain
+	 */
 	info.identities = g_list_copy(jabber_identities);
 	info.forms = NULL;
 
@@ -985,7 +954,7 @@
 	for (node = accounts; node; node = node->next) {
 		PurpleAccount *account = node->data;
 		const char *prpl_id = purple_account_get_protocol_id(account);
-		if (!strcmp("prpl-jabber", prpl_id) && purple_account_is_connected(account)) {
+		if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) {
 			PurpleConnection *gc = purple_account_get_connection(account);
 			jabber_presence_send(gc->proto_data, TRUE);
 		}
--- a/libpurple/protocols/jabber/jabber.c	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sat Jul 10 02:10:19 2010 +0000
@@ -1962,20 +1962,53 @@
 	}
 }
 
-void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name) {
+gint
+jabber_identity_compare(gconstpointer a, gconstpointer b)
+{
+	const JabberIdentity *ac;
+	const JabberIdentity *bc;
+	gint cat_cmp;
+	gint typ_cmp;
+
+	ac = a;
+	bc = b;
+
+	if ((cat_cmp = strcmp(ac->category, bc->category)) == 0) {
+		if ((typ_cmp = strcmp(ac->type, bc->type)) == 0) {
+			if (!ac->lang && !bc->lang) {
+				return 0;
+			} else if (ac->lang && !bc->lang) {
+				return 1;
+			} else if (!ac->lang && bc->lang) {
+				return -1;
+			} else {
+				return strcmp(ac->lang, bc->lang);
+			}
+		} else {
+			return typ_cmp;
+		}
+	} else {
+		return cat_cmp;
+	}
+}
+
+void jabber_add_identity(const gchar *category, const gchar *type,
+                         const gchar *lang, 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) &&
-		    !strcmp(ident->type, type) &&
-		    ((!ident->lang && !lang) || (ident->lang && lang && !strcmp(ident->lang, lang)))) {
+	/* Check if this identity is already there... */
+	for (identity = jabber_identities; identity; identity = identity->next) {
+		JabberIdentity *id = identity->data;
+		if (g_str_equal(id->category, category) &&
+			g_str_equal(id->type, type) &&
+			purple_strequal(id->lang, lang))
 			return;
-		}
 	}
 
 	ident = g_new0(JabberIdentity, 1);
@@ -1983,7 +2016,8 @@
 	ident->type = g_strdup(type);
 	ident->lang = g_strdup(lang);
 	ident->name = g_strdup(name);
-	jabber_identities = g_list_prepend(jabber_identities, ident);
+	jabber_identities = g_list_insert_sorted(jabber_identities, ident,
+	                                         jabber_identity_compare);
 }
 
 static void jabber_identities_destroy(void)
--- a/libpurple/protocols/jabber/jabber.h	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Sat Jul 10 02:10:19 2010 +0000
@@ -303,6 +303,9 @@
 
 /* what kind of additional features as returned from disco#info are supported? */
 extern GList *jabber_features;
+/* A sorted list of identities advertised.  Use jabber_add_identity to add
+ * so it remains sorted.
+ */
 extern GList *jabber_identities;
 
 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet);
@@ -342,6 +345,11 @@
 void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name);
 
 /**
+ * GCompareFunc for JabberIdentity structs.
+ */
+gint jabber_identity_compare(gconstpointer a, gconstpointer b);
+
+/**
  * Returns true if this connection is over a secure (SSL) stream. Use this
  * instead of checking js->gsc because BOSH stores its PurpleSslConnection
  * members in its own data structure.
--- a/libpurple/protocols/jabber/xdata.c	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/protocols/jabber/xdata.c	Sat Jul 10 02:10:19 2010 +0000
@@ -411,4 +411,30 @@
 	return handle;
 }
 
+gchar *
+jabber_x_data_get_formtype(const xmlnode *form)
+{
+	xmlnode *field;
 
+	g_return_val_if_fail(form != NULL, NULL);
+
+	for (field = xmlnode_get_child((xmlnode *)form, "field"); field;
+			field = xmlnode_get_next_twin(field)) {
+		const char *var = xmlnode_get_attrib(field, "var");
+		if (purple_strequal(var, "FORM_TYPE")) {
+			xmlnode *value = xmlnode_get_child(field, "value");
+			if (value)
+				return xmlnode_get_data(value);
+			else
+				/* An interesting corner case... Looking for a second
+				 * FORM_TYPE would be more considerate, but I'm in favor
+				 * of not helping broken clients.
+				 */
+				return NULL;
+		}
+	}
+
+	/* Erm, none found :( */
+	return NULL;
+}
+
--- a/libpurple/protocols/jabber/xdata.h	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/protocols/jabber/xdata.h	Sat Jul 10 02:10:19 2010 +0000
@@ -37,4 +37,19 @@
 void *jabber_x_data_request(JabberStream *js, xmlnode *packet, jabber_x_data_cb cb, gpointer user_data);
 void *jabber_x_data_request_with_actions(JabberStream *js, xmlnode *packet, GList *actions, int defaultaction, jabber_x_data_action_cb cb, gpointer user_data);
 
+/*
+ * Return the form type (the CDATA of the value child of the FORM_TYPE
+ * field entry.
+ * E.g., for the following, "http://jabber.org/protocol/muc#roominfo".
+ * <x xmlns='jabber:x:data' type='result'>
+ *  <field var='FORM_TYPE' type='hidden'>
+ *    <value>http://jabber.org/protocol/muc#roominfo</value>
+ *  </field>
+ * </x>
+ *
+ * @param form The xmlnode for the form (the 'x' element)
+ * @returns The FORM_TYPE.  Must be freed by caller.
+ */
+gchar *jabber_x_data_get_formtype(const xmlnode *form);
+
 #endif /* PURPLE_JABBER_XDATA_H_ */
--- a/libpurple/xmlnode.c	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/xmlnode.c	Sat Jul 10 02:10:19 2010 +0000
@@ -223,7 +223,7 @@
 
 
 const char *
-xmlnode_get_attrib(xmlnode *node, const char *attr)
+xmlnode_get_attrib(const xmlnode *node, const char *attr)
 {
 	xmlnode *x;
 
@@ -240,9 +240,9 @@
 }
 
 const char *
-xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns)
+xmlnode_get_attrib_with_namespace(const xmlnode *node, const char *attr, const char *xmlns)
 {
-	xmlnode *x;
+	const xmlnode *x;
 
 	g_return_val_if_fail(node != NULL, NULL);
 	g_return_val_if_fail(attr != NULL, NULL);
--- a/libpurple/xmlnode.h	Sat Jul 10 00:30:06 2010 +0000
+++ b/libpurple/xmlnode.h	Sat Jul 10 02:10:19 2010 +0000
@@ -205,7 +205,7 @@
  *
  * @return The value of the attribute.
  */
-const char *xmlnode_get_attrib(xmlnode *node, const char *attr);
+const char *xmlnode_get_attrib(const xmlnode *node, const char *attr);
 
 /**
  * Gets a namespaced attribute from a node
@@ -216,7 +216,7 @@
  *
  * @return The value of the attribute/
  */
-const char *xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns);
+const char *xmlnode_get_attrib_with_namespace(const xmlnode *node, const char *attr, const char *xmlns);
 
 /**
  * Removes an attribute from a node.