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-private.h"
33 #include "camel-stream-filter.h"
34 #include "camel-stream.h"
38 static CamelObjectClass *parent_class = NULL;
41 camel_data_wrapper_finalize (CamelObject *object)
43 CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
45 g_static_mutex_free (&camel_data_wrapper->priv->stream_lock);
47 g_free (camel_data_wrapper->priv);
49 if (camel_data_wrapper->mime_type)
50 camel_content_type_unref (camel_data_wrapper->mime_type);
52 if (camel_data_wrapper->stream)
53 camel_object_unref (camel_data_wrapper->stream);
57 data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
62 if (data_wrapper->stream == NULL) {
66 CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
67 if (camel_stream_reset (data_wrapper->stream) == -1) {
68 CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
72 ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
74 CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
80 data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
83 CamelMimeFilter *filter;
87 fstream = camel_stream_filter_new (stream);
89 switch (data_wrapper->encoding) {
90 case CAMEL_TRANSFER_ENCODING_BASE64:
91 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
92 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
93 camel_object_unref (filter);
95 case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
96 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_DEC);
97 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
98 camel_object_unref (filter);
100 case CAMEL_TRANSFER_ENCODING_UUENCODE:
101 filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC);
102 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
103 camel_object_unref (filter);
109 if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
110 filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
111 CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
112 camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
113 camel_object_unref (filter);
116 ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
117 camel_stream_flush (fstream);
118 camel_object_unref (fstream);
124 data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
125 const gchar *mime_type)
127 if (data_wrapper->mime_type)
128 camel_content_type_unref (data_wrapper->mime_type);
129 data_wrapper->mime_type = camel_content_type_decode (mime_type);
133 data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
135 return camel_content_type_simple (data_wrapper->mime_type);
138 static CamelContentType *
139 data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
141 return data_wrapper->mime_type;
145 data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
146 CamelContentType *mime_type)
149 camel_content_type_ref (mime_type);
150 if (data_wrapper->mime_type)
151 camel_content_type_unref (data_wrapper->mime_type);
152 data_wrapper->mime_type = mime_type;
156 data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
159 if (data_wrapper->stream)
160 camel_object_unref (data_wrapper->stream);
162 data_wrapper->stream = camel_object_ref (stream);
168 data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
170 return data_wrapper->offline;
174 camel_data_wrapper_class_init (CamelDataWrapperClass *class)
176 parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
178 class->write_to_stream = data_wrapper_write_to_stream;
179 class->decode_to_stream = data_wrapper_decode_to_stream;
180 class->set_mime_type = data_wrapper_set_mime_type;
181 class->get_mime_type = data_wrapper_get_mime_type;
182 class->get_mime_type_field = data_wrapper_get_mime_type_field;
183 class->set_mime_type_field = data_wrapper_set_mime_type_field;
184 class->construct_from_stream = data_wrapper_construct_from_stream;
185 class->is_offline = data_wrapper_is_offline;
189 camel_data_wrapper_init (CamelDataWrapper *data_wrapper)
191 data_wrapper->priv = g_malloc (sizeof (struct _CamelDataWrapperPrivate));
193 g_static_mutex_init (&data_wrapper->priv->stream_lock);
195 data_wrapper->mime_type = camel_content_type_new (
196 "application", "octet-stream");
197 data_wrapper->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT;
198 data_wrapper->offline = FALSE;
202 camel_data_wrapper_get_type (void)
204 static CamelType type = CAMEL_INVALID_TYPE;
206 if (type == CAMEL_INVALID_TYPE) {
207 type = camel_type_register (CAMEL_TYPE_OBJECT,
209 sizeof (CamelDataWrapper),
210 sizeof (CamelDataWrapperClass),
211 (CamelObjectClassInitFunc) camel_data_wrapper_class_init,
213 (CamelObjectInitFunc) camel_data_wrapper_init,
214 (CamelObjectFinalizeFunc) camel_data_wrapper_finalize);
221 * camel_data_wrapper_new:
223 * Create a new #CamelDataWrapper object.
225 * Returns: a new #CamelDataWrapper object
228 camel_data_wrapper_new (void)
230 return (CamelDataWrapper *) camel_object_new (CAMEL_DATA_WRAPPER_TYPE);
234 * camel_data_wrapper_write_to_stream:
235 * @data_wrapper: a #CamelDataWrapper object
236 * @stream: a #CamelStream for output
238 * Writes the content of @data_wrapper to @stream in a machine-independent
239 * format appropriate for the data. It should be possible to construct an
240 * equivalent data wrapper object later by passing this stream to
241 * #camel_data_wrapper_construct_from_stream.
243 * Returns: the number of bytes written, or %-1 on fail
246 camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
249 CamelDataWrapperClass *class;
251 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
252 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
254 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
255 g_return_val_if_fail (class->write_to_stream != NULL, -1);
257 return class->write_to_stream (data_wrapper, stream);
261 * camel_data_wrapper_decode_to_stream:
262 * @data_wrapper: a #CamelDataWrapper object
263 * @stream: a #CamelStream for decoded data to be written to
265 * Writes the decoded data content to @stream.
267 * Returns: the number of bytes written, or %-1 on fail
270 camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
273 CamelDataWrapperClass *class;
275 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
276 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
278 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
279 g_return_val_if_fail (class->decode_to_stream != NULL, -1);
281 return class->decode_to_stream (data_wrapper, stream);
285 * camel_data_wrapper_construct_from_stream:
286 * @data_wrapper: a #CamelDataWrapper object
287 * @stream: an input #CamelStream
289 * Constructs the content of @data_wrapper from the supplied @stream.
291 * Returns: %0 on success or %-1 on fail
294 camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
297 CamelDataWrapperClass *class;
299 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
300 g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
302 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
303 g_return_val_if_fail (class->construct_from_stream != NULL, -1);
305 return class->construct_from_stream (data_wrapper, stream);
309 * camel_data_wrapper_set_mime_type:
310 * @data_wrapper: a #CamelDataWrapper object
311 * @mime_type: a MIME type
313 * This sets the data wrapper's MIME type.
315 * It might fail, but you won't know. It will allow you to set
316 * Content-Type parameters on the data wrapper, which are meaningless.
317 * You should not be allowed to change the MIME type of a data wrapper
318 * that contains data, or at least, if you do, it should invalidate the
322 camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
323 const gchar *mime_type)
325 CamelDataWrapperClass *class;
327 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
328 g_return_if_fail (mime_type != NULL);
330 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
331 g_return_if_fail (class->set_mime_type);
333 class->set_mime_type (data_wrapper, mime_type);
337 * camel_data_wrapper_get_mime_type:
338 * @data_wrapper: a #CamelDataWrapper object
340 * Returns: the MIME type which must be freed by the caller
343 camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
345 CamelDataWrapperClass *class;
347 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
349 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
350 g_return_val_if_fail (class->get_mime_type != NULL, NULL);
352 return class->get_mime_type (data_wrapper);
356 * camel_data_wrapper_get_mime_type_field:
357 * @data_wrapper: a #CamelDataWrapper object
359 * Returns: the parsed form of the data wrapper's MIME type
362 camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
364 CamelDataWrapperClass *class;
366 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
368 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
369 g_return_val_if_fail (class->get_mime_type_field != NULL, NULL);
371 return class->get_mime_type_field (data_wrapper);
375 * camel_data_wrapper_set_mime_type_field:
376 * @data_wrapper: a #CamelDataWrapper object
377 * @mime_type: a #CamelContentType
379 * This sets the data wrapper's MIME type. It suffers from the same
380 * flaws as #camel_data_wrapper_set_mime_type.
383 camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
384 CamelContentType *mime_type)
386 CamelDataWrapperClass *class;
388 g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
389 g_return_if_fail (mime_type != NULL);
391 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
392 g_return_if_fail (class->set_mime_type_field != NULL);
394 class->set_mime_type_field (data_wrapper, mime_type);
398 * camel_data_wrapper_is_offline:
399 * @data_wrapper: a #CamelDataWrapper object
401 * Returns: whether @data_wrapper is "offline" (data stored
402 * remotely) or not. Some optional code paths may choose to not
403 * operate on offline data.
406 camel_data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
408 CamelDataWrapperClass *class;
410 g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), TRUE);
412 class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
413 g_return_val_if_fail (class->is_offline != NULL, TRUE);
415 return class->is_offline (data_wrapper);