2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
3 * Copyright © 2010 Michal Sojka <sojkam1@fel.cvut.cz>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include "gmime-filter-headers.h"
22 #include <gmime/gmime-utils.h>
23 #include <glib/gprintf.h>
28 * SECTION: gmime-filter-headers
29 * @title: GMimeFilterHeaders
30 * @short_description: Add/remove headers markers
32 * A #GMimeFilter for decoding rfc2047 encoded headers to UTF-8
36 static void g_mime_filter_headers_class_init (GMimeFilterHeadersClass *klass);
37 static void g_mime_filter_headers_init (GMimeFilterHeaders *filter, GMimeFilterHeadersClass *klass);
38 static void g_mime_filter_headers_finalize (GObject *object);
40 static GMimeFilter *filter_copy (GMimeFilter *filter);
41 static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
42 char **out, size_t *outlen, size_t *outprespace);
43 static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
44 char **out, size_t *outlen, size_t *outprespace);
45 static void filter_reset (GMimeFilter *filter);
48 static GMimeFilterClass *parent_class = NULL;
51 g_mime_filter_headers_get_type (void)
53 static GType type = 0;
56 static const GTypeInfo info = {
57 sizeof (GMimeFilterHeadersClass),
58 NULL, /* base_class_init */
59 NULL, /* base_class_finalize */
60 (GClassInitFunc) g_mime_filter_headers_class_init,
61 NULL, /* class_finalize */
62 NULL, /* class_data */
63 sizeof (GMimeFilterHeaders),
65 (GInstanceInitFunc) g_mime_filter_headers_init,
66 NULL /* value_table */
69 type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterHeaders", &info, (GTypeFlags) 0);
77 g_mime_filter_headers_class_init (GMimeFilterHeadersClass *klass)
79 GObjectClass *object_class = G_OBJECT_CLASS (klass);
80 GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass);
82 parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER);
84 object_class->finalize = g_mime_filter_headers_finalize;
86 filter_class->copy = filter_copy;
87 filter_class->filter = filter_filter;
88 filter_class->complete = filter_complete;
89 filter_class->reset = filter_reset;
93 g_mime_filter_headers_init (GMimeFilterHeaders *filter, GMimeFilterHeadersClass *klass)
96 filter->saw_nl = TRUE;
98 filter->line_size = 0;
99 filter->lineptr = NULL;
103 g_mime_filter_headers_finalize (GObject *object)
105 free (GMIME_FILTER_HEADERS (object)->line);
106 G_OBJECT_CLASS (parent_class)->finalize (object);
111 filter_copy (GMimeFilter *filter)
114 return g_mime_filter_headers_new ();
118 output_decoded_header (GMimeFilterHeaders *headers, char **outptr)
120 char *colon, *name, *s, *decoded_value;
124 colon = strchr (headers->line, ':');
128 name = headers->line;
131 while (*s == ' ' || *s == '\t')
133 decoded_value = g_mime_utils_header_decode_text(s);
134 if (decoded_value == NULL)
136 offset = *outptr - GMIME_FILTER (headers)->outbuf;
137 g_mime_filter_set_size (GMIME_FILTER (headers), strlen(name) + 2 +
138 strlen(decoded_value) + 2, TRUE);
139 *outptr = GMIME_FILTER (headers)->outbuf + offset;
140 ret = g_sprintf (*outptr, "%s: %s\n", name, decoded_value);
143 free (decoded_value);
147 output_final_newline (GMimeFilterHeaders *headers, char **outptr)
151 offset = *outptr - GMIME_FILTER (headers)->outbuf;
152 g_mime_filter_set_size (GMIME_FILTER (headers), 1, TRUE);
153 *outptr = GMIME_FILTER (headers)->outbuf + offset;
158 filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
159 char **outbuf, size_t *outlen, size_t *outprespace)
161 GMimeFilterHeaders *headers = (GMimeFilterHeaders *) filter;
162 register const char *inptr = inbuf;
163 const char *inend = inbuf + inlen;
164 char *lineptr, *lineend, *outptr;
167 if (headers->line == NULL) {
168 headers->line_size = 200;
169 headers->lineptr = headers->line = malloc (headers->line_size);
171 lineptr = headers->lineptr;
172 lineend = headers->line + headers->line_size - 1;
175 outptr = filter->outbuf;
176 while (inptr < inend) {
177 if (*inptr == '\n') {
179 output_final_newline(headers, &outptr);
180 headers->saw_nl = TRUE;
185 if (lineptr == lineend) {
186 headers->line_size *= 2;
187 headers->line = xrealloc (headers->line, headers->line_size);
188 lineptr = headers->line + (headers->line_size / 2) - 1;
189 lineend = headers->line + headers->line_size - 1;
192 if (headers->saw_nl && *inptr != ' ' && *inptr != '\t') {
194 output_decoded_header (headers, &outptr);
195 lineptr = headers->line;
197 if (headers->saw_nl && (*inptr == ' ' || *inptr == '\t')) {
200 while (inptr < inend && (*inptr == ' ' || *inptr == '\t'))
202 headers->saw_nl = FALSE;
205 headers->saw_nl = FALSE;
211 if (headers->saw_nl) {
213 output_decoded_header (headers, &outptr);
214 lineptr = headers->line;
216 headers->lineptr = lineptr;
217 *outlen = outptr - filter->outbuf;
218 *outprespace = filter->outpre;
219 *outbuf = filter->outbuf;
223 filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
224 char **outbuf, size_t *outlen, size_t *outprespace)
227 filter_filter (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace);
231 filter_reset (GMimeFilter *filter)
233 GMimeFilterHeaders *headers = (GMimeFilterHeaders *) filter;
235 headers->saw_nl = TRUE;
237 headers->line = NULL;
238 headers->line_size = 0;
243 * g_mime_filter_headers_new:
244 * @encode: %TRUE if the filter should encode or %FALSE otherwise
245 * @dots: encode/decode dots (as for SMTP)
247 * Creates a new #GMimeFilterHeaders filter.
249 * If @encode is %TRUE, then all lines will be prefixed by "> ",
250 * otherwise any lines starting with "> " will have that removed
252 * Returns: a new #GMimeFilterHeaders filter.
255 g_mime_filter_headers_new (void)
257 GMimeFilterHeaders *new_headers;
259 new_headers = (GMimeFilterHeaders *) g_object_newv (GMIME_TYPE_FILTER_HEADERS, 0, NULL);
261 return (GMimeFilter *) new_headers;