Mon, 23 Jun 2025 23:13:43 -0500
Remove some unused markup functions
Testing Done:
Called in the turtles.
Reviewed at https://reviews.imfreedom.org/r/4029/
--- a/libpurple/purplemarkup.c Mon Jun 23 22:36:53 2025 -0500 +++ b/libpurple/purplemarkup.c Mon Jun 23 23:13:43 2025 -0500 @@ -24,7 +24,7 @@ #include "util.h" -const char * +static const char * purple_markup_unescape_entity(const char *text, int *length) { const char *pln; @@ -83,559 +83,6 @@ return pln; } -struct purple_parse_tag { - char *src_tag; - char *dest_tag; - gboolean ignore; -}; - -/* NOTE: Do not put `do {} while(0)` around this macro (as this is the method - recommended in the GCC docs). It contains 'continue's that should - affect the while-loop in purple_markup_html_to_xhtml and doing the - above would break that. - Also, remember to put braces in constructs that require them for - multiple statements when using this macro. */ -#define ALLOW_TAG_ALT(x, y) if(!g_ascii_strncasecmp(c, "<" x " ", strlen("<" x " "))) { \ - const char *o = c + strlen("<" x); \ - const char *p = NULL, *q = NULL, *r = NULL; \ - /* o = iterating over full tag \ - * p = > (end of tag) \ - * q = start of quoted bit \ - * r = < inside tag \ - */ \ - GString *innards = g_string_new(""); \ - while(o && *o) { \ - if(!q && (*o == '\"' || *o == '\'') ) { \ - q = o; \ - } else if(q) { \ - if(*o == *q) { /* end of quoted bit */ \ - char *unescaped = g_strndup(q+1, o-q-1); \ - char *escaped = g_markup_escape_text(unescaped, -1); \ - g_string_append_printf(innards, "%c%s%c", *q, escaped, *q); \ - g_free(unescaped); \ - g_free(escaped); \ - q = NULL; \ - } else if(*c == '\\') { \ - o++; \ - } \ - } else if(*o == '<') { \ - r = o; \ - } else if(*o == '>') { \ - p = o; \ - break; \ - } else { \ - innards = g_string_append_c(innards, *o); \ - } \ - o++; \ - } \ - if(p && !r) { /* got an end of tag and no other < earlier */\ - if(*(p-1) != '/') { \ - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); \ - pt->src_tag = x; \ - pt->dest_tag = y; \ - tags = g_list_prepend(tags, pt); \ - } \ - if(xhtml) { \ - xhtml = g_string_append(xhtml, "<" y); \ - xhtml = g_string_append(xhtml, innards->str); \ - xhtml = g_string_append_c(xhtml, '>'); \ - } \ - c = p + 1; \ - } else { /* got end of tag with earlier < *or* didn't get anything */ \ - if(xhtml) \ - xhtml = g_string_append(xhtml, "<"); \ - if(plain) \ - plain = g_string_append_c(plain, '<'); \ - c++; \ - } \ - g_string_free(innards, TRUE); \ - continue; \ - } \ - if(!g_ascii_strncasecmp(c, "<" x, strlen("<" x)) && \ - (*(c+strlen("<" x)) == '>' || \ - !g_ascii_strncasecmp(c+strlen("<" x), "/>", 2))) { \ - if(xhtml) \ - xhtml = g_string_append(xhtml, "<" y); \ - c += strlen("<" x); \ - if(*c != '/') { \ - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); \ - pt->src_tag = x; \ - pt->dest_tag = y; \ - tags = g_list_prepend(tags, pt); \ - if(xhtml) \ - xhtml = g_string_append_c(xhtml, '>'); \ - } else { \ - if(xhtml) \ - xhtml = g_string_append(xhtml, "/>");\ - } \ - c = strchr(c, '>') + 1; \ - continue; \ - } -/* Don't forget to check the note above for ALLOW_TAG_ALT. */ -#define ALLOW_TAG(x) ALLOW_TAG_ALT(x, x) -void -purple_markup_html_to_xhtml(const char *html, char **xhtml_out, - char **plain_out) -{ - GString *xhtml = NULL; - GString *plain = NULL; - GString *url = NULL; - GString *cdata = NULL; - GList *tags = NULL, *tag; - const char *c = html; - char quote = '\0'; - -#define CHECK_QUOTE(ptr) if (*(ptr) == '\'' || *(ptr) == '\"') \ - quote = *(ptr++); \ - else \ - quote = '\0'; - -#define VALID_CHAR(ptr) (*(ptr) && *(ptr) != quote && (quote || (*(ptr) != ' ' && *(ptr) != '>'))) - - g_return_if_fail(xhtml_out != NULL || plain_out != NULL); - - if(xhtml_out) - xhtml = g_string_new(""); - if(plain_out) - plain = g_string_new(""); - - while(c && *c) { - if(*c == '<') { - if(*(c+1) == '/') { /* closing tag */ - tag = tags; - while(tag) { - struct purple_parse_tag *pt = tag->data; - if(!g_ascii_strncasecmp((c+2), pt->src_tag, strlen(pt->src_tag)) && *(c+strlen(pt->src_tag)+2) == '>') { - c += strlen(pt->src_tag) + 3; - break; - } - tag = tag->next; - } - if(tag) { - while(tags) { - struct purple_parse_tag *pt = tags->data; - if(xhtml && !pt->ignore) - g_string_append_printf(xhtml, "</%s>", pt->dest_tag); - if(plain && purple_strequal(pt->src_tag, "a")) { - /* if this is a link, we have to add the url to the plaintext, too */ - if (cdata && url && - (!g_string_equal(cdata, url) && (g_ascii_strncasecmp(url->str, "mailto:", 7) != 0 || - g_utf8_collate(url->str + 7, cdata->str) != 0))) - { - char *unescaped = purple_unescape_html(url->str); - g_string_append_printf(plain, " <%s>", - g_strstrip(unescaped)); - g_free(unescaped); - } - if (cdata) { - g_string_free(cdata, TRUE); - cdata = NULL; - } - - } - if(tags == tag) - break; - tags = g_list_delete_link(tags, tags); - g_free(pt); - } - g_free(tag->data); - tags = g_list_delete_link(tags, tag); - } else { - /* a closing tag we weren't expecting... - * we'll let it slide, if it's really a tag...if it's - * just a </ we'll escape it properly */ - const char *end = c+2; - while(*end && g_ascii_isalpha(*end)) - end++; - if(*end == '>') { - c = end+1; - } else { - if(xhtml) - xhtml = g_string_append(xhtml, "<"); - if(plain) - plain = g_string_append_c(plain, '<'); - c++; - } - } - } else { /* opening tag */ - ALLOW_TAG("blockquote"); - ALLOW_TAG("cite"); - ALLOW_TAG("div"); - ALLOW_TAG("em"); - ALLOW_TAG("h1"); - ALLOW_TAG("h2"); - ALLOW_TAG("h3"); - ALLOW_TAG("h4"); - ALLOW_TAG("h5"); - ALLOW_TAG("h6"); - /* we only allow html to start the message */ - if(c == html) { - ALLOW_TAG("html"); - } - ALLOW_TAG_ALT("i", "em"); - ALLOW_TAG_ALT("italic", "em"); - ALLOW_TAG("li"); - ALLOW_TAG("ol"); - ALLOW_TAG("p"); - ALLOW_TAG("pre"); - ALLOW_TAG("q"); - ALLOW_TAG("span"); - ALLOW_TAG("ul"); - - - /* we skip <HR> because it's not legal in XHTML-IM. However, - * we still want to send something sensible, so we put a - * linebreak in its place. <BR> also needs special handling - * because putting a </BR> to close it would just be dumb. */ - if((!g_ascii_strncasecmp(c, "<br", 3) - || !g_ascii_strncasecmp(c, "<hr", 3)) - && (*(c+3) == '>' || - !g_ascii_strncasecmp(c+3, "/>", 2) || - !g_ascii_strncasecmp(c+3, " />", 3))) { - c = strchr(c, '>') + 1; - if(xhtml) - xhtml = g_string_append(xhtml, "<br/>"); - if(plain && *c != '\n') - plain = g_string_append_c(plain, '\n'); - continue; - } - if(!g_ascii_strncasecmp(c, "<b>", 3) || !g_ascii_strncasecmp(c, "<bold>", strlen("<bold>")) || !g_ascii_strncasecmp(c, "<strong>", strlen("<strong>"))) { - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - if (*(c+2) == '>') - pt->src_tag = "b"; - else if (*(c+2) == 'o') - pt->src_tag = "bold"; - else - pt->src_tag = "strong"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - c = strchr(c, '>') + 1; - if(xhtml) - xhtml = g_string_append(xhtml, "<span style='font-weight: bold;'>"); - continue; - } - if(!g_ascii_strncasecmp(c, "<u>", 3) || !g_ascii_strncasecmp(c, "<underline>", strlen("<underline>"))) { - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = *(c+2) == '>' ? "u" : "underline"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - c = strchr(c, '>') + 1; - if (xhtml) - xhtml = g_string_append(xhtml, "<span style='text-decoration: underline;'>"); - continue; - } - if(!g_ascii_strncasecmp(c, "<s>", 3) || !g_ascii_strncasecmp(c, "<strike>", strlen("<strike>"))) { - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = *(c+2) == '>' ? "s" : "strike"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - c = strchr(c, '>') + 1; - if(xhtml) - xhtml = g_string_append(xhtml, "<span style='text-decoration: line-through;'>"); - continue; - } - if(!g_ascii_strncasecmp(c, "<sub>", 5)) { - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = "sub"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - c = strchr(c, '>') + 1; - if(xhtml) - xhtml = g_string_append(xhtml, "<span style='vertical-align:sub;'>"); - continue; - } - if(!g_ascii_strncasecmp(c, "<sup>", 5)) { - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = "sup"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - c = strchr(c, '>') + 1; - if(xhtml) - xhtml = g_string_append(xhtml, "<span style='vertical-align:super;'>"); - continue; - } - if (!g_ascii_strncasecmp(c, "<img", 4) && (*(c+4) == '>' || *(c+4) == ' ')) { - const char *p = c + 4; - GString *src = NULL, *alt = NULL; -#define ESCAPE(from, to) \ - CHECK_QUOTE(from); \ - while (VALID_CHAR(from)) { \ - int len; \ - if ((*from == '&') && (purple_markup_unescape_entity(from, &len) == NULL)) \ - to = g_string_append(to, "&"); \ - else if (*from == '\'') \ - to = g_string_append(to, "'"); \ - else \ - to = g_string_append_c(to, *from); \ - from++; \ - } - - while (*p && *p != '>') { - if (!g_ascii_strncasecmp(p, "src=", 4)) { - const char *q = p + 4; - if (src) - g_string_free(src, TRUE); - src = g_string_new(""); - ESCAPE(q, src); - p = q; - } else if (!g_ascii_strncasecmp(p, "alt=", 4)) { - const char *q = p + 4; - if (alt) - g_string_free(alt, TRUE); - alt = g_string_new(""); - ESCAPE(q, alt); - p = q; - } else { - p++; - } - } -#undef ESCAPE - if ((c = strchr(p, '>')) != NULL) - c++; - else - c = p; - /* src and alt are required! */ - if(src && xhtml) - g_string_append_printf(xhtml, "<img src='%s' alt='%s' />", g_strstrip(src->str), alt ? alt->str : ""); - if(alt) { - if(plain) { - char *unescaped = purple_unescape_html(alt->str); - plain = g_string_append(plain, unescaped); - g_free(unescaped); - } - if(!src && xhtml) { - xhtml = g_string_append(xhtml, alt->str); - } - g_string_free(alt, TRUE); - } - g_string_free(src, TRUE); - continue; - } - if (!g_ascii_strncasecmp(c, "<a", 2) && (*(c+2) == '>' || *(c+2) == ' ')) { - const char *p = c + 2; - struct purple_parse_tag *pt; - while (*p && *p != '>') { - if (!g_ascii_strncasecmp(p, "href=", 5)) { - const char *q = p + 5; - if (url) - g_string_free(url, TRUE); - url = g_string_new(""); - if (cdata) - g_string_free(cdata, TRUE); - cdata = g_string_new(""); - CHECK_QUOTE(q); - while (VALID_CHAR(q)) { - int len; - if ((*q == '&') && (purple_markup_unescape_entity(q, &len) == NULL)) - url = g_string_append(url, "&"); - else if (*q == '"') - url = g_string_append(url, """); - else - url = g_string_append_c(url, *q); - q++; - } - p = q; - } else { - p++; - } - } - if ((c = strchr(p, '>')) != NULL) - c++; - else - c = p; - pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = "a"; - pt->dest_tag = "a"; - tags = g_list_prepend(tags, pt); - if(xhtml) - g_string_append_printf(xhtml, "<a href=\"%s\">", url ? g_strstrip(url->str) : ""); - continue; - } -#define ESCAPE(from, to) \ - CHECK_QUOTE(from); \ - while (VALID_CHAR(from)) { \ - int len; \ - if ((*from == '&') && (purple_markup_unescape_entity(from, &len) == NULL)) \ - to = g_string_append(to, "&"); \ - else if (*from == '\'') \ - to = g_string_append_c(to, '\"'); \ - else \ - to = g_string_append_c(to, *from); \ - from++; \ - } - if(!g_ascii_strncasecmp(c, "<font", 5) && (*(c+5) == '>' || *(c+5) == ' ')) { - const char *p = c + 5; - GString *style = g_string_new(""); - struct purple_parse_tag *pt; - while (*p && *p != '>') { - if (!g_ascii_strncasecmp(p, "back=", 5)) { - const char *q = p + 5; - GString *color = g_string_new(""); - ESCAPE(q, color); - g_string_append_printf(style, "background: %s; ", color->str); - g_string_free(color, TRUE); - p = q; - } else if (!g_ascii_strncasecmp(p, "color=", 6)) { - const char *q = p + 6; - GString *color = g_string_new(""); - ESCAPE(q, color); - g_string_append_printf(style, "color: %s; ", color->str); - g_string_free(color, TRUE); - p = q; - } else if (!g_ascii_strncasecmp(p, "face=", 5)) { - const char *q = p + 5; - GString *face = g_string_new(""); - ESCAPE(q, face); - g_string_append_printf(style, "font-family: %s; ", g_strstrip(face->str)); - g_string_free(face, TRUE); - p = q; - } else if (!g_ascii_strncasecmp(p, "size=", 5)) { - const char *q = p + 5; - int sz; - const char *size = "medium"; - CHECK_QUOTE(q); - sz = atoi(q); - switch (sz) - { - case 1: - size = "xx-small"; - break; - case 2: - size = "small"; - break; - case 3: - size = "medium"; - break; - case 4: - size = "large"; - break; - case 5: - size = "x-large"; - break; - case 6: - case 7: - size = "xx-large"; - break; - default: - break; - } - g_string_append_printf(style, "font-size: %s; ", size); - p = q; - } else { - p++; - } - } - if ((c = strchr(p, '>')) != NULL) - c++; - else - c = p; - pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = "font"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - if(style->len && xhtml) - g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); - else - pt->ignore = TRUE; - g_string_free(style, TRUE); - continue; - } -#undef ESCAPE - if (!g_ascii_strncasecmp(c, "<body ", 6)) { - const char *p = c + 6; - gboolean did_something = FALSE; - while (*p && *p != '>') { - if (!g_ascii_strncasecmp(p, "bgcolor=", 8)) { - const char *q = p + 8; - struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - GString *color = g_string_new(""); - CHECK_QUOTE(q); - while (VALID_CHAR(q)) { - color = g_string_append_c(color, *q); - q++; - } - if (xhtml) - g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str)); - g_string_free(color, TRUE); - if ((c = strchr(p, '>')) != NULL) - c++; - else - c = p; - pt->src_tag = "body"; - pt->dest_tag = "span"; - tags = g_list_prepend(tags, pt); - did_something = TRUE; - break; - } - p++; - } - if (did_something) continue; - } - /* this has to come after the special case for bgcolor */ - ALLOW_TAG("body"); - if(!g_ascii_strncasecmp(c, "<!--", strlen("<!--"))) { - char *p = strstr(c + strlen("<!--"), "-->"); - if(p) { - if(xhtml) - xhtml = g_string_append(xhtml, "<!--"); - c += strlen("<!--"); - continue; - } - } - - if(xhtml) - xhtml = g_string_append(xhtml, "<"); - if(plain) - plain = g_string_append_c(plain, '<'); - c++; - } - } else if(*c == '&') { - char buf[7]; - const char *pln; - int len; - - if ((pln = purple_markup_unescape_entity(c, &len)) == NULL) { - len = 1; - g_snprintf(buf, sizeof(buf), "%c", *c); - pln = buf; - } - if(xhtml) - xhtml = g_string_append_len(xhtml, c, len); - if(plain) - plain = g_string_append(plain, pln); - if(cdata) - cdata = g_string_append_len(cdata, c, len); - c += len; - } else { - if(xhtml) - xhtml = g_string_append_c(xhtml, *c); - if(plain) - plain = g_string_append_c(plain, *c); - if(cdata) - cdata = g_string_append_c(cdata, *c); - c++; - } - } - if(xhtml) { - for (tag = tags; tag ; tag = tag->next) { - struct purple_parse_tag *pt = tag->data; - if(!pt->ignore) - g_string_append_printf(xhtml, "</%s>", pt->dest_tag); - } - } - g_clear_list(&tags, g_free); - if(xhtml_out) - *xhtml_out = g_string_free_and_steal(xhtml); - if(plain_out) - *plain_out = g_string_free_and_steal(plain); - if(url) - g_string_free(url, TRUE); - if (cdata) - g_string_free(cdata, TRUE); -#undef CHECK_QUOTE -#undef VALID_CHAR -} - /* The following are probably reasonable changes: * - \n should be converted to a normal space * - in addition to <br>, <p> and <div> etc. should also be converted into \n @@ -1126,126 +573,3 @@ return g_string_free_and_steal(ret); } - -char * -purple_markup_slice(const char *str, guint x, guint y) -{ - GString *ret; - GQueue *q; - guint z = 0; - gboolean appended = FALSE; - gunichar c; - char *tag; - - g_return_val_if_fail(str != NULL, NULL); - g_return_val_if_fail(x <= y, NULL); - - if (x == y) - return g_strdup(""); - - ret = g_string_new(""); - q = g_queue_new(); - - while (*str && (z < y)) { - c = g_utf8_get_char(str); - - if (c == '<') { - char *end = strchr(str, '>'); - - if (!end) { - g_string_free(ret, TRUE); - while ((tag = g_queue_pop_head(q))) - g_free(tag); - g_queue_free(q); - return NULL; - } - - if (!g_ascii_strncasecmp(str, "<img ", 5)) { - z += strlen("[Image]"); - } else if (!g_ascii_strncasecmp(str, "<br", 3)) { - z += 1; - } else if (!g_ascii_strncasecmp(str, "<hr>", 4)) { - z += strlen("\n---\n"); - } else if (!g_ascii_strncasecmp(str, "</", 2)) { - /* pop stack */ - char *tmp; - - tmp = g_queue_pop_head(q); - g_free(tmp); - /* z += 0; */ - } else { - /* push it unto the stack */ - char *tmp; - - tmp = g_strndup(str, end - str + 1); - g_queue_push_head(q, tmp); - /* z += 0; */ - } - - if (z >= x) { - g_string_append_len(ret, str, end - str + 1); - } - - str = end; - } else if (c == '&') { - char *end = strchr(str, ';'); - if (!end) { - g_string_free(ret, TRUE); - while ((tag = g_queue_pop_head(q))) - g_free(tag); - g_queue_free(q); - - return NULL; - } - - if (z >= x) - g_string_append_len(ret, str, end - str + 1); - - z++; - str = end; - } else { - if (z == x && z > 0 && !appended) { - GList *l = q->tail; - - while (l) { - tag = l->data; - g_string_append(ret, tag); - l = l->prev; - } - appended = TRUE; - } - - if (z >= x) - g_string_append_unichar(ret, c); - z++; - } - - str = g_utf8_next_char(str); - } - - while ((tag = g_queue_pop_head(q))) { - char *name; - - name = purple_markup_get_tag_name(tag); - g_string_append_printf(ret, "</%s>", name); - g_free(name); - g_free(tag); - } - - g_queue_free(q); - return g_string_free_and_steal(ret); -} - -char * -purple_markup_get_tag_name(const char *tag) -{ - int i; - g_return_val_if_fail(tag != NULL, NULL); - g_return_val_if_fail(*tag == '<', NULL); - - for (i = 1; tag[i]; i++) - if (tag[i] == '>' || tag[i] == ' ' || tag[i] == '/') - break; - - return g_strndup(tag+1, i-1); -}
--- a/libpurple/purplemarkup.h Mon Jun 23 22:36:53 2025 -0500 +++ b/libpurple/purplemarkup.h Mon Jun 23 23:13:43 2025 -0500 @@ -34,20 +34,6 @@ G_BEGIN_DECLS /** - * purple_markup_html_to_xhtml: - * @html: The HTML markup. - * @dest_xhtml: The destination XHTML output. - * @dest_plain: The destination plain-text output. - * - * Converts HTML markup to XHTML. - * - * Since: 2.0 - */ -PURPLE_AVAILABLE_IN_ALL -void purple_markup_html_to_xhtml(const char *html, char **dest_xhtml, - char **dest_plain); - -/** * purple_markup_strip_html: * @str: The string to strip HTML from. * @@ -117,70 +103,6 @@ PURPLE_AVAILABLE_IN_ALL char *purple_unescape_html(const char *html); -/** - * purple_markup_slice: - * @str: The input NUL terminated, HTML, UTF-8 (or ASCII) string. - * @x: The character offset into an unformatted version of str to begin at. - * @y: The character offset (into an unformatted version of str) of one past - * the last character to include in the slice. - * - * Returns a newly allocated substring of the HTML UTF-8 string "str". - * The markup is preserved such that the substring will have the same - * formatting as original string, even though some tags may have been - * opened before "x", or may close after "y". All open tags are closed - * at the end of the returned string, in the proper order. - * - * Note that x and y are in character offsets, not byte offsets, and - * are offsets into an unformatted version of str. Because of this, - * this function may be sensitive to changes in GtkIMHtml and may break - * when used with other UI's. libpurple users are encouraged to report and - * work out any problems encountered. - * - * Returns: The HTML slice of string, with all formatting retained. - * - * Since: 2.0 - */ -PURPLE_AVAILABLE_IN_ALL -char *purple_markup_slice(const char *str, guint x, guint y); - -/** - * purple_markup_get_tag_name: - * @tag: The string starting a HTML tag. - * - * Returns a newly allocated string containing the name of the tag - * located at "tag". Tag is expected to point to a '<', and contain - * a '>' sometime after that. If there is no '>' and the string is - * not NUL terminated, this function can be expected to segfault. - * - * Returns: A string containing the name of the tag. - * - * Since: 2.0 - */ -PURPLE_AVAILABLE_IN_ALL -char *purple_markup_get_tag_name(const char *tag); - -/** - * purple_markup_unescape_entity: - * @text: A string containing an HTML entity. - * @length: If not %NULL, the string length of the entity is stored in this location. - * - * Returns a constant string of the character representation of the HTML - * entity pointed to by @text. For example, purple_markup_unescape_entity("&amp;") - * will return "&". The @text variable is expected to point to an '&', - * the first character of the entity. If given an unrecognized entity, the function - * returns %NULL. - * - * Note that this function, unlike purple_unescape_html(), does not search - * the string for the entity, does not replace the entity, and does not - * return a newly allocated string. - * - * Returns: A constant string containing the character representation of the given entity. - * - * Since: 2.0 - */ -PURPLE_AVAILABLE_IN_ALL -const char * purple_markup_unescape_entity(const char *text, int *length); - G_END_DECLS #endif /* PURPLE_MARKUP_H */
--- a/libpurple/tests/test_markup.c Mon Jun 23 22:36:53 2025 -0500 +++ b/libpurple/tests/test_markup.c Mon Jun 23 23:13:43 2025 -0500 @@ -31,206 +31,6 @@ } MarkupTestData; static void -test_purple_markup_html_to_xhtml(void) { - int i; - MarkupTestData data[] = { - { - "<a>", - "<a href=\"\"></a>", - "", - }, { - "<A href='URL'>ABOUT</a>", - "<a href=\"URL\">ABOUT</a>", - "ABOUT <URL>", - }, { - "<a href='URL'>URL</a>", - "<a href=\"URL\">URL</a>", - "URL", - }, { - "<a href='mailto:mail'>mail</a>", - "<a href=\"mailto:mail\">mail</a>", - "mail", - }, { - "<A href='\"U'R&L'>ABOUT</a>", - "<a href=\""U'R&L\">ABOUT</a>", - "ABOUT <\"U'R&L>", - }, { - "<img src='SRC' alt='ALT'/>", - "<img src='SRC' alt='ALT' />", - "ALT", - }, { - "<img src=\"'S'R&C\" alt=\"'A'L&T\"/>", - "<img src=''S'R&C' alt=''A'L&T' />", - "'A'L&T", - }, { - "<unknown>", - "<unknown>", - "<unknown>", - }, { - "é&", - "é&", - "é&", - }, { - "<h1>A<h2>B</h2>C</h1>", - "<h1>A<h2>B</h2>C</h1>", - "ABC", - }, { - "<h1><h2><h3><h4>", - "<h1><h2><h3><h4></h4></h3></h2></h1>", - "", - }, { - "<italic/>", - "<em/>", - "", - }, { - "</", - "</", - "</", - }, { - "</div>", - "", - "", - }, { - "<hr/>", - "<br/>", - "\n", - }, { - "<hr>", - "<br/>", - "\n", - }, { - "<br />", - "<br/>", - "\n", - }, { - "<br>INSIDE</br>", - "<br/>INSIDE", - "\nINSIDE", - }, { - "<div></div>", - "<div></div>", - "", - }, { - "<div/>", - "<div/>", - "", - }, { - "<div attr='\"&<>'/>", - "<div attr='"&<>'/>", - "", - }, { - "<div attr=\"'\"/>", - "<div attr=\"'\"/>", - "", - }, { - "<div/> < <div/>", - "<div/> < <div/>", - " < ", - }, { - "<div>x</div>", - "<div>x</div>", - "x", - }, { - "<b>x</b>", - "<span style='font-weight: bold;'>x</span>", - "x", - }, { - "<bold>x</bold>", - "<span style='font-weight: bold;'>x</span>", - "x", - }, { - "<strong>x</strong>", - "<span style='font-weight: bold;'>x</span>", - "x", - }, { - "<u>x</u>", - "<span style='text-decoration: underline;'>x</span>", - "x", - }, { - "<underline>x</underline>", - "<span style='text-decoration: underline;'>x</span>", - "x", - }, { - "<s>x</s>", - "<span style='text-decoration: line-through;'>x</span>", - "x", - }, { - "<strike>x</strike>", - "<span style='text-decoration: line-through;'>x</span>", - "x", - }, { - "<sub>x</sub>", - "<span style='vertical-align:sub;'>x</span>", - "x", - }, { - "<sup>x</sup>", - "<span style='vertical-align:super;'>x</span>", - "x", - }, { - "<FONT>x</FONT>", - "x", - "x", - }, { - "<font face=\"'Times>New & Roman'\">x</font>", - "<span style='font-family: \"Times>New & Roman\";'>x</span>", - "x", - }, { - "<font back=\"'color>blue&red'\">x</font>", - "<span style='background: \"color>blue&red\";'>x</span>", - "x", - }, { - "<font color=\"'color>blue&red'\">x</font>", - "<span style='color: \"color>blue&red\";'>x</span>", - "x", - }, { - "<font size=1>x</font>", - "<span style='font-size: xx-small;'>x</span>", - "x", - }, { - "<font size=432>x</font>", - "<span style='font-size: medium;'>x</span>", - "x", - }, { - "<!--COMMENT-->", - "<!--COMMENT-->", - "COMMENT-->", - }, { - "<br />", - "<br />", - "<br />", - }, { - "<hr />", - "<hr />", - "<hr />" - }, { - NULL, NULL, NULL, - } - }; - - for(i = 0; data[i].markup; i++) { - char *xhtml = NULL, *plaintext = NULL; - - purple_markup_html_to_xhtml(data[i].markup, &xhtml, &plaintext); - - g_assert_cmpstr(data[i].xhtml, ==, xhtml); - g_free(xhtml); - - g_assert_cmpstr(data[i].plaintext, ==, plaintext); - g_free(plaintext); - - /* Check only asking for xhtml works. */ - purple_markup_html_to_xhtml(data[i].markup, &xhtml, NULL); - g_assert_cmpstr(data[i].xhtml, ==, xhtml); - g_free(xhtml); - - /* Check only asking for plaintext works. */ - purple_markup_html_to_xhtml(data[i].markup, NULL, &plaintext); - g_assert_cmpstr(data[i].plaintext, ==, plaintext); - g_free(plaintext); - } -} - -static void test_purple_markup_strip_html(void) { MarkupTestData data[] = { { @@ -284,8 +84,6 @@ g_test_init(&argc, &argv, NULL); g_test_set_nonfatal_assertions(); - g_test_add_func("/util/markup/html-to-xhtml", - test_purple_markup_html_to_xhtml); g_test_add_func("/util/markup/strip-html", test_purple_markup_strip_html);