/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ /* camel-mime-part-utils : Utility for mime parsing and so on * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . * * Authors: Bertrand Guiheneuf * Michael Zucchi * Jeffrey Stedfast */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "camel-charset-map.h" #include "camel-html-parser.h" #include "camel-mime-filter-basic.h" #include "camel-mime-filter-charset.h" #include "camel-mime-filter-crlf.h" #include "camel-mime-message.h" #include "camel-mime-part-utils.h" #include "camel-multipart-encrypted.h" #include "camel-multipart-signed.h" #include "camel-multipart.h" #include "camel-stream-filter.h" #include "camel-stream-fs.h" #include "camel-stream-mem.h" #include "camel-stream-buffer.h" #include "camel-utf8.h" #define d(x) /* (printf("%s(%d): ", __FILE__, __LINE__),(x)) */ /* simple data wrapper */ static gboolean simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser *mp, GCancellable *cancellable, GError **error) { gchar *buf; GByteArray *buffer; CamelStream *mem; gsize len; gboolean success; d (printf ("simple_data_wrapper_construct_from_parser()\n")); /* read in the entire content */ buffer = g_byte_array_new (); while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) { d (printf ("appending o/p data: %d: %.*s\n", len, len, buf)); g_byte_array_append (buffer, (guint8 *) buf, len); } d (printf ("message part kept in memory!\n")); mem = camel_stream_mem_new_with_byte_array (buffer); success = camel_data_wrapper_construct_from_stream_sync ( dw, mem, cancellable, error); g_object_unref (mem); return success; } /** * camel_mime_part_construct_content_from_parser: * * Since: 2.24 **/ gboolean camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParser *mp, GCancellable *cancellable, GError **error) { CamelDataWrapper *content = NULL; CamelContentType *ct; gchar *encoding; gboolean success = TRUE; g_return_val_if_fail (CAMEL_IS_MIME_PART (dw), FALSE); ct = camel_mime_parser_content_type (mp); encoding = camel_content_transfer_encoding_decode (camel_mime_parser_header (mp, "Content-Transfer-Encoding", NULL)); switch (camel_mime_parser_state (mp)) { case CAMEL_MIME_PARSER_STATE_HEADER: d (printf ("Creating body part\n")); /* multipart/signed is some type that we must treat as binary data. */ if (camel_content_type_is (ct, "multipart", "signed")) { content = (CamelDataWrapper *) camel_multipart_signed_new (); camel_multipart_construct_from_parser ((CamelMultipart *) content, mp); } else { content = camel_data_wrapper_new (); success = simple_data_wrapper_construct_from_parser ( content, mp, cancellable, error); } break; case CAMEL_MIME_PARSER_STATE_MESSAGE: d (printf ("Creating message part\n")); content = (CamelDataWrapper *) camel_mime_message_new (); success = camel_mime_part_construct_from_parser_sync ( (CamelMimePart *) content, mp, cancellable, error); break; case CAMEL_MIME_PARSER_STATE_MULTIPART: d (printf ("Creating multi-part\n")); if (camel_content_type_is (ct, "multipart", "encrypted")) content = (CamelDataWrapper *) camel_multipart_encrypted_new (); else if (camel_content_type_is (ct, "multipart", "signed")) content = (CamelDataWrapper *) camel_multipart_signed_new (); else content = (CamelDataWrapper *) camel_multipart_new (); camel_multipart_construct_from_parser ((CamelMultipart *) content, mp); d (printf ("Created multi-part\n")); break; default: g_warning ("Invalid state encountered???: %u", camel_mime_parser_state (mp)); } if (content) { if (encoding) content->encoding = camel_transfer_encoding_from_string (encoding); /* would you believe you have to set this BEFORE you set the content object??? oh my god !!!! */ camel_data_wrapper_set_mime_type_field (content, camel_mime_part_get_content_type (dw)); camel_medium_set_content ((CamelMedium *) dw, content); g_object_unref (content); } g_free (encoding); return success; } /** * camel_mime_message_build_preview: * * * * This function blocks like crazy. * * * * Since: 2.28 **/ gboolean camel_mime_message_build_preview (CamelMimePart *msg, CamelMessageInfo *info) { CamelDataWrapper *dw; gboolean got_plain = FALSE; dw = camel_medium_get_content ((CamelMedium *) msg); if (camel_content_type_is (dw->mime_type, "multipart", "*")) { gint i, nparts; CamelMultipart *mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) msg); g_warn_if_fail (CAMEL_IS_MULTIPART (mp)); nparts = camel_multipart_get_number (mp); for (i = 0; i < nparts && !got_plain; i++) { CamelMimePart *part = camel_multipart_get_part (mp, i); got_plain = camel_mime_message_build_preview (part, info); } } else if (camel_content_type_is (dw->mime_type, "text", "*") && /* !camel_content_type_is (dw->mime_type, "text", "html") && */ !camel_content_type_is (dw->mime_type, "text", "calendar")) { CamelStream *mstream, *bstream; /* FIXME Pass a GCancellable and GError here. */ mstream = camel_stream_mem_new (); if (camel_data_wrapper_decode_to_stream_sync (dw, mstream, NULL, NULL) > 0) { gchar *line = NULL; GString *str = g_string_new (NULL); g_seekable_seek ( G_SEEKABLE (mstream), 0, G_SEEK_SET, NULL, NULL); bstream = camel_stream_buffer_new (mstream, CAMEL_STREAM_BUFFER_READ | CAMEL_STREAM_BUFFER_BUFFER); /* We should fetch just 200 unquoted lines. */ while ((line = camel_stream_buffer_read_line ((CamelStreamBuffer *) bstream, NULL, NULL)) && str->len < 200) { gchar *tmp = line; if (*line == '>' || strstr (line, "wrote:")) { g_free (tmp); continue; } if (g_str_has_prefix (line, "--")) { g_free (tmp); line = NULL; break; } while (*line && ((*line == ' ') || *line == '\t')) line++; if (*line == '\0' || *line == '\n') { g_free (tmp); continue; } g_string_append (str, " "); g_string_append (str, line); g_free (tmp); line = NULL; } if (str->len > 100) { g_string_insert (str, 100, "\n"); } /* We don't mark dirty, as we don't store these */ ((CamelMessageInfoBase *) info)->preview = camel_utf8_make_valid (str->str); g_string_free (str, TRUE); g_object_unref (bstream); } g_object_unref (mstream); return TRUE; } return got_plain; }