From 7e6119378401be13db70e78cf249104e86a9101e Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Mon, 31 Mar 2003 21:54:46 +0000 Subject: Use strncasecmp for matching the nofill and /nofill tags. Also fixed to 2003-03-31 Jeffrey Stedfast * camel-mime-filter-enriched.c (enriched_to_html): Use strncasecmp for matching the nofill and /nofill tags. Also fixed to handle enriched tags that require tags. svn path=/trunk/; revision=20603 --- camel/ChangeLog | 6 + camel/camel-mime-filter-enriched.c | 278 +++++++++++++++++++++++++++++++------ 2 files changed, 243 insertions(+), 41 deletions(-) (limited to 'camel') diff --git a/camel/ChangeLog b/camel/ChangeLog index 518237af2e..a7022b0cc7 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,9 @@ +2003-03-31 Jeffrey Stedfast + + * camel-mime-filter-enriched.c (enriched_to_html): Use strncasecmp + for matching the nofill and /nofill tags. Also fixed to handle + enriched tags that require tags. + 2003-03-28 Not Zed * providers/local/camel-spool-store.c (get_folder): remove unused diff --git a/camel/camel-mime-filter-enriched.c b/camel/camel-mime-filter-enriched.c index 349a56d07b..23ffd73493 100644 --- a/camel/camel-mime-filter-enriched.c +++ b/camel/camel-mime-filter-enriched.c @@ -32,38 +32,62 @@ #include "camel-mime-filter-enriched.h" +/* text/enriched is rfc1896 */ + +typedef char * (*EnrichedParamParser) (const char *inptr, int inlen); + +static char *param_parse_colour (const char *inptr, int inlen); +static char *param_parse_font (const char *inptr, int inlen); +static char *param_parse_lang (const char *inptr, int inlen); + static struct { char *enriched; char *html; + gboolean needs_param; + EnrichedParamParser parse_param; /* parses *and* validates the input */ } enriched_tags[] = { - { "bold", "" }, - { "/bold", "" }, - { "italic", "" }, - { "/italic", "" }, - { "fixed", "" }, - { "/fixed", "" }, - { "smaller", "" }, - { "/smaller", "" }, - { "bigger", "" }, - { "/bigger", "" }, - { "underline", "" }, - { "/underline", "" }, - { "center", "

" }, - { "/center", "

" }, - { "flushleft", "

" }, - { "/flushleft", "

" }, - { "flushright", "

" }, - { "/flushright", "

" }, - { "excerpt", "
" }, - { "/excerpt", "
" }, - { "paragraph", "

" }, - { "signature", "

" }, - { "/signature", "
" }, - { "comment", "" }, - { "param", "" }, - { "np", "
" } + { "bold", "", FALSE, NULL }, + { "/bold", "", FALSE, NULL }, + { "italic", "", FALSE, NULL }, + { "/italic", "", FALSE, NULL }, + { "fixed", "", FALSE, NULL }, + { "/fixed", "", FALSE, NULL }, + { "smaller", "", FALSE, NULL }, + { "/smaller", "", FALSE, NULL }, + { "bigger", "", FALSE, NULL }, + { "/bigger", "", FALSE, NULL }, + { "underline", "", FALSE, NULL }, + { "/underline", "", FALSE, NULL }, + { "center", "

", FALSE, NULL }, + { "/center", "

", FALSE, NULL }, + { "flushleft", "

", FALSE, NULL }, + { "/flushleft", "

", FALSE, NULL }, + { "flushright", "

", FALSE, NULL }, + { "/flushright", "

", FALSE, NULL }, + { "excerpt", "
", FALSE, NULL }, + { "/excerpt", "
", FALSE, NULL }, + { "paragraph", "

", FALSE, NULL }, + { "signature", "

", FALSE, NULL }, + { "/signature", "
", FALSE, NULL }, + { "comment", "", FALSE, NULL }, + { "np", "
", FALSE, NULL }, + { "fontfamily", "", TRUE, param_parse_font }, + { "/fontfamily", "", FALSE, NULL }, + { "color", "", TRUE, param_parse_colour }, + { "/color", "", FALSE, NULL }, + { "lang", "", TRUE, param_parse_lang }, + { "/lang", "", FALSE, NULL }, + + /* don't handle this tag yet... */ + { "paraindent", "", FALSE, NULL }, + + /* as soon as we support all the tags that can have a param + * tag argument, these should be unnecessary, but we'll keep + * them anyway just in case? */ + { "param", "", FALSE, NULL }, }; #define NUM_ENRICHED_TAGS (sizeof (enriched_tags) / sizeof (enriched_tags[0])) @@ -137,6 +161,119 @@ camel_mime_filter_enriched_init (CamelMimeFilterEnriched *filter) filter->nofill = 0; } + +#if 0 +static gboolean +enriched_tag_needs_param (const char *tag) +{ + int i; + + for (i = 0; i < NUM_ENRICHED_TAGS; i++) + if (!strcasecmp (tag, enriched_tags[i].enriched)) + return enriched_tags[i].needs_param; + + return FALSE; +} +#endif + +static gboolean +html_tag_needs_param (const char *tag) +{ + return strstr (tag, "%s") != NULL; +} + +static const char *valid_colours[] = { + "red", "green", "blue", "yellow", "cyan", "magenta", "black", "white" +}; + +#define NUM_VALID_COLOURS (sizeof (valid_colours) / sizeof (valid_colours[0])) + +static char * +param_parse_colour (const char *inptr, int inlen) +{ + const char *inend, *end; + guint32 rgb = 0; + guint v; + int i; + + for (i = 0; i < NUM_VALID_COLOURS; i++) { + if (!strncasecmp (inptr, valid_colours[i], inlen)) + return g_strdup (valid_colours[i]); + } + + /* check for numeric r/g/b in the format: ####,####,#### */ + if (inptr[4] != ',' || inptr[9] != ',') { + /* okay, mailer must have used a string name that + * rfc1896 did not specify? do some simple scanning + * action, a colour name MUST be [a-zA-Z] */ + end = inptr; + inend = inptr + inlen; + while (end < inend && ((*end >= 'a' && *end <= 'z') || (*end >= 'A' && *end <= 'Z'))) + end++; + + return g_strndup (inptr, end - inptr); + } + + for (i = 0; i < 3; i++) { + v = strtoul (inptr, (char **) &end, 16); + if (end != inptr + 4) + goto invalid_format; + + v >>= 8; + rgb = (rgb << 8) | (v & 0xff); + + inptr += 5; + } + + return g_strdup_printf ("#%.6X", rgb); + + invalid_format: + + /* default colour? */ + return g_strdup ("black"); +} + +static char * +param_parse_font (const char *fontfamily, int inlen) +{ + register const char *inptr = fontfamily; + const char *inend = inptr + inlen; + + /* don't allow any of '"', '<', nor '>' */ + while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>') + inptr++; + + return g_strndup (fontfamily, inptr - fontfamily); +} + +static char * +param_parse_lang (const char *lang, int inlen) +{ + register const char *inptr = lang; + const char *inend = inptr + inlen; + + /* don't allow any of '"', '<', nor '>' */ + while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>') + inptr++; + + return g_strndup (lang, inptr - lang); +} + +static char * +param_parse (const char *enriched, const char *inptr, int inlen) +{ + int i; + + for (i = 0; i < NUM_ENRICHED_TAGS; i++) { + if (!strcasecmp (enriched, enriched_tags[i].enriched)) + return enriched_tags[i].parse_param (inptr, inlen); + } + + g_assert_not_reached (); + + return NULL; +} + #define IS_RICHTEXT CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT static void @@ -155,7 +292,7 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa outptr = filter->outbuf; outend = filter->outbuf + filter->outsize; - loop: + retry: do { while (inptr < inend && outptr < outend && !strchr (" <>&\n", *inptr)) *outptr++ = *inptr++; @@ -242,7 +379,7 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa goto backup; } } - + tag = inptr; while (inptr < inend && *inptr != '>') inptr++; @@ -252,7 +389,7 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa goto need_input; } - if (!strncmp (tag, "nofill>", 7)) { + if (!strncasecmp (tag, "nofill>", 7)) { if ((outptr + 5) < outend) { memcpy (outptr, "
", 5);
 					enriched->nofill++;
@@ -261,7 +398,7 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa
 					inptr = tag - 1;
 					goto backup;
 				}
-			} else if (!strncmp (tag, "/nofill>", 8)) {
+			} else if (!strncasecmp (tag, "/nofill>", 8)) {
 				if ((outptr + 6) < outend) {
 					memcpy (outptr, "
", 6); enriched->nofill--; @@ -275,21 +412,80 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa char *enriched_tag; int len; - enriched_tag = g_strndup (tag, (inptr - tag)); + len = inptr - tag; + enriched_tag = g_alloca (len + 1); + memcpy (enriched_tag, tag, len); + enriched_tag[len] = '\0'; + html_tag = g_hash_table_lookup (enriched_hash, enriched_tag); - g_free (enriched_tag); + if (html_tag) { - len = strlen (html_tag); - if ((outptr + len) < outend) { - memcpy (outptr, html_tag, len); - outptr += len; + if (html_tag_needs_param (html_tag)) { + const char *start; + char *param; + + while (inptr < inend && *inptr != '<') + inptr++; + +#define PARAM_TAG_MIN_LEN (sizeof ("") + sizeof ("") - 1) + if (inptr == inend || (inend - inptr) <= PARAM_TAG_MIN_LEN) { + inptr = tag - 1; + goto need_input; + } + + if (strncasecmp (inptr, "", 7) != 0) { + /* ignore the enriched command tag... */ + inptr -= 1; + goto loop; + } + + inptr += 7; + start = inptr; + + while (inptr < inend && *inptr != '<') + inptr++; + + if (inptr == inend || (inend - inptr) <= 8) { + inptr = tag - 1; + goto need_input; + } + + if (strncasecmp (inptr, "", 8) != 0) { + /* ignore the enriched command tag... */ + inptr += 7; + goto loop; + } + + len = inptr - start; + param = param_parse (enriched_tag, start, len); + len = strlen (param); + + inptr += 7; + + len += strlen (html_tag); + + if ((outptr + len) < outend) { + outptr += snprintf (outptr, len, html_tag, param); + g_free (param); + } else { + g_free (param); + inptr = tag - 1; + goto backup; + } } else { - inptr = tag - 1; - goto backup; + len = strlen (html_tag); + if ((outptr + len) < outend) { + memcpy (outptr, html_tag, len); + outptr += len; + } else { + inptr = tag - 1; + goto backup; + } } } } + loop: inptr++; break; default: @@ -323,7 +519,7 @@ enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespa outend = filter->outbuf + filter->outsize; outptr = filter->outbuf + offset; - goto loop; + goto retry; } else { camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr)); } -- cgit v1.2.3