Blame src/em-format/e-mail-parser.c.cve-2018-15587-reposition-signature-bar

Packit 96aaae
/*
Packit 96aaae
 * e-mail-parser.c
Packit 96aaae
 *
Packit 96aaae
 * This program is free software; you can redistribute it and/or modify it
Packit 96aaae
 * under the terms of the GNU Lesser General Public License as published by
Packit 96aaae
 * the Free Software Foundation.
Packit 96aaae
 *
Packit 96aaae
 * This program is distributed in the hope that it will be useful, but
Packit 96aaae
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 96aaae
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 96aaae
 * for more details.
Packit 96aaae
 *
Packit 96aaae
 * You should have received a copy of the GNU Lesser General Public License
Packit 96aaae
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit 96aaae
 *
Packit 96aaae
 */
Packit 96aaae
Packit 96aaae
#include "evolution-config.h"
Packit 96aaae
Packit 96aaae
#include "e-mail-parser.h"
Packit 96aaae
Packit 96aaae
#include <string.h>
Packit 96aaae
Packit 96aaae
#include <libebackend/libebackend.h>
Packit 96aaae
Packit 96aaae
#include <shell/e-shell.h>
Packit 96aaae
#include <shell/e-shell-window.h>
Packit 96aaae
Packit 96aaae
#include "e-mail-parser-extension.h"
Packit 96aaae
#include "e-mail-part-attachment.h"
Packit 96aaae
#include "e-mail-part-utils.h"
Packit 96aaae
Packit 96aaae
#define E_MAIL_PARSER_GET_PRIVATE(obj) \
Packit 96aaae
	(G_TYPE_INSTANCE_GET_PRIVATE \
Packit 96aaae
	((obj), E_TYPE_MAIL_PARSER, EMailParserPrivate))
Packit 96aaae
Packit 96aaae
#define d(x)
Packit 96aaae
Packit 96aaae
struct _EMailParserPrivate {
Packit 96aaae
	GMutex mutex;
Packit 96aaae
Packit 96aaae
	gint last_error;
Packit 96aaae
Packit 96aaae
	CamelSession *session;
Packit 96aaae
};
Packit 96aaae
Packit 96aaae
enum {
Packit 96aaae
	PROP_0,
Packit 96aaae
	PROP_SESSION
Packit 96aaae
};
Packit 96aaae
Packit 96aaae
/* internal parser extensions */
Packit 96aaae
GType e_mail_parser_application_mbox_get_type (void);
Packit 96aaae
GType e_mail_parser_audio_get_type (void);
Packit 96aaae
GType e_mail_parser_headers_get_type (void);
Packit 96aaae
GType e_mail_parser_message_get_type (void);
Packit 96aaae
GType e_mail_parser_secure_button_get_type (void);
Packit 96aaae
GType e_mail_parser_source_get_type (void);
Packit 96aaae
GType e_mail_parser_image_get_type (void);
Packit 96aaae
GType e_mail_parser_inline_pgp_encrypted_get_type (void);
Packit 96aaae
GType e_mail_parser_inline_pgp_signed_get_type (void);
Packit 96aaae
GType e_mail_parser_message_delivery_status_get_type (void);
Packit 96aaae
GType e_mail_parser_message_external_get_type (void);
Packit 96aaae
GType e_mail_parser_message_rfc822_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_alternative_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_apple_double_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_digest_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_encrypted_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_mixed_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_related_get_type (void);
Packit 96aaae
GType e_mail_parser_multipart_signed_get_type (void);
Packit 96aaae
GType e_mail_parser_text_enriched_get_type (void);
Packit 96aaae
GType e_mail_parser_text_html_get_type (void);
Packit 96aaae
GType e_mail_parser_text_plain_get_type (void);
Packit 96aaae
#ifdef ENABLE_SMIME
Packit 96aaae
GType e_mail_parser_application_smime_get_type (void);
Packit 96aaae
#endif
Packit 96aaae
Packit 96aaae
static gpointer parent_class;
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
mail_parser_run (EMailParser *parser,
Packit 96aaae
                 EMailPartList *part_list,
Packit 96aaae
                 GCancellable *cancellable)
Packit 96aaae
{
Packit 96aaae
	EMailExtensionRegistry *reg;
Packit 96aaae
	CamelMimeMessage *message;
Packit 96aaae
	EMailPart *mail_part;
Packit 96aaae
	GQueue *parsers;
Packit 96aaae
	GQueue mail_part_queue = G_QUEUE_INIT;
Packit 96aaae
	GList *iter;
Packit 96aaae
	GString *part_id;
Packit 96aaae
Packit 96aaae
	message = e_mail_part_list_get_message (part_list);
Packit 96aaae
Packit 96aaae
	reg = e_mail_parser_get_extension_registry (parser);
Packit 96aaae
Packit 96aaae
	parsers = e_mail_extension_registry_get_for_mime_type (
Packit 96aaae
		reg, "application/vnd.evolution.message");
Packit 96aaae
Packit 96aaae
	if (parsers == NULL)
Packit 96aaae
		parsers = e_mail_extension_registry_get_for_mime_type (
Packit 96aaae
			reg, "message/*");
Packit 96aaae
Packit 96aaae
	/* No parsers means the internal Evolution parser
Packit 96aaae
	 * extensions were not loaded. Something is terribly wrong! */
Packit 96aaae
	g_return_if_fail (parsers != NULL);
Packit 96aaae
Packit 96aaae
	part_id = g_string_new (".message");
Packit 96aaae
Packit 96aaae
	mail_part = e_mail_part_new (CAMEL_MIME_PART (message), ".message");
Packit 96aaae
	e_mail_part_list_add_part (part_list, mail_part);
Packit 96aaae
	g_object_unref (mail_part);
Packit 96aaae
Packit 96aaae
	for (iter = parsers->head; iter; iter = iter->next) {
Packit 96aaae
		EMailParserExtension *extension;
Packit 96aaae
		gboolean message_handled;
Packit 96aaae
Packit 96aaae
		if (g_cancellable_is_cancelled (cancellable))
Packit 96aaae
			break;
Packit 96aaae
Packit 96aaae
		extension = iter->data;
Packit 96aaae
		if (!extension)
Packit 96aaae
			continue;
Packit 96aaae
Packit 96aaae
		message_handled = e_mail_parser_extension_parse (
Packit 96aaae
			extension, parser,
Packit 96aaae
			CAMEL_MIME_PART (message),
Packit 96aaae
			part_id, cancellable, &mail_part_queue);
Packit 96aaae
Packit 96aaae
		if (message_handled)
Packit 96aaae
			break;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	while (!g_queue_is_empty (&mail_part_queue)) {
Packit 96aaae
		mail_part = g_queue_pop_head (&mail_part_queue);
Packit 96aaae
		e_mail_part_list_add_part (part_list, mail_part);
Packit 96aaae
		g_object_unref (mail_part);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	g_string_free (part_id, TRUE);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
shell_gone_cb (gpointer user_data,
Packit 96aaae
	       GObject *gone_extension_registry)
Packit 96aaae
{
Packit 96aaae
	EMailParserClass *class = user_data;
Packit 96aaae
Packit 96aaae
	g_return_if_fail (class != NULL);
Packit 96aaae
Packit 96aaae
	g_clear_object (&class->extension_registry);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
mail_parser_set_session (EMailParser *parser,
Packit 96aaae
                         CamelSession *session)
Packit 96aaae
{
Packit 96aaae
	g_return_if_fail (CAMEL_IS_SESSION (session));
Packit 96aaae
	g_return_if_fail (parser->priv->session == NULL);
Packit 96aaae
Packit 96aaae
	parser->priv->session = g_object_ref (session);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_set_property (GObject *object,
Packit 96aaae
                          guint property_id,
Packit 96aaae
                          const GValue *value,
Packit 96aaae
                          GParamSpec *pspec)
Packit 96aaae
{
Packit 96aaae
	switch (property_id) {
Packit 96aaae
		case PROP_SESSION:
Packit 96aaae
			mail_parser_set_session (
Packit 96aaae
				E_MAIL_PARSER (object),
Packit 96aaae
				g_value_get_object (value));
Packit 96aaae
			return;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_get_property (GObject *object,
Packit 96aaae
                          guint property_id,
Packit 96aaae
                          GValue *value,
Packit 96aaae
                          GParamSpec *pspec)
Packit 96aaae
{
Packit 96aaae
	switch (property_id) {
Packit 96aaae
		case PROP_SESSION:
Packit 96aaae
			g_value_set_object (
Packit 96aaae
				value,
Packit 96aaae
				e_mail_parser_get_session (
Packit 96aaae
				E_MAIL_PARSER (object)));
Packit 96aaae
			return;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_finalize (GObject *object)
Packit 96aaae
{
Packit 96aaae
	EMailParserPrivate *priv;
Packit 96aaae
Packit 96aaae
	priv = E_MAIL_PARSER_GET_PRIVATE (object);
Packit 96aaae
Packit 96aaae
	g_clear_object (&priv->session);
Packit 96aaae
	g_mutex_clear (&priv->mutex);
Packit 96aaae
Packit 96aaae
	/* Chain up to parent's finalize() method. */
Packit 96aaae
	G_OBJECT_CLASS (parent_class)->finalize (object);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_base_init (EMailParserClass *class)
Packit 96aaae
{
Packit 96aaae
	EShell *shell;
Packit 96aaae
Packit 96aaae
	/* Register internal extensions. */
Packit 96aaae
	g_type_ensure (e_mail_parser_application_mbox_get_type ());
Packit 96aaae
	/* This is currently disabled, because the WebKit player requires javascript,
Packit 96aaae
	   which is disabled in Evolution. */
Packit 96aaae
	/* g_type_ensure (e_mail_parser_audio_get_type ()); */
Packit 96aaae
	g_type_ensure (e_mail_parser_headers_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_message_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_secure_button_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_source_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_image_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_inline_pgp_encrypted_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_inline_pgp_signed_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_message_delivery_status_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_message_external_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_message_rfc822_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_alternative_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_apple_double_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_digest_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_encrypted_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_mixed_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_related_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_multipart_signed_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_text_enriched_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_text_html_get_type ());
Packit 96aaae
	g_type_ensure (e_mail_parser_text_plain_get_type ());
Packit 96aaae
#ifdef ENABLE_SMIME
Packit 96aaae
	g_type_ensure (e_mail_parser_application_smime_get_type ());
Packit 96aaae
#endif
Packit 96aaae
Packit 96aaae
	class->extension_registry = g_object_new (
Packit 96aaae
		E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, NULL);
Packit 96aaae
Packit 96aaae
	e_mail_parser_extension_registry_load (class->extension_registry);
Packit 96aaae
Packit 96aaae
	e_extensible_load_extensions (E_EXTENSIBLE (class->extension_registry));
Packit 96aaae
Packit 96aaae
	shell = e_shell_get_default ();
Packit 96aaae
	g_object_weak_ref (G_OBJECT (shell), shell_gone_cb, class);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_class_init (EMailParserClass *class)
Packit 96aaae
{
Packit 96aaae
	GObjectClass *object_class;
Packit 96aaae
Packit 96aaae
	parent_class = g_type_class_peek_parent (class);
Packit 96aaae
	g_type_class_add_private (class, sizeof (EMailParserPrivate));
Packit 96aaae
Packit 96aaae
	object_class = G_OBJECT_CLASS (class);
Packit 96aaae
	object_class->finalize = e_mail_parser_finalize;
Packit 96aaae
	object_class->set_property = e_mail_parser_set_property;
Packit 96aaae
	object_class->get_property = e_mail_parser_get_property;
Packit 96aaae
Packit 96aaae
	g_object_class_install_property (
Packit 96aaae
		object_class,
Packit 96aaae
		PROP_SESSION,
Packit 96aaae
		g_param_spec_object (
Packit 96aaae
			"session",
Packit 96aaae
			"Camel Session",
Packit 96aaae
			NULL,
Packit 96aaae
			CAMEL_TYPE_SESSION,
Packit 96aaae
			G_PARAM_READWRITE |
Packit 96aaae
			G_PARAM_CONSTRUCT_ONLY));
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
e_mail_parser_init (EMailParser *parser)
Packit 96aaae
{
Packit 96aaae
	parser->priv = E_MAIL_PARSER_GET_PRIVATE (parser);
Packit 96aaae
Packit 96aaae
	g_mutex_init (&parser->priv->mutex);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
GType
Packit 96aaae
e_mail_parser_get_type (void)
Packit 96aaae
{
Packit 96aaae
	static GType type = 0;
Packit 96aaae
Packit 96aaae
	if (G_UNLIKELY (type == 0)) {
Packit 96aaae
		static const GTypeInfo type_info = {
Packit 96aaae
			sizeof (EMailParserClass),
Packit 96aaae
			(GBaseInitFunc) e_mail_parser_base_init,
Packit 96aaae
			(GBaseFinalizeFunc) NULL,
Packit 96aaae
			(GClassInitFunc) e_mail_parser_class_init,
Packit 96aaae
			(GClassFinalizeFunc) NULL,
Packit 96aaae
			NULL,  /* class_data */
Packit 96aaae
			sizeof (EMailParser),
Packit 96aaae
			0,     /* n_preallocs */
Packit 96aaae
			(GInstanceInitFunc) e_mail_parser_init,
Packit 96aaae
			NULL   /* value_table */
Packit 96aaae
		};
Packit 96aaae
Packit 96aaae
		type = g_type_register_static (
Packit 96aaae
			G_TYPE_OBJECT, "EMailParser",
Packit 96aaae
			&type_info, 0);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	return type;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
EMailParser *
Packit 96aaae
e_mail_parser_new (CamelSession *session)
Packit 96aaae
{
Packit 96aaae
	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
Packit 96aaae
Packit 96aaae
	return g_object_new (
Packit 96aaae
		E_TYPE_MAIL_PARSER,
Packit 96aaae
		"session", session, NULL);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
/**
Packit 96aaae
 * e_mail_parser_parse_sync:
Packit 96aaae
 * @parser: an #EMailParser
Packit 96aaae
 * @folder: (allow none) a #CamelFolder containing the @message or %NULL
Packit 96aaae
 * @message_uid: (allow none) UID of the @message within the @folder or %NULL
Packit 96aaae
 * @message: a #CamelMimeMessage
Packit 96aaae
 * @cancellable: (allow-none) a #GCancellable
Packit 96aaae
 *
Packit 96aaae
 * Parses the @message synchronously. Returns a list of #EMailParts which
Packit 96aaae
 * represents structure of the message and additional properties of each part.
Packit 96aaae
 *
Packit 96aaae
 * Note that this function can block for a while, so it's not a good idea to call
Packit 96aaae
 * it from main thread.
Packit 96aaae
 *
Packit 96aaae
 * Return Value: An #EMailPartsList
Packit 96aaae
 */
Packit 96aaae
EMailPartList *
Packit 96aaae
e_mail_parser_parse_sync (EMailParser *parser,
Packit 96aaae
                          CamelFolder *folder,
Packit 96aaae
                          const gchar *message_uid,
Packit 96aaae
                          CamelMimeMessage *message,
Packit 96aaae
                          GCancellable *cancellable)
Packit 96aaae
{
Packit 96aaae
	EMailPartList *part_list;
Packit 96aaae
Packit 96aaae
	g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
Packit 96aaae
	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
Packit 96aaae
Packit 96aaae
	part_list = e_mail_part_list_new (message, message_uid, folder);
Packit 96aaae
Packit 96aaae
	mail_parser_run (parser, part_list, cancellable);
Packit 96aaae
Packit 96aaae
	if (camel_debug_start ("emformat:parser")) {
Packit 96aaae
		GQueue queue = G_QUEUE_INIT;
Packit 96aaae
Packit 96aaae
		printf (
Packit 96aaae
			"%s finished with EMailPartList:\n",
Packit 96aaae
			G_OBJECT_TYPE_NAME (parser));
Packit 96aaae
Packit 96aaae
		e_mail_part_list_queue_parts (part_list, NULL, &queue);
Packit 96aaae
Packit 96aaae
		while (!g_queue_is_empty (&queue)) {
Packit 96aaae
			EMailPart *part;
Packit 96aaae
Packit 96aaae
			part = g_queue_pop_head (&queue);
Packit 96aaae
Packit 96aaae
			printf (
Packit 96aaae
				"	id: %s | cid: %s | mime_type: %s | "
Packit 96aaae
				"is_hidden: %d | is_attachment: %d\n",
Packit 96aaae
				e_mail_part_get_id (part),
Packit 96aaae
				e_mail_part_get_cid (part),
Packit 96aaae
				e_mail_part_get_mime_type (part),
Packit 96aaae
				part->is_hidden ? 1 : 0,
Packit 96aaae
				e_mail_part_get_is_attachment (part) ? 1 : 0);
Packit 96aaae
Packit 96aaae
			g_object_unref (part);
Packit 96aaae
		}
Packit 96aaae
Packit 96aaae
		camel_debug_end ();
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	return part_list;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
mail_parser_parse_thread (GSimpleAsyncResult *simple,
Packit 96aaae
                          GObject *source_object,
Packit 96aaae
                          GCancellable *cancellable)
Packit 96aaae
{
Packit 96aaae
	EMailPartList *part_list;
Packit 96aaae
Packit 96aaae
	part_list = g_simple_async_result_get_op_res_gpointer (simple);
Packit 96aaae
Packit 96aaae
	mail_parser_run (
Packit 96aaae
		E_MAIL_PARSER (source_object),
Packit 96aaae
		part_list, cancellable);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
/**
Packit 96aaae
 * e_mail_parser_parse:
Packit 96aaae
 * @parser: an #EMailParser
Packit 96aaae
 * @message: a #CamelMimeMessage
Packit 96aaae
 * @callback: a #GAsyncReadyCallback
Packit 96aaae
 * @cancellable: (allow-none) a #GCancellable
Packit 96aaae
 * @user_data: (allow-none) user data passed to the callback
Packit 96aaae
 *
Packit 96aaae
 * Asynchronous version of e_mail_parser_parse_sync().
Packit 96aaae
 */
Packit 96aaae
void
Packit 96aaae
e_mail_parser_parse (EMailParser *parser,
Packit 96aaae
                     CamelFolder *folder,
Packit 96aaae
                     const gchar *message_uid,
Packit 96aaae
                     CamelMimeMessage *message,
Packit 96aaae
                     GAsyncReadyCallback callback,
Packit 96aaae
                     GCancellable *cancellable,
Packit 96aaae
                     gpointer user_data)
Packit 96aaae
{
Packit 96aaae
	GSimpleAsyncResult *simple;
Packit 96aaae
	EMailPartList *part_list;
Packit 96aaae
Packit 96aaae
	g_return_if_fail (E_IS_MAIL_PARSER (parser));
Packit 96aaae
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
Packit 96aaae
Packit 96aaae
	part_list = e_mail_part_list_new (message, message_uid, folder);
Packit 96aaae
Packit 96aaae
	simple = g_simple_async_result_new (
Packit 96aaae
		G_OBJECT (parser), callback,
Packit 96aaae
		user_data, e_mail_parser_parse);
Packit 96aaae
Packit 96aaae
	g_simple_async_result_set_check_cancellable (simple, cancellable);
Packit 96aaae
Packit 96aaae
	g_simple_async_result_set_op_res_gpointer (
Packit 96aaae
		simple, part_list, (GDestroyNotify) g_object_unref);
Packit 96aaae
Packit 96aaae
	g_simple_async_result_run_in_thread (
Packit 96aaae
		simple, mail_parser_parse_thread,
Packit 96aaae
		G_PRIORITY_DEFAULT, cancellable);
Packit 96aaae
Packit 96aaae
	g_object_unref (simple);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
EMailPartList *
Packit 96aaae
e_mail_parser_parse_finish (EMailParser *parser,
Packit 96aaae
                            GAsyncResult *result,
Packit 96aaae
                            GError **error)
Packit 96aaae
{
Packit 96aaae
	GSimpleAsyncResult *simple;
Packit 96aaae
	EMailPartList *part_list;
Packit 96aaae
Packit 96aaae
	g_return_val_if_fail (
Packit 96aaae
		g_simple_async_result_is_valid (
Packit 96aaae
		result, G_OBJECT (parser), e_mail_parser_parse), NULL);
Packit 96aaae
Packit 96aaae
	simple = G_SIMPLE_ASYNC_RESULT (result);
Packit 96aaae
	part_list = g_simple_async_result_get_op_res_gpointer (simple);
Packit 96aaae
Packit 96aaae
	if (camel_debug_start ("emformat:parser")) {
Packit 96aaae
		GQueue queue = G_QUEUE_INIT;
Packit 96aaae
Packit 96aaae
		printf (
Packit 96aaae
			"%s finished with EMailPartList:\n",
Packit 96aaae
			G_OBJECT_TYPE_NAME (parser));
Packit 96aaae
Packit 96aaae
		e_mail_part_list_queue_parts (part_list, NULL, &queue);
Packit 96aaae
Packit 96aaae
		while (!g_queue_is_empty (&queue)) {
Packit 96aaae
			EMailPart *part;
Packit 96aaae
Packit 96aaae
			part = g_queue_pop_head (&queue);
Packit 96aaae
Packit 96aaae
			printf (
Packit 96aaae
				"	id: %s | cid: %s | mime_type: %s | "
Packit 96aaae
				"is_hidden: %d | is_attachment: %d\n",
Packit 96aaae
				e_mail_part_get_id (part),
Packit 96aaae
				e_mail_part_get_cid (part),
Packit 96aaae
				e_mail_part_get_mime_type (part),
Packit 96aaae
				part->is_hidden ? 1 : 0,
Packit 96aaae
				e_mail_part_get_is_attachment (part) ? 1 : 0);
Packit 96aaae
Packit 96aaae
			g_object_unref (part);
Packit 96aaae
		}
Packit 96aaae
Packit 96aaae
		camel_debug_end ();
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	return g_object_ref (part_list);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
GQueue *
Packit 96aaae
e_mail_parser_get_parsers_for_part (EMailParser *parser,
Packit 96aaae
				    CamelMimePart *part)
Packit 96aaae
{
Packit 96aaae
	CamelContentType *ct;
Packit 96aaae
	gchar *mime_type;
Packit 96aaae
	GQueue *parsers;
Packit 96aaae
Packit 96aaae
	g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
Packit 96aaae
	g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
Packit 96aaae
Packit 96aaae
	ct = camel_mime_part_get_content_type (part);
Packit 96aaae
	if (!ct) {
Packit 96aaae
		mime_type = (gchar *) "application/vnd.evolution.error";
Packit 96aaae
	} else {
Packit 96aaae
		gchar *tmp;
Packit 96aaae
		tmp = camel_content_type_simple (ct);
Packit 96aaae
		mime_type = g_ascii_strdown (tmp, -1);
Packit 96aaae
		g_free (tmp);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	parsers = e_mail_parser_get_parsers (parser, mime_type);
Packit 96aaae
Packit 96aaae
	if (ct)
Packit 96aaae
		g_free (mime_type);
Packit 96aaae
Packit 96aaae
	return parsers;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
GQueue *
Packit 96aaae
e_mail_parser_get_parsers (EMailParser *parser,
Packit 96aaae
			   const gchar *mime_type)
Packit 96aaae
{
Packit 96aaae
	EMailExtensionRegistry *reg;
Packit 96aaae
	EMailParserClass *parser_class;
Packit 96aaae
	gchar *as_mime_type;
Packit 96aaae
	GQueue *parsers;
Packit 96aaae
Packit 96aaae
	g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
Packit 96aaae
Packit 96aaae
	parser_class = E_MAIL_PARSER_GET_CLASS (parser);
Packit 96aaae
	g_return_val_if_fail (parser_class != NULL, NULL);
Packit 96aaae
Packit 96aaae
	if (mime_type)
Packit 96aaae
		as_mime_type = g_ascii_strdown (mime_type, -1);
Packit 96aaae
	else
Packit 96aaae
		as_mime_type = NULL;
Packit 96aaae
Packit 96aaae
	reg = E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
Packit 96aaae
Packit 96aaae
	parsers = e_mail_extension_registry_get_for_mime_type (reg, as_mime_type);
Packit 96aaae
	if (!parsers)
Packit 96aaae
		parsers = e_mail_extension_registry_get_fallback (reg, as_mime_type);
Packit 96aaae
Packit 96aaae
	g_free (as_mime_type);
Packit 96aaae
Packit 96aaae
	return parsers;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
gboolean
Packit 96aaae
e_mail_parser_parse_part (EMailParser *parser,
Packit 96aaae
                          CamelMimePart *part,
Packit 96aaae
                          GString *part_id,
Packit 96aaae
                          GCancellable *cancellable,
Packit 96aaae
                          GQueue *out_mail_parts)
Packit 96aaae
{
Packit 96aaae
	CamelContentType *ct;
Packit 96aaae
	gchar *mime_type;
Packit 96aaae
	gint handled;
Packit 96aaae
Packit 96aaae
	ct = camel_mime_part_get_content_type (part);
Packit 96aaae
	if (!ct) {
Packit 96aaae
		mime_type = (gchar *) "application/vnd.evolution.error";
Packit 96aaae
	} else {
Packit 96aaae
		gchar *tmp;
Packit 96aaae
		tmp = camel_content_type_simple (ct);
Packit 96aaae
		mime_type = g_ascii_strdown (tmp, -1);
Packit 96aaae
		g_free (tmp);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	handled = e_mail_parser_parse_part_as (
Packit 96aaae
		parser, part, part_id, mime_type,
Packit 96aaae
		cancellable, out_mail_parts);
Packit 96aaae
Packit 96aaae
	if (ct) {
Packit 96aaae
		g_free (mime_type);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	return handled;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
gboolean
Packit 96aaae
e_mail_parser_parse_part_as (EMailParser *parser,
Packit 96aaae
                             CamelMimePart *part,
Packit 96aaae
                             GString *part_id,
Packit 96aaae
                             const gchar *mime_type,
Packit 96aaae
                             GCancellable *cancellable,
Packit 96aaae
                             GQueue *out_mail_parts)
Packit 96aaae
{
Packit 96aaae
	GQueue *parsers;
Packit 96aaae
	GList *iter;
Packit 96aaae
	gboolean mime_part_handled = FALSE;
Packit 96aaae
Packit 96aaae
	parsers = e_mail_parser_get_parsers (parser, mime_type);
Packit 96aaae
Packit 96aaae
	if (parsers == NULL) {
Packit 96aaae
		e_mail_parser_wrap_as_attachment (
Packit 96aaae
			parser, part, part_id, out_mail_parts);
Packit 96aaae
		return TRUE;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	for (iter = parsers->head; iter; iter = iter->next) {
Packit 96aaae
		EMailParserExtension *extension;
Packit 96aaae
Packit 96aaae
		extension = iter->data;
Packit 96aaae
		if (!extension)
Packit 96aaae
			continue;
Packit 96aaae
Packit 96aaae
		mime_part_handled = e_mail_parser_extension_parse (
Packit 96aaae
			extension, parser, part, part_id,
Packit 96aaae
			cancellable, out_mail_parts);
Packit 96aaae
Packit 96aaae
		if (mime_part_handled)
Packit 96aaae
			break;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	return mime_part_handled;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
void
Packit 96aaae
e_mail_parser_error (EMailParser *parser,
Packit 96aaae
                     GQueue *out_mail_parts,
Packit 96aaae
                     const gchar *format,
Packit 96aaae
                     ...)
Packit 96aaae
{
Packit 96aaae
	const gchar *mime_type = "application/vnd.evolution.error";
Packit 96aaae
	EMailPart *mail_part;
Packit 96aaae
	CamelMimePart *part;
Packit 96aaae
	gchar *errmsg;
Packit 96aaae
	gchar *uri;
Packit 96aaae
	va_list ap;
Packit 96aaae
Packit 96aaae
	g_return_if_fail (E_IS_MAIL_PARSER (parser));
Packit 96aaae
	g_return_if_fail (out_mail_parts != NULL);
Packit 96aaae
	g_return_if_fail (format != NULL);
Packit 96aaae
Packit 96aaae
	va_start (ap, format);
Packit 96aaae
	errmsg = g_strdup_vprintf (format, ap);
Packit 96aaae
Packit 96aaae
	part = camel_mime_part_new ();
Packit 96aaae
	camel_mime_part_set_content (
Packit 96aaae
		part, errmsg, strlen (errmsg), mime_type);
Packit 96aaae
	g_free (errmsg);
Packit 96aaae
	va_end (ap);
Packit 96aaae
Packit 96aaae
	g_mutex_lock (&parser->priv->mutex);
Packit 96aaae
	parser->priv->last_error++;
Packit 96aaae
	uri = g_strdup_printf (".error.%d", parser->priv->last_error);
Packit 96aaae
	g_mutex_unlock (&parser->priv->mutex);
Packit 96aaae
Packit 96aaae
	mail_part = e_mail_part_new (part, uri);
Packit 96aaae
	e_mail_part_set_mime_type (mail_part, mime_type);
Packit 96aaae
	mail_part->is_error = TRUE;
Packit 96aaae
Packit 96aaae
	g_free (uri);
Packit 96aaae
	g_object_unref (part);
Packit 96aaae
Packit 96aaae
	g_queue_push_tail (out_mail_parts, mail_part);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
static void
Packit 96aaae
attachment_loaded (EAttachment *attachment,
Packit 96aaae
                   GAsyncResult *res,
Packit 96aaae
                   gpointer user_data)
Packit 96aaae
{
Packit 96aaae
	EShell *shell;
Packit 96aaae
	GtkWindow *window;
Packit 96aaae
Packit 96aaae
	shell = e_shell_get_default ();
Packit 96aaae
	window = e_shell_get_active_window (shell);
Packit 96aaae
Packit 96aaae
	e_attachment_load_handle_error (attachment, res, window);
Packit 96aaae
Packit 96aaae
	g_object_unref (attachment);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
/* Idle callback */
Packit 96aaae
static gboolean
Packit 96aaae
load_attachment_idle (EAttachment *attachment)
Packit 96aaae
{
Packit 96aaae
	e_attachment_load_async (
Packit 96aaae
		attachment,
Packit 96aaae
		(GAsyncReadyCallback) attachment_loaded, NULL);
Packit 96aaae
Packit 96aaae
	return FALSE;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
void
Packit 96aaae
e_mail_parser_wrap_as_attachment (EMailParser *parser,
Packit 96aaae
                                  CamelMimePart *part,
Packit 96aaae
                                  GString *part_id,
Packit 96aaae
                                  GQueue *parts_queue)
Packit 96aaae
{
Packit 96aaae
	EMailPartAttachment *empa;
Packit 96aaae
	EAttachment *attachment;
Packit 96aaae
	EMailPart *first_part;
Packit 96aaae
	const gchar *snoop_mime_type;
Packit 96aaae
	GQueue *extensions;
Packit 96aaae
	CamelContentType *ct;
Packit 96aaae
	gchar *mime_type;
Packit 96aaae
	CamelDataWrapper *dw;
Packit 96aaae
	GByteArray *ba;
Packit 96aaae
	gsize size;
Packit 96aaae
	gint part_id_len;
Packit 96aaae
Packit 96aaae
	ct = camel_mime_part_get_content_type (part);
Packit 96aaae
	extensions = NULL;
Packit 96aaae
	snoop_mime_type = NULL;
Packit 96aaae
	if (ct) {
Packit 96aaae
		EMailExtensionRegistry *reg;
Packit 96aaae
		mime_type = camel_content_type_simple (ct);
Packit 96aaae
Packit 96aaae
		reg = e_mail_parser_get_extension_registry (parser);
Packit 96aaae
		extensions = e_mail_extension_registry_get_for_mime_type (
Packit 96aaae
			reg, mime_type);
Packit 96aaae
Packit 96aaae
		if (camel_content_type_is (ct, "text", "*") ||
Packit 96aaae
		    camel_content_type_is (ct, "message", "*"))
Packit 96aaae
			snoop_mime_type = mime_type;
Packit 96aaae
		else
Packit 96aaae
			g_free (mime_type);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	if (!snoop_mime_type)
Packit 96aaae
		snoop_mime_type = e_mail_part_snoop_type (part);
Packit 96aaae
Packit 96aaae
	if (!extensions) {
Packit 96aaae
		EMailExtensionRegistry *reg;
Packit 96aaae
Packit 96aaae
		reg = e_mail_parser_get_extension_registry (parser);
Packit 96aaae
		extensions = e_mail_extension_registry_get_for_mime_type (
Packit 96aaae
			reg, snoop_mime_type);
Packit 96aaae
Packit 96aaae
		if (!extensions) {
Packit 96aaae
			extensions = e_mail_extension_registry_get_fallback (
Packit 96aaae
				reg, snoop_mime_type);
Packit 96aaae
		}
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	part_id_len = part_id->len;
Packit 96aaae
	g_string_append (part_id, ".attachment");
Packit 96aaae
Packit 96aaae
	empa = e_mail_part_attachment_new (part, part_id->str);
Packit 96aaae
	empa->shown = extensions && (!g_queue_is_empty (extensions) &&
Packit 96aaae
		e_mail_part_is_inline (part, extensions));
Packit 96aaae
	empa->snoop_mime_type = snoop_mime_type;
Packit 96aaae
Packit 96aaae
	first_part = g_queue_peek_head (parts_queue);
Packit 96aaae
	if (first_part != NULL && !E_IS_MAIL_PART_ATTACHMENT (first_part)) {
Packit 96aaae
		const gchar *id = e_mail_part_get_id (first_part);
Packit 96aaae
		empa->part_id_with_attachment = g_strdup (id);
Packit 96aaae
		first_part->is_hidden = TRUE;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	attachment = e_mail_part_attachment_ref_attachment (empa);
Packit 96aaae
Packit 96aaae
	e_attachment_set_initially_shown (attachment, empa->shown);
Packit 96aaae
	e_attachment_set_can_show (
Packit 96aaae
		attachment,
Packit 96aaae
		extensions && !g_queue_is_empty (extensions));
Packit 96aaae
Packit 96aaae
	/* Try to guess size of the attachments */
Packit 96aaae
	dw = camel_medium_get_content (CAMEL_MEDIUM (part));
Packit 96aaae
	ba = camel_data_wrapper_get_byte_array (dw);
Packit 96aaae
	if (ba) {
Packit 96aaae
		size = ba->len;
Packit 96aaae
Packit 96aaae
		if (camel_mime_part_get_encoding (part) == CAMEL_TRANSFER_ENCODING_BASE64)
Packit 96aaae
			size = size / 1.37;
Packit 96aaae
	} else {
Packit 96aaae
		size = 0;
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	/* e_attachment_load_async must be called from main thread */
Packit 96aaae
	/* Prioritize ahead of GTK+ redraws. */
Packit 96aaae
	g_idle_add_full (
Packit 96aaae
		G_PRIORITY_HIGH_IDLE,
Packit 96aaae
		(GSourceFunc) load_attachment_idle,
Packit 96aaae
		g_object_ref (attachment),
Packit 96aaae
		NULL);
Packit 96aaae
Packit 96aaae
	if (size != 0) {
Packit 96aaae
		GFileInfo *file_info;
Packit 96aaae
Packit 96aaae
		file_info = e_attachment_ref_file_info (attachment);
Packit 96aaae
Packit 96aaae
		if (file_info == NULL) {
Packit 96aaae
			file_info = g_file_info_new ();
Packit 96aaae
			g_file_info_set_content_type (
Packit 96aaae
				file_info, empa->snoop_mime_type);
Packit 96aaae
		}
Packit 96aaae
Packit 96aaae
		g_file_info_set_size (file_info, size);
Packit 96aaae
		e_attachment_set_file_info (attachment, file_info);
Packit 96aaae
Packit 96aaae
		g_object_unref (file_info);
Packit 96aaae
	}
Packit 96aaae
Packit 96aaae
	g_object_unref (attachment);
Packit 96aaae
Packit 96aaae
	g_string_truncate (part_id, part_id_len);
Packit 96aaae
Packit 96aaae
	/* Push to head, not tail. */
Packit 96aaae
	g_queue_push_head (parts_queue, empa);
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
CamelSession *
Packit 96aaae
e_mail_parser_get_session (EMailParser *parser)
Packit 96aaae
{
Packit 96aaae
	g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
Packit 96aaae
Packit 96aaae
	return parser->priv->session;
Packit 96aaae
}
Packit 96aaae
Packit 96aaae
EMailExtensionRegistry *
Packit 96aaae
e_mail_parser_get_extension_registry (EMailParser *parser)
Packit 96aaae
{
Packit 96aaae
	EMailParserClass *parser_class;
Packit 96aaae
Packit 96aaae
	g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
Packit 96aaae
Packit 96aaae
	parser_class = E_MAIL_PARSER_GET_CLASS (parser);
Packit 96aaae
	g_return_val_if_fail (parser_class != NULL, NULL);
Packit 96aaae
Packit 96aaae
	return E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
Packit 96aaae
}