1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
2 /* camelMimePart.c : Abstract class for a mime_part */
5 * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
6 * Michael Zucchi <notzed@ximian.com>
8 * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34 #include <gal/util/e-iconv.h>
36 #include "camel-mime-parser.h"
37 #include "camel-stream-mem.h"
38 #include "camel-stream-filter.h"
39 #include "camel-mime-filter-basic.h"
40 #include "camel-mime-filter-crlf.h"
41 #include "camel-mime-filter-charset.h"
42 #include "camel-mime-part.h"
43 #include "camel-mime-part-utils.h"
44 #include "camel-mime-utils.h"
45 #include "camel-exception.h"
46 #include "camel-charset-map.h"
47 #include "string-utils.h"
49 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
58 HEADER_CONTENT_LOCATION,
59 HEADER_CONTENT_LANGUAGES,
64 static GHashTable *header_name_table;
65 static GHashTable *header_formatted_table;
67 static CamelMediumClass *parent_class=NULL;
69 /* Returns the class for a CamelMimePart */
70 #define CMP_CLASS(so) CAMEL_MIME_PART_CLASS (CAMEL_OBJECT_GET_CLASS(so))
71 #define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
72 #define CMD_CLASS(so) CAMEL_MEDIUM_CLASS (CAMEL_OBJECT_GET_CLASS(so))
74 /* from CamelDataWrapper */
75 static int write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
76 static int construct_from_stream (CamelDataWrapper *dw, CamelStream *s);
79 static void add_header (CamelMedium *medium, const char *header_name, const void *header_value);
80 static void set_header (CamelMedium *medium, const char *header_name, const void *header_value);
81 static void remove_header (CamelMedium *medium, const char *header_name);
82 static const void *get_header (CamelMedium *medium, const char *header_name);
83 static GArray *get_headers (CamelMedium *medium);
84 static void free_headers (CamelMedium *medium, GArray *headers);
86 static void set_content_object (CamelMedium *medium, CamelDataWrapper *content);
88 /* from camel mime parser */
89 static int construct_from_parser (CamelMimePart *, CamelMimeParser *);
91 /* forward references */
92 static void set_disposition (CamelMimePart *mime_part, const gchar *disposition);
94 /* format output of headers */
95 static int write_references(CamelStream *stream, struct _header_raw *h);
96 /*static int write_fold(CamelStream *stream, struct _header_raw *h);*/
97 static int write_raw(CamelStream *stream, struct _header_raw *h);
100 /* loads in a hash table the set of header names we */
101 /* recognize and associate them with a unique enum */
102 /* identifier (see CamelHeaderType above) */
104 init_header_name_table()
106 header_name_table = g_hash_table_new (g_strcase_hash, g_strcase_equal);
107 g_hash_table_insert (header_name_table, "Content-Description", (gpointer)HEADER_DESCRIPTION);
108 g_hash_table_insert (header_name_table, "Content-Disposition", (gpointer)HEADER_DISPOSITION);
109 g_hash_table_insert (header_name_table, "Content-id", (gpointer)HEADER_CONTENT_ID);
110 g_hash_table_insert (header_name_table, "Content-Transfer-Encoding", (gpointer)HEADER_ENCODING);
111 g_hash_table_insert (header_name_table, "Content-MD5", (gpointer)HEADER_CONTENT_MD5);
112 g_hash_table_insert (header_name_table, "Content-Location", (gpointer)HEADER_CONTENT_LOCATION);
113 g_hash_table_insert (header_name_table, "Content-Type", (gpointer)HEADER_CONTENT_TYPE);
115 header_formatted_table = g_hash_table_new(g_strcase_hash, g_strcase_equal);
116 g_hash_table_insert(header_formatted_table, "Content-Type", write_raw);
117 g_hash_table_insert(header_formatted_table, "Content-Disposition", write_raw);
118 g_hash_table_insert(header_formatted_table, "To", write_raw);
119 g_hash_table_insert(header_formatted_table, "From", write_raw);
120 g_hash_table_insert(header_formatted_table, "Reply-To", write_raw);
121 g_hash_table_insert(header_formatted_table, "Cc", write_raw);
122 g_hash_table_insert(header_formatted_table, "Bcc", write_raw);
123 g_hash_table_insert(header_formatted_table, "Message-ID", write_raw);
124 g_hash_table_insert(header_formatted_table, "In-Reply-To", write_raw);
125 g_hash_table_insert(header_formatted_table, "References", write_references);
129 camel_mime_part_class_init (CamelMimePartClass *camel_mime_part_class)
131 CamelMediumClass *camel_medium_class = CAMEL_MEDIUM_CLASS (camel_mime_part_class);
132 CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_mime_part_class);
134 parent_class = CAMEL_MEDIUM_CLASS (camel_type_get_global_classfuncs (camel_medium_get_type ()));
135 init_header_name_table();
137 camel_mime_part_class->construct_from_parser = construct_from_parser;
139 /* virtual method overload */
140 camel_medium_class->add_header = add_header;
141 camel_medium_class->set_header = set_header;
142 camel_medium_class->get_header = get_header;
143 camel_medium_class->remove_header = remove_header;
144 camel_medium_class->get_headers = get_headers;
145 camel_medium_class->free_headers = free_headers;
146 camel_medium_class->set_content_object = set_content_object;
148 camel_data_wrapper_class->write_to_stream = write_to_stream;
149 camel_data_wrapper_class->construct_from_stream= construct_from_stream;
153 camel_mime_part_init (gpointer object, gpointer klass)
155 CamelMimePart *camel_mime_part = CAMEL_MIME_PART (object);
157 camel_mime_part->content_type = header_content_type_new ("text", "plain");
158 camel_mime_part->description = NULL;
159 camel_mime_part->disposition = NULL;
160 camel_mime_part->content_id = NULL;
161 camel_mime_part->content_MD5 = NULL;
162 camel_mime_part->content_location = NULL;
163 camel_mime_part->content_languages = NULL;
164 camel_mime_part->encoding = CAMEL_MIME_PART_ENCODING_DEFAULT;
169 camel_mime_part_finalize (CamelObject *object)
171 CamelMimePart *mime_part = CAMEL_MIME_PART (object);
173 g_free (mime_part->description);
174 g_free (mime_part->content_id);
175 g_free (mime_part->content_MD5);
176 g_free (mime_part->content_location);
177 string_list_free (mime_part->content_languages);
178 header_disposition_unref(mime_part->disposition);
180 if (mime_part->content_type)
181 header_content_type_unref (mime_part->content_type);
183 header_raw_clear(&mime_part->headers);
189 camel_mime_part_get_type (void)
191 static CamelType camel_mime_part_type = CAMEL_INVALID_TYPE;
193 if (camel_mime_part_type == CAMEL_INVALID_TYPE) {
194 camel_mime_part_type = camel_type_register (CAMEL_MEDIUM_TYPE, "CamelMimePart",
195 sizeof (CamelMimePart),
196 sizeof (CamelMimePartClass),
197 (CamelObjectClassInitFunc) camel_mime_part_class_init,
199 (CamelObjectInitFunc) camel_mime_part_init,
200 (CamelObjectFinalizeFunc) camel_mime_part_finalize);
203 return camel_mime_part_type;
210 process_header(CamelMedium *medium, const char *header_name, const char *header_value)
212 CamelMimePart *mime_part = CAMEL_MIME_PART (medium);
213 CamelHeaderType header_type;
217 /* Try to parse the header pair. If it corresponds to something */
218 /* known, the job is done in the parsing routine. If not, */
219 /* we simply add the header in a raw fashion */
221 header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, header_name);
222 switch (header_type) {
223 case HEADER_DESCRIPTION: /* raw header->utf8 conversion */
224 g_free (mime_part->description);
225 if (mime_part->content_type) {
226 charset = header_content_type_param (mime_part->content_type, "charset");
227 charset = e_iconv_charset_name (charset);
230 mime_part->description = g_strstrip (header_decode_string (header_value, charset));
232 case HEADER_DISPOSITION:
233 set_disposition (mime_part, header_value);
235 case HEADER_CONTENT_ID:
236 g_free (mime_part->content_id);
237 mime_part->content_id = header_contentid_decode (header_value);
239 case HEADER_ENCODING:
240 text = header_token_decode (header_value);
241 mime_part->encoding = camel_mime_part_encoding_from_string (text);
244 case HEADER_CONTENT_MD5:
245 g_free (mime_part->content_MD5);
246 mime_part->content_MD5 = g_strdup (header_value);
248 case HEADER_CONTENT_LOCATION:
249 g_free (mime_part->content_location);
250 mime_part->content_location = header_location_decode (header_value);
252 case HEADER_CONTENT_TYPE:
253 if (mime_part->content_type)
254 header_content_type_unref (mime_part->content_type);
255 mime_part->content_type = header_content_type_decode (header_value);
264 set_header (CamelMedium *medium, const char *header_name, const void *header_value)
266 CamelMimePart *part = CAMEL_MIME_PART (medium);
268 process_header(medium, header_name, header_value);
269 header_raw_replace(&part->headers, header_name, header_value, -1);
273 add_header (CamelMedium *medium, const char *header_name, const void *header_value)
275 CamelMimePart *part = CAMEL_MIME_PART (medium);
277 /* Try to parse the header pair. If it corresponds to something */
278 /* known, the job is done in the parsing routine. If not, */
279 /* we simply add the header in a raw fashion */
281 /* If it was one of the headers we handled, it must be unique, set it instead of add */
282 if (process_header(medium, header_name, header_value))
283 header_raw_replace(&part->headers, header_name, header_value, -1);
285 header_raw_append(&part->headers, header_name, header_value, -1);
289 remove_header (CamelMedium *medium, const char *header_name)
291 CamelMimePart *part = (CamelMimePart *)medium;
293 process_header(medium, header_name, NULL);
294 header_raw_remove(&part->headers, header_name);
298 get_header (CamelMedium *medium, const char *header_name)
300 CamelMimePart *part = (CamelMimePart *)medium;
302 return header_raw_find(&part->headers, header_name, NULL);
306 get_headers (CamelMedium *medium)
308 CamelMimePart *part = (CamelMimePart *)medium;
310 CamelMediumHeader header;
311 struct _header_raw *h;
313 headers = g_array_new (FALSE, FALSE, sizeof (CamelMediumHeader));
314 for (h = part->headers; h; h = h->next) {
315 header.name = h->name;
316 header.value = h->value;
317 g_array_append_val (headers, header);
324 free_headers (CamelMedium *medium, GArray *gheaders)
326 g_array_free (gheaders, TRUE);
329 /* **** Content-Description */
331 camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description)
333 char *text = header_encode_string (description);
335 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
336 "Content-Description", text);
341 camel_mime_part_get_description (CamelMimePart *mime_part)
343 return mime_part->description;
346 /* **** Content-Disposition */
349 set_disposition (CamelMimePart *mime_part, const gchar *disposition)
351 header_disposition_unref(mime_part->disposition);
353 mime_part->disposition = header_disposition_decode(disposition);
355 mime_part->disposition = NULL;
360 camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition)
364 /* we poke in a new disposition (so we dont lose 'filename', etc) */
365 if (mime_part->disposition == NULL) {
366 set_disposition(mime_part, disposition);
368 if (mime_part->disposition != NULL) {
369 g_free(mime_part->disposition->disposition);
370 mime_part->disposition->disposition = g_strdup(disposition);
372 text = header_disposition_format(mime_part->disposition);
374 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
375 "Content-Disposition", text);
381 camel_mime_part_get_disposition (CamelMimePart *mime_part)
383 if (mime_part->disposition)
384 return (mime_part->disposition)->disposition;
390 /* **** Content-Disposition: filename="xxx" */
393 camel_mime_part_set_filename (CamelMimePart *mime_part, const gchar *filename)
397 if (mime_part->disposition == NULL)
398 mime_part->disposition = header_disposition_decode("attachment");
400 header_set_param(&mime_part->disposition->params, "filename", filename);
401 str = header_disposition_format(mime_part->disposition);
403 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
404 "Content-Disposition", str);
407 header_content_type_set_param (mime_part->content_type, "name", filename);
408 str = header_content_type_format (mime_part->content_type);
409 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", str);
414 camel_mime_part_get_filename (CamelMimePart *mime_part)
416 if (mime_part->disposition) {
417 const gchar *name = header_param (mime_part->disposition->params, "filename");
422 return header_content_type_param (mime_part->content_type, "name");
426 /* **** Content-ID: */
429 camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid)
434 id = g_strstrip (g_strdup (contentid));
436 id = header_msgid_generate ();
438 cid = g_strdup_printf ("<%s>", id);
440 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-ID", cid);
445 camel_mime_part_get_content_id (CamelMimePart *mime_part)
447 return mime_part->content_id;
450 /* **** Content-MD5: */
453 camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *md5)
455 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-MD5", md5);
459 camel_mime_part_get_content_MD5 (CamelMimePart *mime_part)
461 return mime_part->content_MD5;
464 /* **** Content-MD5: */
467 camel_mime_part_set_content_location (CamelMimePart *mime_part, const char *location)
469 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Location", location);
473 camel_mime_part_get_content_location (CamelMimePart *mime_part)
475 return mime_part->content_location;
478 /* **** Content-Transfer-Encoding: */
481 camel_mime_part_set_encoding (CamelMimePart *mime_part,
482 CamelMimePartEncodingType encoding)
486 text = camel_mime_part_encoding_to_string (encoding);
487 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
488 "Content-Transfer-Encoding", text);
491 CamelMimePartEncodingType
492 camel_mime_part_get_encoding (CamelMimePart *mime_part)
494 return mime_part->encoding;
497 /* FIXME: do something with this stuff ... */
500 camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages)
502 if (mime_part->content_languages) string_list_free (mime_part->content_languages);
503 mime_part->content_languages = content_languages;
505 /* FIXME: translate to a header and set it */
509 camel_mime_part_get_content_languages (CamelMimePart *mime_part)
511 return mime_part->content_languages;
517 /* **** Content-Type: */
520 camel_mime_part_set_content_type (CamelMimePart *mime_part, const gchar *content_type)
522 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
523 "Content-Type", content_type);
527 camel_mime_part_get_content_type (CamelMimePart *mime_part)
529 return mime_part->content_type;
537 set_content_object (CamelMedium *medium, CamelDataWrapper *content)
539 CamelMimePart *mime_part = CAMEL_MIME_PART (medium);
540 CamelContentType *object_content_type;
542 parent_class->set_content_object (medium, content);
544 object_content_type = camel_data_wrapper_get_mime_type_field (content);
545 if (mime_part->content_type != object_content_type) {
548 txt = header_content_type_format (object_content_type);
549 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", txt);
554 /**********************************************************************/
557 write_references(CamelStream *stream, struct _header_raw *h)
562 /* this is only approximate, based on the next >, this way it retains any content
563 from the original which may not be properly formatted, etc. It also doesn't handle
564 the case where an individual messageid is too long, however thats a bad mail to
568 len = strlen(h->name)+1;
569 total = camel_stream_printf(stream, "%s%s", h->name, isspace(v[0])?":":": ");
574 ide = strchr(ids+1, '>');
578 ide = v = strlen(ids)+ids;
580 if (len>0 && len + (ide - ids) >= CAMEL_FOLD_SIZE) {
581 out = camel_stream_printf(stream, "\n\t");
587 out = camel_stream_write(stream, ids, ide-ids);
593 camel_stream_write(stream, "\n", 1);
599 /* not needed - yet - handled by default case */
601 write_fold(CamelStream *stream, struct _header_raw *h)
606 val = header_fold(h->value, strlen(h->name));
607 count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
615 write_raw(CamelStream *stream, struct _header_raw *h)
617 char *val = h->value;
619 return camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
623 write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream)
625 CamelMimePart *mp = CAMEL_MIME_PART(data_wrapper);
626 CamelMedium *medium = CAMEL_MEDIUM(data_wrapper);
627 CamelStream *ostream = stream;
628 CamelDataWrapper *content;
632 d(printf("mime_part::write_to_stream\n"));
634 /* FIXME: something needs to be done about this ... */
635 /* TODO: content-languages header? */
638 struct _header_raw *h = mp->headers;
640 int (*writefn)(CamelStream *stream, struct _header_raw *);
642 /* fold/write the headers. But dont fold headers that are already formatted
643 (e.g. ones with parameter-lists, that we know about, and have created) */
647 g_warning("h->value is NULL here for %s", h->name);
649 } else if ((writefn = g_hash_table_lookup(header_formatted_table, h->name)) == NULL) {
650 val = header_fold(val, strlen(h->name));
651 count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
654 count = writefn(stream, h);
663 count = camel_stream_write(stream, "\n", 1);
668 content = camel_medium_get_content_object(medium);
670 /* I dont really like this here, but i dont know where else it might go ... */
671 #define CAN_THIS_GO_ELSEWHERE
672 #ifdef CAN_THIS_GO_ELSEWHERE
673 CamelMimeFilter *filter = NULL;
674 CamelStreamFilter *filter_stream = NULL;
675 CamelMimeFilter *charenc = NULL;
676 const char *filename;
679 switch (mp->encoding) {
680 case CAMEL_MIME_PART_ENCODING_BASE64:
681 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_ENC);
683 case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE:
684 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_ENC);
686 case CAMEL_MIME_PART_ENCODING_UUENCODE:
687 filename = camel_mime_part_get_filename (mp);
688 count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled");
692 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_ENC);
698 if (!content->rawtext && header_content_type_is(mp->content_type, "text", "*")) {
699 charset = header_content_type_param(mp->content_type, "charset");
700 if (charset && !(!strcasecmp(charset, "us-ascii") || !strcasecmp(charset, "utf-8"))) {
701 charenc = (CamelMimeFilter *)camel_mime_filter_charset_new_convert("UTF-8", charset);
705 if (filter || charenc) {
706 filter_stream = camel_stream_filter_new_with_stream(stream);
708 /* if we have a character encoder, add that always */
710 camel_stream_filter_add(filter_stream, charenc);
711 camel_object_unref((CamelObject *)charenc);
714 /* we only re-do crlf on encoded blocks */
715 if (filter && header_content_type_is(mp->content_type, "text", "*")) {
716 CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE,
717 CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
719 camel_stream_filter_add(filter_stream, crlf);
720 camel_object_unref((CamelObject *)crlf);
724 camel_stream_filter_add(filter_stream, filter);
725 camel_object_unref((CamelObject *)filter);
728 stream = (CamelStream *)filter_stream;
733 count = camel_data_wrapper_write_to_stream(content, stream);
736 camel_stream_flush((CamelStream *)filter_stream);
737 camel_object_unref((CamelObject *)filter_stream);
743 if (mp->encoding == CAMEL_MIME_PART_ENCODING_UUENCODE) {
744 count = camel_stream_write (ostream, "end\n", 4);
750 g_warning("No content for medium, nothing to write");
758 construct_from_parser(CamelMimePart *dw, CamelMimeParser *mp)
760 struct _header_raw *headers;
766 d(printf("mime_part::construct_from_parser()\n"));
768 switch (camel_mime_parser_step(mp, &buf, &len)) {
770 /* set the default type of a message always */
771 if (dw->content_type)
772 header_content_type_unref (dw->content_type);
773 dw->content_type = header_content_type_decode ("message/rfc822");
775 case HSCAN_MULTIPART:
776 /* we have the headers, build them into 'us' */
777 headers = camel_mime_parser_headers_raw(mp);
779 /* if content-type exists, process it first, set for fallback charset in headers */
780 content = header_raw_find(&headers, "content-type", NULL);
782 process_header((CamelMedium *)dw, "content-type", content);
785 if (strcasecmp(headers->name, "content-type") == 0
786 && headers->value != content)
787 camel_medium_add_header((CamelMedium *)dw, "X-Invalid-Content-Type", headers->value);
789 camel_medium_add_header((CamelMedium *)dw, headers->name, headers->value);
790 headers = headers->next;
793 camel_mime_part_construct_content_from_parser(dw, mp);
796 g_warning("Invalid state encountered???: %d", camel_mime_parser_state(mp));
799 d(printf("mime_part::construct_from_parser() leaving\n"));
800 err = camel_mime_parser_errno(mp);
810 * camel_mime_part_construct_from_parser:
819 camel_mime_part_construct_from_parser(CamelMimePart *mime_part, CamelMimeParser *mp)
821 return CMP_CLASS (mime_part)->construct_from_parser (mime_part, mp);
825 construct_from_stream(CamelDataWrapper *dw, CamelStream *s)
830 d(printf("mime_part::construct_from_stream()\n"));
832 mp = camel_mime_parser_new();
833 if (camel_mime_parser_init_with_stream(mp, s) == -1) {
834 g_warning("Cannot create parser for stream");
837 ret = camel_mime_part_construct_from_parser((CamelMimePart *)dw, mp);
839 camel_object_unref((CamelObject *)mp);
843 /* this must be kept in sync with the header */
844 static const char *encodings[] = {
855 camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding)
857 if (encoding >= sizeof(encodings)/sizeof(encodings[0]))
860 return encodings[encoding];
863 /* FIXME I am not sure this is the correct way to do this. */
864 CamelMimePartEncodingType
865 camel_mime_part_encoding_from_string (const gchar *string)
869 if (string != NULL) {
870 for (i=0;i<sizeof(encodings)/sizeof(encodings[0]);i++)
871 if (!strcasecmp(string, encodings[i]))
875 return CAMEL_MIME_PART_ENCODING_DEFAULT;
879 /******************************/
880 /** Misc utility functions **/
883 * camel_mime_part_new:
885 * Return value: a new CamelMimePart
888 camel_mime_part_new (void)
890 return (CamelMimePart *)camel_object_new (CAMEL_MIME_PART_TYPE);
894 * camel_mime_part_set_content:
895 * @camel_mime_part: Mime part
896 * @data: data to put into the part
897 * @length: length of @data
898 * @type: Content-Type of the data
900 * Utility function used to set the content of a mime part object to
901 * be the provided data. If @length is 0, this routine can be used as
902 * a way to remove old content (in which case @data and @type are
903 * ignored and may be %NULL).
906 camel_mime_part_set_content (CamelMimePart *camel_mime_part,
907 const char *data, int length,
908 const char *type) /* why on earth is the type last? */
910 CamelMedium *medium = CAMEL_MEDIUM (camel_mime_part);
913 CamelDataWrapper *dw;
916 dw = camel_data_wrapper_new ();
917 camel_data_wrapper_set_mime_type (dw, type);
918 stream = camel_stream_mem_new_with_buffer (data, length);
919 camel_data_wrapper_construct_from_stream (dw, stream);
920 camel_object_unref (CAMEL_OBJECT (stream));
921 camel_medium_set_content_object (medium, dw);
922 camel_object_unref (CAMEL_OBJECT (dw));
925 camel_object_unref (CAMEL_OBJECT (medium->content));
926 medium->content = NULL;