Files
evolution/em-format/e-mail-parser-text-plain.c
Milan Crha a4af2d6aee Postscript attachments not shown in message preview
The application/postscript mime type had been handled by the text-hightlight
module, but thinking of it, it doesn't make much sense, because most users
would prefer to see the content rather in a postscript viewer, than
the source of the postscript file, thus this change removes the mime type
from the text-hightlight module. There had been also issues about thinking
that certain parts had been handled, while they did not, which this change
fixes as well.

The issue had been reported downstream at:
https://bugzilla.redhat.com/show_bug.cgi?id=1187327
2015-02-09 18:08:29 +01:00

216 lines
5.7 KiB
C

/*
* e-mail-parser-text-plain.c
*
* This program 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 program 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 General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ctype.h>
#include <glib/gi18n-lib.h>
#include <e-util/e-util.h>
#include "e-mail-inline-filter.h"
#include "e-mail-parser-extension.h"
#include "e-mail-part-utils.h"
typedef EMailParserExtension EMailParserTextPlain;
typedef EMailParserExtensionClass EMailParserTextPlainClass;
GType e_mail_parser_text_plain_get_type (void);
G_DEFINE_TYPE (
EMailParserTextPlain,
e_mail_parser_text_plain,
E_TYPE_MAIL_PARSER_EXTENSION)
static const gchar *parser_mime_types[] = {
"text/plain",
"text/*",
NULL
};
static gboolean
process_part (EMailParser *parser,
GString *part_id,
gint part_number,
CamelMimePart *part,
gboolean is_attachment,
GCancellable *cancellable,
GQueue *out_mail_parts)
{
CamelContentType *type;
EMailPart *mail_part;
gint s_len = part_id->len;
gboolean handled = TRUE;
type = camel_mime_part_get_content_type (part);
if (!camel_content_type_is (type, "text", "*")) {
handled = e_mail_parser_parse_part (
parser, CAMEL_MIME_PART (part), part_id,
cancellable, out_mail_parts);
} else if (!camel_content_type_is (type, "text", "calendar")) {
GQueue work_queue = G_QUEUE_INIT;
gchar *mime_type;
g_string_append_printf (part_id, ".plain_text.%d", part_number);
mail_part = e_mail_part_new (part, part_id->str);
mime_type = camel_content_type_simple (type);
e_mail_part_set_mime_type (mail_part, mime_type);
g_free (mime_type);
g_string_truncate (part_id, s_len);
g_queue_push_tail (&work_queue, mail_part);
if (is_attachment)
e_mail_parser_wrap_as_attachment (
parser, part, part_id, &work_queue);
e_queue_transfer (&work_queue, out_mail_parts);
} else {
g_string_append_printf (part_id, ".inline.%d", part_number);
handled = e_mail_parser_parse_part (
parser, CAMEL_MIME_PART (part), part_id,
cancellable, out_mail_parts);
g_string_truncate (part_id, s_len);
}
return handled;
}
static gboolean
empe_text_plain_parse (EMailParserExtension *extension,
EMailParser *parser,
CamelMimePart *part,
GString *part_id,
GCancellable *cancellable,
GQueue *out_mail_parts)
{
CamelStream *filtered_stream, *null;
CamelMultipart *mp;
CamelDataWrapper *dw;
CamelContentType *type;
gint ii, count;
EMailInlineFilter *inline_filter;
gboolean charset_added = FALSE;
const gchar *snoop_type = NULL;
gboolean is_attachment;
gboolean handled = FALSE;
dw = camel_medium_get_content ((CamelMedium *) part);
if (!dw)
return FALSE;
/* This scans the text part for inline-encoded data, creates
* a multipart of all the parts inside it. */
/* FIXME: We should discard this multipart if it only contains
* the original text, but it makes this hash lookup more complex */
if (!dw->mime_type)
snoop_type = e_mail_part_snoop_type (part);
/* if we had to snoop the part type to get here, then
* use that as the base type, yuck */
if (snoop_type == NULL
|| (type = camel_content_type_decode (snoop_type)) == NULL) {
type = dw->mime_type;
camel_content_type_ref (type);
}
if (dw->mime_type && type != dw->mime_type && camel_content_type_param (dw->mime_type, "charset")) {
camel_content_type_set_param (type, "charset", camel_content_type_param (dw->mime_type, "charset"));
charset_added = TRUE;
}
null = camel_stream_null_new ();
filtered_stream = camel_stream_filter_new (null);
g_object_unref (null);
inline_filter = e_mail_inline_filter_new (
camel_mime_part_get_encoding (part),
type,
camel_mime_part_get_filename (part));
camel_stream_filter_add (
CAMEL_STREAM_FILTER (filtered_stream),
CAMEL_MIME_FILTER (inline_filter));
camel_data_wrapper_decode_to_stream_sync (
dw, (CamelStream *) filtered_stream, cancellable, NULL);
camel_stream_close ((CamelStream *) filtered_stream, cancellable, NULL);
g_object_unref (filtered_stream);
if (!e_mail_inline_filter_found_any (inline_filter)) {
g_object_unref (inline_filter);
camel_content_type_unref (type);
return process_part (
parser, part_id, 0,
part, e_mail_part_is_attachment (part),
cancellable, out_mail_parts);
}
mp = e_mail_inline_filter_get_multipart (inline_filter);
if (charset_added) {
camel_content_type_set_param (type, "charset", NULL);
}
g_object_unref (inline_filter);
camel_content_type_unref (type);
/* We handle our made-up multipart here,
* so we don't recursively call ourselves. */
count = camel_multipart_get_number (mp);
is_attachment = ((count == 1) && (e_mail_part_is_attachment (part)));
for (ii = 0; ii < count; ii++) {
CamelMimePart *newpart = camel_multipart_get_part (mp, ii);
if (newpart != NULL) {
handled |= process_part (
parser, part_id, ii,
newpart, is_attachment,
cancellable, out_mail_parts);
}
}
g_object_unref (mp);
return handled;
}
static void
e_mail_parser_text_plain_class_init (EMailParserExtensionClass *class)
{
class->mime_types = parser_mime_types;
class->priority = G_PRIORITY_LOW;
class->parse = empe_text_plain_parse;
}
static void
e_mail_parser_text_plain_init (EMailParserExtension *extension)
{
}