changeset 28020:df76369ffde4

merge of 'a34b37757cd241377842a2da55e7c7ece45d69dd' and 'e4c44c708110388bc6b4646a63b5749285e0e820'
author Paul Aurich <paul@darkrain42.org>
date Thu, 20 Aug 2009 03:40:18 +0000
parents 9fa1de6d508a (current diff) 5ff49aa05439 (diff)
children a3bcf06057f0
files
diffstat 2 files changed, 108 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/yahoo/util.c	Thu Aug 20 03:40:09 2009 +0000
+++ b/libpurple/protocols/yahoo/util.c	Thu Aug 20 03:40:18 2009 +0000
@@ -660,7 +660,7 @@
 	xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13);
 	g_free(xmlstr1);
 
-	purple_debug_misc("yahoo", "yahoo_codes_to_html:  Returning string: '%s'.\n", xmlstr2);
+	purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", x, xmlstr2);
 	return xmlstr2;
 }
 
@@ -669,25 +669,6 @@
 #define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1])
 static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
 
-enum fontattr_type
-{
-	FATYPE_SIZE,
-	FATYPE_COLOR,
-	FATYPE_FACE,
-	FATYPE_JUNK
-};
-
-typedef struct
-{
-	enum fontattr_type type;
-	union {
-		int size;
-		char *color;
-		char *face;
-		char *junk;
-	} u;
-} fontattr;
-
 typedef struct
 {
 	gboolean bold;
@@ -699,15 +680,6 @@
 	char *font_color;
 } CurrentMsgState;
 
-static void fontattr_free(fontattr *f)
-{
-	if (f->type == FATYPE_COLOR)
-		g_free(f->u.color);
-	else if (f->type == FATYPE_FACE)
-		g_free(f->u.face);
-	g_free(f);
-}
-
 static void yahoo_htc_list_cleanup(GSList *l)
 {
 	while (l != NULL) {
@@ -716,177 +688,74 @@
 	}
 }
 
-static void _parse_font_tag(const char *src, GString *dest, int *i, int *j,
-				int len, GSList **colors, GSList **tags, GQueue *ftattr)
+static void parse_font_tag(const char *src, GString *dest, const char *tag_name, const char *tag,
+				int src_len, GSList **colors, GSList **tags)
 {
-	int m, n, vstart;
-	gboolean quote = FALSE, done = FALSE;
+	const char *start;
+	const char *end;
+	GData *attributes;
+	const char *attribute;
+	gboolean needendtag;
+	GString *tmp;
 
-	m = *j;
+	purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+
+	needendtag = FALSE;
+	tmp = g_string_new(NULL);
 
-	while (1) {
-		m++;
+	attribute = g_datalist_get_data(&attributes, "color");
+	if (attribute != NULL) {
+		g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
+		g_string_append_printf(dest, "\033[%sm", attribute);
+		*colors = g_slist_prepend(*colors,
+				g_strdup_printf("\033[%sm", attribute));
+	}
 
-		if (m >= len) {
-			g_string_append(dest, &src[*i]);
-			*i = len;
-			break;
+	attribute = g_datalist_get_data(&attributes, "face");
+	if (attribute != NULL) {
+		needendtag = TRUE;
+		g_string_append(dest, "<font ");
+		g_string_append_printf(dest, "face=\"%s\" ", attribute);
+	}
+
+	attribute = g_datalist_get_data(&attributes, "size");
+	if (attribute != NULL) {
+		if (!needendtag) {
+			needendtag = TRUE;
+			g_string_append(dest, "<font ");
 		}
 
-		if (src[m] == '=') {
-			n = vstart = m;
-			while (1) {
-				n++;
-
-				if (n >= len) {
-					m = n;
-					break;
-				}
-
-				if (src[n] == '"') {
-					if (!quote) {
-						quote = TRUE;
-						vstart = n;
-						continue;
-					} else {
-						done = 1;
-					}
-				}
-
-				if (!quote && ((src[n] == ' ') || (src[n] == '>')))
-					done = TRUE;
-
-				if (done) {
-					if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) {
-						fontattr *f;
-
-						f = g_new(fontattr, 1);
-						f->type = FATYPE_FACE;
-						f->u.face = g_strndup(&src[vstart+1], n-vstart-1);
-						if (!ftattr)
-							ftattr = g_queue_new();
-						g_queue_push_tail(ftattr, f);
-						m = n;
-						break;
-					} else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) {
-						fontattr *f;
-
-						f = g_new(fontattr, 1);
-						f->type = FATYPE_SIZE;
-						f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10));
-						if (!ftattr)
-							ftattr = g_queue_new();
-						g_queue_push_tail(ftattr, f);
-						m = n;
-						break;
-					} else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) {
-						fontattr *f;
-
-						f = g_new(fontattr, 1);
-						f->type = FATYPE_COLOR;
-						f->u.color = g_strndup(&src[vstart+1], n-vstart-1);
-						if (!ftattr)
-							ftattr = g_queue_new();
-						g_queue_push_head(ftattr, f);
-						m = n;
-						break;
-					} else {
-						fontattr *f;
-
-						f = g_new(fontattr, 1);
-						f->type = FATYPE_JUNK;
-						f->u.junk = g_strndup(&src[*j+1], n-*j);
-						if (!ftattr)
-							ftattr = g_queue_new();
-						g_queue_push_tail(ftattr, f);
-						m = n;
-						break;
-					}
+		g_string_append_printf(dest, "size=\"%d\" ",
+				POINT_SIZE(strtol(attribute, NULL, 10)));
+	}
 
-				}
-			}
-		}
-
-		if (src[m] == ' ')
-			*j = m;
-
-		if (src[m] == '>') {
-			gboolean needendtag = FALSE;
-			fontattr *f;
-			GString *tmp = g_string_new(NULL);
-
-			if (!g_queue_is_empty(ftattr)) {
-				while ((f = g_queue_pop_tail(ftattr))) {
-					switch (f->type) {
-					case FATYPE_SIZE:
-						if (!needendtag) {
-							needendtag = TRUE;
-							g_string_append(dest, "<font ");
-						}
-
-						g_string_append_printf(dest, "size=\"%d\" ", f->u.size);
-						break;
-					case FATYPE_FACE:
-						if (!needendtag) {
-							needendtag = TRUE;
-							g_string_append(dest, "<font ");
-						}
-
-						g_string_append_printf(dest, "face=\"%s\" ", f->u.face);
-						break;
-					case FATYPE_JUNK:
-						if (!needendtag) {
-							needendtag = TRUE;
-							g_string_append(dest, "<font ");
-						}
+	if (needendtag) {
+		dest->str[dest->len-1] = '>';
+		*tags = g_slist_prepend(*tags, g_strdup("</font>"));
+		g_string_free(tmp, TRUE);
+	} else {
+		*tags = g_slist_prepend(*tags, tmp->str);
+		g_string_free(tmp, FALSE);
+	}
 
-						g_string_append(dest, f->u.junk);
-						break;
-
-					case FATYPE_COLOR:
-						if (needendtag) {
-							g_string_append(tmp, "</font>");
-							dest->str[dest->len-1] = '>';
-							needendtag = TRUE;
-						}
-
-						g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
-						g_string_append_printf(dest, "\033[%sm", f->u.color);
-						*colors = g_slist_prepend(*colors,
-								g_strdup_printf("\033[%sm", f->u.color));
-						break;
-					}
-					fontattr_free(f);
-				}
-
-				g_queue_free(ftattr);
-				ftattr = NULL;
-
-				if (needendtag) {
-					dest->str[dest->len-1] = '>';
-					*tags = g_slist_prepend(*tags, g_strdup("</font>"));
-					g_string_free(tmp, TRUE);
-				} else {
-					*tags = g_slist_prepend(*tags, tmp->str);
-					g_string_free(tmp, FALSE);
-				}
-			}
-
-			*i = *j = m;
-			break;
-		}
-	}
+	g_datalist_clear(&attributes);
 }
 
 char *yahoo_html_to_codes(const char *src)
 {
 	GSList *colors = NULL;
+
+	/**
+	 * A stack of char*s where each char* is the string that should be
+	 * appended to dest in order to close all the tags that were opened
+	 * by a <font> tag.
+	 */
 	GSList *tags = NULL;
+
 	size_t src_len;
 	int i, j;
 	GString *dest;
 	char *esc;
-	GQueue *ftattr = NULL;
 	gboolean no_more_gt_brackets = FALSE;
 	gchar *tag, *tag_name;
 	gboolean is_closing_tag;
@@ -929,35 +798,40 @@
 				tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
 
 				if (g_str_equal(tag_name, "a")) {
-					j += 7;
-					g_string_append(dest, "\033[lm");
-					if (purple_str_has_prefix(src + j, "mailto:"))
-						j += sizeof("mailto:") - 1;
-					while (1) {
-						g_string_append_c(dest, src[j]);
-						if (++j >= src_len) {
-							i = src_len;
-							break;
-						}
-						if (src[j] == '"') {
-							g_string_append(dest, "\033[xlm");
-							while (1) {
-								if (++j >= src_len) {
-									i = src_len;
-									break;
-								}
-								if (!g_ascii_strncasecmp(&src[j], "</A>", 4)) {
-									j += 3;
-									break;
-								}
-							}
-							i = j;
-							break;
-						}
+					const char *start;
+					const char *end;
+					GData *attributes;
+					const char *attribute;
+
+					/*
+					 * TODO: Ideally we would replace this:
+					 * <a href="http://pidgin.im/">Pidgin</a>
+					 * with this:
+					 * Pidgin (http://pidgin.im/)
+					 *
+					 * Currently we drop the text within the <a> tag and
+					 * just show the URL.  Doing it the fancy way is
+					 * complicated when dealing with HTML tags within the
+					 * <a> tag.
+					 */
+
+					/* Append the URL */
+					purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+					attribute = g_datalist_get_data(&attributes, "href");
+					if (attribute != NULL) {
+						if (purple_str_has_prefix(attribute, "mailto:"))
+							attribute += 7;
+						g_string_append(dest, attribute);
 					}
+					g_datalist_clear(&attributes);
+
+					/* Skip past the closing </a> tag */
+					end = purple_strcasestr(src + j, "</a>");
+					if (end != NULL)
+						j = end - src + 3;
 
 				} else if (g_str_equal(tag_name, "font")) {
-					_parse_font_tag(src, dest, &i, &j, src_len, &colors, &tags, ftattr);
+					parse_font_tag(src, dest, tag_name, tag, src_len, &colors, &tags);
 				} else if (g_str_equal(tag_name, "b")) {
 					g_string_append(dest, "\033[1m");
 					current_state.bold = TRUE;
@@ -983,7 +857,7 @@
 						current_state.underline = FALSE;
 					}
 				} else if (g_str_equal(tag_name, "/a")) {
-					g_string_append(dest, "\033[xlm");
+					/* Do nothing */
 				} else if (g_str_equal(tag_name, "br")) {
 					g_string_append_c(dest, '\n');
 				} else if (g_str_equal(tag_name, "/font")) {
@@ -1023,7 +897,7 @@
 	}
 
 	esc = g_strescape(dest->str, NULL);
-	purple_debug_misc("yahoo", "yahoo_html_to_codes:  Returning string: '%s'.\n", esc);
+	purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc);
 	g_free(esc);
 
 	yahoo_htc_list_cleanup(colors);
--- a/libpurple/tests/test_yahoo_util.c	Thu Aug 20 03:40:09 2009 +0000
+++ b/libpurple/tests/test_yahoo_util.c	Thu Aug 20 03:40:18 2009 +0000
@@ -142,6 +142,30 @@
 			yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> italic</i>"));
 	assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m",
 			yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>"));
+
+	/* link */
+	assert_string_equal_free("http://pidgin.im/",
+			yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>"));
+	assert_string_equal_free("mark@example.com",
+			yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>"));
+#if 0
+	assert_string_equal_free("http://pidgin.im/",
+			yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>"));
+#endif
+
+	/* font nothing */
+	assert_string_equal_free("nothing",
+			yahoo_html_to_codes("<font>nothing</font>"));
+
+	/* font color */
+	assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m",
+			yahoo_html_to_codes("<font color=\"#E71414\">red</font>"));
+
+	/* font size */
+	assert_string_equal_free("<font size=\"10\">test</font>",
+			yahoo_html_to_codes("<font size=\"2\">test</font>"));
+	assert_string_equal_free("<font size=\"30\">test</font>",
+			yahoo_html_to_codes("<font size=\"6\">test</font>"));
 }
 END_TEST