~ubuntu-branches/ubuntu/karmic/libtinymail/karmic

« back to all changes in this revision

Viewing changes to libtinymail-camel/camel-lite/camel/camel-mime-filter.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-10-12 11:21:12 UTC
  • Revision ID: james.westby@ubuntu.com-20071012112112-fod9fs7yrooxjr7i
Tags: upstream-0.0.2
ImportĀ upstreamĀ versionĀ 0.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2000 Ximian Inc.
 
3
 *
 
4
 *  Authors: Michael Zucchi <notzed@ximian.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of version 2 of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but 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.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this program; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include <string.h>
 
22
 
 
23
#include "camel-mime-filter.h"
 
24
 
 
25
/*#define MALLOC_CHECK */ /* for some malloc checking, requires mcheck enabled */
 
26
 
 
27
/* only suitable for glibc */
 
28
#ifdef MALLOC_CHECK
 
29
#include <mcheck.h>
 
30
#endif
 
31
 
 
32
struct _CamelMimeFilterPrivate {
 
33
        char *inbuf;
 
34
        size_t inlen;
 
35
};
 
36
 
 
37
#define PRE_HEAD (64)
 
38
#define BACK_HEAD (64)
 
39
#define _PRIVATE(o) (((CamelMimeFilter *)(o))->priv)
 
40
#define FCLASS(o) ((CamelMimeFilterClass *)(CAMEL_OBJECT_GET_CLASS(o)))
 
41
 
 
42
static CamelObjectClass *camel_mime_filter_parent;
 
43
 
 
44
static void complete (CamelMimeFilter *mf, char *in, size_t len, 
 
45
                      size_t prespace, char **out, size_t *outlen, 
 
46
                      size_t *outprespace);
 
47
 
 
48
static void
 
49
camel_mime_filter_class_init (CamelMimeFilterClass *klass)
 
50
{
 
51
        camel_mime_filter_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
 
52
 
 
53
        klass->complete = complete;
 
54
}
 
55
 
 
56
static void
 
57
camel_mime_filter_init (CamelMimeFilter *obj)
 
58
{
 
59
        obj->outreal = NULL;
 
60
        obj->outbuf = NULL;
 
61
        obj->outsize = 0;
 
62
 
 
63
        obj->backbuf = NULL;
 
64
        obj->backsize = 0;
 
65
        obj->backlen = 0;
 
66
 
 
67
        _PRIVATE(obj) = g_malloc0(sizeof(*obj->priv));
 
68
}
 
69
 
 
70
static void
 
71
camel_mime_filter_finalize(CamelObject *o)
 
72
{
 
73
        CamelMimeFilter *f = (CamelMimeFilter *)o;
 
74
        struct _CamelMimeFilterPrivate *p = _PRIVATE(f);
 
75
 
 
76
        g_free(f->outreal);
 
77
        g_free(f->backbuf);
 
78
        g_free(p->inbuf);
 
79
        g_free(p);
 
80
}
 
81
 
 
82
CamelType
 
83
camel_mime_filter_get_type (void)
 
84
{
 
85
        static CamelType camel_mime_filter_type = CAMEL_INVALID_TYPE;
 
86
        
 
87
        if (camel_mime_filter_type == CAMEL_INVALID_TYPE) {
 
88
                camel_mime_filter_type = camel_type_register (CAMEL_OBJECT_TYPE, "CamelMimeFilter",
 
89
                                                              sizeof (CamelMimeFilter),
 
90
                                                              sizeof (CamelMimeFilterClass),
 
91
                                                              (CamelObjectClassInitFunc) camel_mime_filter_class_init,
 
92
                                                              NULL,
 
93
                                                              (CamelObjectInitFunc) camel_mime_filter_init,
 
94
                                                              (CamelObjectFinalizeFunc) camel_mime_filter_finalize);
 
95
        }
 
96
        
 
97
        return camel_mime_filter_type;
 
98
}
 
99
 
 
100
static void
 
101
complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
 
102
{
 
103
        /* default - do nothing */
 
104
}
 
105
 
 
106
 
 
107
/**
 
108
 * camel_mime_filter_new:
 
109
 *
 
110
 * Create a new #CamelMimeFilter object.
 
111
 * 
 
112
 * Returns a new #CamelMimeFilter
 
113
 **/
 
114
CamelMimeFilter *
 
115
camel_mime_filter_new (void)
 
116
{
 
117
        CamelMimeFilter *new = CAMEL_MIME_FILTER ( camel_object_new (camel_mime_filter_get_type ()));
 
118
        return new;
 
119
}
 
120
 
 
121
#ifdef MALLOC_CHECK
 
122
static void
 
123
checkmem(void *p)
 
124
{
 
125
        if (p) {
 
126
                int status = mprobe(p);
 
127
 
 
128
                switch (status) {
 
129
                case MCHECK_HEAD:
 
130
                        printf("Memory underrun at %p\n", p);
 
131
                        abort();
 
132
                case MCHECK_TAIL:
 
133
                        printf("Memory overrun at %p\n", p);
 
134
                        abort();
 
135
                case MCHECK_FREE:
 
136
                        printf("Double free %p\n", p);
 
137
                        abort();
 
138
                }
 
139
        }
 
140
}
 
141
#endif
 
142
 
 
143
static void filter_run(CamelMimeFilter *f,
 
144
                       char *in, size_t len, size_t prespace,
 
145
                       char **out, size_t *outlen, size_t *outprespace,
 
146
                       void (*filterfunc)(CamelMimeFilter *f,
 
147
                                          char *in, size_t len, size_t prespace,
 
148
                                          char **out, size_t *outlen, size_t *outprespace))
 
149
{
 
150
        struct _CamelMimeFilterPrivate *p;
 
151
 
 
152
#ifdef MALLOC_CHECK
 
153
        checkmem(f->outreal);
 
154
        checkmem(f->backbuf);
 
155
#endif
 
156
        /*
 
157
          here we take a performance hit, if the input buffer doesn't
 
158
          have the pre-space required.  We make a buffer that does ...
 
159
        */
 
160
        if (prespace < f->backlen) {
 
161
                int newlen = len+prespace+f->backlen;
 
162
                p = _PRIVATE(f);
 
163
                if (p->inlen < newlen) {
 
164
                        /* NOTE: g_realloc copies data, we dont need that (slower) */
 
165
                        g_free(p->inbuf);
 
166
                        p->inbuf = g_malloc(newlen+PRE_HEAD);
 
167
                        p->inlen = newlen+PRE_HEAD;
 
168
                }
 
169
                /* copy to end of structure */
 
170
                memcpy(p->inbuf+p->inlen - len, in, len);
 
171
                in = p->inbuf+p->inlen - len;
 
172
                prespace = p->inlen - len;
 
173
        }
 
174
 
 
175
#ifdef MALLOC_CHECK
 
176
        checkmem(f->outreal);
 
177
        checkmem(f->backbuf);
 
178
#endif
 
179
 
 
180
        /* preload any backed up data */
 
181
        if (f->backlen > 0) {
 
182
                memcpy(in-f->backlen, f->backbuf, f->backlen);
 
183
                in -= f->backlen;
 
184
                len += f->backlen;
 
185
                prespace -= f->backlen;
 
186
                f->backlen = 0;
 
187
        }
 
188
        
 
189
        filterfunc(f, in, len, prespace, out, outlen, outprespace);
 
190
 
 
191
#ifdef MALLOC_CHECK
 
192
        checkmem(f->outreal);
 
193
        checkmem(f->backbuf);
 
194
#endif
 
195
 
 
196
}
 
197
 
 
198
 
 
199
/**
 
200
 * camel_mime_filter_filter:
 
201
 * @filter: a #CamelMimeFilter object
 
202
 * @in: input buffer
 
203
 * @len: length of @in
 
204
 * @prespace: amount of prespace
 
205
 * @out: pointer to the output buffer (to be set)
 
206
 * @outlen: pointer to the length of the output buffer (to be set)
 
207
 * @outprespace: pointer to the output prespace length (to be set)
 
208
 *
 
209
 * Passes the input buffer, @in, through @filter and generates an
 
210
 * output buffer, @out.
 
211
 **/
 
212
void
 
213
camel_mime_filter_filter (CamelMimeFilter *filter,
 
214
                          char *in, size_t len, size_t prespace,
 
215
                          char **out, size_t *outlen, size_t *outprespace)
 
216
{
 
217
        if (FCLASS(filter)->filter)
 
218
                filter_run(filter, in, len, prespace, out, outlen, outprespace, FCLASS(filter)->filter);
 
219
        else
 
220
                g_error("Filter function unplmenented in class");
 
221
}
 
222
 
 
223
 
 
224
/**
 
225
 * camel_mime_filter_complete:
 
226
 * @filter: a #CamelMimeFilter object
 
227
 * @in: input buffer
 
228
 * @len: length of @in
 
229
 * @prespace: amount of prespace
 
230
 * @out: pointer to the output buffer (to be set)
 
231
 * @outlen: pointer to the length of the output buffer (to be set)
 
232
 * @outprespace: pointer to the output prespace length (to be set)
 
233
 *
 
234
 * Passes the input buffer, @in, through @filter and generates an
 
235
 * output buffer, @out and makes sure that all data is flushed to the
 
236
 * output buffer. This must be the last filtering call made, no
 
237
 * further calls to #camel_mime_filter_filter may be called on @filter
 
238
 * until @filter has been reset using #camel_mime_filter_reset.
 
239
 **/
 
240
void
 
241
camel_mime_filter_complete (CamelMimeFilter *filter,
 
242
                            char *in, size_t len, size_t prespace,
 
243
                            char **out, size_t *outlen, size_t *outprespace)
 
244
{
 
245
        if (FCLASS(filter)->complete)
 
246
                filter_run(filter, in, len, prespace, out, outlen, outprespace, FCLASS(filter)->complete);
 
247
}
 
248
 
 
249
 
 
250
/**
 
251
 * camel_mime_filter_reset:
 
252
 * @filter: a #CamelMimeFilter object
 
253
 *
 
254
 * Resets the state on @filter so that it may be used again.
 
255
 **/
 
256
void
 
257
camel_mime_filter_reset(CamelMimeFilter *filter)
 
258
{
 
259
        if (FCLASS(filter)->reset) {
 
260
                FCLASS(filter)->reset(filter);
 
261
        }
 
262
 
 
263
        /* could free some buffers, if they are really big? */
 
264
        filter->backlen = 0;
 
265
}
 
266
 
 
267
 
 
268
/**
 
269
 * camel_mime_filter_backup:
 
270
 * @filter: a #camelMimeFilter object
 
271
 * @data: data buffer to backup
 
272
 * @length: length of @data
 
273
 *
 
274
 * Saves @data to be used as prespace input data to the next call to
 
275
 * #camel_mime_filter_filter or #camel_mime_filter_complete.
 
276
 *
 
277
 * Note: New calls replace old data.
 
278
 **/
 
279
void
 
280
camel_mime_filter_backup(CamelMimeFilter *filter, const char *data, size_t length)
 
281
{
 
282
        if (filter->backsize < length) {
 
283
                /* g_realloc copies data, unnecessary overhead */
 
284
                g_free(filter->backbuf);
 
285
                filter->backbuf = g_malloc(length+BACK_HEAD);
 
286
                filter->backsize = length+BACK_HEAD;
 
287
        }
 
288
        filter->backlen = length;
 
289
        memcpy(filter->backbuf, data, length);
 
290
}
 
291
 
 
292
 
 
293
/**
 
294
 * camel_mime_filter_set_size:
 
295
 * @filter: a #camelMimeFilter object
 
296
 * @size: requested amount of storage space
 
297
 * @keep: %TRUE to keep existing buffered data or %FALSE otherwise
 
298
 *
 
299
 * Ensure that @filter has enough storage space to store @size bytes
 
300
 * for filter output.
 
301
 **/
 
302
void
 
303
camel_mime_filter_set_size(CamelMimeFilter *filter, size_t size, int keep)
 
304
{
 
305
        if (filter->outsize < size) {
 
306
                int offset = filter->outptr - filter->outreal;
 
307
                if (keep) {
 
308
                        filter->outreal = g_realloc(filter->outreal, size + PRE_HEAD*4);
 
309
                } else {
 
310
                        g_free(filter->outreal);
 
311
                        filter->outreal = g_malloc(size + PRE_HEAD*4);
 
312
                }
 
313
                filter->outptr = filter->outreal + offset;
 
314
                filter->outbuf = filter->outreal + PRE_HEAD*4;
 
315
                filter->outsize = size;
 
316
                /* this could be offset from the end of the structure, but 
 
317
                   this should be good enough */
 
318
                filter->outpre = PRE_HEAD*4;
 
319
        }
 
320
}