# HG changeset patch # User Paul Aurich # Date 1241227578 0 # Node ID e72df47d41fe9ff66e2c5966a1bbff7f0939f927 # Parent 7c1ecd0727db25bdf65d416bd7bea9d9f9413a67 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] turns into 'client/pc//SomeClient, which is a collision, right? diff -r 7c1ecd0727db -r e72df47d41fe ChangeLog.API --- 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 diff -r 7c1ecd0727db -r e72df47d41fe libpurple/protocols/jabber/caps.c --- 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 */ diff -r 7c1ecd0727db -r e72df47d41fe libpurple/util.c --- 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, "&", 5); + break; + case '"': + ret = g_string_append_len(ret, """, 6); + break; + case '<': + ret = g_string_append_len(ret, "<", 4); + break; + case '>': + ret = g_string_append_len(ret, ">", 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; diff -r 7c1ecd0727db -r e72df47d41fe libpurple/util.h --- 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 "
". + * + * @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 + * "
" to "\n". * For example "&" is replaced by '&' and so on. * Actually only "&", """, "<" and ">" 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);