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 "camel-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 (camel_strcase_hash, camel_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 (camel_strcase_hash, camel_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 camel_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)
503 camel_string_list_free (mime_part->content_languages);
505 mime_part->content_languages = content_languages;
507 /* FIXME: translate to a header and set it */
511 camel_mime_part_get_content_languages (CamelMimePart *mime_part)
513 return mime_part->content_languages;
519 /* **** Content-Type: */
522 camel_mime_part_set_content_type (CamelMimePart *mime_part, const gchar *content_type)
524 camel_medium_set_header (CAMEL_MEDIUM (mime_part),
525 "Content-Type", content_type);
529 camel_mime_part_get_content_type (CamelMimePart *mime_part)
531 return mime_part->content_type;
539 set_content_object (CamelMedium *medium, CamelDataWrapper *content)
541 CamelMimePart *mime_part = CAMEL_MIME_PART (medium);
542 CamelContentType *object_content_type;
544 parent_class->set_content_object (medium, content);
546 object_content_type = camel_data_wrapper_get_mime_type_field (content);
547 if (mime_part->content_type != object_content_type) {
550 txt = header_content_type_format (object_content_type);
551 camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", txt);
556 /**********************************************************************/
559 write_references(CamelStream *stream, struct _header_raw *h)
564 /* this is only approximate, based on the next >, this way it retains any content
565 from the original which may not be properly formatted, etc. It also doesn't handle
566 the case where an individual messageid is too long, however thats a bad mail to
570 len = strlen(h->name)+1;
571 total = camel_stream_printf(stream, "%s%s", h->name, isspace(v[0])?":":": ");
576 ide = strchr(ids+1, '>');
580 ide = v = strlen(ids)+ids;
582 if (len>0 && len + (ide - ids) >= CAMEL_FOLD_SIZE) {
583 out = camel_stream_printf(stream, "\n\t");
589 out = camel_stream_write(stream, ids, ide-ids);
595 camel_stream_write(stream, "\n", 1);
601 /* not needed - yet - handled by default case */
603 write_fold(CamelStream *stream, struct _header_raw *h)
608 val = header_fold(h->value, strlen(h->name));
609 count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
617 write_raw(CamelStream *stream, struct _header_raw *h)
619 char *val = h->value;
621 return camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
625 write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream)
627 CamelMimePart *mp = CAMEL_MIME_PART(data_wrapper);
628 CamelMedium *medium = CAMEL_MEDIUM(data_wrapper);
629 CamelStream *ostream = stream;
630 CamelDataWrapper *content;
634 d(printf("mime_part::write_to_stream\n"));
636 /* FIXME: something needs to be done about this ... */
637 /* TODO: content-languages header? */
640 struct _header_raw *h = mp->headers;
642 int (*writefn)(CamelStream *stream, struct _header_raw *);
644 /* fold/write the headers. But dont fold headers that are already formatted
645 (e.g. ones with parameter-lists, that we know about, and have created) */
649 g_warning("h->value is NULL here for %s", h->name);
651 } else if ((writefn = g_hash_table_lookup(header_formatted_table, h->name)) == NULL) {
652 val = header_fold(val, strlen(h->name));
653 count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val);
656 count = writefn(stream, h);
665 count = camel_stream_write(stream, "\n", 1);
670 content = camel_medium_get_content_object(medium);
672 /* I dont really like this here, but i dont know where else it might go ... */
673 #define CAN_THIS_GO_ELSEWHERE
674 #ifdef CAN_THIS_GO_ELSEWHERE
675 CamelMimeFilter *filter = NULL;
676 CamelStreamFilter *filter_stream = NULL;
677 CamelMimeFilter *charenc = NULL;
678 const char *filename;
681 switch (mp->encoding) {
682 case CAMEL_MIME_PART_ENCODING_BASE64:
683 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_ENC);
685 case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE:
686 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_ENC);
688 case CAMEL_MIME_PART_ENCODING_UUENCODE:
689 filename = camel_mime_part_get_filename (mp);
690 count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled");
694 filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_ENC);
700 if (!content->rawtext && header_content_type_is(mp->content_type, "text", "*")) {
701 charset = header_content_type_param(mp->content_type, "charset");
702 if (charset && !(!strcasecmp(charset, "us-ascii") || !strcasecmp(charset, "utf-8"))) {
703 charenc = (CamelMimeFilter *)camel_mime_filter_charset_new_convert("UTF-8", charset);
707 if (filter || charenc) {
708 filter_stream = camel_stream_filter_new_with_stream(stream);
710 /* if we have a character encoder, add that always */
712 camel_stream_filter_add(filter_stream, charenc);
713 camel_object_unref((CamelObject *)charenc);
716 /* we only re-do crlf on encoded blocks */
717 if (filter && header_content_type_is(mp->content_type, "text", "*")) {
718 CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE,
719 CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
721 camel_stream_filter_add(filter_stream, crlf);
722 camel_object_unref((CamelObject *)crlf);
726 camel_stream_filter_add(filter_stream, filter);
727 camel_object_unref((CamelObject *)filter);
730 stream = (CamelStream *)filter_stream;
735 count = camel_data_wrapper_write_to_stream(content, stream);
738 camel_stream_flush((CamelStream *)filter_stream);
739 camel_object_unref((CamelObject *)filter_stream);
745 if (mp->encoding == CAMEL_MIME_PART_ENCODING_UUENCODE) {
746 count = camel_stream_write (ostream, "end\n", 4);
752 g_warning("No content for medium, nothing to write");
760 construct_from_parser(CamelMimePart *dw, CamelMimeParser *mp)
762 struct _header_raw *headers;
768 d(printf("mime_part::construct_from_parser()\n"));
770 switch (camel_mime_parser_step(mp, &buf, &len)) {
772 /* set the default type of a message always */
773 if (dw->content_type)
774 header_content_type_unref (dw->content_type);
775 dw->content_type = header_content_type_decode ("message/rfc822");
777 case HSCAN_MULTIPART:
778 /* we have the headers, build them into 'us' */
779 headers = camel_mime_parser_headers_raw(mp);
781 /* if content-type exists, process it first, set for fallback charset in headers */
782 content = header_raw_find(&headers, "content-type", NULL);
784 process_header((CamelMedium *)dw, "content-type", content);
787 if (strcasecmp(headers->name, "content-type") == 0
788 && headers->value != content)
789 camel_medium_add_header((CamelMedium *)dw, "X-Invalid-Content-Type", headers->value);
791 camel_medium_add_header((CamelMedium *)dw, headers->name, headers->value);
792 headers = headers->next;
795 camel_mime_part_construct_content_from_parser(dw, mp);
798 g_warning("Invalid state encountered???: %d", camel_mime_parser_state(mp));
801 d(printf("mime_part::construct_from_parser() leaving\n"));
802 err = camel_mime_parser_errno(mp);
812 * camel_mime_part_construct_from_parser:
821 camel_mime_part_construct_from_parser(CamelMimePart *mime_part, CamelMimeParser *mp)
823 return CMP_CLASS (mime_part)->construct_from_parser (mime_part, mp);
827 construct_from_stream(CamelDataWrapper *dw, CamelStream *s)
832 d(printf("mime_part::construct_from_stream()\n"));
834 mp = camel_mime_parser_new();
835 if (camel_mime_parser_init_with_stream(mp, s) == -1) {
836 g_warning("Cannot create parser for stream");
839 ret = camel_mime_part_construct_from_parser((CamelMimePart *)dw, mp);
841 camel_object_unref((CamelObject *)mp);
845 /* this must be kept in sync with the header */
846 static const char *encodings[] = {
857 camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding)
859 if (encoding >= sizeof(encodings)/sizeof(encodings[0]))
862 return encodings[encoding];
865 /* FIXME I am not sure this is the correct way to do this. */
866 CamelMimePartEncodingType
867 camel_mime_part_encoding_from_string (const gchar *string)
871 if (string != NULL) {
872 for (i=0;i<sizeof(encodings)/sizeof(encodings[0]);i++)
873 if (!strcasecmp(string, encodings[i]))
877 return CAMEL_MIME_PART_ENCODING_DEFAULT;
881 /******************************/
882 /** Misc utility functions **/
885 * camel_mime_part_new:
887 * Return value: a new CamelMimePart
890 camel_mime_part_new (void)
892 return (CamelMimePart *)camel_object_new (CAMEL_MIME_PART_TYPE);
896 * camel_mime_part_set_content:
897 * @camel_mime_part: Mime part
898 * @data: data to put into the part
899 * @length: length of @data
900 * @type: Content-Type of the data
902 * Utility function used to set the content of a mime part object to
903 * be the provided data. If @length is 0, this routine can be used as
904 * a way to remove old content (in which case @data and @type are
905 * ignored and may be %NULL).
908 camel_mime_part_set_content (CamelMimePart *camel_mime_part,
909 const char *data, int length,
910 const char *type) /* why on earth is the type last? */
912 CamelMedium *medium = CAMEL_MEDIUM (camel_mime_part);
915 CamelDataWrapper *dw;
918 dw = camel_data_wrapper_new ();
919 camel_data_wrapper_set_mime_type (dw, type);
920 stream = camel_stream_mem_new_with_buffer (data, length);
921 camel_data_wrapper_construct_from_stream (dw, stream);
922 camel_object_unref (CAMEL_OBJECT (stream));
923 camel_medium_set_content_object (medium, dw);
924 camel_object_unref (CAMEL_OBJECT (dw));
927 camel_object_unref (CAMEL_OBJECT (medium->content));
928 medium->content = NULL;