2 * Copyright (C) 2000 Ximian Inc.
4 * Authors: Michael Zucchi <notzed@ximian.com>
5 * Jeffrey Stedfast <fejj@ximian.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
24 #include "camel-mime-filter-basic.h"
25 #include "camel-mime-utils.h"
27 static void reset(CamelMimeFilter *mf);
28 static void complete(CamelMimeFilter *mf, char *in, size_t len,
29 size_t prespace, char **out,
30 size_t *outlen, size_t *outprespace);
31 static void filter(CamelMimeFilter *mf, char *in, size_t len,
32 size_t prespace, char **out,
33 size_t *outlen, size_t *outprespace);
35 static void camel_mime_filter_basic_class_init (CamelMimeFilterBasicClass *klass);
36 static void camel_mime_filter_basic_init (CamelMimeFilterBasic *obj);
38 static CamelMimeFilterClass *camel_mime_filter_basic_parent;
41 camel_mime_filter_basic_class_init (CamelMimeFilterBasicClass *klass)
43 CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
45 camel_mime_filter_basic_parent = CAMEL_MIME_FILTER_CLASS(camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
47 filter_class->reset = reset;
48 filter_class->filter = filter;
49 filter_class->complete = complete;
53 camel_mime_filter_basic_init (CamelMimeFilterBasic *obj)
61 camel_mime_filter_basic_get_type (void)
63 static CamelType type = CAMEL_INVALID_TYPE;
65 if (type == CAMEL_INVALID_TYPE) {
66 type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterBasic",
67 sizeof (CamelMimeFilterBasic),
68 sizeof (CamelMimeFilterBasicClass),
69 (CamelObjectClassInitFunc) camel_mime_filter_basic_class_init,
71 (CamelObjectInitFunc) camel_mime_filter_basic_init,
78 /* should this 'flush' outstanding state/data bytes? */
80 reset(CamelMimeFilter *mf)
82 CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
85 case CAMEL_MIME_FILTER_BASIC_QP_ENC:
95 complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
97 CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
101 case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
102 /* wont go to more than 2x size (overly conservative) */
103 camel_mime_filter_set_size(mf, len*2+6, FALSE);
104 newlen = camel_base64_encode_close(in, len, TRUE, mf->outbuf, &f->state, &f->save);
105 g_assert(newlen <= len*2+6);
107 case CAMEL_MIME_FILTER_BASIC_QP_ENC:
108 /* *4 is definetly more than needed ... */
109 camel_mime_filter_set_size(mf, len*4+4, FALSE);
110 newlen = camel_quoted_encode_close(in, len, mf->outbuf, &f->state, &f->save);
111 g_assert(newlen <= len*4+4);
113 case CAMEL_MIME_FILTER_BASIC_UU_ENC:
114 /* won't go to more than 2 * (x + 2) + 62 */
115 camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE);
116 newlen = camel_uuencode_close (in, len, mf->outbuf, f->uubuf, &f->state, &f->save);
117 g_assert (newlen <= (len + 2) * 2 + 62);
119 case CAMEL_MIME_FILTER_BASIC_BASE64_DEC:
120 /* output can't possibly exceed the input size */
121 camel_mime_filter_set_size(mf, len, FALSE);
122 newlen = camel_base64_decode_step(in, len, mf->outbuf, &f->state, &f->save);
123 g_assert(newlen <= len);
125 case CAMEL_MIME_FILTER_BASIC_QP_DEC:
126 /* output can't possibly exceed the input size, well unless its not really qp, then +2 max */
127 camel_mime_filter_set_size(mf, len+2, FALSE);
128 newlen = camel_quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save);
129 g_assert(newlen <= len+2);
131 case CAMEL_MIME_FILTER_BASIC_UU_DEC:
132 if ((f->state & CAMEL_UUDECODE_STATE_BEGIN) && !(f->state & CAMEL_UUDECODE_STATE_END)) {
133 /* "begin <mode> <filename>\n" has been found, so we can now start decoding */
134 camel_mime_filter_set_size (mf, len + 3, FALSE);
135 newlen = camel_uudecode_step (in, len, mf->outbuf, &f->state, &f->save);
141 g_warning ("unknown type %u in CamelMimeFilterBasic", f->type);
147 *outprespace = mf->outpre;
153 *outprespace = prespace;
156 /* here we do all of the basic mime filtering */
158 filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
160 CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
164 case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
165 /* wont go to more than 2x size (overly conservative) */
166 camel_mime_filter_set_size(mf, len*2+6, FALSE);
167 newlen = camel_base64_encode_step(in, len, TRUE, mf->outbuf, &f->state, &f->save);
168 g_assert(newlen <= len*2+6);
170 case CAMEL_MIME_FILTER_BASIC_QP_ENC:
171 /* *4 is overly conservative, but will do */
172 camel_mime_filter_set_size(mf, len*4+4, FALSE);
173 newlen = camel_quoted_encode_step(in, len, mf->outbuf, &f->state, &f->save);
174 g_assert(newlen <= len*4+4);
176 case CAMEL_MIME_FILTER_BASIC_UU_ENC:
177 /* won't go to more than 2 * (x + 2) + 62 */
178 camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE);
179 newlen = camel_uuencode_step (in, len, mf->outbuf, f->uubuf, &f->state, &f->save);
180 g_assert (newlen <= (len + 2) * 2 + 62);
182 case CAMEL_MIME_FILTER_BASIC_BASE64_DEC:
183 /* output can't possibly exceed the input size */
184 camel_mime_filter_set_size(mf, len+3, FALSE);
185 newlen = camel_base64_decode_step(in, len, mf->outbuf, &f->state, &f->save);
186 g_assert(newlen <= len+3);
188 case CAMEL_MIME_FILTER_BASIC_QP_DEC:
189 /* output can't possibly exceed the input size */
190 camel_mime_filter_set_size(mf, len + 2, FALSE);
191 newlen = camel_quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save);
192 g_assert(newlen <= len + 2);
194 case CAMEL_MIME_FILTER_BASIC_UU_DEC:
195 if (!(f->state & CAMEL_UUDECODE_STATE_BEGIN)) {
196 register char *inptr, *inend;
202 while (inptr < inend) {
203 left = inend - inptr;
205 if (!strncmp (inptr, "begin ", left))
206 camel_mime_filter_backup (mf, inptr, left);
208 } else if (!strncmp (inptr, "begin ", 6)) {
209 for (in = inptr; inptr < inend && *inptr != '\n'; inptr++);
212 f->state |= CAMEL_UUDECODE_STATE_BEGIN;
213 /* we can start uudecoding... */
217 camel_mime_filter_backup (mf, in, left);
222 /* go to the next line */
223 for ( ; inptr < inend && *inptr != '\n'; inptr++);
230 if ((f->state & CAMEL_UUDECODE_STATE_BEGIN) && !(f->state & CAMEL_UUDECODE_STATE_END)) {
231 /* "begin <mode> <filename>\n" has been found, so we can now start decoding */
232 camel_mime_filter_set_size (mf, len + 3, FALSE);
233 newlen = camel_uudecode_step (in, len, mf->outbuf, &f->state, &f->save);
239 g_warning ("unknown type %u in CamelMimeFilterBasic", f->type);
245 *outprespace = mf->outpre;
251 *outprespace = prespace;
256 * camel_mime_filter_basic_new:
258 * Create a new #CamelMimeFilterBasic object.
260 * Returns a new #CamelMimeFilterBasic object
262 CamelMimeFilterBasic *
263 camel_mime_filter_basic_new (void)
265 CamelMimeFilterBasic *new = CAMEL_MIME_FILTER_BASIC ( camel_object_new (camel_mime_filter_basic_get_type ()));
271 * camel_mime_filter_basic_new_type:
272 * @type: a #CamelMimeFilterBasicType type
274 * Create a new #CamelMimeFilterBasic object of type @type.
276 * Returns a new #CamelMimeFilterBasic object
278 CamelMimeFilterBasic *
279 camel_mime_filter_basic_new_type(CamelMimeFilterBasicType type)
281 CamelMimeFilterBasic *new;
284 case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
285 case CAMEL_MIME_FILTER_BASIC_QP_ENC:
286 case CAMEL_MIME_FILTER_BASIC_BASE64_DEC:
287 case CAMEL_MIME_FILTER_BASIC_QP_DEC:
288 case CAMEL_MIME_FILTER_BASIC_UU_ENC:
289 case CAMEL_MIME_FILTER_BASIC_UU_DEC:
290 new = camel_mime_filter_basic_new();
294 g_warning ("Invalid type of CamelMimeFilterBasic requested: %u", type);
298 camel_mime_filter_reset((CamelMimeFilter *)new);