1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright 2002 Ximian, Inc. (www.ximian.com)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
31 #include "string-utils.h"
33 #include "camel-mime-filter-enriched.h"
42 { "/italic", "</i>" },
44 { "/fixed", "</tt>" },
45 { "smaller", "<font size=-1>" },
46 { "/smaller", "</font>" },
47 { "bigger", "<font size=+1>" },
48 { "/bigger", "</font>" },
49 { "underline", "<u>" },
50 { "/underline", "</u>" },
51 { "center", "<p align=center>" },
52 { "/center", "</p>" },
53 { "flushleft", "<p align=left>" },
54 { "/flushleft", "</p>" },
55 { "flushright", "<p align=right>" },
56 { "/flushright", "</p>" },
57 { "excerpt", "<blockquote>" },
58 { "/excerpt", "</blockquote>" },
59 { "paragraph", "<p>" },
60 { "signature", "<address>" },
61 { "/signature", "</address>" },
62 { "comment", "<!-- " },
63 { "/comment", " -->" },
69 #define NUM_ENRICHED_TAGS (sizeof (enriched_tags) / sizeof (enriched_tags[0]))
71 static GHashTable *enriched_hash = NULL;
74 static void camel_mime_filter_enriched_class_init (CamelMimeFilterEnrichedClass *klass);
75 static void camel_mime_filter_enriched_init (CamelMimeFilterEnriched *filter);
76 static void camel_mime_filter_enriched_finalize (CamelObject *obj);
78 static void filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
79 char **out, size_t *outlen, size_t *outprespace);
80 static void filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
81 char **out, size_t *outlen, size_t *outprespace);
82 static void filter_reset (CamelMimeFilter *filter);
85 static CamelMimeFilterClass *parent_class = NULL;
89 camel_mime_filter_enriched_get_type (void)
91 static CamelType type = CAMEL_INVALID_TYPE;
93 if (type == CAMEL_INVALID_TYPE) {
94 type = camel_type_register (camel_mime_filter_get_type (),
95 "CamelMimeFilterEnriched",
96 sizeof (CamelMimeFilterEnriched),
97 sizeof (CamelMimeFilterEnrichedClass),
98 (CamelObjectClassInitFunc) camel_mime_filter_enriched_class_init,
100 (CamelObjectInitFunc) camel_mime_filter_enriched_init,
101 (CamelObjectFinalizeFunc) camel_mime_filter_enriched_finalize);
108 camel_mime_filter_enriched_class_init (CamelMimeFilterEnrichedClass *klass)
110 CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
113 parent_class = CAMEL_MIME_FILTER_CLASS (camel_mime_filter_get_type ());
115 filter_class->reset = filter_reset;
116 filter_class->filter = filter_filter;
117 filter_class->complete = filter_complete;
119 if (!enriched_hash) {
120 enriched_hash = g_hash_table_new (g_strcase_hash, g_strcase_equal);
121 for (i = 0; i < NUM_ENRICHED_TAGS; i++)
122 g_hash_table_insert (enriched_hash, enriched_tags[i].enriched,
123 enriched_tags[i].html);
128 camel_mime_filter_enriched_finalize (CamelObject *obj)
134 camel_mime_filter_enriched_init (CamelMimeFilterEnriched *filter)
140 #define IS_RICHTEXT CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT
143 enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespace,
144 char **out, size_t *outlen, size_t *outprespace, gboolean flush)
146 CamelMimeFilterEnriched *enriched = (CamelMimeFilterEnriched *) filter;
147 const char *tag, *inend, *outend;
148 register const char *inptr;
149 register char *outptr;
151 camel_mime_filter_set_size (filter, inlen * 2 + 6, FALSE);
155 outptr = filter->outbuf;
156 outend = filter->outbuf + filter->outsize;
160 while (inptr < inend && outptr < outend && !strchr (" <>&\n", *inptr))
161 *outptr++ = *inptr++;
163 if (outptr == outend)
166 if ((inptr + 1) >= inend)
171 while (inptr < inend && (outptr + 7) < outend && *inptr == ' ') {
172 memcpy (outptr, " ", 6);
182 if (!(enriched->flags & IS_RICHTEXT) && enriched->nofill <= 0) {
184 while (inptr < inend && (outptr + 4) < outend && *inptr == '\n') {
185 memcpy (outptr, "<br>", 4);
195 if ((outptr + 4) < outend) {
196 memcpy (outptr, ">", 4);
204 if ((outptr + 5) < outend) {
205 memcpy (outptr, "&", 5);
213 if (!(enriched->flags & IS_RICHTEXT)) {
215 if ((outptr + 4) < outend && *inptr == '<') {
216 memcpy (outptr, "<", 4);
226 if ((inend - inptr) >= 3 && (outptr + 4) < outend) {
227 if (strncmp (inptr, "lt>", 3) == 0) {
228 memcpy (outptr, "<", 4);
232 } else if (strncmp (inptr, "nl>", 3) == 0) {
233 memcpy (outptr, "<br>", 4);
245 while (inptr < inend && *inptr != '>')
248 if (inptr == inend) {
253 if (!strncmp (tag, "nofill>", 7)) {
254 if ((outptr + 5) < outend) {
255 memcpy (outptr, "<pre>", 5);
262 } else if (!strncmp (tag, "/nofill>", 8)) {
263 if ((outptr + 6) < outend) {
264 memcpy (outptr, "</pre>", 6);
272 const char *html_tag;
276 enriched_tag = g_strndup (tag, (inptr - tag));
277 html_tag = g_hash_table_lookup (enriched_hash, enriched_tag);
278 g_free (enriched_tag);
280 len = strlen (html_tag);
281 if ((outptr + len) < outend) {
282 memcpy (outptr, html_tag, len);
296 } while (inptr < inend);
300 /* the reason we ignore @flush here is because if there isn't
301 enough input to parse a tag, then there's nothing we can
305 camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr));
307 *out = filter->outbuf;
308 *outlen = outptr - filter->outbuf;
309 *outprespace = filter->outpre;
318 grow = (inend - inptr) * 2 + 20;
319 offset = outptr - filter->outbuf;
320 camel_mime_filter_set_size (filter, filter->outsize + grow, TRUE);
321 outend = filter->outbuf + filter->outsize;
322 outptr = filter->outbuf + offset;
326 camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr));
329 *out = filter->outbuf;
330 *outlen = outptr - filter->outbuf;
331 *outprespace = filter->outpre;
335 filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
336 char **out, size_t *outlen, size_t *outprespace)
338 enriched_to_html (filter, in, len, prespace, out, outlen, outprespace, FALSE);
342 filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
343 char **out, size_t *outlen, size_t *outprespace)
345 enriched_to_html (filter, in, len, prespace, out, outlen, outprespace, TRUE);
349 filter_reset (CamelMimeFilter *filter)
351 CamelMimeFilterEnriched *enriched = (CamelMimeFilterEnriched *) filter;
353 enriched->nofill = 0;
358 * camel_mime_filter_enriched_new:
361 * Creates a new CamelMimeFilterEnriched object.
363 * Returns a new CamelMimeFilter object.
366 camel_mime_filter_enriched_new (guint32 flags)
368 CamelMimeFilterEnriched *new;
371 new = (CamelMimeFilterEnriched *) camel_object_new (CAMEL_TYPE_MIME_FILTER_ENRICHED);
374 return CAMEL_MIME_FILTER (new);