1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
4 * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
6 * Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
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 Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
30 #include "camel-data-wrapper.h"
31 #include "camel-exception.h"
32 #include "camel-mime-filter-basic.h"
33 #include "camel-mime-filter-crlf.h"
34 #include "camel-private.h"
35 #include "camel-stream-filter.h"
36 #include "camel-stream.h"
40 static CamelObjectClass *parent_class = NULL;
42 /* Returns the class for a CamelDataWrapper */
43 #define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
45 static int construct_from_stream(CamelDataWrapper *, CamelStream *);
46 static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
47 static ssize_t decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
48 static void set_mime_type (CamelDataWrapper *data_wrapper, const char *mime_type);
49 static gchar *get_mime_type (CamelDataWrapper *data_wrapper);
50 static CamelContentType *get_mime_type_field (CamelDataWrapper *data_wrapper);
51 static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type);
52 static gboolean is_offline (CamelDataWrapper *data_wrapper);
55 camel_data_wrapper_class_init (CamelDataWrapperClass *camel_data_wrapper_class)
57 parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
59 /* virtual method definition */
60 camel_data_wrapper_class->write_to_stream = write_to_stream;
61 camel_data_wrapper_class->decode_to_stream = decode_to_stream;
62 camel_data_wrapper_class->set_mime_type = set_mime_type;
63 camel_data_wrapper_class->get_mime_type = get_mime_type;
64 camel_data_wrapper_class->get_mime_type_field = get_mime_type_field;
65 camel_data_wrapper_class->set_mime_type_field = set_mime_type_field;
66 camel_data_wrapper_class->construct_from_stream = construct_from_stream;
67 camel_data_wrapper_class->is_offline = is_offline;
71 camel_data_wrapper_init (gpointer object, gpointer klass)
73 CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
75 camel_data_wrapper->priv = g_malloc (sizeof (struct _CamelDataWrapperPrivate));
76 pthread_mutex_init (&camel_data_wrapper->priv->stream_lock, NULL);
78 camel_data_wrapper->mime_type = camel_content_type_new ("application", "octet-stream");
79 camel_data_wrapper->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT;
80 camel_data_wrapper->offline = FALSE;
84 camel_data_wrapper_finalize (CamelObject *object)
86 CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
88 pthread_mutex_destroy (&camel_data_wrapper->priv->stream_lock);
90 g_free (camel_data_wrapper->priv);
92 if (camel_data_wrapper->mime_type)
93 camel_content_type_unref (camel_data_wrapper->mime_type);
95 if (camel_data_wrapper->stream)
96 camel_object_unref (camel_data_wrapper->stream);
100 camel_data_wrapper_get_type (void)
102 static CamelType type = CAMEL_INVALID_TYPE;
104 if (type == CAMEL_INVALID_TYPE) {
105 type = camel_type_register (CAMEL_OBJECT_TYPE,
107 sizeof (CamelDataWrapper),
108 sizeof (CamelDataWrapperClass),
109 (CamelObjectClassInitFunc) camel_data_wrapper_class_init,
111 (CamelObjectInitFunc) camel_data_wrapper_init,
112 (CamelObjectFinalizeFunc) camel_data_wrapper_finalize);
120 * camel_data_wrapper_new:
122 * Create a new #CamelDataWrapper object.
124 * Returns a new #CamelDataWrapper object
127 camel_data_wrapper_new (void)
129 return (CamelDataWrapper *) camel_object_new (CAMEL_DATA_WRAPPER_TYPE);
133 write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
137 if (data_wrapper->stream == NULL) {
141 CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
142 if (camel_stream_reset (data_wrapper->stream) == -1) {
143 CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
147 ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
149 CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
156 * camel_data_wrapper_write_to_stream:
157 * @data_wrapper: a #CamelDataWrapper object
158 * @stream: a #CamelStream for output
160 * Writes the content of @data_wrapper to @stream in a machine-independent
161 * format appropriate for the data. It should be possible to construct an
162 * equivalent data wrapper object later by passing this stream to
163 * #camel_data_wrapper_construct_from_stream.
165 * Returns the number of bytes written, or %-1 on fail
168 camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
171 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
172 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
174 return CDW_CLASS (data_wrapper)->write_to_stream (data_wrapper, stream);
179 decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
181 CamelMimeFilter *filter;
182 CamelStream *fstream;
185 fstream = (CamelStream *) camel_stream_filter_new_with_stream (stream);
187 switch (data_wrapper->encoding) {
188 case CAMEL_TRANSFER_ENCODING_BASE64:
189 filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
190 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
191 camel_object_unref (filter);
193 case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
194 filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_QP_DEC);
195 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
196 camel_object_unref (filter);
198 case CAMEL_TRANSFER_ENCODING_UUENCODE:
199 filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_UU_DEC);
200 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
201 camel_object_unref (filter);
207 if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
208 filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
209 CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
210 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
211 camel_object_unref (filter);
214 ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
215 camel_stream_flush (fstream);
216 camel_object_unref (fstream);
223 * camel_data_wrapper_decode_to_stream:
224 * @data_wrapper: a #CamelDataWrapper object
225 * @stream: a #CamelStream for decoded data to be written to
227 * Writes the decoded data content to @stream.
229 * Returns the number of bytes written, or %-1 on fail
232 camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
235 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
236 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
238 return CDW_CLASS (data_wrapper)->decode_to_stream (data_wrapper, stream);
243 construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
245 if (data_wrapper->stream)
246 camel_object_unref (data_wrapper->stream);
248 data_wrapper->stream = stream;
249 camel_object_ref (stream);
255 * camel_data_wrapper_construct_from_stream:
256 * @data_wrapper: a #CamelDataWrapper object
257 * @stream: an input #CamelStream
259 * Constructs the content of @data_wrapper from the supplied @stream.
261 * Returns %0 on success or %-1 on fail
264 camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
267 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
268 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
270 return CDW_CLASS (data_wrapper)->construct_from_stream (data_wrapper, stream);
275 set_mime_type (CamelDataWrapper *data_wrapper, const char *mime_type)
277 if (data_wrapper->mime_type)
278 camel_content_type_unref (data_wrapper->mime_type);
279 data_wrapper->mime_type = camel_content_type_decode (mime_type);
284 * camel_data_wrapper_set_mime_type:
285 * @data_wrapper: a #CamelDataWrapper object
286 * @mime_type: a MIME type
288 * This sets the data wrapper's MIME type.
290 * It might fail, but you won't know. It will allow you to set
291 * Content-Type parameters on the data wrapper, which are meaningless.
292 * You should not be allowed to change the MIME type of a data wrapper
293 * that contains data, or at least, if you do, it should invalidate the
297 camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
298 const char *mime_type)
300 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
301 g_return_if_fail (mime_type != NULL);
303 CDW_CLASS (data_wrapper)->set_mime_type (data_wrapper, mime_type);
307 get_mime_type (CamelDataWrapper *data_wrapper)
309 return camel_content_type_simple (data_wrapper->mime_type);
314 * camel_data_wrapper_get_mime_type:
315 * @data_wrapper: a #CamelDataWrapper object
317 * Returns the MIME type which must be freed by the caller
320 camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
322 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
324 return CDW_CLASS (data_wrapper)->get_mime_type (data_wrapper);
328 static CamelContentType *
329 get_mime_type_field (CamelDataWrapper *data_wrapper)
331 return data_wrapper->mime_type;
336 * camel_data_wrapper_get_mime_type_field:
337 * @data_wrapper: a #CamelDataWrapper object
339 * Returns the parsed form of the data wrapper's MIME type
342 camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
344 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
346 return CDW_CLASS (data_wrapper)->get_mime_type_field (data_wrapper);
350 set_mime_type_field (CamelDataWrapper *data_wrapper,
351 CamelContentType *mime_type)
354 camel_content_type_ref (mime_type);
355 if (data_wrapper->mime_type)
356 camel_content_type_unref (data_wrapper->mime_type);
357 data_wrapper->mime_type = mime_type;
362 * camel_data_wrapper_set_mime_type_field:
363 * @data_wrapper: a #CamelDataWrapper object
364 * @mime_type: a #CamelContentType
366 * This sets the data wrapper's MIME type. It suffers from the same
367 * flaws as #camel_data_wrapper_set_mime_type.
370 camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
371 CamelContentType *mime_type)
373 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
374 g_return_if_fail (mime_type != NULL);
376 CDW_CLASS (data_wrapper)->set_mime_type_field (data_wrapper, mime_type);
381 is_offline (CamelDataWrapper *data_wrapper)
383 return data_wrapper->offline;
388 * camel_data_wrapper_is_offline:
389 * @data_wrapper: a #CamelDataWrapper object
391 * Returns whether @data_wrapper is "offline" (data stored
392 * remotely) or not. Some optional code paths may choose to not
393 * operate on offline data.
396 camel_data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
398 return CDW_CLASS (data_wrapper)->is_offline (data_wrapper);