Correctly parse "<br>" in an XML attribute. Closes #11318.
If nobody has objections, I intend to add purple_unescape_text() to
util.[ch] for 2.7.0.
1.1 --- a/ChangeLog
1.2 +++ b/ChangeLog
1.3 @@ -10,6 +10,8 @@
1.4 * When looking up DNS records, use the type of record returned by the
1.5 server (instead of the type we asked for) to determine how to process
1.6 the record.
1.7 + * Fix an issue with parsing XML attributes that contain "<br>".
1.8 + See ChangeLog.API for more details.
1.9
1.10 General:
1.11 * Correctly disable all missing dependencies when using the
2.1 --- a/ChangeLog.API
2.2 +++ b/ChangeLog.API
2.3 @@ -7,6 +7,12 @@
2.4 purple_xfer_request_denied if an error is found when selecting
2.5 a file to send. Request denied is still used when a receive
2.6 request is not allowed.
2.7 + * xmlnode_from_str now properly handles paring an attribute which
2.8 + contain "<br>", which were previously transformed into a
2.9 + newline character (libxml2 unescapes all entities except
2.10 + representations of '&', and libpurple's purple_unescape_html
2.11 + converts "<br>" to a newline).
2.12 +
2.13 Perl:
2.14 Changed:
2.15 * Corrected the package names for the PurpleProxyType and
3.1 --- a/libpurple/protocols/bonjour/parser.c
3.2 +++ b/libpurple/protocols/bonjour/parser.c
3.3 @@ -49,6 +49,31 @@
3.4 return FALSE;
3.5 }
3.6
3.7 +static char *purple_unescape_text(const char *in)
3.8 +{
3.9 + GString *ret;
3.10 + const char *c = in;
3.11 +
3.12 + if (in == NULL)
3.13 + return NULL;
3.14 +
3.15 + ret = g_string_new("");
3.16 + while (*c) {
3.17 + int len;
3.18 + const char *ent;
3.19 +
3.20 + if ((ent = purple_markup_unescape_entity(c, &len)) != NULL) {
3.21 + g_string_append(ret, ent);
3.22 + c += len;
3.23 + } else {
3.24 + g_string_append_c(ret, *c);
3.25 + c++;
3.26 + }
3.27 + }
3.28 +
3.29 + return g_string_free(ret, FALSE);
3.30 +}
3.31 +
3.32 static void
3.33 bonjour_parser_element_start_libxml(void *user_data,
3.34 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace,
3.35 @@ -102,7 +127,7 @@
3.36 attrib[attrib_len] = '\0';
3.37
3.38 txt = attrib;
3.39 - attrib = purple_unescape_html(txt);
3.40 + attrib = purple_unescape_text(txt);
3.41 g_free(txt);
3.42 xmlnode_set_attrib_full(node, name, attrib_ns, prefix, attrib);
3.43 g_free(attrib);
4.1 --- a/libpurple/protocols/jabber/parser.c
4.2 +++ b/libpurple/protocols/jabber/parser.c
4.3 @@ -31,6 +31,31 @@
4.4 #include "util.h"
4.5 #include "xmlnode.h"
4.6
4.7 +static char *purple_unescape_text(const char *in)
4.8 +{
4.9 + GString *ret;
4.10 + const char *c = in;
4.11 +
4.12 + if (in == NULL)
4.13 + return NULL;
4.14 +
4.15 + ret = g_string_new("");
4.16 + while (*c) {
4.17 + int len;
4.18 + const char *ent;
4.19 +
4.20 + if ((ent = purple_markup_unescape_entity(c, &len)) != NULL) {
4.21 + g_string_append(ret, ent);
4.22 + c += len;
4.23 + } else {
4.24 + g_string_append_c(ret, *c);
4.25 + c++;
4.26 + }
4.27 + }
4.28 +
4.29 + return g_string_free(ret, FALSE);
4.30 +}
4.31 +
4.32 static void
4.33 jabber_parser_element_start_libxml(void *user_data,
4.34 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace,
4.35 @@ -89,7 +114,7 @@
4.36 char *attrib = g_strndup((gchar *)attributes[i+3], attrib_len);
4.37
4.38 txt = attrib;
4.39 - attrib = purple_unescape_html(txt);
4.40 + attrib = purple_unescape_text(txt);
4.41 g_free(txt);
4.42 xmlnode_set_attrib_full(node, name, attrib_ns, prefix, attrib);
4.43 g_free(attrib);
5.1 --- a/libpurple/xmlnode.c
5.2 +++ b/libpurple/xmlnode.c
5.3 @@ -545,6 +545,31 @@
5.4 return xml_with_declaration;
5.5 }
5.6
5.7 +static char *purple_unescape_text(const char *in)
5.8 +{
5.9 + GString *ret;
5.10 + const char *c = in;
5.11 +
5.12 + if (in == NULL)
5.13 + return NULL;
5.14 +
5.15 + ret = g_string_new("");
5.16 + while (*c) {
5.17 + int len;
5.18 + const char *ent;
5.19 +
5.20 + if ((ent = purple_markup_unescape_entity(c, &len)) != NULL) {
5.21 + g_string_append(ret, ent);
5.22 + c += len;
5.23 + } else {
5.24 + g_string_append_c(ret, *c);
5.25 + c++;
5.26 + }
5.27 + }
5.28 +
5.29 + return g_string_free(ret, FALSE);
5.30 +}
5.31 +
5.32 struct _xmlnode_parser_data {
5.33 xmlnode *current;
5.34 gboolean error;
5.35 @@ -590,7 +615,7 @@
5.36 int attrib_len = attributes[i+4] - attributes[i+3];
5.37 char *attrib = g_strndup((const char *)attributes[i+3], attrib_len);
5.38 txt = attrib;
5.39 - attrib = purple_unescape_html(txt);
5.40 + attrib = purple_unescape_text(txt);
5.41 g_free(txt);
5.42 xmlnode_set_attrib_full(node, name, NULL, prefix, attrib);
5.43 g_free(attrib);