1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
4 * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
6 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.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
29 #include "camel-data-wrapper.h"
30 #include "camel-mime-filter-basic.h"
31 #include "camel-mime-filter-crlf.h"
32 #include "camel-stream-filter.h"
33 #include "camel-stream.h"
37 struct _CamelDataWrapperPrivate {
38 GStaticMutex stream_lock;
41 static CamelObjectClass *parent_class = NULL;
44 camel_data_wrapper_finalize (CamelObject *object)
46 CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
48 g_static_mutex_free (&camel_data_wrapper->priv->stream_lock);
50 g_free (camel_data_wrapper->priv);
52 if (camel_data_wrapper->mime_type)
53 camel_content_type_unref (camel_data_wrapper->mime_type);
55 if (camel_data_wrapper->stream)
56 camel_object_unref (camel_data_wrapper->stream);
60 data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
65 if (data_wrapper->stream == NULL) {
69 camel_data_wrapper_lock (data_wrapper, CDW_STREAM_LOCK);
70 if (camel_stream_reset (data_wrapper->stream) == -1) {
71 camel_data_wrapper_unlock (data_wrapper, CDW_STREAM_LOCK);
75 ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
77 camel_data_wrapper_unlock (data_wrapper, CDW_STREAM_LOCK);
83 data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
86 CamelMimeFilter *filter;
90 fstream = camel_stream_filter_new (stream);
92 switch (data_wrapper->encoding) {
93 case CAMEL_TRANSFER_ENCODING_BASE64:
94 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
95 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
96 camel_object_unref (filter);
98 case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
99 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_DEC);
100 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
101 camel_object_unref (filter);
103 case CAMEL_TRANSFER_ENCODING_UUENCODE:
104 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC);
105 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
106 camel_object_unref (filter);
112 if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
113 filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
114 CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
115 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
116 camel_object_unref (filter);
119 ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
120 camel_stream_flush (fstream);
121 camel_object_unref (fstream);
127 data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
128 const gchar *mime_type)
130 if (data_wrapper->mime_type)
131 camel_content_type_unref (data_wrapper->mime_type);
132 data_wrapper->mime_type = camel_content_type_decode (mime_type);
136 data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
138 return camel_content_type_simple (data_wrapper->mime_type);
141 static CamelContentType *
142 data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
144 return data_wrapper->mime_type;
148 data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
149 CamelContentType *mime_type)
152 camel_content_type_ref (mime_type);
153 if (data_wrapper->mime_type)
154 camel_content_type_unref (data_wrapper->mime_type);
155 data_wrapper->mime_type = mime_type;
159 data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
162 if (data_wrapper->stream)
163 camel_object_unref (data_wrapper->stream);
165 data_wrapper->stream = camel_object_ref (stream);
171 data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
173 return data_wrapper->offline;
177 camel_data_wrapper_class_init (CamelDataWrapperClass *class)
179 parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
181 class->write_to_stream = data_wrapper_write_to_stream;
182 class->decode_to_stream = data_wrapper_decode_to_stream;
183 class->set_mime_type = data_wrapper_set_mime_type;
184 class->get_mime_type = data_wrapper_get_mime_type;
185 class->get_mime_type_field = data_wrapper_get_mime_type_field;
186 class->set_mime_type_field = data_wrapper_set_mime_type_field;
187 class->construct_from_stream = data_wrapper_construct_from_stream;
188 class->is_offline = data_wrapper_is_offline;
192 camel_data_wrapper_init (CamelDataWrapper *data_wrapper)
194 data_wrapper->priv = g_malloc (sizeof (struct _CamelDataWrapperPrivate));
196 g_static_mutex_init (&data_wrapper->priv->stream_lock);
198 data_wrapper->mime_type = camel_content_type_new (
199 "application", "octet-stream");
200 data_wrapper->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT;
201 data_wrapper->offline = FALSE;
205 camel_data_wrapper_get_type (void)
207 static CamelType type = CAMEL_INVALID_TYPE;
209 if (type == CAMEL_INVALID_TYPE) {
210 type = camel_type_register (CAMEL_TYPE_OBJECT,
212 sizeof (CamelDataWrapper),
213 sizeof (CamelDataWrapperClass),
214 (CamelObjectClassInitFunc) camel_data_wrapper_class_init,
216 (CamelObjectInitFunc) camel_data_wrapper_init,
217 (CamelObjectFinalizeFunc) camel_data_wrapper_finalize);
224 * camel_data_wrapper_new:
226 * Create a new #CamelDataWrapper object.
228 * Returns: a new #CamelDataWrapper object
231 camel_data_wrapper_new (void)
233 return (CamelDataWrapper *) camel_object_new (CAMEL_DATA_WRAPPER_TYPE);
237 * camel_data_wrapper_write_to_stream:
238 * @data_wrapper: a #CamelDataWrapper object
239 * @stream: a #CamelStream for output
241 * Writes the content of @data_wrapper to @stream in a machine-independent
242 * format appropriate for the data. It should be possible to construct an
243 * equivalent data wrapper object later by passing this stream to
244 * #camel_data_wrapper_construct_from_stream.
246 * Returns: the number of bytes written, or %-1 on fail
249 camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
252 CamelDataWrapperClass *class;
254 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
255 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
257 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
258 g_return_val_if_fail (class->write_to_stream != NULL, -1);
260 return class->write_to_stream (data_wrapper, stream);
264 * camel_data_wrapper_decode_to_stream:
265 * @data_wrapper: a #CamelDataWrapper object
266 * @stream: a #CamelStream for decoded data to be written to
268 * Writes the decoded data content to @stream.
270 * Returns: the number of bytes written, or %-1 on fail
273 camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
276 CamelDataWrapperClass *class;
278 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
279 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
281 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
282 g_return_val_if_fail (class->decode_to_stream != NULL, -1);
284 return class->decode_to_stream (data_wrapper, stream);
288 * camel_data_wrapper_construct_from_stream:
289 * @data_wrapper: a #CamelDataWrapper object
290 * @stream: an input #CamelStream
292 * Constructs the content of @data_wrapper from the supplied @stream.
294 * Returns: %0 on success or %-1 on fail
297 camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
300 CamelDataWrapperClass *class;
302 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
303 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
305 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
306 g_return_val_if_fail (class->construct_from_stream != NULL, -1);
308 return class->construct_from_stream (data_wrapper, stream);
312 * camel_data_wrapper_set_mime_type:
313 * @data_wrapper: a #CamelDataWrapper object
314 * @mime_type: a MIME type
316 * This sets the data wrapper's MIME type.
318 * It might fail, but you won't know. It will allow you to set
319 * Content-Type parameters on the data wrapper, which are meaningless.
320 * You should not be allowed to change the MIME type of a data wrapper
321 * that contains data, or at least, if you do, it should invalidate the
325 camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
326 const gchar *mime_type)
328 CamelDataWrapperClass *class;
330 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
331 g_return_if_fail (mime_type != NULL);
333 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
334 g_return_if_fail (class->set_mime_type);
336 class->set_mime_type (data_wrapper, mime_type);
340 * camel_data_wrapper_get_mime_type:
341 * @data_wrapper: a #CamelDataWrapper object
343 * Returns: the MIME type which must be freed by the caller
346 camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
348 CamelDataWrapperClass *class;
350 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
352 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
353 g_return_val_if_fail (class->get_mime_type != NULL, NULL);
355 return class->get_mime_type (data_wrapper);
359 * camel_data_wrapper_get_mime_type_field:
360 * @data_wrapper: a #CamelDataWrapper object
362 * Returns: the parsed form of the data wrapper's MIME type
365 camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
367 CamelDataWrapperClass *class;
369 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
371 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
372 g_return_val_if_fail (class->get_mime_type_field != NULL, NULL);
374 return class->get_mime_type_field (data_wrapper);
378 * camel_data_wrapper_set_mime_type_field:
379 * @data_wrapper: a #CamelDataWrapper object
380 * @mime_type: a #CamelContentType
382 * This sets the data wrapper's MIME type. It suffers from the same
383 * flaws as #camel_data_wrapper_set_mime_type.
386 camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
387 CamelContentType *mime_type)
389 CamelDataWrapperClass *class;
391 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
392 g_return_if_fail (mime_type != NULL);
394 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
395 g_return_if_fail (class->set_mime_type_field != NULL);
397 class->set_mime_type_field (data_wrapper, mime_type);
401 * camel_data_wrapper_is_offline:
402 * @data_wrapper: a #CamelDataWrapper object
404 * Returns: whether @data_wrapper is "offline" (data stored
405 * remotely) or not. Some optional code paths may choose to not
406 * operate on offline data.
409 camel_data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
411 CamelDataWrapperClass *class;
413 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), TRUE);
415 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
416 g_return_val_if_fail (class->is_offline != NULL, TRUE);
418 return class->is_offline (data_wrapper);
422 * camel_data_wrapper_lock:
423 * @data_wrapper: a #CamelDataWrapper
424 * @lock: lock type to lock
426 * Locks #data_wrapper's #lock. Unlock it with camel_data_wrapper_unlock().
431 camel_data_wrapper_lock (CamelDataWrapper *data_wrapper, CamelDataWrapperLock lock)
433 g_return_if_fail (data_wrapper != NULL);
434 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
435 g_return_if_fail (data_wrapper->priv != NULL);
438 case CDW_STREAM_LOCK:
439 g_static_mutex_lock (&data_wrapper->priv->stream_lock);
442 g_return_if_reached ();
447 * camel_data_wrapper_unlock:
448 * @data_wrapper: a #CamelDataWrapper
449 * @lock: lock type to unlock
451 * Unlocks #data_wrapper's #lock, previously locked with camel_data_wrapper_lock().
456 camel_data_wrapper_unlock (CamelDataWrapper *data_wrapper, CamelDataWrapperLock lock)
458 g_return_if_fail (data_wrapper != NULL);
459 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
460 g_return_if_fail (data_wrapper->priv != NULL);
463 case CDW_STREAM_LOCK:
464 g_static_mutex_unlock (&data_wrapper->priv->stream_lock);
467 g_return_if_reached ();