changeset 26771:e72df47d41fe

Escape all the values when appending them to the Entity Caps verification str. xmlnode_get_attrib and xmlnode_get_data unescape what they return. Thanks to Tobias and Waqas. This will still fail to validate if the other side uses entity codes (or uses other entities unnecessarily), but that should be dealt with as a hash failure instead of a collision. (10:12:11) Tobias: [18:48:43] <waqas> <identity category='client' type='pc' name='SomeClient'/><feature var='http://jabber.org/protocol/muc'/> turns into 'client/pc//SomeClient<http://jabber.org/protocol/caps<' but so does <identity category='client' type='pc' name='SomeClient&lt;http://jabber.org/protocol/caps'/>, which is a collision, right?
author Paul Aurich <paul@darkrain42.org>
date Sat, 02 May 2009 01:26:18 +0000
parents 7c1ecd0727db
children ab31daf1c1ee
files ChangeLog.API libpurple/protocols/jabber/caps.c libpurple/util.c libpurple/util.h
diffstat 4 files changed, 70 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Fri May 01 22:40:41 2009 +0000
+++ b/ChangeLog.API	Sat May 02 01:26:18 2009 +0000
@@ -27,6 +27,7 @@
 		* purple_connection_set_protocol_data
 		* purple_contact_destroy
 		* purple_conv_chat_invite_user
+		* purple_escape_html
 		* purple_global_proxy_set_info
 		* purple_group_destroy
 		* purple_log_get_activity_score
--- a/libpurple/protocols/jabber/caps.c	Fri May 01 22:40:41 2009 +0000
+++ b/libpurple/protocols/jabber/caps.c	Sat May 02 01:26:18 2009 +0000
@@ -286,10 +286,10 @@
 					id->type = g_strdup(type);
 					id->name = g_strdup(name);
 					id->lang = g_strdup(lang);
-					
+
 					value->identities = g_list_append(value->identities,id);
 				} else if(!strcmp(child->name,"x")) {
-					/* FIXME: See #7814 -- this will cause problems if anyone
+					/* 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... */
@@ -794,9 +794,11 @@
 }
 
 static GString*
-jabber_caps_verification_append(GString *verification, const gchar *string)
+jabber_caps_verification_append(GString *verification, const gchar *str)
 {
-	verification = g_string_append(verification, string);
+	char *tmp = purple_escape_html(str);
+	verification = g_string_append(verification, tmp);
+	g_free(tmp);
 	return g_string_append_c(verification, '<');
 }
 
@@ -822,9 +824,18 @@
 	/* concat identities to the verification string */
 	for (node = info->identities; node; node = node->next) {
 		JabberIdentity *id = (JabberIdentity*)node->data;
+		char *category = purple_escape_html(id->category);
+		char *type = purple_escape_html(id->type);
+		char *lang = purple_escape_html(id->lang);
+		char *name = purple_escape_html(id->name);
 
-		g_string_append_printf(verification, "%s/%s/%s/%s<", id->category,
-		        id->type, id->lang ? id->lang : "", id->name);
+		g_string_append_printf(verification, "%s/%s/%s/%s<", category,
+		        type, lang ? lang : "", name ? name : "");
+
+		g_free(category);
+		g_free(type);
+		g_free(lang);
+		g_free(name);
 	}
 
 	/* concat features to the verification string */
--- a/libpurple/util.c	Fri May 01 22:40:41 2009 +0000
+++ b/libpurple/util.c	Sat May 02 01:26:18 2009 +0000
@@ -2357,6 +2357,39 @@
 }
 
 char *
+purple_escape_html(const char *str)
+{
+	GString *ret;
+	const char *in = str;
+
+	if (str == NULL)
+		return NULL;
+
+	ret = g_string_sized_new(strlen(str));
+	for ( ; *in; ++in) {
+		switch (*in) {
+			case '&':
+				ret = g_string_append_len(ret, "&amp;", 5);
+				break;
+			case '"':
+				ret = g_string_append_len(ret, "&quot;", 6);
+				break;
+			case '<':
+				ret = g_string_append_len(ret, "&lt;", 4);
+				break;
+			case '>':
+				ret = g_string_append_len(ret, "&gt;", 4);
+				break;
+			default:
+				ret = g_string_append_c(ret, *in);
+				break;
+		}
+	}
+
+	return g_string_free(ret, FALSE);
+}
+
+char *
 purple_unescape_html(const char *html) {
 	if (html != NULL) {
 		const char *c = html;
--- a/libpurple/util.h	Fri May 01 22:40:41 2009 +0000
+++ b/libpurple/util.h	Sat May 02 01:26:18 2009 +0000
@@ -496,7 +496,23 @@
 char *purple_markup_linkify(const char *str);
 
 /**
- * Unescapes HTML entities to their literal characters.
+ * Escape special HTML characters to their HTML entities.
+ * This is almost the reverse of purple_unescape_html except that
+ * this does not translate "\n" into "<br>".
+ *
+ * @param str The string in which to escape special characters.
+ *
+ * @return The text with the special characters escaped. You must
+ *         g_free this string when finished with it.
+ *
+ * @see purple_unescape_html
+ * @since 2.6.0
+ */
+char *purple_escape_html(const char *str);
+
+/**
+ * Unescapes HTML entities to their literal characters. Also translates
+ * "<br>" to "\n".
  * For example "&amp;" is replaced by '&' and so on.
  * Actually only "&amp;", "&quot;", "&lt;" and "&gt;" are currently
  * supported.
@@ -505,6 +521,8 @@
  *
  * @return The text with HTML entities literalized.  You must g_free
  *         this string when finished with it.
+ *
+ * @see purple_escape_html
  */
 char *purple_unescape_html(const char *html);