1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
2 /* camel-mime-part-utils : Utility for mime parsing and so on
4 * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
5 * Michael Zucchi <notzed@ximian.com>
6 * Jeffrey Stedfast <fejj@ximian.com>
8 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.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 Lesser 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
35 #include "camel-charset-map.h"
36 #include "camel-html-parser.h"
37 #include "camel-mime-filter-basic.h"
38 #include "camel-mime-filter-charset.h"
39 #include "camel-mime-filter-crlf.h"
40 #include "camel-mime-filter-save.h"
41 #include "camel-mime-message.h"
42 #include "camel-mime-part-utils.h"
43 #include "camel-multipart-encrypted.h"
44 #include "camel-multipart-signed.h"
45 #include "camel-multipart.h"
46 #include "camel-stream-filter.h"
47 #include "camel-stream-fs.h"
48 #include "camel-stream-mem.h"
49 #include "camel-stream-buffer.h"
50 #include "camel-utf8.h"
52 #define d(x) /* (printf("%s(%d): ", __FILE__, __LINE__),(x)) */
54 /* simple data wrapper */
56 simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw,
58 GCancellable *cancellable,
67 d (printf ("simple_data_wrapper_construct_from_parser()\n"));
69 /* read in the entire content */
70 buffer = g_byte_array_new ();
71 while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) {
72 d (printf ("appending o/p data: %d: %.*s\n", len, len, buf));
73 g_byte_array_append (buffer, (guint8 *) buf, len);
76 d (printf ("message part kept in memory!\n"));
78 mem = camel_stream_mem_new_with_byte_array (buffer);
79 success = camel_data_wrapper_construct_from_stream_sync (
80 dw, mem, cancellable, error);
87 * camel_mime_part_construct_content_from_parser:
92 camel_mime_part_construct_content_from_parser (CamelMimePart *dw,
94 GCancellable *cancellable,
97 CamelDataWrapper *content = NULL;
100 gboolean success = TRUE;
102 g_return_val_if_fail (CAMEL_IS_MIME_PART (dw), FALSE);
104 ct = camel_mime_parser_content_type (mp);
106 encoding = camel_content_transfer_encoding_decode (camel_mime_parser_header (mp, "Content-Transfer-Encoding", NULL));
108 switch (camel_mime_parser_state (mp)) {
109 case CAMEL_MIME_PARSER_STATE_HEADER:
110 d (printf ("Creating body part\n"));
111 /* multipart/signed is some type that we must treat as binary data. */
112 if (camel_content_type_is (ct, "multipart", "signed")) {
113 content = (CamelDataWrapper *) camel_multipart_signed_new ();
114 camel_multipart_construct_from_parser ((CamelMultipart *) content, mp);
116 content = camel_data_wrapper_new ();
117 success = simple_data_wrapper_construct_from_parser (
118 content, mp, cancellable, error);
121 case CAMEL_MIME_PARSER_STATE_MESSAGE:
122 d (printf ("Creating message part\n"));
123 content = (CamelDataWrapper *) camel_mime_message_new ();
124 success = camel_mime_part_construct_from_parser_sync (
125 (CamelMimePart *) content, mp, cancellable, error);
127 case CAMEL_MIME_PARSER_STATE_MULTIPART:
128 d (printf ("Creating multi-part\n"));
129 if (camel_content_type_is (ct, "multipart", "encrypted"))
130 content = (CamelDataWrapper *) camel_multipart_encrypted_new ();
131 else if (camel_content_type_is (ct, "multipart", "signed"))
132 content = (CamelDataWrapper *) camel_multipart_signed_new ();
134 content = (CamelDataWrapper *) camel_multipart_new ();
136 camel_multipart_construct_from_parser ((CamelMultipart *) content, mp);
137 d (printf ("Created multi-part\n"));
140 g_warning ("Invalid state encountered???: %u", camel_mime_parser_state (mp));
145 content->encoding = camel_transfer_encoding_from_string (encoding);
147 /* would you believe you have to set this BEFORE you set the content object??? oh my god !!!! */
148 camel_data_wrapper_set_mime_type_field (content, camel_mime_part_get_content_type (dw));
149 camel_medium_set_content ((CamelMedium *) dw, content);
150 g_object_unref (content);
159 * camel_mime_message_build_preview:
163 * This function blocks like crazy.
170 camel_mime_message_build_preview (CamelMimePart *msg,
171 CamelMessageInfo *info)
173 CamelDataWrapper *dw;
174 gboolean got_plain = FALSE;
176 dw = camel_medium_get_content ((CamelMedium *) msg);
177 if (camel_content_type_is (dw->mime_type, "multipart", "*")) {
179 CamelMultipart *mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) msg);
181 if (!CAMEL_IS_MULTIPART (mp))
183 nparts = camel_multipart_get_number (mp);
184 for (i = 0; i < nparts && !got_plain; i++) {
185 CamelMimePart *part = camel_multipart_get_part (mp, i);
186 got_plain = camel_mime_message_build_preview (part, info);
189 } else if (camel_content_type_is (dw->mime_type, "text", "*") &&
190 /* !camel_content_type_is (dw->mime_type, "text", "html") && */
191 !camel_content_type_is (dw->mime_type, "text", "calendar")) {
192 CamelStream *mstream, *bstream;
194 /* FIXME Pass a GCancellable and GError here. */
195 mstream = camel_stream_mem_new ();
196 if (camel_data_wrapper_decode_to_stream_sync (dw, mstream, NULL, NULL) > 0) {
198 GString *str = g_string_new (NULL);
201 G_SEEKABLE (mstream), 0,
202 G_SEEK_SET, NULL, NULL);
204 bstream = camel_stream_buffer_new (mstream, CAMEL_STREAM_BUFFER_READ | CAMEL_STREAM_BUFFER_BUFFER);
206 /* We should fetch just 200 unquoted lines. */
207 while ((line = camel_stream_buffer_read_line ((CamelStreamBuffer *) bstream, NULL, NULL)) && str->len < 200) {
210 if (*line == '>' || strstr (line, "wrote:")) {
214 if (g_str_has_prefix (line, "--")) {
219 while (*line && ((*line == ' ') || *line == '\t'))
221 if (*line == '\0' || *line == '\n') {
226 g_string_append (str, " ");
227 g_string_append (str, line);
231 if (str->len > 100) {
232 g_string_insert (str, 100, "\n");
234 /* We don't mark dirty, as we don't store these */
235 ((CamelMessageInfoBase *) info)->preview = camel_utf8_make_valid (str->str);
236 g_string_free (str, TRUE);
238 g_object_unref (bstream);
240 g_object_unref (mstream);