From f264b93590916f9f223528c8c97c823009b4dad8 Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Mon, 9 Aug 2010 13:23:15 +0300 Subject: [PATCH] Fix for bug #3002993: Group Name issues with ampersand sipe-xml.c didn't unescape XML attribute values like the original purple implementation did. --- ChangeLog | 1 + src/core/sipe-xml.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 034c3abe..1593e142 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ version 1.11.0 "Lotus Domino/Calendar & Voice Call" (2010-XX-XX) - Fixed #2982424: krb5 build errors on FreeBSD (Stefan Becker) - Fixed #2997639: pidgin crash after accepting cert (Stefan Becker) - Fixed #3001523: Cancelling a long pending file transfer crashes Pidgin (Jakub Adam) + - Fixed #3002993: Group Name issues with ampersand (Stefan Becker) - Fixed #3029228: Calendar published at/with incorrect time (Stefan Becker) - Fixed #3029929: Crash with outlook 2k3 Calendar (Stefan Becker) - Fix logout from OCS (Jakub Adam) diff --git a/src/core/sipe-xml.c b/src/core/sipe-xml.c index a966ae06..1f602738 100644 --- a/src/core/sipe-xml.c +++ b/src/core/sipe-xml.c @@ -24,6 +24,8 @@ * This code is loosely based on libpurple xmlnode.c */ +#include +#include #include #include #include @@ -51,6 +53,75 @@ struct _parser_data { gboolean error; }; +static const gchar *unescape_entity(const gchar *text, guint *length) +{ + const char *pln; + int len, pound; + char temp[2]; + + if (!text || *text != '&') return NULL; + +#define IS_ENTITY(s) (!g_ascii_strncasecmp(text, s, (len = sizeof(s) - 1))) + + if (IS_ENTITY("&")) + pln = "&"; + else if (IS_ENTITY("<")) + pln = "<"; + else if (IS_ENTITY(">")) + pln = ">"; + else if (IS_ENTITY(" ")) + pln = " "; + else if (IS_ENTITY("©")) + pln = "\302\251"; /* or use g_unichar_to_utf8(0xa9); */ + else if (IS_ENTITY(""")) + pln = "\""; + else if (IS_ENTITY("®")) + pln = "\302\256"; /* or use g_unichar_to_utf8(0xae); */ + else if (IS_ENTITY("'")) + pln = "\'"; + else if ((*(text + 1) == '#') && + ((sscanf(text, "&#%u%1[;]", £, temp) == 2) || + (sscanf(text, "&#x%x%1[;]", £, temp) == 2)) && + (pound != 0)) { + static gchar buf[7]; + guint buflen = g_unichar_to_utf8((gunichar)pound, buf); + buf[buflen] = '\0'; + pln = buf; + + len = (*(text + 2) == 'x' ? 3 : 2); + while (isxdigit((gint) text[len])) len++; + if (text[len] == ';') len++; + } else + return NULL; + + if (length) + *length = len; + return pln; +} + +static gchar *unescape_text(const gchar *escaped) +{ + GString *unescaped; + + if (!escaped) return NULL; + + unescaped = g_string_new(""); + while (*escaped) { + guint len; + const gchar *entity; + + if ((entity = unescape_entity(escaped, &len)) != NULL) { + g_string_append(unescaped, entity); + escaped += len; + } else { + g_string_append_c(unescaped, *escaped); + escaped++; + } + } + + return g_string_free(unescaped, FALSE); +} + static void callback_start_element(void *user_data, const xmlChar *name, const xmlChar **attrs) { struct _parser_data *pd = user_data; @@ -92,7 +163,7 @@ static void callback_start_element(void *user_data, const xmlChar *name, const x } g_hash_table_insert(node->attributes, g_strdup((gchar *) key), - g_strdup((gchar *) *attrs++)); + unescape_text((gchar *) *attrs++)); } } -- 2.11.4.GIT