aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2012-06-06 21:27:19 +0800
committerDan Vrátil <dvratil@redhat.com>2012-06-06 21:27:19 +0800
commit5b8340563c271fb684a88c6e5bb6dd3bfb629058 (patch)
treec1c7d606fb4ce9fd2fe459a9226bfb9125423991
parent26a4f24188fd89dbabaff192bec9c54af8fe5a80 (diff)
downloadgsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar.gz
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar.bz2
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar.lz
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar.xz
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.tar.zst
gsoc2013-evolution-5b8340563c271fb684a88c6e5bb6dd3bfb629058.zip
Mail formatter rewrite
All mail-parsing and formatting code has been moved to em-format. Parsing is handeled by EMailParser class, formatting by EMailFormatter. Both classes have registry which hold extensions - simple classes that do actual parsing and formatting. Each supported mime-type has it's own parser and formatter extension class.
-rw-r--r--composer/e-msg-composer.c63
-rw-r--r--data/webview.css2
-rw-r--r--em-format/Makefile.am105
-rw-r--r--em-format/e-mail-extension-registry.c294
-rw-r--r--em-format/e-mail-extension-registry.h156
-rw-r--r--em-format/e-mail-extension.c67
-rw-r--r--em-format/e-mail-extension.h60
-rw-r--r--em-format/e-mail-format-extensions.c124
-rw-r--r--em-format/e-mail-format-extensions.h88
-rw-r--r--em-format/e-mail-formatter-attachment-bar.c154
-rw-r--r--em-format/e-mail-formatter-attachment.c403
-rw-r--r--em-format/e-mail-formatter-error.c160
-rw-r--r--em-format/e-mail-formatter-extension.c189
-rw-r--r--em-format/e-mail-formatter-extension.h106
-rw-r--r--em-format/e-mail-formatter-headers.c615
-rw-r--r--em-format/e-mail-formatter-image.c191
-rw-r--r--em-format/e-mail-formatter-message-rfc822.c276
-rw-r--r--em-format/e-mail-formatter-print-headers.c258
-rw-r--r--em-format/e-mail-formatter-print.c266
-rw-r--r--em-format/e-mail-formatter-print.h63
-rw-r--r--em-format/e-mail-formatter-quote-attachment.c163
-rw-r--r--em-format/e-mail-formatter-quote-headers.c162
-rw-r--r--em-format/e-mail-formatter-quote-message-rfc822.c188
-rw-r--r--em-format/e-mail-formatter-quote-text-enriched.c141
-rw-r--r--em-format/e-mail-formatter-quote-text-html.c143
-rw-r--r--em-format/e-mail-formatter-quote-text-plain.c162
-rw-r--r--em-format/e-mail-formatter-quote.c224
-rw-r--r--em-format/e-mail-formatter-quote.h79
-rw-r--r--em-format/e-mail-formatter-secure-button.c472
-rw-r--r--em-format/e-mail-formatter-source.c178
-rw-r--r--em-format/e-mail-formatter-text-enriched.c154
-rw-r--r--em-format/e-mail-formatter-text-html.c376
-rw-r--r--em-format/e-mail-formatter-text-plain.c212
-rw-r--r--em-format/e-mail-formatter-utils.c434
-rw-r--r--em-format/e-mail-formatter-utils.h56
-rw-r--r--em-format/e-mail-formatter.c1510
-rw-r--r--em-format/e-mail-formatter.h266
-rw-r--r--em-format/e-mail-inline-filter.c (renamed from em-format/em-inline-filter.c)37
-rw-r--r--em-format/e-mail-inline-filter.h (renamed from em-format/em-inline-filter.h)48
-rw-r--r--em-format/e-mail-parser-application-mbox.c213
-rw-r--r--em-format/e-mail-parser-application-smime.c199
-rw-r--r--em-format/e-mail-parser-attachment-bar.c120
-rw-r--r--em-format/e-mail-parser-extension.c101
-rw-r--r--em-format/e-mail-parser-extension.h86
-rw-r--r--em-format/e-mail-parser-headers.c112
-rw-r--r--em-format/e-mail-parser-image.c147
-rw-r--r--em-format/e-mail-parser-inlinepgp-encrypted.c205
-rw-r--r--em-format/e-mail-parser-inlinepgp-signed.c230
-rw-r--r--em-format/e-mail-parser-message-deliverystatus.c116
-rw-r--r--em-format/e-mail-parser-message-external.c211
-rw-r--r--em-format/e-mail-parser-message-rfc822.c174
-rw-r--r--em-format/e-mail-parser-message.c129
-rw-r--r--em-format/e-mail-parser-multipart-alternative.c191
-rw-r--r--em-format/e-mail-parser-multipart-appledouble.c130
-rw-r--r--em-format/e-mail-parser-multipart-digest.c175
-rw-r--r--em-format/e-mail-parser-multipart-encrypted.c220
-rw-r--r--em-format/e-mail-parser-multipart-mixed.c158
-rw-r--r--em-format/e-mail-parser-multipart-related.c162
-rw-r--r--em-format/e-mail-parser-multipart-signed.c252
-rw-r--r--em-format/e-mail-parser-secure-button.c104
-rw-r--r--em-format/e-mail-parser-source.c108
-rw-r--r--em-format/e-mail-parser-text-enriched.c128
-rw-r--r--em-format/e-mail-parser-text-html.c138
-rw-r--r--em-format/e-mail-parser-text-plain.c253
-rw-r--r--em-format/e-mail-parser.c693
-rw-r--r--em-format/e-mail-parser.h114
-rw-r--r--em-format/e-mail-part-attachment-bar.h34
-rw-r--r--em-format/e-mail-part-attachment.c30
-rw-r--r--em-format/e-mail-part-attachment.h45
-rw-r--r--em-format/e-mail-part-list.c130
-rw-r--r--em-format/e-mail-part-list.h76
-rw-r--r--em-format/e-mail-part-utils.c546
-rw-r--r--em-format/e-mail-part-utils.h58
-rw-r--r--em-format/e-mail-part.c196
-rw-r--r--em-format/e-mail-part.h98
-rw-r--r--em-format/e-mail-stripsig-filter.c (renamed from em-format/em-stripsig-filter.c)18
-rw-r--r--em-format/e-mail-stripsig-filter.h (renamed from em-format/em-stripsig-filter.h)42
-rw-r--r--em-format/em-format-quote.c844
-rw-r--r--em-format/em-format-quote.h79
-rw-r--r--em-format/em-format.c2676
-rw-r--r--em-format/em-format.h333
-rw-r--r--mail/Makefile.am10
-rw-r--r--mail/e-http-request.c67
-rw-r--r--mail/e-mail-attachment-bar.h79
-rw-r--r--mail/e-mail-browser.c7
-rw-r--r--mail/e-mail-browser.h2
-rw-r--r--mail/e-mail-config-lookup-page.c2
-rw-r--r--mail/e-mail-display.c779
-rw-r--r--mail/e-mail-display.h16
-rw-r--r--mail/e-mail-folder-pane.c1
-rw-r--r--mail/e-mail-paned-view.h2
-rw-r--r--mail/e-mail-printer.c160
-rw-r--r--mail/e-mail-printer.h8
-rw-r--r--mail/e-mail-reader-utils.c351
-rw-r--r--mail/e-mail-reader-utils.h17
-rw-r--r--mail/e-mail-reader.c217
-rw-r--r--mail/e-mail-reader.h4
-rw-r--r--mail/e-mail-request.c110
-rw-r--r--mail/em-composer-utils.c57
-rw-r--r--mail/em-composer-utils.h6
-rw-r--r--mail/em-format-hook.c286
-rw-r--r--mail/em-format-hook.h90
-rw-r--r--mail/em-format-html-display.c1080
-rw-r--r--mail/em-format-html-display.h117
-rw-r--r--mail/em-format-html-print.c634
-rw-r--r--mail/em-format-html-print.h66
-rw-r--r--mail/em-format-html.c3011
-rw-r--r--mail/em-format-html.h223
-rw-r--r--mail/em-utils.c75
-rw-r--r--mail/em-utils.h4
-rw-r--r--modules/mail/e-mail-config-format-html.c4
-rw-r--r--modules/mail/e-mail-shell-backend.c73
-rw-r--r--modules/mail/e-mail-shell-content.h1
-rw-r--r--modules/mail/e-mail-shell-view-actions.c2
-rw-r--r--modules/mail/em-mailer-prefs.c1
-rw-r--r--widgets/misc/Makefile.am2
-rw-r--r--widgets/misc/e-attachment-bar.c (renamed from mail/e-mail-attachment-bar.c)224
-rw-r--r--widgets/misc/e-attachment-bar.h79
-rw-r--r--widgets/misc/e-attachment-button.c3
119 files changed, 16050 insertions, 10539 deletions
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index ae5048208e..90ce610eb9 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -40,11 +40,15 @@
#include <libevolution-utils/e-alert-dialog.h>
#include <e-util/e-dialog-utils.h>
#include <e-util/e-util-private.h>
-#include <em-format/em-format.h>
-#include <em-format/em-format-quote.h>
#include "e-composer-private.h"
+#include <em-format/e-mail-part.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-formatter-quote.h>
+
+#include <shell/e-shell.h>
+
typedef struct _AsyncContext AsyncContext;
struct _AsyncContext {
@@ -179,49 +183,50 @@ static gchar *
emcu_part_to_html (CamelSession *session,
CamelMimePart *part,
gssize *len,
- EMFormat *source,
GCancellable *cancellable)
{
- EMFormatQuote *emfq;
CamelStreamMem *mem;
GByteArray *buf;
gchar *text;
- EMFormatParserInfo p_info = { 0 };
- EMFormatWriterInfo w_info = { 0 };
+ EMailParser *parser;
+ EMailFormatter *formatter;
+ EMailPartList *part_list;
GString *part_id;
+ EShell *shell;
+ GtkWindow *window;
+
+ shell = e_shell_get_default ();
+ window = e_shell_get_active_window (shell);
buf = g_byte_array_new ();
mem = (CamelStreamMem *) camel_stream_mem_new ();
camel_stream_mem_set_byte_array (mem, buf);
- emfq = em_format_quote_new (
- session, NULL, (CamelStream *) mem,
- EM_FORMAT_QUOTE_KEEP_SIG);
- em_format_set_composer ((EMFormat *) emfq, TRUE);
- if (source) {
- /* Copy over things we can, other things are internal.
- * XXX Perhaps need different api than 'clone'. */
- if (em_format_get_default_charset (source))
- em_format_set_default_charset (
- (EMFormat *) emfq, em_format_get_default_charset (source));
- if (em_format_get_charset (source))
- em_format_set_charset (
- (EMFormat *) emfq, em_format_get_charset (source));
- }
+ part_list = e_mail_part_list_new ();
part_id = g_string_sized_new (0);
- em_format_parse_part (EM_FORMAT (emfq), part, part_id, &p_info, cancellable);
- em_format_write (EM_FORMAT (emfq), CAMEL_STREAM (mem), &w_info, cancellable);
+ parser = e_mail_parser_new (session);
+ part_list->list = e_mail_parser_parse_part (parser, part, part_id, cancellable);
g_string_free (part_id, TRUE);
+ g_object_unref (parser);
+
+ formatter = e_mail_formatter_quote_new (NULL, E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG);
+ e_mail_formatter_set_style (formatter,
+ gtk_widget_get_style (GTK_WIDGET (window)),
+ gtk_widget_get_state (GTK_WIDGET (window)));
- g_object_unref (emfq);
+ e_mail_formatter_format_sync (
+ formatter, part_list, (CamelStream *) mem,
+ 0, E_MAIL_FORMATTER_MODE_PRINTING, cancellable);
+ g_object_unref (formatter);
+ g_object_unref (part_list);
camel_stream_write((CamelStream *) mem, "", 1, cancellable, NULL);
g_object_unref (mem);
text = (gchar *) buf->data;
if (len)
- *len = buf->len-1;
+ *len = buf->len - 1;
g_byte_array_free (buf, FALSE);
return text;
@@ -2711,7 +2716,7 @@ handle_multipart_signed (EMsgComposer *composer,
gssize length;
html = emcu_part_to_html (
- session, mime_part, &length, NULL, cancellable);
+ session, mime_part, &length, cancellable);
e_msg_composer_set_pending_body (composer, html, length);
} else {
e_msg_composer_attach (composer, mime_part);
@@ -2799,7 +2804,7 @@ handle_multipart_encrypted (EMsgComposer *composer,
gssize length;
html = emcu_part_to_html (
- session, mime_part, &length, NULL, cancellable);
+ session, mime_part, &length, cancellable);
e_msg_composer_set_pending_body (composer, html, length);
} else {
e_msg_composer_attach (composer, mime_part);
@@ -2880,7 +2885,7 @@ handle_multipart_alternative (EMsgComposer *composer,
gssize length;
html = emcu_part_to_html (
- session, text_part, &length, NULL, cancellable);
+ session, text_part, &length, cancellable);
e_msg_composer_set_pending_body (composer, html, length);
}
}
@@ -2948,7 +2953,7 @@ handle_multipart (EMsgComposer *composer,
/* Since the first part is not multipart/alternative,
* this must be the body. */
html = emcu_part_to_html (
- session, mime_part, &length, NULL, cancellable);
+ session, mime_part, &length, cancellable);
e_msg_composer_set_pending_body (composer, html, length);
} else if (camel_mime_part_get_content_id (mime_part) ||
camel_mime_part_get_content_location (mime_part)) {
@@ -3325,7 +3330,7 @@ e_msg_composer_new_with_message (EShell *shell,
html = emcu_part_to_html (
session, CAMEL_MIME_PART (message),
- &length, NULL, cancellable);
+ &length, cancellable);
e_msg_composer_set_pending_body (composer, html, length);
}
diff --git a/data/webview.css b/data/webview.css
index 5b0e7348c3..09f94043fb 100644
--- a/data/webview.css
+++ b/data/webview.css
@@ -58,13 +58,13 @@ img.navigable {
}
.part-container {
- width: 100%;
height: 100%;
background: #FFF;
margin-top: 2px;
margin-bottom: 3px;
border-width: 1px;
border-style: solid;
+ right: 0;
}
.part-container-inner-margin {
diff --git a/em-format/Makefile.am b/em-format/Makefile.am
index 392a195044..6b42ec1262 100644
--- a/em-format/Makefile.am
+++ b/em-format/Makefile.am
@@ -3,33 +3,118 @@ emformatincludedir = $(privincludedir)/em-format
privsolib_LTLIBRARIES = libemformat.la
emformatinclude_HEADERS = \
- em-format.h \
- em-format-quote.h \
- em-inline-filter.h \
- em-stripsig-filter.h
+ e-mail-extension-registry.h \
+ e-mail-extension.h \
+ e-mail-formatter-extension.h \
+ e-mail-formatter.h \
+ e-mail-formatter-print.h \
+ e-mail-formatter-quote.h \
+ e-mail-formatter-utils.h \
+ e-mail-inline-filter.h \
+ e-mail-parser-extension.h \
+ e-mail-parser.h \
+ e-mail-part.h \
+ e-mail-part-attachment.h \
+ e-mail-part-attachment-bar.h \
+ e-mail-part-list.h \
+ e-mail-part-utils.h \
+ e-mail-stripsig-filter.h
libemformat_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(top_srcdir) \
+ -I$(top_srcdir)/em-format \
+ -I$(top_srcdir)/smime/lib \
+ -I$(top_srcdir)/smime/gui \
-I$(top_srcdir)/widgets \
$(EVOLUTION_DATA_SERVER_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
- $(LIBSOUP_CFLAGS)
+ $(LIBSOUP_CFLAGS) \
+ -DEVOLUTION_IMAGESDIR=\""$(imagesdir)"\" \
+ -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\"
+
+if ENABLE_SMIME
+SMIME_EXTENSIONS = e-mail-parser-application-smime.c
+endif
libemformat_la_SOURCES = \
$(emformatinclude_HEADERS) \
- em-format.c \
- em-format-quote.c \
- em-inline-filter.c \
- em-stripsig-filter.c
+ $(emformatextensions_SOURCES) \
+ e-mail-extension-registry.c \
+ e-mail-extension.c \
+ e-mail-inline-filter.c \
+ e-mail-format-extensions.c \
+ e-mail-formatter.c \
+ e-mail-formatter-print.c \
+ e-mail-formatter-quote.c \
+ e-mail-formatter-utils.c \
+ e-mail-formatter-attachment.c \
+ e-mail-formatter-attachment-bar.c \
+ e-mail-formatter-error.c \
+ e-mail-formatter-extension.c \
+ e-mail-formatter-headers.c \
+ e-mail-formatter-image.c \
+ e-mail-formatter-message-rfc822.c \
+ e-mail-formatter-secure-button.c \
+ e-mail-formatter-source.c \
+ e-mail-formatter-text-enriched.c \
+ e-mail-formatter-text-html.c \
+ e-mail-formatter-text-plain.c \
+ e-mail-formatter-print-headers.c \
+ e-mail-formatter-quote-attachment.c \
+ e-mail-formatter-quote-headers.c \
+ e-mail-formatter-quote-message-rfc822.c \
+ e-mail-formatter-quote-text-enriched.c \
+ e-mail-formatter-quote-text-html.c \
+ e-mail-formatter-quote-text-plain.c \
+ e-mail-parser-extension.c \
+ e-mail-parser.c \
+ e-mail-parser-application-mbox.c \
+ e-mail-parser-attachment-bar.c \
+ e-mail-parser-headers.c \
+ e-mail-parser-image.c \
+ e-mail-parser-inlinepgp-encrypted.c \
+ e-mail-parser-inlinepgp-signed.c \
+ e-mail-parser-message.c \
+ e-mail-parser-message-deliverystatus.c \
+ e-mail-parser-message-external.c \
+ e-mail-parser-message-rfc822.c \
+ e-mail-parser-multipart-alternative.c \
+ e-mail-parser-multipart-appledouble.c \
+ e-mail-parser-multipart-digest.c \
+ e-mail-parser-multipart-encrypted.c \
+ e-mail-parser-multipart-mixed.c \
+ e-mail-parser-multipart-related.c \
+ e-mail-parser-multipart-signed.c \
+ e-mail-parser-secure-button.c \
+ e-mail-parser-source.c \
+ e-mail-parser-text-enriched.c \
+ e-mail-parser-text-html.c \
+ e-mail-parser-text-plain.c \
+ e-mail-part.c \
+ e-mail-part-attachment.c \
+ e-mail-part-list.c \
+ e-mail-part-utils.c \
+ e-mail-stripsig-filter.c \
+ $(SMIME_EXTENSIONS)
libemformat_la_LDFLAGS = -avoid-version $(NO_UNDEFINED)
+
+if ENABLE_SMIME
+SMIME_LIBS = \
+ $(top_builddir)/smime/lib/libessmime.la \
+ $(top_builddir)/smime/gui/libevolution-smime.la
+endif
+
libemformat_la_LIBADD = \
$(top_builddir)/e-util/libeutil.la \
$(top_builddir)/shell/libeshell.la \
+ $(top_builddir)/libemail-utils/libemail-utils.la \
+ $(top_builddir)/libemail-engine/libemail-engine.la \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS) \
- $(LIBSOUP_LIBS)
+ $(LIBSOUP_LIBS) \
+ $(SMIME_LIBS)
-include $(top_srcdir)/git.mk
diff --git a/em-format/e-mail-extension-registry.c b/em-format/e-mail-extension-registry.c
new file mode 100644
index 0000000000..ef08761300
--- /dev/null
+++ b/em-format/e-mail-extension-registry.c
@@ -0,0 +1,294 @@
+/*
+ * e-mail-extension-registry.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <glib-object.h>
+
+#include "e-mail-extension-registry.h"
+#include "e-mail-extension.h"
+#include "e-mail-format-extensions.h"
+#include <libebackend/libebackend.h>
+#include <camel/camel.h>
+
+#include <glib-object.h>
+
+#include <string.h>
+
+#define E_MAIL_EXTENSION_REGISTRY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_EXTENSION_REGISTRY, EMailExtensionRegistryPrivate))
+
+struct _EMailExtensionRegistryPrivate {
+ GHashTable *table;
+};
+
+static gconstpointer parent_class = 0;
+
+G_DEFINE_ABSTRACT_TYPE (
+ EMailExtensionRegistry,
+ e_mail_extension_registry,
+ G_TYPE_OBJECT)
+
+/**
+ * EMailExtensionRegistry:
+ *
+ * The #EMailExtensionRegistry is an abstract class representing a registry
+ * for #EMailExtension<!-//>s.
+ *
+ * #EMailParser and #EMailFormatter both have internally a registry object
+ * based on the #EMailExtensionRegistry.
+ *
+ * One extension can registry itself for more mime-types.
+ */
+
+static void
+mail_extension_registry_finalize (GObject *object)
+{
+ EMailExtensionRegistry *reg = E_MAIL_EXTENSION_REGISTRY (object);
+
+ if (reg->priv->table) {
+ g_hash_table_destroy (reg->priv->table);
+ reg->priv->table = NULL;
+ }
+
+ /* Chain up to parent's finalize() */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+void
+e_mail_extension_registry_class_init (EMailExtensionRegistryClass *klass)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (klass, sizeof (EMailExtensionRegistryPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = mail_extension_registry_finalize;
+}
+
+static void
+destroy_queue (GQueue *queue)
+{
+ g_queue_free_full (queue, g_object_unref);
+}
+
+void
+e_mail_extension_registry_init (EMailExtensionRegistry *reg)
+{
+ reg->priv = E_MAIL_EXTENSION_REGISTRY_GET_PRIVATE (reg);
+
+ reg->priv->table = g_hash_table_new_full (
+ g_str_hash, g_str_equal, NULL, (GDestroyNotify) destroy_queue);
+}
+
+/**
+ * e_mail_extension_registry_add_extension:
+ * @reg: An #EMailExtensionRegistry
+ * @extension: An #EMailExtension
+ *
+ * Registrys the @extension as a handler for all mime-types that it is able
+ * to handle.
+ */
+void
+e_mail_extension_registry_add_extension (EMailExtensionRegistry *reg,
+ EMailExtension *extension)
+{
+ gint i;
+ const gchar **types;
+
+ g_return_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (reg));
+ g_return_if_fail (E_IS_MAIL_EXTENSION (extension));
+
+ /* One reference per extension is enough */
+ g_object_ref (extension);
+
+ types = e_mail_extension_get_mime_types (extension);
+ for (i = 0; types && types[i]; i++) {
+ GQueue *queue;
+
+ queue = g_hash_table_lookup (reg->priv->table, types[i]);
+ if (!queue) {
+ queue = g_queue_new ();
+ g_queue_push_head (queue, extension);
+ g_hash_table_insert (reg->priv->table, (gchar *) types[i], queue);
+ } else {
+ g_queue_push_head (queue, extension);
+ }
+
+ if (camel_debug ("emformat:registry")) {
+ printf("Added extension '%s' for type '%s'\n",
+ G_OBJECT_TYPE_NAME (extension), types[i]);
+ }
+ }
+}
+
+/**
+ * e_mail_extension_registry_remove_extension:
+ * @reg: An #EMailExtensionRegistry
+ * @extension: An #EMailExtension
+ *
+ * Removes @extension from the registry.
+ */
+void
+e_mail_extension_registry_remove_extension (EMailExtensionRegistry *reg,
+ EMailExtension *extension)
+{
+ gint i;
+ const gchar **types;
+
+ g_return_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (reg));
+ g_return_if_fail (E_IS_MAIL_EXTENSION (extension));
+
+ types = e_mail_extension_get_mime_types (extension);
+ for (i = 0; types && types[i]; i++) {
+ GQueue *queue;
+
+ queue = g_hash_table_lookup (reg->priv->table, types[i]);
+ if (!queue) {
+ i++;
+ continue;
+ }
+
+ g_queue_remove (queue, extension);
+
+ if (camel_debug ("emformat:registry")) {
+ printf("Removed extension '%s' from type '%s'\n",
+ G_OBJECT_TYPE_NAME (extension), types[i]);
+ }
+ }
+
+ g_object_unref (extension);
+}
+
+/**
+ * e_mail_extension_registry_get_for_mime_type:
+ * @reg: An #EMailExtensionRegistry
+ * @mime_type: A string with mime-type to look up
+ *
+ * Tries to lookup list of #EMailExtension<!-//>s that has registryed themselves
+ * as handlers for the @mime_type.
+ *
+ * Return value: Returns #GQueue of #EMailExtension<!-//>s or %NULL when there
+ * are no extension registryed for given @mime_type.
+ */
+GQueue *
+e_mail_extension_registry_get_for_mime_type (EMailExtensionRegistry *reg,
+ const gchar *mime_type)
+{
+ g_return_val_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (reg), NULL);
+ g_return_val_if_fail (mime_type && *mime_type, NULL);
+
+ return g_hash_table_lookup (reg->priv->table, mime_type);
+}
+
+/**
+ * e_mail_extension_registry_get_fallback:
+ * @reg: An #EMailExtensionRegistry
+ * @mime_type: A string with mime-type whose fallback to look up
+ *
+ * Tries to lookup fallback parsers for given mime type. For instance, for
+ * multipart/alternative, it will try to lookup multipart/ * parser.
+ *
+ * Return Value: Returns #QGueue of #EMailExtension<!-//>>s or %NULL when there
+ * are no extensions registryed for the fallback type.
+ */
+GQueue *
+e_mail_extension_registry_get_fallback (EMailExtensionRegistry *reg,
+ const gchar *mime_type)
+{
+ gchar *s, *type;
+ gsize len;
+ GQueue *parsers;
+
+ g_return_val_if_fail (E_IS_MAIL_EXTENSION_REGISTRY (reg), NULL);
+ g_return_val_if_fail (mime_type && *mime_type, NULL);
+
+ s = strchr (mime_type, '/');
+ len = s - mime_type;
+
+ s = g_alloca (len);
+ strncpy (s, mime_type, len);
+ type = g_ascii_strdown (s, len);
+ s = g_strdup_printf ("%s/*", type);
+
+ parsers = g_hash_table_lookup (reg->priv->table, s);
+
+ g_free (type);
+ g_free (s);
+
+ return parsers;
+}
+
+/******************************************************************************/
+
+static void e_mail_parser_extension_registry_extensible_interface_init (EExtensibleInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (
+ EMailParserExtensionRegistry,
+ e_mail_parser_extension_registry,
+ E_TYPE_MAIL_EXTENSION_REGISTRY,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_EXTENSIBLE,
+ e_mail_parser_extension_registry_extensible_interface_init));
+
+static void
+e_mail_parser_extension_registry_init (EMailParserExtensionRegistry *parser_ereg)
+{
+
+}
+
+static void
+e_mail_parser_extension_registry_class_init (EMailParserExtensionRegistryClass *klass)
+{
+ e_mail_parser_extension_registry_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_extension_registry_extensible_interface_init (EExtensibleInterface *interface)
+{
+
+}
+
+/******************************************************************************/
+
+static void e_mail_formatter_extension_registry_extensible_interface_init (EExtensibleInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (
+ EMailFormatterExtensionRegistry,
+ e_mail_formatter_extension_registry,
+ E_TYPE_MAIL_EXTENSION_REGISTRY,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_EXTENSIBLE,
+ e_mail_formatter_extension_registry_extensible_interface_init));
+
+static void
+e_mail_formatter_extension_registry_init (EMailFormatterExtensionRegistry *formatter_ereg)
+{
+
+}
+
+static void
+e_mail_formatter_extension_registry_class_init (EMailFormatterExtensionRegistryClass *klass)
+{
+ e_mail_formatter_extension_registry_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_extension_registry_extensible_interface_init (EExtensibleInterface *interface)
+{
+
+}
diff --git a/em-format/e-mail-extension-registry.h b/em-format/e-mail-extension-registry.h
new file mode 100644
index 0000000000..a6ddb441e0
--- /dev/null
+++ b/em-format/e-mail-extension-registry.h
@@ -0,0 +1,156 @@
+/*
+ * e-mail-extension-registry.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_EXTENSION_REGISTRY_H_
+#define E_MAIL_EXTENSION_REGISTRY_H_
+
+#include <em-format/e-mail-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_EXTENSION_REGISTRY \
+ (e_mail_extension_registry_get_type ())
+#define E_MAIL_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_EXTENSION_REGISTRY, EMailExtensionRegistry))
+#define E_MAIL_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_EXTENSION_REGISTRY, EMailExtensionRegistryClass))
+#define E_IS_MAIL_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_EXTENSION_REGISTRY))
+#define E_IS_MAIL_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_EXTENSION_REGISTRY))
+#define E_MAIL_EXTENSION_REGISTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_EXTENSION_REGISTRY, EMailExtensionRegistryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailExtensionRegistry EMailExtensionRegistry;
+typedef struct _EMailExtensionRegistryClass EMailExtensionRegistryClass;
+typedef struct _EMailExtensionRegistryPrivate EMailExtensionRegistryPrivate;
+
+struct _EMailExtensionRegistryClass {
+ GObjectClass parent_class;
+};
+
+struct _EMailExtensionRegistry {
+ GObject parent;
+ EMailExtensionRegistryPrivate *priv;
+};
+
+GType e_mail_extension_registry_get_type (void);
+
+void e_mail_extension_registry_add_extension (EMailExtensionRegistry *reg,
+ EMailExtension *extension);
+
+void e_mail_extension_registry_remove_extension
+ (EMailExtensionRegistry *reg,
+ EMailExtension *extension);
+
+GQueue * e_mail_extension_registry_get_for_mime_type
+ (EMailExtensionRegistry *reg,
+ const gchar *mime_type);
+
+GQueue * e_mail_extension_registry_get_fallback (EMailExtensionRegistry *reg,
+ const gchar *mime_type);
+
+G_END_DECLS
+
+/******************************************************************************/
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY \
+ (e_mail_parser_extension_registry_get_type ())
+#define E_MAIL_PARSER_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, EMailParserExtensionRegistry))
+#define E_MAIL_PARSER_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, EMailParserExtensionRegistryClass))
+#define E_IS_MAIL_PARSER_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY))
+#define E_IS_MAIL_PARSER_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY))
+#define E_MAIL_PARSER_EXTENSION_REGISTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, EMailParserExtensionRegistryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailParserExtensionRegistry EMailParserExtensionRegistry;
+typedef struct _EMailParserExtensionRegistryClass EMailParserExtensionRegistryClass;
+typedef struct _EMailParserExtensionRegistryPrivate EMailParserExtensionRegistryPrivate;
+
+struct _EMailParserExtensionRegistryClass {
+ EMailExtensionRegistryClass parent_class;
+};
+
+struct _EMailParserExtensionRegistry {
+ EMailExtensionRegistry parent;
+ EMailParserExtensionRegistryPrivate *priv;
+};
+
+GType e_mail_parser_extension_registry_get_type (void);
+
+G_END_DECLS
+
+/******************************************************************************/
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY \
+ (e_mail_formatter_extension_registry_get_type ())
+#define E_MAIL_FORMATTER_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY, EMailFormatterExtensionRegistry))
+#define E_MAIL_FORMATTER_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY, EMailFormatterExtensionRegistryClass))
+#define E_IS_MAIL_FORMATTER_EXTENSION_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY))
+#define E_IS_MAIL_FORMATTER_EXTENSION_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY))
+#define E_MAIL_FORMATTER_EXTENSION_REGISTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY, EMailFormatterExtensionRegistryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailFormatterExtensionRegistry EMailFormatterExtensionRegistry;
+typedef struct _EMailFormatterExtensionRegistryClass EMailFormatterExtensionRegistryClass;
+typedef struct _EMailFormatterExtensionRegistryPrivate EMailFormatterExtensionRegistryPrivate;
+
+struct _EMailFormatterExtensionRegistryClass {
+ EMailExtensionRegistryClass parent_class;
+};
+
+struct _EMailFormatterExtensionRegistry {
+ EMailExtensionRegistry parent;
+ EMailFormatterExtensionRegistryPrivate *priv;
+};
+
+GType e_mail_formatter_extension_registry_get_type (void);
+
+G_END_DECLS
+
+#endif /* E_MAIL_EXTENSION_REGISTRY_H_ */
diff --git a/em-format/e-mail-extension.c b/em-format/e-mail-extension.c
new file mode 100644
index 0000000000..9516974824
--- /dev/null
+++ b/em-format/e-mail-extension.c
@@ -0,0 +1,67 @@
+/*
+ * e-mail-extension.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-extension.h"
+
+#include <glib-object.h>
+
+G_DEFINE_INTERFACE (EMailExtension, e_mail_extension, G_TYPE_OBJECT)
+
+static void
+e_mail_extension_default_init (EMailExtensionInterface *iface)
+{
+
+}
+
+/**
+ * EMailExtension:
+ *
+ * The #EMailExtension is an abstract interface for all extensions for
+ * #EMailParser and #EmailFormatter.
+ *
+ * The interface is further extended by #EMailParserExtension and
+ * #EMailFormatterExtension interfaces which define final API for both types
+ * of extensions.
+ */
+
+/**
+ * e_mail_extension_get_mime_types:
+ * @extension: an #EMailExtension
+ *
+ * A virtual function reimplemented in all mail extensions that returns a
+ * @NULL-terminated array of mime types that the particular extension is able
+ * to process.
+ *
+ * The mime-types can be either full (like text/plain), or with common subtype,
+ * e.g. text/ *. User should try to find the best mathing mime-type handler and
+ * use the latter type only as a fallback.
+ *
+ * Return value: a @NULL-terminated array or @NULL
+ */
+const gchar **
+e_mail_extension_get_mime_types (EMailExtension *extension)
+{
+ EMailExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_EXTENSION (extension), NULL);
+
+ interface = E_MAIL_EXTENSION_GET_INTERFACE (extension);
+ g_return_val_if_fail (interface->mime_types != NULL, NULL);
+
+ return interface->mime_types (extension);
+}
diff --git a/em-format/e-mail-extension.h b/em-format/e-mail-extension.h
new file mode 100644
index 0000000000..941638aed8
--- /dev/null
+++ b/em-format/e-mail-extension.h
@@ -0,0 +1,60 @@
+/*
+ * e-mail-extension.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_EXTENSION_H
+#define E_MAIL_EXTENSION_H
+
+#include <glib-object.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_EXTENSION \
+ (e_mail_extension_get_type ())
+#define E_MAIL_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_EXTENSION, EMailExtension))
+#define E_MAIL_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_EXTENSION, EMailExtensionInterface))
+#define E_IS_MAIL_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_EXTENSION))
+#define E_IS_MAIL_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_EXTENSION))
+#define E_MAIL_EXTENSION_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE \
+ ((obj), E_TYPE_MAIL_EXTENSION, EMailExtensionInterface))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailExtension EMailExtension;
+typedef struct _EMailExtensionInterface EMailExtensionInterface;
+
+struct _EMailExtensionInterface {
+ GTypeInterface parent_interface;
+
+ const gchar ** (*mime_types) (EMailExtension *extension);
+};
+
+GType e_mail_extension_get_type (void);
+
+const gchar ** e_mail_extension_get_mime_types (EMailExtension *extension);
+
+G_END_DECLS
+
+#endif /* E_MAIL_EXTENSION_H */
diff --git a/em-format/e-mail-format-extensions.c b/em-format/e-mail-format-extensions.c
new file mode 100644
index 0000000000..fa7d5d8683
--- /dev/null
+++ b/em-format/e-mail-format-extensions.c
@@ -0,0 +1,124 @@
+/*
+ * e-mail-format-extensions.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-format-extensions.h"
+
+#include "em-format/e-mail-parser-extension.h"
+#include "em-format/e-mail-formatter-extension.h"
+
+typedef GType (*TypeFunc) (void);
+
+TypeFunc parser_funcs[] = {
+ e_mail_parser_application_mbox_get_type,
+ e_mail_parser_attachment_bar_get_type,
+ e_mail_parser_headers_get_type,
+ e_mail_parser_message_get_type,
+ e_mail_parser_secure_button_get_type,
+ e_mail_parser_source_get_type,
+ e_mail_parser_image_get_type,
+ e_mail_parser_inline_pgp_encrypted_get_type,
+ e_mail_parser_inline_pgp_signed_get_type,
+ e_mail_parser_message_delivery_status_get_type,
+ e_mail_parser_message_external_get_type,
+ e_mail_parser_message_rfc822_get_type,
+ e_mail_parser_multipart_alternative_get_type,
+ e_mail_parser_multipart_apple_double_get_type,
+ e_mail_parser_multipart_digest_get_type,
+ e_mail_parser_multipart_encrypted_get_type,
+ e_mail_parser_multipart_mixed_get_type,
+ e_mail_parser_multipart_related_get_type,
+ e_mail_parser_multipart_signed_get_type,
+ e_mail_parser_text_enriched_get_type,
+ e_mail_parser_text_html_get_type,
+ e_mail_parser_text_plain_get_type,
+#ifdef ENABLE_SMIME
+ e_mail_parser_application_smime_get_type,
+#endif
+ NULL
+};
+
+TypeFunc formatter_funcs[] = {
+ e_mail_formatter_attachment_get_type,
+ e_mail_formatter_attachment_bar_get_type,
+ e_mail_formatter_error_get_type,
+ e_mail_formatter_headers_get_type,
+ e_mail_formatter_secure_button_get_type,
+ e_mail_formatter_source_get_type,
+ e_mail_formatter_image_get_type,
+ e_mail_formatter_message_rfc822_get_type,
+ e_mail_formatter_text_enriched_get_type,
+ e_mail_formatter_text_html_get_type,
+ e_mail_formatter_text_plain_get_type,
+ NULL
+};
+
+TypeFunc quote_formatter_funcs[] = {
+ e_mail_formatter_quote_attachment_get_type,
+ e_mail_formatter_quote_headers_get_type,
+ e_mail_formatter_quote_message_rfc822_get_type,
+ e_mail_formatter_quote_text_enriched_get_type,
+ e_mail_formatter_quote_text_html_get_type,
+ e_mail_formatter_quote_text_plain_get_type,
+ NULL
+};
+
+TypeFunc print_formatter_funcs[] = {
+ e_mail_formatter_print_headers_get_type,
+ NULL
+};
+
+static void
+load (EMailExtensionRegistry *ereg,
+ TypeFunc *func_array)
+{
+ gint i = 0;
+
+ for (i = 0; func_array[i] != NULL; i++) {
+ GType type;
+ EMailExtension *extension;
+
+ type = func_array[i]();
+ extension = g_object_new (type, NULL);
+
+ e_mail_extension_registry_add_extension (ereg, extension);
+ }
+}
+
+void
+e_mail_parser_internal_extensions_load (EMailExtensionRegistry *ereg)
+{
+ load (ereg, parser_funcs);
+}
+
+void
+e_mail_formatter_internal_extensions_load (EMailExtensionRegistry *ereg)
+{
+ load (ereg, formatter_funcs);
+}
+
+void
+e_mail_formatter_quote_internal_extensions_load (EMailExtensionRegistry *ereg)
+{
+ load (ereg, quote_formatter_funcs);
+}
+
+void
+e_mail_formatter_print_internal_extensions_load (EMailExtensionRegistry *ereg)
+{
+ load (ereg, print_formatter_funcs);
+}
diff --git a/em-format/e-mail-format-extensions.h b/em-format/e-mail-format-extensions.h
new file mode 100644
index 0000000000..74638ef499
--- /dev/null
+++ b/em-format/e-mail-format-extensions.h
@@ -0,0 +1,88 @@
+/*
+ * extensions.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef EXTENSIONS_H_
+#define EXTENSIONS_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <em-format/e-mail-extension-registry.h>
+#include <em-format/e-mail-part.h>
+#include <widgets/misc/e-attachment-view.h>
+
+G_BEGIN_DECLS
+
+void e_mail_formatter_internal_extensions_load (EMailExtensionRegistry *ereg);
+void e_mail_parser_internal_extensions_load (EMailExtensionRegistry *ereg);
+void e_mail_formatter_quote_internal_extensions_load (EMailExtensionRegistry *ereg);
+void e_mail_formatter_print_internal_extensions_load (EMailExtensionRegistry *ereg);
+
+GType e_mail_formatter_attachment_get_type (void);
+GType e_mail_formatter_attachment_bar_get_type
+ (void);
+GType e_mail_formatter_error_get_type (void);
+GType e_mail_formatter_headers_get_type (void);
+GType e_mail_formatter_secure_button_get_type
+ (void);
+GType e_mail_formatter_source_get_type (void);
+GType e_mail_formatter_image_get_type (void);
+GType e_mail_formatter_message_rfc822_get_type (void);
+GType e_mail_formatter_text_enriched_get_type (void);
+GType e_mail_formatter_text_html_get_type (void);
+GType e_mail_formatter_text_plain_get_type (void);
+
+GType e_mail_parser_application_mbox_get_type (void);
+GType e_mail_parser_attachment_bar_get_type (void);
+GType e_mail_parser_headers_get_type (void);
+GType e_mail_parser_message_get_type (void);
+GType e_mail_parser_secure_button_get_type (void);
+GType e_mail_parser_source_get_type (void);
+GType e_mail_parser_image_get_type (void);
+GType e_mail_parser_inline_pgp_encrypted_get_type (void);
+GType e_mail_parser_inline_pgp_signed_get_type (void);
+GType e_mail_parser_message_delivery_status_get_type (void);
+GType e_mail_parser_message_external_get_type (void);
+GType e_mail_parser_message_rfc822_get_type (void);
+GType e_mail_parser_multipart_alternative_get_type (void);
+GType e_mail_parser_multipart_apple_double_get_type (void);
+GType e_mail_parser_multipart_digest_get_type (void);
+GType e_mail_parser_multipart_encrypted_get_type (void);
+GType e_mail_parser_multipart_mixed_get_type (void);
+GType e_mail_parser_multipart_related_get_type (void);
+GType e_mail_parser_multipart_signed_get_type (void);
+GType e_mail_parser_text_enriched_get_type (void);
+GType e_mail_parser_text_html_get_type (void);
+GType e_mail_parser_text_plain_get_type (void);
+#ifdef ENABLE_SMIME
+GType e_mail_parser_application_smime_get_type (void);
+#endif
+
+GType e_mail_formatter_quote_attachment_get_type (void);
+GType e_mail_formatter_quote_headers_get_type (void);
+GType e_mail_formatter_quote_message_rfc822_get_type (void);
+GType e_mail_formatter_quote_text_enriched_get_type (void);
+GType e_mail_formatter_quote_text_html_get_type (void);
+GType e_mail_formatter_quote_text_plain_get_type (void);
+
+GType e_mail_formatter_print_headers_get_type (void);
+
+G_END_DECLS
+
+#endif /* EXTENSIONS_H_ */
diff --git a/em-format/e-mail-formatter-attachment-bar.c b/em-format/e-mail-formatter-attachment-bar.c
new file mode 100644
index 0000000000..c1fda1636c
--- /dev/null
+++ b/em-format/e-mail-formatter-attachment-bar.c
@@ -0,0 +1,154 @@
+/*
+ * e-mail-formatter-attachment-bar.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "e-mail-format-extensions.h"
+#include "e-mail-part-attachment-bar.h"
+#include <misc/e-attachment-bar.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+
+typedef struct _EMailFormatterAttachmentBar {
+ GObject parent;
+} EMailFormatterAttachmentBar;
+
+typedef struct _EMailFormatterAttachmentBarClass {
+ GObjectClass parent_class;
+} EMailFormatterAttachmentBarClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterAttachmentBar,
+ e_mail_formatter_attachment_bar,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.widget.attachment-bar", NULL };
+
+static gboolean
+emfe_attachment_bar_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *str;
+
+ if ((context->mode != E_MAIL_FORMATTER_MODE_NORMAL) &&
+ (context->mode != E_MAIL_FORMATTER_MODE_RAW))
+ return FALSE;
+
+ str = g_strdup_printf (
+ "<object type=\"application/vnd.evolution.widget.attachment-bar\" "
+ "height=\"0\" width=\"100%%\" data=\"%s\" id=\"%s\"></object>",
+ part->id, part->id);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+ return TRUE;
+}
+
+static void
+unset_bar_from_store_data (GObject *store,
+ EAttachmentBar *bar)
+{
+ /*
+ if (E_IS_ATTACHMENT_STORE (store))
+ g_object_set_data (store, "attachment-bar", NULL);
+ */
+}
+
+static GtkWidget *
+emfe_attachment_bar_get_widget (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params)
+{
+ EMailPartAttachmentBar *empab;
+ GtkWidget *widget;
+
+ g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAttachmentBar), NULL);
+
+ empab = (EMailPartAttachmentBar *) part;
+ widget = e_attachment_bar_new (empab->store);
+ g_object_set_data (G_OBJECT (empab->store), "attachment-bar", widget);
+ g_object_weak_ref (G_OBJECT (widget),
+ (GWeakNotify) unset_bar_from_store_data, empab->store);
+
+ return widget;
+}
+
+static const gchar *
+emfe_attachment_bar_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfe_attachment_bar_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfe_attachment_bar_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_attachment_bar_class_init (EMailFormatterAttachmentBarClass *klass)
+{
+ e_mail_formatter_attachment_bar_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_attachment_bar_format;
+ iface->get_widget = emfe_attachment_bar_get_widget;
+ iface->get_display_name = emfe_attachment_bar_get_display_name;
+ iface->get_description = emfe_attachment_bar_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_attachment_bar_mime_types;
+}
+
+static void
+e_mail_formatter_attachment_bar_init (EMailFormatterAttachmentBar *extension)
+{
+
+}
diff --git a/em-format/e-mail-formatter-attachment.c b/em-format/e-mail-formatter-attachment.c
new file mode 100644
index 0000000000..3d63413a69
--- /dev/null
+++ b/em-format/e-mail-formatter-attachment.c
@@ -0,0 +1,403 @@
+/*
+ * e-mail-formatter-attachment.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+#include "e-mail-part-attachment.h"
+#include "e-mail-part-attachment-bar.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <e-util/e-util.h>
+
+#include <shell/e-shell.h>
+#include <shell/e-shell-window.h>
+
+#include <widgets/misc/e-attachment-button.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#define d(x)
+
+typedef struct _EMailFormatterAttachment {
+ GObject parent;
+} EMailFormatterAttachment;
+
+typedef struct _EMailFormatterAttachmentClass {
+ GObjectClass parent_class;
+} EMailFormatterAttachmentClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterAttachment,
+ e_mail_formatter_attachment,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init)
+)
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.attachment",
+ "application/vnd.evolution.widget.attachment-button",
+ NULL };
+
+static EAttachmentStore *
+find_attachment_store (GSList *parts,
+ const gchar *start_id)
+{
+ gchar *tmp, *pos;
+ EMailPart *part;
+ gchar *id;
+
+ id = g_strconcat (start_id, ".attachment-bar", NULL);
+ tmp = g_strdup (id);
+ part = NULL;
+ do {
+ GSList *iter;
+
+ d(printf("Looking up attachment bar as %s\n", id));
+
+ for (iter = parts; iter; iter = iter->next) {
+ EMailPart *p = iter->data;
+
+ if (!p)
+ continue;
+
+ if (g_strcmp0 (p->id, id) == 0) {
+ part = p;
+ break;
+ }
+ }
+
+ pos = g_strrstr (tmp, ".");
+ if (!pos)
+ break;
+
+ g_free (id);
+ g_free (tmp);
+ tmp = g_strndup (start_id, pos - tmp);
+ id = g_strdup_printf ("%s.attachment-bar", tmp);
+
+ } while (pos && !part);
+
+ g_free (id);
+ g_free (tmp);
+
+ if (part) {
+ return ((EMailPartAttachmentBar *) part)->store;
+ }
+
+ return NULL;
+}
+
+static gboolean
+emfe_attachment_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *str, *text, *html;
+ gchar *button_id;
+ EAttachmentStore *store;
+ EMailExtensionRegistry *reg;
+ GQueue *extensions;
+ EMailPartAttachment *empa;
+ gchar *attachment_part_id;
+
+ g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAttachment), FALSE);
+
+ empa = (EMailPartAttachment *) part;
+
+ if ((context->mode == E_MAIL_FORMATTER_MODE_NORMAL) ||
+ (context->mode == E_MAIL_FORMATTER_MODE_PRINTING)) {
+ if (part->validity) {
+ e_attachment_set_signed (
+ empa->attachment, part->validity->sign.status);
+ e_attachment_set_encrypted (
+ empa->attachment, part->validity->encrypt.status);
+ }
+
+ store = find_attachment_store (context->parts, part->id);
+ if (store) {
+ GList *attachments = e_attachment_store_get_attachments (store);
+ if (!g_list_find (attachments, empa->attachment)) {
+ e_attachment_store_add_attachment (
+ store, empa->attachment);
+ }
+ g_list_free (attachments);
+ } else {
+ g_warning ("Failed to locate attachment-bar for %s", part->id);
+ }
+ }
+
+ /* If the attachment is requested as RAW, then call the handler directly
+ * and do not append any other code. */
+ if ((context->mode == E_MAIL_FORMATTER_MODE_RAW) ||
+ (context->mode == E_MAIL_FORMATTER_MODE_PRINTING)) {
+ EMailExtensionRegistry *reg;
+ GQueue *extensions;
+ GList *iter;
+ reg = e_mail_formatter_get_extension_registry (formatter);
+
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, empa->snoop_mime_type);
+ if (!extensions) {
+ extensions = e_mail_extension_registry_get_fallback (
+ reg, empa->snoop_mime_type);
+ }
+
+ if (!extensions)
+ return FALSE;
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
+ gchar *name;
+ EAttachment *attachment;
+ GFileInfo *fi;
+ const gchar *description;
+
+ attachment = empa->attachment;
+ fi = e_attachment_get_file_info (attachment);
+
+ description = e_attachment_get_description (attachment);
+ if (description && *description) {
+ name = g_strdup_printf ("<h2>Attachment: %s (%s)</h2>\n",
+ description, g_file_info_get_display_name (fi));
+ } else {
+ name = g_strdup_printf ("<h2>Attachment: %s</h2>\n",
+ g_file_info_get_display_name (fi));
+ }
+
+ camel_stream_write_string (stream, name, cancellable, NULL);
+ g_free (name);
+ }
+
+ for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) {
+
+ EMailFormatterExtension *ext;
+ ext = iter->data;
+ if (!ext)
+ continue;
+
+ if (e_mail_formatter_extension_format (ext, formatter,
+ context, part, stream, cancellable)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+ /* E_MAIL_FORMATTER_MODE_NORMAL: */
+
+ reg = e_mail_formatter_get_extension_registry (formatter);
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, empa->snoop_mime_type);
+
+ if (!extensions) {
+ extensions = e_mail_extension_registry_get_fallback (
+ reg, empa->snoop_mime_type);
+ }
+
+ text = e_mail_part_describe (part->part, empa->snoop_mime_type);
+ html = camel_text_to_html (
+ text, e_mail_formatter_get_text_format_flags (formatter) &
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
+ g_free (text);
+
+ if (empa->attachment_view_part_id)
+ attachment_part_id = empa->attachment_view_part_id;
+ else
+ attachment_part_id = part->id;
+
+ button_id = g_strconcat (attachment_part_id, ".attachment_button", NULL);
+
+ str = g_strdup_printf (
+ "<div class=\"attachment\">"
+ "<table width=\"100%%\" border=\"0\">"
+ "<tr valign=\"middle\">"
+ "<td align=\"left\" width=\"100\">"
+ "<object type=\"application/vnd.evolution.widget.attachment-button\" "
+ "height=\"20\" width=\"100\" data=\"%s\" id=\"%s\"></object>"
+ "</td>"
+ "<td align=\"left\">%s</td>"
+ "</tr>", part->id, button_id, html);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+ g_free (button_id);
+ g_free (str);
+ g_free (html);
+
+ if (extensions) {
+ GList *iter;
+ CamelStream *content_stream;
+ gboolean ok;
+
+ content_stream = camel_stream_mem_new ();
+ ok = FALSE;
+ if (empa->attachment_view_part_id != NULL) {
+
+ GSList *att_parts;
+
+ att_parts = e_mail_part_list_get_iter (
+ context->parts,
+ empa->attachment_view_part_id);
+
+ if (att_parts && att_parts->data) {
+ ok = e_mail_formatter_format_as (
+ formatter, context, att_parts->data,
+ content_stream, NULL, cancellable);
+ }
+
+ } else {
+
+ for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) {
+
+ EMailFormatterExtension *ext;
+
+ ext = iter->data;
+ if (!ext)
+ continue;
+
+ if (e_mail_formatter_extension_format (
+ ext, formatter, context,
+ part, content_stream,
+ cancellable)) {
+ ok = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (ok) {
+ str = g_strdup_printf (
+ "<tr><td colspan=\"2\">"
+ "<div class=\"attachment-wrapper\" id=\"%s\">",
+ attachment_part_id);
+
+ camel_stream_write_string (
+ stream, str, cancellable, NULL);
+ g_free (str);
+
+ g_seekable_seek (
+ G_SEEKABLE (content_stream), 0,
+ G_SEEK_SET, cancellable, NULL);
+ camel_stream_write_to_stream (
+ content_stream, stream,
+ cancellable, NULL);
+
+ camel_stream_write_string (
+ stream, "</div></td></tr>", cancellable, NULL);
+ }
+
+ g_object_unref (content_stream);
+ }
+
+ camel_stream_write_string (stream, "</table></div>", cancellable, NULL);
+
+ return TRUE;
+}
+
+static GtkWidget *
+emfe_attachment_get_widget (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params)
+{
+ EMailPartAttachment *empa;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GtkWidget *widget;
+
+ g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAttachment), NULL);
+ empa = (EMailPartAttachment *) part;
+
+ store = find_attachment_store (context->list, part->id);
+ widget = e_attachment_button_new ();
+ g_object_set_data (G_OBJECT (widget), "uri", part->id);
+ e_attachment_button_set_attachment (
+ E_ATTACHMENT_BUTTON (widget), empa->attachment);
+ view = g_object_get_data (G_OBJECT (store), "attachment-bar");
+ if (view) {
+ e_attachment_button_set_view (
+ E_ATTACHMENT_BUTTON (widget), view);
+ }
+
+ gtk_widget_set_can_focus (widget, TRUE);
+ gtk_widget_show (widget);
+
+ return widget;
+}
+
+static const gchar *
+emfe_attachment_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Attachment");
+}
+
+static const gchar *
+emfe_attachment_get_description (EMailFormatterExtension *extension)
+{
+ return _("Display as attachment");
+}
+
+static const gchar **
+emfe_attachment_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_attachment_class_init (EMailFormatterAttachmentClass *klass)
+{
+ e_mail_formatter_attachment_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_attachment_format;
+ iface->get_widget = emfe_attachment_get_widget;
+ iface->get_display_name = emfe_attachment_get_display_name;
+ iface->get_description = emfe_attachment_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_attachment_mime_types;
+}
+
+static void
+e_mail_formatter_attachment_init (EMailFormatterAttachment *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-error.c b/em-format/e-mail-formatter-error.c
new file mode 100644
index 0000000000..95f201145b
--- /dev/null
+++ b/em-format/e-mail-formatter-error.c
@@ -0,0 +1,160 @@
+/*
+ * e-mail-formatter-error.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+typedef struct _EMailFormatterError {
+ GObject parent;
+} EMailFormatterError;
+
+typedef struct _EMailFormatterErrorClass {
+ GObjectClass parent_class;
+} EMailFormatterErrorClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterError,
+ e_mail_formatter_error,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.error", NULL };
+
+static gboolean
+emfe_error_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelStream *filtered_stream;
+ CamelMimeFilter *filter;
+ CamelDataWrapper *dw;
+ gchar *html;
+
+ dw = camel_medium_get_content ((CamelMedium *) part->part);
+
+ html = g_strdup_printf (
+ "<div class=\"part-container\" style=\""
+ "border-color: #%06x;"
+ "background-color: #%06x; color: #%06x;\">"
+ "<div class=\"part-container-inner-margin pre\">\n"
+ "<table border=\"0\" cellspacing=\"10\" "
+ "cellpadding=\"0\" width=\"100%%\">\n"
+ "<tr valign=\"top\"><td width=50>"
+ "<img src=\"gtk-stock://%s/?size=%d\" /></td>\n"
+ "<td style=\"color: red;\">",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_TEXT)),
+ GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
+
+ camel_stream_write_string (stream, html, cancellable, NULL);
+ g_free (html);
+
+ filtered_stream = camel_stream_filter_new (stream);
+ filter = camel_mime_filter_tohtml_new (
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
+ camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered_stream), filter);
+ g_object_unref (filter);
+
+ camel_data_wrapper_decode_to_stream_sync (dw, filtered_stream, cancellable, NULL);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ camel_stream_write_string (stream,
+ "</td>\n"
+ "</tr>\n"
+ "</table>\n"
+ "</div>\n"
+ "</div>",
+ cancellable, NULL);
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_error_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfe_error_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfe_error_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_error_class_init (EMailFormatterErrorClass *klass)
+{
+ e_mail_formatter_error_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_error_format;
+ iface->get_display_name = emfe_error_get_display_name;
+ iface->get_description = emfe_error_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_error_mime_types;
+}
+
+static void
+e_mail_formatter_error_init (EMailFormatterError *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-extension.c b/em-format/e-mail-formatter-extension.c
new file mode 100644
index 0000000000..381855bac5
--- /dev/null
+++ b/em-format/e-mail-formatter-extension.c
@@ -0,0 +1,189 @@
+/*
+ * e-mail-formatter-extension.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter-extension.h"
+
+G_DEFINE_INTERFACE (
+ EMailFormatterExtension,
+ e_mail_formatter_extension,
+ E_TYPE_MAIL_EXTENSION)
+
+/**
+ * EMailFormatterExtension:
+ *
+ * The #EMailFormatterExtension is an abstract interface for all extensions for
+ * #EmailFormatter.
+ */
+
+static void
+e_mail_formatter_extension_default_init (EMailFormatterExtensionInterface *iface)
+{
+
+}
+
+/**
+ * e_mail_formatter_extension_format
+ * @extension: an #EMailFormatterExtension
+ * @formatter: an #EMailFormatter
+ * @context: an #EMailFormatterContext
+ * @part: a #EMailPart to be formatter
+ * @stream: a #CamelStream to which the output should be written
+ * @cancellable: (allow-none) a #GCancellable
+ *
+ * A virtual function reimplemented in all mail formatter extensions. The function
+ * formats @part, generated HTML (or other format that can be displayed to user)
+ * and writes it to the @stream.
+ *
+ * When the function is unable to format the @part (either because it's broken
+ * or because it is a different mimetype then the extension is specialized for), the
+ * function will return @FALSE indicating the #EMailFormatter, that it should pick
+ * another extension.
+ *
+ * Implementation of this function must be thread-safe.
+ *
+ * Return value: Returns @TRUE when the @part was successfully formatted and
+ * data were written to the @stream, @FALSE otherwise.
+ */
+gboolean
+e_mail_formatter_extension_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ EMailFormatterExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER_EXTENSION (extension), FALSE);
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+ g_return_val_if_fail (context != NULL, FALSE);
+ g_return_val_if_fail (part != NULL, FALSE);
+ g_return_val_if_fail (CAMEL_IS_STREAM (stream), FALSE);
+
+ interface = E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE (extension);
+ g_return_val_if_fail (interface->format != NULL, FALSE);
+
+ return interface->format (extension, formatter, context, part, stream, cancellable);
+}
+
+/**
+ * e_mail_formatter_extension_has_widget:
+ * @extension: an #EMailFormatterExtension
+ *
+ * Returns whether the extension can provide a GtkWidget.
+ *
+ * Return value: Returns %TRUE when @extension reimplements get_widget(), %FALSE
+ * otherwise.
+ */
+gboolean
+e_mail_formatter_extension_has_widget (EMailFormatterExtension *extension)
+{
+ EMailFormatterExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER_EXTENSION (extension), FALSE);
+
+ interface = E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE (extension);
+
+ return (interface->get_widget != NULL);
+}
+
+/**
+ * e_mail_formatter_extension_get_widget:
+ * @extension: an #EMailFormatterExtension
+ * @part: an #EMailPart
+ * @params: a #GHashTable
+ *
+ * A virtual function reimplemented in some mail formatter extensions. The function
+ * should construct a #GtkWidget for given @part. The @params hash table can contain
+ * additional parameters listed in the &lt;object&gt; HTML element that has requested
+ * the widget.
+ *
+ * When @bind_dom_func is not %NULL, the callee will set a callback function
+ * which should be called when the webpage is completely rendered to setup
+ * bindings between DOM events and the widget.
+ *
+ * Return value: Returns a #GtkWidget or %NULL, when error occurs or given @extension
+ * does not reimplement this method.
+ */
+GtkWidget *
+e_mail_formatter_extension_get_widget (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params)
+{
+ EMailFormatterExtensionInterface *interface;
+ GtkWidget *widget;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER_EXTENSION (extension), NULL);
+ g_return_val_if_fail (part != NULL, NULL);
+ g_return_val_if_fail (params != NULL, NULL);
+
+ interface = E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE (extension);
+
+ widget = NULL;
+ if (interface->get_widget) {
+ widget = interface->get_widget (
+ extension, context, part, params);
+ }
+
+ return widget;
+}
+
+/**
+ * e_mail_formatter_extension_get_display_name:
+ * @extension: an #EMailFormatterExtension
+ *
+ * A virtual function reimplemented in all formatter extensions. It returns a
+ * short name of the extension that can be displayed in user interface.
+ *
+ * Return value: A (localized) string with name of the extension
+ */
+const gchar *
+e_mail_formatter_extension_get_display_name (EMailFormatterExtension *extension)
+{
+ EMailFormatterExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER_EXTENSION (extension), NULL);
+
+ interface = E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE (extension);
+ g_return_val_if_fail (interface->get_display_name != NULL, NULL);
+
+ return interface->get_display_name (extension);
+}
+
+/**
+ * e_mail_formatter_extension_get_description:
+ * @extension: an #EMailFormatterExtension
+ *
+ * A virtual function reimplemented in all formatter extensions. It returns a
+ * longer description of capabilities of the extension.
+ *
+ * Return value: A (localized) string with description of the extension.
+ */
+const gchar *
+e_mail_formatter_extension_get_description (EMailFormatterExtension *extension)
+{
+ EMailFormatterExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER_EXTENSION (extension), NULL);
+
+ interface = E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE (extension);
+ g_return_val_if_fail (interface->get_description != NULL, NULL);
+
+ return interface->get_description (extension);
+}
diff --git a/em-format/e-mail-formatter-extension.h b/em-format/e-mail-formatter-extension.h
new file mode 100644
index 0000000000..e2c4ee6cf1
--- /dev/null
+++ b/em-format/e-mail-formatter-extension.h
@@ -0,0 +1,106 @@
+/*
+ * e-mail-formatter-extension.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_EXTENSION_H
+#define E_MAIL_FORMATTER_EXTENSION_H
+
+#include <em-format/e-mail-extension.h>
+#include <em-format/e-mail-part.h>
+#include <em-format/e-mail-formatter.h>
+#include <camel/camel.h>
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_FORMATTER_EXTENSION \
+ (e_mail_formatter_extension_get_type ())
+#define E_MAIL_FORMATTER_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION, EMailFormatterExtension))
+#define E_MAIL_FORMATTER_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_FORMATTER_EXTENSION, EMailFormatterExtensionInterface))
+#define E_IS_MAIL_FORMATTER_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION))
+#define E_IS_MAIL_FORMATTER_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_FORMATTER_EXTENSION))
+#define E_MAIL_FORMATTER_EXTENSION_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE \
+ ((obj), E_TYPE_MAIL_FORMATTER_EXTENSION, EMailFormatterExtensionInterface))
+
+#define EMF_EXTENSION_GET_FORMATTER(e) \
+ E_MAIL_FORMATTER (e_extension_get_extensible (E_EXTENSION (e)))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailFormatterExtension EMailFormatterExtension;
+typedef struct _EMailFormatterExtensionInterface EMailFormatterExtensionInterface;
+
+struct _EMailFormatterExtensionInterface {
+ EMailExtensionInterface parent_interface;
+
+ gboolean (*format) (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable);
+
+ GtkWidget * (*get_widget) (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params);
+
+ const gchar * (*get_display_name)
+ (EMailFormatterExtension *extension);
+
+ const gchar * (*get_description)
+ (EMailFormatterExtension *extension);
+
+};
+
+GType e_mail_formatter_extension_get_type
+ (void);
+
+gboolean e_mail_formatter_extension_format
+ (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable);
+
+gboolean e_mail_formatter_extension_has_widget
+ (EMailFormatterExtension *extension);
+
+GtkWidget * e_mail_formatter_extension_get_widget
+ (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params);
+
+const gchar * e_mail_formatter_extension_get_display_name
+ (EMailFormatterExtension *extension);
+
+const gchar * e_mail_formatter_extension_get_description
+ (EMailFormatterExtension *extension);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_EXTENSION_H */
diff --git a/em-format/e-mail-formatter-headers.c b/em-format/e-mail-formatter-headers.c
new file mode 100644
index 0000000000..24d27139b5
--- /dev/null
+++ b/em-format/e-mail-formatter-headers.c
@@ -0,0 +1,615 @@
+/*
+ * e-mail-formatter-headers.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-formatter-utils.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <libemail-engine/e-mail-utils.h>
+#include <libedataserver/libedataserver.h>
+#include <e-util/e-util.h>
+#include <shell/e-shell.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailFormatterHeaders {
+ GObject parent;
+} EMailFormatterHeaders;
+
+typedef struct _EMailFormatterHeadersClass {
+ GObjectClass parent_class;
+} EMailFormatterHeadersClass;
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.headers", NULL };
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterHeaders,
+ e_mail_formatter_headers,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init))
+
+static void
+format_short_headers (EMailFormatter *formatter,
+ GString *buffer,
+ CamelMedium *part,
+ guint32 flags,
+ GCancellable *cancellable)
+{
+ const gchar *charset;
+ CamelContentType *ct;
+ const gchar *hdr_charset;
+ gchar *evolution_imagesdir;
+ gchar *subject = NULL;
+ struct _camel_header_address *addrs = NULL;
+ struct _camel_header_raw *header;
+ GString *from;
+ gboolean is_rtl;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
+ charset = camel_content_type_param (ct, "charset");
+ charset = camel_iconv_charset_name (charset);
+ hdr_charset = e_mail_formatter_get_charset (formatter) ?
+ e_mail_formatter_get_charset (formatter) :
+ e_mail_formatter_get_default_charset (formatter);
+
+ evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+ from = g_string_new ("");
+
+ g_string_append_printf (buffer,
+ "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" "
+ "id=\"__evo-short-headers\" style=\"display: %s\">",
+ flags & E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSED ? "block" : "none");
+
+ header = ((CamelMimePart *) part)->headers;
+ while (header) {
+ if (!g_ascii_strcasecmp (header->name, "From")) {
+ GString *tmp;
+ if (!(addrs = camel_header_address_decode (header->value, hdr_charset))) {
+ header = header->next;
+ continue;
+ }
+ tmp = g_string_new ("");
+ e_mail_formatter_format_address (
+ formatter, tmp, addrs, header->name, FALSE,
+ !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
+
+ if (tmp->len)
+ g_string_printf (from, _("From: %s"), tmp->str);
+ g_string_free (tmp, TRUE);
+
+ } else if (!g_ascii_strcasecmp (header->name, "Subject")) {
+ gchar *buf = NULL;
+ subject = camel_header_unfold (header->value);
+ buf = camel_header_decode_string (subject, hdr_charset);
+ g_free (subject);
+ subject = camel_text_to_html (buf, CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0);
+ g_free (buf);
+ }
+ header = header->next;
+ }
+
+ is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
+ if (is_rtl) {
+ g_string_append_printf (
+ buffer,
+ "<tr><td width=\"100%%\" align=\"right\">%s%s%s <strong>%s</strong></td></tr>",
+ from->len ? "(" : "", from->str, from->len ? ")" : "",
+ subject ? subject : _("(no subject)"));
+ } else {
+ g_string_append_printf (
+ buffer,
+ "<tr><td><strong>%s</strong> %s%s%s</td></tr>",
+ subject ? subject : _("(no subject)"),
+ from->len ? "(" : "", from->str, from->len ? ")" : "");
+ }
+
+ g_string_append (buffer, "</table>");
+
+ g_free (subject);
+ if (addrs)
+ camel_header_address_list_clear (&addrs);
+
+ g_string_free (from, TRUE);
+ g_free (evolution_imagesdir);
+}
+
+static void
+write_contact_picture (CamelMimePart *part,
+ gint size,
+ GString *buffer)
+{
+ gchar *b64, *content_type;
+ CamelDataWrapper *dw;
+ CamelContentType *ct;
+ GByteArray *ba;
+
+ ba = NULL;
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ if (dw) {
+ ba = camel_data_wrapper_get_byte_array (dw);
+ }
+
+ if (!ba || ba->len == 0) {
+
+ if (camel_mime_part_get_filename (part)) {
+
+ if (size >= 0) {
+ g_string_append_printf (
+ buffer,
+ "<img width=\"%d\" src=\"evo-file://%s\" />",
+ size, camel_mime_part_get_filename (part));
+ } else {
+ g_string_append_printf (
+ buffer,
+ "<img src=\"evo-file://%s\" />",
+ camel_mime_part_get_filename (part));
+ }
+ }
+
+ return;
+ }
+
+ b64 = g_base64_encode (ba->data, ba->len);
+ ct = camel_mime_part_get_content_type (part);
+ content_type = camel_content_type_simple (ct);
+
+ if (size >= 0) {
+ g_string_append_printf (
+ buffer,
+ "<img width=\"%d\" src=\"data:%s;base64,%s\">",
+ size, content_type, b64);
+ } else {
+ g_string_append_printf (
+ buffer,
+ "<img src=\"data:%s;base64,%s\">",
+ content_type, b64);
+ }
+
+ g_free (b64);
+ g_free (content_type);
+}
+
+static CamelMimePart *
+load_picture_from_file (const gchar *mime_type,
+ const gchar *filename,
+ GCancellable *cancellable)
+{
+ CamelMimePart *part;
+ CamelStream *stream;
+ CamelDataWrapper *dw;
+ gchar *basename;
+
+ stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0, NULL);
+ if (stream == NULL)
+ return NULL;
+
+ dw = camel_data_wrapper_new ();
+ camel_data_wrapper_construct_from_stream_sync (
+ dw, stream, cancellable, NULL);
+ g_object_unref (stream);
+ if (mime_type)
+ camel_data_wrapper_set_mime_type (dw, mime_type);
+ part = camel_mime_part_new ();
+ camel_medium_set_content ((CamelMedium *) part, dw);
+ g_object_unref (dw);
+ basename = g_path_get_basename (filename);
+ camel_mime_part_set_filename (part, basename);
+ g_free (basename);
+
+ return part;
+}
+
+static void
+format_full_headers (EMailFormatter *formatter,
+ GString *buffer,
+ CamelMedium *part,
+ guint32 flags,
+ GCancellable *cancellable)
+{
+ const gchar *charset;
+ CamelContentType *ct;
+ struct _camel_header_raw *header;
+ gboolean have_icon = FALSE;
+ const gchar *photo_name = NULL;
+ CamelInternetAddress *cia = NULL;
+ EShell *shell;
+ ESourceRegistry *registry;
+ gboolean face_decoded = FALSE, contact_has_photo = FALSE;
+ guchar *face_header_value = NULL;
+ gsize face_header_len = 0;
+ gchar *header_sender = NULL, *header_from = NULL, *name;
+ gboolean mail_from_delegate = FALSE;
+ const gchar *hdr_charset;
+ gchar *evolution_imagesdir;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ shell = e_shell_get_default ();
+ registry = e_shell_get_registry (shell);
+
+ ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
+ charset = camel_content_type_param (ct, "charset");
+ charset = camel_iconv_charset_name (charset);
+ hdr_charset = e_mail_formatter_get_charset (formatter) ?
+ e_mail_formatter_get_charset (formatter) :
+ e_mail_formatter_get_default_charset (formatter);
+
+ evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+
+ g_string_append_printf (buffer,
+ "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" "
+ "id=\"__evo-full-headers\" style=\"display: %s\" width=\"100%%\">",
+ flags & E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSED ? "none" : "block");
+
+ header = ((CamelMimePart *) part)->headers;
+ while (header) {
+ if (!g_ascii_strcasecmp (header->name, "Sender")) {
+ struct _camel_header_address *addrs;
+ GString *html;
+
+ if (!(addrs = camel_header_address_decode (header->value, hdr_charset)))
+ break;
+
+ html = g_string_new("");
+ name = e_mail_formatter_format_address (
+ formatter, html, addrs, header->name, FALSE,
+ ~(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
+
+ header_sender = html->str;
+ camel_header_address_list_clear (&addrs);
+
+ g_string_free (html, FALSE);
+ g_free (name);
+ } else if (!g_ascii_strcasecmp (header->name, "From")) {
+ struct _camel_header_address *addrs;
+ GString *html;
+
+ if (!(addrs = camel_header_address_decode (header->value, hdr_charset)))
+ break;
+
+ html = g_string_new("");
+ name = e_mail_formatter_format_address (
+ formatter, html, addrs, header->name, FALSE,
+ !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
+
+ header_from = html->str;
+ camel_header_address_list_clear (&addrs);
+
+ g_string_free (html, FALSE);
+ g_free (name);
+ } else if (!g_ascii_strcasecmp (header->name, "X-Evolution-Mail-From-Delegate")) {
+ mail_from_delegate = TRUE;
+ }
+
+ header = header->next;
+ }
+
+ if (header_sender && header_from && mail_from_delegate) {
+ gchar *bold_sender, *bold_from;
+
+ g_string_append (
+ buffer,
+ "<tr><td><table border=1 width=\"100%%\" "
+ "cellspacing=2 cellpadding=2><tr>");
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ g_string_append (
+ buffer, "<td align=\"right\" width=\"100%%\">");
+ else
+ g_string_append (
+ buffer, "<td align=\"left\" width=\"100%%\">");
+ bold_sender = g_strconcat ("<b>", header_sender, "</b>", NULL);
+ bold_from = g_strconcat ("<b>", header_from, "</b>", NULL);
+ /* Translators: This message suggests to the receipients
+ * that the sender of the mail is different from the one
+ * listed in From field. */
+ g_string_append_printf (
+ buffer,
+ _("This message was sent by %s on behalf of %s"),
+ bold_sender, bold_from);
+ g_string_append (buffer, "</td></tr></table></td></tr>");
+ g_free (bold_sender);
+ g_free (bold_from);
+ }
+
+ g_free (header_sender);
+ g_free (header_from);
+
+ g_string_append (buffer, "<tr><td width=\"100%%\"><table border=0 cellpadding=\"0\">\n");
+
+ g_free (evolution_imagesdir);
+
+ /* dump selected headers */
+ if (flags & E_MAIL_FORMATTER_MODE_ALL_HEADERS) {
+ header = ((CamelMimePart *) part)->headers;
+ while (header) {
+ e_mail_formatter_format_header (
+ formatter, buffer, part, header,
+ E_MAIL_FORMATTER_HEADER_FLAG_NOCOLUMNS, charset);
+ header = header->next;
+ }
+ } else {
+ GList *link;
+ gint mailer_shown = FALSE;
+
+ link = g_queue_peek_head_link (
+ (GQueue *) e_mail_formatter_get_headers (formatter));
+
+ while (link != NULL) {
+ EMailFormatterHeader *h = link->data;
+ gint mailer, face;
+
+ header = ((CamelMimePart *) part)->headers;
+ mailer = !g_ascii_strcasecmp (h->name, "X-Evolution-Mailer");
+ face = !g_ascii_strcasecmp (h->name, "Face");
+
+ while (header) {
+ if (e_mail_formatter_get_show_sender_photo (formatter) &&
+ !photo_name && !g_ascii_strcasecmp (header->name, "From"))
+ photo_name = header->value;
+
+ if (!mailer_shown && mailer && (
+ !g_ascii_strcasecmp (header->name, "X-Mailer") ||
+ !g_ascii_strcasecmp (header->name, "User-Agent") ||
+ !g_ascii_strcasecmp (header->name, "X-Newsreader") ||
+ !g_ascii_strcasecmp (header->name, "X-MimeOLE"))) {
+ struct _camel_header_raw xmailer, *use_header = NULL;
+
+ if (!g_ascii_strcasecmp (header->name, "X-MimeOLE")) {
+ for (use_header = header->next; use_header; use_header = use_header->next) {
+ if (!g_ascii_strcasecmp (use_header->name, "X-Mailer") ||
+ !g_ascii_strcasecmp (use_header->name, "User-Agent") ||
+ !g_ascii_strcasecmp (use_header->name, "X-Newsreader")) {
+ /* even we have X-MimeOLE, then use rather the standard one, when available */
+ break;
+ }
+ }
+ }
+
+ if (!use_header)
+ use_header = header;
+
+ xmailer.name = (gchar *) "X-Evolution-Mailer";
+ xmailer.value = use_header->value;
+ mailer_shown = TRUE;
+
+ e_mail_formatter_format_header (
+ formatter, buffer, part,
+ &xmailer, h->flags, charset);
+ if (strstr(use_header->value, "Evolution"))
+ have_icon = TRUE;
+ } else if (!face_decoded && face && !g_ascii_strcasecmp (header->name, "Face")) {
+ gchar *cp = header->value;
+
+ /* Skip over spaces */
+ while (*cp == ' ')
+ cp++;
+
+ face_header_value = g_base64_decode (
+ cp, &face_header_len);
+ face_header_value = g_realloc (
+ face_header_value,
+ face_header_len + 1);
+ face_header_value[face_header_len] = 0;
+ face_decoded = TRUE;
+ /* Showing an encoded "Face" header makes little sense */
+ } else if (!g_ascii_strcasecmp (header->name, h->name) && !face) {
+ e_mail_formatter_format_header (
+ formatter, buffer, part,
+ header, h->flags, charset);
+ }
+
+ header = header->next;
+ }
+
+ link = g_list_next (link);
+ }
+ }
+
+ g_string_append (buffer, "</table></td>");
+
+ if (photo_name) {
+ CamelMimePart *photopart;
+ gboolean only_local_photo;
+
+ cia = camel_internet_address_new ();
+ camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
+ only_local_photo = e_mail_formatter_get_only_local_photos (formatter);
+ photopart = em_utils_contact_photo (
+ registry, cia, only_local_photo);
+
+ if (photopart) {
+ g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
+ write_contact_picture (photopart, -1, buffer);
+ g_string_append (buffer, "</td>");
+ g_object_unref (photopart);
+ }
+ g_object_unref (cia);
+ }
+
+ if (!contact_has_photo && face_decoded) {
+ CamelMimePart *part;
+
+ part = camel_mime_part_new ();
+ camel_mime_part_set_content (
+ (CamelMimePart *) part,
+ (const gchar *) face_header_value,
+ face_header_len, "image/png");
+
+ g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
+ write_contact_picture (part, 48, buffer);
+ g_string_append (buffer, "</td>");
+
+ g_object_unref (part);
+ g_free (face_header_value);
+ }
+
+ if (have_icon) {
+ GtkIconInfo *icon_info;
+ CamelMimePart *iconpart = NULL;
+
+ icon_info = gtk_icon_theme_lookup_icon (
+ gtk_icon_theme_get_default (),
+ "evolution", 16, GTK_ICON_LOOKUP_NO_SVG);
+ if (icon_info != NULL) {
+ iconpart = load_picture_from_file (
+ "image/png", gtk_icon_info_get_filename (icon_info),
+ cancellable);
+ gtk_icon_info_free (icon_info);
+ }
+ if (iconpart) {
+ g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
+ write_contact_picture (iconpart, 16, buffer);
+ g_string_append (buffer, "</td>");
+
+ g_object_unref (iconpart);
+ }
+ }
+
+ g_string_append (buffer, "</tr></table>");
+}
+
+static gboolean
+emfe_headers_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GString *buffer;
+ gint bg_color;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ if (!part->part)
+ return FALSE;
+
+ buffer = g_string_new ("");
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
+ GdkColor white = { 0, G_MAXUINT16, G_MAXUINT16, G_MAXUINT16 };
+ bg_color = e_color_to_value (&white);
+ } else {
+ bg_color = e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY));
+ }
+
+ g_string_append_printf (
+ buffer,
+ "<div class=\"headers\" style=\"background: #%06x;\">"
+ "<table border=\"0\" width=\"100%%\" style=\"color: #%06x;\">\n"
+ "<tr><td valign=\"top\" width=\"16\">\n",
+ bg_color,
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter,
+ E_MAIL_FORMATTER_COLOR_HEADER)));
+
+ if (context->flags & E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSABLE) {
+ g_string_append_printf (buffer,
+ "<img src=\"evo-file://%s/%s\" class=\"navigable\" "
+ "id=\"__evo-collapse-headers-img\" />"
+ "</td><td>",
+ EVOLUTION_IMAGESDIR,
+ (context->flags & E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSED) ?
+ "plus.png" : "minus.png");
+
+ format_short_headers (formatter, buffer,
+ (CamelMedium *) part->part, context->flags, cancellable);
+ }
+
+ format_full_headers (formatter, buffer,
+ (CamelMedium *) part->part, context->flags, cancellable);
+
+ g_string_append (buffer, "</td></tr></table></div>");
+
+ camel_stream_write_string (stream, buffer->str, cancellable, NULL);
+
+ g_string_free (buffer, TRUE);
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_headers_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfe_headers_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfe_headers_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_headers_class_init (EMailFormatterHeadersClass *klass)
+{
+ e_mail_formatter_headers_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_headers_format;
+ iface->get_display_name = emfe_headers_get_display_name;
+ iface->get_description = emfe_headers_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_headers_mime_types;
+}
+
+static void
+e_mail_formatter_headers_init (EMailFormatterHeaders *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-image.c b/em-format/e-mail-formatter-image.c
new file mode 100644
index 0000000000..890e9f3dcc
--- /dev/null
+++ b/em-format/e-mail-formatter-image.c
@@ -0,0 +1,191 @@
+/*
+ * image-any.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-part-utils.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+static const gchar *formatter_mime_types[] = { "image/gif", "image/jpeg",
+ "image/png", "image/x-png",
+ "image/x-bmp", "image/bmp",
+ "image/svg", "image/x-cmu-raster",
+ "image/x-ico",
+ "image/x-portable-anymap",
+ "image/x-portable-bitmap",
+ "image/x-portable-graymap",
+ "image/x-portable-pixmap",
+ "image/x-xpixmap",
+ "image/jpg", "image/pjpeg",
+ "image/*", NULL };
+
+typedef struct _EMailFormatterImage {
+ GObject parent;
+} EMailFormatterImage;
+
+typedef struct _EMailFormatterImageClass {
+ GObjectClass parent_class;
+} EMailFormatterImageClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterImage,
+ e_mail_formatter_image,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static gboolean
+emfe_image_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *content;
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ CamelStream *raw_content;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part->part));
+ g_return_val_if_fail (dw, FALSE);
+
+ raw_content = camel_stream_mem_new ();
+ camel_data_wrapper_decode_to_stream_sync (dw, raw_content, cancellable, NULL);
+ ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (raw_content));
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
+
+ if (!e_mail_formatter_get_animate_images (formatter)) {
+
+ gchar *buff;
+ gsize len;
+
+ e_mail_part_animation_extract_frame (ba, &buff, &len);
+
+ camel_stream_write (stream, buff, len, cancellable, NULL);
+
+ g_free (buff);
+
+ } else {
+
+ camel_stream_write (
+ stream, (gchar *) ba->data,
+ ba->len, cancellable, NULL);
+ }
+
+ } else {
+
+ gchar *buffer;
+
+ if (!e_mail_formatter_get_animate_images (formatter)) {
+
+ gchar *buff;
+ gsize len;
+
+ e_mail_part_animation_extract_frame (ba, &buff, &len);
+
+ content = g_base64_encode ((guchar *) buff, len);
+ g_free (buff);
+
+ } else {
+ content = g_base64_encode ((guchar *) ba->data, ba->len);
+ }
+
+ /* The image is already base64-encrypted so we can directly
+ * paste it to the output */
+ buffer = g_strdup_printf (
+ "<img src=\"data:%s;base64,%s\" style=\"max-width: 100%%;\" />",
+ part->mime_type ? part->mime_type : "image/*", content);
+
+ camel_stream_write_string (stream, buffer, cancellable, NULL);
+ g_free (buffer);
+ g_free (content);
+ }
+
+ g_object_unref (raw_content);
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_image_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Regular Image");
+}
+
+static const gchar *
+emfe_image_get_description (EMailFormatterExtension *extension)
+{
+ return _("Display part as an image");
+}
+
+static const gchar **
+emfe_image_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_image_class_init (EMailFormatterImageClass *klass)
+{
+ e_mail_formatter_image_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_image_format;
+ iface->get_display_name = emfe_image_get_display_name;
+ iface->get_description = emfe_image_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_image_mime_types;
+}
+
+static void
+e_mail_formatter_image_init (EMailFormatterImage *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-message-rfc822.c b/em-format/e-mail-formatter-message-rfc822.c
new file mode 100644
index 0000000000..558579b00a
--- /dev/null
+++ b/em-format/e-mail-formatter-message-rfc822.c
@@ -0,0 +1,276 @@
+/*
+ * e-mail-formatter-message-rfc822.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-part-list.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+static const gchar* formatter_mime_types[] = { "message/rfc822",
+ "application/vnd.evolution.rfc822.end",
+ NULL };
+
+typedef struct _EMailFormatterMessageRFC822 {
+ GObject parent;
+} EMailFormatterMessageRFC822;
+
+typedef struct _EMailFormatterMessageRFC822Class {
+ GObjectClass parent_class;
+} EMailFormatterMessageRFC822Class;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterMessageRFC822,
+ e_mail_formatter_message_rfc822,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static gboolean
+emfe_message_rfc822_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
+ GSList *iter;
+ gchar *header, *end;
+
+ header = e_mail_formatter_get_html_header (formatter);
+ camel_stream_write_string (stream, header, cancellable, NULL);
+ g_free (header);
+
+ /* Print content of the message normally */
+ context->mode = E_MAIL_FORMATTER_MODE_NORMAL;
+
+ iter = e_mail_part_list_get_iter (context->parts, part->id);
+
+ end = g_strconcat (part->id, ".end", NULL);
+ for (iter = iter->next; iter; iter = g_slist_next (iter)) {
+ EMailPart * p = iter->data;
+ if (!p)
+ continue;
+
+ /* Check for nested rfc822 messages */
+ if (g_str_has_suffix (p->id, ".rfc822")) {
+ gchar *sub_end = g_strconcat (p->id, ".end", NULL);
+
+ while (iter) {
+ p = iter->data;
+ if (!p) {
+ iter = iter->next;
+ continue;
+ }
+
+ if (g_strcmp0 (p->id, sub_end) == 0) {
+ break;
+ }
+
+ iter = iter->next;
+ }
+ g_free (sub_end);
+ continue;
+ }
+ if ((g_strcmp0 (p->id, end) == 0))
+ break;
+
+ if (p->is_hidden)
+ continue;
+
+ e_mail_formatter_format_as (
+ formatter, context, p,
+ stream, NULL, cancellable);
+
+ }
+
+ g_free (end);
+
+ context->mode = E_MAIL_FORMATTER_MODE_RAW;
+
+ camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
+
+ } else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
+
+ GSList *iter;
+ gchar *end;
+
+ /* Part is EMailPartAttachment */
+ iter = e_mail_part_list_get_iter (context->parts, part->id);
+ iter = g_slist_next (iter);
+
+ if (!iter || !iter->next || !iter->data)
+ return FALSE;
+
+ part = iter->data;
+ end = g_strconcat (part->id, ".end", NULL);
+
+ for (iter = iter->next; iter; iter = g_slist_next (iter)) {
+ EMailPart * p = iter->data;
+ if (!p)
+ continue;
+
+ /* Skip attachment bar */
+ if (g_str_has_suffix (part->id, ".attachment-bar"))
+ continue;
+
+ /* Check for nested rfc822 messages */
+ if (g_str_has_suffix (p->id, ".rfc822")) {
+ gchar *sub_end = g_strconcat (p->id, ".end", NULL);
+
+ while (iter) {
+ p = iter->data;
+ if (!p) {
+ iter = iter->next;
+ continue;
+ }
+
+ if (g_strcmp0 (p->id, sub_end) == 0) {
+ break;
+ }
+
+ iter = iter->next;
+ }
+ g_free (sub_end);
+ continue;
+ }
+
+ if ((g_strcmp0 (p->id, end) == 0))
+ break;
+
+ if (p->is_hidden)
+ continue;
+
+ e_mail_formatter_format_as (
+ formatter, context, p,
+ stream, NULL, cancellable);
+ }
+
+ g_free (end);
+
+ } else {
+ gchar *str;
+ gchar *uri;
+
+ EMailPart *p;
+ GSList *iter;
+
+ iter = e_mail_part_list_get_iter (context->parts, part->id);
+ if (!iter || !iter->next)
+ return FALSE;
+
+ p = iter->data;
+
+ uri = e_mail_part_build_uri (context->folder, context->message_uid,
+ "part_id", G_TYPE_STRING, p->id,
+ "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW,
+ "headers_collapsable", G_TYPE_INT, 0,
+ NULL);
+
+ str = g_strdup_printf (
+ "<div class=\"part-container\" style=\"border-color: #%06x; "
+ "background-color: #%06x;\">\n"
+ "<iframe width=\"100%%\" height=\"10\""
+ " id=\"%s.iframe\" "
+ " frameborder=\"0\" src=\"%s\" name=\"%s\"></iframe>"
+ "</div>",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY)),
+ part->id, uri, part->id);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+ g_free (uri);
+ }
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_message_rfc822_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("RFC822 message");
+}
+
+static const gchar *
+emfe_message_rfc822_get_description (EMailFormatterExtension *extension)
+{
+ return _("Format part as an RFC822 message");
+}
+
+static const gchar **
+emfe_message_rfc822_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_message_rfc822_class_init (EMailFormatterMessageRFC822Class *klass)
+{
+ e_mail_formatter_message_rfc822_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_message_rfc822_format;
+ iface->get_display_name = emfe_message_rfc822_get_display_name;
+ iface->get_description = emfe_message_rfc822_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_message_rfc822_mime_types;
+}
+
+static void
+e_mail_formatter_message_rfc822_init (EMailFormatterMessageRFC822 *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-print-headers.c b/em-format/e-mail-formatter-print-headers.c
new file mode 100644
index 0000000000..86fc85b063
--- /dev/null
+++ b/em-format/e-mail-formatter-print-headers.c
@@ -0,0 +1,258 @@
+/*
+ * e-mail-formatter-print-headers.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-formatter-utils.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <libemail-engine/e-mail-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailFormatterPrintHeaders {
+ GObject parent;
+} EMailFormatterPrintHeaders;
+
+typedef struct _EMailFormatterPrintHeadersClass {
+ GObjectClass parent_class;
+} EMailFormatterPrintHeadersClass;
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.headers", NULL };
+
+static void e_mail_formatter_print_formatter_extension_interface_init
+ (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_print_mail_extension_interface_init
+ (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterPrintHeaders,
+ e_mail_formatter_print_headers,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_print_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_print_formatter_extension_interface_init))
+
+static gboolean
+emfpe_headers_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ struct _camel_header_raw raw_header;
+ GString *str, *tmp;
+ gchar *subject;
+ const gchar *buf;
+ GSList *parts_iter;
+ GList *iter;
+ gint attachments_count;
+ gchar *part_id_prefix;
+ const GQueue *headers;
+
+ buf = camel_medium_get_header (CAMEL_MEDIUM (part->part), "subject");
+ subject = camel_header_decode_string (buf, "UTF-8");
+ str = g_string_new ("");
+ g_string_append_printf (str, "<h1>%s</h1>\n", subject);
+ g_free (subject);
+
+ g_string_append (
+ str,
+ "<table border=\"0\" cellspacing=\"5\" "
+ "cellpadding=\"0\" class=\"printing-header\">\n");
+
+ headers = e_mail_formatter_get_headers (formatter);
+ for (iter = headers->head; iter; iter = iter->next) {
+
+ EMailFormatterHeader *header = iter->data;
+ raw_header.name = header->name;
+
+ /* Skip 'Subject' header, it's already displayed. */
+ if (g_ascii_strncasecmp (header->name, "Subject", 7) == 0)
+ continue;
+
+ if (header->value && *header->value) {
+ raw_header.value = header->value;
+ e_mail_formatter_format_header (formatter, str,
+ CAMEL_MEDIUM (part->part), &raw_header,
+ header->flags | E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS,
+ "UTF-8");
+ } else {
+ raw_header.value = g_strdup (camel_medium_get_header (
+ CAMEL_MEDIUM (context->message), header->name));
+
+ if (raw_header.value && *raw_header.value) {
+ e_mail_formatter_format_header (formatter, str,
+ CAMEL_MEDIUM (part->part), &raw_header,
+ header->flags | E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS,
+ "UTF-8");
+ }
+
+ if (raw_header.value)
+ g_free (raw_header.value);
+ }
+ }
+
+ /* Get prefix of this PURI */
+ part_id_prefix = g_strndup (part->id, g_strrstr (part->id, ".") - part->id);
+
+ /* Add encryption/signature header */
+ raw_header.name = _("Security");
+ tmp = g_string_new ("");
+ /* Find first secured part. */
+ for (parts_iter = context->parts; parts_iter; parts_iter = parts_iter->next) {
+
+ EMailPart *mail_part = parts_iter->data;
+ if (mail_part == NULL)
+ continue;
+
+ if (mail_part->validity_type == 0)
+ continue;
+
+ if (!g_str_has_prefix (mail_part->id, part_id_prefix))
+ continue;
+
+ if ((mail_part->validity_type & E_MAIL_PART_VALIDITY_PGP) &&
+ (mail_part->validity_type & E_MAIL_PART_VALIDITY_SIGNED)) {
+ g_string_append (tmp, _("GPG signed"));
+ }
+ if ((mail_part->validity_type & E_MAIL_PART_VALIDITY_PGP) &&
+ (mail_part->validity_type & E_MAIL_PART_VALIDITY_ENCRYPTED)) {
+ if (tmp->len > 0) g_string_append (tmp, ", ");
+ g_string_append (tmp, _("GPG encrpyted"));
+ }
+ if ((mail_part->validity_type & E_MAIL_PART_VALIDITY_SMIME) &&
+ (mail_part->validity_type & E_MAIL_PART_VALIDITY_SIGNED)) {
+
+ if (tmp->len > 0) g_string_append (tmp, ", ");
+ g_string_append (tmp, _("S/MIME signed"));
+ }
+ if ((mail_part->validity_type & E_MAIL_PART_VALIDITY_SMIME) &&
+ (mail_part->validity_type & E_MAIL_PART_VALIDITY_ENCRYPTED)) {
+
+ if (tmp->len > 0) g_string_append (tmp, ", ");
+ g_string_append (tmp, _("S/MIME encrpyted"));
+ }
+
+ break;
+ }
+
+ if (tmp->len > 0) {
+ raw_header.value = tmp->str;
+ e_mail_formatter_format_header (
+ formatter, str, CAMEL_MEDIUM (part->part), &raw_header,
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD |
+ E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS, "UTF-8");
+ }
+ g_string_free (tmp, TRUE);
+
+ /* Count attachments and display the number as a header */
+ attachments_count = 0;
+
+ for (parts_iter = context->parts; parts_iter; parts_iter = parts_iter->next) {
+
+ EMailPart *mail_part = parts_iter->data;
+ if (!mail_part)
+ continue;
+
+ if (!g_str_has_prefix (mail_part->id, part_id_prefix))
+ continue;
+
+ if (mail_part->is_attachment && !mail_part->cid &&
+ !mail_part->is_hidden) {
+ attachments_count++;
+ }
+ }
+
+ if (attachments_count > 0) {
+ raw_header.name = _("Attachments");
+ raw_header.value = g_strdup_printf ("%d", attachments_count);
+ e_mail_formatter_format_header (
+ formatter, str, CAMEL_MEDIUM (part->part), &raw_header,
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD |
+ E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS, "UTF-8");
+ g_free (raw_header.value);
+ }
+
+ g_string_append (str, "</table>");
+
+ camel_stream_write_string (stream, str->str, cancellable, NULL);
+ g_string_free (str, TRUE);
+ g_free (part_id_prefix);
+
+ return TRUE;
+}
+
+static const gchar *
+emfpe_headers_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfpe_headers_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfpe_headers_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_print_headers_class_init (EMailFormatterPrintHeadersClass *klass)
+{
+ e_mail_formatter_print_headers_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_print_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfpe_headers_format;
+ iface->get_display_name = emfpe_headers_get_display_name;
+ iface->get_description = emfpe_headers_get_description;
+}
+
+static void
+e_mail_formatter_print_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfpe_headers_mime_types;
+}
+
+static void
+e_mail_formatter_print_headers_init (EMailFormatterPrintHeaders *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-print.c b/em-format/e-mail-formatter-print.c
new file mode 100644
index 0000000000..a9109a647e
--- /dev/null
+++ b/em-format/e-mail-formatter-print.c
@@ -0,0 +1,266 @@
+/*
+ * e-mail-formatter-print.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter-print.h"
+
+#include <camel/camel.h>
+
+#include "e-mail-format-extensions.h"
+#include "e-mail-part-attachment.h"
+#include "e-mail-formatter-extension.h"
+#include "e-mail-formatter-utils.h"
+#include "e-mail-part.h"
+
+#include <gdk/gdk.h>
+#include <glib/gi18n.h>
+
+static gpointer e_mail_formatter_print_parent_class = 0;
+
+static void
+write_attachments_list (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ GSList *attachments,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GString *str;
+ GSList *iter;
+
+ if (!attachments)
+ return;
+
+ str = g_string_new (
+ "<table border=\"0\" cellspacing=\"5\" cellpadding=\"0\" "
+ "class=\"attachments-list\" >\n");
+ g_string_append_printf (str,
+ "<tr><th colspan=\"2\"><h1>%s</h1></td></tr>\n"
+ "<tr><th>%s</th><th>%s</th></tr>\n",
+ _("Attachments"), _("Name"), _("Size"));
+
+ for (iter = attachments; iter; iter = iter->next) {
+ EMailPartAttachment *part = iter->data;
+ EAttachment *attachment;
+ GFileInfo *fi;
+ gchar *name, *size;
+
+ if (!part)
+ continue;
+
+ attachment = part->attachment;
+ fi = e_attachment_get_file_info (attachment);
+ if (!fi)
+ continue;
+
+ if (e_attachment_get_description (attachment) &&
+ *e_attachment_get_description (attachment)) {
+ name = g_strdup_printf ("%s (%s)",
+ e_attachment_get_description (attachment),
+ g_file_info_get_display_name (fi));
+ } else {
+ name = g_strdup (g_file_info_get_display_name (fi));
+ }
+
+ size = g_format_size (g_file_info_get_size (fi));
+
+ g_string_append_printf (str, "<tr><td>%s</td><td>%s</td></tr>\n",
+ name, size);
+
+ g_free (name);
+ g_free (size);
+ }
+
+ g_string_append (str, "</table>\n");
+
+ camel_stream_write_string (stream, str->str, cancellable, NULL);
+ g_string_free (str, TRUE);
+}
+
+static void
+mail_formatter_print_run (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GSList *iter;
+ GSList *attachments;
+
+ context->mode = E_MAIL_FORMATTER_MODE_PRINTING;
+
+ camel_stream_write_string (stream,
+ "<!DOCTYPE HTML>\n<html>\n"
+ "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\" />\n"
+ "<title>Evolution Mail Display</title>\n"
+ "<link type=\"text/css\" rel=\"stylesheet\" media=\"print\" "
+ "href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview-print.css\" />\n"
+ "</head>\n"
+ "<body style=\"background: #FFF; color: #000;\">",
+ cancellable, NULL);
+
+ attachments = NULL;
+ for (iter = context->parts; iter; iter = g_slist_next (iter)) {
+
+ EMailPart *part;
+ gboolean ok;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+
+ part = iter->data;
+ if (!part)
+ continue;
+
+ if (part->is_hidden && !part->is_error) {
+ if (g_str_has_suffix (part->id, ".rfc822")) {
+ iter = e_mail_formatter_find_rfc822_end_iter (iter);
+ }
+
+ continue;
+ }
+
+ if (!part->mime_type)
+ continue;
+
+ if (part->is_attachment) {
+ if (part->cid != NULL)
+ continue;
+
+ attachments = g_slist_append (attachments, part);
+ }
+
+ ok = e_mail_formatter_format_as (
+ formatter, context, part, stream,
+ part->mime_type, cancellable);
+
+ /* If the written part was message/rfc822 then
+ * jump to the end of the message, because content
+ * of the whole message has been formatted by
+ * message_rfc822 formatter */
+ if (ok && g_str_has_suffix (part->id, ".rfc822")) {
+ iter = e_mail_formatter_find_rfc822_end_iter (iter);
+
+ continue;
+ }
+ }
+
+ write_attachments_list (formatter, context, attachments, stream, cancellable);
+
+ camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
+}
+
+static void
+mail_formatter_set_style (EMailFormatter *formatter,
+ GtkStyle *style,
+ GtkStateType state)
+{
+ EMailFormatterClass *formatter_class;
+
+ /* White background */
+ GdkColor body_color = { 0, G_MAXUINT16, G_MAXUINT16, G_MAXUINT16 };
+ /* Black text */
+ GdkColor text_color = { 0, 0, 0, 0 };
+
+ g_object_freeze_notify (G_OBJECT (formatter));
+
+ /* Set the other colors */
+ formatter_class = E_MAIL_FORMATTER_CLASS (e_mail_formatter_print_parent_class);
+ formatter_class->set_style (formatter, style, state);
+
+ e_mail_formatter_set_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME, &body_color);
+ e_mail_formatter_set_color (
+ formatter, E_MAIL_FORMATTER_COLOR_CONTENT, &body_color);
+ e_mail_formatter_set_color (
+ formatter, E_MAIL_FORMATTER_COLOR_TEXT, &text_color);
+
+ g_object_thaw_notify (G_OBJECT (formatter));
+}
+
+static void
+e_mail_formatter_print_init (EMailFormatterPrint *formatter)
+{
+
+}
+
+static void
+e_mail_formatter_print_finalize (GObject *object)
+{
+ /* Chain up to parent's finalize() */
+ G_OBJECT_CLASS (e_mail_formatter_print_parent_class)->finalize (object);
+}
+
+static void
+e_mail_formatter_print_class_init (EMailFormatterPrintClass *klass)
+{
+ GObjectClass *object_class;
+ EMailFormatterClass *formatter_class;
+
+ e_mail_formatter_print_parent_class = g_type_class_peek_parent (klass);
+
+ formatter_class = E_MAIL_FORMATTER_CLASS (klass);
+ formatter_class->run = mail_formatter_print_run;
+ formatter_class->set_style = mail_formatter_set_style;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = e_mail_formatter_print_finalize;
+}
+
+static void
+e_mail_formatter_print_base_init (EMailFormatterPrintClass *klass)
+{
+ e_mail_formatter_print_internal_extensions_load (
+ E_MAIL_EXTENSION_REGISTRY (
+ E_MAIL_FORMATTER_CLASS (klass)->extension_registry));
+
+ E_MAIL_FORMATTER_CLASS (klass)->text_html_flags =
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
+}
+
+EMailFormatter *
+e_mail_formatter_print_new (void)
+{
+ return g_object_new (E_TYPE_MAIL_FORMATTER_PRINT, NULL);
+}
+
+GType
+e_mail_formatter_print_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EMailFormatterClass),
+ (GBaseInitFunc) e_mail_formatter_print_base_init,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) e_mail_formatter_print_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailFormatterPrint),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_mail_formatter_print_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (E_TYPE_MAIL_FORMATTER,
+ "EMailFormatterPrint", &type_info, 0);
+ }
+
+ return type;
+}
+
diff --git a/em-format/e-mail-formatter-print.h b/em-format/e-mail-formatter-print.h
new file mode 100644
index 0000000000..1783cc068a
--- /dev/null
+++ b/em-format/e-mail-formatter-print.h
@@ -0,0 +1,63 @@
+/*
+ * e-mail-formatter-print.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_PRINT_H_
+#define E_MAIL_FORMATTER_PRINT_H_
+
+#include <em-format/e-mail-formatter.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_FORMATTER_PRINT \
+ (e_mail_formatter_print_get_type ())
+#define E_MAIL_FORMATTER_PRINT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_FORMATTER_PRINT, EMailFormatterPrint))
+#define E_MAIL_FORMATTER_PRINT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_FORMATTER_PRINT, EMailFormatterPrintClass))
+#define E_IS_MAIL_FORMATTER_PRINT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_FORMATTER_PRINT))
+#define E_IS_MAIL_FORMATTER_PRINT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_FORMATTER_PRINT))
+#define E_MAIL_FORMATTER_PRINT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_FORMATTER_PRINT, EMailFormatterPrintClass))
+
+G_BEGIN_DECLS;
+
+typedef struct _EMailFormatterPrint EMailFormatterPrint;
+typedef struct _EMailFormatterPrintClass EMailFormatterPrintClass;
+typedef struct _EMailFormatterPrintContext EMailFormatterPrintContext;
+
+struct _EMailFormatterPrint {
+ EMailFormatter parent;
+};
+
+struct _EMailFormatterPrintClass {
+ EMailFormatterClass parent_class;
+};
+
+GType e_mail_formatter_print_get_type (void);
+
+EMailFormatter * e_mail_formatter_print_new (void);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_PRINT_H_ */
diff --git a/em-format/e-mail-formatter-quote-attachment.c b/em-format/e-mail-formatter-quote-attachment.c
new file mode 100644
index 0000000000..590f23ee6d
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-attachment.c
@@ -0,0 +1,163 @@
+/*
+ * e-mail-formatter-qoute-attachment.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+#include "e-mail-part-attachment.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#define d(x)
+
+typedef struct _EMailFormatterQuoteAttachment {
+ GObject parent;
+} EMailFormatterQuoteAttachment;
+
+typedef struct _EMailFormatterQuoteAttachmentClass {
+ GObjectClass parent_class;
+} EMailFormatterQuoteAttachmentClass;
+
+static void e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteAttachment,
+ e_mail_formatter_quote_attachment,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interface_init)
+)
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.attachment",
+ NULL };
+
+static gboolean
+emfqe_attachment_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *text, *html;
+ guint32 text_format_flags;
+ EMailPartAttachment *empa;
+ EMailPart *att_part;
+ GSList *iter;
+
+ empa = E_MAIL_PART_ATTACHMENT (part);
+
+ if (!empa->attachment_view_part_id)
+ return FALSE;
+
+ iter = e_mail_part_list_get_iter (
+ context->parts, empa->attachment_view_part_id);
+ if (!iter || !iter->data)
+ return FALSE;
+
+ att_part = iter->data;
+
+ camel_stream_write_string (stream, "<br><br>", cancellable, NULL);
+
+ text_format_flags =
+ e_mail_formatter_get_text_format_flags (formatter);
+ text = e_mail_part_describe (part->part,
+ empa ? empa->snoop_mime_type : part->mime_type);
+
+ html = camel_text_to_html (
+ text,
+ text_format_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS,
+ 0);
+ camel_stream_write_string (stream, html, cancellable, NULL);
+ camel_stream_write_string (stream, "<br>", cancellable, NULL);
+ g_free (html);
+ g_free (text);
+
+ camel_stream_write_string (stream,
+ "<!--+GtkHTML:<DATA class=\"ClueFlow\" "
+ "key=\"orig\" value=\"1\">-->\n"
+ "<blockquote type=cite>\n", cancellable, NULL);
+
+ e_mail_formatter_format_as (
+ formatter, context, att_part, stream, NULL, cancellable);
+
+ camel_stream_write_string (stream,
+ "</blockquote><!--+GtkHTML:"
+ "<DATA class=\"ClueFlow\" clear=\"orig\">-->",
+ cancellable, NULL);
+
+ return TRUE;
+}
+
+static const gchar *
+emfqe_attachment_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfqe_attachment_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfqe_attachment_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_attachment_class_init (EMailFormatterQuoteAttachmentClass *klass)
+{
+ e_mail_formatter_quote_attachment_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfqe_attachment_format;
+ iface->get_display_name = emfqe_attachment_get_display_name;
+ iface->get_description = emfqe_attachment_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfqe_attachment_mime_types;
+}
+
+static void
+e_mail_formatter_quote_attachment_init (EMailFormatterQuoteAttachment *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote-headers.c b/em-format/e-mail-formatter-quote-headers.c
new file mode 100644
index 0000000000..f1b2b2e61f
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-headers.c
@@ -0,0 +1,162 @@
+/*
+ * e-mail-formatter-quote-headers.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-formatter-utils.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <libemail-engine/e-mail-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailFormatterQuoteHeaders {
+ GObject parent;
+} EMailFormatterQuoteHeaders;
+
+typedef struct _EMailFormatterQuoteHeadersClass {
+ GObjectClass parent_class;
+} EMailFormatterQuoteHeadersClass;
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.headers", NULL };
+
+static void e_mail_formatter_quote_formatter_extension_interface_init
+ (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init
+ (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteHeaders,
+ e_mail_formatter_quote_headers,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interface_init))
+
+static gboolean
+emqfe_headers_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelContentType *ct;
+ const gchar *charset;
+ GList *iter;
+ GString *buffer;
+ const GQueue *default_headers;
+
+ if (!part)
+ return FALSE;
+
+ ct = camel_mime_part_get_content_type ((CamelMimePart *) part->part);
+ charset = camel_content_type_param (ct, "charset");
+ charset = camel_iconv_charset_name (charset);
+
+ buffer = g_string_new ("");
+
+ /* dump selected headers */
+ default_headers = e_mail_formatter_get_headers (formatter);
+ for (iter = default_headers->head; iter; iter = iter->next) {
+ struct _camel_header_raw *raw_header;
+ EMailFormatterHeader *h = iter->data;
+ guint32 flags;
+
+ flags = h->flags & ~E_MAIL_FORMATTER_HEADER_FLAG_HTML;
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE;
+
+ for (raw_header = part->part->headers; raw_header; raw_header = raw_header->next) {
+
+ if (g_strcmp0 (raw_header->name, h->name) == 0) {
+
+ e_mail_formatter_format_header (
+ formatter, buffer, (CamelMedium *) part->part,
+ raw_header, flags, charset);
+
+ g_string_append (buffer, "<br>\n");
+ break;
+ }
+ }
+ }
+ g_string_append (buffer, "<br>\n");
+
+ camel_stream_write_string (stream, buffer->str, cancellable, NULL);
+
+ g_string_free (buffer, TRUE);
+
+ return TRUE;
+}
+
+static const gchar *
+emqfe_headers_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emqfe_headers_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emqfe_headers_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_headers_class_init (EMailFormatterQuoteHeadersClass *klass)
+{
+ e_mail_formatter_quote_headers_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emqfe_headers_format;
+ iface->get_display_name = emqfe_headers_get_display_name;
+ iface->get_description = emqfe_headers_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emqfe_headers_mime_types;
+}
+
+static void
+e_mail_formatter_quote_headers_init (EMailFormatterQuoteHeaders *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote-message-rfc822.c b/em-format/e-mail-formatter-quote-message-rfc822.c
new file mode 100644
index 0000000000..847686240f
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-message-rfc822.c
@@ -0,0 +1,188 @@
+/*
+ * e-mail-formatter-quote-message-rfc822.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter-quote.h>
+#include <em-format/e-mail-part-list.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+static const gchar* formatter_mime_types[] = { "message/rfc822",
+ "application/vnd.evolution.rfc822.end",
+ NULL };
+
+typedef struct _EMailFormatterQuoteMessageRFC822 {
+ GObject parent;
+} EMailFormatterQuoteMessageRFC822;
+
+typedef struct _EMailFormatterQuoteMessageRFC822Class {
+ GObjectClass parent_class;
+} EMailFormatterQuoteMessageRFC822Class;
+
+static void e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteMessageRFC822,
+ e_mail_formatter_quote_message_rfc822,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interface_init));
+
+static gboolean
+emfqe_message_rfc822_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GSList *iter;
+ gchar *header, *end;
+ EMailFormatterQuoteContext *qc = (EMailFormatterQuoteContext *) context;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ header = e_mail_formatter_get_html_header (formatter);
+ camel_stream_write_string (stream, header, cancellable, NULL);
+ g_free (header);
+
+ iter = e_mail_part_list_get_iter (context->parts, part->id);
+
+ end = g_strconcat (part->id, ".end", NULL);
+ for (iter = iter->next; iter; iter = iter->next) {
+ EMailPart * p = iter->data;
+ if (!p)
+ continue;
+
+ /* Skip attachment bar */
+ if (g_str_has_suffix (p->id, ".attachment-bar"))
+ continue;
+
+ if (g_str_has_suffix (p->id, ".headers.")) {
+ if (qc->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS) {
+ e_mail_formatter_format_as (
+ formatter, context, part, stream,
+ "application/vnd.evolution.headers",
+ cancellable);
+ }
+
+ continue;
+ }
+
+ /* Check for nested rfc822 messages */
+ if (g_str_has_suffix (p->id, ".rfc822")) {
+ gchar *sub_end = g_strconcat (p->id, ".end", NULL);
+
+ while (iter) {
+ p = iter->data;
+ if (!p) {
+ iter = iter->next;
+ continue;
+ }
+
+ if (g_strcmp0 (p->id, sub_end) == 0) {
+ break;
+ }
+
+ iter = iter->next;
+ }
+ g_free (sub_end);
+ continue;
+ }
+ if ((g_strcmp0 (p->id, end) == 0))
+ break;
+
+ if (p->is_hidden)
+ continue;
+
+ e_mail_formatter_format_as (
+ formatter, context, p,
+ stream, NULL, cancellable);
+
+ }
+
+ g_free (end);
+
+ camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
+
+ return TRUE;
+}
+
+static const gchar *
+emfqe_message_rfc822_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfqe_message_rfc822_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfqe_message_rfc822_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_message_rfc822_class_init (EMailFormatterQuoteMessageRFC822Class *klass)
+{
+ e_mail_formatter_quote_message_rfc822_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfqe_message_rfc822_format;
+ iface->get_display_name = emfqe_message_rfc822_get_display_name;
+ iface->get_description = emfqe_message_rfc822_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfqe_message_rfc822_mime_types;
+}
+
+static void
+e_mail_formatter_quote_message_rfc822_init (EMailFormatterQuoteMessageRFC822 *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote-text-enriched.c b/em-format/e-mail-formatter-quote-text-enriched.c
new file mode 100644
index 0000000000..e48154edd8
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-text-enriched.c
@@ -0,0 +1,141 @@
+/*
+ * e-mail-formatter-quote-text-enriched.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+static const gchar *formatter_mime_types[] = { "text/enriched",
+ "text/richtext",
+ NULL };
+
+typedef struct _EMailFormatterQuoteTextEnriched {
+ GObject parent;
+} EMailFormatterQuoteTextEnriched;
+
+typedef struct _EMailFormatterQuoteTextEnrichedClass {
+ GObjectClass parent_class;
+} EMailFormatterQuoteTextEnrichedClass;
+
+static void e_mail_formatter_quote_formatter_extension_interace_init
+ (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init
+ (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteTextEnriched,
+ e_mail_formatter_quote_text_enriched,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interace_init));
+
+static gboolean
+emqfe_text_enriched_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelStream *filtered_stream;
+ CamelMimeFilter *enriched;
+ guint32 camel_flags = 0;
+
+ if (g_strcmp0 (part->mime_type, "text/richtext") == 0) {
+ camel_flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT;
+ camel_stream_write_string (
+ stream, "\n<!-- text/richtext -->\n",
+ cancellable, NULL);
+ } else {
+ camel_stream_write_string (
+ stream, "\n<!-- text/enriched -->\n",
+ cancellable, NULL);
+ }
+
+ enriched = camel_mime_filter_enriched_new (camel_flags);
+ filtered_stream = camel_stream_filter_new (stream);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), enriched);
+ g_object_unref (enriched);
+
+ camel_stream_write_string (stream, "<br><hr><br>", cancellable, NULL);
+ e_mail_formatter_format_text (formatter, part, filtered_stream, cancellable);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ return TRUE;
+}
+
+static const gchar *
+emqfe_text_enriched_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Richtext");
+}
+
+static const gchar *
+emqfe_text_enriched_get_description (EMailFormatterExtension *extension)
+{
+ return _("Display part as enriched text");
+}
+
+static const gchar **
+emqfe_text_enriched_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_enriched_class_init (EMailFormatterQuoteTextEnrichedClass *klass)
+{
+ e_mail_formatter_quote_text_enriched_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interace_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emqfe_text_enriched_format;
+ iface->get_display_name = emqfe_text_enriched_get_display_name;
+ iface->get_description = emqfe_text_enriched_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emqfe_text_enriched_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_enriched_init (EMailFormatterQuoteTextEnriched *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote-text-html.c b/em-format/e-mail-formatter-quote-text-html.c
new file mode 100644
index 0000000000..d4ef287878
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-text-html.c
@@ -0,0 +1,143 @@
+/*
+ * e-mail-formatter-quote-text-html.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter-quote.h>
+#include <em-format/e-mail-stripsig-filter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <string.h>
+
+static const gchar *formatter_mime_types[] = { "text/html", NULL };
+
+typedef struct _EMailFormatterQuoteTextHTML {
+ GObject parent;
+} EMailFormatterQuoteTextHTML;
+
+typedef struct _EMailFormatterQuoteTextHTMLClass {
+ GObjectClass parent_class;
+} EMailFormatterQuoteTextHTMLClass;
+
+static void e_mail_formatter_quote_formatter_extension_interface_init
+ (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init
+ (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteTextHTML,
+ e_mail_formatter_quote_text_html,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interface_init));
+
+static gboolean
+emqfe_text_html_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ EMailFormatterQuoteContext *qf_context;
+
+ qf_context = (EMailFormatterQuoteContext *) context;
+
+ camel_stream_write_string (
+ stream, "\n<!-- text/html -->\n", cancellable, NULL);
+
+ if ((qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG) == 0) {
+ CamelMimeFilter *sig_strip;
+ CamelStream *filtered_stream;
+
+ filtered_stream = camel_stream_filter_new (stream);
+
+ sig_strip = e_mail_stripsig_filter_new (FALSE);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), sig_strip);
+ g_object_unref (sig_strip);
+
+ e_mail_formatter_format_text (
+ formatter, part, filtered_stream, cancellable);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+ } else {
+ e_mail_formatter_format_text (
+ formatter, part, stream, cancellable);
+ }
+
+ return TRUE;
+}
+
+static const gchar *
+emqfe_text_html_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("HTML");
+}
+
+static const gchar *
+emqfe_text_html_get_description (EMailFormatterExtension *extension)
+{
+ return _("Format part as HTML");
+}
+
+static const gchar **
+emqfe_text_html_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_html_class_init (EMailFormatterQuoteTextHTMLClass *klass)
+{
+ e_mail_formatter_quote_text_html_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emqfe_text_html_format;
+ iface->get_display_name = emqfe_text_html_get_display_name;
+ iface->get_description = emqfe_text_html_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emqfe_text_html_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_html_init (EMailFormatterQuoteTextHTML *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote-text-plain.c b/em-format/e-mail-formatter-quote-text-plain.c
new file mode 100644
index 0000000000..062e945fea
--- /dev/null
+++ b/em-format/e-mail-formatter-quote-text-plain.c
@@ -0,0 +1,162 @@
+/*
+ * e-mail-formatter-quote-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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter-quote.h>
+#include <em-format/e-mail-part-utils.h>
+#include <em-format/e-mail-stripsig-filter.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+static const gchar *formatter_mime_types[] = { "text/plain", NULL };
+
+typedef struct _EMailFormatterQuoteTextPlain {
+ GObject parent;
+} EMailFormatterQuoteTextPlain;
+
+typedef struct _EMailFormatterQuoteTextPlainClass {
+ GObjectClass parent_class;
+} EMailFormatterQuoteTextPlainClass;
+
+static void e_mail_formatter_quote_formatter_extension_interface_init
+ (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_quote_mail_extension_interface_init
+ (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterQuoteTextPlain,
+ e_mail_formatter_quote_text_plain,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_quote_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_quote_formatter_extension_interface_init));
+
+static gboolean
+emqfe_text_plain_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelStream *filtered_stream;
+ CamelMimeFilter *html_filter;
+ CamelMimeFilter *sig_strip;
+ CamelContentType *type;
+ EMailFormatterQuoteContext *qf_context;
+ const gchar *format;
+ guint32 rgb = 0x737373, text_flags;
+
+ if (!part->part)
+ return FALSE;
+
+ qf_context = (EMailFormatterQuoteContext *) context;
+
+ text_flags = CAMEL_MIME_FILTER_TOHTML_PRE |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
+
+ if (e_mail_formatter_get_mark_citations (formatter)) {
+ text_flags |= CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
+ }
+
+ /* Check for RFC 2646 flowed text. */
+ type = camel_mime_part_get_content_type (part->part);
+ if (camel_content_type_is(type, "text", "plain")
+ && (format = camel_content_type_param(type, "format"))
+ && !g_ascii_strcasecmp(format, "flowed"))
+ text_flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED;
+
+ filtered_stream = camel_stream_filter_new (stream);
+
+ if ((qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG) == 0) {
+ sig_strip = e_mail_stripsig_filter_new (TRUE);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), sig_strip);
+ g_object_unref (sig_strip);
+ }
+
+ html_filter = camel_mime_filter_tohtml_new (text_flags, rgb);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), html_filter);
+ g_object_unref (html_filter);
+
+ e_mail_formatter_format_text (
+ formatter, part, filtered_stream, cancellable);
+
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ return TRUE;
+}
+
+static const gchar *
+emqfe_text_plain_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Plain Text");
+}
+
+static const gchar *
+emqfe_text_plain_get_description (EMailFormatterExtension *extension)
+{
+ return _("Format part as plain text");
+}
+
+static const gchar **
+emqfe_text_plain_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_plain_class_init (EMailFormatterQuoteTextPlainClass *klass)
+{
+ e_mail_formatter_quote_text_plain_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_quote_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emqfe_text_plain_format;
+ iface->get_display_name = emqfe_text_plain_get_display_name;
+ iface->get_description = emqfe_text_plain_get_description;
+}
+
+static void
+e_mail_formatter_quote_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emqfe_text_plain_mime_types;
+}
+
+static void
+e_mail_formatter_quote_text_plain_init (EMailFormatterQuoteTextPlain *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-quote.c b/em-format/e-mail-formatter-quote.c
new file mode 100644
index 0000000000..e4a221e3d1
--- /dev/null
+++ b/em-format/e-mail-formatter-quote.c
@@ -0,0 +1,224 @@
+/*
+ * e-mail-formatter-quote.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter-quote.h"
+
+#include <camel/camel.h>
+
+#include "e-mail-formatter-extension.h"
+#include "e-mail-format-extensions.h"
+#include "e-mail-part.h"
+#include "e-mail-part-attachment.h"
+#include "e-mail-part-utils.h"
+
+#include <libebackend/libebackend.h>
+#include <gdk/gdk.h>
+#include <glib/gi18n.h>
+
+struct _EMailFormatterQuotePrivate {
+ gchar *credits;
+ EMailFormatterQuoteFlags flags;
+};
+
+#define E_MAIL_FORMATTER_QUOTE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_FORMATTER_QUOTE, EMailFormatterQuotePrivate))
+
+static gpointer e_mail_formatter_quote_parent_class = 0;
+
+static EMailFormatterContext *
+mail_formatter_quote_create_context (EMailFormatter *formatter)
+{
+ return g_malloc0 (sizeof (EMailFormatterQuoteContext));
+}
+
+static void
+mail_formatter_quote_free_context (EMailFormatter *formatter,
+ EMailFormatterContext *context)
+{
+ g_free ((EMailFormatterQuoteContext *) context);
+}
+
+static void
+mail_formatter_quote_run (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ EMailFormatterQuote *qf;
+ EMailFormatterQuoteContext *qf_context;
+ GSettings *settings;
+ GSList *iter;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ qf = E_MAIL_FORMATTER_QUOTE (formatter);
+
+ qf_context = (EMailFormatterQuoteContext *) context;
+ qf_context->qf_flags = qf->priv->flags;
+
+ g_seekable_seek (
+ G_SEEKABLE (stream),
+ 0, G_SEEK_SET, NULL, NULL);
+
+ settings = g_settings_new ("org.gnome.evolution.mail");
+ if (g_settings_get_boolean (
+ settings, "composer-top-signature"))
+ camel_stream_write_string (
+ stream, "<br>\n", cancellable, NULL);
+ g_object_unref (settings);
+
+ if (qf->priv->credits && *qf->priv->credits) {
+ gchar *credits = g_strdup_printf ("%s<br/>", qf->priv->credits);
+ camel_stream_write_string (stream, credits, cancellable, NULL);
+ g_free (credits);
+ } else {
+ camel_stream_write_string (stream, "<br/>", cancellable, NULL);
+ }
+
+ if (qf->priv->flags & E_MAIL_FORMATTER_QUOTE_FLAG_CITE) {
+ camel_stream_write_string (stream,
+ "<!--+GtkHTML:<DATA class=\"ClueFlow\" "
+ "key=\"orig\" value=\"1\">-->\n"
+ "<blockquote type=cite>\n", cancellable, NULL);
+ }
+
+ for (iter = context->parts; iter; iter = iter->next) {
+ EMailPart *part = iter->data;
+
+ if (!part)
+ continue;
+
+ if (g_str_has_suffix (part->id, ".rfc822")) {
+ gchar *end = g_strconcat (part->id, ".end", NULL);
+
+ while (iter) {
+ EMailPart *p = iter->data;
+ if (!p) {
+ iter = iter->next;
+ continue;
+ }
+
+ if (g_strcmp0 (p->id, end) == 0)
+ break;
+
+ iter = iter->next;
+ }
+ g_free (end);
+ continue;
+ }
+
+ if (part->is_hidden)
+ continue;
+
+ e_mail_formatter_format_as (
+ formatter, context, part, stream,
+ part->mime_type, cancellable);
+ }
+
+ if (qf->priv->flags & E_MAIL_FORMATTER_QUOTE_FLAG_CITE) {
+ camel_stream_write_string (
+ stream, "</blockquote><!--+GtkHTML:"
+ "<DATA class=\"ClueFlow\" clear=\"orig\">-->",
+ cancellable, NULL);
+ }
+}
+
+static void
+e_mail_formatter_quote_init (EMailFormatterQuote *formatter)
+{
+ formatter->priv = E_MAIL_FORMATTER_QUOTE_GET_PRIVATE (formatter);
+}
+
+static void
+e_mail_formatter_quote_finalize (GObject *object)
+{
+ /* Chain up to parent's finalize() */
+ G_OBJECT_CLASS (e_mail_formatter_quote_parent_class)->finalize (object);
+}
+
+static void
+e_mail_formatter_quote_base_init (EMailFormatterQuoteClass *klass)
+{
+ e_mail_formatter_quote_internal_extensions_load (
+ E_MAIL_EXTENSION_REGISTRY (
+ E_MAIL_FORMATTER_CLASS (klass)->extension_registry));
+
+ E_MAIL_FORMATTER_CLASS (klass)->text_html_flags =
+ CAMEL_MIME_FILTER_TOHTML_PRE |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
+}
+
+static void
+e_mail_formatter_quote_class_init (EMailFormatterQuoteClass *klass)
+{
+ GObjectClass *object_class;
+ EMailFormatterClass *formatter_class;
+
+ e_mail_formatter_quote_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (EMailFormatterQuotePrivate));
+
+ formatter_class = E_MAIL_FORMATTER_CLASS (klass);
+ formatter_class->run = mail_formatter_quote_run;
+ formatter_class->create_context = mail_formatter_quote_create_context;
+ formatter_class->free_context = mail_formatter_quote_free_context;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = e_mail_formatter_quote_finalize;
+}
+
+GType
+e_mail_formatter_quote_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EMailFormatterClass),
+ (GBaseInitFunc) e_mail_formatter_quote_base_init,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) e_mail_formatter_quote_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailFormatterQuote),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_mail_formatter_quote_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (E_TYPE_MAIL_FORMATTER,
+ "EMailFormatterQuote", &type_info, 0);
+ }
+
+ return type;
+}
+
+EMailFormatter *
+e_mail_formatter_quote_new (const gchar *credits,
+ EMailFormatterQuoteFlags flags)
+{
+ EMailFormatterQuote *formatter;
+ formatter = g_object_new (E_TYPE_MAIL_FORMATTER_QUOTE, NULL);
+
+ formatter->priv->credits = g_strdup (credits);
+ formatter->priv->flags = flags;
+
+ return (EMailFormatter *) formatter;
+}
diff --git a/em-format/e-mail-formatter-quote.h b/em-format/e-mail-formatter-quote.h
new file mode 100644
index 0000000000..fa6730b964
--- /dev/null
+++ b/em-format/e-mail-formatter-quote.h
@@ -0,0 +1,79 @@
+/*
+ * e-mail-formatter-quote.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_QUOTE_H_
+#define E_MAIL_FORMATTER_QUOTE_H_
+
+#include <em-format/e-mail-formatter.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_FORMATTER_QUOTE \
+ (e_mail_formatter_quote_get_type ())
+#define E_MAIL_FORMATTER_QUOTE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_FORMATTER_QUOTE, EMailFormatterQuote))
+#define E_MAIL_FORMATTER_QUOTE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_FORMATTER_QUOTE, EMailFormatterQuoteClass))
+#define E_IS_MAIL_FORMATTER_QUOTE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_FORMATTER_QUOTE))
+#define E_IS_MAIL_FORMATTER_QUOTE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_FORMATTER_QUOTE))
+#define E_MAIL_FORMATTER_QUOTE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_FORMATTER_QUOTE, EMailFormatterQuoteClass))
+
+G_BEGIN_DECLS;
+
+typedef struct _EMailFormatterQuote EMailFormatterQuote;
+typedef struct _EMailFormatterQuoteClass EMailFormatterQuoteClass;
+typedef struct _EMailFormatterQuotePrivate EMailFormatterQuotePrivate;
+typedef struct _EMailFormatterQuoteContext EMailFormatterQuoteContext;
+
+typedef enum {
+ E_MAIL_FORMATTER_QUOTE_FLAG_CITE = 1 << 0,
+ E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS = 1 << 1,
+ E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG = 1 << 2 /* do not strip signature */
+} EMailFormatterQuoteFlags;
+
+struct _EMailFormatterQuoteContext {
+ EMailFormatterContext parent;
+
+ guint32 qf_flags;
+};
+
+struct _EMailFormatterQuote {
+ EMailFormatter parent;
+
+ EMailFormatterQuotePrivate *priv;
+};
+
+struct _EMailFormatterQuoteClass {
+ EMailFormatterClass parent_class;
+};
+
+GType e_mail_formatter_quote_get_type (void);
+
+EMailFormatter * e_mail_formatter_quote_new (const gchar *credits,
+ EMailFormatterQuoteFlags flags);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_QUOTE_H_ */
diff --git a/em-format/e-mail-formatter-secure-button.c b/em-format/e-mail-formatter-secure-button.c
new file mode 100644
index 0000000000..05319ef7fc
--- /dev/null
+++ b/em-format/e-mail-formatter-secure-button.c
@@ -0,0 +1,472 @@
+/*
+ * evolution-secure-button.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <e-util/e-util.h>
+
+#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
+#include "certificate-viewer.h"
+#include "e-cert-db.h"
+#endif
+
+#include <camel/camel.h>
+
+typedef struct _EMailFormatterSecureButton {
+ GObject parent;
+} EMailFormatterSecureButton;
+
+typedef struct _EMailFormatterSecureButtonClass {
+ GObjectClass parent_class;
+} EMailFormatterSecureButtonClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterSecureButton,
+ e_mail_formatter_secure_button,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.widget.secure-button", NULL };
+
+static const struct {
+ const gchar *icon, *shortdesc, *description;
+} smime_sign_table[5] = {
+ { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") },
+ { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") },
+ { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") },
+ { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") },
+ { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") },
+
+};
+
+static const struct {
+ const gchar *icon, *shortdesc, *description;
+} smime_encrypt_table[4] = {
+ { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") },
+ { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") },
+ { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") },
+ { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") },
+};
+
+static const GdkRGBA smime_sign_colour[5] = {
+ { 0 }, { 0.53, 0.73, 0.53, 1 }, { 0.73, 0.53, 0.53, 1 }, { 0.91, 0.82, 0.13, 1 }, { 0 },
+};
+
+static gboolean
+emfe_secure_button_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ gchar *str;
+
+ if ((context->mode != E_MAIL_FORMATTER_MODE_NORMAL) &&
+ (context->mode != E_MAIL_FORMATTER_MODE_RAW))
+ return FALSE;
+
+ str = g_strdup_printf (
+ "<object type=\"application/vnd.evolution.widget.secure-button\" "
+ "height=\"20\" width=\"100%%\" data=\"%s\" id=\"%s\"></object>",
+ part->id, part->id);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+ return TRUE;
+}
+
+#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
+static void
+viewcert_clicked (GtkWidget *button,
+ GtkWidget *parent)
+{
+ CamelCipherCertInfo *info = g_object_get_data((GObject *) button, "e-cert-info");
+ ECert *ec = NULL;
+
+ if (info->cert_data)
+ ec = e_cert_new (CERT_DupCertificate (info->cert_data));
+
+ if (ec != NULL) {
+ GtkWidget *w = certificate_viewer_show (ec);
+
+ /* oddly enough certificate_viewer_show doesn't ... */
+ gtk_widget_show (w);
+ g_signal_connect (
+ w, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ if (w && parent)
+ gtk_window_set_transient_for (
+ (GtkWindow *) w, (GtkWindow *) parent);
+
+ g_object_unref (ec);
+ } else {
+ g_warning("can't find certificate for %s <%s>",
+ info->name ? info->name : "",
+ info->email ? info->email : "");
+ }
+}
+#endif
+
+static void
+info_response (GtkWidget *widget,
+ guint button,
+ gpointer user_data)
+{
+ gtk_widget_destroy (widget);
+}
+
+static void
+add_cert_table (GtkWidget *grid,
+ GQueue *certlist,
+ gpointer user_data)
+{
+ GList *head, *link;
+ GtkTable *table;
+ gint n = 0;
+
+ table = (GtkTable *) gtk_table_new (certlist->length, 2, FALSE);
+
+ head = g_queue_peek_head_link (certlist);
+
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ CamelCipherCertInfo *info = link->data;
+ gchar *la = NULL;
+ const gchar *l = NULL;
+
+ if (info->name) {
+ if (info->email && strcmp (info->name, info->email) != 0)
+ l = la = g_strdup_printf("%s <%s>", info->name, info->email);
+ else
+ l = info->name;
+ } else {
+ if (info->email)
+ l = info->email;
+ }
+
+ if (l) {
+ GtkWidget *w;
+#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
+ ECert *ec = NULL;
+#endif
+ w = gtk_label_new (l);
+ gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
+ g_free (la);
+ gtk_table_attach (table, w, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 3, 3);
+#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
+ w = gtk_button_new_with_mnemonic(_("_View Certificate"));
+ gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
+ g_object_set_data((GObject *)w, "e-cert-info", info);
+ g_signal_connect (
+ w, "clicked",
+ G_CALLBACK (viewcert_clicked), grid);
+
+ if (info->cert_data)
+ ec = e_cert_new (CERT_DupCertificate (info->cert_data));
+
+ if (ec == NULL)
+ gtk_widget_set_sensitive (w, FALSE);
+ else
+ g_object_unref (ec);
+#else
+ w = gtk_label_new (_("This certificate is not viewable"));
+ gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
+#endif
+ n++;
+ }
+ }
+
+ gtk_container_add (GTK_CONTAINER (grid), GTK_WIDGET (table));
+}
+
+static void
+format_cert_infos (GQueue *cert_infos,
+ GString *output_buffer)
+{
+ GQueue valid = G_QUEUE_INIT;
+ GList *head, *link;
+
+ head = g_queue_peek_head_link (cert_infos);
+
+ /* Make sure we have a valid CamelCipherCertInfo before
+ * appending anything to the output buffer, so we don't
+ * end up with "()". */
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ CamelCipherCertInfo *cinfo = link->data;
+
+ if ((cinfo->name != NULL && *cinfo->name != '\0') ||
+ (cinfo->email != NULL && *cinfo->email != '\0')) {
+ g_queue_push_tail (&valid, cinfo);
+ }
+ }
+
+ if (g_queue_is_empty (&valid))
+ return;
+
+ g_string_append (output_buffer, " (");
+
+ while (!g_queue_is_empty (&valid)) {
+ CamelCipherCertInfo *cinfo;
+
+ cinfo = g_queue_pop_head (&valid);
+
+ if (cinfo->name != NULL && *cinfo->name != '\0') {
+ g_string_append (output_buffer, cinfo->name);
+
+ if (cinfo->email != NULL && *cinfo->email != '\0') {
+ g_string_append (output_buffer, " <");
+ g_string_append (output_buffer, cinfo->email);
+ g_string_append (output_buffer, ">");
+ }
+
+ } else if (cinfo->email != NULL && *cinfo->email != '\0') {
+ g_string_append (output_buffer, cinfo->email);
+ }
+
+ if (!g_queue_is_empty (&valid))
+ g_string_append (output_buffer, ", ");
+ }
+
+ g_string_append_c (output_buffer, ')');
+}
+
+static void
+secure_button_clicked_cb (GtkWidget *widget,
+ EMailPart *part)
+{
+ GtkBuilder *builder;
+ GtkWidget *grid, *w;
+ GtkWidget *dialog;
+
+ builder = gtk_builder_new ();
+ e_load_ui_builder_definition (builder, "mail-dialogs.ui");
+
+ dialog = e_builder_get_widget(builder, "message_security_dialog");
+
+ grid = e_builder_get_widget(builder, "signature_grid");
+ w = gtk_label_new (_(smime_sign_table[part->validity->sign.status].description));
+ gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
+ gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
+ gtk_container_add (GTK_CONTAINER (grid), w);
+ if (part->validity->sign.description) {
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_buffer_new (NULL);
+ gtk_text_buffer_set_text (
+ buffer, part->validity->sign.description,
+ strlen (part->validity->sign.description));
+ w = g_object_new (gtk_scrolled_window_get_type (),
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "shadow_type", GTK_SHADOW_IN,
+ "expand", TRUE,
+ "child", g_object_new(gtk_text_view_get_type(),
+ "buffer", buffer,
+ "cursor_visible", FALSE,
+ "editable", FALSE,
+ "width_request", 500,
+ "height_request", 160,
+ NULL),
+ NULL);
+ g_object_unref (buffer);
+
+ gtk_container_add (GTK_CONTAINER (grid), w);
+ }
+
+ if (!g_queue_is_empty (&part->validity->sign.signers))
+ add_cert_table (
+ grid, &part->validity->sign.signers, NULL);
+
+ gtk_widget_show_all (grid);
+
+ grid = e_builder_get_widget(builder, "encryption_grid");
+ w = gtk_label_new (_(smime_encrypt_table[part->validity->encrypt.status].description));
+ gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
+ gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
+ gtk_container_add (GTK_CONTAINER (grid), w);
+ if (part->validity->encrypt.description) {
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_buffer_new (NULL);
+ gtk_text_buffer_set_text (
+ buffer, part->validity->encrypt.description,
+ strlen (part->validity->encrypt.description));
+ w = g_object_new (gtk_scrolled_window_get_type (),
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "shadow_type", GTK_SHADOW_IN,
+ "expand", TRUE,
+ "child", g_object_new(gtk_text_view_get_type(),
+ "buffer", buffer,
+ "cursor_visible", FALSE,
+ "editable", FALSE,
+ "width_request", 500,
+ "height_request", 160,
+ NULL),
+ NULL);
+ g_object_unref (buffer);
+
+ gtk_container_add (GTK_CONTAINER (grid), w);
+ }
+
+ if (!g_queue_is_empty (&part->validity->encrypt.encrypters))
+ add_cert_table (grid, &part->validity->encrypt.encrypters, NULL);
+
+ gtk_widget_show_all (grid);
+
+ g_object_unref (builder);
+
+ g_signal_connect (
+ dialog, "response",
+ G_CALLBACK (info_response), NULL);
+
+ gtk_widget_show (dialog);
+}
+
+static GtkWidget *
+emfe_secure_button_get_widget (EMailFormatterExtension *extension,
+ EMailPartList *context,
+ EMailPart *part,
+ GHashTable *params)
+{
+ GtkWidget *box, *button, *layout, *widget;
+ const gchar *icon_name;
+ gchar *description;
+ GString *buffer;
+ buffer = g_string_new ("");
+
+ if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
+ const gchar *desc;
+ gint status;
+
+ status = part->validity->sign.status;
+ desc = smime_sign_table[status].shortdesc;
+
+ g_string_append (buffer, gettext (desc));
+
+ format_cert_infos (&part->validity->sign.signers, buffer);
+ }
+
+ if (part->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
+ const gchar *desc;
+ gint status;
+
+ if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)
+ g_string_append (buffer, "\n");
+
+ status = part->validity->encrypt.status;
+ desc = smime_encrypt_table[status].shortdesc;
+ g_string_append (buffer, gettext (desc));
+ }
+
+ description = g_string_free (buffer, FALSE);
+
+ /* FIXME: need to have it based on encryption and signing too */
+ if (part->validity->sign.status != 0)
+ icon_name = smime_sign_table[part->validity->sign.status].icon;
+ else
+ icon_name = smime_encrypt_table[part->validity->encrypt.status].icon;
+
+ box = gtk_event_box_new ();
+ if (part->validity->sign.status != 0)
+ gtk_widget_override_background_color (box, GTK_STATE_FLAG_NORMAL,
+ &smime_sign_colour[part->validity->sign.status]);
+
+ layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+ gtk_container_add (GTK_CONTAINER (box), layout);
+
+ button = gtk_button_new ();
+ gtk_box_pack_start (GTK_BOX (layout), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (secure_button_clicked_cb), part);
+
+ widget = gtk_image_new_from_icon_name (
+ icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_button_set_image (GTK_BUTTON (button), widget);
+
+ widget = gtk_label_new (description);
+ gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (box);
+
+ g_free (description);
+ return box;
+}
+
+static const gchar *
+emfe_secure_button_get_display_name (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar *
+emfe_secure_button_get_description (EMailFormatterExtension *extension)
+{
+ return NULL;
+}
+
+static const gchar **
+emfe_secure_button_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_secure_button_class_init (EMailFormatterSecureButtonClass *klass)
+{
+ e_mail_formatter_secure_button_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_secure_button_format;
+ iface->get_widget = emfe_secure_button_get_widget;
+ iface->get_display_name = emfe_secure_button_get_display_name;
+ iface->get_description = emfe_secure_button_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_secure_button_mime_types;
+}
+
+static void
+e_mail_formatter_secure_button_init (EMailFormatterSecureButton *extension)
+{
+
+}
diff --git a/em-format/e-mail-formatter-source.c b/em-format/e-mail-formatter-source.c
new file mode 100644
index 0000000000..92c3a925f1
--- /dev/null
+++ b/em-format/e-mail-formatter-source.c
@@ -0,0 +1,178 @@
+/*
+ * evolution-source.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailFormatterSource {
+ GObject parent;
+} EMailFormatterSource;
+
+typedef struct _EMailFormatterSourceClass {
+ GObjectClass parent_class;
+} EMailFormatterSourceClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterSource,
+ e_mail_formatter_source,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init)
+)
+
+static const gchar *formatter_mime_types[] = { "application/vnd.evolution.source", NULL };
+
+static gboolean
+emfe_source_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GString *buffer;
+ CamelStream *filtered_stream;
+ CamelMimeFilter *filter;
+ CamelDataWrapper *dw = (CamelDataWrapper *) part->part;
+
+ filtered_stream = camel_stream_filter_new (stream);
+
+ filter = camel_mime_filter_tohtml_new (
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
+ CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), filter);
+ g_object_unref (filter);
+
+ buffer = g_string_new ("");
+
+ if (CAMEL_IS_MIME_MESSAGE (part->part)) {
+ g_string_append_printf (
+ buffer,
+ "<div class=\"part-container\" "
+ "style=\"border: 0; background: #%06x; color: #%06x;\" >",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_TEXT)));
+ } else {
+ g_string_append_printf (
+ buffer,
+ "<div class=\"part-container\" "
+ "style=\"border-color: #%06x; background: #%06x; color: #%06x;\">"
+ "<div class=\"part-container-inner-margin pre\">\n",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_TEXT)));
+ }
+
+ camel_stream_write_string (
+ stream, buffer->str, cancellable, NULL);
+ camel_stream_write_string (
+ stream, "<code class=\"pre\">", cancellable, NULL);
+
+ camel_data_wrapper_write_to_stream_sync (dw, filtered_stream,
+ cancellable, NULL);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ camel_stream_write_string (
+ stream, "</code>", cancellable, NULL);
+
+ g_string_free (buffer, TRUE);
+
+ if (CAMEL_IS_MIME_MESSAGE (part->part)) {
+ camel_stream_write_string (stream, "</div>", cancellable, NULL);
+ } else {
+ camel_stream_write_string (stream, "</div></div>", cancellable, NULL);
+ }
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_source_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Source");
+}
+
+static const gchar *
+emfe_source_get_description (EMailFormatterExtension *extension)
+{
+ return _("Display source of a MIME part");
+}
+
+static const gchar **
+emfe_source_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_source_class_init (EMailFormatterSourceClass *klass)
+{
+ e_mail_formatter_source_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_source_format;
+ iface->get_display_name = emfe_source_get_display_name;
+ iface->get_description = emfe_source_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_source_mime_types;
+}
+
+static void
+e_mail_formatter_source_init (EMailFormatterSource *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-text-enriched.c b/em-format/e-mail-formatter-text-enriched.c
new file mode 100644
index 0000000000..fce7b317e2
--- /dev/null
+++ b/em-format/e-mail-formatter-text-enriched.c
@@ -0,0 +1,154 @@
+/*
+ * e-mail-formatter-text-enriched.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+static const gchar *formatter_mime_types[] = { "text/enriched",
+ "text/richtext",
+ NULL };
+
+typedef struct _EMailFormatterTextEnriched {
+ GObject parent;
+} EMailFormatterTextEnriched;
+
+typedef struct _EMailFormatterTextEnrichedClass {
+ GObjectClass parent_class;
+} EMailFormatterTextEnrichedClass;
+
+static void e_mail_formatter_formatter_extension_interace_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterTextEnriched,
+ e_mail_formatter_text_enriched,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interace_init));
+
+static gboolean
+emfe_text_enriched_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelStream *filtered_stream;
+ CamelMimeFilter *enriched;
+ guint32 filter_flags = 0;
+ GString *buffer;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ if (!g_strcmp0(part->mime_type, "text/richtext")) {
+ filter_flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT;
+ }
+
+ enriched = camel_mime_filter_enriched_new (filter_flags);
+ filtered_stream = camel_stream_filter_new (stream);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), enriched);
+ g_object_unref (enriched);
+
+ buffer = g_string_new ("");
+
+ g_string_append_printf (buffer,
+ "<div class=\"part-container\" style=\"border-color: #%06x; "
+ "background-color: #%06x; color: #%06x;\">"
+ "<div class=\"part-container-inner-margin\">\n",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (formatter, E_MAIL_FORMATTER_COLOR_CONTENT)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (formatter, E_MAIL_FORMATTER_COLOR_TEXT)));
+
+ camel_stream_write_string (stream, buffer->str, cancellable, NULL);
+ g_string_free (buffer, TRUE);
+
+ e_mail_formatter_format_text (
+ formatter, part, filtered_stream, cancellable);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ camel_stream_write_string (stream, "</div></div>", cancellable, NULL);
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_text_enriched_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Richtext");
+}
+
+static const gchar *
+emfe_text_enriched_get_description (EMailFormatterExtension *extension)
+{
+ return _("Display part as enriched text");
+}
+
+static const gchar **
+emfe_text_enriched_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_text_enriched_class_init (EMailFormatterTextEnrichedClass *klass)
+{
+ e_mail_formatter_text_enriched_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interace_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_text_enriched_format;
+ iface->get_display_name = emfe_text_enriched_get_display_name;
+ iface->get_description = emfe_text_enriched_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_text_enriched_mime_types;
+}
+
+static void
+e_mail_formatter_text_enriched_init (EMailFormatterTextEnriched *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-text-html.c b/em-format/e-mail-formatter-text-html.c
new file mode 100644
index 0000000000..28fb2644de
--- /dev/null
+++ b/em-format/e-mail-formatter-text-html.c
@@ -0,0 +1,376 @@
+/*
+ * e-mail-formatter-text-html.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <ctype.h>
+#include <string.h>
+
+static const gchar *formatter_mime_types[] = { "text/html", NULL };
+
+typedef struct _EMailFormatterTextHTML {
+ GObject parent;
+} EMailFormatterTextHTML;
+
+typedef struct _EMailFormatterTextHTMLClass {
+ GObjectClass parent_class;
+} EMailFormatterTextHTMLClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterTextHTML,
+ e_mail_formatter_text_html,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static gchar *
+get_tag (const gchar *utf8_string,
+ const gchar *tag_name,
+ gchar *opening,
+ gchar *closing)
+{
+ gchar *t;
+ gunichar c;
+ gboolean has_end;
+
+ t = g_utf8_find_prev_char (utf8_string, closing);
+ while (t != opening) {
+
+ c = g_utf8_get_char (t);
+ if (!g_unichar_isspace (c))
+ break;
+ }
+
+ /* Not a pair tag */
+ if (c == '/')
+ return g_strndup (opening, closing - opening + 1);
+
+ t = closing;
+ while (t) {
+ c = g_utf8_get_char (t);
+ if (c == '<')
+ break;
+
+ t = g_utf8_find_next_char (t, NULL);
+ }
+
+ do {
+ c = g_utf8_get_char (t);
+
+ if (c == '/') {
+ has_end = TRUE;
+ break;
+ }
+
+ if (c == '>') {
+ has_end = FALSE;
+ break;
+ }
+
+ t = g_utf8_find_next_char (t, NULL);
+
+ } while (t);
+
+ /* Broken HTML? */
+ if (!has_end)
+ return g_strndup (opening, closing - opening + 1);
+
+ do {
+ c = g_utf8_get_char (t);
+ if ((c != ' ') && (c != '/'))
+ break;
+
+ t = g_utf8_find_next_char (t, NULL);
+ } while (t);
+
+ /* tag_name is always ASCII */
+ if (g_ascii_strncasecmp (t, tag_name, strlen (tag_name)) == 0) {
+
+ closing = g_utf8_strchr (t, -1, '>');
+
+ return g_strndup (opening, closing - opening + 1);
+ }
+
+ /* Broken HTML? */
+ return g_strndup (opening, closing - opening + 1);
+}
+
+static gboolean
+emfe_text_html_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
+ /* FORMATTER FIXME: Shouldn't we have some extra method for
+ * BASE64 and QP decoding?? */
+ e_mail_formatter_format_text (formatter, part, stream, cancellable);
+
+ } else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
+ GString *string;
+ GByteArray *ba;
+ gchar *pos;
+ GList *tags, *iter;
+ gboolean valid;
+ gchar *tag;
+ const gchar *document_end;
+ gint length;
+ gint i;
+ CamelStream *decoded_stream;
+
+ decoded_stream = camel_stream_mem_new ();
+ /* FORMATTER FIXME: See above */
+ e_mail_formatter_format_text (formatter, part, decoded_stream, cancellable);
+ g_seekable_seek (G_SEEKABLE (decoded_stream), 0, G_SEEK_SET, cancellable, NULL);
+
+ ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (decoded_stream));
+ string = g_string_new_len ((gchar *) ba->data, ba->len);
+
+ g_object_unref (decoded_stream);
+
+ tags = NULL;
+ pos = string->str;
+ valid = FALSE;
+
+ if (!g_utf8_validate (string->str, -1, NULL)) {
+ /* FIXME - What do we do if the string is not UTF-8 valid? */
+ }
+
+ do {
+ gchar *tmp;
+ gchar *closing;
+ gchar *opening;
+
+ tmp = g_utf8_find_next_char (pos, NULL);
+ pos = g_utf8_strchr (tmp, -1, '<');
+ if (!pos)
+ break;
+
+ opening = pos;
+ closing = g_utf8_strchr (pos, -1, '>');
+
+ /* Find where the actual tag name begins */
+ tag = g_utf8_find_next_char (pos, NULL);
+ while ((tag = g_utf8_find_next_char (pos, NULL)) != NULL) {
+ gunichar c = g_utf8_get_char (tag);
+ if (!g_unichar_isspace (c))
+ break;
+
+ }
+
+ if (g_ascii_strncasecmp (tag, "style", 5) == 0) {
+ tags = g_list_append (
+ tags,
+ get_tag (string->str, "style", opening, closing));
+ } else if (g_ascii_strncasecmp (tag, "script", 6) == 0) {
+ tags = g_list_append (
+ tags,
+ get_tag (string->str, "script", opening, closing));
+ } else if (g_ascii_strncasecmp (tag, "link", 4) == 0) {
+ tags = g_list_append (
+ tags,
+ get_tag (string->str, "link", opening, closing));
+ } else if (g_ascii_strncasecmp (tag, "body", 4) == 0) {
+ valid = TRUE;
+ break;
+ }
+
+ } while (pos);
+
+ if (tags)
+ printf("\n\n**%s**\n\n", (gchar *) tags->data);
+
+ /* Something's wrong, let's write the entire HTML and hope
+ * that WebKit can handle it */
+ if (!valid) {
+ EMailFormatterContext c = {
+ .folder = context->folder,
+ .message = context->message,
+ .message_uid = context->message_uid,
+ .parts = context->parts,
+ .flags = context->flags,
+ .mode = E_MAIL_FORMATTER_MODE_RAW,
+ };
+
+ emfe_text_html_format (
+ extension, formatter, &c, part, stream, cancellable);
+ return FALSE;
+ }
+
+ /* include the "body" as well -----v */
+ g_string_erase (string, 0, tag - string->str + 4);
+ g_string_prepend (string, "<div ");
+
+ for (iter = tags; iter; iter = iter->next) {
+ g_string_prepend (string, iter->data);
+ }
+
+ g_list_free_full (tags, g_free);
+
+ document_end = NULL;
+ /* We can probably use ASCII functions here */
+ if (g_strrstr (string->str, "</body>")) {
+ document_end = ">ydob/<";
+ }
+
+ if (g_strrstr (string->str, "</html>")) {
+ if (document_end) {
+ document_end = ">lmth/<>ydob/<";
+ } else {
+ document_end = ">lmth/<";
+ }
+ }
+
+ if (document_end ) {
+ length = strlen (document_end);
+ tag = string->str + string->len - 1;
+ i = 0;
+ valid = FALSE;
+ while (i < length - 1) {
+ gunichar c;
+
+ c = g_utf8_get_char (tag);
+ if (g_unichar_isspace (c)) {
+ tag = g_utf8_find_prev_char (string->str, tag);
+ continue;
+ }
+
+ c = g_unichar_tolower (c);
+
+ if (c == document_end[i]) {
+ tag = g_utf8_find_prev_char (string->str, tag);
+ i++;
+ valid = TRUE;
+ continue;
+ }
+
+ tag = g_utf8_find_prev_char (string->str, tag);
+ valid = FALSE;
+ }
+ }
+
+ if (valid)
+ g_string_truncate (string, tag - string->str);
+
+ camel_stream_write_string (stream, string->str, cancellable, NULL);
+
+ g_string_free (string, TRUE);
+ } else {
+ gchar *uri, *str;
+
+ uri = e_mail_part_build_uri (
+ context->folder, context->message_uid,
+ "part_id", G_TYPE_STRING, part->id,
+ "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW,
+ NULL);
+
+ str = g_strdup_printf (
+ "<div class=\"part-container-nostyle\">"
+ "<iframe width=\"100%%\" height=\"10\" "
+ " frameborder=\"0\" src=\"%s\" "
+ " id=\"%s.iframe\" "
+ " style=\"border: 1px solid #%06x; background-color: #%06x;\">"
+ "</iframe>"
+ "</div>",
+ uri,
+ part->id,
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_CONTENT)));
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+ g_free (uri);
+ }
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_text_html_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("HTML");
+}
+
+static const gchar *
+emfe_text_html_get_description (EMailFormatterExtension *extension)
+{
+ return _("Format part as HTML");
+}
+
+static const gchar **
+emfe_text_html_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_text_html_class_init (EMailFormatterTextHTMLClass *klass)
+{
+ e_mail_formatter_text_html_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_text_html_format;
+ iface->get_display_name = emfe_text_html_get_display_name;
+ iface->get_description = emfe_text_html_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_text_html_mime_types;
+}
+
+static void
+e_mail_formatter_text_html_init (EMailFormatterTextHTML *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-text-plain.c b/em-format/e-mail-formatter-text-plain.c
new file mode 100644
index 0000000000..631c46a3bc
--- /dev/null
+++ b/em-format/e-mail-formatter-text-plain.c
@@ -0,0 +1,212 @@
+/*
+ * e-mail-formatter-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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+static const gchar *formatter_mime_types[] = { "text/plain", "text/*", NULL };
+
+typedef struct _EMailFormatterTextPlain {
+ GObject parent;
+} EMailFormatterTextPlain;
+
+typedef struct _EMailFormatterTextPlainClass {
+ GObjectClass parent_class;
+} EMailFormatterTextPlainClass;
+
+static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
+static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailFormatterTextPlain,
+ e_mail_formatter_text_plain,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_formatter_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_FORMATTER_EXTENSION,
+ e_mail_formatter_formatter_extension_interface_init));
+
+static gboolean
+emfe_text_plain_format (EMailFormatterExtension *extension,
+ EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelDataWrapper *dw;
+ CamelStream *filtered_stream;
+ CamelMimeFilter *html_filter;
+ gchar *content;
+ const gchar *format;
+ guint32 filter_flags;
+ guint32 rgb;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return FALSE;
+
+ if ((context->mode == E_MAIL_FORMATTER_MODE_RAW) ||
+ (context->mode == E_MAIL_FORMATTER_MODE_PRINTING)) {
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
+ gchar *header;
+ header = e_mail_formatter_get_html_header (formatter);
+ camel_stream_write_string (stream, header, cancellable, NULL);
+ g_free (header);
+
+ /* No need for body margins within <iframe> */
+ camel_stream_write_string (stream,
+ "<style>body{ margin: 0; }</style>",
+ cancellable, NULL);
+ }
+
+ filter_flags = e_mail_formatter_get_text_format_flags (formatter);
+
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part->part));
+ if (!dw)
+ return FALSE;
+
+ /* Check for RFC 2646 flowed text. */
+ if (camel_content_type_is(dw->mime_type, "text", "plain")
+ && (format = camel_content_type_param(dw->mime_type, "format"))
+ && !g_ascii_strcasecmp(format, "flowed"))
+ filter_flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED;
+
+ rgb = e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_CITATION));
+
+ filtered_stream = camel_stream_filter_new (stream);
+ html_filter = camel_mime_filter_tohtml_new (filter_flags, rgb);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream), html_filter);
+ g_object_unref (html_filter);
+
+ content = g_strdup_printf (
+ "<div class=\"part-container\" style=\""
+ "border-color: #%06x;"
+ "background-color: #%06x; color: #%06x;\">"
+ "<div class=\"part-container-inner-margin pre\">\n",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_CONTENT)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_TEXT)));
+
+ camel_stream_write_string (stream, content, cancellable, NULL);
+ e_mail_formatter_format_text (formatter, part, filtered_stream, cancellable);
+ camel_stream_flush (filtered_stream, cancellable, NULL);
+
+ g_object_unref (filtered_stream);
+ g_free (content);
+
+ camel_stream_write_string (stream, "</div></div>\n", cancellable, NULL);
+
+ if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
+ camel_stream_write_string (stream, "</body></html>",
+ cancellable, NULL);
+ }
+
+ return TRUE;
+
+ } else {
+ gchar *uri, *str;
+
+ uri = e_mail_part_build_uri (
+ context->folder, context->message_uid,
+ "part_id", G_TYPE_STRING, part->id,
+ "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW,
+ NULL);
+
+ str = g_strdup_printf (
+ "<iframe width=\"100%%\" height=\"10\""
+ " id=\"%s.iframe\" "
+ " frameborder=\"0\" src=\"%s\"></iframe>",
+ part->id, uri);
+
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
+ g_free (uri);
+ }
+
+ return TRUE;
+}
+
+static const gchar *
+emfe_text_plain_get_display_name (EMailFormatterExtension *extension)
+{
+ return _("Plain Text");
+}
+
+static const gchar *
+emfe_text_plain_get_description (EMailFormatterExtension *extension)
+{
+ return _("Format part as plain text");
+}
+
+static const gchar **
+emfe_text_plain_mime_types (EMailExtension *extension)
+{
+ return formatter_mime_types;
+}
+
+static void
+e_mail_formatter_text_plain_class_init (EMailFormatterTextPlainClass *klass)
+{
+ e_mail_formatter_text_plain_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
+{
+ iface->format = emfe_text_plain_format;
+ iface->get_display_name = emfe_text_plain_get_display_name;
+ iface->get_description = emfe_text_plain_get_description;
+}
+
+static void
+e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = emfe_text_plain_mime_types;
+}
+
+static void
+e_mail_formatter_text_plain_init (EMailFormatterTextPlain *formatter)
+{
+
+}
diff --git a/em-format/e-mail-formatter-utils.c b/em-format/e-mail-formatter-utils.c
new file mode 100644
index 0000000000..12ee042c90
--- /dev/null
+++ b/em-format/e-mail-formatter-utils.c
@@ -0,0 +1,434 @@
+/*
+ * e-mail-formatter-utils.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG
+#include <config.h>
+#endif
+
+#include "e-mail-formatter-utils.h"
+
+#include <camel/camel.h>
+
+#include <libemail-engine/e-mail-utils.h>
+#include <libemail-engine/mail-config.h>
+#include <e-util/e-util.h>
+#include <e-util/e-datetime-format.h>
+#include <libedataserver/libedataserver.h>
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+static const gchar *addrspec_hdrs[] = {
+ "Sender", "From", "Reply-To", "To", "Cc", "Bcc",
+ "Resent-Sender", "Resent-From", "Resent-Reply-To",
+ "Resent-To", "Resent-Cc", "Resent-Bcc", NULL
+};
+
+void
+e_mail_formatter_format_text_header (EMailFormatter *formatter,
+ GString *buffer,
+ const gchar *label,
+ const gchar *value,
+ guint32 flags)
+{
+ const gchar *fmt, *html;
+ gchar *mhtml = NULL;
+ gboolean is_rtl;
+
+ if (value == NULL)
+ return;
+
+ while (*value == ' ')
+ value++;
+
+ if (!(flags & E_MAIL_FORMATTER_HEADER_FLAG_HTML))
+ html = mhtml = camel_text_to_html (value,
+ e_mail_formatter_get_text_format_flags (formatter), 0);
+ else
+ html = value;
+
+ is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
+
+ if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOCOLUMNS) {
+ if (flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) {
+ fmt = "<tr class=\"header-item\" style=\"display: %s\"><td><b>%s:</b> %s</td></tr>";
+ } else {
+ fmt = "<tr class=\"header-item\" style=\"display: %s\"><td>%s: %s</td></tr>";
+ }
+ } else if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NODEC) {
+ if (is_rtl)
+ fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th valign=top align=\"left\" nowrap>%1$s<b>&nbsp;</b></th></tr>";
+ else
+ fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s<b>&nbsp;</b></th><td valign=top>%s</td></tr>";
+ } else {
+ if (flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) {
+ if (is_rtl)
+ fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th align=\"left\" nowrap>%1$s:<b>&nbsp;</b></th></tr>";
+ else
+ fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s:<b>&nbsp;</b></th><td>%s</td></tr>";
+ } else {
+ if (is_rtl)
+ fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%\">%2$s</td><td align=\"left\" nowrap>%1$s:<b>&nbsp;</b></td></tr>";
+ else
+ fmt = "<tr class=\"header-item\" style=\"display: %s\"><td align=\"right\" valign=\"top\" nowrap>%s:<b>&nbsp;</b></td><td>%s</td></tr>";
+ }
+ }
+
+ g_string_append_printf (buffer, fmt,
+ (flags & E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN ? "none" : "table-row"), label, html);
+
+ g_free (mhtml);
+}
+
+gchar *
+e_mail_formatter_format_address (EMailFormatter *formatter,
+ GString *out,
+ struct _camel_header_address *a,
+ gchar *field,
+ gboolean no_links,
+ gboolean elipsize)
+{
+ guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
+ gchar *name, *mailto, *addr;
+ gint i = 0;
+ gchar *str = NULL;
+ gint limit = mail_config_get_address_count ();
+
+ while (a) {
+ if (a->name)
+ name = camel_text_to_html (a->name, flags, 0);
+ else
+ name = NULL;
+
+ switch (a->type) {
+ case CAMEL_HEADER_ADDRESS_NAME:
+ if (name && *name) {
+ gchar *real, *mailaddr;
+
+ if (strchr (a->name, ',') || strchr (a->name, ';'))
+ g_string_append_printf (out, "&quot;%s&quot;", name);
+ else
+ g_string_append (out, name);
+
+ g_string_append (out, " &lt;");
+
+ /* rfc2368 for mailto syntax and url encoding extras */
+ if ((real = camel_header_encode_phrase ((guchar *) a->name))) {
+ mailaddr = g_strdup_printf("%s <%s>", real, a->v.addr);
+ g_free (real);
+ mailto = camel_url_encode (mailaddr, "?=&()");
+ g_free (mailaddr);
+ } else {
+ mailto = camel_url_encode (a->v.addr, "?=&()");
+ }
+ } else {
+ mailto = camel_url_encode (a->v.addr, "?=&()");
+ }
+ addr = camel_text_to_html (a->v.addr, flags, 0);
+ if (no_links)
+ g_string_append_printf (out, "%s", addr);
+ else
+ g_string_append_printf (out, "<a href=\"mailto:%s\">%s</a>", mailto, addr);
+ g_free (mailto);
+ g_free (addr);
+
+ if (name && *name)
+ g_string_append (out, "&gt;");
+ break;
+ case CAMEL_HEADER_ADDRESS_GROUP:
+ g_string_append_printf (out, "%s: ", name);
+ e_mail_formatter_format_address (
+ formatter, out, a->v.members, field,
+ no_links, elipsize);
+ g_string_append_printf (out, ";");
+ break;
+ default:
+ g_warning ("Invalid address type");
+ break;
+ }
+
+ g_free (name);
+
+ i++;
+ a = a->next;
+ if (a)
+ g_string_append (out, ", ");
+
+ if (!elipsize)
+ continue;
+
+ /* Let us add a '...' if we have more addresses */
+ if (limit > 0 && (i == limit - 1)) {
+ const gchar *id = NULL;
+
+ if (strcmp (field, _("To")) == 0) {
+ id = "to";
+ } else if (strcmp (field, _("Cc")) == 0) {
+ id = "cc";
+ } else if (strcmp (field, _("Bcc")) == 0) {
+ id = "bcc";
+ }
+
+ if (id) {
+ g_string_append_printf (out,
+ "<span id=\"__evo-moreaddr-%s\" "
+ "style=\"display: none;\">", id);
+ str = g_strdup_printf (
+ "<img src=\"evo-file://%s/plus.png\" "
+ "id=\"__evo-moreaddr-img-%s\" class=\"navigable\">",
+ EVOLUTION_IMAGESDIR, id);
+ }
+ }
+ }
+
+ if (elipsize && str) {
+ const gchar *id = NULL;
+
+ if (strcmp (field, _("To")) == 0) {
+ id = "to";
+ } else if (strcmp (field, _("Cc")) == 0) {
+ id = "cc";
+ } else if (strcmp (field, _("Bcc")) == 0) {
+ id = "bcc";
+ }
+
+ if (id) {
+ g_string_append_printf (out,
+ "</span>"
+ "<span class=\"navigable\" "
+ "id=\"__evo-moreaddr-ellipsis-%s\" "
+ "style=\"display: inline;\">...</span>",
+ id);
+ }
+ }
+
+ return str;
+}
+
+void
+e_mail_formatter_canon_header_name (gchar *name)
+{
+ gchar *inptr = name;
+
+ /* canonicalise the header name... first letter is
+ * capitalised and any letter following a '-' also gets
+ * capitalised */
+
+ if (*inptr >= 'a' && *inptr <= 'z')
+ *inptr -= 0x20;
+
+ inptr++;
+
+ while (*inptr) {
+ if (inptr[-1] == '-' && *inptr >= 'a' && *inptr <= 'z')
+ *inptr -= 0x20;
+ else if (*inptr >= 'A' && *inptr <= 'Z')
+ *inptr += 0x20;
+
+ inptr++;
+ }
+}
+
+void
+e_mail_formatter_format_header (EMailFormatter *formatter,
+ GString *buffer,
+ CamelMedium *part,
+ struct _camel_header_raw *header,
+ guint32 flags,
+ const gchar *charset)
+{
+ gchar *name, *buf, *value = NULL;
+ const gchar *label, *txt;
+ gboolean addrspec = FALSE;
+ gchar *str_field = NULL;
+ gint i;
+
+ name = g_alloca (strlen (header->name) + 1);
+ strcpy (name, header->name);
+ e_mail_formatter_canon_header_name (name);
+
+ for (i = 0; addrspec_hdrs[i]; i++) {
+ if (!strcmp (name, addrspec_hdrs[i])) {
+ addrspec = TRUE;
+ break;
+ }
+ }
+
+ label = _(name);
+
+ if (addrspec) {
+ struct _camel_header_address *addrs;
+ GString *html;
+ gchar *img;
+ const gchar *charset = e_mail_formatter_get_charset (formatter) ?
+ e_mail_formatter_get_charset (formatter) :
+ e_mail_formatter_get_default_charset (formatter);
+
+ buf = camel_header_unfold (header->value);
+ if (!(addrs = camel_header_address_decode (buf, charset))) {
+ g_free (buf);
+ return;
+ }
+
+ g_free (buf);
+
+ html = g_string_new("");
+ img = e_mail_formatter_format_address (formatter, html, addrs, (gchar *) label,
+ (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS),
+ !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
+
+ if (img) {
+ str_field = g_strdup_printf ("%s%s:", img, label);
+ label = str_field;
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_NODEC;
+ g_free (img);
+ }
+
+ camel_header_address_list_clear (&addrs);
+ txt = value = html->str;
+ g_string_free (html, FALSE);
+
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML | E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
+ } else if (!strcmp (name, "Subject")) {
+ buf = camel_header_unfold (header->value);
+ txt = value = camel_header_decode_string (buf, charset);
+ g_free (buf);
+
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
+ } else if (!strcmp(name, "X-evolution-mailer")) {
+ /* pseudo-header */
+ label = _("Mailer");
+ txt = value = camel_header_format_ctext (header->value, charset);
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
+ } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) {
+ gint msg_offset, local_tz;
+ time_t msg_date;
+ struct tm local;
+ gchar *html;
+ gboolean hide_real_date;
+
+ hide_real_date = !e_mail_formatter_get_show_real_date (formatter);
+
+ txt = header->value;
+ while (*txt == ' ' || *txt == '\t')
+ txt++;
+
+ html = camel_text_to_html (txt,
+ e_mail_formatter_get_text_format_flags (formatter), 0);
+
+ msg_date = camel_header_decode_date (txt, &msg_offset);
+ e_localtime_with_offset (msg_date, &local, &local_tz);
+
+ /* Convert message offset to minutes (e.g. -0400 --> -240) */
+ msg_offset = ((msg_offset / 100) * 60) + (msg_offset % 100);
+ /* Turn into offset from localtime, not UTC */
+ msg_offset -= local_tz / 60;
+
+ /* value will be freed at the end */
+ if (!hide_real_date && !msg_offset) {
+ /* No timezone difference; just show the real Date: header */
+ txt = value = html;
+ } else {
+ gchar *date_str;
+
+ date_str = e_datetime_format_format ("mail", "header",
+ DTFormatKindDateTime, msg_date);
+
+ if (hide_real_date) {
+ /* Show only the local-formatted date, losing all timezone
+ * information like Outlook does. Should we attempt to show
+ * it somehow? */
+ txt = value = date_str;
+ } else {
+ txt = value = g_strdup_printf ("%s (<I>%s</I>)", html, date_str);
+ g_free (date_str);
+ }
+ g_free (html);
+ }
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML |
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
+ } else if (!strcmp(name, "Newsgroups")) {
+ struct _camel_header_newsgroup *ng, *scan;
+ GString *html;
+
+ buf = camel_header_unfold (header->value);
+
+ if (!(ng = camel_header_newsgroups_decode (buf))) {
+ g_free (buf);
+ return;
+ }
+
+ g_free (buf);
+
+ html = g_string_new("");
+ scan = ng;
+ while (scan) {
+ if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS)
+ g_string_append_printf (html, "%s", scan->newsgroup);
+ else
+ g_string_append_printf(html, "<a href=\"news:%s\">%s</a>",
+ scan->newsgroup, scan->newsgroup);
+ scan = scan->next;
+ if (scan)
+ g_string_append_printf(html, ", ");
+ }
+
+ camel_header_newsgroups_free (ng);
+
+ txt = html->str;
+ g_string_free (html, FALSE);
+ flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML |
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
+ } else if (!strcmp (name, "Received") || !strncmp (name, "X-", 2)) {
+ /* don't unfold Received nor extension headers */
+ txt = value = camel_header_decode_string (header->value, charset);
+ } else {
+ /* don't unfold Received nor extension headers */
+ buf = camel_header_unfold (header->value);
+ txt = value = camel_header_decode_string (buf, charset);
+ g_free (buf);
+ }
+
+ e_mail_formatter_format_text_header (formatter, buffer, label, txt, flags);
+
+ g_free (value);
+ g_free (str_field);
+}
+
+GSList *
+e_mail_formatter_find_rfc822_end_iter (GSList *iter)
+{
+ EMailPart *part;
+ gchar *end;
+
+ part = iter->data;
+ end = g_strconcat (part->id, ".end", NULL);
+ for (; iter != NULL; iter = g_slist_next (iter)) {
+ part = iter->data;
+ if (!part)
+ continue;
+
+ if (g_strcmp0 (part->id, end) == 0) {
+ g_free (end);
+ return iter;
+ }
+ }
+ g_free (end);
+ return iter;
+}
diff --git a/em-format/e-mail-formatter-utils.h b/em-format/e-mail-formatter-utils.h
new file mode 100644
index 0000000000..59d8e43257
--- /dev/null
+++ b/em-format/e-mail-formatter-utils.h
@@ -0,0 +1,56 @@
+/*
+ * e-mail-formatter-utils.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_UTILS_H_
+#define E_MAIL_FORMATTER_UTILS_H_
+
+#include <camel/camel.h>
+#include <em-format/e-mail-formatter.h>
+
+G_BEGIN_DECLS
+
+void e_mail_formatter_format_header (EMailFormatter *formatter,
+ GString *buffer,
+ CamelMedium *part,
+ struct _camel_header_raw *header,
+ guint32 flags,
+ const gchar *charset);
+
+void e_mail_formatter_format_text_header
+ (EMailFormatter *formatter,
+ GString *buffer,
+ const gchar *label,
+ const gchar *value,
+ guint32 flags);
+
+gchar * e_mail_formatter_format_address (EMailFormatter *formatter,
+ GString *out,
+ struct _camel_header_address *a,
+ gchar *field,
+ gboolean no_links,
+ gboolean elipsize);
+
+void e_mail_formatter_canon_header_name
+ (gchar *name);
+
+GSList * e_mail_formatter_find_rfc822_end_iter
+ (GSList *rfc822_start_iter);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_UTILS_H_ */
diff --git a/em-format/e-mail-formatter.c b/em-format/e-mail-formatter.c
new file mode 100644
index 0000000000..a08504a21f
--- /dev/null
+++ b/em-format/e-mail-formatter.c
@@ -0,0 +1,1510 @@
+/*
+ * e-mail-formatter.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-formatter.h"
+
+#include <camel/camel.h>
+
+#include "e-mail-formatter-extension.h"
+#include "e-mail-formatter-utils.h"
+#include "e-mail-part.h"
+
+#include "e-mail-format-extensions.h"
+
+#include <e-util/e-util.h>
+#include <libebackend/libebackend.h>
+#include <gdk/gdk.h>
+#include <glib/gi18n.h>
+
+#define d(x)
+
+struct _EMailFormatterPrivate {
+ EMailImageLoadingPolicy image_loading_policy;
+
+ guint only_local_photos : 1;
+ guint show_sender_photo : 1;
+ guint show_real_date : 1;
+ guint animate_images : 1;
+
+ gchar *charset;
+ gchar *default_charset;
+
+ GQueue *header_list;
+};
+
+#define E_MAIL_FORMATTER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_FORMATTER, EMailFormatterPrivate))\
+
+static gpointer e_mail_formatter_parent_class = 0;
+
+enum {
+ PROP_0,
+ PROP_BODY_COLOR,
+ PROP_CITATION_COLOR,
+ PROP_CONTENT_COLOR,
+ PROP_FRAME_COLOR,
+ PROP_HEADER_COLOR,
+ PROP_TEXT_COLOR,
+ PROP_IMAGE_LOADING_POLICY,
+ PROP_FORCE_IMAGE_LOADING,
+ PROP_MARK_CITATIONS,
+ PROP_ONLY_LOCAL_PHOTOS,
+ PROP_SHOW_SENDER_PHOTO,
+ PROP_SHOW_REAL_DATE,
+ PROP_ANIMATE_IMAGES,
+ PROP_CHARSET,
+ PROP_DEFAULT_CHARSET
+};
+
+static void
+mail_formatter_run (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ GSList *iter;
+ gchar *hdr;
+
+ hdr = e_mail_formatter_get_html_header (formatter);
+ camel_stream_write_string (stream, hdr, cancellable, NULL);
+ g_free (hdr);
+
+ for (iter = context->parts; iter; iter = iter->next) {
+
+ EMailPart *part;
+ gboolean ok;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+
+ part = iter->data;
+ if (!part)
+ continue;
+
+ if (part->is_hidden && !part->is_error) {
+ if (g_str_has_suffix (part->id, ".rfc822")) {
+ iter = e_mail_formatter_find_rfc822_end_iter (iter);
+ }
+
+ if (!iter)
+ break;
+
+ continue;
+ }
+
+ /* Force formatting as source if needed */
+ if (context->mode != E_MAIL_FORMATTER_MODE_SOURCE) {
+
+ if (!part->mime_type)
+ continue;
+
+ ok = e_mail_formatter_format_as (
+ formatter, context, part, stream,
+ part->mime_type, cancellable);
+
+ /* If the written part was message/rfc822 then
+ * jump to the end of the message, because content
+ * of the whole message has been formatted by
+ * message_rfc822 formatter */
+ if (ok && g_str_has_suffix (part->id, ".rfc822")) {
+ iter = e_mail_formatter_find_rfc822_end_iter (iter);
+
+ if (!iter)
+ break;
+
+ continue;
+ }
+
+ } else {
+ ok = FALSE;
+ }
+
+ if (!ok) {
+ /* We don't want to source these */
+ if (g_str_has_suffix (part->id, ".headers") ||
+ g_str_has_suffix (part->id, "attachment-bar"))
+ continue;
+
+ e_mail_formatter_format_as (
+ formatter, context, part, stream,
+ "application/vnd.evolution.source", cancellable);
+
+ /* .message is the entire message. There's nothing more
+ * to be written. */
+ if (g_strcmp0 (part->id, ".message") == 0)
+ break;
+
+ /* If we just wrote source of a rfc822 message, then jump
+ * behind the message (otherwise source of all parts
+ * would be rendered twice) */
+ if (g_str_has_suffix (part->id, ".rfc822")) {
+
+ do {
+ part = iter->data;
+ if (part && g_str_has_suffix (part->id, ".rfc822.end"))
+ break;
+
+ iter = iter->next;
+ } while (iter);
+ }
+ }
+ }
+
+ camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
+}
+
+static EMailFormatterContext *
+mail_formatter_create_context (EMailFormatter *formatter)
+{
+ EMailFormatterClass *formatter_class;
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+
+ if (formatter_class->create_context) {
+ if (!formatter_class->free_context) {
+ g_warning ("%s implements create_context() but "
+ "does not implement free_context()!",
+ G_OBJECT_TYPE_NAME (formatter));
+ }
+
+ return formatter_class->create_context (formatter);
+ }
+
+ return g_new0 (EMailFormatterContext, 1);
+}
+
+static void
+mail_formatter_free_context (EMailFormatter *formatter,
+ EMailFormatterContext *context)
+{
+ EMailFormatterClass *formatter_class;
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+
+ if (formatter_class->free_context) {
+ formatter_class->free_context (formatter, context);
+ } else {
+ g_free (context);
+ }
+}
+
+static void
+mail_formatter_set_style (EMailFormatter *formatter,
+ GtkStyle *style,
+ GtkStateType state)
+{
+ GdkColor *color;
+ EMailFormatterColorType type;
+
+ g_object_freeze_notify (G_OBJECT (formatter));
+
+ color = &style->bg[state];
+ type = E_MAIL_FORMATTER_COLOR_BODY;
+ e_mail_formatter_set_color (formatter, type, color);
+
+ color = &style->base[GTK_STATE_NORMAL];
+ type = E_MAIL_FORMATTER_COLOR_CONTENT;
+ e_mail_formatter_set_color (formatter, type, color);
+
+ color = &style->dark[state];
+ type = E_MAIL_FORMATTER_COLOR_FRAME;
+ e_mail_formatter_set_color (formatter, type, color);
+
+ color = &style->fg[state];
+ type = E_MAIL_FORMATTER_COLOR_HEADER;
+ e_mail_formatter_set_color (formatter, type, color);
+
+ color = &style->text[state];
+ type = E_MAIL_FORMATTER_COLOR_TEXT;
+ e_mail_formatter_set_color (formatter, type, color);
+
+ g_object_thaw_notify (G_OBJECT (formatter));
+}
+
+static void
+e_mail_formatter_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_BODY_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_BODY,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_CITATION_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_CITATION,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_CONTENT_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_CONTENT,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_FRAME_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_FRAME,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_HEADER_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_HEADER,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_IMAGE_LOADING_POLICY:
+ e_mail_formatter_set_image_loading_policy (
+ E_MAIL_FORMATTER (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_MARK_CITATIONS:
+ e_mail_formatter_set_mark_citations (
+ E_MAIL_FORMATTER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_ONLY_LOCAL_PHOTOS:
+ e_mail_formatter_set_only_local_photos (
+ E_MAIL_FORMATTER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_SHOW_SENDER_PHOTO:
+ e_mail_formatter_set_show_sender_photo (
+ E_MAIL_FORMATTER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_SHOW_REAL_DATE:
+ e_mail_formatter_set_show_real_date (
+ E_MAIL_FORMATTER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_TEXT_COLOR:
+ e_mail_formatter_set_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_TEXT,
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_ANIMATE_IMAGES:
+ e_mail_formatter_set_animate_images (
+ E_MAIL_FORMATTER (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_CHARSET:
+ e_mail_formatter_set_charset (
+ E_MAIL_FORMATTER (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_DEFAULT_CHARSET:
+ e_mail_formatter_set_default_charset (
+ E_MAIL_FORMATTER (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_formatter_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_BODY_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_BODY));
+ return;
+
+ case PROP_CITATION_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_CITATION));
+ return;
+
+ case PROP_CONTENT_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_CONTENT));
+ return;
+
+ case PROP_FRAME_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_FRAME));
+ return;
+
+ case PROP_HEADER_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_HEADER));
+ return;
+
+ case PROP_IMAGE_LOADING_POLICY:
+ g_value_set_int (
+ value,
+ e_mail_formatter_get_image_loading_policy (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_MARK_CITATIONS:
+ g_value_set_boolean (
+ value, e_mail_formatter_get_mark_citations (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_ONLY_LOCAL_PHOTOS:
+ g_value_set_boolean (
+ value, e_mail_formatter_get_only_local_photos (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_SHOW_SENDER_PHOTO:
+ g_value_set_boolean (
+ value, e_mail_formatter_get_show_sender_photo (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_SHOW_REAL_DATE:
+ g_value_set_boolean (
+ value, e_mail_formatter_get_show_real_date (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_TEXT_COLOR:
+ g_value_set_boxed (value,
+ e_mail_formatter_get_color (
+ E_MAIL_FORMATTER (object),
+ E_MAIL_FORMATTER_COLOR_TEXT));
+ return;
+
+ case PROP_ANIMATE_IMAGES:
+ g_value_set_boolean (
+ value, e_mail_formatter_get_animate_images (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_CHARSET:
+ g_value_set_string (
+ value, e_mail_formatter_get_charset (
+ E_MAIL_FORMATTER (object)));
+ return;
+
+ case PROP_DEFAULT_CHARSET:
+ g_value_set_string (
+ value, e_mail_formatter_get_default_charset (
+ E_MAIL_FORMATTER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_formatter_init (EMailFormatter *formatter)
+{
+ formatter->priv = E_MAIL_FORMATTER_GET_PRIVATE (formatter);
+
+ formatter->priv->header_list = g_queue_new ();
+ e_mail_formatter_set_default_headers (formatter);
+}
+
+static void
+e_mail_formatter_finalize (GObject *object)
+{
+ EMailFormatterPrivate *priv;
+
+ priv = E_MAIL_FORMATTER (object)->priv;
+
+ if (priv->charset) {
+ g_free (priv->charset);
+ priv->charset = NULL;
+ }
+
+ if (priv->default_charset) {
+ g_free (priv->default_charset);
+ priv->default_charset = NULL;
+ }
+
+ if (priv->header_list) {
+ e_mail_formatter_clear_headers (E_MAIL_FORMATTER (object));
+ g_queue_free (priv->header_list);
+ priv->header_list = NULL;
+ }
+
+ /* Chain up to parent's finalize() */
+ G_OBJECT_CLASS (e_mail_formatter_parent_class)->finalize (object);
+}
+
+static void
+e_mail_formatter_base_init (EMailFormatterClass *klass)
+{
+ klass->extension_registry = g_object_new (
+ E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY, NULL);
+
+ e_mail_formatter_internal_extensions_load (
+ E_MAIL_EXTENSION_REGISTRY (klass->extension_registry));
+
+ e_extensible_load_extensions (
+ E_EXTENSIBLE (klass->extension_registry));
+
+ klass->text_html_flags =
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
+ CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
+}
+
+static void
+e_mail_formatter_base_finalize (EMailFormatterClass *klass)
+{
+ g_object_unref (klass->extension_registry);
+}
+
+static void
+e_mail_formatter_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (e_mail_formatter_parent_class)->constructed (object);
+
+ e_extensible_load_extensions (E_EXTENSIBLE (object));
+}
+
+static void
+e_mail_formatter_class_init (EMailFormatterClass *klass)
+{
+ GObjectClass *object_class;
+ GdkColor *color;
+
+ e_mail_formatter_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (EMailFormatterPrivate));
+
+ klass->run = mail_formatter_run;
+
+ /* EMailFormatter calls these directly */
+ klass->create_context = NULL;
+ klass->free_context = NULL;
+ klass->set_style = mail_formatter_set_style;
+
+ color = &klass->colors[E_MAIL_FORMATTER_COLOR_BODY];
+ gdk_color_parse ("#eeeeee", color);
+
+ color = &klass->colors[E_MAIL_FORMATTER_COLOR_CONTENT];
+ gdk_color_parse ("#ffffff", color);
+
+ color = &klass->colors[E_MAIL_FORMATTER_COLOR_FRAME];
+ gdk_color_parse ("#3f3f3f", color);
+
+ color = &klass->colors[E_MAIL_FORMATTER_COLOR_HEADER];
+ gdk_color_parse ("#eeeeee", color);
+
+ color = &klass->colors[E_MAIL_FORMATTER_COLOR_TEXT];
+ gdk_color_parse ("#000000", color);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = e_mail_formatter_constructed;
+ object_class->get_property = e_mail_formatter_get_property;
+ object_class->set_property = e_mail_formatter_set_property;
+ object_class->finalize = e_mail_formatter_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_BODY_COLOR,
+ g_param_spec_boxed (
+ "body-color",
+ "Body Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CITATION_COLOR,
+ g_param_spec_boxed (
+ "citation-color",
+ "Citation Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CONTENT_COLOR,
+ g_param_spec_boxed (
+ "content-color",
+ "Content Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FRAME_COLOR,
+ g_param_spec_boxed (
+ "frame-color",
+ "Frame Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HEADER_COLOR,
+ g_param_spec_boxed (
+ "header-color",
+ "Header Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ /* FIXME Make this a proper enum property. */
+ g_object_class_install_property (
+ object_class,
+ PROP_IMAGE_LOADING_POLICY,
+ g_param_spec_int (
+ "image-loading-policy",
+ "Image Loading Policy",
+ NULL,
+ E_MAIL_IMAGE_LOADING_POLICY_NEVER,
+ E_MAIL_IMAGE_LOADING_POLICY_ALWAYS,
+ E_MAIL_IMAGE_LOADING_POLICY_NEVER,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_MARK_CITATIONS,
+ g_param_spec_boolean (
+ "mark-citations",
+ "Mark Citations",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ONLY_LOCAL_PHOTOS,
+ g_param_spec_boolean (
+ "only-local-photos",
+ "Only Local Photos",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SHOW_SENDER_PHOTO,
+ g_param_spec_boolean (
+ "show-sender-photo",
+ "Show Sender Photo",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SHOW_REAL_DATE,
+ g_param_spec_boolean (
+ "show-real-date",
+ "Show real Date header value",
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_TEXT_COLOR,
+ g_param_spec_boxed (
+ "text-color",
+ "Text Color",
+ NULL,
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ANIMATE_IMAGES,
+ g_param_spec_boolean (
+ "animate-images",
+ "Animate images",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CHARSET,
+ g_param_spec_string (
+ "charset",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DEFAULT_CHARSET,
+ g_param_spec_string (
+ "default-charset",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+e_mail_formatter_extensible_interface_init (EExtensibleInterface *interface)
+{
+
+}
+
+EMailFormatter *
+e_mail_formatter_new (void)
+{
+ return g_object_new (E_TYPE_MAIL_FORMATTER, NULL);
+}
+
+GType
+e_mail_formatter_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EMailFormatterClass),
+ (GBaseInitFunc) e_mail_formatter_base_init,
+ (GBaseFinalizeFunc) e_mail_formatter_base_finalize,
+ (GClassInitFunc) e_mail_formatter_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailFormatter),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_mail_formatter_init,
+ NULL /* value_table */
+ };
+
+ const GInterfaceInfo e_extensible_interface_info = {
+ (GInterfaceInitFunc) e_mail_formatter_extensible_interface_init
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "EMailFormatter", &type_info, 0);
+
+ g_type_add_interface_static (type,
+ E_TYPE_EXTENSIBLE, &e_extensible_interface_info);
+ }
+
+ return type;
+}
+
+void
+e_mail_formatter_format_sync (EMailFormatter *formatter,
+ EMailPartList *parts,
+ CamelStream *stream,
+ guint32 flags,
+ EMailFormatterMode mode,
+ GCancellable *cancellable)
+{
+ EMailFormatterContext *context;
+ EMailFormatterClass *formatter_class;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (CAMEL_IS_STREAM (stream));
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+ g_return_if_fail (formatter_class->run != NULL);
+
+ context = mail_formatter_create_context (formatter);
+ context->message = parts->message;
+ context->folder = parts->folder;
+ context->message_uid = parts->message_uid;
+ context->parts = parts->list;
+ context->flags = flags;
+ context->mode = mode;
+
+ formatter_class->run (
+ formatter, context, stream, cancellable);
+
+ mail_formatter_free_context (formatter, context);
+}
+
+static void
+mail_format_async_prepare (GSimpleAsyncResult *result,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ EMailFormatterContext *context;
+ EMailFormatterClass *formatter_class;
+ CamelStream *stream;
+
+ context = g_object_get_data (G_OBJECT (result), "context");
+ stream = g_object_get_data (G_OBJECT (result), "stream");
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (object);
+ formatter_class->run (
+ E_MAIL_FORMATTER (object), context, stream, cancellable);
+}
+
+void
+e_mail_formatter_format (EMailFormatter *formatter,
+ EMailPartList *parts,
+ CamelStream *stream,
+ guint32 flags,
+ EMailFormatterMode mode,
+ GAsyncReadyCallback callback,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ EMailFormatterContext *context;
+ EMailFormatterClass *formatter_class;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (CAMEL_IS_STREAM (stream));
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+ g_return_if_fail (formatter_class->run != NULL);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (formatter), callback,
+ user_data, e_mail_formatter_format);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ if (!parts && callback) {
+ callback (G_OBJECT (formatter), G_ASYNC_RESULT (simple), user_data);
+ g_object_unref (simple);
+ return;
+ }
+
+ context = mail_formatter_create_context (formatter);
+ context->message = g_object_ref (parts->message);
+ context->folder = g_object_ref (parts->folder);
+ context->message_uid = g_strdup (parts->message_uid);
+ context->parts = g_slist_copy (parts->list);
+ g_slist_foreach (context->parts, (GFunc) e_mail_part_ref, NULL);
+ context->flags = flags;
+ context->mode = mode;
+
+ g_object_set_data (G_OBJECT (simple), "context", context);
+ g_object_set_data (G_OBJECT (simple), "stream", stream);
+
+ g_simple_async_result_run_in_thread (
+ simple, mail_format_async_prepare,
+ G_PRIORITY_DEFAULT, cancellable);
+
+ g_object_unref (simple);
+}
+
+CamelStream *
+e_mail_formatter_format_finished (EMailFormatter *formatter,
+ GAsyncResult *result,
+ GError *error)
+{
+ EMailFormatterContext *context;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+ context = g_object_get_data (G_OBJECT (result), "context");
+
+ g_free (context->message_uid);
+ g_object_unref (context->message);
+ g_object_unref (context->folder);
+ g_slist_foreach (context->parts, (GFunc) e_mail_part_unref, NULL);
+ g_slist_free (context->parts);
+ mail_formatter_free_context (formatter, context);
+
+ return g_object_get_data (G_OBJECT (result), "stream");
+}
+
+/**
+ * e_mail_formatter_format_as:
+ * @formatter: an #EMailFormatter
+ * @context: an #EMailFormatterContext
+ * @part: an #EMailPart
+ * @stream: a #CamelStream
+ * @as_mime_type: (allow-none) mime-type to use for formatting, or %NULL
+ * @cancellable: (allow-none) an optional #GCancellable
+ *
+ * Formats given @part using a @formatter extension for given mime type. When
+ * the mime type is %NULL, the function will try to lookup the best formatter
+ * for given @part by it's default mime type.
+ *
+ * Return Value: %TRUE on success, %FALSE when no suitable formatter is found or
+ * when it fails to format the part.
+ */
+gboolean
+e_mail_formatter_format_as (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ const gchar *as_mime_type,
+ GCancellable *cancellable)
+{
+ EMailExtensionRegistry *reg;
+ GQueue *formatters;
+ GList *iter;
+ gboolean ok;
+ d (
+ gint _call_i;
+ static gint _call = 0;
+ G_LOCK_DEFINE_STATIC (_call);
+ G_LOCK (_call);
+ _call++;
+ _call_i = _call;
+ G_UNLOCK (_call)
+ );
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+ g_return_val_if_fail (part, FALSE);
+ g_return_val_if_fail (CAMEL_IS_STREAM (stream), FALSE);
+
+ if (!as_mime_type || !*as_mime_type)
+ as_mime_type = part->mime_type;
+
+ if (!as_mime_type || !*as_mime_type)
+ return FALSE;
+
+ reg = e_mail_formatter_get_extension_registry (formatter);
+ formatters = e_mail_extension_registry_get_for_mime_type (
+ reg, as_mime_type);
+ if (!formatters) {
+ formatters = e_mail_extension_registry_get_fallback (
+ reg, as_mime_type);
+ }
+
+ ok = FALSE;
+
+ d(printf("(%d) Formatting for part %s of type %s (found %d formatters)\n",
+ _call_i, part->id, as_mime_type,
+ formatters ? g_queue_get_length (formatters) : 0));
+
+ if (formatters) {
+ for (iter = formatters->head; iter; iter = iter->next) {
+
+ EMailFormatterExtension *extension;
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+
+ ok = e_mail_formatter_extension_format (
+ extension, formatter, context,
+ part, stream, cancellable);
+
+ d(printf("\t(%d) trying %s...%s\n", _call_i,
+ G_OBJECT_TYPE_NAME (extension),
+ ok ? "OK" : "failed"));
+
+ if (ok)
+ break;
+ }
+ }
+
+ return ok;
+}
+
+/**
+ * em_format_format_text:
+ * @part: an #EMailPart to decode
+ * @formatter: an #EMailFormatter
+ * @stream: Where to write the converted text
+ * @cancellable: optional #GCancellable object, or %NULL
+ *
+ * Decode/output a part's content to @stream.
+ **/
+void
+e_mail_formatter_format_text (EMailFormatter *formatter,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable)
+{
+ CamelStream *filter_stream;
+ CamelMimeFilter *filter;
+ const gchar *charset = NULL;
+ CamelMimeFilterWindows *windows = NULL;
+ CamelStream *mem_stream = NULL;
+ CamelDataWrapper *dw;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ dw = CAMEL_DATA_WRAPPER (part->part);
+
+ if (formatter->priv->charset) {
+ charset = formatter->priv->charset;
+ } else if (dw->mime_type
+ && (charset = camel_content_type_param (dw->mime_type, "charset"))
+ && g_ascii_strncasecmp(charset, "iso-8859-", 9) == 0) {
+ CamelStream *null;
+
+ /* Since a few Windows mailers like to claim they sent
+ * out iso-8859-# encoded text when they really sent
+ * out windows-cp125#, do some simple sanity checking
+ * before we move on... */
+
+ null = camel_stream_null_new ();
+ filter_stream = camel_stream_filter_new (null);
+ g_object_unref (null);
+
+ windows = (CamelMimeFilterWindows *) camel_mime_filter_windows_new (charset);
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filter_stream),
+ CAMEL_MIME_FILTER (windows));
+
+ camel_data_wrapper_decode_to_stream_sync (
+ dw, (CamelStream *) filter_stream, cancellable, NULL);
+ camel_stream_flush ((CamelStream *) filter_stream, cancellable, NULL);
+ g_object_unref (filter_stream);
+
+ charset = camel_mime_filter_windows_real_charset (windows);
+ } else if (charset == NULL) {
+ charset = formatter->priv->default_charset;
+ }
+
+ mem_stream = (CamelStream *) camel_stream_mem_new ();
+ filter_stream = camel_stream_filter_new (mem_stream);
+
+ if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filter_stream),
+ CAMEL_MIME_FILTER (filter));
+ g_object_unref (filter);
+ }
+
+ camel_data_wrapper_decode_to_stream_sync (
+ camel_medium_get_content ((CamelMedium *) dw),
+ (CamelStream *) filter_stream, cancellable, NULL);
+ camel_stream_flush ((CamelStream *) filter_stream, cancellable, NULL);
+ g_object_unref (filter_stream);
+
+ g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, NULL, NULL);
+
+ camel_stream_write_to_stream (
+ mem_stream, (CamelStream *) stream, cancellable, NULL);
+ camel_stream_flush ((CamelStream *) mem_stream, cancellable, NULL);
+
+ if (windows) {
+ g_object_unref (windows);
+ }
+
+ g_object_unref (mem_stream);
+}
+
+gchar *
+e_mail_formatter_get_html_header (EMailFormatter *formatter)
+{
+ return g_strdup_printf (
+ "<!DOCTYPE HTML>\n<html>\n"
+ "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\" />\n"
+ "<title>Evolution Mail Display</title>\n"
+ "<link type=\"text/css\" rel=\"stylesheet\" href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview.css\" />\n"
+ "<style type=\"text/css\">\n"
+ " table th { color: #000; font-weight: bold; }\n"
+ "</style>\n"
+ "</head><body bgcolor=\"#%06x\">",
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_BODY)));
+}
+
+EMailExtensionRegistry *
+e_mail_formatter_get_extension_registry (EMailFormatter *formatter)
+{
+ EMailFormatterClass * formatter_class;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+ return E_MAIL_EXTENSION_REGISTRY (formatter_class->extension_registry);
+}
+
+guint32
+e_mail_formatter_get_text_format_flags (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), 0);
+
+ return E_MAIL_FORMATTER_GET_CLASS (formatter)->text_html_flags;
+}
+
+const GdkColor *
+e_mail_formatter_get_color (EMailFormatter *formatter,
+ EMailFormatterColorType type)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+ g_return_val_if_fail (type < E_MAIL_FORMATTER_NUM_COLOR_TYPES, NULL);
+
+ return &E_MAIL_FORMATTER_GET_CLASS (formatter)->colors[type];
+}
+
+void
+e_mail_formatter_set_color (EMailFormatter *formatter,
+ EMailFormatterColorType type,
+ const GdkColor *color)
+{
+ GdkColor *format_color;
+ const gchar *property_name;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (type < E_MAIL_FORMATTER_NUM_COLOR_TYPES);
+ g_return_if_fail (color != NULL);
+
+ format_color = &E_MAIL_FORMATTER_GET_CLASS (formatter)->colors[type];
+
+ if (gdk_color_equal (color, format_color))
+ return;
+
+ format_color->red = color->red;
+ format_color->green = color->green;
+ format_color->blue = color->blue;
+
+ switch (type) {
+ case E_MAIL_FORMATTER_COLOR_BODY:
+ property_name = "body-color";
+ break;
+ case E_MAIL_FORMATTER_COLOR_CITATION:
+ property_name = "citation-color";
+ break;
+ case E_MAIL_FORMATTER_COLOR_CONTENT:
+ property_name = "content-color";
+ break;
+ case E_MAIL_FORMATTER_COLOR_FRAME:
+ property_name = "frame-color";
+ break;
+ case E_MAIL_FORMATTER_COLOR_HEADER:
+ property_name = "header-color";
+ break;
+ case E_MAIL_FORMATTER_COLOR_TEXT:
+ property_name = "text-color";
+ break;
+ default:
+ g_return_if_reached ();
+ }
+
+ g_object_notify (G_OBJECT (formatter), property_name);
+}
+
+void
+e_mail_formatter_set_style (EMailFormatter *formatter,
+ GtkStyle *style,
+ GtkStateType state)
+{
+ EMailFormatterClass *formatter_class;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (GTK_IS_STYLE (style));
+
+ formatter_class = E_MAIL_FORMATTER_GET_CLASS (formatter);
+ g_return_if_fail (formatter_class->set_style != NULL);
+
+ formatter_class->set_style (formatter, style, state);
+}
+
+EMailImageLoadingPolicy
+e_mail_formatter_get_image_loading_policy (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), 0);
+
+ return formatter->priv->image_loading_policy;
+}
+
+void
+e_mail_formatter_set_image_loading_policy (EMailFormatter *formatter,
+ EMailImageLoadingPolicy policy)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ if (policy == formatter->priv->image_loading_policy)
+ return;
+
+ formatter->priv->image_loading_policy = policy;
+
+ g_object_notify (G_OBJECT (formatter), "image-loading-policy");
+}
+
+gboolean
+e_mail_formatter_get_mark_citations (EMailFormatter *formatter)
+{
+ guint32 flags;
+
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+
+ flags = E_MAIL_FORMATTER_GET_CLASS (formatter)->text_html_flags;
+
+ return ((flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) != 0);
+}
+
+void
+e_mail_formatter_set_mark_citations (EMailFormatter *formatter,
+ gboolean mark_citations)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ if (mark_citations)
+ E_MAIL_FORMATTER_GET_CLASS (formatter)->text_html_flags |=
+ CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
+ else
+ E_MAIL_FORMATTER_GET_CLASS (formatter)->text_html_flags &=
+ ~CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
+
+ g_object_notify (G_OBJECT (formatter), "mark-citations");
+}
+
+gboolean
+e_mail_formatter_get_only_local_photos (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+
+ return formatter->priv->only_local_photos;
+}
+
+void
+e_mail_formatter_set_only_local_photos (EMailFormatter *formatter,
+ gboolean only_local_photos)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ formatter->priv->only_local_photos = only_local_photos;
+
+ g_object_notify (G_OBJECT (formatter), "only-local-photos");
+}
+
+gboolean
+e_mail_formatter_get_show_sender_photo (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+
+ return formatter->priv->show_sender_photo;
+}
+
+void
+e_mail_formatter_set_show_sender_photo (EMailFormatter *formatter,
+ gboolean show_sender_photo)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ formatter->priv->show_sender_photo = show_sender_photo;
+
+ g_object_notify (G_OBJECT (formatter), "show-sender-photo");
+}
+
+gboolean
+e_mail_formatter_get_show_real_date (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+
+ return formatter->priv->show_real_date;
+}
+
+void
+e_mail_formatter_set_show_real_date (EMailFormatter *formatter,
+ gboolean show_real_date)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ formatter->priv->show_real_date = show_real_date;
+
+ g_object_notify (G_OBJECT (formatter), "show-real-date");
+}
+
+gboolean
+e_mail_formatter_get_animate_images (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
+
+ return formatter->priv->animate_images;
+}
+
+void
+e_mail_formatter_set_animate_images (EMailFormatter *formatter,
+ gboolean animate_images)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ formatter->priv->animate_images = animate_images;
+
+ g_object_notify (G_OBJECT (formatter), "animate-images");
+}
+
+const gchar *
+e_mail_formatter_get_charset (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+ return formatter->priv->charset;
+}
+
+void
+e_mail_formatter_set_charset (EMailFormatter *formatter,
+ const gchar *charset)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (charset && *charset);
+
+ if (formatter->priv->charset)
+ g_free (formatter->priv->charset);
+
+ formatter->priv->charset = g_strdup (charset);
+
+ g_object_notify (G_OBJECT (formatter), "charset");
+}
+
+const gchar *
+e_mail_formatter_get_default_charset (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+ return formatter->priv->default_charset;
+}
+
+void
+e_mail_formatter_set_default_charset (EMailFormatter *formatter,
+ const gchar *default_charset)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (default_charset && *default_charset);
+
+ if (formatter->priv->default_charset)
+ g_free (formatter->priv->default_charset);
+
+ formatter->priv->default_charset = g_strdup (default_charset);
+
+ g_object_notify (G_OBJECT (formatter), "default-charset");
+}
+
+/* note: also copied in em-mailer-prefs.c */
+static const struct {
+ const gchar *name;
+ guint32 flags;
+} default_headers[] = {
+ { N_("From"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Reply-To"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("To"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Cc"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Bcc"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Subject"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Date"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Newsgroups"), E_MAIL_FORMATTER_HEADER_FLAG_BOLD },
+ { N_("Face"), 0 },
+};
+
+/**
+ * e_mail_formatter_get_headers:
+ * @formatter: an #EMailFormatter
+ *
+ * Returns list of currently set headers.
+ *
+ * Return Value: A #GQueue of headers which you should not modify or unref
+ */
+const GQueue *
+e_mail_formatter_get_headers (EMailFormatter *formatter)
+{
+ g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
+
+ return formatter->priv->header_list;
+}
+
+/**
+ * e_mail_formatter_clear_headers:
+ * @formatter: an #EMailFormatter
+ *
+ * Clear the list of headers to be displayed. This will force all headers to
+ * be shown.
+ **/
+void
+e_mail_formatter_clear_headers (EMailFormatter *formatter)
+{
+ EMailFormatterHeader *header;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ while ((header = g_queue_pop_head (formatter->priv->header_list)) != NULL) {
+ e_mail_formatter_header_free (header);
+ }
+}
+
+/**
+ * e_mail_formatter_set_default_headers:
+ * @formatter: an #EMailFormatter
+ *
+ * Clear the list of headers and sets the default ones, e.g. "To", "From", "Cc"
+ * "Subject", etc...
+ */
+void
+e_mail_formatter_set_default_headers (EMailFormatter *formatter)
+{
+ gint ii;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ /* Set the default headers */
+ e_mail_formatter_clear_headers (formatter);
+ for (ii = 0; ii < G_N_ELEMENTS (default_headers); ii++) {
+ e_mail_formatter_add_header (
+ formatter, default_headers[ii].name, NULL,
+ default_headers[ii].flags);
+ }
+}
+
+/**
+ * e_mail_formatter_add_header:
+ * @formatter:
+ * @name: The name of the header, as it will appear during output.
+ * @value: Value of the header. Can be %NULL.
+ * @flags: EM_FORMAT_HEAD_* defines to control display attributes.
+ *
+ * Add a specific header to show. If any headers are set, they will
+ * be displayed in the order set by this function. Certain known
+ * headers included in this list will be shown using special
+ * formatting routines.
+ **/
+void
+e_mail_formatter_add_header (EMailFormatter *formatter,
+ const gchar *name,
+ const gchar *value,
+ guint32 flags)
+{
+ EMailFormatterHeader *h;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (name && *name);
+
+ h = e_mail_formatter_header_new (name, value);
+ h->flags = flags;
+ g_queue_push_tail (formatter->priv->header_list, h);
+}
+
+void
+e_mail_formatter_add_header_struct (EMailFormatter *formatter,
+ const EMailFormatterHeader *header)
+{
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (header && header->name);
+
+ e_mail_formatter_add_header (formatter, header->name, header->value, header->flags);
+}
+
+void e_mail_formatter_remove_header (EMailFormatter *formatter,
+ const gchar *name,
+ const gchar *value)
+{
+ GList *iter = NULL;
+
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+ g_return_if_fail (name && *name);
+
+ iter = g_queue_peek_head_link (formatter->priv->header_list);
+ while (iter) {
+ EMailFormatterHeader *header = iter->data;
+
+ if (!header->value || !*header->value) {
+ GList *next = iter->next;
+ if (g_strcmp0 (name, header->name) == 0)
+ g_queue_delete_link (formatter->priv->header_list, iter);
+
+ iter = next;
+ continue;
+ }
+
+ if (value && *value) {
+ if ((g_strcmp0 (name, header->name) == 0) &&
+ (g_strcmp0 (value, header->value) == 0))
+ break;
+ } else {
+ if (g_strcmp0 (name, header->name) == 0)
+ break;
+ }
+
+ iter = iter->next;
+ }
+
+ if (iter) {
+ e_mail_formatter_header_free (iter->data);
+ g_queue_delete_link (formatter->priv->header_list, iter);
+ }
+}
+
+void
+e_mail_formatter_remove_header_struct (EMailFormatter *formatter,
+ const EMailFormatterHeader *header)
+{
+ g_return_if_fail (header != NULL);
+
+ e_mail_formatter_remove_header (formatter, header->name, header->value);
+}
+
+EMailFormatterHeader *
+e_mail_formatter_header_new (const gchar *name,
+ const gchar *value)
+{
+ EMailFormatterHeader *header;
+
+ g_return_val_if_fail (name && *name, NULL);
+
+ header = g_new0 (EMailFormatterHeader, 1);
+ header->name = g_strdup (name);
+ if (value && *value)
+ header->value = g_strdup (value);
+
+ return header;
+}
+
+void
+e_mail_formatter_header_free (EMailFormatterHeader *header)
+{
+ g_return_if_fail (header);
+
+ if (header->name) {
+ g_free (header->name);
+ header->name = NULL;
+ }
+
+ if (header->value) {
+ g_free (header->value);
+ header->value = NULL;
+ }
+
+ g_free (header);
+}
diff --git a/em-format/e-mail-formatter.h b/em-format/e-mail-formatter.h
new file mode 100644
index 0000000000..aea18439b2
--- /dev/null
+++ b/em-format/e-mail-formatter.h
@@ -0,0 +1,266 @@
+/*
+ * e-mail-formatter.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_FORMATTER_H_
+#define E_MAIL_FORMATTER_H_
+
+#include <em-format/e-mail-part-list.h>
+#include <em-format/e-mail-extension-registry.h>
+#include <gdk/gdk.h>
+#include <libemail-engine/e-mail-enums.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_FORMATTER \
+ (e_mail_formatter_get_type ())
+#define E_MAIL_FORMATTER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_FORMATTER, EMailFormatter))
+#define E_MAIL_FORMATTER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_FORMATTER, EMailFormatterClass))
+#define E_IS_MAIL_FORMATTER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_FORMATTER))
+#define E_IS_MAIL_FORMATTER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_FORMATTER))
+#define E_MAIL_FORMATTER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_FORMATTER, EMailFormatterClass))
+
+G_BEGIN_DECLS;
+
+typedef enum {
+ E_MAIL_FORMATTER_MODE_INVALID = -1,
+ E_MAIL_FORMATTER_MODE_NORMAL = 0,
+ E_MAIL_FORMATTER_MODE_SOURCE,
+ E_MAIL_FORMATTER_MODE_RAW,
+ E_MAIL_FORMATTER_MODE_PRINTING,
+ E_MAIL_FORMATTER_MODE_ALL_HEADERS
+} EMailFormatterMode;
+
+typedef enum {
+ E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSABLE = 1 << 0,
+ E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSED = 1 << 1,
+ E_MAIL_FORMATTER_HEADER_FLAG_HTML = 1 << 2,
+ E_MAIL_FORMATTER_HEADER_FLAG_NOCOLUMNS = 1 << 3,
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD = 1 << 4,
+ E_MAIL_FORMATTER_HEADER_FLAG_NODEC = 1 << 5,
+ E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN = 1 << 6,
+ E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS = 1 << 7,
+ E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE = 1 << 8
+} EMailFormatterHeaderFlags;
+
+typedef enum {
+ E_MAIL_FORMATTER_COLOR_BODY, /* header area background */
+ E_MAIL_FORMATTER_COLOR_CITATION, /* citation font color */
+ E_MAIL_FORMATTER_COLOR_CONTENT, /* message area background */
+ E_MAIL_FORMATTER_COLOR_FRAME, /* frame around message area */
+ E_MAIL_FORMATTER_COLOR_HEADER, /* header font color */
+ E_MAIL_FORMATTER_COLOR_TEXT, /* message font color */
+ E_MAIL_FORMATTER_NUM_COLOR_TYPES
+} EMailFormatterColorType;
+
+typedef struct _EMailFormatter EMailFormatter;
+typedef struct _EMailFormatterClass EMailFormatterClass;
+typedef struct _EMailFormatterPrivate EMailFormatterPrivate;
+typedef struct _EMailFormatterHeader EMailFormatterHeader;
+typedef struct _EMailFormatterContext EMailFormatterContext;
+
+struct _EMailFormatterHeader {
+ guint32 flags; /* E_MAIL_FORMATTER_HEADER_FLAG_ * */
+ gchar *name;
+ gchar *value;
+};
+
+struct _EMailFormatterContext {
+ CamelMimeMessage *message;
+ CamelFolder *folder;
+ gchar *message_uid;
+ GSList *parts;
+
+ EMailFormatterMode mode;
+ guint32 flags;
+};
+
+struct _EMailFormatter {
+ GObject parent;
+ EMailFormatterPrivate *priv;
+};
+
+struct _EMailFormatterClass {
+ GObjectClass parent_class;
+
+ EMailFormatterExtensionRegistry *extension_registry;
+ guint32 text_html_flags;
+
+ /* Colors should apply globally */
+ GdkColor colors[E_MAIL_FORMATTER_NUM_COLOR_TYPES];
+
+ void (*run) (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ CamelStream *stream,
+ GCancellable *cancellable);
+
+ EMailFormatterContext * (*create_context) (EMailFormatter *formatter);
+
+ void (*free_context) (EMailFormatter *formatter,
+ EMailFormatterContext *context);
+
+ void (*set_style) (EMailFormatter *formatter,
+ GtkStyle *style,
+ GtkStateType state);
+
+};
+
+GType e_mail_formatter_get_type (void);
+
+EMailFormatter *
+ e_mail_formatter_new (void);
+
+void e_mail_formatter_format_sync (EMailFormatter *formatter,
+ EMailPartList *parts_list,
+ CamelStream *stream,
+ guint32 flags,
+ EMailFormatterMode mode,
+ GCancellable *cancellable);
+
+void e_mail_formatter_format (EMailFormatter *formatter,
+ EMailPartList *parts_list,
+ CamelStream *stream,
+ guint32 flags,
+ EMailFormatterMode mode,
+ GAsyncReadyCallback callback,
+ GCancellable *cancellable,
+ gpointer user_data);
+
+CamelStream * e_mail_formatter_format_finished
+ (EMailFormatter *formatter,
+ GAsyncResult *result,
+ GError *error);
+
+gboolean e_mail_formatter_format_as (EMailFormatter *formatter,
+ EMailFormatterContext *context,
+ EMailPart *part,
+ CamelStream *stream,
+ const gchar *as_mime_type,
+ GCancellable *cancellable);
+
+void e_mail_formatter_format_text (EMailFormatter *formatter,
+ EMailPart *part,
+ CamelStream *stream,
+ GCancellable *cancellable);
+gchar * e_mail_formatter_get_html_header
+ (EMailFormatter *formatter);
+EMailExtensionRegistry *
+ e_mail_formatter_get_extension_registry
+ (EMailFormatter *formatter);
+
+guint32 e_mail_formatter_get_text_format_flags
+ (EMailFormatter *formatter);
+
+const GdkColor *
+ e_mail_formatter_get_color (EMailFormatter *formatter,
+ EMailFormatterColorType type);
+void e_mail_formatter_set_color (EMailFormatter *efh,
+ EMailFormatterColorType type,
+ const GdkColor *color);
+void e_mail_formatter_set_style (EMailFormatter *formatter,
+ GtkStyle *style,
+ GtkStateType state);
+
+EMailImageLoadingPolicy
+ e_mail_formatter_get_image_loading_policy
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_image_loading_policy
+ (EMailFormatter *formatter,
+ EMailImageLoadingPolicy policy);
+
+gboolean e_mail_formatter_get_mark_citations
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_mark_citations
+ (EMailFormatter *formatter,
+ gboolean mark_citations);
+
+gboolean e_mail_formatter_get_only_local_photos
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_only_local_photos
+ (EMailFormatter *formatter,
+ gboolean only_local_photos);
+
+gboolean e_mail_formatter_get_show_sender_photo
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_show_sender_photo
+ (EMailFormatter *formatter,
+ gboolean show_sender_photo);
+
+gboolean e_mail_formatter_get_animate_images
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_animate_images
+ (EMailFormatter *formatter,
+ gboolean animate_images);
+
+gboolean e_mail_formatter_get_show_real_date
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_show_real_date
+ (EMailFormatter *formatter,
+ gboolean show_real_date);
+
+const gchar * e_mail_formatter_get_charset (EMailFormatter *formatter);
+void e_mail_formatter_set_charset (EMailFormatter *formatter,
+ const gchar *charset);
+
+const gchar * e_mail_formatter_get_default_charset
+ (EMailFormatter *formatter);
+void e_mail_formatter_set_default_charset
+ (EMailFormatter *formatter,
+ const gchar *charset);
+
+const GQueue * e_mail_formatter_get_headers (EMailFormatter *formatter);
+
+void e_mail_formatter_clear_headers (EMailFormatter *formatter);
+
+void e_mail_formatter_set_default_headers
+ (EMailFormatter *formatter);
+
+void e_mail_formatter_add_header (EMailFormatter *formatter,
+ const gchar *name,
+ const gchar *value,
+ guint32 flags);
+
+void e_mail_formatter_add_header_struct
+ (EMailFormatter *formatter,
+ const EMailFormatterHeader *header);
+
+void e_mail_formatter_remove_header (EMailFormatter *formatter,
+ const gchar *name,
+ const gchar *value);
+
+void e_mail_formatter_remove_header_struct
+ (EMailFormatter *formatter,
+ const EMailFormatterHeader *header);
+
+EMailFormatterHeader *
+ e_mail_formatter_header_new (const gchar *name,
+ const gchar *value);
+
+void e_mail_formatter_header_free (EMailFormatterHeader *header);
+
+G_END_DECLS
+
+#endif /* E_MAIL_FORMATTER_H_ */
diff --git a/em-format/em-inline-filter.c b/em-format/e-mail-inline-filter.c
index f70915148f..aa65708f7e 100644
--- a/em-format/em-inline-filter.c
+++ b/em-format/e-mail-inline-filter.c
@@ -26,13 +26,12 @@
#include <string.h>
-#include "em-inline-filter.h"
-
-#include "em-format/em-format.h"
+#include "e-mail-inline-filter.h"
+#include "e-mail-part-utils.h"
#define d(x)
-G_DEFINE_TYPE (EMInlineFilter, em_inline_filter, CAMEL_TYPE_MIME_FILTER)
+G_DEFINE_TYPE (EMailInlineFilter, e_mail_inline_filter, CAMEL_TYPE_MIME_FILTER)
enum {
EMIF_PLAIN,
@@ -95,7 +94,7 @@ construct_part_from_stream (CamelStream *mem,
}
static void
-inline_filter_add_part (EMInlineFilter *emif,
+inline_filter_add_part (EMailInlineFilter *emif,
const gchar *data,
gint len)
{
@@ -186,7 +185,7 @@ inline_filter_add_part (EMInlineFilter *emif,
/* pre-snoop the mime type of unknown objects, and poke and hack it into place */
if (camel_content_type_is(dw->mime_type, "application", "octet-stream")
- && (mimetype = em_format_snoop_type (part))
+ && (mimetype = e_mail_part_snoop_type (part))
&& strcmp(mimetype, "application/octet-stream") != 0) {
camel_data_wrapper_set_mime_type (dw, mimetype);
camel_mime_part_set_content_type (part, mimetype);
@@ -206,7 +205,7 @@ inline_filter_scan (CamelMimeFilter *f,
gsize len,
gint final)
{
- EMInlineFilter *emif = (EMInlineFilter *) f;
+ EMailInlineFilter *emif = (EMailInlineFilter *) f;
gchar *inptr = in, *inend = in + len;
gchar *data_start = in;
gchar *start = in;
@@ -323,7 +322,7 @@ inline_filter_scan (CamelMimeFilter *f,
static void
inline_filter_finalize (GObject *object)
{
- EMInlineFilter *emif = EM_INLINE_FILTER (object);
+ EMailInlineFilter *emif = E_MAIL_INLINE_FILTER (object);
if (emif->base_type)
camel_content_type_unref (emif->base_type);
@@ -333,7 +332,7 @@ inline_filter_finalize (GObject *object)
g_free (emif->filename);
/* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (em_inline_filter_parent_class)->finalize (object);
+ G_OBJECT_CLASS (e_mail_inline_filter_parent_class)->finalize (object);
}
static void
@@ -371,7 +370,7 @@ inline_filter_complete (CamelMimeFilter *filter,
static void
inline_filter_reset (CamelMimeFilter *filter)
{
- EMInlineFilter *emif = EM_INLINE_FILTER (filter);
+ EMailInlineFilter *emif = E_MAIL_INLINE_FILTER (filter);
GSList *l;
l = emif->parts;
@@ -389,7 +388,7 @@ inline_filter_reset (CamelMimeFilter *filter)
}
static void
-em_inline_filter_class_init (EMInlineFilterClass *class)
+e_mail_inline_filter_class_init (EMailInlineFilterClass *class)
{
GObjectClass *object_class;
CamelMimeFilterClass *mime_filter_class;
@@ -404,7 +403,7 @@ em_inline_filter_class_init (EMInlineFilterClass *class)
}
static void
-em_inline_filter_init (EMInlineFilter *emif)
+e_mail_inline_filter_init (EMailInlineFilter *emif)
{
emif->data = g_byte_array_new ();
emif->found_any = FALSE;
@@ -423,13 +422,13 @@ em_inline_filter_init (EMInlineFilter *emif)
*
* Return value:
**/
-EMInlineFilter *
-em_inline_filter_new (CamelTransferEncoding base_encoding,
- CamelContentType *base_type)
+EMailInlineFilter *
+e_mail_inline_filter_new (CamelTransferEncoding base_encoding,
+ CamelContentType *base_type)
{
- EMInlineFilter *emif;
+ EMailInlineFilter *emif;
- emif = g_object_new (EM_TYPE_INLINE_FILTER, NULL);
+ emif = g_object_new (E_TYPE_MAIL_INLINE_FILTER, NULL);
emif->base_encoding = base_encoding;
if (base_type) {
emif->base_type = base_type;
@@ -440,7 +439,7 @@ em_inline_filter_new (CamelTransferEncoding base_encoding,
}
CamelMultipart *
-em_inline_filter_get_multipart (EMInlineFilter *emif)
+e_mail_inline_filter_get_multipart (EMailInlineFilter *emif)
{
GSList *l = emif->parts;
CamelMultipart *mp;
@@ -455,7 +454,7 @@ em_inline_filter_get_multipart (EMInlineFilter *emif)
}
gboolean
-em_inline_filter_found_any (EMInlineFilter *emif)
+e_mail_inline_filter_found_any (EMailInlineFilter *emif)
{
g_return_val_if_fail (emif != NULL, FALSE);
diff --git a/em-format/em-inline-filter.h b/em-format/e-mail-inline-filter.h
index 503ec7c66c..ff8248c681 100644
--- a/em-format/em-inline-filter.h
+++ b/em-format/e-mail-inline-filter.h
@@ -21,36 +21,36 @@
*
*/
-#ifndef EM_INLINE_FILTER_H
-#define EM_INLINE_FILTER_H
+#ifndef E_MAIL_INLINE_FILTER_H
+#define E_MAIL_INLINE_FILTER_H
#include <camel/camel.h>
/* Standard GObject macros */
-#define EM_TYPE_INLINE_FILTER \
- (em_inline_filter_get_type ())
-#define EM_INLINE_FILTER(obj) \
+#define E_TYPE_MAIL_INLINE_FILTER \
+ (e_mail_inline_filter_get_type ())
+#define E_MAIL_INLINE_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_INLINE_FILTER, EMInlineFilter))
-#define EM_INLINE_FILTER_CLASS(cls) \
+ ((obj), E_TYPE_MAIL_INLINE_FILTER, EMailInlineFilter))
+#define E_MAIL_INLINE_FILTER_CLASS(cls) \
(G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_INLINE_FILTER, EMInlineFilterClass))
-#define EM_IS_INLINE_FILTER(obj) \
+ ((cls), E_TYPE_MAIL_INLINE_FILTER, EMailInlineFilterClass))
+#define E_MAIL_IS_INLINE_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_INLINE_FILTER))
-#define EM_IS_INLINE_FILTER_CLASS(cls) \
+ ((obj), E_TYPE_MAIL_INLINE_FILTER))
+#define E_MAIL_IS_INLINE_FILTER_CLASS(cls) \
(G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_INLINE_FILTER))
-#define EM_INLINE_FILTER_GET_CLASS(obj) \
+ ((cls), E_TYPE_MAIL_INLINE_FILTER))
+#define E_MAIL_INLINE_FILTER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_INLINE_FILTER, EMInlineFilterClass))
+ ((obj), E_TYPE_MAIL_INLINE_FILTER, EMailInlineFilterClass))
G_BEGIN_DECLS
-typedef struct _EMInlineFilter EMInlineFilter;
-typedef struct _EMInlineFilterClass EMInlineFilterClass;
+typedef struct _EMailInlineFilter EMailInlineFilter;
+typedef struct _EMailInlineFilterClass EMailInlineFilterClass;
-struct _EMInlineFilter {
+struct _EMailInlineFilter {
CamelMimeFilter filter;
gint state;
@@ -65,16 +65,18 @@ struct _EMInlineFilter {
gboolean found_any;
};
-struct _EMInlineFilterClass {
+struct _EMailInlineFilterClass {
CamelMimeFilterClass filter_class;
};
-GType em_inline_filter_get_type (void);
-EMInlineFilter *em_inline_filter_new (CamelTransferEncoding base_encoding,
+GType e_mail_inline_filter_get_type (void);
+EMailInlineFilter *
+ e_mail_inline_filter_new (CamelTransferEncoding base_encoding,
CamelContentType *type);
-CamelMultipart *em_inline_filter_get_multipart (EMInlineFilter *emif);
-gboolean em_inline_filter_found_any (EMInlineFilter *emif);
+CamelMultipart *e_mail_inline_filter_get_multipart
+ (EMailInlineFilter *emif);
+gboolean e_mail_inline_filter_found_any (EMailInlineFilter *emif);
G_END_DECLS
-#endif /* EM_INLINE_FILTER_H */
+#endif /* E_MAIL_INLINE_FILTER_H */
diff --git a/em-format/e-mail-parser-application-mbox.c b/em-format/e-mail-parser-application-mbox.c
new file mode 100644
index 0000000000..c396c48416
--- /dev/null
+++ b/em-format/e-mail-parser-application-mbox.c
@@ -0,0 +1,213 @@
+/*
+ * e-mail-parser-application-mbox.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserApplicationMBox {
+ GObject parent;
+} EMailParserApplicationMBox;
+
+typedef struct _EMailParserApplicationMBoxClass {
+ GObjectClass parent_class;
+} EMailParserApplicationMBoxClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserApplicationMBox,
+ e_mail_parser_application_mbox,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "application/mbox",
+ NULL };
+
+static GSList *
+empe_app_mbox_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMimeParser *mime_parser;
+ CamelStream *mem_stream;
+ camel_mime_parser_state_t state;
+ gint old_len;
+ gint messages;
+ GSList *parts;
+ GError *error;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ /* Extract messages from the application/mbox part and
+ * render them as a flat list of messages. */
+
+ /* XXX If the mbox has multiple messages, maybe render them
+ * as a multipart/digest so each message can be expanded
+ * or collapsed individually.
+ *
+ * See attachment_handler_mail_x_uid_list() for example. */
+
+ /* XXX This is based on em_utils_read_messages_from_stream().
+ * Perhaps refactor that function to return an array of
+ * messages instead of assuming we want to append them
+ * to a folder? */
+
+ mime_parser = camel_mime_parser_new ();
+ camel_mime_parser_scan_from (mime_parser, TRUE);
+
+ mem_stream = camel_stream_mem_new ();
+ camel_data_wrapper_decode_to_stream_sync (
+ camel_medium_get_content (CAMEL_MEDIUM (part)),
+ mem_stream, NULL, NULL);
+ g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, cancellable, NULL);
+
+ error = NULL;
+ camel_mime_parser_init_with_stream (mime_parser, mem_stream, &error);
+ if (error) {
+ parts = e_mail_parser_error (parser, cancellable,
+ _("Error parsing MBOX part: %s"),
+ error->message ?
+ error->message :
+ _("Unknown error"));
+ g_clear_error (&error);
+ g_object_unref (mem_stream);
+ g_object_unref (mime_parser);
+ return parts;
+ }
+
+ g_object_unref (mem_stream);
+
+ old_len = part_id->len;
+
+ /* Extract messages from the mbox. */
+ messages = 0;
+ state = camel_mime_parser_step (mime_parser, NULL, NULL);
+
+ parts = NULL;
+ while (state == CAMEL_MIME_PARSER_STATE_FROM) {
+ CamelMimeMessage *message;
+ CamelMimePart *opart;
+ GSList *new_parts;
+
+ message = camel_mime_message_new ();
+ opart = CAMEL_MIME_PART (message);
+
+ if (!camel_mime_part_construct_from_parser_sync (
+ opart, mime_parser, NULL, NULL)) {
+ g_object_unref (message);
+ break;
+ }
+
+ g_string_append_printf (part_id, ".mbox.%d", messages);
+
+ new_parts = e_mail_parser_parse_part_as (
+ parser, CAMEL_MIME_PART (message),
+ part_id, "message/rfc822", cancellable);
+
+ /* Wrap every message as attachment */
+ new_parts = e_mail_parser_wrap_as_attachment (
+ parser, CAMEL_MIME_PART (message),
+ new_parts, part_id, cancellable);
+
+ /* Inline all messages in mbox */
+ if (new_parts && new_parts->data) {
+ EMailPart *p = new_parts->data;
+
+ p->force_inline = TRUE;
+ }
+
+ parts = g_slist_concat (parts, new_parts);
+
+ g_string_truncate (part_id, old_len);
+
+ g_object_unref (message);
+
+ /* Skip past CAMEL_MIME_PARSER_STATE_FROM_END. */
+ camel_mime_parser_step (mime_parser, NULL, NULL);
+
+ state = camel_mime_parser_step (mime_parser, NULL, NULL);
+
+ messages++;
+ }
+
+ g_object_unref (mime_parser);
+
+ return parts;
+}
+
+static guint32
+empe_app_mbox_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_INLINE |
+ E_MAIL_PARSER_EXTENSION_COMPOUND_TYPE;
+}
+
+static const gchar **
+empe_app_mbox_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_application_mbox_class_init (EMailParserApplicationMBoxClass *klass)
+{
+ e_mail_parser_application_mbox_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *interface)
+{
+ interface->parse = empe_app_mbox_parse;
+ interface->get_flags = empe_app_mbox_get_flags;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *interface)
+{
+ interface->mime_types = empe_app_mbox_mime_types;
+}
+
+static void
+e_mail_parser_application_mbox_init (EMailParserApplicationMBox *self)
+{
+}
diff --git a/em-format/e-mail-parser-application-smime.c b/em-format/e-mail-parser-application-smime.c
new file mode 100644
index 0000000000..12bce2fa56
--- /dev/null
+++ b/em-format/e-mail-parser-application-smime.c
@@ -0,0 +1,199 @@
+/*
+ * e-mail-parser-application-xpkcs7mime.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserApplicationSMIME {
+ GObject parent;
+} EMailParserApplicationSMIME;
+
+typedef struct _EMailParserAppplicationSMIMEClass {
+ GObjectClass parent_class;
+} EMailParserApplicationSMIMEClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserApplicationSMIME,
+ e_mail_parser_application_smime,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "application/xpkcs7mime",
+ "application/x-pkcs7-mime",
+ "application/pkcs7-mime",
+ "application/pkcs7-signature",
+ "application/xpkcs7-signature",
+ NULL };
+
+static GSList *
+empe_app_smime_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelCipherContext *context;
+ CamelMimePart *opart;
+ CamelCipherValidity *valid;
+ GError *local_error = NULL;
+ GSList *parts, *iter;
+ CamelContentType *ct;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ ct = camel_mime_part_get_content_type (part);
+ if (camel_content_type_is (ct, "application", "pkcs7-signature") ||
+ camel_content_type_is (ct, "application", "xpkcs7-signature")) {
+ return g_slist_alloc ();
+ }
+
+ context = camel_smime_context_new (e_mail_parser_get_session (parser));
+
+ opart = camel_mime_part_new ();
+ valid = camel_cipher_context_decrypt_sync (
+ context, part, opart,
+ cancellable, &local_error);
+
+ e_mail_part_preserve_charset_in_content_type (part, opart);
+
+ if (valid == NULL) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Could not parse S/MIME message: %s"),
+ local_error->message ?
+ local_error->message :
+ _("Unknown error"));
+ g_clear_error (&local_error);
+ } else {
+ gint len = part_id->len;
+
+ g_string_append (part_id, ".encrypted");
+
+ parts = e_mail_parser_parse_part (
+ parser, opart, part_id, cancellable);
+
+ g_string_truncate (part_id, len);
+
+ /* Update validity flags of all the involved subp-arts */
+ for (iter = parts; iter; iter = iter->next) {
+
+ EMailPart *mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_SMIME);
+
+ }
+
+ /* Add a widget with details about the encryption, but only when
+ * the encrypted isn't itself secured, in that case it has created
+ * the button itself */
+ if (!e_mail_part_is_secured (opart)) {
+ GSList *button;
+ EMailPart *mail_part;
+ g_string_append (part_id, ".encrypted.button");
+
+ button = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.secure-button",
+ cancellable);
+ if (button && button->data) {
+ mail_part = button->data;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_SMIME);
+ }
+
+ parts = g_slist_concat (parts, button);
+
+ g_string_truncate (part_id, len);
+ }
+
+ camel_cipher_validity_free (valid);
+ }
+
+ g_object_unref (opart);
+ g_object_unref (context);
+
+ return parts;
+}
+
+static guint32
+empe_app_smime_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_INLINE;
+}
+
+static const gchar **
+empe_application_smime_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_application_smime_class_init (EMailParserApplicationSMIMEClass *klass)
+{
+ e_mail_parser_application_smime_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *interface)
+{
+ interface->parse = empe_app_smime_parse;
+ interface->get_flags = empe_app_smime_get_flags;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *interface)
+{
+ interface->mime_types = empe_application_smime_mime_types;
+}
+
+static void
+e_mail_parser_application_smime_init (EMailParserApplicationSMIME *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-attachment-bar.c b/em-format/e-mail-parser-attachment-bar.c
new file mode 100644
index 0000000000..009869d43c
--- /dev/null
+++ b/em-format/e-mail-parser-attachment-bar.c
@@ -0,0 +1,120 @@
+/*
+ * e-mail-parser-attachment-bar.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+#include "e-mail-part-attachment-bar.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <widgets/misc/e-attachment-bar.h>
+
+#include <camel/camel.h>
+
+static void
+mail_part_attachment_bar_free (EMailPart *part)
+{
+ EMailPartAttachmentBar *empab = (EMailPartAttachmentBar *) part;
+
+ g_clear_object (&empab->store);
+}
+
+/******************************************************************************/
+
+typedef struct _EMailParserAttachmentBar {
+ GObject parent;
+} EMailParserAttachmentBar;
+
+typedef struct _EMailParserAttachmentBarClass {
+ GObjectClass parent_class;
+} EMailParserAttachmentBarClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserAttachmentBar,
+ e_mail_parser_attachment_bar,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init))
+
+static const gchar *parser_mime_types[] = { "application/vnd.evolution.widget.attachment-bar", NULL };
+
+static GSList *
+empe_attachment_bar_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPartAttachmentBar *empab;
+ gint len;
+
+ len = part_id->len;
+ g_string_append (part_id, ".attachment-bar");
+ empab = (EMailPartAttachmentBar *) e_mail_part_subclass_new (
+ part, part_id->str, sizeof (EMailPartAttachmentBar),
+ (GFreeFunc) mail_part_attachment_bar_free);
+ empab->parent.mime_type = g_strdup ("application/vnd.evolution.widget.attachment-bar");
+ empab->store = E_ATTACHMENT_STORE (e_attachment_store_new ());
+ g_string_truncate (part_id, len);
+
+ return g_slist_append (NULL, empab);
+}
+
+static const gchar **
+empe_attachment_bar_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_attachment_bar_class_init (EMailParserAttachmentBarClass *klass)
+{
+ e_mail_parser_attachment_bar_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_attachment_bar_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_attachment_bar_mime_types;
+}
+
+static void
+e_mail_parser_attachment_bar_init (EMailParserAttachmentBar *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-extension.c b/em-format/e-mail-parser-extension.c
new file mode 100644
index 0000000000..589fae31f7
--- /dev/null
+++ b/em-format/e-mail-parser-extension.c
@@ -0,0 +1,101 @@
+/*
+ * e-mail-parser-extension.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <camel/camel.h>
+
+#include "e-mail-parser-extension.h"
+
+G_DEFINE_INTERFACE (
+ EMailParserExtension,
+ e_mail_parser_extension,
+ E_TYPE_MAIL_EXTENSION)
+
+/**
+ * EMailParserExtension:
+ *
+ * The #EMailParserExtension is an abstract interface for all extensions for
+ * #EMailParser.
+ */
+
+static void
+e_mail_parser_extension_default_init (EMailParserExtensionInterface *iface)
+{
+
+}
+
+/**
+ * e_mail_parser_extension_parse
+ * @extension: an #EMailParserExtension
+ * @parser: a #EMailParser
+ * @mime_part: (allow-none) a #CamelMimePart to parse
+ * @part_id: a #GString to which parser will append ID of the parsed part.
+ * @flags: #EMailParserFlags
+ * @cancellable: (allow-none) A #GCancellable
+ *
+ * A virtual function reimplemented in all mail parser extensions. The function
+ * decodes and parses the @mime_part, creating one or more #EMailPart<!-//>s.
+ *
+ * When the function is unable to parse the @mime_part (either because it's broken
+ * or because it is a different mimetype then the extension is specialized for), the
+ * function will return @NULL indicating the #EMailParser, that it should pick
+ * another extension.
+ *
+ * When the @mime_part contains for example multipart/mixed of one RFC822 message
+ * with an attachment and of one image, then parser must make sure that the
+ * returned #GSList is correctly ordered:
+ *
+ * part1.rfc822.plain_text
+ * part1.rfc822.attachment
+ * part2.image
+ *
+ * Implementation of this function must be thread-safe.
+ *
+ * Return value: Returns #GSList of #EMailPart<!-//>s when the part was succesfully
+ * parsed, returns @NULL when the parser is not able to parse the part.
+ */
+GSList *
+e_mail_parser_extension_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *mime_part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailParserExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER_EXTENSION (extension), NULL);
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+ interface = E_MAIL_PARSER_EXTENSION_GET_INTERFACE (extension);
+ g_return_val_if_fail (interface->parse != NULL, NULL);
+
+ return interface->parse (extension, parser, mime_part, part_id, cancellable);
+}
+
+guint32
+e_mail_parser_extension_get_flags (EMailParserExtension *extension)
+{
+ EMailParserExtensionInterface *interface;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER_EXTENSION (extension), 0);
+
+ interface = E_MAIL_PARSER_EXTENSION_GET_INTERFACE (extension);
+ if (interface->get_flags == NULL)
+ return 0;
+
+ return interface->get_flags (extension);
+}
diff --git a/em-format/e-mail-parser-extension.h b/em-format/e-mail-parser-extension.h
new file mode 100644
index 0000000000..0dcff76212
--- /dev/null
+++ b/em-format/e-mail-parser-extension.h
@@ -0,0 +1,86 @@
+/*
+ * e-mail-parser-extension.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PARSER_EXTENSION_H
+#define E_MAIL_PARSER_EXTENSION_H
+
+#include <em-format/e-mail-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_PARSER_EXTENSION \
+ (e_mail_parser_extension_get_type ())
+#define E_MAIL_PARSER_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION, EMailParserExtension))
+#define E_MAIL_PARSER_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_PARSER_EXTENSION, EMailParserExtensionInterface))
+#define E_IS_MAIL_PARSER_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION))
+#define E_IS_MAIL_PARSER_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_PARSER_EXTENSION))
+#define E_MAIL_PARSER_EXTENSION_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE \
+ ((obj), E_TYPE_MAIL_PARSER_EXTENSION, EMailParserExtensionInterface))
+
+#define EMP_EXTENSION_GET_PARSER(e) \
+ E_MAIL_PARSER (e_extension_get_extensible (E_EXTENSION (e)))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailParserExtension EMailParserExtension;
+typedef struct _EMailParserExtensionInterface EMailParserExtensionInterface;
+
+typedef enum {
+ E_MAIL_PARSER_EXTENSION_INLINE = 1 << 0, /* Don't parse as attachment */
+ E_MAIL_PARSER_EXTENSION_INLINE_DISPOSITION = 1 << 1, /* Always expand */
+ E_MAIL_PARSER_EXTENSION_COMPOUND_TYPE = 1 << 2 /* Always check what's inside */
+} EMailParserExtensionFlags;
+
+struct _EMailParserExtensionInterface {
+ EMailExtensionInterface parent_interface;
+
+ GSList * (*parse) (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *mime_part,
+ GString *part_id,
+ GCancellable *cancellable);
+
+ guint32 (*get_flags) (EMailParserExtension *extension);
+
+};
+
+GType e_mail_parser_extension_get_type
+ (void);
+
+GSList * e_mail_parser_extension_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *mime_part,
+ GString *part_id,
+ GCancellable *cancellable);
+
+guint32 e_mail_parser_extension_get_flags
+ (EMailParserExtension *extension);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PARSER_EXTENSION_H */
diff --git a/em-format/e-mail-parser-headers.c b/em-format/e-mail-parser-headers.c
new file mode 100644
index 0000000000..06f28746f0
--- /dev/null
+++ b/em-format/e-mail-parser-headers.c
@@ -0,0 +1,112 @@
+/*
+ * e-mail-parser-headers.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <libemail-engine/e-mail-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserHeaders {
+ GObject parent;
+} EMailParserHeaders;
+
+typedef struct _EMailParserHeadersClass {
+ GObjectClass parent_class;
+} EMailParserHeadersClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserHeaders,
+ e_mail_parser_headers,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "application/vnd.evolution.headers", NULL };
+
+static GSList *
+empe_headers_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ gint len;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ len = part_id->len;
+ g_string_append (part_id, ".headers");
+
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = g_strdup ("application/vnd.evolution.headers");
+ g_string_truncate (part_id, len);
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_headers_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_headers_class_init (EMailParserHeadersClass *klass)
+{
+ e_mail_parser_headers_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_headers_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_headers_mime_types;
+}
+
+static void
+e_mail_parser_headers_init (EMailParserHeaders *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-image.c b/em-format/e-mail-parser-image.c
new file mode 100644
index 0000000000..2fb1fdff2f
--- /dev/null
+++ b/em-format/e-mail-parser-image.c
@@ -0,0 +1,147 @@
+/*
+ * e-mail-parser-image.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-part-utils.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailParserImage {
+ GObject parent;
+} EMailParserImage;
+
+typedef struct _EMailParserImageClass {
+ GObjectClass parent_class;
+} EMailParserImageClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserImage,
+ e_mail_parser_image,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "image/gif",
+ "image/jpeg",
+ "image/png",
+ "image/x-png",
+ "image/x-bmp",
+ "image/bmp",
+ "image/svg",
+ "image/x-cmu-raster",
+ "image/x-ico",
+ "image/x-portable-anymap",
+ "image/x-portable-bitmap",
+ "image/x-portable-graymap",
+ "image/x-portable-pixmap",
+ "image/x-xpixmap",
+ "image/jpg",
+ "image/pjpeg",
+ NULL };
+
+static GSList *
+empe_image_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ const gchar *tmp;
+ gchar *cid;
+ gint len;
+ CamelContentType *ct;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ tmp = camel_mime_part_get_content_id (part);
+ if (tmp) {
+ cid = g_strdup_printf ("cid:%s", tmp);
+ } else {
+ cid = NULL;
+ }
+
+ len = part_id->len;
+ g_string_append (part_id, ".image");
+
+ ct = camel_mime_part_get_content_type (part);
+
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->is_attachment = TRUE;
+ mail_part->cid = cid;
+ mail_part->mime_type = ct ? camel_content_type_simple (ct) : g_strdup ("image/*");
+ mail_part->is_hidden = (cid != NULL);
+
+ g_string_truncate (part_id, len);
+
+ if (!cid) {
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, g_slist_append (NULL, mail_part),
+ part_id, cancellable);
+ }
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_image_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_image_class_init (EMailParserImageClass *klass)
+{
+ e_mail_parser_image_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_image_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_image_mime_types;
+}
+
+static void
+e_mail_parser_image_init (EMailParserImage *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-inlinepgp-encrypted.c b/em-format/e-mail-parser-inlinepgp-encrypted.c
new file mode 100644
index 0000000000..5395b7be7e
--- /dev/null
+++ b/em-format/e-mail-parser-inlinepgp-encrypted.c
@@ -0,0 +1,205 @@
+/*
+ * e-mail-parser-inlinepgp-encrypted.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserInlinePGPEncrypted {
+ GObject parent;
+} EMailParserInlinePGPEncrypted;
+
+typedef struct _EMailParserInlinePGPEncryptedClass {
+ GObjectClass parent_class;
+} EMailParserInlinePGPEncryptedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserInlinePGPEncrypted,
+ e_mail_parser_inline_pgp_encrypted,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "application/x-inlinepgp-encrypted",
+ NULL };
+
+static GSList *
+empe_inlinepgp_encrypted_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelCipherContext *cipher;
+ CamelCipherValidity *valid;
+ CamelMimePart *opart;
+ CamelDataWrapper *dw;
+ gchar *mime_type;
+ gint len;
+ GError *local_error = NULL;
+ GSList *parts, *iter;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ cipher = camel_gpg_context_new (e_mail_parser_get_session (parser));
+
+ opart = camel_mime_part_new ();
+
+ /* Decrypt the message */
+ valid = camel_cipher_context_decrypt_sync (
+ cipher, part, opart, cancellable, &local_error);
+
+ if (!valid) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Could not parse PGP message: %s"),
+ local_error->message ?
+ local_error->message :
+ _("Unknown error"));
+ g_clear_error (&local_error);
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (parser,
+ part, part_id,
+ "application/vnd.evolution.source",
+ cancellable));
+
+ g_object_unref (cipher);
+ g_object_unref (opart);
+ return parts;
+ }
+
+ dw = camel_medium_get_content ((CamelMedium *) opart);
+ mime_type = camel_data_wrapper_get_mime_type (dw);
+
+ /* this ensures to show the 'opart' as inlined, if possible */
+ if (mime_type && g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0) {
+ const gchar *snoop = e_mail_part_snoop_type (opart);
+
+ if (snoop)
+ camel_data_wrapper_set_mime_type (dw, snoop);
+ }
+
+ e_mail_part_preserve_charset_in_content_type (part, opart);
+ g_free (mime_type);
+
+ /* Pass it off to the real formatter */
+ len = part_id->len;
+ g_string_append (part_id, ".inlinepgp_encrypted");
+
+ parts = e_mail_parser_parse_part_as (
+ parser, opart, part_id,
+ camel_data_wrapper_get_mime_type (dw), cancellable);
+
+ g_string_truncate (part_id, len);
+
+ for (iter = parts; iter; iter = iter->next) {
+ EMailPart *mail_part;
+
+ mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ /* Add a widget with details about the encryption, but only when
+ * the encrypted isn't itself secured, in that case it has created
+ * the button itself */
+ if (!e_mail_part_is_secured (opart)) {
+ GSList *button;
+ EMailPart *mail_part;
+ g_string_append (part_id, ".inlinepgp_encrypted.button");
+
+ button = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.secure-button",
+ cancellable);
+ if (button && button->data) {
+ mail_part = button->data;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ parts = g_slist_concat (parts, button);
+
+ g_string_truncate (part_id, len);
+ }
+
+ /* Clean Up */
+ camel_cipher_validity_free (valid);
+ g_object_unref (opart);
+ g_object_unref (cipher);
+
+ return parts;
+}
+
+static const gchar **
+empe_inlinepgp_encrypted_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_inline_pgp_encrypted_class_init (EMailParserInlinePGPEncryptedClass *klass)
+{
+ e_mail_parser_inline_pgp_encrypted_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_inlinepgp_encrypted_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_inlinepgp_encrypted_mime_types;
+}
+
+static void
+e_mail_parser_inline_pgp_encrypted_init (EMailParserInlinePGPEncrypted *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-inlinepgp-signed.c b/em-format/e-mail-parser-inlinepgp-signed.c
new file mode 100644
index 0000000000..d90dcddd2e
--- /dev/null
+++ b/em-format/e-mail-parser-inlinepgp-signed.c
@@ -0,0 +1,230 @@
+/*
+ * e-mail-parser-inlinepgp-signed.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserInlinePGPSigned {
+ GObject parent;
+} EMailParserInlinePGPSigned;
+
+typedef struct _EMailParserInlinePGPSignedClass {
+ GObjectClass parent_class;
+} EMailParserInlinePGPSignedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserInlinePGPSigned,
+ e_mail_parser_inline_pgp_signed,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "application/x-inlinepgp-signed",
+ NULL };
+
+static GSList *
+empe_inlinepgp_signed_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelStream *filtered_stream;
+ CamelMimeFilterPgp *pgp_filter;
+ CamelContentType *content_type;
+ CamelCipherContext *cipher;
+ CamelCipherValidity *valid;
+ CamelDataWrapper *dw;
+ CamelMimePart *opart;
+ CamelStream *ostream;
+ gchar *type;
+ gint len;
+ GError *local_error = NULL;
+ GByteArray *ba;
+ GSList *parts, *iter;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ cipher = camel_gpg_context_new (e_mail_parser_get_session (parser));
+
+ /* Verify the signature of the message */
+ valid = camel_cipher_context_verify_sync (
+ cipher, part, cancellable, &local_error);
+ if (!valid) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Error verifying signature: %s"),
+ local_error->message ?
+ local_error->message :
+ _("Unknown error"));
+
+ g_clear_error (&local_error);
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source",
+ cancellable));
+
+ g_object_unref (cipher);
+ return parts;
+ }
+
+ /* Setup output stream */
+ ostream = camel_stream_mem_new ();
+ filtered_stream = camel_stream_filter_new (ostream);
+
+ /* Add PGP header / footer filter */
+ pgp_filter = (CamelMimeFilterPgp *) camel_mime_filter_pgp_new ();
+ camel_stream_filter_add (
+ CAMEL_STREAM_FILTER (filtered_stream),
+ CAMEL_MIME_FILTER (pgp_filter));
+ g_object_unref (pgp_filter);
+
+ /* Pass through the filters that have been setup */
+ dw = camel_medium_get_content ((CamelMedium *) part);
+ camel_data_wrapper_decode_to_stream_sync (
+ dw, (CamelStream *) filtered_stream, cancellable, NULL);
+ camel_stream_flush ((CamelStream *) filtered_stream, cancellable, NULL);
+ g_object_unref (filtered_stream);
+
+ /* Create a new text/plain MIME part containing the signed
+ * content preserving the original part's Content-Type params. */
+ content_type = camel_mime_part_get_content_type (part);
+ type = camel_content_type_format (content_type);
+ content_type = camel_content_type_decode (type);
+ g_free (type);
+
+ g_free (content_type->type);
+ content_type->type = g_strdup ("text");
+ g_free (content_type->subtype);
+ content_type->subtype = g_strdup ("plain");
+ type = camel_content_type_format (content_type);
+ camel_content_type_unref (content_type);
+
+ ba = camel_stream_mem_get_byte_array ((CamelStreamMem *) ostream);
+ opart = camel_mime_part_new ();
+ camel_mime_part_set_content (opart, (gchar *) ba->data, ba->len, type);
+ g_free (type);
+
+ len = part_id->len;
+ g_string_append (part_id, ".inlinepgp_signed");
+
+ parts = e_mail_parser_parse_part (
+ parser, opart, part_id, cancellable);
+
+ for (iter = parts; iter; iter = iter->next) {
+ EMailPart *mail_part;
+
+ mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_SIGNED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ g_string_truncate (part_id, len);
+
+ /* Add a widget with details about the encryption, but only when
+ * the encrypted isn't itself secured, in that case it has created
+ * the button itself */
+ if (!e_mail_part_is_secured (opart)) {
+ GSList *button;
+ EMailPart *mail_part;
+ g_string_append (part_id, ".inlinepgp_signed.button");
+
+ button = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.secure-button",
+ cancellable);
+ if (button && button->data) {
+ mail_part = button->data;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_SIGNED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ parts = g_slist_concat (parts, button);
+
+ g_string_truncate (part_id, len);
+ }
+
+ /* Clean Up */
+ camel_cipher_validity_free (valid);
+ g_object_unref (dw);
+ g_object_unref (opart);
+ g_object_unref (ostream);
+ g_object_unref (cipher);
+
+ return parts;
+}
+
+static const gchar **
+empe_inlinepgp_signed_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_inline_pgp_signed_class_init (EMailParserInlinePGPSignedClass *klass)
+{
+ e_mail_parser_inline_pgp_signed_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_inlinepgp_signed_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_inlinepgp_signed_mime_types;
+}
+
+static void
+e_mail_parser_inline_pgp_signed_init (EMailParserInlinePGPSigned *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-message-deliverystatus.c b/em-format/e-mail-parser-message-deliverystatus.c
new file mode 100644
index 0000000000..feae7c2cf5
--- /dev/null
+++ b/em-format/e-mail-parser-message-deliverystatus.c
@@ -0,0 +1,116 @@
+/*
+ * e-mail-parser-message-deliverystatus.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib-object.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMessageDeliveryStatus {
+ GObject parent;
+} EMailParserMessageDeliveryStatus;
+
+typedef struct _EMailParserMessageDeliveryStatusClass {
+ GObjectClass parent_class;
+} EMailParserMessageDeliveryStatusClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMessageDeliveryStatus,
+ e_mail_parser_message_delivery_status,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "message/delivery-status",
+ NULL };
+
+static GSList *
+empe_msg_deliverystatus_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ gsize len;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ len = part_id->len;
+ g_string_append (part_id, ".delivery-status");
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = g_strdup ("text/plain");
+
+ g_string_truncate (part_id, len);
+
+ /* The only reason for having a separate parser for
+ * message/delivery-status is to display the part as an attachment */
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, g_slist_append (NULL, mail_part),
+ part_id, cancellable);
+}
+
+static const gchar **
+empe_msg_deliverystatus_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_message_delivery_status_class_init (EMailParserMessageDeliveryStatusClass *klass)
+{
+ e_mail_parser_message_delivery_status_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_msg_deliverystatus_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_msg_deliverystatus_mime_types;
+}
+
+static void
+e_mail_parser_message_delivery_status_init (EMailParserMessageDeliveryStatus *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-message-external.c b/em-format/e-mail-parser-message-external.c
new file mode 100644
index 0000000000..8c02a3ef3b
--- /dev/null
+++ b/em-format/e-mail-parser-message-external.c
@@ -0,0 +1,211 @@
+/*
+ * e-mail-parser-message-external.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <string.h>
+#include <ctype.h>
+
+typedef struct _EMailParserMessageExternal {
+ GObject parent;
+} EMailParserMessageExternal;
+
+typedef struct _EMailParserMessageExternalClass {
+ GObjectClass parent_class;
+} EMailParserMessageExternalClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMessageExternal,
+ e_mail_parser_message_external,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "message/external-body",
+ NULL };
+
+static GSList *
+empe_msg_external_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ CamelMimePart *newpart;
+ CamelContentType *type;
+ const gchar *access_type;
+ gchar *url = NULL, *desc = NULL;
+ gchar *content;
+ gint len;
+ gchar *mime_type;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ newpart = camel_mime_part_new ();
+
+ /* needs to be cleaner */
+ type = camel_mime_part_get_content_type (part);
+ access_type = camel_content_type_param (type, "access-type");
+ if (!access_type) {
+ const gchar *msg = _("Malformed external-body part");
+ mime_type = g_strdup ("text/plain");
+ camel_mime_part_set_content (newpart, msg, strlen (msg), mime_type);
+ goto addPart;
+ }
+
+ if (!g_ascii_strcasecmp(access_type, "ftp") ||
+ !g_ascii_strcasecmp(access_type, "anon-ftp")) {
+ const gchar *name, *site, *dir, *mode;
+ gchar *path;
+ gchar ftype[16];
+
+ name = camel_content_type_param (type, "name");
+ site = camel_content_type_param (type, "site");
+ dir = camel_content_type_param (type, "directory");
+ mode = camel_content_type_param (type, "mode");
+ if (name == NULL || site == NULL)
+ goto fail;
+
+ /* Generate the path. */
+ if (dir)
+ path = g_strdup_printf("/%s/%s", *dir=='/'?dir+1:dir, name);
+ else
+ path = g_strdup_printf("/%s", *name=='/'?name+1:name);
+
+ if (mode && *mode)
+ sprintf(ftype, ";type=%c", *mode);
+ else
+ ftype[0] = 0;
+
+ url = g_strdup_printf ("ftp://%s%s%s", site, path, ftype);
+ g_free (path);
+ desc = g_strdup_printf (_("Pointer to FTP site (%s)"), url);
+ } else if (!g_ascii_strcasecmp (access_type, "local-file")) {
+ const gchar *name, *site;
+
+ name = camel_content_type_param (type, "name");
+ site = camel_content_type_param (type, "site");
+ if (name == NULL)
+ goto fail;
+
+ url = g_filename_to_uri (name, NULL, NULL);
+ if (site)
+ desc = g_strdup_printf(_("Pointer to local file (%s) valid at site \"%s\""), name, site);
+ else
+ desc = g_strdup_printf(_("Pointer to local file (%s)"), name);
+ } else if (!g_ascii_strcasecmp (access_type, "URL")) {
+ const gchar *urlparam;
+ gchar *s, *d;
+
+ /* RFC 2017 */
+ urlparam = camel_content_type_param (type, "url");
+ if (urlparam == NULL)
+ goto fail;
+
+ /* For obscure MIMEy reasons, the URL may be split into words */
+ url = g_strdup (urlparam);
+ s = d = url;
+ while (*s) {
+ if (!isspace ((guchar) * s))
+ *d++ = *s;
+ s++;
+ }
+ *d = 0;
+ desc = g_strdup_printf (_("Pointer to remote data (%s)"), url);
+ } else {
+ goto fail;
+ }
+
+ mime_type = g_strdup ("text/html");
+ content = g_strdup_printf ("<a href=\"%s\">%s</a>", url, desc);
+ camel_mime_part_set_content (newpart, content, strlen (content), mime_type);
+ g_free (content);
+
+ g_free (url);
+ g_free (desc);
+
+ goto addPart;
+
+fail:
+ content = g_strdup_printf (
+ _("Pointer to unknown external data (\"%s\" type)"),
+ access_type);
+ mime_type = g_strdup ("text/plain");
+ camel_mime_part_set_content (newpart, content, strlen (content), mime_type);
+ g_free (content);
+
+addPart:
+ len = part_id->len;
+ g_string_append (part_id, ".msg_external");
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = mime_type;
+ g_string_truncate (part_id, len);
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_msg_external_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_message_external_class_init (EMailParserMessageExternalClass *klass)
+{
+ e_mail_parser_message_external_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_msg_external_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_msg_external_mime_types;
+}
+
+static void
+e_mail_parser_message_external_init (EMailParserMessageExternal *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-message-rfc822.c b/em-format/e-mail-parser-message-rfc822.c
new file mode 100644
index 0000000000..75b0306d84
--- /dev/null
+++ b/em-format/e-mail-parser-message-rfc822.c
@@ -0,0 +1,174 @@
+/*
+ * e-mail-parser-message-rfc822.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-list.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMessageRFC822 {
+ GObject parent;
+} EMailParserMessageRFC822;
+
+typedef struct _EMailParserMessageRFC822Class {
+ GObjectClass parent_class;
+} EMailParserMessageRFC822Class;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMessageRFC822,
+ e_mail_parser_message_rfc822,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "message/rfc822",
+ "message/news",
+ "message/*",
+ NULL };
+
+static GSList *
+empe_msg_rfc822_parse (EMailParserExtension *extension,
+ EMailParser *eparser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ GSList *parts = NULL;
+ EMailPart *mail_part;
+ gint len;
+ CamelMimePart *message;
+ CamelDataWrapper *dw;
+ CamelStream *new_stream;
+ CamelMimeParser *mime_parser;
+ CamelContentType *ct;
+
+ len = part_id->len;
+ g_string_append (part_id, ".rfc822");
+
+ /* Create an empty PURI that will represent start of the RFC message */
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = g_strdup ("message/rfc822");
+ parts = g_slist_append (NULL, mail_part);
+
+ /* Sometime the _actual_ message is encapsulated in another CamelMimePart,
+ * sometimes the CamelMimePart actually represents the RFC822 message */
+ ct = camel_mime_part_get_content_type (part);
+ if (camel_content_type_is (ct, "message", "rfc822")) {
+ new_stream = camel_stream_mem_new ();
+ mime_parser = camel_mime_parser_new ();
+ message = (CamelMimePart *) camel_mime_message_new ();
+
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ camel_data_wrapper_decode_to_stream_sync (
+ dw, new_stream, cancellable, NULL);
+ g_seekable_seek (
+ G_SEEKABLE (new_stream), 0, G_SEEK_SET, cancellable, NULL);
+ camel_mime_parser_init_with_stream (
+ mime_parser, new_stream, NULL);
+ camel_mime_part_construct_from_parser_sync (
+ message, mime_parser, cancellable, NULL);
+
+ g_object_unref (mime_parser);
+ g_object_unref (new_stream);
+ } else {
+ message = g_object_ref (part);
+ }
+
+ parts = g_slist_concat (parts, e_mail_parser_parse_part_as (
+ eparser, message, part_id,
+ "application/vnd.evolution.message",
+ cancellable));
+
+ g_object_unref (message);
+
+ /* Add another generic EMailPart that represents end of the RFC message.
+ * The em_format_write() function will skip all parts between the ".rfc822"
+ * part and ".rfc822.end" part as they will be rendered in an <iframe> */
+ g_string_append (part_id, ".end");
+ mail_part = e_mail_part_new (message, part_id->str);
+ mail_part->is_hidden = TRUE;
+ parts = g_slist_append (parts, mail_part);
+ g_string_truncate (part_id, len);
+
+ if (e_mail_part_is_attachment (message)) {
+ return e_mail_parser_wrap_as_attachment (
+ eparser, message, parts, part_id, cancellable);
+ }
+
+ return parts;
+}
+
+static guint32
+empe_msg_rfc822_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_INLINE |
+ E_MAIL_PARSER_EXTENSION_COMPOUND_TYPE;
+}
+
+static const gchar **
+empe_msg_rfc822_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_message_rfc822_class_init (EMailParserMessageRFC822Class *klass)
+{
+ e_mail_parser_message_rfc822_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_msg_rfc822_parse;
+ iface->get_flags = empe_msg_rfc822_get_flags;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_msg_rfc822_mime_types;
+}
+
+static void
+e_mail_parser_message_rfc822_init (EMailParserMessageRFC822 *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-message.c b/em-format/e-mail-parser-message.c
new file mode 100644
index 0000000000..acfebb8977
--- /dev/null
+++ b/em-format/e-mail-parser-message.c
@@ -0,0 +1,129 @@
+/*
+ * e-mail-parser-message.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include "e-mail-part-utils.h"
+#include <libemail-engine/e-mail-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMessage {
+ GObject parent;
+} EMailParserMessage;
+
+typedef struct _EMailParserMessageClass {
+ GObjectClass parent_class;
+} EMailParserMessageClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMessage,
+ e_mail_parser_message,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "application/vnd.evolution.message", NULL };
+
+static GSList *
+empe_message_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ GSList *parts;
+ CamelContentType *ct;
+ gchar *mime_type;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ /* Headers */
+ parts = g_slist_concat (NULL, e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.headers",
+ cancellable));
+
+ /* Attachment Bar */
+ parts = g_slist_concat (parts, e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.attachment-bar",
+ cancellable));
+
+ ct = camel_mime_part_get_content_type (part);
+ mime_type = camel_content_type_simple (ct);
+
+ /* Actual message body */
+ parts = g_slist_concat (parts, e_mail_parser_parse_part_as (
+ parser, part, part_id, mime_type,
+ cancellable));
+
+ g_free (mime_type);
+
+ return parts;
+}
+
+static const gchar **
+empe_message_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_message_class_init (EMailParserMessageClass *klass)
+{
+ e_mail_parser_message_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_message_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_message_mime_types;
+}
+
+static void
+e_mail_parser_message_init (EMailParserMessage *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-alternative.c b/em-format/e-mail-parser-multipart-alternative.c
new file mode 100644
index 0000000000..c8bbfdc31d
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-alternative.c
@@ -0,0 +1,191 @@
+/*
+ * e-mail-parser-multipart-alternative.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMultipartAlternative {
+ GObject parent;
+} EMailParserMultipartAlternative;
+
+typedef struct _EMailParserMultipartAlternativeClass {
+ GObjectClass parent_class;
+} EMailParserMultipartAlternativeClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartAlternative,
+ e_mail_parser_multipart_alternative,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/alternative", NULL };
+
+static gboolean
+related_display_part_is_attachment (CamelMimePart *part)
+{
+ CamelMimePart *display_part;
+
+ display_part = e_mail_part_get_related_display_part (part, NULL);
+ return display_part && e_mail_part_is_attachment (display_part);
+}
+
+static GSList *
+empe_mp_alternative_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMultipart *mp;
+ gint i, nparts, bestid = 0;
+ CamelMimePart *best = NULL;
+ GSList *parts;
+ EMailExtensionRegistry *reg;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ reg = e_mail_parser_get_extension_registry (parser);
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ return e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source",
+ cancellable);
+ }
+
+ /* as per rfc, find the last part we know how to display */
+ nparts = camel_multipart_get_number (mp);
+ for (i = 0; i < nparts; i++) {
+ CamelMimePart *mpart;
+ CamelDataWrapper *data_wrapper;
+ CamelContentType *type;
+ CamelStream *null_stream;
+ gchar *mime_type;
+ gsize content_size;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ /* is it correct to use the passed in *part here? */
+ mpart = camel_multipart_get_part (mp, i);
+
+ if (mpart == NULL)
+ continue;
+
+ /* This may block even though the stream does not.
+ * XXX Pretty inefficient way to test if the MIME part
+ * is empty. Surely there's a quicker way? */
+ null_stream = camel_stream_null_new ();
+ data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (mpart));
+ camel_data_wrapper_decode_to_stream_sync (
+ data_wrapper, null_stream, cancellable, NULL);
+ content_size = CAMEL_STREAM_NULL (null_stream)->written;
+ g_object_unref (null_stream);
+
+ if (content_size == 0)
+ continue;
+
+ type = camel_mime_part_get_content_type (mpart);
+ mime_type = camel_content_type_simple (type);
+
+ camel_strdown (mime_type);
+
+ if (!e_mail_part_is_attachment (mpart) &&
+ ((camel_content_type_is (type, "multipart", "related") == 0) ||
+ !related_display_part_is_attachment (mpart)) &&
+ (e_mail_extension_registry_get_for_mime_type (reg, mime_type) ||
+ ((best == NULL) &&
+ (e_mail_extension_registry_get_fallback (reg, mime_type)))))
+ {
+ best = mpart;
+ bestid = i;
+ }
+
+ g_free (mime_type);
+ }
+
+ if (best) {
+ gint len = part_id->len;
+
+ g_string_append_printf(part_id, ".alternative.%d", bestid);
+
+ parts = e_mail_parser_parse_part (
+ parser, best, part_id, cancellable);
+
+ g_string_truncate (part_id, len);
+ } else {
+ parts = e_mail_parser_parse_part_as (
+ parser, part, part_id, "multipart/mixed", cancellable);
+ }
+
+ return parts;
+}
+
+static const gchar **
+empe_mp_alternative_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_alternative_class_init (EMailParserMultipartAlternativeClass *klass)
+{
+ e_mail_parser_multipart_alternative_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_alternative_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_alternative_mime_types;
+}
+
+static void
+e_mail_parser_multipart_alternative_init (EMailParserMultipartAlternative *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-appledouble.c b/em-format/e-mail-parser-multipart-appledouble.c
new file mode 100644
index 0000000000..5591b10dd5
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-appledouble.c
@@ -0,0 +1,130 @@
+/*
+ * e-mail-parser-multipart-appledouble.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+
+#include <camel/camel.h>
+
+typedef struct _EMailParserMultipartAppleDouble {
+ GObject parent;
+} EMailParserMultipartAppleDouble;
+
+typedef struct _EMailParserMultipartAppleDoubleClass {
+ GObjectClass parent_class;
+} EMailParserMultipartAppleDoubleClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartAppleDouble,
+ e_mail_parser_multipart_apple_double,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/appledouble", NULL };
+
+static GSList *
+empe_mp_appledouble_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMultipart *mp;
+ GSList *parts;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ parts = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source",
+ cancellable);
+ } else {
+ CamelMimePart *mime_part;
+ mime_part = camel_multipart_get_part (mp, 1);
+
+ if (mime_part) {
+ gint len;
+ /* try the data fork for something useful, doubtful but who knows */
+ len = part_id->len;
+ g_string_append_printf(part_id, ".appledouble.1");
+
+ parts = e_mail_parser_parse_part (
+ parser, mime_part, part_id, cancellable);
+
+ g_string_truncate (part_id, len);
+
+ } else {
+
+ parts = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source",
+ cancellable);
+ }
+ }
+
+ return parts;
+}
+
+static const gchar **
+empe_mp_appledouble_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_apple_double_class_init (EMailParserMultipartAppleDoubleClass *klass)
+{
+ e_mail_parser_multipart_apple_double_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_appledouble_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_appledouble_mime_types;
+}
+
+static void
+e_mail_parser_multipart_apple_double_init (EMailParserMultipartAppleDouble *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-digest.c b/em-format/e-mail-parser-multipart-digest.c
new file mode 100644
index 0000000000..5b96d1fa23
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-digest.c
@@ -0,0 +1,175 @@
+/*
+ * e-mail-parser-multipart-digest.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMultipartDigest {
+ GObject parent;
+} EMailParserMultipartDigest;
+
+typedef struct _EMailParserMultipartDigestClass {
+ GObjectClass parent_class;
+} EMailParserMultipartDigestClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartDigest,
+ e_mail_parser_multipart_digest,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/digest",
+ NULL };
+
+static GSList *
+empe_mp_digest_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMultipart *mp;
+ gint i, nparts, len;
+ GSList *parts;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ return e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source", cancellable);
+ }
+
+ len = part_id->len;
+ nparts = camel_multipart_get_number (mp);
+ parts = NULL;
+ for (i = 0; i < nparts; i++) {
+ CamelMimePart *subpart;
+ CamelContentType *ct;
+ gchar *cts;
+
+ subpart = camel_multipart_get_part (mp, i);
+
+ if (!subpart)
+ continue;
+
+ g_string_append_printf(part_id, ".digest.%d", i);
+
+ ct = camel_mime_part_get_content_type (subpart);
+
+ /* According to RFC this shouldn't happen, but who knows... */
+ if (ct && !camel_content_type_is (ct, "message", "rfc822")) {
+ cts = camel_content_type_simple (ct);
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, subpart, part_id,
+ cts, cancellable));
+
+ g_free (cts);
+ } else {
+ GSList *new_parts;
+
+ new_parts = e_mail_parser_parse_part_as (
+ parser, subpart, part_id,
+ "message/rfc822", cancellable);
+
+ /* Force the message to be collapsable */
+ if (new_parts && new_parts->data &&
+ !E_MAIL_PART (new_parts->data)->is_attachment) {
+ new_parts = e_mail_parser_wrap_as_attachment (
+ parser, subpart, new_parts, part_id,
+ cancellable);
+ }
+
+ /* Force the message to be expanded */
+ if (new_parts) {
+ EMailPart *p = new_parts->data;
+ if (p) {
+ p->force_inline = TRUE;
+ }
+ }
+
+ parts = g_slist_concat (parts, new_parts);
+ }
+
+ g_string_truncate (part_id, len);
+ }
+
+ return parts;
+}
+
+static guint32
+empe_mp_digest_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_COMPOUND_TYPE;
+}
+
+static const gchar **
+empe_mp_digest_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_digest_class_init (EMailParserMultipartDigestClass *klass)
+{
+ e_mail_parser_multipart_digest_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_digest_parse;
+ iface->get_flags = empe_mp_digest_get_flags;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_digest_mime_types;
+}
+
+static void
+e_mail_parser_multipart_digest_init (EMailParserMultipartDigest *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-encrypted.c b/em-format/e-mail-parser-multipart-encrypted.c
new file mode 100644
index 0000000000..f03588ac82
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-encrypted.c
@@ -0,0 +1,220 @@
+/*
+ * e-mail-parser-multipart-encrypted.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailParserMultipartEncrypted {
+ GObject parent;
+} EMailParserMultipartEncrypted;
+
+typedef struct _EMailParserMultipartEncryptedClass {
+ GObjectClass parent_class;
+} EMailParserMultipartEncryptedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartEncrypted,
+ e_mail_parser_multipart_encrypted,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init))
+
+static const gchar* parser_mime_types[] = { "multipart/encrypted", NULL };
+
+static GSList *
+empe_mp_encrypted_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelCipherContext *context;
+ const gchar *protocol;
+ CamelMimePart *opart;
+ CamelCipherValidity *valid;
+ CamelMultipartEncrypted *mpe;
+ GError *local_error = NULL;
+ GSList *parts;
+ gint len;
+ GSList *iter;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ mpe = (CamelMultipartEncrypted *) camel_medium_get_content ((CamelMedium *) part);
+ if (!CAMEL_IS_MULTIPART_ENCRYPTED (mpe)) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Could not parse MIME message. "
+ "Displaying as source."));
+ parts = g_slist_concat (
+ parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution/source",
+ cancellable));
+
+ return parts;
+ }
+
+ /* Currently we only handle RFC2015-style PGP encryption. */
+ protocol = camel_content_type_param (
+ ((CamelDataWrapper *)mpe)->mime_type, "protocol");
+ if (!protocol || g_ascii_strcasecmp (protocol, "application/pgp-encrypted") != 0) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Unsupported encryption type for multipart/encrypted"));
+
+ parts = g_slist_concat (
+ parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "multipart/mixed", cancellable));
+ return parts;
+ }
+
+ context = camel_gpg_context_new (e_mail_parser_get_session (parser));
+
+ opart = camel_mime_part_new ();
+ valid = camel_cipher_context_decrypt_sync (
+ context, part, opart, cancellable, &local_error);
+
+ e_mail_part_preserve_charset_in_content_type (part, opart);
+ if (valid == NULL) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Could not parse PGP/MIME message: %s"),
+ local_error->message ?
+ local_error->message :
+ _("Unknown error"));
+
+ g_clear_error (&local_error);
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "multipart/mixed", cancellable));
+
+ g_object_unref (opart);
+ g_object_unref (context);
+
+ return parts;
+ }
+
+ len = part_id->len;
+ g_string_append (part_id, ".encrypted");
+
+ parts = e_mail_parser_parse_part (
+ parser, opart, part_id, cancellable);
+
+ g_string_truncate (part_id, len);
+
+ /* Update validity of all encrypted sub-parts */
+ for (iter = parts; iter; iter = iter->next) {
+ EMailPart *mail_part;
+
+ mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ /* Add a widget with details about the encryption, but only when
+ * the decrypted part isn't itself secured, in that case it has created
+ * the button itself */
+ if (!e_mail_part_is_secured (opart)) {
+ GSList *button;
+ EMailPart *mail_part;
+ g_string_append (part_id, ".encrypted.button");
+
+ button = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.secure-button",
+ cancellable);
+ if (button && button->data) {
+ mail_part = button->data;
+
+ e_mail_part_update_validity (mail_part, valid,
+ E_MAIL_PART_VALIDITY_ENCRYPTED |
+ E_MAIL_PART_VALIDITY_PGP);
+ }
+
+ parts = g_slist_concat (parts, button);
+
+ g_string_truncate (part_id, len);
+ }
+
+ camel_cipher_validity_free (valid);
+
+ /* TODO: Make sure when we finalize this part, it is zero'd out */
+ g_object_unref (opart);
+ g_object_unref (context);
+
+ return parts;
+}
+
+static const gchar **
+empe_mp_encrypted_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_encrypted_class_init (EMailParserMultipartEncryptedClass *klass)
+{
+ e_mail_parser_multipart_encrypted_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_encrypted_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_encrypted_mime_types;
+}
+
+static void
+e_mail_parser_multipart_encrypted_init (EMailParserMultipartEncrypted *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-mixed.c b/em-format/e-mail-parser-multipart-mixed.c
new file mode 100644
index 0000000000..0da450f747
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-mixed.c
@@ -0,0 +1,158 @@
+/*
+ * e-mail-parser-multipart-mixed.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+#include <em-format/e-mail-part-utils.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMultipartMixed {
+ GObject parent;
+} EMailParserMultipartMixed;
+
+typedef struct _EMailParserMultipartMixedClass {
+ GObjectClass parent_class;
+} EMailParserMultipartMixedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartMixed,
+ e_mail_parser_multipart_mixed,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/mixed",
+ "multipart/report",
+ "multipart/*",
+ NULL };
+
+static GSList *
+empe_mp_mixed_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMultipart *mp;
+ gint i, nparts, len;
+ GSList *parts;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ parts = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source", cancellable);
+ return parts;
+ }
+
+ len = part_id->len;
+ parts = NULL;
+ nparts = camel_multipart_get_number (mp);
+ for (i = 0; i < nparts; i++) {
+ CamelMimePart *subpart;
+ CamelContentType *ct;
+ GSList *new_parts;
+
+ subpart = camel_multipart_get_part (mp, i);
+
+ g_string_append_printf(part_id, ".mixed.%d", i);
+
+ new_parts = e_mail_parser_parse_part (
+ parser, subpart, part_id, cancellable);
+
+ /* Force messages to be expandable */
+ ct = camel_mime_part_get_content_type (subpart);
+ if (!new_parts ||
+ (camel_content_type_is (ct, "message", "rfc822") &&
+ new_parts && new_parts->data &&
+ !E_MAIL_PART (new_parts->data)->is_attachment)) {
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_wrap_as_attachment (
+ parser, subpart, new_parts,
+ part_id, cancellable));
+ if (parts && parts->data)
+ E_MAIL_PART (parts->data)->force_inline = TRUE;
+ } else {
+ parts = g_slist_concat (parts, new_parts);
+ }
+
+ g_string_truncate (part_id, len);
+ }
+
+ return parts;
+}
+
+static guint32
+empe_mp_mixed_get_flags (EMailParserExtension *extension)
+{
+ return E_MAIL_PARSER_EXTENSION_COMPOUND_TYPE;
+}
+
+static const gchar **
+empe_mp_mixed_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_mixed_class_init (EMailParserMultipartMixedClass *klass)
+{
+ e_mail_parser_multipart_mixed_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_mixed_parse;
+ iface->get_flags = empe_mp_mixed_get_flags;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_mixed_mime_types;
+}
+
+static void
+e_mail_parser_multipart_mixed_init (EMailParserMultipartMixed *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-related.c b/em-format/e-mail-parser-multipart-related.c
new file mode 100644
index 0000000000..ff7621202d
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-related.c
@@ -0,0 +1,162 @@
+/*
+ * e-mail-parser-multipart-related.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserMultipartRelated {
+ GObject parent;
+} EMailParserMultipartRelated;
+
+typedef struct _EMailParserMultipartRelatedClass {
+ GObjectClass parent_class;
+} EMailParserMultipartRelatedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartRelated,
+ e_mail_parser_multipart_related,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/related",
+ NULL };
+
+static GSList *
+empe_mp_related_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMultipart *mp;
+ CamelMimePart *body_part, *display_part = NULL;
+ gint i, nparts, partidlen, displayid = 0;
+ GSList *parts;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ return e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source", cancellable);
+ }
+
+ display_part = e_mail_part_get_related_display_part (part, &displayid);
+
+ if (display_part == NULL) {
+ return e_mail_parser_parse_part_as (
+ parser, part, part_id, "multipart/mixed",
+ cancellable);
+ }
+
+ /* The to-be-displayed part goes first */
+ partidlen = part_id->len;
+ g_string_append_printf(part_id, ".related.%d", displayid);
+
+ parts = e_mail_parser_parse_part (
+ parser, display_part, part_id, cancellable);
+
+ g_string_truncate (part_id, partidlen);
+
+ /* Process the related parts */
+ nparts = camel_multipart_get_number (mp);
+ for (i = 0; i < nparts; i++) {
+ GSList *list, *iter;
+ body_part = camel_multipart_get_part (mp, i);
+ list = NULL;
+
+ if (body_part == display_part)
+ continue;
+
+ g_string_append_printf(part_id, ".related.%d", i);
+
+ list = e_mail_parser_parse_part (
+ parser, body_part, part_id, cancellable);
+
+ g_string_truncate (part_id, partidlen);
+
+ for (iter = list; iter; iter = iter->next) {
+ EMailPart *mail_part;
+
+ mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ /* Don't render the part on it's own! */
+ mail_part->is_hidden = TRUE;
+ }
+
+ parts = g_slist_concat (parts, list);
+ }
+
+ return parts;
+}
+
+static const gchar **
+empe_mp_related_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_related_class_init (EMailParserMultipartRelatedClass *klass)
+{
+ e_mail_parser_multipart_related_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_related_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_related_mime_types;
+}
+
+static void
+e_mail_parser_multipart_related_init (EMailParserMultipartRelated *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-multipart-signed.c b/em-format/e-mail-parser-multipart-signed.c
new file mode 100644
index 0000000000..37bedc91f0
--- /dev/null
+++ b/em-format/e-mail-parser-multipart-signed.c
@@ -0,0 +1,252 @@
+/*
+ * e-mail-parser-multipart-signed.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailParserMultipartSigned {
+ GObject parent;
+} EMailParserMultipartSigned;
+
+typedef struct _EMailParserMultipartSignedClass {
+ GObjectClass parent_class;
+} EMailParserMultipartSignedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserMultipartSigned,
+ e_mail_parser_multipart_signed,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar* parser_mime_types[] = { "multipart/signed",
+ "application/pgp-signature",
+ NULL };
+
+static GSList *
+empe_mp_signed_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelMimePart *cpart;
+ CamelMultipartSigned *mps;
+ CamelCipherContext *cipher = NULL;
+ CamelSession *session;
+ guint32 validity_type;
+ GSList *parts;
+ CamelCipherValidity *valid;
+ GError *local_error = NULL;
+ gint i, nparts, len;
+ gboolean secured;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ /* If the part is application/pgp-signature sub-part then skip it. */
+ if (!CAMEL_IS_MULTIPART (part)) {
+ CamelContentType *ct;
+ ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (part));
+ if (camel_content_type_is (ct, "application", "pgp-signature")) {
+ return g_slist_alloc ();
+ }
+ }
+
+ mps = (CamelMultipartSigned *) camel_medium_get_content ((CamelMedium *) part);
+ if (!CAMEL_IS_MULTIPART_SIGNED (mps)
+ || (cpart = camel_multipart_get_part ((CamelMultipart *) mps,
+ CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Could not parse MIME message. "
+ "Displaying as source."));
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source",
+ cancellable));
+ return parts;
+ }
+
+ session = e_mail_parser_get_session (parser);
+ /* FIXME: Should be done via a plugin interface */
+ /* FIXME: duplicated in em-format-html-display.c */
+ if (mps->protocol) {
+#ifdef ENABLE_SMIME
+ if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0
+ || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) {
+ cipher = camel_smime_context_new (session);
+ validity_type = E_MAIL_PART_VALIDITY_SMIME;
+ } else {
+#endif
+ if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) {
+ cipher = camel_gpg_context_new (session);
+ validity_type = E_MAIL_PART_VALIDITY_PGP;
+ }
+#ifdef ENABLE_SMIME
+ }
+#endif
+ }
+
+ if (cipher == NULL) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Unsupported signature format"));
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "multipart/mixed", cancellable));
+
+ return parts;
+ }
+
+ valid = camel_cipher_context_verify_sync (
+ cipher, part, cancellable, &local_error);
+ if (valid == NULL) {
+ parts = e_mail_parser_error (
+ parser, cancellable,
+ _("Error verifying signature: %s"),
+ local_error->message ?
+ local_error->message :
+ _("Unknown error"));
+
+ g_clear_error (&local_error);
+
+ parts = g_slist_concat (parts,
+ e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "multipart/mixed", cancellable));
+
+ g_object_unref (cipher);
+ return parts;
+ }
+
+ nparts = camel_multipart_get_number (CAMEL_MULTIPART (mps));
+ secured = FALSE;
+ len = part_id->len;
+ parts = NULL;
+ for (i = 0; i < nparts; i++) {
+ CamelMimePart *subpart;
+ GSList *mail_parts, *iter;
+ subpart = camel_multipart_get_part (CAMEL_MULTIPART (mps), i);
+
+ g_string_append_printf(part_id, ".signed.%d", i);
+
+ mail_parts = e_mail_parser_parse_part (
+ parser, subpart, part_id, cancellable);
+
+ g_string_truncate (part_id, len);
+
+ if (!secured)
+ secured = e_mail_part_is_secured (subpart);
+
+ for (iter = mail_parts; iter; iter = iter->next) {
+ EMailPart *mail_part;
+
+ mail_part = iter->data;
+ if (!mail_part)
+ continue;
+
+ e_mail_part_update_validity (mail_part, valid,
+ validity_type | E_MAIL_PART_VALIDITY_SIGNED);
+ }
+
+ parts = g_slist_concat (parts, mail_parts);
+ }
+
+ /* Add a widget with details about the encryption, but only when
+ * the encrypted isn't itself secured, in that case it has created
+ * the button itself */
+ if (!secured) {
+ GSList *button;
+ EMailPart *mail_part;
+ g_string_append (part_id, ".signed.button");
+
+ button = e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.widget.secure-button",
+ cancellable);
+ if (button && button->data) {
+ mail_part = button->data;
+
+ e_mail_part_update_validity (mail_part, valid,
+ validity_type | E_MAIL_PART_VALIDITY_SIGNED);
+ }
+
+ parts = g_slist_concat (parts, button);
+
+ g_string_truncate (part_id, len);
+ }
+
+ camel_cipher_validity_free (valid);
+
+ g_object_unref (cipher);
+
+ return parts;
+}
+
+static const gchar **
+empe_mp_signed_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_multipart_signed_class_init (EMailParserMultipartSignedClass *klass)
+{
+ e_mail_parser_multipart_signed_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_mp_signed_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_mp_signed_mime_types;
+}
+
+static void
+e_mail_parser_multipart_signed_init (EMailParserMultipartSigned *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-secure-button.c b/em-format/e-mail-parser-secure-button.c
new file mode 100644
index 0000000000..6c8a0e69c6
--- /dev/null
+++ b/em-format/e-mail-parser-secure-button.c
@@ -0,0 +1,104 @@
+/*
+ * e-mail-parser-secure-button.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "e-mail-format-extensions.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <camel/camel.h>
+
+typedef struct _EMailParserSecureButton {
+ GObject parent;
+} EMailParserSecureButton;
+
+typedef struct _EMailParserSecureButtonClass {
+ GObjectClass parent_class;
+} EMailParserSecureButtonClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserSecureButton,
+ e_mail_parser_secure_button,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init))
+
+static const gchar *parser_mime_types[] = { "application/vnd.evolution.widget.secure-button", NULL };
+
+static GSList *
+empe_secure_button_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ gint len;
+
+ len = part_id->len;
+ g_string_append (part_id, ".secure_button");
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = g_strdup ("application/vnd.evolution.widget.secure-button");
+ g_string_truncate (part_id, len);
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_secure_button_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_secure_button_class_init (EMailParserSecureButtonClass *klass)
+{
+ e_mail_parser_secure_button_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_secure_button_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_secure_button_mime_types;
+}
+
+static void
+e_mail_parser_secure_button_init (EMailParserSecureButton *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-source.c b/em-format/e-mail-parser-source.c
new file mode 100644
index 0000000000..ae1a9a3a51
--- /dev/null
+++ b/em-format/e-mail-parser-source.c
@@ -0,0 +1,108 @@
+/*
+ * e-mail-parser-source.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailParserSource {
+ GObject parent;
+} EMailParserSource;
+
+typedef struct _EMailParserSourceClass {
+ GObjectClass parent_class;
+} EMailParserSourceClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserSource,
+ e_mail_parser_source,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "application/vnd.evolution.source", NULL };
+
+static GSList *
+empe_source_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ gint len;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ len = part_id->len;
+ g_string_append (part_id, ".source");
+
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = g_strdup ("application/vnd.evolution.source");
+ g_string_truncate (part_id, len);
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_source_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_source_class_init (EMailParserSourceClass *klass)
+{
+ e_mail_parser_source_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_source_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_source_mime_types;
+}
+
+static void
+e_mail_parser_source_init (EMailParserSource *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-text-enriched.c b/em-format/e-mail-parser-text-enriched.c
new file mode 100644
index 0000000000..fad71f825b
--- /dev/null
+++ b/em-format/e-mail-parser-text-enriched.c
@@ -0,0 +1,128 @@
+/*
+ * e-mail-parser-text-enriched.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+typedef struct _EMailParserTextEnriched {
+ GObject parent;
+} EMailParserTextEnriched;
+
+typedef struct _EMailParserTextEnrichedClass {
+ GObjectClass parent_class;
+} EMailParserTextEnrichedClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserTextEnriched,
+ e_mail_parser_text_enriched,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "text/richtext",
+ "text/enriched",
+ NULL };
+
+static GSList *
+empe_text_enriched_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *mail_part;
+ const gchar *tmp;
+ gint len;
+ CamelContentType *ct;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ len = part_id->len;
+ g_string_append (part_id, ".text_enriched");
+
+ ct = camel_mime_part_get_content_type (part);
+
+ mail_part = e_mail_part_new (part, part_id->str);
+ mail_part->mime_type = ct ? camel_content_type_simple (ct) : g_strdup ("text/enriched");
+ tmp = camel_mime_part_get_content_id (part);
+ if (!tmp) {
+ mail_part->cid = NULL;
+ } else {
+ mail_part->cid = g_strdup_printf ("cid:%s", tmp);
+ }
+
+ g_string_truncate (part_id, len);
+
+ if (e_mail_part_is_attachment (part)) {
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, g_slist_append (NULL, mail_part),
+ part_id, cancellable);
+ }
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static const gchar **
+empe_text_enriched_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_text_enriched_class_init (EMailParserTextEnrichedClass *klass)
+{
+ e_mail_parser_text_enriched_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_text_enriched_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_text_enriched_mime_types;
+}
+
+static void
+e_mail_parser_text_enriched_init (EMailParserTextEnriched *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-text-html.c b/em-format/e-mail-parser-text-html.c
new file mode 100644
index 0000000000..05c7bcd242
--- /dev/null
+++ b/em-format/e-mail-parser-text-html.c
@@ -0,0 +1,138 @@
+/*
+ * e-mail-parser-text-html.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+
+#include <string.h>
+
+typedef struct _EMailParserTextHTML {
+ GObject parent;
+} EMailParserTextHTML;
+
+typedef struct _EMailParserTextHTMLClass {
+ GObjectClass parent_class;
+} EMailParserTextHTMLClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserTextHTML,
+ e_mail_parser_text_html,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "text/html", NULL };
+
+static GSList *
+empe_text_html_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPart *empart;
+ const gchar *location;
+ gchar *cid = NULL;
+ const gchar *base;
+ gint len;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ cid = NULL;
+ base = camel_medium_get_header (CAMEL_MEDIUM (part), "content-base");
+ location = camel_mime_part_get_content_location (part);
+ if (location != NULL) {
+ if (strchr (location, ':') == NULL && base != NULL) {
+ CamelURL *uri;
+ CamelURL *base_url = camel_url_new (base, NULL);
+
+ uri = camel_url_new_with_base (base_url, location);
+ cid = camel_url_to_string (uri, 0);
+ camel_url_free (uri);
+ camel_url_free (base_url);
+ } else {
+ cid = g_strdup (location);
+ }
+ }
+
+ len = part_id->len;
+ g_string_append (part_id, ".text_html");
+
+ empart = e_mail_part_new (part, part_id->str);
+ empart->mime_type = g_strdup ("text/html");
+ empart->cid = cid;
+ g_string_truncate (part_id, len);
+
+ if (e_mail_part_is_attachment (part)) {
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, g_slist_append (NULL, empart),
+ part_id, cancellable);
+ }
+
+ return g_slist_append (NULL, empart);
+}
+
+static const gchar **
+empe_text_html_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_text_html_class_init (EMailParserTextHTMLClass *klass)
+{
+ e_mail_parser_text_html_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_text_html_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_text_html_mime_types;
+}
+
+static void
+e_mail_parser_text_html_init (EMailParserTextHTML *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser-text-plain.c b/em-format/e-mail-parser-text-plain.c
new file mode 100644
index 0000000000..999030447b
--- /dev/null
+++ b/em-format/e-mail-parser-text-plain.c
@@ -0,0 +1,253 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-format-extensions.h"
+
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-inline-filter.h>
+#include <em-format/e-mail-part-utils.h>
+#include <e-util/e-util.h>
+
+#include <glib/gi18n-lib.h>
+#include <camel/camel.h>
+#include <ctype.h>
+
+typedef struct _EMailParserTextPlain {
+ GObject parent;
+} EMailParserTextPlain;
+
+typedef struct _EMailParserTextPlainClass {
+ GObjectClass parent_class;
+} EMailParserTextPlainClass;
+
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (
+ EMailParserTextPlain,
+ e_mail_parser_text_plain,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_EXTENSION,
+ e_mail_parser_mail_extension_interface_init)
+ G_IMPLEMENT_INTERFACE (
+ E_TYPE_MAIL_PARSER_EXTENSION,
+ e_mail_parser_parser_extension_interface_init));
+
+static const gchar *parser_mime_types[] = { "text/plain", "text/*", NULL };
+
+static gboolean
+part_is_empty (CamelMimePart *part)
+{
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ guint i;
+
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ ba = camel_data_wrapper_get_byte_array (dw);
+
+ if (!ba)
+ return TRUE;
+
+ for (i = 0; i < ba->len; i++) {
+
+ /* Checks for \n, \t, \f, \r, \v and space */
+ if (!isspace (ba->data[i]))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GSList *
+process_part (EMailParser *parser,
+ GString *part_id,
+ gint part_number,
+ CamelMimePart *part,
+ gboolean is_attachment,
+ GCancellable *cancellable)
+{
+ CamelContentType *type;
+ EMailPart *empart;
+ gint s_len = part_id->len;
+ GSList *parts;
+
+ if (part_is_empty (part)) {
+ return g_slist_alloc ();
+ }
+
+ type = camel_mime_part_get_content_type (part);
+ if (camel_content_type_is (type, "text", "*") &&
+ (!camel_content_type_is (type, "text", "calendar"))) {
+
+ g_string_append_printf (part_id, ".plain_text.%d", part_number);
+
+ empart = e_mail_part_new (part, part_id->str);
+ empart->mime_type = camel_content_type_simple (type);
+
+ g_string_truncate (part_id, s_len);
+
+ if (is_attachment) {
+
+ return e_mail_parser_wrap_as_attachment (
+ parser, part,
+ g_slist_append (NULL, empart),
+ part_id, cancellable);
+
+ }
+
+ return g_slist_append (NULL, empart);
+ }
+
+ g_string_append_printf (part_id, ".inline.%d", part_number);
+
+ parts = e_mail_parser_parse_part (
+ parser, CAMEL_MIME_PART (part),
+ part_id, cancellable);
+
+ g_string_truncate (part_id, s_len);
+
+ return parts;
+}
+
+static GSList *
+empe_text_plain_parse (EMailParserExtension *extension,
+ EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ GSList *parts;
+ CamelStream *filtered_stream, *null;
+ CamelMultipart *mp;
+ CamelDataWrapper *dw;
+ CamelContentType *type;
+ gint i, count;
+ EMailInlineFilter *inline_filter;
+ gboolean charset_added = FALSE;
+ const gchar *snoop_type = NULL;
+ gboolean is_attachment;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ dw = camel_medium_get_content ((CamelMedium *) part);
+ if (!dw)
+ return NULL;
+
+ /* 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_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);
+
+ 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);
+ parts = NULL;
+
+ is_attachment = ((count == 1) && (e_mail_part_is_attachment (part)));
+
+ for (i = 0; i < count; i++) {
+ CamelMimePart *newpart = camel_multipart_get_part (mp, i);
+
+ if (!newpart)
+ continue;
+
+ parts = g_slist_concat (parts,
+ process_part (
+ parser, part_id, i,
+ newpart, is_attachment,
+ cancellable));
+ }
+
+ g_object_unref (mp);
+
+ return parts;
+}
+
+static const gchar **
+empe_text_plain_mime_types (EMailExtension *extension)
+{
+ return parser_mime_types;
+}
+
+static void
+e_mail_parser_text_plain_class_init (EMailParserTextPlainClass *klass)
+{
+ e_mail_parser_text_plain_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+ iface->parse = empe_text_plain_parse;
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+ iface->mime_types = empe_text_plain_mime_types;
+}
+
+static void
+e_mail_parser_text_plain_init (EMailParserTextPlain *parser)
+{
+
+}
diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c
new file mode 100644
index 0000000000..98b31b73ad
--- /dev/null
+++ b/em-format/e-mail-parser.c
@@ -0,0 +1,693 @@
+/*
+ * e-mail-parser.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-parser.h"
+#include "e-mail-parser-extension.h"
+#include "e-mail-format-extensions.h"
+#include "e-mail-part-attachment.h"
+#include "e-mail-part-utils.h"
+
+#include <camel/camel.h>
+#include <libebackend/libebackend.h>
+
+#include <e-util/e-util.h>
+
+#include <shell/e-shell.h>
+#include <shell/e-shell-window.h>
+
+#include <widgets/misc/e-attachment.h>
+
+#include <string.h>
+
+static gpointer parent_class = 0;
+
+struct _EMailParserPrivate {
+ GMutex *mutex;
+
+ gint last_error;
+
+ CamelSession *session;
+};
+
+#define E_MAIL_PARSER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_PARSER, EMailParserPrivate))
+
+#define d(x)
+
+enum {
+ PROP_0,
+ PROP_SESSION
+};
+
+static GSList *
+mail_parser_run (EMailParser *parser,
+ CamelMimeMessage *message,
+ GCancellable *cancellable)
+{
+ GSList *parts;
+ EMailExtensionRegistry *reg;
+ GQueue *parsers;
+ GList *iter;
+ GString *part_id;
+
+ reg = e_mail_parser_get_extension_registry (parser);
+
+ parsers = e_mail_extension_registry_get_for_mime_type (
+ reg, "application/vnd.evolution.message");
+
+ if (!parsers)
+ parsers = e_mail_extension_registry_get_for_mime_type (
+ reg, "message/*");
+
+ /* parsers == NULL means, that the internal Evolution parser extensions
+ * were not loaded. Something is terribly wrong. */
+ g_return_val_if_fail (parsers != NULL, NULL);
+
+ part_id = g_string_new (".message");
+ parts = NULL;
+
+ if (!parsers) {
+ parts = e_mail_parser_wrap_as_attachment (
+ parser, CAMEL_MIME_PART (message),
+ NULL, part_id, cancellable);
+ } else {
+ for (iter = parsers->head; iter; iter = iter->next) {
+
+ EMailParserExtension *extension;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+
+ parts = e_mail_parser_extension_parse (
+ extension, parser, CAMEL_MIME_PART (message),
+ part_id, cancellable);
+
+ if (parts != NULL)
+ break;
+ }
+
+ parts = g_slist_prepend (
+ parts,
+ e_mail_part_new (
+ CAMEL_MIME_PART (message),
+ ".message"));
+ }
+
+ g_string_free (part_id, TRUE);
+
+ return parts;
+}
+
+static void
+mail_parser_set_session (EMailParser *parser,
+ CamelSession *session)
+{
+ g_return_if_fail (E_IS_MAIL_PARSER (parser));
+ g_return_if_fail (CAMEL_IS_SESSION (session));
+
+ g_object_ref (session);
+
+ if (parser->priv->session)
+ g_object_unref (parser->priv->session);
+
+ parser->priv->session = session;
+}
+
+static void
+e_mail_parser_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EMailParser *parser = E_MAIL_PARSER (object);
+
+ switch (property_id) {
+ case PROP_SESSION:
+ mail_parser_set_session (parser,
+ CAMEL_SESSION (g_value_get_object (value)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_parser_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EMailParser *parser = E_MAIL_PARSER (object);
+
+ switch (property_id) {
+ case PROP_SESSION:
+ g_value_set_object (value,
+ G_OBJECT (e_mail_parser_get_session (parser)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_parser_finalize (GObject *object)
+{
+ EMailParserPrivate *priv;
+
+ priv = E_MAIL_PARSER (object)->priv;
+
+ if (priv->mutex) {
+ g_mutex_free (priv->mutex);
+ priv->mutex = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+static void
+e_mail_parser_init (EMailParser *parser)
+{
+ parser->priv = E_MAIL_PARSER_GET_PRIVATE (parser);
+
+ parser->priv->mutex = g_mutex_new ();
+}
+
+static void
+e_mail_parser_base_init (EMailParserClass *klass)
+{
+ klass->extension_registry = g_object_new (
+ E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, NULL);
+
+ e_mail_parser_internal_extensions_load (
+ E_MAIL_EXTENSION_REGISTRY (klass->extension_registry));
+
+ e_extensible_load_extensions (E_EXTENSIBLE (klass->extension_registry));
+}
+
+static void
+e_mail_parser_base_finalize (EMailParserClass *klass)
+{
+ g_object_unref (klass->extension_registry);
+}
+
+static void
+e_mail_parser_class_init (EMailParserClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (EMailParserPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = e_mail_parser_finalize;
+ object_class->set_property = e_mail_parser_set_property;
+ object_class->get_property = e_mail_parser_get_property;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SESSION,
+ g_param_spec_object (
+ "session",
+ "Camel Session",
+ NULL,
+ CAMEL_TYPE_SESSION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+GType
+e_mail_parser_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EMailParserClass),
+ (GBaseInitFunc) e_mail_parser_base_init,
+ (GBaseFinalizeFunc) e_mail_parser_base_finalize,
+ (GClassInitFunc) e_mail_parser_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailParser),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_mail_parser_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EMailParser",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+EMailParser *
+e_mail_parser_new (CamelSession *session)
+{
+ return g_object_new (E_TYPE_MAIL_PARSER,
+ "session", session, NULL);
+}
+
+/**
+ * e_mail_parser_parse_sync:
+ * @parser: an #EMailParser
+ * @folder: (allow none) a #CamelFolder containing the @message or %NULL
+ * @message_uid: (allow none) UID of the @message within the @folder or %NULL
+ * @message: a #CamelMimeMessage
+ * @cancellable: (allow-none) a #GCancellable
+ *
+ * Parses the @message synchronously. Returns a list of #EMailPart<!-//>s which
+ * represents structure of the message and additional properties of each part.
+ *
+ * Note that this function can block for a while, so it's not a good idea to call
+ * it from main thread.
+ *
+ * Return Value: An #EMailPartsList
+ */
+EMailPartList *
+e_mail_parser_parse_sync (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GCancellable *cancellable)
+{
+ EMailPartList *parts_list;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+ g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+ parts_list = e_mail_part_list_new ();
+
+ if (folder)
+ parts_list->folder = g_object_ref (folder);
+
+ if (message_uid)
+ parts_list->message_uid = g_strdup (message_uid);
+
+ parts_list->message = g_object_ref (message);
+
+ parts_list->list = mail_parser_run (parser, message, cancellable);
+
+ return parts_list;
+}
+
+static void
+mail_parser_prepare_async (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ CamelMimeMessage *message;
+ GSList *list;
+
+ message = g_object_get_data (G_OBJECT (res), "message");
+
+ list = mail_parser_run (E_MAIL_PARSER (object), message, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (res, list, NULL);
+}
+
+/**
+ * e_mail_parser_parse:
+ * @parser: an #EMailParser
+ * @message: a #CamelMimeMessage
+ * @callback: a #GAsyncReadyCallback
+ * @cancellable: (allow-none) a #GCancellable
+ * @user_data: (allow-none) user data passed to the callback
+ *
+ * Asynchronous version of #e_mail_parser_parse_sync().
+ */
+void
+e_mail_parser_parse (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GAsyncReadyCallback callback,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ g_return_if_fail (E_IS_MAIL_PARSER (parser));
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+
+ result = g_simple_async_result_new (
+ G_OBJECT (parser), callback,
+ user_data, e_mail_parser_parse);
+
+ g_object_set_data (G_OBJECT (result), "message", g_object_ref (message));
+
+ if (folder)
+ g_object_set_data (G_OBJECT (result), "folder", g_object_ref (folder));
+ if (message_uid)
+ g_object_set_data (G_OBJECT (result), "message_uid", g_strdup (message_uid));
+
+ g_simple_async_result_run_in_thread (
+ result, mail_parser_prepare_async, G_PRIORITY_DEFAULT, cancellable);
+}
+
+EMailPartList *
+e_mail_parser_parse_finish (EMailParser *parser,
+ GAsyncResult *result,
+ GError **error)
+{
+ EMailPartList *parts_list;
+
+ parts_list = e_mail_part_list_new ();
+
+ /* The data were ref'ed or copied in e_mail_parser_parse_async */
+ parts_list->message = g_object_get_data (G_OBJECT (result), "message");
+ parts_list->folder = g_object_get_data (G_OBJECT (result), "folder");
+ parts_list->message_uid = g_object_get_data (G_OBJECT (result), "message_uid");
+
+ parts_list->list = g_simple_async_result_get_op_res_gpointer (
+ G_SIMPLE_ASYNC_RESULT (result));
+
+ if (camel_debug_start ("emformat:parser")) {
+ GSList *iter;
+
+ printf("%s finished with EMailPartList:\n",
+ G_OBJECT_TYPE_NAME (parser));
+
+ for (iter = parts_list->list; iter; iter = iter->next) {
+ EMailPart *part = iter->data;
+ if (!part) continue;
+ printf(" id: %s | cid: %s | mime_type: %s | is_hidden: %d | is_attachment: %d\n",
+ part->id, part->cid, part->mime_type,
+ part->is_hidden ? 1 : 0, part->is_attachment ? 1 : 0);
+ }
+
+ camel_debug_end ();
+ }
+
+ return parts_list;
+}
+
+GSList *
+e_mail_parser_parse_part (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ CamelContentType *ct;
+ gchar *mime_type;
+ GSList *list;
+
+ ct = camel_mime_part_get_content_type (part);
+ if (!ct) {
+ mime_type = (gchar *) "application/vnd.evolution.error";
+ } else {
+ gchar *tmp;
+ tmp = camel_content_type_simple (ct);
+ mime_type = g_ascii_strdown (tmp, -1);
+ g_free (tmp);
+ }
+
+ list = e_mail_parser_parse_part_as (
+ parser, part, part_id, mime_type, cancellable);
+
+ if (ct) {
+ g_free (mime_type);
+ }
+
+ return list;
+}
+
+GSList *
+e_mail_parser_parse_part_as (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ const gchar *mime_type,
+ GCancellable *cancellable)
+{
+ GQueue *parsers;
+ GList *iter;
+ EMailExtensionRegistry *reg;
+ EMailParserClass *parser_class;
+ GSList *part_list;
+ gchar *as_mime_type;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
+
+ if (mime_type)
+ as_mime_type = g_ascii_strdown (mime_type, -1);
+ else
+ as_mime_type = NULL;
+
+ parser_class = E_MAIL_PARSER_GET_CLASS (parser);
+ reg = E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
+
+ parsers = e_mail_extension_registry_get_for_mime_type (reg, as_mime_type);
+ if (!parsers) {
+ parsers = e_mail_extension_registry_get_fallback (reg, as_mime_type);
+ }
+
+ if (as_mime_type)
+ g_free (as_mime_type);
+
+ if (!parsers) {
+ return e_mail_parser_wrap_as_attachment (
+ parser, part, NULL, part_id, cancellable);
+ }
+
+ for (iter = parsers->head; iter; iter = iter->next) {
+ EMailParserExtension *extension;
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+
+ part_list = e_mail_parser_extension_parse (
+ extension, parser, part, part_id, cancellable);
+
+ if (part_list)
+ break;
+ }
+
+ return part_list;
+}
+
+GSList *
+e_mail_parser_error (EMailParser *parser,
+ GCancellable *cancellable,
+ const gchar *format,
+ ...)
+{
+ EMailPart *mail_part;
+ CamelMimePart *part;
+ gchar *errmsg;
+ gchar *uri;
+ va_list ap;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+ g_return_val_if_fail (format != NULL, NULL);
+
+ va_start (ap, format);
+ errmsg = g_strdup_vprintf (format, ap);
+
+ part = camel_mime_part_new ();
+ camel_mime_part_set_content (part,
+ errmsg, strlen (errmsg),
+ "application/vnd.evolution.error");
+ g_free (errmsg);
+ va_end (ap);
+
+ g_mutex_lock (parser->priv->mutex);
+ parser->priv->last_error++;
+ uri = g_strdup_printf (".error.%d", parser->priv->last_error);
+ g_mutex_unlock (parser->priv->mutex);
+
+ mail_part = e_mail_part_new (part, uri);
+ mail_part->mime_type = g_strdup ("application/vnd.evolution.error");
+ mail_part->is_error = TRUE;
+
+ g_free (uri);
+ g_object_unref (part);
+
+ return g_slist_append (NULL, mail_part);
+}
+
+static void
+attachment_loaded (EAttachment *attachment,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EShell *shell;
+ GtkWindow *window;
+
+ shell = e_shell_get_default ();
+ window = e_shell_get_active_window (shell);
+
+ e_attachment_load_handle_error (attachment, res, window);
+
+ g_object_unref (attachment);
+}
+
+/* Idle callback */
+static gboolean
+load_attachment_idle (EAttachment *attachment)
+{
+ e_attachment_load_async (attachment,
+ (GAsyncReadyCallback) attachment_loaded, NULL);
+
+ return FALSE;
+}
+
+GSList *
+e_mail_parser_wrap_as_attachment (EMailParser *parser,
+ CamelMimePart *part,
+ GSList *parts,
+ GString *part_id,
+ GCancellable *cancellable)
+{
+ EMailPartAttachment *empa;
+ const gchar *snoop_mime_type, *cid;
+ GQueue *extensions;
+ CamelContentType *ct;
+ gchar *mime_type;
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ gsize size;
+ gint part_id_len;
+
+ ct = camel_mime_part_get_content_type (part);
+ extensions = NULL;
+ snoop_mime_type = NULL;
+ if (ct) {
+ EMailExtensionRegistry *reg;
+ mime_type = camel_content_type_simple (ct);
+
+ reg = e_mail_parser_get_extension_registry (parser);
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, mime_type);
+
+ if (camel_content_type_is (ct, "text", "*") ||
+ camel_content_type_is (ct, "message", "rfc822"))
+ snoop_mime_type = mime_type;
+ else
+ g_free (mime_type);
+ }
+
+ if (!snoop_mime_type)
+ snoop_mime_type = e_mail_part_snoop_type (part);
+
+ if (parts)
+ printf("WRAPPING %s AS %s\n", E_MAIL_PART (parts->data)->id, snoop_mime_type);
+
+ if (!extensions) {
+ EMailExtensionRegistry *reg;
+
+ reg = e_mail_parser_get_extension_registry (parser);
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, snoop_mime_type);
+
+ if (!extensions) {
+ extensions = e_mail_extension_registry_get_fallback (
+ reg, snoop_mime_type);
+ }
+ }
+
+ part_id_len = part_id->len;
+ g_string_append (part_id, ".attachment");
+
+ empa = (EMailPartAttachment *) e_mail_part_subclass_new (
+ part, part_id->str, sizeof (EMailPartAttachment),
+ (GFreeFunc) e_mail_part_attachment_free);
+ empa->parent.mime_type = g_strdup ("application/vnd.evolution.attachment");
+ empa->parent.is_attachment = TRUE;
+ empa->shown = extensions && (!g_queue_is_empty (extensions) &&
+ e_mail_part_is_inline (part, extensions));
+ empa->snoop_mime_type = snoop_mime_type;
+ empa->attachment = e_attachment_new ();
+ empa->attachment_view_part_id = parts ? g_strdup (E_MAIL_PART (parts->data)->id) : NULL;
+
+ cid = camel_mime_part_get_content_id (part);
+ if (cid)
+ empa->parent.cid = g_strdup_printf ("cid:%s", cid);
+
+ e_attachment_set_mime_part (empa->attachment, part);
+ e_attachment_set_shown (empa->attachment, empa->shown);
+ e_attachment_set_can_show (empa->attachment,
+ extensions && !g_queue_is_empty (extensions));
+
+ /* Try to guess size of the attachments */
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ ba = camel_data_wrapper_get_byte_array (dw);
+ if (ba) {
+ size = ba->len;
+
+ if (camel_mime_part_get_encoding (part) == CAMEL_TRANSFER_ENCODING_BASE64)
+ size = size / 1.37;
+ }
+
+ /* e_attachment_load_async must be called from main thread */
+ g_idle_add (
+ (GSourceFunc) load_attachment_idle,
+ g_object_ref (empa->attachment));
+
+ if (size != 0) {
+ GFileInfo *fileinfo;
+
+ fileinfo = e_attachment_get_file_info (empa->attachment);
+
+ if (!fileinfo) {
+ fileinfo = g_file_info_new ();
+ g_file_info_set_content_type (
+ fileinfo, empa->snoop_mime_type);
+ } else {
+ g_object_ref (fileinfo);
+ }
+
+ g_file_info_set_size (fileinfo, size);
+ e_attachment_set_file_info (empa->attachment, fileinfo);
+
+ g_object_unref (fileinfo);
+ }
+
+ if (parts && parts->data) {
+ E_MAIL_PART (parts->data)->is_hidden = TRUE;
+ }
+
+ g_string_truncate (part_id, part_id_len);
+
+ return g_slist_prepend (parts, empa);
+}
+
+CamelSession *
+e_mail_parser_get_session (EMailParser *parser)
+{
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+ return parser->priv->session;
+}
+
+EMailExtensionRegistry *
+e_mail_parser_get_extension_registry (EMailParser *parser)
+{
+ EMailParserClass *parser_class;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+ parser_class = E_MAIL_PARSER_GET_CLASS (parser);
+ return E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
+}
diff --git a/em-format/e-mail-parser.h b/em-format/e-mail-parser.h
new file mode 100644
index 0000000000..202e28d267
--- /dev/null
+++ b/em-format/e-mail-parser.h
@@ -0,0 +1,114 @@
+/*
+ * e-mail-parser.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PARSER_H_
+#define E_MAIL_PARSER_H_
+
+#include <em-format/e-mail-part-list.h>
+#include <em-format/e-mail-extension-registry.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_PARSER \
+ (e_mail_parser_get_type ())
+#define E_MAIL_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_PARSER, EMailParser))
+#define E_MAIL_PARSER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_PARSER, EMailParserClass))
+#define E_IS_MAIL_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_PARSER))
+#define E_IS_MAIL_PARSER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_PARSER))
+#define E_MAIL_PARSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_PARSER, EMailParserClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailParser EMailParser;
+typedef struct _EMailParserClass EMailParserClass;
+typedef struct _EMailParserPrivate EMailParserPrivate;
+
+struct _EMailParser {
+ GObject parent;
+ EMailParserPrivate *priv;
+};
+
+struct _EMailParserClass {
+ GObjectClass parent_class;
+
+ EMailParserExtensionRegistry *extension_registry;
+};
+
+GType e_mail_parser_get_type (void);
+
+EMailParser * e_mail_parser_new (CamelSession *session);
+
+EMailPartList * e_mail_parser_parse_sync (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GCancellable *cancellable);
+
+void e_mail_parser_parse (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GAsyncReadyCallback callback,
+ GCancellable *cancellable,
+ gpointer user_data);
+
+EMailPartList * e_mail_parser_parse_finish (EMailParser *parser,
+ GAsyncResult *result,
+ GError **error);
+
+GSList * e_mail_parser_parse_part (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable);
+
+GSList * e_mail_parser_parse_part_as (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ const gchar *mime_type,
+ GCancellable *cancellable);
+
+GSList * e_mail_parser_error (EMailParser *parser,
+ GCancellable *cancellable,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (3, 4);
+
+GSList * e_mail_parser_wrap_as_attachment
+ (EMailParser *parser,
+ CamelMimePart *part,
+ GSList *parts,
+ GString *part_id,
+ GCancellable *cancellable);
+
+CamelSession * e_mail_parser_get_session (EMailParser *parser);
+
+EMailExtensionRegistry *
+ e_mail_parser_get_extension_registry
+ (EMailParser *parser);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PARSER_H_ */
diff --git a/em-format/e-mail-part-attachment-bar.h b/em-format/e-mail-part-attachment-bar.h
new file mode 100644
index 0000000000..e6d65428cb
--- /dev/null
+++ b/em-format/e-mail-part-attachment-bar.h
@@ -0,0 +1,34 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_ATTACHMENT_BAR_H
+#define E_MAIL_PART_ATTACHMENT_BAR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <em-format/e-mail-part.h>
+
+#include <widgets/misc/e-attachment-store.h>
+
+typedef struct _EMailPartAttachmentBar {
+ EMailPart parent;
+
+ EAttachmentStore *store;
+} EMailPartAttachmentBar;
+
+#endif /* E_MAIL_PART_ATTACHMENT_BAR_H */
diff --git a/em-format/e-mail-part-attachment.c b/em-format/e-mail-part-attachment.c
new file mode 100644
index 0000000000..2047f9d6b2
--- /dev/null
+++ b/em-format/e-mail-part-attachment.c
@@ -0,0 +1,30 @@
+/*
+ * e-mail-part-attachment.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-part-attachment.h"
+
+void
+e_mail_part_attachment_free (EMailPartAttachment *empa)
+{
+ g_clear_object (&empa->attachment);
+
+ if (empa->attachment_view_part_id) {
+ g_free (empa->attachment_view_part_id);
+ empa->attachment_view_part_id = NULL;
+ }
+}
diff --git a/em-format/e-mail-part-attachment.h b/em-format/e-mail-part-attachment.h
new file mode 100644
index 0000000000..cd07e3634b
--- /dev/null
+++ b/em-format/e-mail-part-attachment.h
@@ -0,0 +1,45 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_ATTACHMENT_H
+#define E_MAIL_PART_ATTACHMENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <em-format/e-mail-part.h>
+
+#define E_MAIL_PART_ATTACHMENT(p) ((EMailPartAttachment *) p)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailPartAttachment {
+ EMailPart parent;
+
+ EAttachment *attachment;
+ gchar *attachment_view_part_id;
+
+ gboolean shown;
+ const gchar *snoop_mime_type;
+
+} EMailPartAttachment;
+
+void e_mail_part_attachment_free (EMailPartAttachment *empa);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PART_ATTACHMENT_H */
diff --git a/em-format/e-mail-part-list.c b/em-format/e-mail-part-list.c
new file mode 100644
index 0000000000..743834beef
--- /dev/null
+++ b/em-format/e-mail-part-list.c
@@ -0,0 +1,130 @@
+/*
+ * e-mail-part-list.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <camel/camel.h>
+
+#include "e-mail-part-list.h"
+
+G_DEFINE_TYPE (EMailPartList, e_mail_part_list, G_TYPE_OBJECT)
+
+static void
+unref_mail_part (gpointer user_data)
+{
+ if (user_data)
+ e_mail_part_unref (user_data);
+}
+
+static void
+e_mail_part_list_finalize (GObject *object)
+{
+ EMailPartList *part_list = E_MAIL_PART_LIST (object);
+
+ g_clear_object (&part_list->folder);
+ g_clear_object (&part_list->message);
+
+ if (part_list->list) {
+ g_slist_free_full (part_list->list, unref_mail_part);
+ part_list->list = NULL;
+ }
+
+ if (part_list->message_uid) {
+ g_free (part_list->message_uid);
+ part_list->message_uid = NULL;
+ }
+
+ G_OBJECT_CLASS (e_mail_part_list_parent_class)->finalize (object);
+}
+
+static void
+e_mail_part_list_class_init (EMailPartListClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = e_mail_part_list_finalize;
+}
+
+static void
+e_mail_part_list_init (EMailPartList *part_list)
+{
+
+}
+
+EMailPartList *
+e_mail_part_list_new ()
+{
+ return g_object_new (E_TYPE_MAIL_PART_LIST, NULL);
+}
+
+EMailPart *
+e_mail_part_list_find_part (EMailPartList *part_list,
+ const gchar *id)
+{
+ GSList *iter;
+ gboolean by_cid;
+
+ g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
+ g_return_val_if_fail (id && *id, NULL);
+
+ by_cid = (g_str_has_prefix (id, "cid:") || g_str_has_prefix (id, "CID:"));
+
+ for (iter = part_list->list; iter; iter = iter->next) {
+
+ EMailPart *part = iter->data;
+ if (!part)
+ continue;
+
+ if ((by_cid && (g_strcmp0 (part->cid, id) == 0)) ||
+ (!by_cid && (g_strcmp0 (part->id, id) == 0)))
+ return part;
+ }
+
+ return NULL;
+}
+
+/**
+ * e_mail_part_list_get_iter:
+ * @part_list: a #GSList of #EMailPart
+ * @id: id of #EMailPart to lookup
+ *
+ * Returns iter of an #EMailPart within the @part_list.
+ *
+ * Return Value: a #GSList sublist. The list is owned by #EMailPartList and
+ * must not be freed or altered.
+ */
+GSList *
+e_mail_part_list_get_iter (GSList *list,
+ const gchar *id)
+{
+ GSList *iter;
+
+ g_return_val_if_fail (list != NULL, NULL);
+ g_return_val_if_fail (id && *id, NULL);
+
+ for (iter = list; iter; iter = iter->next) {
+
+ EMailPart *part = iter->data;
+ if (!part)
+ continue;
+
+ if (g_strcmp0 (part->id, id) == 0)
+ return iter;
+ }
+
+ return NULL;
+}
diff --git a/em-format/e-mail-part-list.h b/em-format/e-mail-part-list.h
new file mode 100644
index 0000000000..12a24f365f
--- /dev/null
+++ b/em-format/e-mail-part-list.h
@@ -0,0 +1,76 @@
+/*
+ * e-mail-part-list.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_LIST_H_
+#define E_MAIL_PART_LIST_H_
+
+#include <camel/camel.h>
+#include <em-format/e-mail-part.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_PART_LIST \
+ (e_mail_part_list_get_type ())
+#define E_MAIL_PART_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_PART_LIST, EMailPartList))
+#define E_MAIL_PART_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_PART_LIST, EMailPartListClass))
+#define E_IS_MAIL_PART_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_PART_LIST))
+#define E_IS_MAIL_PART_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_PART_LIST))
+#define E_MAIL_PART_LIST_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_PART_LIST, EMailPartListClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailPartList EMailPartList;
+typedef struct _EMailPartListClass EMailPartListClass;
+
+struct _EMailPartList {
+ GObject parent;
+
+ CamelMimeMessage *message;
+ CamelFolder *folder;
+ gchar *message_uid;
+
+ /* GSList of EMailPart's */
+ GSList *list;
+};
+
+struct _EMailPartListClass {
+ GObjectClass parent_class;
+};
+
+EMailPartList * e_mail_part_list_new ();
+
+GType e_mail_part_list_get_type ();
+
+EMailPart * e_mail_part_list_find_part (EMailPartList *part_list,
+ const gchar *id);
+
+GSList * e_mail_part_list_get_iter (GSList *list,
+ const gchar *id);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PART_LIST_H_ */
diff --git a/em-format/e-mail-part-utils.c b/em-format/e-mail-part-utils.c
new file mode 100644
index 0000000000..858209b7df
--- /dev/null
+++ b/em-format/e-mail-part-utils.c
@@ -0,0 +1,546 @@
+/*
+ * e-mail-part-utils.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include "e-mail-part-utils.h"
+#include "e-mail-parser-extension.h"
+
+#include <camel/camel.h>
+#include <e-util/e-util.h>
+#include <gdk/gdk.h>
+
+#include <libsoup/soup.h>
+
+#include <string.h>
+
+#define d(x)
+
+/**
+ * e_mail_parst_is_secured:
+ * @part: a #CamelMimePart
+ *
+ * Whether @part is signed or encrypted or not.
+ *
+ * Return Value: TRUE/FALSE
+ */
+gboolean
+e_mail_part_is_secured (CamelMimePart *part)
+{
+ CamelContentType *ct = camel_mime_part_get_content_type (part);
+
+ return (camel_content_type_is (ct, "multipart", "signed") ||
+ camel_content_type_is (ct, "multipart", "encrypted") ||
+ camel_content_type_is (ct, "application", "x-inlinepgp-signed") ||
+ camel_content_type_is (ct, "application", "x-inlinepgp-encrypted") ||
+ camel_content_type_is (ct, "application", "x-pkcs7-mime") ||
+ camel_content_type_is (ct, "application", "pkcs7-mime"));
+}
+
+/**
+ * e_mail_partr_snoop_type:
+ * @part: a #CamelMimePart
+ *
+ * Tries to snoop the mime type of a part.
+ *
+ * Return value: %NULL if unknown (more likely application/octet-stream).
+ **/
+const gchar *
+e_mail_part_snoop_type (CamelMimePart *part)
+{
+ /* cache is here only to be able still return const gchar * */
+ static GHashTable *types_cache = NULL;
+
+ const gchar *filename;
+ gchar *name_type = NULL, *magic_type = NULL, *res, *tmp;
+ CamelDataWrapper *dw;
+
+ filename = camel_mime_part_get_filename (part);
+ if (filename != NULL)
+ name_type = e_util_guess_mime_type (filename, FALSE);
+
+ dw = camel_medium_get_content ((CamelMedium *) part);
+ if (!camel_data_wrapper_is_offline (dw)) {
+ GByteArray *byte_array;
+ CamelStream *stream;
+
+ byte_array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (byte_array);
+
+ if (camel_data_wrapper_decode_to_stream_sync (dw, stream, NULL, NULL) > 0) {
+ gchar *content_type;
+
+ content_type = g_content_type_guess (
+ filename, byte_array->data,
+ byte_array->len, NULL);
+
+ if (content_type != NULL)
+ magic_type = g_content_type_get_mime_type (content_type);
+
+ g_free (content_type);
+ }
+
+ g_object_unref (stream);
+ }
+
+ /* If gvfs doesn't recognize the data by magic, but it
+ * contains English words, it will call it text/plain. If the
+ * filename-based check came up with something different, use
+ * that instead and if it returns "application/octet-stream"
+ * try to do better with the filename check.
+ */
+
+ if (magic_type) {
+ if (name_type
+ && (!strcmp(magic_type, "text/plain")
+ || !strcmp(magic_type, "application/octet-stream")))
+ res = name_type;
+ else
+ res = magic_type;
+ } else
+ res = name_type;
+
+ if (res != name_type)
+ g_free (name_type);
+
+ if (res != magic_type)
+ g_free (magic_type);
+
+ if (!types_cache)
+ types_cache = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) NULL);
+
+ if (res) {
+ tmp = g_hash_table_lookup (types_cache, res);
+ if (tmp) {
+ g_free (res);
+ res = tmp;
+ } else {
+ g_hash_table_insert (types_cache, res, res);
+ }
+ }
+
+ d(printf("Snooped mime type %s\n", res));
+ return res;
+
+ /* We used to load parts to check their type, we don't anymore,
+ * see bug #211778 for some discussion */
+}
+
+/**
+ * e_mail_part_is_attachment
+ * @part: Part to check.
+ *
+ * Returns true if the part is an attachment.
+ *
+ * A part is not considered an attachment if it is a
+ * multipart, or a text part with no filename. It is used
+ * to determine if an attachment header should be displayed for
+ * the part.
+ *
+ * Content-Disposition is not checked.
+ *
+ * Return value: TRUE/FALSE
+ **/
+gboolean
+e_mail_part_is_attachment (CamelMimePart *part)
+{
+ /*CamelContentType *ct = camel_mime_part_get_content_type(part);*/
+ CamelDataWrapper *dw = camel_medium_get_content ((CamelMedium *) part);
+
+ if (!dw)
+ return 0;
+
+ d(printf("checking is attachment %s/%s\n", dw->mime_type->type, dw->mime_type->subtype));
+ return !(camel_content_type_is (dw->mime_type, "multipart", "*")
+ || camel_content_type_is (
+ dw->mime_type, "application", "x-pkcs7-mime")
+ || camel_content_type_is (
+ dw->mime_type, "application", "pkcs7-mime")
+ || camel_content_type_is (
+ dw->mime_type, "application", "x-inlinepgp-signed")
+ || camel_content_type_is (
+ dw->mime_type, "application", "x-inlinepgp-encrypted")
+ || camel_content_type_is (
+ dw->mime_type, "x-evolution", "evolution-rss-feed")
+ || camel_content_type_is (dw->mime_type, "text", "calendar")
+ || camel_content_type_is (dw->mime_type, "text", "x-calendar")
+ || (camel_content_type_is (dw->mime_type, "text", "*")
+ && camel_mime_part_get_filename (part) == NULL));
+}
+
+/**
+ * e_mail_part_preserve_charset_in_content_type:
+ * @ipart: Source #CamelMimePart
+ * @opart: Target #CamelMimePart
+ *
+ * Copies 'charset' part of content-type header from @ipart to @opart.
+ */
+void
+e_mail_part_preserve_charset_in_content_type (CamelMimePart *ipart,
+ CamelMimePart *opart)
+{
+ CamelDataWrapper *data_wrapper;
+ CamelContentType *content_type;
+ const gchar *charset;
+
+ g_return_if_fail (ipart != NULL);
+ g_return_if_fail (opart != NULL);
+
+ data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (ipart));
+ content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
+
+ if (content_type == NULL)
+ return;
+
+ charset = camel_content_type_param (content_type, "charset");
+
+ if (charset == NULL || *charset == '\0')
+ return;
+
+ data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (opart));
+ content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
+
+ if (content_type)
+ camel_content_type_set_param (content_type, "charset", charset);
+
+ /* update charset also on the part itself */
+ data_wrapper = CAMEL_DATA_WRAPPER (opart);
+ content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
+ if (content_type)
+ camel_content_type_set_param (content_type, "charset", charset);
+}
+
+/**
+ * e_mail_part_get_related_display_part:
+ * @part: a multipart/related or multipart/alternative #CamelMimePart
+ * @out_displayid: (out) returns index of the returned part
+ *
+ * Goes through all subparts of given @part and tries to determine which
+ * part should be displayed and which parts are just attachments to the
+ * part.
+ *
+ * Return Value: A #CamelMimePart that should be displayed
+ */
+CamelMimePart *
+e_mail_part_get_related_display_part (CamelMimePart *part,
+ gint *out_displayid)
+{
+ CamelMultipart *mp;
+ CamelMimePart *body_part, *display_part = NULL;
+ CamelContentType *content_type;
+ const gchar *start;
+ gint i, nparts, displayid = 0;
+
+ mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
+
+ if (!CAMEL_IS_MULTIPART (mp))
+ return NULL;
+
+ nparts = camel_multipart_get_number (mp);
+ content_type = camel_mime_part_get_content_type (part);
+ start = camel_content_type_param (content_type, "start");
+ if (start && strlen (start) > 2) {
+ gint len;
+ const gchar *cid;
+
+ /* strip <>'s from CID */
+ len = strlen (start) - 2;
+ start++;
+
+ for (i = 0; i < nparts; i++) {
+ body_part = camel_multipart_get_part (mp, i);
+ cid = camel_mime_part_get_content_id (body_part);
+
+ if (cid && !strncmp (cid, start, len) && strlen (cid) == len) {
+ display_part = body_part;
+ displayid = i;
+ break;
+ }
+ }
+ } else {
+ display_part = camel_multipart_get_part (mp, 0);
+ }
+
+ if (out_displayid)
+ *out_displayid = displayid;
+
+ return display_part;
+}
+
+void
+e_mail_part_animation_extract_frame (const GByteArray *anim,
+ gchar **frame,
+ gsize *len)
+{
+ GdkPixbufLoader *loader;
+ GdkPixbufAnimation *animation;
+ GdkPixbuf *frame_buf;
+
+ /* GIF89a (GIF image signature) */
+ const gchar GIF_HEADER[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
+ const gint GIF_HEADER_LEN = sizeof (GIF_HEADER);
+
+ /* NETSCAPE2.0 (extension describing animated GIF, starts on 0x310) */
+ const gchar GIF_APPEXT[] = { 0x4E, 0x45, 0x54, 0x53, 0x43, 0x41,
+ 0x50, 0x45, 0x32, 0x2E, 0x30 };
+ const gint GIF_APPEXT_LEN = sizeof (GIF_APPEXT);
+
+ if ((anim == NULL) || (anim->data == NULL)) {
+ *frame = NULL;
+ *len = 0;
+ return;
+ }
+
+ /* Check if the image is an animated GIF. We don't care about any
+ * other animated formats (APNG or MNG) as WebKit does not support them
+ * and displays only the first frame. */
+ if ((anim->len < 0x331)
+ || (memcmp (anim->data, GIF_HEADER, GIF_HEADER_LEN) != 0)
+ || (memcmp (&anim->data[0x310], GIF_APPEXT, GIF_APPEXT_LEN) != 0)) {
+
+ *frame = g_memdup (anim->data, anim->len);
+ *len = anim->len;
+ return;
+ }
+
+ loader = gdk_pixbuf_loader_new ();
+ gdk_pixbuf_loader_write (loader, (guchar *) anim->data, anim->len, NULL);
+ gdk_pixbuf_loader_close (loader, NULL);
+ animation = gdk_pixbuf_loader_get_animation (loader);
+ if (!animation) {
+
+ *frame = g_memdup (anim->data, anim->len);
+ *len = anim->len;
+ g_object_unref (loader);
+ return;
+ }
+
+ /* Extract first frame */
+ frame_buf = gdk_pixbuf_animation_get_static_image (animation);
+ if (!frame_buf) {
+ *frame = g_memdup (anim->data, anim->len);
+ *len = anim->len;
+ g_object_unref (loader);
+ g_object_unref (animation);
+ return;
+ }
+
+ /* Unforunatelly, GdkPixbuf cannot save to GIF, but WebKit does not
+ * have any trouble displaying PNG image despite the part having
+ * image/gif mime-type */
+ gdk_pixbuf_save_to_buffer (frame_buf, frame, len, "png", NULL, NULL);
+
+ g_object_unref (loader);
+}
+
+/**
+ * e_mail_part_build_url:
+ * @folder: (allow-none) a #CamelFolder with the message or %NULL
+ * @message_uid: (allow-none) uid of the message within the @folder or %NULL
+ * @first_param_name: Name of first query parameter followed by GType of it's value and value
+ * terminated by %NULL.
+ *
+ * Construct a URI for message.
+ *
+ * The URI can contain multiple query parameters. The list of parameters must be
+ * NULL-terminated. Each query must contain name, GType of value and value.
+ *
+ * Return Value: a URL of a message or part
+ */
+gchar *
+e_mail_part_build_uri (CamelFolder *folder,
+ const gchar *message_uid,
+ const gchar *first_param_name,
+ ...)
+{
+ CamelStore *store;
+ gchar *uri, *tmp;
+ va_list ap;
+ const gchar *name;
+ const gchar *service_uid, *folder_name;
+ gchar separator;
+
+ g_return_val_if_fail (message_uid && *message_uid, NULL);
+
+ if (!folder) {
+ folder_name = "generic";
+ service_uid = "generic";
+ } else {
+ tmp = (gchar *) camel_folder_get_full_name (folder);
+ folder_name = (const gchar *) soup_uri_encode (tmp, NULL);
+ store = camel_folder_get_parent_store (folder);
+ if (store)
+ service_uid = camel_service_get_uid (CAMEL_SERVICE (store));
+ else
+ service_uid = "generic";
+ }
+
+ tmp = g_strdup_printf ("mail://%s/%s/%s",
+ service_uid,
+ folder_name,
+ message_uid);
+
+ if (folder) {
+ g_free ((gchar *) folder_name);
+ }
+
+ va_start (ap, first_param_name);
+ name = first_param_name;
+ separator = '?';
+ while (name) {
+ gchar *tmp2;
+ gint type = va_arg (ap, gint);
+ switch (type) {
+ case G_TYPE_INT:
+ case G_TYPE_BOOLEAN: {
+ gint val = va_arg (ap, gint);
+ tmp2 = g_strdup_printf ("%s%c%s=%d", tmp,
+ separator, name, val);
+ break;
+ }
+ case G_TYPE_FLOAT:
+ case G_TYPE_DOUBLE: {
+ gdouble val = va_arg (ap, double);
+ tmp2 = g_strdup_printf ("%s%c%s=%f", tmp,
+ separator, name, val);
+ break;
+ }
+ case G_TYPE_STRING: {
+ gchar *val = va_arg (ap, gchar *);
+ gchar *escaped = soup_uri_encode (val, NULL);
+ tmp2 = g_strdup_printf ("%s%c%s=%s", tmp,
+ separator, name, escaped);
+ g_free (escaped);
+ break;
+ }
+ default:
+ g_warning ("Invalid param type %s", g_type_name (type));
+ return NULL;
+ }
+
+ g_free (tmp);
+ tmp = tmp2;
+
+ if (separator == '?')
+ separator = '&';
+
+ name = va_arg (ap, gchar *);
+ }
+ va_end (ap);
+
+ uri = tmp;
+ if (uri == NULL)
+ return NULL;
+
+ /* For some reason, webkit won't accept URL with username, but
+ * without password (mail://store@host/folder/mail), so we
+ * will replace the '@' symbol by '/' to get URL like
+ * mail://store/host/folder/mail which is OK
+ */
+ while ((tmp = strchr (uri, '@')) != NULL) {
+ tmp[0] = '/';
+ }
+
+ return uri;
+}
+
+/**
+ * e_mail_part_describe:
+ * @part: a #CamelMimePart
+ * @mimetype: mimetype of the content
+ *
+ * Generate a simple textual description of a part, @mime_type represents
+ * the content.
+ *
+ * Return value:
+ **/
+gchar *
+e_mail_part_describe (CamelMimePart *part,
+ const gchar *mime_type)
+{
+ GString *stext;
+ const gchar *filename, *description;
+ gchar *content_type, *desc;
+
+ stext = g_string_new("");
+ content_type = g_content_type_from_mime_type (mime_type);
+ desc = g_content_type_get_description (
+ content_type != NULL ? content_type : mime_type);
+ g_free (content_type);
+ g_string_append_printf (
+ stext, _("%s attachment"), desc ? desc : mime_type);
+ g_free (desc);
+
+ filename = camel_mime_part_get_filename (part);
+ description = camel_mime_part_get_description (part);
+
+ if (!filename || !*filename) {
+ CamelDataWrapper *content;
+
+ content = camel_medium_get_content (CAMEL_MEDIUM (part));
+
+ if (CAMEL_IS_MIME_MESSAGE (content))
+ filename = camel_mime_message_get_subject (
+ CAMEL_MIME_MESSAGE (content));
+ }
+
+ if (filename != NULL && *filename != '\0') {
+ gchar *basename = g_path_get_basename (filename);
+ g_string_append_printf (stext, " (%s)", basename);
+ g_free (basename);
+ }
+
+ if (description != NULL && *description != '\0' &&
+ g_strcmp0 (filename, description) != 0)
+ g_string_append_printf (stext, ", \"%s\"", description);
+
+ return g_string_free (stext, FALSE);
+}
+
+gboolean
+e_mail_part_is_inline (CamelMimePart *mime_part,
+ GQueue *extensions)
+{
+ const gchar *disposition;
+ EMailParserExtension *extension;
+
+ if ((extensions == NULL) || g_queue_is_empty (extensions))
+ return FALSE;
+
+ extension = g_queue_peek_head (extensions);
+ /* Some types need to override the disposition.
+ * e.g. application/x-pkcs7-mime */
+ if (e_mail_parser_extension_get_flags (extension) &
+ E_MAIL_PARSER_EXTENSION_INLINE_DISPOSITION)
+ return TRUE;
+
+ disposition = camel_mime_part_get_disposition (mime_part);
+ if (disposition != NULL)
+ return g_ascii_strcasecmp (disposition, "inline") == 0;
+
+ /* Otherwise, use the default for this handler type. */
+ return (e_mail_parser_extension_get_flags (extension) &
+ E_MAIL_PARSER_EXTENSION_INLINE) != 0;
+}
diff --git a/em-format/e-mail-part-utils.h b/em-format/e-mail-part-utils.h
new file mode 100644
index 0000000000..97c483db94
--- /dev/null
+++ b/em-format/e-mail-part-utils.h
@@ -0,0 +1,58 @@
+/*
+ * e-mail-part-utils.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_UTILS_H_
+#define E_MAIL_PART_UTILS_H_
+
+#include <camel/camel.h>
+
+G_BEGIN_DECLS
+
+gboolean e_mail_part_is_secured (CamelMimePart *part);
+
+const gchar * e_mail_part_snoop_type (CamelMimePart *part);
+
+gboolean e_mail_part_is_attachment (CamelMimePart *part);
+
+void e_mail_part_preserve_charset_in_content_type
+ (CamelMimePart *ipart,
+ CamelMimePart *opart);
+
+CamelMimePart * e_mail_part_get_related_display_part
+ (CamelMimePart *part,
+ gint *out_displayid);
+
+void e_mail_part_animation_extract_frame (
+ const GByteArray *anim,
+ gchar **frame,
+ gsize *len);
+
+gchar * e_mail_part_build_uri (CamelFolder *folder,
+ const gchar *message_uid,
+ const gchar *first_param_name,
+ ...);
+
+gchar * e_mail_part_describe (CamelMimePart *part,
+ const gchar *mime_type);
+
+gboolean e_mail_part_is_inline (CamelMimePart *part,
+ GQueue *extensions);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PART_UTILS_H_ */
diff --git a/em-format/e-mail-part.c b/em-format/e-mail-part.c
new file mode 100644
index 0000000000..a0d493afe4
--- /dev/null
+++ b/em-format/e-mail-part.c
@@ -0,0 +1,196 @@
+/*
+ * e-mail-part.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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <camel/camel.h>
+
+#include "e-mail-part.h"
+
+/**
+ * EMailPart:
+ *
+ * The #EMailPart is a wrapper around #CamelMimePart which holds additional
+ * information about the mime part, like it's ID, encryption type etc.
+ *
+ * #EMailPart is not GObject-based, but has a simple reference counting.
+ *
+ * Each #EMailPart must have a unique ID. The ID is a dot-separated hierarchical
+ * description of the location of the part within the email message.
+ */
+
+struct _EMailPartPrivate {
+ guint ref_cnt;
+ gsize instance_size;
+ GFreeFunc free_func;
+};
+
+static void
+mail_part_free (EMailPart *part)
+{
+ if (!part)
+ return;
+
+ if (part->part) {
+ g_object_unref (part->part);
+ part->part = NULL;
+ }
+
+ if (part->cid) {
+ g_free (part->cid);
+ part->cid = NULL;
+ }
+
+ if (part->mime_type) {
+ g_free (part->mime_type);
+ part->mime_type = NULL;
+ }
+
+ if (part->validity) {
+ camel_cipher_validity_free (part->validity);
+ part->validity = NULL;
+ }
+
+ if (part->validity_parent) {
+ camel_cipher_validity_free (part->validity_parent);
+ part->validity_parent = NULL;
+ }
+
+ if (part->priv->free_func) {
+ part->priv->free_func (part);
+ part->priv->free_func = NULL;
+ }
+
+ if (part->id) {
+ g_free (part->id);
+ part->id = NULL;
+ }
+
+ g_free (part->priv);
+ part->priv = NULL;
+
+ g_free (part);
+}
+
+/**
+ * e_mail_part_new:
+ * @part: (allow-none) a #CamelMimePart or %NULL
+ * @id: part ID
+ *
+ * Creates a new #EMailPart for given mime part.
+ *
+ * Return value: a new #EMailPart
+ */
+EMailPart *
+e_mail_part_new (CamelMimePart *part,
+ const gchar *id)
+{
+ return e_mail_part_subclass_new (part, id, sizeof (EMailPart), NULL);
+}
+
+/**
+ * e_mail_part_new:
+ * @part: (allow-none) a #CamelMimePart or %NULL
+ * @id: part ID
+ * @size: Size of the EMailPart subclass
+ *
+ * Allocates a @size bytes representing an #EMailPart subclass.
+ *
+ * Return value: a new #EMailPart-based object
+ */
+EMailPart *
+e_mail_part_subclass_new (CamelMimePart *part,
+ const gchar *id,
+ gsize size,
+ GFreeFunc free_func)
+{
+ EMailPart *mail_part;
+
+ g_return_val_if_fail (size >= sizeof (EMailPart), NULL);
+
+ mail_part = g_malloc0 (size);
+ mail_part->priv = g_new0 (EMailPartPrivate, 1);
+
+ mail_part->priv->ref_cnt = 1;
+ mail_part->priv->free_func = free_func;
+ mail_part->priv->instance_size = size;
+
+ if (part) {
+ mail_part->part = g_object_ref (part);
+ }
+
+ if (id) {
+ mail_part->id = g_strdup (id);
+ }
+
+ return mail_part;
+}
+
+EMailPart *
+e_mail_part_ref (EMailPart *part)
+{
+ g_return_val_if_fail (part != NULL, NULL);
+ g_return_val_if_fail (part->priv != NULL, NULL);
+
+ g_atomic_int_inc (&part->priv->ref_cnt);
+
+ return part;
+}
+
+void
+e_mail_part_unref (EMailPart *part)
+{
+ g_return_if_fail (part != NULL);
+ g_return_if_fail (part->priv != NULL);
+
+ if (g_atomic_int_dec_and_test (&part->priv->ref_cnt)) {
+ mail_part_free (part);
+ }
+}
+
+gsize
+e_mail_part_get_instance_size (EMailPart *part)
+{
+ g_return_val_if_fail (part != NULL, 0);
+
+ return part->priv->instance_size;
+}
+
+/**
+ * e_mail_part_update_validity:
+ * @part: An #EMailPart
+ * @validity_type: E_MAIL_PART_VALIDITY_* flags
+ * @validity: a #CamelCipherValidity
+ *
+ * Updates validity of the @part. When the part already has some validity
+ * set, the new @validity and @validity_type are just appended, preserving
+ * the original validity.
+ */
+void
+e_mail_part_update_validity (EMailPart *part,
+ CamelCipherValidity *validity,
+ guint32 validity_type)
+{
+ g_return_if_fail (part != NULL);
+
+ part->validity_type &= validity_type;
+
+ if (part->validity) {
+ camel_cipher_validity_envelope (part->validity, validity);
+ } else {
+ part->validity = camel_cipher_validity_clone (validity);
+ }
+}
diff --git a/em-format/e-mail-part.h b/em-format/e-mail-part.h
new file mode 100644
index 0000000000..3d2e9628eb
--- /dev/null
+++ b/em-format/e-mail-part.h
@@ -0,0 +1,98 @@
+/*
+ * e-mail-part.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PART_H_
+#define E_MAIL_PART_H_
+
+#include <camel/camel.h>
+#include <misc/e-attachment.h>
+#include <webkit/webkitdom.h>
+
+#define E_MAIL_PART_IS(p,s_t) \
+ ((p != NULL) && (e_mail_part_get_instance_size (p) == sizeof (s_t)))
+#define E_MAIL_PART(o) ((EMailPart *) o)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailPart EMailPart;
+typedef struct _EMailPartPrivate EMailPartPrivate;
+
+typedef void (*EMailPartDOMBindFunc) (EMailPart *part,
+ WebKitDOMElement *element);
+
+enum {
+ E_MAIL_PART_VALIDITY_NONE = 0,
+ E_MAIL_PART_VALIDITY_PGP = 1 << 0,
+ E_MAIL_PART_VALIDITY_SMIME = 1 << 1,
+ E_MAIL_PART_VALIDITY_SIGNED = 1 << 2,
+ E_MAIL_PART_VALIDITY_ENCRYPTED = 1 << 3
+} EMailPartValidityFlags;
+
+struct _EMailPart {
+ EMailPartPrivate *priv;
+
+ EMailPartDOMBindFunc bind_func;
+
+ CamelMimePart *part;
+ gchar *id;
+ gchar *cid;
+ gchar *mime_type;
+
+ guint32 validity_type; /* E_MAIL_PART_VALIDITY_ * flags */
+ CamelCipherValidity *validity;
+ CamelCipherValidity *validity_parent;
+
+ gint is_attachment: 1;
+
+ /* Whether the part should be rendered or not.
+ * This is used for example to prevent images
+ * related to text/html parts from being
+ * rendered as attachments. */
+ gint is_hidden: 1;
+
+ /* Force attachment to be expanded, even without
+ * content-disposition: inline */
+ gint force_inline: 1;
+
+ /* Force attachment to be collapsed, even with
+ * content-disposition: inline */
+ gint force_collapse: 1;
+
+ /* Does part contain an error message? */
+ gint is_error: 1;
+};
+
+EMailPart * e_mail_part_new (CamelMimePart *part,
+ const gchar *id);
+EMailPart * e_mail_part_subclass_new (CamelMimePart *part,
+ const gchar *id,
+ gsize size,
+ GFreeFunc free_func);
+
+EMailPart * e_mail_part_ref (EMailPart *part);
+void e_mail_part_unref (EMailPart *part);
+
+gsize e_mail_part_get_instance_size (EMailPart *part);
+
+void e_mail_part_update_validity (EMailPart *part,
+ CamelCipherValidity *validity,
+ guint32 validity_type);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PART_H_ */
diff --git a/em-format/em-stripsig-filter.c b/em-format/e-mail-stripsig-filter.c
index fe08383d5c..e861a13a53 100644
--- a/em-format/em-stripsig-filter.c
+++ b/em-format/e-mail-stripsig-filter.c
@@ -28,9 +28,9 @@
#include <stdio.h>
#include <string.h>
-#include "em-stripsig-filter.h"
+#include "e-mail-stripsig-filter.h"
-G_DEFINE_TYPE (EMStripSigFilter, em_stripsig_filter, CAMEL_TYPE_MIME_FILTER)
+G_DEFINE_TYPE (EMailStripSigFilter, e_mail_stripsig_filter, CAMEL_TYPE_MIME_FILTER)
static void
strip_signature (CamelMimeFilter *filter,
@@ -42,7 +42,7 @@ strip_signature (CamelMimeFilter *filter,
gsize *outprespace,
gint flush)
{
- EMStripSigFilter *stripsig = (EMStripSigFilter *) filter;
+ EMailStripSigFilter *stripsig = (EMailStripSigFilter *) filter;
register const gchar *inptr = in;
const gchar *inend = in + len;
const gchar *start = NULL;
@@ -124,13 +124,13 @@ filter_complete (CamelMimeFilter *filter,
static void
filter_reset (CamelMimeFilter *filter)
{
- EMStripSigFilter *stripsig = (EMStripSigFilter *) filter;
+ EMailStripSigFilter *stripsig = (EMailStripSigFilter *) filter;
stripsig->midline = FALSE;
}
static void
-em_stripsig_filter_class_init (EMStripSigFilterClass *class)
+e_mail_stripsig_filter_class_init (EMailStripSigFilterClass *class)
{
CamelMimeFilterClass *mime_filter_class;
@@ -141,12 +141,12 @@ em_stripsig_filter_class_init (EMStripSigFilterClass *class)
}
static void
-em_stripsig_filter_init (EMStripSigFilter *filter)
+e_mail_stripsig_filter_init (EMailStripSigFilter *filter)
{
}
/**
- * em_stripsig_filter_new:
+ * e_mail_stripsig_filter_new:
* @text_plain_only: Whether should look for a text/plain signature
* delimiter "-- \n" only or also an HTML signature delimiter "-- <BR>".
*
@@ -155,9 +155,9 @@ em_stripsig_filter_init (EMStripSigFilter *filter)
* Returns a new stripsig filter.
**/
CamelMimeFilter *
-em_stripsig_filter_new (gboolean text_plain_only)
+e_mail_stripsig_filter_new (gboolean text_plain_only)
{
- EMStripSigFilter *filter = g_object_new (EM_TYPE_STRIPSIG_FILTER, NULL);
+ EMailStripSigFilter *filter = g_object_new (E_TYPE_MAIL_STRIPSIG_FILTER, NULL);
filter->text_plain_only = text_plain_only;
diff --git a/em-format/em-stripsig-filter.h b/em-format/e-mail-stripsig-filter.h
index 47017f79fe..730d55eaaf 100644
--- a/em-format/em-stripsig-filter.h
+++ b/em-format/e-mail-stripsig-filter.h
@@ -20,50 +20,50 @@
*
*/
-#ifndef EM_STRIPSIG_FILTER_H
-#define EM_STRIPSIG_FILTER_H
+#ifndef E_MAIL_STRIPSIG_FILTER_H
+#define E_MAIL_STRIPSIG_FILTER_H
#include <camel/camel.h>
/* Standard GObject macros */
-#define EM_TYPE_STRIPSIG_FILTER \
- (em_stripsig_filter_get_type ())
-#define EM_STRIPSIG_FILTER(obj) \
+#define E_TYPE_MAIL_STRIPSIG_FILTER \
+ (e_mail_stripsig_filter_get_type ())
+#define E_MAIL_STRIPSIG_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_STRIPSIG_FILTER, EMStripSigFilter))
-#define EM_STRIPSIG_FILTER_CLASS(cls) \
+ ((obj), E_TYPE_MAIL_STRIPSIG_FILTER, EMailStripSigFilter))
+#define E_MAIL_STRIPSIG_FILTER_CLASS(cls) \
(G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_STRIPSIG_FILTER, EMStripSigFilterClass))
-#define EM_IS_STRIPSIG_FILTER(obj) \
+ ((cls), E_TYPE_MAIL_STRIPSIG_FILTER, EMailStripSigFilterClass))
+#define E_MAIL_IS_STRIPSIG_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_STRIPSIG_FILTER))
-#define EM_IS_STRIPSIG_FILTER_CLASS(cls) \
+ ((obj), E_TYPE_MAIL_STRIPSIG_FILTER))
+#define E_MAIL_IS_STRIPSIG_FILTER_CLASS(cls) \
(G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_STRIPSIG_FILTER))
-#define EM_STRIPSIG_FILTER_GET_CLASS(obj) \
+ ((cls), E_TYPE_MAIL_STRIPSIG_FILTER))
+#define E_MAIL_STRIPSIG_FILTER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_STRIPSIG_FILTER, EMStripSigFilterClass))
+ ((obj), E_TYPE_MAIL_STRIPSIG_FILTER, EMailStripSigFilterClass))
G_BEGIN_DECLS
-typedef struct _EMStripSigFilter EMStripSigFilter;
-typedef struct _EMStripSigFilterClass EMStripSigFilterClass;
+typedef struct _EMailStripSigFilter EMailStripSigFilter;
+typedef struct _EMailStripSigFilterClass EMailStripSigFilterClass;
-struct _EMStripSigFilter {
+struct _EMailStripSigFilter {
CamelMimeFilter parent;
guint32 midline : 1;
guint32 text_plain_only : 1;
};
-struct _EMStripSigFilterClass {
+struct _EMailStripSigFilterClass {
CamelMimeFilterClass parent_class;
};
-GType em_stripsig_filter_get_type (void);
+GType e_mail_stripsig_filter_get_type (void);
CamelMimeFilter *
- em_stripsig_filter_new (gboolean text_plain_only);
+ e_mail_stripsig_filter_new (gboolean text_plain_only);
G_END_DECLS
-#endif /* EM_STRIPSIG_FILTER_H */
+#endif /* E_MAIL_STRIPSIG_FILTER_H */
diff --git a/em-format/em-format-quote.c b/em-format/em-format-quote.c
deleted file mode 100644
index b74da215f4..0000000000
--- a/em-format/em-format-quote.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <glib/gi18n.h>
-
-#include "em-inline-filter.h"
-#include "em-stripsig-filter.h"
-#include "em-format-quote.h"
-
-#define EM_FORMAT_QUOTE_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), EM_TYPE_FORMAT_QUOTE, EMFormatQuotePrivate))
-
-struct _EMFormatQuotePrivate {
- gchar *credits;
- EMFormatQuoteFlags flags;
- guint32 text_html_flags;
-};
-
-static void emfq_builtin_init (EMFormatQuoteClass *efhc);
-
-static CamelMimePart * decode_inline_parts (CamelMimePart *part, GCancellable *cancellable);
-
-static void emfq_parse_text_plain (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emfq_parse_text_enriched (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emfq_parse_text_html (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emfq_parse_attachment (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-
-static void emfq_write_text_plain (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emfq_write_text_enriched (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emfq_write_text_html (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-static gpointer parent_class;
-
-/* Decodes inline encoded parts of 'part'. The returned pointer,
- * if not NULL, should be unreffed with g_object_unref(). */
-static CamelMimePart *
-decode_inline_parts (CamelMimePart *part,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- CamelStream *null;
- CamelStream *filtered_stream;
- EMInlineFilter *inline_filter;
-
- g_return_val_if_fail (part != NULL, NULL);
-
- null = camel_stream_null_new ();
- filtered_stream = camel_stream_filter_new (null);
- g_object_unref (null);
-
- inline_filter = em_inline_filter_new (
- camel_mime_part_get_encoding (part),
- camel_mime_part_get_content_type (part));
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream),
- CAMEL_MIME_FILTER (inline_filter));
- camel_data_wrapper_decode_to_stream_sync (
- camel_medium_get_content (CAMEL_MEDIUM (part)),
- filtered_stream, cancellable, NULL);
- camel_stream_close (filtered_stream, cancellable, NULL);
- g_object_unref (filtered_stream);
-
- if (!em_inline_filter_found_any (inline_filter)) {
- g_object_unref (inline_filter);
- return NULL;
- }
-
- mp = em_inline_filter_get_multipart (inline_filter);
-
- g_object_unref (inline_filter);
-
- if (mp) {
- part = camel_mime_part_new ();
- camel_medium_set_content (
- CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp));
- g_object_unref (mp);
- } else {
- g_object_ref (part);
- }
-
- return part;
-}
-
-static void
-emfq_format_text_header (EMFormatQuote *emfq,
- GString *buffer,
- const gchar *label,
- const gchar *value,
- guint32 flags,
- gint is_html)
-{
- const gchar *html;
- gchar *mhtml = NULL;
-
- if (value == NULL)
- return;
-
- while (*value == ' ')
- value++;
-
- if (!is_html)
- html = mhtml = camel_text_to_html (value, 0, 0);
- else
- html = value;
-
- if (flags & EM_FORMAT_HEADER_BOLD)
- g_string_append_printf (
- buffer, "<b>%s</b>: %s<br>", label, html);
- else
- g_string_append_printf (
- buffer, "%s: %s<br>", label, html);
-
- g_free (mhtml);
-}
-
-static const gchar *addrspec_hdrs[] = {
- "Sender", "From", "Reply-To", "To", "Cc", "Bcc",
- "Resent-Sender", "Resent-from", "Resent-Reply-To",
- "Resent-To", "Resent-cc", "Resent-Bcc", NULL
-};
-
-#if 0
-/* FIXME: include Sender and Resent-* headers too? */
-/* For Translators only: The following strings are
- * used in the header table in the preview pane. */
-static gchar *i18n_hdrs[] = {
- N_("From"), N_("Reply-To"), N_("To"), N_("Cc"), N_("Bcc")
-};
-#endif
-
-static void
-emfq_format_address (GString *out,
- struct _camel_header_address *a)
-{
- guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
- gchar *name, *mailto, *addr;
-
- while (a) {
- if (a->name)
- name = camel_text_to_html (a->name, flags, 0);
- else
- name = NULL;
-
- switch (a->type) {
- case CAMEL_HEADER_ADDRESS_NAME:
- if (name && *name) {
- gchar *real, *mailaddr;
-
- g_string_append_printf (out, "%s &lt;", name);
- /* rfc2368 for mailto syntax and url encoding extras */
- if ((real = camel_header_encode_phrase ((guchar *) a->name))) {
- mailaddr = g_strdup_printf ("%s <%s>", real, a->v.addr);
- g_free (real);
- mailto = camel_url_encode (mailaddr, "?=&()");
- g_free (mailaddr);
- } else {
- mailto = camel_url_encode (a->v.addr, "?=&()");
- }
- } else {
- mailto = camel_url_encode (a->v.addr, "?=&()");
- }
- addr = camel_text_to_html (a->v.addr, flags, 0);
- g_string_append_printf (
- out, "<a href=\"mailto:%s\">%s</a>",
- mailto, addr);
- g_free (mailto);
- g_free (addr);
-
- if (name && *name)
- g_string_append (out, "&gt;");
- break;
- case CAMEL_HEADER_ADDRESS_GROUP:
- g_string_append_printf (out, "%s: ", name);
- emfq_format_address (out, a->v.members);
- g_string_append_printf (out, ";");
- break;
- default:
- g_warning ("Invalid address type");
- break;
- }
-
- g_free (name);
-
- a = a->next;
- if (a)
- g_string_append (out, ", ");
- }
-}
-
-static void
-canon_header_name (gchar *name)
-{
- gchar *inptr = name;
-
- /* canonicalise the header name... first letter is
- * capitalised and any letter following a '-' also gets
- * capitalised */
-
- if (g_ascii_islower (*inptr))
- *inptr = g_ascii_toupper (*inptr);
-
- inptr++;
-
- while (*inptr) {
- if (inptr[-1] == '-' && g_ascii_islower (*inptr))
- *inptr = g_ascii_toupper (*inptr);
- else if (g_ascii_isupper (*inptr))
- *inptr = g_ascii_tolower (*inptr);
-
- inptr++;
- }
-}
-
-static void
-emfq_format_header (EMFormat *emf,
- GString *buffer,
- CamelMedium *part,
- const gchar *namein,
- guint32 flags,
- const gchar *charset)
-{
- CamelMimeMessage *msg = (CamelMimeMessage *) part;
- EMFormatQuote *emfq = (EMFormatQuote *) emf;
- gchar *name, *buf, *value = NULL;
- const gchar *txt, *label;
- gboolean addrspec = FALSE;
- gint is_html = FALSE;
- gint i;
-
- name = g_alloca (strlen (namein) + 1);
- strcpy (name, namein);
- canon_header_name (name);
-
- /* Never quote Bcc headers */
- if (g_str_equal (name, "Bcc") || g_str_equal (name, "Resent-Bcc"))
- return;
-
- for (i = 0; addrspec_hdrs[i]; i++) {
- if (!strcmp (name, addrspec_hdrs[i])) {
- addrspec = TRUE;
- break;
- }
- }
-
- label = _(name);
-
- if (addrspec) {
- struct _camel_header_address *addrs;
- GString *html;
-
- if (!(txt = camel_medium_get_header (part, name)))
- return;
-
- buf = camel_header_unfold (txt);
- addrs = camel_header_address_decode (
- txt, em_format_get_charset (emf) ?
- em_format_get_charset (emf) : em_format_get_default_charset (emf));
- if (addrs == NULL) {
- g_free (buf);
- return;
- }
-
- g_free (buf);
-
- html = g_string_new ("");
- emfq_format_address (html, addrs);
- camel_header_address_unref (addrs);
- txt = value = html->str;
- g_string_free (html, FALSE);
- flags |= EM_FORMAT_HEADER_BOLD;
- is_html = TRUE;
- } else if (!strcmp (name, "Subject")) {
- txt = camel_mime_message_get_subject (msg);
- label = _("Subject");
- flags |= EM_FORMAT_HEADER_BOLD;
- } else if (!strcmp (name, "X-Evolution-Mailer")) { /* pseudo-header */
- if (!(txt = camel_medium_get_header (part, "x-mailer")))
- if (!(txt = camel_medium_get_header (part, "user-agent")))
- if (!(txt = camel_medium_get_header (part, "x-newsreader")))
- if (!(txt = camel_medium_get_header (part, "x-mimeole")))
- return;
-
- txt = value = camel_header_format_ctext (txt, charset);
-
- label = _("Mailer");
- flags |= EM_FORMAT_HEADER_BOLD;
- } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) {
- if (!(txt = camel_medium_get_header (part, name)))
- return;
-
- flags |= EM_FORMAT_HEADER_BOLD;
- } else {
- txt = camel_medium_get_header (part, name);
- buf = camel_header_unfold (txt);
- txt = value = camel_header_decode_string (txt, charset);
- g_free (buf);
- }
-
- emfq_format_text_header (emfq, buffer, label, txt, flags, is_html);
-
- g_free (value);
-}
-
-static void
-emfq_format_headers (EMFormatQuote *emfq,
- GString *buffer,
- CamelMedium *part)
-{
- EMFormat *emf = (EMFormat *) emfq;
- CamelContentType *ct;
- const gchar *charset;
- GList *link;
-
- if (!part)
- return;
-
- ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
- charset = camel_content_type_param (ct, "charset");
- charset = camel_iconv_charset_name (charset);
-
- /* dump selected headers */
- link = g_queue_peek_head_link (&emf->header_list);
- while (link != NULL) {
- EMFormatHeader *h = link->data;
- emfq_format_header (
- emf, buffer, part, h->name, h->flags, charset);
- link = g_list_next (link);
- }
-
- g_string_append (buffer, "<br>\n");
-}
-
-static void
-emfq_dispose (GObject *object)
-{
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-emfq_finalize (GObject *object)
-{
- EMFormatQuotePrivate *priv;
-
- priv = EM_FORMAT_QUOTE_GET_PRIVATE (object);
-
- g_free (priv->credits);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/******************************************************************************/
-static void
-emfq_parse_text_plain (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- CamelMimePart *mp;
- gint len;
-
- len = part_id->len;
- g_string_append (part_id, ".text_plain");
-
- mp = decode_inline_parts (part, cancellable);
- if (mp) {
-
- if (CAMEL_IS_MULTIPART (camel_medium_get_content (CAMEL_MEDIUM (mp)))) {
- em_format_parse_part (emf, mp, part_id, info, cancellable);
- }
-
- g_object_unref (mp);
- }
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = emfq_write_text_plain;
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-}
-
-static void
-emfq_parse_text_html (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- len = part_id->len;
- g_string_append (part_id, ".text_html");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = emfq_write_text_html;
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-}
-
-static void
-emfq_parse_text_enriched (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- len = part_id->len;
- g_string_append (part_id, ".text_enriched");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = emfq_write_text_enriched;
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-}
-
-static void
-emfq_parse_attachment (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- len = part_id->len;
- g_string_append (part_id, ".attachment");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = emfq_write_text_html;
- puri->mime_type = g_strdup ("text/html");
- puri->is_attachment = TRUE;
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-}
-
-/******************************************************************************/
-
-static void
-emfq_write_attachment (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf);
- const EMFormatHandler *handler;
- gchar *text, *html;
- CamelContentType *ct;
- const gchar *mime_type;
-
- ct = camel_mime_part_get_content_type (puri->part);
- if (ct) {
- mime_type = camel_content_type_simple (ct);
- camel_content_type_unref (ct);
- } else {
- mime_type = "application/octet-stream";
- }
-
- handler = em_format_find_handler (emf, mime_type);
-
- if (!em_format_is_inline (emf, puri->uri, puri->part, handler))
- return;
-
- camel_stream_write_string (
- stream, "<table border=1 cellspacing=0 cellpadding=0>"
- "<tr><td><font size=-1>\n", cancellable, NULL);
-
- /* output some info about it */
- text = em_format_describe_part (puri->part, mime_type);
- html = camel_text_to_html (
- text, emfq->priv->text_html_flags &
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- camel_stream_write_string (stream, html, cancellable, NULL);
- g_free (html);
- g_free (text);
-
- camel_stream_write_string (
- stream, "</font></td></tr></table>", cancellable, NULL);
-
- if (handler && handler->write_func)
- handler->write_func (emf, puri, stream, info, cancellable);
-}
-
-static void
-emfq_write (EMFormat *emf,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GList *iter;
-
- for (iter = emf->mail_part_list; iter; iter = iter->next) {
-
- EMFormatPURI *puri = iter->data;
- if (!puri || !puri->write_func)
- continue;
-
- puri->write_func (emf, puri, stream, info, cancellable);
- }
-}
-
-static void
-emfq_base_init (EMFormatQuoteClass *klass)
-{
- emfq_builtin_init (klass);
-}
-
-static void
-emfq_class_init (EMFormatQuoteClass *klass)
-{
- GObjectClass *object_class;
- EMFormatClass *format_class;
-
- parent_class = g_type_class_peek_parent (klass);
- g_type_class_add_private (klass, sizeof (EMFormatQuotePrivate));
-
- format_class = EM_FORMAT_CLASS (klass);
- format_class->write = emfq_write;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->dispose = emfq_dispose;
- object_class->finalize = emfq_finalize;
-}
-
-static void
-emfq_init (EMFormatQuote *emfq)
-{
- emfq->priv = EM_FORMAT_QUOTE_GET_PRIVATE (emfq);
-
- /* we want to convert url's etc */
- emfq->priv->text_html_flags =
- CAMEL_MIME_FILTER_TOHTML_PRE |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
-}
-
-GType
-em_format_quote_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EMFormatQuoteClass),
- (GBaseInitFunc) emfq_base_init,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) emfq_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EMFormatQuote),
- 0, /* n_preallocs */
- (GInstanceInitFunc) emfq_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- EM_TYPE_FORMAT, "EMFormatQuote", &type_info, 0);
- }
-
- return type;
-}
-
-EMFormatQuote *
-em_format_quote_new (CamelSession *session,
- const gchar *credits,
- CamelStream *stream,
- EMFormatQuoteFlags flags)
-{
- EMFormatQuote *emfq;
-
- g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
- g_return_val_if_fail (CAMEL_IS_STREAM (stream), NULL);
-
- /* Steam must also be seekable so we can reset its position. */
- g_return_val_if_fail (G_IS_SEEKABLE (stream), NULL);
-
- emfq = g_object_new (
- EM_TYPE_FORMAT_QUOTE,
- "session", session, NULL);
-
- emfq->priv->credits = g_strdup (credits);
- emfq->priv->flags = flags;
-
- return emfq;
-}
-
-void
-em_format_quote_write (EMFormatQuote *emfq,
- CamelStream *stream,
- GCancellable *cancellable)
-{
- EMFormat *emf;
- GSettings *settings;
- GList *iter;
- EMFormatWriterInfo info = { 0 };
-
- emf = (EMFormat *) emfq;
-
- g_seekable_seek (
- G_SEEKABLE (stream),
- 0, G_SEEK_SET, NULL, NULL);
-
- settings = g_settings_new ("org.gnome.evolution.mail");
- if (g_settings_get_boolean (
- settings, "composer-top-signature"))
- camel_stream_write_string (
- stream, "<br>\n", cancellable, NULL);
- g_object_unref (settings);
-
- if (emfq->priv->credits && *emfq->priv->credits) {
- gchar *credits = g_strdup_printf ("%s<br/>", emfq->priv->credits);
- camel_stream_write_string (stream, credits, cancellable, NULL);
- g_free (credits);
- } else {
- camel_stream_write_string (stream, "<br/>", cancellable, NULL);
- }
-
- if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE)
- camel_stream_write_string (stream,
- "<!--+GtkHTML:<DATA class=\"ClueFlow\" "
- "key=\"orig\" value=\"1\">-->\n"
- "<blockquote type=cite>\n", cancellable, NULL);
-
- for (iter = emf->mail_part_list; iter; iter = iter->next) {
- EMFormatPURI *puri = iter->data;
-
- if (puri->is_attachment || !puri->write_func)
- continue;
-
- puri = iter->data;
-
- if (emfq->priv->flags & EM_FORMAT_QUOTE_HEADERS) {
- GString *buffer = g_string_new ("");
- emfq_format_headers (emfq, buffer, (CamelMedium *) puri->part);
- camel_stream_write_string (stream, buffer->str, cancellable, NULL);
- g_string_free (buffer, TRUE);
- }
-
- puri->write_func (emf, puri, stream, &info, cancellable);
- }
-
- if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE)
- camel_stream_write_string (
- stream, "</blockquote><!--+GtkHTML:"
- "<DATA class=\"ClueFlow\" clear=\"orig\">-->",
- cancellable, NULL);
-}
-
-static void
-emfq_write_text_plain (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf);
- CamelStream *filtered_stream;
- CamelMimeFilter *html_filter;
- CamelMimeFilter *sig_strip;
- CamelContentType *type;
- const gchar *format;
- guint32 rgb = 0x737373, flags;
-
- if (!puri->part)
- return;
-
- flags = emfq->priv->text_html_flags;
-
- /* Check for RFC 2646 flowed text. */
- type = camel_mime_part_get_content_type (puri->part);
- if (camel_content_type_is(type, "text", "plain")
- && (format = camel_content_type_param(type, "format"))
- && !g_ascii_strcasecmp(format, "flowed"))
- flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED;
-
- filtered_stream = camel_stream_filter_new (stream);
-
- if ((emfq->priv->flags & EM_FORMAT_QUOTE_KEEP_SIG) == 0) {
- sig_strip = em_stripsig_filter_new (TRUE);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), sig_strip);
- g_object_unref (sig_strip);
- }
-
- html_filter = camel_mime_filter_tohtml_new (flags, rgb);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), html_filter);
- g_object_unref (html_filter);
-
- em_format_format_text (
- EM_FORMAT (emfq), filtered_stream,
- CAMEL_DATA_WRAPPER (puri->part), cancellable);
-
- camel_stream_flush (filtered_stream, cancellable, NULL);
- g_object_unref (filtered_stream);
-}
-
-static void
-emfq_write_text_enriched (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- CamelStream *filtered_stream;
- CamelMimeFilter *enriched;
- guint32 flags = 0;
- CamelContentType *ct;
- const gchar *mime_type = NULL;
-
- ct = camel_mime_part_get_content_type (puri->part);
- if (ct) {
- mime_type = camel_content_type_simple (ct);
- camel_content_type_unref (ct);
- }
-
- if (g_strcmp0 (mime_type, "text/richtext") == 0) {
- flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT;
- camel_stream_write_string (
- stream, "\n<!-- text/richtext -->\n",
- cancellable, NULL);
- } else {
- camel_stream_write_string (
- stream, "\n<!-- text/enriched -->\n",
- cancellable, NULL);
- }
-
- enriched = camel_mime_filter_enriched_new (flags);
- filtered_stream = camel_stream_filter_new (stream);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), enriched);
- g_object_unref (enriched);
-
- camel_stream_write_string (stream, "<br><hr><br>", cancellable, NULL);
- em_format_format_text (
- emf, filtered_stream, CAMEL_DATA_WRAPPER (puri->part), cancellable);
- camel_stream_flush (filtered_stream, cancellable, NULL);
- g_object_unref (filtered_stream);
-}
-
-static void
-emfq_write_text_html (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatQuotePrivate *priv;
-
- priv = EM_FORMAT_QUOTE_GET_PRIVATE (emf);
-
- camel_stream_write_string (
- stream, "\n<!-- text/html -->\n", cancellable, NULL);
-
- if ((priv->flags & EM_FORMAT_QUOTE_KEEP_SIG) == 0) {
- CamelMimeFilter *sig_strip;
- CamelStream *filtered_stream;
-
- filtered_stream = camel_stream_filter_new (stream);
-
- sig_strip = em_stripsig_filter_new (FALSE);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), sig_strip);
- g_object_unref (sig_strip);
-
- em_format_format_text (
- emf, filtered_stream,
- (CamelDataWrapper *) puri->part, cancellable);
- camel_stream_flush (filtered_stream, cancellable, NULL);
- g_object_unref (filtered_stream);
- } else {
- em_format_format_text (
- emf, stream,
- (CamelDataWrapper *) puri->part, cancellable);
- }
-}
-
-/****************************************************************************/
-static EMFormatHandler type_builtin_table[] = {
- { (gchar *) "text/plain", emfq_parse_text_plain, emfq_write_text_plain, },
- { (gchar *) "text/enriched", emfq_parse_text_enriched, emfq_write_text_enriched, },
- { (gchar *) "text/richtext", emfq_parse_text_enriched, emfq_write_text_enriched, },
- { (gchar *) "text/html", emfq_parse_text_html, emfq_write_text_html, },
- { (gchar *) "text/*", emfq_parse_text_plain, emfq_write_text_plain, },
- { (gchar *) "message/external-body", em_format_empty_parser, em_format_empty_writer, },
- { (gchar *) "multipart/appledouble", em_format_empty_parser, em_format_empty_writer, },
-
- /* internal evolution types */
- { (gchar *) "x-evolution/evolution-rss-feed", 0, emfq_write_text_html, },
- { (gchar *) "x-evolution/message/attachment", emfq_parse_attachment, emfq_write_attachment, },
-};
-
-static void
-emfq_builtin_init (EMFormatQuoteClass *efhc)
-{
- gint ii;
-
- EMFormatClass *emfc = (EMFormatClass *) efhc;
-
- for (ii = 0; ii < G_N_ELEMENTS (type_builtin_table); ii++)
- em_format_class_add_handler (
- emfc, &type_builtin_table[ii]);
-}
diff --git a/em-format/em-format-quote.h b/em-format/em-format-quote.h
deleted file mode 100644
index 4ad66a5d2a..0000000000
--- a/em-format/em-format-quote.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef EM_FORMAT_QUOTE_H
-#define EM_FORMAT_QUOTE_H
-
-#include "em-format.h"
-
-/* Standard GObject macros */
-#define EM_TYPE_FORMAT_QUOTE \
- (em_format_quote_get_type ())
-#define EM_FORMAT_QUOTE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_FORMAT_QUOTE, EMFormatQuote))
-#define EM_FORMAT_QUOTE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_FORMAT_QUOTE, EMFormatQuoteClass))
-#define EM_IS_FORMAT_QUOTE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_FORMAT_QUOTE))
-#define EM_IS_FORMAT_QUOTE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_FORMAT_QUOTE))
-#define EM_FORMAT_QUOTE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_FORMAT_QUOTE, EMFormatQuoteClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EMFormatQuote EMFormatQuote;
-typedef struct _EMFormatQuoteClass EMFormatQuoteClass;
-typedef struct _EMFormatQuotePrivate EMFormatQuotePrivate;
-
-typedef enum {
- EM_FORMAT_QUOTE_CITE = 1 << 0,
- EM_FORMAT_QUOTE_HEADERS = 1 << 1,
- EM_FORMAT_QUOTE_KEEP_SIG = 1 << 2 /* do not strip signature */
-} EMFormatQuoteFlags;
-
-struct _EMFormatQuote {
- EMFormat format;
- EMFormatQuotePrivate *priv;
-};
-
-struct _EMFormatQuoteClass {
- EMFormatClass format_class;
-};
-
-GType em_format_quote_get_type (void);
-EMFormatQuote * em_format_quote_new (CamelSession *session,
- const gchar *credits,
- CamelStream *stream,
- EMFormatQuoteFlags flags);
-void em_format_quote_write (EMFormatQuote *emfq,
- CamelStream *stream,
- GCancellable *cancellable);
-
-G_END_DECLS
-
-#endif /* EM_FORMAT_QUOTE_H */
diff --git a/em-format/em-format.c b/em-format/em-format.c
deleted file mode 100644
index 9603dbd4cb..0000000000
--- a/em-format/em-format.c
+++ /dev/null
@@ -1,2676 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gio/gio.h>
-#include <glib/gi18n-lib.h>
-#include <libsoup/soup-uri.h>
-
-#include "em-format.h"
-#include "e-util/e-util.h"
-#include "shell/e-shell.h"
-#include "shell/e-shell-settings.h"
-
-#define d(x)
-
-#define EM_FORMAT_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), EM_TYPE_FORMAT, EMFormatPrivate))
-
-struct _EMFormatPrivate {
- GNode *current_node;
-
- CamelSession *session;
-
- CamelURL *base_url;
-
- gchar *charset;
- gchar *default_charset;
- gboolean composer;
-
- gint last_error;
-};
-
-enum {
- PROP_0,
- PROP_BASE_URL,
- PROP_CHARSET,
- PROP_COMPOSER,
- PROP_DEFAULT_CHARSET,
- PROP_SESSION
-};
-
-enum {
- REDRAW_REQUESTED,
- LAST_SIGNAL
-};
-
-gint signals[LAST_SIGNAL];
-
-static gpointer parent_class;
-
-/* PARSERS */
-static void emf_parse_application_xpkcs7mime (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_application_mbox (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_alternative (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_appledouble (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_encrypted (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_mixed (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_signed (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_related (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_multipart_digest (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_message_deliverystatus (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_inlinepgp_signed (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_inlinepgp_encrypted (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_message (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_headers (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_post_headers (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void emf_parse_source (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-
-/* WRITERS */
-static void emf_write_text (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emf_write_source (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emf_write_error (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-/**************************************************************************/
-
-static gboolean
-is_secured (CamelMimePart *part)
-{
- CamelContentType *ct = camel_mime_part_get_content_type (part);
-
- return (camel_content_type_is (ct, "multipart", "signed") ||
- camel_content_type_is (ct, "multipart", "encrypted") ||
- camel_content_type_is (ct, "application", "x-inlinepgp-signed") ||
- camel_content_type_is (ct, "application", "x-inlinepgp-encrypted") ||
- camel_content_type_is (ct, "application", "x-pkcs7-mime") ||
- camel_content_type_is (ct, "application", "pkcs7-mime"));
-}
-
-static void
-preserve_charset_in_content_type (CamelMimePart *ipart,
- CamelMimePart *opart)
-{
- CamelDataWrapper *data_wrapper;
- CamelContentType *content_type;
- const gchar *charset;
-
- g_return_if_fail (ipart != NULL);
- g_return_if_fail (opart != NULL);
-
- data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (ipart));
- content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
-
- if (content_type == NULL)
- return;
-
- charset = camel_content_type_param (content_type, "charset");
-
- if (charset == NULL || *charset == '\0')
- return;
-
- data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (opart));
- content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
- if (content_type)
- camel_content_type_set_param (content_type, "charset", charset);
-
- /* update charset also on the part itself */
- data_wrapper = CAMEL_DATA_WRAPPER (opart);
- content_type = camel_data_wrapper_get_mime_type_field (data_wrapper);
- if (content_type)
- camel_content_type_set_param (content_type, "charset", charset);
-}
-
-static CamelMimePart *
-get_related_display_part (CamelMimePart *part,
- gint *out_displayid)
-{
- CamelMultipart *mp;
- CamelMimePart *body_part, *display_part = NULL;
- CamelContentType *content_type;
- const gchar *start;
- gint i, nparts, displayid = 0;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp))
- return NULL;
-
- nparts = camel_multipart_get_number (mp);
- content_type = camel_mime_part_get_content_type (part);
- start = camel_content_type_param (content_type, "start");
- if (start && strlen (start) > 2) {
- gint len;
- const gchar *cid;
-
- /* strip <>'s from CID */
- len = strlen (start) - 2;
- start++;
-
- for (i = 0; i < nparts; i++) {
- body_part = camel_multipart_get_part (mp, i);
- cid = camel_mime_part_get_content_id (body_part);
-
- if (cid && !strncmp (cid, start, len) && strlen (cid) == len) {
- display_part = body_part;
- displayid = i;
- break;
- }
- }
- } else {
- display_part = camel_multipart_get_part (mp, 0);
- }
-
- if (out_displayid)
- *out_displayid = displayid;
-
- return display_part;
-}
-
-static gboolean
-related_display_part_is_attachment (EMFormat *emf,
- CamelMimePart *part)
-{
- CamelMimePart *display_part;
-
- display_part = get_related_display_part (part, NULL);
- return display_part && em_format_is_attachment (emf, display_part);
-}
-
-/**************************************************************************/
-void
-em_format_empty_parser (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- /* DO NOTHING */
-}
-
-#ifdef ENABLE_SMIME
-static void
-emf_parse_application_xpkcs7mime (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelCipherContext *context;
- CamelMimePart *opart;
- CamelCipherValidity *valid;
- GError *local_error = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- context = camel_smime_context_new (emf->priv->session);
-
- opart = camel_mime_part_new ();
- valid = camel_cipher_context_decrypt_sync (
- context, part, opart, cancellable, &local_error);
- preserve_charset_in_content_type (part, opart);
- if (valid == NULL) {
- em_format_format_error (
- emf, "%s",
- local_error->message ? local_error->message :
- _("Could not parse S/MIME message: Unknown error"));
- g_clear_error (&local_error);
- } else {
- EMFormatParserInfo encinfo = {
- info->handler,
- info->validity_type | EM_FORMAT_VALIDITY_FOUND_ENCRYPTED | EM_FORMAT_VALIDITY_FOUND_SMIME,
- valid
- };
- gint len = part_id->len;
-
- g_string_append (part_id, ".encrypted");
- em_format_parse_part (emf, opart, part_id, &encinfo, cancellable);
- g_string_truncate (part_id, len);
-
- /* Add a widget with details about the encryption, but only when
- * the encrypted isn't itself secured, in that case it has created
- * the button itself */
- if (!is_secured (opart)) {
- g_string_append (part_id, ".encrypted.button");
- em_format_parse_part_as (emf, part, part_id, &encinfo,
- "x-evolution/message/x-secure-button", cancellable);
- g_string_truncate (part_id, len);
- }
-
- camel_cipher_validity_free (valid);
- }
-
- g_object_unref (opart);
- g_object_unref (context);
-}
-#endif
-
-/* RFC 4155 */
-static void
-emf_parse_application_mbox (EMFormat *emf,
- CamelMimePart *mime_part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMimeParser *parser;
- CamelStream *mem_stream;
- camel_mime_parser_state_t state;
- gint old_len;
- gint messages;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- /* Extract messages from the application/mbox part and
- * render them as a flat list of messages. */
-
- /* XXX If the mbox has multiple messages, maybe render them
- * as a multipart/digest so each message can be expanded
- * or collapsed individually.
- *
- * See attachment_handler_mail_x_uid_list() for example. */
-
- /* XXX This is based on em_utils_read_messages_from_stream().
- * Perhaps refactor that function to return an array of
- * messages instead of assuming we want to append them
- * to a folder? */
-
- parser = camel_mime_parser_new ();
- camel_mime_parser_scan_from (parser, TRUE);
-
- mem_stream = camel_stream_mem_new ();
- camel_data_wrapper_decode_to_stream_sync (
- camel_medium_get_content (CAMEL_MEDIUM (mime_part)),
- mem_stream, NULL, NULL);
- g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, NULL, NULL);
- camel_mime_parser_init_with_stream (parser, mem_stream, NULL);
- g_object_unref (mem_stream);
-
- old_len = part_id->len;
-
- /* Extract messages from the mbox. */
- messages = 0;
- state = camel_mime_parser_step (parser, NULL, NULL);
-
- while (state == CAMEL_MIME_PARSER_STATE_FROM) {
- CamelMimeMessage *message;
-
- message = camel_mime_message_new ();
- mime_part = CAMEL_MIME_PART (message);
-
- if (!camel_mime_part_construct_from_parser_sync (
- mime_part, parser, NULL, NULL)) {
- g_object_unref (message);
- break;
- }
-
- g_string_append_printf (part_id, ".mbox.%d", messages);
- em_format_parse_part_as (emf, CAMEL_MIME_PART (message),
- part_id, info, "message/rfc822", cancellable);
- g_string_truncate (part_id, old_len);
-
- g_object_unref (message);
-
- /* Skip past CAMEL_MIME_PARSER_STATE_FROM_END. */
- camel_mime_parser_step (parser, NULL, NULL);
-
- state = camel_mime_parser_step (parser, NULL, NULL);
-
- messages++;
- }
-
- g_object_unref (parser);
-}
-
-/* RFC 1740 */
-static void
-emf_parse_multipart_alternative (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- gint i, nparts, bestid = 0;
- CamelMimePart *best = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp)) {
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- /* as per rfc, find the last part we know how to display */
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- CamelMimePart *mpart;
- CamelDataWrapper *data_wrapper;
- CamelContentType *type;
- CamelStream *null_stream;
- gchar *mime_type;
- gsize content_size;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- /* is it correct to use the passed in *part here? */
- mpart = camel_multipart_get_part (mp, i);
-
- if (mpart == NULL)
- continue;
-
- /* This may block even though the stream does not.
- * XXX Pretty inefficient way to test if the MIME part
- * is empty. Surely there's a quicker way? */
- null_stream = camel_stream_null_new ();
- data_wrapper = camel_medium_get_content (CAMEL_MEDIUM (mpart));
- camel_data_wrapper_decode_to_stream_sync (
- data_wrapper, null_stream, cancellable, NULL);
- content_size = CAMEL_STREAM_NULL (null_stream)->written;
- g_object_unref (null_stream);
-
- if (content_size == 0)
- continue;
-
- type = camel_mime_part_get_content_type (mpart);
- mime_type = camel_content_type_simple (type);
-
- camel_strdown (mime_type);
-
- if (!em_format_is_attachment (emf, mpart) &&
- ((camel_content_type_is (type, "multipart", "related") == 0) ||
- !related_display_part_is_attachment (emf, mpart)) &&
- (em_format_find_handler (emf, mime_type)
- || (best == NULL && em_format_fallback_handler (emf, mime_type)))) {
- best = mpart;
- bestid = i;
- }
-
- g_free (mime_type);
- }
-
- if (best) {
- gint len = part_id->len;
-
- g_string_append_printf(part_id, ".alternative.%d", bestid);
- em_format_parse_part (emf, best, part_id, info, cancellable);
- g_string_truncate (part_id, len);
- } else
- emf_parse_multipart_mixed (emf, part, part_id, info, cancellable);
-}
-
-/* RFC 1740 */
-static void
-emf_parse_multipart_appledouble (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- CamelMimePart *mime_part;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp)) {
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- mime_part = camel_multipart_get_part (mp, 1);
- if (mime_part) {
- gint len;
- /* try the data fork for something useful, doubtful but who knows */
- len = part_id->len;
- g_string_append_printf(part_id, ".appledouble.1");
- em_format_parse_part (emf, mime_part, part_id, info, cancellable);
- g_string_truncate (part_id, len);
- } else {
- emf_parse_source (emf, part, part_id, info, cancellable);
- }
-}
-
-static void
-emf_parse_multipart_encrypted (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelCipherContext *context;
- const gchar *protocol;
- CamelMimePart *opart;
- CamelCipherValidity *valid;
- CamelMultipartEncrypted *mpe;
- GError *local_error = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mpe = (CamelMultipartEncrypted *) camel_medium_get_content ((CamelMedium *) part);
- if (!CAMEL_IS_MULTIPART_ENCRYPTED (mpe)) {
- em_format_format_error (
- emf, _("Could not parse MIME message. "
- "Displaying as source."));
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- /* Currently we only handle RFC2015-style PGP encryption. */
- protocol = camel_content_type_param (
- ((CamelDataWrapper *)mpe)->mime_type, "protocol");
- if (!protocol || g_ascii_strcasecmp (protocol, "application/pgp-encrypted") != 0) {
- em_format_format_error (emf, _("Unsupported encryption type for multipart/encrypted"));
- emf_parse_multipart_mixed (emf, part, part_id, info, cancellable);
- return;
- }
-
- context = camel_gpg_context_new (emf->priv->session);
- opart = camel_mime_part_new ();
- valid = camel_cipher_context_decrypt_sync (
- context, part, opart, cancellable, &local_error);
- preserve_charset_in_content_type (part, opart);
- if (valid == NULL) {
- em_format_format_error (
- emf, local_error->message ?
- _("Could not parse PGP/MIME message") :
- _("Could not parse PGP/MIME message: Unknown error"));
- if (local_error->message != NULL)
- em_format_format_error (
- emf, "%s", local_error->message);
- g_clear_error (&local_error);
- emf_parse_multipart_mixed (emf, part, part_id, info, cancellable);
- } else {
- gint len = part_id->len;
-
- EMFormatParserInfo encinfo = {
- info->handler,
- info->validity_type | EM_FORMAT_VALIDITY_FOUND_ENCRYPTED | EM_FORMAT_VALIDITY_FOUND_PGP,
- };
-
- if (info->validity)
- camel_cipher_validity_envelope (valid, info->validity);
-
- encinfo.validity = valid;
-
- g_string_append (part_id, ".encrypted");
- em_format_parse_part (emf, opart, part_id, &encinfo, cancellable);
- g_string_truncate (part_id, len);
-
- /* Add a widget with details about the encryption, but only when
- * the encrypted isn't itself secured, in that case it has created
- * the button itself */
- if (!is_secured (opart)) {
- g_string_append (part_id, ".encrypted.button");
- em_format_parse_part_as (emf, part, part_id, &encinfo,
- "x-evolution/message/x-secure-button", cancellable);
- g_string_truncate (part_id, len);
- }
-
- camel_cipher_validity_free (valid);
- }
-
- /* TODO: Make sure when we finalize this part, it is zero'd out */
- g_object_unref (opart);
- g_object_unref (context);
-}
-
-/* RFC 2046 */
-static void
-emf_parse_multipart_mixed (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- gint i, nparts, len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp)) {
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- len = part_id->len;
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- CamelMimePart *subpart;
-
- subpart = camel_multipart_get_part (mp, i);
-
- g_string_append_printf(part_id, ".mixed.%d", i);
- em_format_parse_part (emf, subpart, part_id, info, cancellable);
- g_string_truncate (part_id, len);
- }
-}
-
-static void
-emf_parse_multipart_signed (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMimePart *cpart;
- CamelMultipartSigned *mps;
- CamelCipherContext *cipher = NULL;
- guint32 validity_type;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mps = (CamelMultipartSigned *) camel_medium_get_content ((CamelMedium *) part);
- if (!CAMEL_IS_MULTIPART_SIGNED (mps)
- || (cpart = camel_multipart_get_part ((CamelMultipart *) mps,
- CAMEL_MULTIPART_SIGNED_CONTENT)) == NULL) {
- em_format_format_error (
- emf, _("Could not parse MIME message. "
- "Displaying as source."));
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- /* FIXME: Should be done via a plugin interface */
- /* FIXME: duplicated in em-format-html-display.c */
- if (mps->protocol) {
-#ifdef ENABLE_SMIME
- if (g_ascii_strcasecmp("application/x-pkcs7-signature", mps->protocol) == 0
- || g_ascii_strcasecmp("application/pkcs7-signature", mps->protocol) == 0) {
- cipher = camel_smime_context_new (emf->priv->session);
- validity_type = EM_FORMAT_VALIDITY_FOUND_SMIME;
- } else
-#endif
- if (g_ascii_strcasecmp("application/pgp-signature", mps->protocol) == 0) {
- cipher = camel_gpg_context_new (emf->priv->session);
- validity_type = EM_FORMAT_VALIDITY_FOUND_PGP;
- }
- }
-
- if (cipher == NULL) {
- em_format_format_error(emf, _("Unsupported signature format"));
- emf_parse_multipart_mixed (emf, part, part_id, info, cancellable);
- } else {
- CamelCipherValidity *valid;
- GError *local_error = NULL;
-
- valid = camel_cipher_context_verify_sync (
- cipher, part, cancellable, &local_error);
- if (valid == NULL) {
- em_format_format_error (
- emf, local_error->message ?
- _("Error verifying signature") :
- _("Unknown error verifying signature"));
- if (local_error->message != NULL)
- em_format_format_error (
- emf, "%s",
- local_error->message);
- g_clear_error (&local_error);
- emf_parse_multipart_mixed (emf, part, part_id,info, cancellable);
- } else {
- gint i, nparts, len = part_id->len;
- gboolean secured;
-
- EMFormatParserInfo signinfo = {
- info->handler,
- info->validity_type | validity_type | EM_FORMAT_VALIDITY_FOUND_SIGNED,
- };
-
- if (info->validity)
- camel_cipher_validity_envelope (valid, info->validity);
- signinfo.validity = valid;
-
- nparts = camel_multipart_get_number (CAMEL_MULTIPART (mps));
- secured = FALSE;
- for (i = 0; i < nparts; i++) {
- CamelMimePart *subpart;
- subpart = camel_multipart_get_part (CAMEL_MULTIPART (mps), i);
-
- g_string_append_printf(part_id, ".signed.%d", i);
- em_format_parse_part (emf, subpart, part_id, &signinfo, cancellable);
- g_string_truncate (part_id, len);
-
- if (!secured)
- secured = is_secured (subpart);
- }
-
- /* Add a widget with details about the encryption, but only when
- * the encrypted isn't itself secured, in that case it has created
- * the button itself */
- if (!secured) {
- g_string_append (part_id, ".signed.button");
- em_format_parse_part_as (emf, part, part_id, &signinfo,
- "x-evolution/message/x-secure-button", cancellable);
- g_string_truncate (part_id, len);
- }
-
- camel_cipher_validity_free (valid);
- }
- }
-
- g_object_unref (cipher);
-}
-
-/* RFC 2046 */
-static void
-emf_parse_multipart_digest (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- gint i, nparts, len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp)) {
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- len = part_id->len;
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- CamelMimePart *subpart;
- CamelContentType *ct;
- gchar *cts;
- const EMFormatHandler *handler;
-
- subpart = camel_multipart_get_part (mp, i);
-
- if (!subpart)
- continue;
-
- g_string_append_printf(part_id, ".digest.%d", i);
-
- ct = camel_mime_part_get_content_type (subpart);
- /* According to RFC this shouldn't happen, but who knows... */
- if (ct && !camel_content_type_is (ct, "message", "rfc822")) {
- cts = camel_content_type_simple (ct);
- em_format_parse_part_as (emf, part, part_id, info, cts, cancellable);
- g_free (cts);
- g_string_truncate (part_id, len);
- continue;
- }
-
- handler = em_format_find_handler (emf, "message/rfc822");
- if (handler && handler->parse_func)
- handler->parse_func (emf, subpart, part_id, info, cancellable);
-
- g_string_truncate (part_id, len);
- }
-}
-
-/* RFC 2387 */
-static void
-emf_parse_multipart_related (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelMultipart *mp;
- CamelMimePart *body_part, *display_part = NULL;
- gint i, nparts, partidlen, displayid = 0;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- if (!CAMEL_IS_MULTIPART (mp)) {
- emf_parse_source (emf, part, part_id, info, cancellable);
- return;
- }
-
- display_part = get_related_display_part (part, &displayid);
-
- if (display_part == NULL) {
- emf_parse_multipart_mixed (
- emf, part, part_id, info, cancellable);
- return;
- }
-
- /* The to-be-displayed part goes first */
- partidlen = part_id->len;
- g_string_append_printf(part_id, ".related.%d", displayid);
- em_format_parse_part (emf, display_part, part_id, info, cancellable);
- g_string_truncate (part_id, partidlen);
-
- /* Process the related parts */
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- body_part = camel_multipart_get_part (mp, i);
- if (body_part != display_part) {
- g_string_append_printf(part_id, ".related.%d", i);
- em_format_parse_part (emf, body_part, part_id, info, cancellable);
- g_string_truncate (part_id, partidlen);
- }
- }
-}
-
-static void
-emf_parse_message_deliverystatus (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- len = part_id->len;
- g_string_append (part_id, ".deliverystatus");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = emf_write_text;
- puri->mime_type = g_strdup ("text/html");
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
-
- g_string_truncate (part_id, len);
-
- em_format_add_puri (emf, puri);
-}
-
-static void
-emf_parse_inlinepgp_signed (EMFormat *emf,
- CamelMimePart *ipart,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelStream *filtered_stream;
- CamelMimeFilterPgp *pgp_filter;
- CamelContentType *content_type;
- CamelCipherContext *cipher;
- CamelCipherValidity *valid;
- CamelDataWrapper *dw;
- CamelMimePart *opart;
- CamelStream *ostream;
- gchar *type;
- gint len;
- GError *local_error = NULL;
- EMFormatParserInfo signinfo;
- GByteArray *ba;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- if (!ipart) {
- em_format_format_error(emf, _("Unknown error verifying signature"));
- return;
- }
-
- cipher = camel_gpg_context_new (emf->priv->session);
- /* Verify the signature of the message */
- valid = camel_cipher_context_verify_sync (
- cipher, ipart, cancellable, &local_error);
- if (!valid) {
- em_format_format_error (
- emf, local_error->message ?
- _("Error verifying signature") :
- _("Unknown error verifying signature"));
- if (local_error->message)
- em_format_format_error (
- emf, "%s", local_error->message);
- emf_parse_source (emf, ipart, part_id, info, cancellable);
- /* XXX I think this will loop:
- * em_format_part_as(emf, stream, part, "text/plain"); */
- g_clear_error (&local_error);
- g_object_unref (cipher);
- return;
- }
-
- /* Setup output stream */
- ostream = camel_stream_mem_new ();
- filtered_stream = camel_stream_filter_new (ostream);
-
- /* Add PGP header / footer filter */
- pgp_filter = (CamelMimeFilterPgp *) camel_mime_filter_pgp_new ();
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream),
- CAMEL_MIME_FILTER (pgp_filter));
- g_object_unref (pgp_filter);
-
- /* Pass through the filters that have been setup */
- dw = camel_medium_get_content ((CamelMedium *) ipart);
- camel_data_wrapper_decode_to_stream_sync (
- dw, (CamelStream *) filtered_stream, cancellable, NULL);
- camel_stream_flush ((CamelStream *) filtered_stream, cancellable, NULL);
- g_object_unref (filtered_stream);
-
- /* Create a new text/plain MIME part containing the signed
- * content preserving the original part's Content-Type params. */
- content_type = camel_mime_part_get_content_type (ipart);
- type = camel_content_type_format (content_type);
- content_type = camel_content_type_decode (type);
- g_free (type);
-
- g_free (content_type->type);
- content_type->type = g_strdup ("text");
- g_free (content_type->subtype);
- content_type->subtype = g_strdup ("plain");
- type = camel_content_type_format (content_type);
- camel_content_type_unref (content_type);
-
- ba = camel_stream_mem_get_byte_array ((CamelStreamMem *) ostream);
- opart = camel_mime_part_new ();
- camel_mime_part_set_content (opart, (gchar *) ba->data, ba->len, type);
- g_free (type);
-
- if (info->validity)
- camel_cipher_validity_envelope (valid, info->validity);
-
- /* Pass it off to the real formatter */
- len = part_id->len;
- g_string_append (part_id, ".inlinepgp_signed");
- signinfo.handler = info->handler;
- signinfo.validity_type = info->validity_type | EM_FORMAT_VALIDITY_FOUND_SIGNED | EM_FORMAT_VALIDITY_FOUND_PGP;
- signinfo.validity = valid;
- em_format_parse_part (emf, opart, part_id, &signinfo, cancellable);
- g_string_truncate (part_id, len);
-
- /* Add a widget with details about the encryption, but only when
- * the encrypted isn't itself secured, in that case it has created
- * the button itself */
- if (!is_secured (opart)) {
- g_string_append (part_id, ".inlinepgp_signed.button");
- em_format_parse_part_as (emf, opart, part_id, &signinfo,
- "x-evolution/message/x-secure-button", cancellable);
- g_string_truncate (part_id, len);
- }
-
- /* Clean Up */
- camel_cipher_validity_free (valid);
- g_object_unref (dw);
- g_object_unref (opart);
- g_object_unref (ostream);
- g_object_unref (cipher);
-}
-
-static void
-emf_parse_inlinepgp_encrypted (EMFormat *emf,
- CamelMimePart *ipart,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelCipherContext *cipher;
- CamelCipherValidity *valid;
- CamelMimePart *opart;
- CamelDataWrapper *dw;
- gchar *mime_type;
- gint len;
- GError *local_error = NULL;
- EMFormatParserInfo encinfo;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- cipher = camel_gpg_context_new (emf->priv->session);
- opart = camel_mime_part_new ();
-
- /* Decrypt the message */
- valid = camel_cipher_context_decrypt_sync (
- cipher, ipart, opart, cancellable, &local_error);
-
- if (!valid) {
- em_format_format_error (
- emf, _("Could not parse PGP message: "));
- if (local_error->message != NULL)
- em_format_format_error (
- emf, "%s", local_error->message);
- else
- em_format_format_error (
- emf, _("Unknown error"));
- emf_parse_source (emf, ipart, part_id, info, cancellable);
- /* XXX I think this will loop:
- * em_format_part_as(emf, stream, part, "text/plain"); */
-
- g_clear_error (&local_error);
- g_object_unref (cipher);
- g_object_unref (opart);
- return;
- }
-
- dw = camel_medium_get_content ((CamelMedium *) opart);
- mime_type = camel_data_wrapper_get_mime_type (dw);
-
- /* this ensures to show the 'opart' as inlined, if possible */
- if (mime_type && g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0) {
- const gchar *snoop = em_format_snoop_type (opart);
-
- if (snoop)
- camel_data_wrapper_set_mime_type (dw, snoop);
- }
-
- preserve_charset_in_content_type (ipart, opart);
- g_free (mime_type);
-
- if (info->validity)
- camel_cipher_validity_envelope (valid, info->validity);
-
- /* Pass it off to the real formatter */
- len = part_id->len;
- g_string_append (part_id, ".inlinepgp_encrypted");
- encinfo.handler = info->handler;
- encinfo.validity_type = info->validity_type | EM_FORMAT_VALIDITY_FOUND_ENCRYPTED | EM_FORMAT_VALIDITY_FOUND_PGP;
- encinfo.validity = valid;
- em_format_parse_part (emf, opart, part_id, &encinfo, cancellable);
- g_string_truncate (part_id, len);
-
- /* Add a widget with details about the encryption, but only when
- * the encrypted isn't itself secured, in that case it has created
- * the button itself */
- if (!is_secured (opart)) {
- g_string_append (part_id, ".inlinepgp_encrypted.button");
- em_format_parse_part_as (emf, opart, part_id, &encinfo,
- "x-evolution/message/x-secure-button", cancellable);
- g_string_truncate (part_id, len);
- }
-
- /* Clean Up */
- camel_cipher_validity_free (valid);
- g_object_unref (opart);
- g_object_unref (cipher);
-}
-
-static void
-emf_parse_message (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- /* Headers */
- info->force_handler = TRUE;
- em_format_parse_part_as (emf, part, part_id, info,
- "x-evolution/message/headers", cancellable);
-
- /* Anything that comes between headers and message body */
- info->force_handler = TRUE;
- em_format_parse_part_as (emf, part, part_id, info,
- "x-evolution/message/post-headers", cancellable);
-
- /* Begin parsing the message */
- info->force_handler = FALSE;
- em_format_parse_part (emf, part, part_id, info, cancellable);
-}
-
-static void
-emf_parse_headers (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- len = part_id->len;
- g_string_append (part_id, ".headers");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = info->handler->write_func;
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-}
-
-static void
-emf_parse_post_headers (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- /* Add attachment bar */
- info->force_handler = TRUE;
- em_format_parse_part_as (emf, part, part_id, info,
- "x-evolution/message/attachment-bar", cancellable);
-}
-
-static void
-emf_parse_source (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- len = part_id->len;
- g_string_append (part_id, ".source");
-
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = info->handler->write_func;
- puri->mime_type = g_strdup ("text/html");
- g_string_truncate (part_id, len);
-
- em_format_add_puri (emf, puri);
-}
-
-/**************************************************************************/
-
-void
-em_format_empty_writer (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- /* DO NOTHING */
-}
-
-static void
-emf_write_error (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) puri->part,
- stream, cancellable, NULL);
-}
-
-static void
-emf_write_text (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- CamelContentType *ct;
-
- ct = camel_mime_part_get_content_type (puri->part);
- if (!camel_content_type_is (ct, "text", "plain")) {
- camel_stream_write_string (stream, _("Cannot proccess non-text mime/part"),
- cancellable, NULL);
- return;
- }
-
- camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) puri->part,
- stream, cancellable, NULL);
-}
-
-static void
-emf_write_source (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GByteArray *ba;
- gchar *data;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- ba = camel_data_wrapper_get_byte_array ((CamelDataWrapper *) puri->part);
-
- data = g_strndup ((gchar *) ba->data, ba->len);
- camel_stream_write_string (stream, data, cancellable, NULL);
- g_free (data);
-}
-
-/**************************************************************************/
-
-static gboolean
-emf_is_inline (EMFormat *emf,
- const gchar *part_id,
- CamelMimePart *mime_part,
- const EMFormatHandler *handle)
-{
- //EMFormatCache *emfc;
- const gchar *disposition;
-
- if (handle == NULL)
- return FALSE;
-
- /* Some types need to override the disposition.
- * e.g. application/x-pkcs7-mime */
- if (handle->flags & EM_FORMAT_HANDLER_INLINE_DISPOSITION)
- return TRUE;
-
- disposition = camel_mime_part_get_disposition (mime_part);
- if (disposition != NULL)
- return g_ascii_strcasecmp (disposition, "inline") == 0;
-
- /* Otherwise, use the default for this handler type. */
- return (handle->flags & EM_FORMAT_HANDLER_INLINE) != 0;
-}
-
-/**************************************************************************/
-
-static EMFormatHandler type_handlers[] = {
-#ifdef ENABLE_SMIME
- { (gchar *) "application/x-pkcs7-mime", emf_parse_application_xpkcs7mime, 0, EM_FORMAT_HANDLER_INLINE_DISPOSITION },
-#endif
- { (gchar *) "application/mbox", emf_parse_application_mbox, 0, EM_FORMAT_HANDLER_INLINE | EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "multipart/alternative", emf_parse_multipart_alternative, },
- { (gchar *) "multipart/appledouble", emf_parse_multipart_appledouble, },
- { (gchar *) "multipart/encrypted", emf_parse_multipart_encrypted, },
- { (gchar *) "multipart/mixed", emf_parse_multipart_mixed, },
- { (gchar *) "multipart/signed", emf_parse_multipart_signed, },
- { (gchar *) "multipart/related", emf_parse_multipart_related, },
- { (gchar *) "multipart/digest", emf_parse_multipart_digest, 0, EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "multipart/*", emf_parse_multipart_mixed, 0, EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "message/deliverystatus", emf_parse_message_deliverystatus, 0, },
-
- /* Ignore PGP signature part */
- { (gchar *) "application/pgp-signature", em_format_empty_parser, },
-
- /* Insert brokenly-named parts here */
-#ifdef ENABLE_SMIME
- { (gchar *) "application/pkcs7-mime", emf_parse_application_xpkcs7mime, 0, EM_FORMAT_HANDLER_INLINE_DISPOSITION },
-#endif
-
- /* internal types */
- { (gchar *) "application/x-inlinepgp-signed", emf_parse_inlinepgp_signed, },
- { (gchar *) "application/x-inlinepgp-encrypted", emf_parse_inlinepgp_encrypted, },
- { (gchar *) "x-evolution/message", emf_parse_message, 0, EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "x-evolution/message/headers", emf_parse_headers, },
- { (gchar *) "x-evolution/message/post-headers", emf_parse_post_headers, },
- { (gchar *) "x-evolution/message/source", emf_parse_source, emf_write_source },
-};
-
-/* note: also copied in em-mailer-prefs.c */
-static const struct {
- const gchar *name;
- guint32 flags;
-} default_headers[] = {
- { N_("From"), EM_FORMAT_HEADER_BOLD },
- { N_("Reply-To"), EM_FORMAT_HEADER_BOLD },
- { N_("To"), EM_FORMAT_HEADER_BOLD },
- { N_("Cc"), EM_FORMAT_HEADER_BOLD },
- { N_("Bcc"), EM_FORMAT_HEADER_BOLD },
- { N_("Subject"), EM_FORMAT_HEADER_BOLD },
- { N_("Date"), EM_FORMAT_HEADER_BOLD },
- { N_("Newsgroups"), EM_FORMAT_HEADER_BOLD },
- { N_("Face"), 0 },
-};
-
-static void
-em_format_set_session (EMFormat *emf,
- CamelSession *session)
-{
- g_return_if_fail (CAMEL_IS_SESSION (session));
- g_return_if_fail (emf->priv->session == NULL);
-
- emf->priv->session = g_object_ref (session);
-}
-
-static void
-em_format_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_BASE_URL:
- em_format_set_base_url (
- EM_FORMAT (object),
- g_value_get_object (value));
- return;
-
- case PROP_CHARSET:
- em_format_set_charset (
- EM_FORMAT (object),
- g_value_get_string (value));
- return;
-
- case PROP_COMPOSER:
- em_format_set_composer (
- EM_FORMAT (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_DEFAULT_CHARSET:
- em_format_set_default_charset (
- EM_FORMAT (object),
- g_value_get_string (value));
- return;
-
- case PROP_SESSION:
- em_format_set_session (
- EM_FORMAT (object),
- g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-
-}
-
-static void
-em_format_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_BASE_URL:
- g_value_set_object (
- value, em_format_get_base_url (
- EM_FORMAT (object)));
- return;
-
- case PROP_CHARSET:
- g_value_set_string (
- value, em_format_get_charset (
- EM_FORMAT (object)));
- return;
-
- case PROP_COMPOSER:
- g_value_set_boolean (
- value, em_format_get_composer (
- EM_FORMAT (object)));
- return;
-
- case PROP_DEFAULT_CHARSET:
- g_value_set_string (
- value, em_format_get_default_charset (
- EM_FORMAT (object)));
- return;
-
- case PROP_SESSION:
- g_value_set_object (
- value, em_format_get_session (
- EM_FORMAT (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-em_format_finalize (GObject *object)
-{
- EMFormat *emf = EM_FORMAT (object);
-
- if (emf->message_uid) {
- g_free (emf->message_uid);
- emf->message_uid = NULL;
- }
-
- if (emf->uri_base) {
- g_free (emf->uri_base);
- emf->uri_base = NULL;
- }
-
- if (emf->message) {
- g_object_unref (emf->message);
- emf->message = NULL;
- }
-
- if (emf->folder) {
- g_object_unref (emf->folder);
- emf->folder = NULL;
- }
-
- if (emf->mail_part_table) {
- /* This will destroy all the EMFormatPURI objects stored
- * inside!!!! */
- g_hash_table_destroy (emf->mail_part_table);
- emf->mail_part_table = NULL;
- }
-
- if (emf->mail_part_list) {
- g_list_free (emf->mail_part_list);
- emf->mail_part_list = NULL;
- }
-
- if (emf->priv->base_url) {
- camel_url_free (emf->priv->base_url);
- emf->priv->base_url = NULL;
- }
-
- if (emf->priv->session) {
- g_object_unref (emf->priv->session);
- emf->priv->session = NULL;
- }
-
- if (emf->priv->charset) {
- g_free (emf->priv->charset);
- emf->priv->charset = NULL;
- }
-
- em_format_clear_headers (emf);
-
- /* Chain up to parent's finalize() method */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-em_format_base_init (EMFormatClass *class)
-{
- gint i;
-
- class->type_handlers = g_hash_table_new (g_str_hash, g_str_equal);
-
- for (i = 0; i < G_N_ELEMENTS (type_handlers); i++) {
- g_hash_table_insert (class->type_handlers,
- type_handlers[i].mime_type,
- &type_handlers[i]);
- }
-}
-
-static void
-em_format_class_init (EMFormatClass *class)
-{
- GObjectClass *object_class;
-
- parent_class = g_type_class_peek_parent (class);
-
- g_type_class_add_private (class, sizeof (EMFormatPrivate));
-
- class->is_inline = emf_is_inline;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = em_format_set_property;
- object_class->get_property = em_format_get_property;
- object_class->finalize = em_format_finalize;
-
- g_object_class_install_property (
- object_class,
- PROP_BASE_URL,
- g_param_spec_pointer (
- "base-url",
- NULL,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_CHARSET,
- g_param_spec_string (
- "charset",
- NULL,
- NULL,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_COMPOSER,
- g_param_spec_boolean (
- "composer",
- NULL,
- NULL,
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_DEFAULT_CHARSET,
- g_param_spec_string (
- "default-charset",
- NULL,
- NULL,
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_SESSION,
- g_param_spec_object (
- "session",
- "Session",
- "A CamelSession",
- CAMEL_TYPE_SESSION,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- signals[REDRAW_REQUESTED] = g_signal_new (
- "redraw-requested",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EMFormatClass, redraw_requested),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,0);
-}
-
-static void
-mail_part_table_item_free (gpointer data)
-{
- GList *iter = data;
- EMFormatPURI *puri = iter->data;
-
- em_format_puri_free (puri);
-}
-
-static void
-em_format_init (EMFormat *emf)
-{
- emf->priv = EM_FORMAT_GET_PRIVATE (emf);
-
- emf->message = NULL;
- emf->folder = NULL;
- emf->mail_part_list = NULL;
- emf->mail_part_table = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify) mail_part_table_item_free);
- /* No need to free the key, because it's owned and free'd by the PURI */
-
- emf->priv->last_error = 0;
-
- em_format_default_headers (emf);
-}
-
-EMFormat *
-em_format_new (void)
-{
- return g_object_new (EM_TYPE_FORMAT, NULL);
-}
-
-GType
-em_format_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EMFormatClass),
- (GBaseInitFunc) em_format_base_init,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) em_format_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EMFormat),
- 0, /* n_preallocs */
- (GInstanceInitFunc) em_format_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- G_TYPE_OBJECT, "EMFormat", &type_info, 0);
- }
-
- return type;
-}
-
-void
-em_format_set_charset (EMFormat *emf,
- const gchar *charset)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- if (emf->priv->charset)
- g_free (emf->priv->charset);
-
- emf->priv->charset = g_strdup (charset);
-
- g_object_notify (G_OBJECT (emf), "charset");
-}
-
-const gchar *
-em_format_get_charset (EMFormat *emf)
-{
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
-
- return emf->priv->charset;
-}
-
-void
-em_format_set_default_charset (EMFormat *emf,
- const gchar *charset)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- if (emf->priv->default_charset)
- g_free (emf->priv->default_charset);
-
- emf->priv->default_charset = g_strdup (charset);
-
- g_object_notify (G_OBJECT (emf), "default-charset");
-}
-
-const gchar *
-em_format_get_default_charset (EMFormat *emf)
-{
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
-
- return emf->priv->default_charset;
-}
-
-void
-em_format_set_composer (EMFormat *emf,
- gboolean composer)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- if (emf->priv->composer && composer)
- return;
-
- emf->priv->composer = composer;
-
- g_object_notify (G_OBJECT (emf), "composer");
-}
-
-gboolean
-em_format_get_composer (EMFormat *emf)
-{
- g_return_val_if_fail (EM_IS_FORMAT (emf), FALSE);
-
- return emf->priv->composer;
-}
-
-CamelSession *
-em_format_get_session (EMFormat *emf)
-{
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
-
- return emf->priv->session;
-}
-
-void
-em_format_set_base_url (EMFormat *emf,
- CamelURL *url)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (url);
-
- if (emf->priv->base_url)
- camel_url_free (emf->priv->base_url);
-
- emf->priv->base_url = camel_url_copy (url);
-
- g_object_notify (G_OBJECT (emf), "base-url");
-}
-
-void
-em_format_set_base_url_string (EMFormat *emf,
- const gchar *url_string)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (url_string && *url_string);
-
- if (emf->priv->base_url)
- camel_url_free (emf->priv->base_url);
-
- emf->priv->base_url = camel_url_new (url_string, NULL);
-
- g_object_notify (G_OBJECT (emf), "base-url");
-}
-
-CamelURL *
-em_format_get_base_url (EMFormat *emf)
-{
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
-
- return emf->priv->base_url;
-}
-
-/**
- * em_format_clear_headers:
- * @emf:
- *
- * Clear the list of headers to be displayed. This will force all headers to
- * be shown.
- **/
-void
-em_format_clear_headers (EMFormat *emf)
-{
- EMFormatHeader *eh;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- while ((eh = g_queue_pop_head (&emf->header_list)) != NULL) {
- em_format_header_free (eh);
- }
-
-}
-
-void
-em_format_default_headers (EMFormat *emf)
-{
- gint ii;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- /* Set the default headers */
- em_format_clear_headers (emf);
- for (ii = 0; ii < G_N_ELEMENTS (default_headers); ii++)
- em_format_add_header (
- emf, default_headers[ii].name, NULL,
- default_headers[ii].flags);
-}
-
-/**
- * em_format_add_header:
- * @emf:
- * @name: The name of the header, as it will appear during output.
- * @value: Value of the header. Can be NULL.
- * @flags: EM_FORMAT_HEAD_* defines to control display attributes.
- *
- * Add a specific header to show. If any headers are set, they will
- * be displayed in the order set by this function. Certain known
- * headers included in this list will be shown using special
- * formatting routines.
- **/
-void
-em_format_add_header (EMFormat *emf,
- const gchar *name,
- const gchar *value,
- guint32 flags)
-{
- EMFormatHeader *h;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (name && *name);
-
- h = em_format_header_new (name, value);
- h->flags = flags;
- g_queue_push_tail (&emf->header_list, h);
-}
-
-void
-em_format_add_header_struct (EMFormat *emf,
- EMFormatHeader *header)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (header && header->name);
-
- em_format_add_header (emf, header->name, header->value, header->flags);
-}
-
-void
-em_format_remove_header (EMFormat *emf,
- const gchar *name,
- const gchar *value)
-{
- GList *iter = NULL;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (name && *name);
-
- iter = g_queue_peek_head_link (&emf->header_list);
- while (iter) {
- EMFormatHeader *header = iter->data;
-
- if (!header->value || !*header->value) {
- GList *next = iter->next;
- if (g_strcmp0 (name, header->name) == 0)
- g_queue_delete_link (&emf->header_list, iter);
-
- iter = next;
- continue;
- }
-
- if (value && *value) {
- if ((g_strcmp0 (name, header->name) == 0) &&
- (g_strcmp0 (value, header->value) == 0))
- break;
- } else {
- if (g_strcmp0 (name, header->name) == 0)
- break;
- }
-
- iter = iter->next;
- }
-
- if (iter) {
- em_format_header_free (iter->data);
- g_queue_delete_link (&emf->header_list, iter);
- }
-}
-
-void
-em_format_remove_header_struct (EMFormat *emf,
- const EMFormatHeader *header)
-{
- g_return_if_fail (header);
-
- em_format_remove_header (emf, header->name, header->value);
-}
-
-void
-em_format_add_puri (EMFormat *emf,
- EMFormatPURI *puri)
-{
- GList *item;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (puri != NULL);
-
- emf->mail_part_list = g_list_append (emf->mail_part_list, puri);
- item = g_list_last (emf->mail_part_list);
-
- g_hash_table_insert (emf->mail_part_table,
- puri->uri, item);
-
- d(printf("Added PURI %s\n", puri->uri));
-}
-
-EMFormatPURI *
-em_format_find_puri (EMFormat *emf,
- const gchar *id)
-{
- GList *list_iter;
-
- /* First handle CIDs... */
- if (g_str_has_prefix (id, "CID:") || g_str_has_prefix (id, "cid:")) {
- GHashTableIter iter;
- gpointer key, value;
-
- g_hash_table_iter_init (&iter, emf->mail_part_table);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- EMFormatPURI *puri = ((GList *) value)->data;
- if (g_strcmp0 (puri->cid, id) == 0)
- return puri;
- }
-
- return NULL;
- }
-
- list_iter = g_hash_table_lookup (emf->mail_part_table, id);
- if (list_iter)
- return list_iter->data;
-
- return NULL;
-}
-
-void
-em_format_class_add_handler (EMFormatClass *emfc,
- EMFormatHandler *handler)
-{
- EMFormatHandler *old_handler;
-
- g_return_if_fail (EM_IS_FORMAT_CLASS (emfc));
- g_return_if_fail (handler);
-
- old_handler = g_hash_table_lookup (
- emfc->type_handlers, handler->mime_type);
-
- handler->old = old_handler;
-
- /* If parse_func or write_func of the new handler is not set,
- * use function from the old handler (if it exists).
- * This way we can assign a new write_func for to an existing
- * parse_func */
- if (old_handler && handler->parse_func == NULL) {
- handler->parse_func = old_handler->parse_func;
- }
-
- if (old_handler && handler->write_func == NULL) {
- handler->write_func = old_handler->write_func;
- }
-
- g_hash_table_insert (emfc->type_handlers,
- handler->mime_type, handler);
-}
-
-void
-em_format_class_remove_handler (EMFormatClass *emfc,
- EMFormatHandler *handler)
-{
- g_return_if_fail (EM_IS_FORMAT_CLASS (emfc));
- g_return_if_fail (handler);
-
- g_hash_table_remove (emfc->type_handlers, handler->mime_type);
-}
-
-const EMFormatHandler *
-em_format_find_handler (EMFormat *emf,
- const gchar *mime_type)
-{
- EMFormatClass *emfc;
- gchar *s;
- const EMFormatHandler *handler;
-
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
- g_return_val_if_fail (mime_type && *mime_type, NULL);
-
- emfc = (EMFormatClass *) G_OBJECT_GET_CLASS (emf);
-
- s = g_ascii_strdown (mime_type, -1);
-
- handler = g_hash_table_lookup (
- emfc->type_handlers, s);
-
- g_free (s);
-
- return handler;
-}
-
-/**
- * em_format_fallback_handler:
- * @emf:
- * @mime_type:
- *
- * Try to find a format handler based on the major type of the @mime_type.
- *
- * The subtype is replaced with "*" and a lookup performed.
- *
- * Return value:
- **/
-const EMFormatHandler *
-em_format_fallback_handler (EMFormat *emf,
- const gchar *mime_type)
-{
- gchar *mime, *s;
-
- s = strchr (mime_type, '/');
- if (s == NULL)
- mime = (gchar *) mime_type;
- else {
- gsize len = (s - mime_type) + 1;
-
- mime = g_alloca (len + 2);
- strncpy (mime, mime_type, len);
- strcpy(mime+len, "*");
- }
-
- return em_format_find_handler (emf, mime);
-}
-
-void
-em_format_parse (EMFormat *emf,
- CamelMimeMessage *message,
- CamelFolder *folder,
- GCancellable *cancellable)
-{
- GString *part_id;
- EMFormatPURI *puri;
- EMFormatParserInfo info = { 0 };
-
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- if (message) {
- g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
-
- if (emf->message)
- g_object_unref (emf->message);
- emf->message = g_object_ref (message);
- }
-
- if (folder) {
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
- if (emf->folder)
- g_object_unref (emf->folder);
- emf->folder = g_object_ref (folder);
- }
-
- /* Before the actual parsing starts,
- * let child classes prepare themselves. */
- if (EM_FORMAT_GET_CLASS (emf)->preparse)
- EM_FORMAT_GET_CLASS (emf)->preparse (emf);
-
- part_id = g_string_new (".message");
-
- /* Create a special PURI with entire message */
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI),
- (CamelMimePart *) emf->message, part_id->str);
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (emf, puri);
-
- info.force_handler = TRUE;
- em_format_parse_part_as (emf, CAMEL_MIME_PART (emf->message), part_id, &info,
- "x-evolution/message", cancellable);
-
- g_string_free (part_id, TRUE);
-}
-
-void
-em_format_write (EMFormat *emf,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatClass *emf_class;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (CAMEL_IS_STREAM (stream));
-
- emf_class = EM_FORMAT_GET_CLASS (emf);
- if (emf_class->write)
- emf_class->write (emf, stream, info, cancellable);
-}
-
-static void
-emf_start_async_parser (GSimpleAsyncResult *result,
- GObject *object,
- GCancellable *cancellable)
-{
- em_format_parse (EM_FORMAT (object), NULL, NULL, cancellable);
-}
-
-void
-em_format_parse_async (EMFormat *emf,
- CamelMimeMessage *message,
- CamelFolder *folder,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- if (message) {
- g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
-
- if (emf->message)
- g_object_unref (emf->message);
-
- emf->message = g_object_ref (message);
-
- }
-
- if (folder) {
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
- if (emf->folder)
- g_object_unref (emf->folder);
-
- emf->folder = g_object_ref (folder);
-
- }
-
- simple = g_simple_async_result_new (
- G_OBJECT (emf), callback,
- user_data, em_format_parse_async);
-
- g_simple_async_result_set_check_cancellable (simple, cancellable);
-
- g_simple_async_result_run_in_thread (
- simple, emf_start_async_parser,
- G_PRIORITY_DEFAULT, cancellable);
-
- g_object_unref (simple);
-}
-
-void
-em_format_parse_part_as (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- const gchar *mime_type,
- GCancellable *cancellable)
-{
- const EMFormatHandler *handler;
- const CamelContentDisposition *disposition;
- EMFormatParserInfo ninfo = {
- .handler = 0,
- .validity_type = info ? info->validity_type : 0,
- .validity = info ? info->validity : 0,
- .force_handler = 0
- };
-
- /* Let everything that claims to be an attachment or inlined
- * part to be parsed as an attachment. The parser will decide
- * how to display it. */
- disposition = camel_mime_part_get_content_disposition (part);
- if (!info->force_handler && disposition &&
- (g_strcmp0 (disposition->disposition, "attachment") == 0)) {
- ninfo.is_attachment = TRUE;
- handler = em_format_find_handler (emf, "x-evolution/message/attachment");
- ninfo.handler = handler;
-
- if (handler && handler->parse_func)
- handler->parse_func (emf, part, part_id, &ninfo, cancellable);
-
- return;
- }
-
- handler = em_format_find_handler (emf, mime_type);
- if (handler && handler->parse_func) {
- ninfo.handler = handler;
- handler->parse_func (emf, part, part_id, &ninfo, cancellable);
- } else {
- handler = em_format_find_handler (emf, "x-evolution/message/attachment");
- ninfo.handler = handler;
-
- /* When this fails, something is probably very wrong...*/
- if (handler && handler->parse_func)
- handler->parse_func (emf, part, part_id, &ninfo, cancellable);
- }
-}
-
-void
-em_format_parse_part (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelContentType *ct;
- gchar *mime_type;
-
- ct = camel_mime_part_get_content_type (part);
- if (ct) {
- mime_type = camel_content_type_simple (ct);
- } else {
- mime_type = (gchar *) "text/plain";
- }
-
- em_format_parse_part_as (emf, part, part_id, info, mime_type, cancellable);
-
- if (ct)
- g_free (mime_type);
-}
-
-gboolean
-em_format_is_inline (EMFormat *emf,
- const gchar *part_id,
- CamelMimePart *part,
- const EMFormatHandler *handler)
-{
- EMFormatClass *class;
-
- g_return_val_if_fail (EM_IS_FORMAT (emf), FALSE);
- g_return_val_if_fail (part_id && *part_id, FALSE);
- g_return_val_if_fail (CAMEL_IS_MIME_PART (part), FALSE);
- g_return_val_if_fail (handler, FALSE);
-
- class = EM_FORMAT_GET_CLASS (emf);
- g_return_val_if_fail (class->is_inline != NULL, FALSE);
-
- return class->is_inline (emf, part_id, part, handler);
-
-}
-
-void
-em_format_format_error (EMFormat *emf,
- const gchar *format,
- ...)
-{
- EMFormatPURI *puri;
- CamelMimePart *part;
- const EMFormatHandler *handler;
- gchar *errmsg;
- gchar *uri;
- va_list ap;
-
- g_return_if_fail (EM_IS_FORMAT (emf));
- g_return_if_fail (format != NULL);
-
- va_start (ap, format);
- errmsg = g_strdup_vprintf (format, ap);
-
- part = camel_mime_part_new ();
- camel_mime_part_set_content (part, errmsg, strlen (errmsg), "text/plain");
- g_free (errmsg);
- va_end (ap);
-
- handler = em_format_find_handler (emf, "x-evolution/error");
-
- emf->priv->last_error++;
- uri = g_strdup_printf (".error.%d", emf->priv->last_error);
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, uri);
- puri->mime_type = g_strdup ("text/html");
- if (handler && handler->write_func)
- puri->write_func = handler->write_func;
- else
- puri->write_func = emf_write_error;
-
- em_format_add_puri (emf, puri);
-
- g_free (uri);
- g_object_unref (part);
-}
-
-/**
- * em_format_format_text:
- * @emf:
- * @stream: Where to write the converted text
- * @part: Part whose container is to be formatted
- * @cancellable: optional #GCancellable object, or %NULL
- *
- * Decode/output a part's content to @stream.
- **/
-void
-em_format_format_text (EMFormat *emf,
- CamelStream *stream,
- CamelDataWrapper *dw,
- GCancellable *cancellable)
-{
- CamelStream *filter_stream;
- CamelMimeFilter *filter;
- const gchar *charset = NULL;
- CamelMimeFilterWindows *windows = NULL;
- CamelStream *mem_stream = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- if (emf->priv->charset) {
- charset = emf->priv->charset;
- } else if (dw->mime_type
- && (charset = camel_content_type_param (dw->mime_type, "charset"))
- && g_ascii_strncasecmp(charset, "iso-8859-", 9) == 0) {
- CamelStream *null;
-
- /* Since a few Windows mailers like to claim they sent
- * out iso-8859-# encoded text when they really sent
- * out windows-cp125#, do some simple sanity checking
- * before we move on... */
-
- null = camel_stream_null_new ();
- filter_stream = camel_stream_filter_new (null);
- g_object_unref (null);
-
- windows = (CamelMimeFilterWindows *) camel_mime_filter_windows_new (charset);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filter_stream),
- CAMEL_MIME_FILTER (windows));
-
- camel_data_wrapper_decode_to_stream_sync (
- dw, (CamelStream *) filter_stream, cancellable, NULL);
- camel_stream_flush ((CamelStream *) filter_stream, cancellable, NULL);
- g_object_unref (filter_stream);
-
- charset = camel_mime_filter_windows_real_charset (windows);
- } else if (charset == NULL) {
- charset = emf->priv->default_charset;
- }
-
- mem_stream = (CamelStream *) camel_stream_mem_new ();
- filter_stream = camel_stream_filter_new (mem_stream);
-
- if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filter_stream),
- CAMEL_MIME_FILTER (filter));
- g_object_unref (filter);
- }
-
- camel_data_wrapper_decode_to_stream_sync (
- camel_medium_get_content ((CamelMedium *) dw),
- (CamelStream *) filter_stream, cancellable, NULL);
- camel_stream_flush ((CamelStream *) filter_stream, cancellable, NULL);
- g_object_unref (filter_stream);
-
- g_seekable_seek (G_SEEKABLE (mem_stream), 0, G_SEEK_SET, NULL, NULL);
-
- camel_stream_write_to_stream (
- mem_stream, (CamelStream *) stream, cancellable, NULL);
- camel_stream_flush ((CamelStream *) mem_stream, cancellable, NULL);
-
- if (windows)
- g_object_unref (windows);
-
- g_object_unref (mem_stream);
-}
-
-/**
- * em_format_describe_part:
- * @part:
- * @mimetype:
- *
- * Generate a simple textual description of a part, @mime_type represents
- * the content.
- *
- * Return value:
- **/
-gchar *
-em_format_describe_part (CamelMimePart *part,
- const gchar *mime_type)
-{
- GString *stext;
- const gchar *filename, *description;
- gchar *content_type, *desc;
-
- stext = g_string_new("");
- content_type = g_content_type_from_mime_type (mime_type);
- desc = g_content_type_get_description (
- content_type != NULL ? content_type : mime_type);
- g_free (content_type);
- g_string_append_printf (
- stext, _("%s attachment"), desc ? desc : mime_type);
- g_free (desc);
-
- filename = camel_mime_part_get_filename (part);
- description = camel_mime_part_get_description (part);
-
- if (!filename || !*filename) {
- CamelDataWrapper *content;
-
- content = camel_medium_get_content (CAMEL_MEDIUM (part));
-
- if (CAMEL_IS_MIME_MESSAGE (content))
- filename = camel_mime_message_get_subject (
- CAMEL_MIME_MESSAGE (content));
- }
-
- if (filename != NULL && *filename != '\0') {
- gchar *basename = g_path_get_basename (filename);
- g_string_append_printf (stext, " (%s)", basename);
- g_free (basename);
- }
-
- if (description != NULL && *description != '\0' &&
- g_strcmp0 (filename, description) != 0)
- g_string_append_printf (stext, ", \"%s\"", description);
-
- return g_string_free (stext, FALSE);
-}
-
-/**
- * em_format_is_attachment:
- * @emf:
- * @part: Part to check.
- *
- * Returns true if the part is an attachment.
- *
- * A part is not considered an attachment if it is a
- * multipart, or a text part with no filename. It is used
- * to determine if an attachment header should be displayed for
- * the part.
- *
- * Content-Disposition is not checked.
- *
- * Return value: TRUE/FALSE
- **/
-gint
-em_format_is_attachment (EMFormat *emf,
- CamelMimePart *part)
-{
- /*CamelContentType *ct = camel_mime_part_get_content_type(part);*/
- CamelDataWrapper *dw = camel_medium_get_content ((CamelMedium *) part);
-
- if (!dw)
- return 0;
-
- d(printf("checking is attachment %s/%s\n", dw->mime_type->type, dw->mime_type->subtype));
- return !(camel_content_type_is (dw->mime_type, "multipart", "*")
- || camel_content_type_is (
- dw->mime_type, "application", "x-pkcs7-mime")
- || camel_content_type_is (
- dw->mime_type, "application", "pkcs7-mime")
- || camel_content_type_is (
- dw->mime_type, "application", "x-inlinepgp-signed")
- || camel_content_type_is (
- dw->mime_type, "application", "x-inlinepgp-encrypted")
- || camel_content_type_is (
- dw->mime_type, "x-evolution", "evolution-rss-feed")
- || camel_content_type_is (dw->mime_type, "text", "calendar")
- || camel_content_type_is (dw->mime_type, "text", "x-calendar")
- || (camel_content_type_is (dw->mime_type, "text", "*")
- && camel_mime_part_get_filename (part) == NULL));
-}
-
-/**
- * em_format_snoop_type:
- * @part:
- *
- * Tries to snoop the mime type of a part.
- *
- * Return value: NULL if unknown (more likely application/octet-stream).
- **/
-const gchar *
-em_format_snoop_type (CamelMimePart *part)
-{
- /* cache is here only to be able still return const gchar * */
- static GHashTable *types_cache = NULL;
-
- const gchar *filename;
- gchar *name_type = NULL, *magic_type = NULL, *res, *tmp;
- CamelDataWrapper *dw;
-
- filename = camel_mime_part_get_filename (part);
- if (filename != NULL)
- name_type = e_util_guess_mime_type (filename, FALSE);
-
- dw = camel_medium_get_content ((CamelMedium *) part);
- if (!camel_data_wrapper_is_offline (dw)) {
- GByteArray *byte_array;
- CamelStream *stream;
-
- byte_array = g_byte_array_new ();
- stream = camel_stream_mem_new_with_byte_array (byte_array);
-
- if (camel_data_wrapper_decode_to_stream_sync (dw, stream, NULL, NULL) > 0) {
- gchar *content_type;
-
- content_type = g_content_type_guess (
- filename, byte_array->data,
- byte_array->len, NULL);
-
- if (content_type != NULL)
- magic_type = g_content_type_get_mime_type (content_type);
-
- g_free (content_type);
- }
-
- g_object_unref (stream);
- }
-
- /* If gvfs doesn't recognize the data by magic, but it
- * contains English words, it will call it text/plain. If the
- * filename-based check came up with something different, use
- * that instead and if it returns "application/octet-stream"
- * try to do better with the filename check.
- */
-
- if (magic_type) {
- if (name_type
- && (!strcmp(magic_type, "text/plain")
- || !strcmp(magic_type, "application/octet-stream")))
- res = name_type;
- else
- res = magic_type;
- } else
- res = name_type;
-
- if (res != name_type)
- g_free (name_type);
-
- if (res != magic_type)
- g_free (magic_type);
-
- if (!types_cache)
- types_cache = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) NULL);
-
- if (res) {
- tmp = g_hash_table_lookup (types_cache, res);
- if (tmp) {
- g_free (res);
- res = tmp;
- } else {
- g_hash_table_insert (types_cache, res, res);
- }
- }
-
- return res;
-
- /* We used to load parts to check their type, we don't anymore,
- * see bug #211778 for some discussion */
-}
-
-/**
- * Construct a URI for message.
- *
- * The URI can contain multiple query parameters. The list of parameters must be
- * NULL-terminated. Each query must contain name, GType of value and value.
- *
- * @param folder Folder wit the message
- * @param message_uid ID of message within the \p folder
- * @param first_param_name Name of first query parameter followed by GType of it's value and value.
- */
-gchar *
-em_format_build_mail_uri (CamelFolder *folder,
- const gchar *message_uid,
- const gchar *first_param_name,
- ...)
-{
- CamelStore *store;
- gchar *uri, *tmp;
- va_list ap;
- const gchar *name;
- const gchar *service_uid, *folder_name;
- gchar separator;
-
- g_return_val_if_fail (message_uid && *message_uid, NULL);
-
- if (!folder) {
- folder_name = "generic";
- service_uid = "generic";
- } else {
- tmp = (gchar *) camel_folder_get_full_name (folder);
- folder_name = (const gchar *) soup_uri_encode (tmp, NULL);
- store = camel_folder_get_parent_store (folder);
- if (store)
- service_uid = camel_service_get_uid (CAMEL_SERVICE (store));
- else
- service_uid = "generic";
- }
-
- tmp = g_strdup_printf ("mail://%s/%s/%s",
- service_uid,
- folder_name,
- message_uid);
-
- if (folder) {
- g_free ((gchar *) folder_name);
- }
-
- va_start (ap, first_param_name);
- name = first_param_name;
- separator = '?';
- while (name) {
- gchar *tmp2;
- gint type = va_arg (ap, gint);
- switch (type) {
- case G_TYPE_INT:
- case G_TYPE_BOOLEAN: {
- gint val = va_arg (ap, gint);
- tmp2 = g_strdup_printf ("%s%c%s=%d", tmp,
- separator, name, val);
- break;
- }
- case G_TYPE_FLOAT:
- case G_TYPE_DOUBLE: {
- gdouble val = va_arg (ap, double);
- tmp2 = g_strdup_printf ("%s%c%s=%f", tmp,
- separator, name, val);
- break;
- }
- case G_TYPE_STRING: {
- gchar *val = va_arg (ap, gchar *);
- gchar *escaped = soup_uri_encode (val, NULL);
- tmp2 = g_strdup_printf ("%s%c%s=%s", tmp,
- separator, name, escaped);
- g_free (escaped);
- break;
- }
- default:
- g_warning ("Invalid param type %s", g_type_name (type));
- return NULL;
- }
-
- g_free (tmp);
- tmp = tmp2;
-
- if (separator == '?')
- separator = '&';
-
- name = va_arg (ap, gchar *);
- }
- va_end (ap);
-
- uri = tmp;
- if (uri == NULL)
- return NULL;
-
- /* For some reason, webkit won't accept URL with username, but
- * without password (mail://store@host/folder/mail), so we
- * will replace the '@' symbol by '/' to get URL like
- * mail://store/host/folder/mail which is OK
- */
- while ((tmp = strchr (uri, '@')) != NULL) {
- tmp[0] = '/';
- }
-
- return uri;
-}
-
-void
-em_format_redraw (EMFormat *emf)
-{
- g_return_if_fail (EM_IS_FORMAT (emf));
-
- g_signal_emit (emf, signals[REDRAW_REQUESTED], 0);
-}
-
-/**************************************************************************/
-EMFormatPURI *
-em_format_puri_new (EMFormat *emf,
- gsize puri_size,
- CamelMimePart *part,
- const gchar *uri)
-{
- EMFormatPURI *puri;
-
- g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
- g_return_val_if_fail (puri_size >= sizeof (EMFormatPURI), NULL);
-
- puri = (EMFormatPURI *) g_malloc0 (puri_size);
- puri->emf = emf;
-
- if (part)
- puri->part = g_object_ref (part);
-
- if (uri)
- puri->uri = g_strdup (uri);
-
- return puri;
-}
-
-void
-em_format_puri_free (EMFormatPURI *puri)
-{
- g_return_if_fail (puri);
-
- if (puri->part)
- g_object_unref (puri->part);
-
- if (puri->uri)
- g_free (puri->uri);
-
- if (puri->cid)
- g_free (puri->cid);
-
- if (puri->mime_type)
- g_free (puri->mime_type);
-
- if (puri->validity)
- camel_cipher_validity_free (puri->validity);
-
- if (puri->validity_parent)
- camel_cipher_validity_free (puri->validity_parent);
-
- if (puri->free)
- puri->free (puri);
-
- g_free (puri);
-}
-
-void
-em_format_puri_write (EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- g_return_if_fail (puri);
- g_return_if_fail (CAMEL_IS_STREAM (stream));
-
- if (info->mode == EM_FORMAT_WRITE_MODE_SOURCE) {
- const EMFormatHandler *handler;
- handler = em_format_find_handler (puri->emf, "x-evolution/message/source");
- handler->write_func (puri->emf, puri, stream, info, cancellable);
- return;
- }
-
- if (puri->write_func) {
- puri->write_func (puri->emf, puri, stream, info, cancellable);
- } else {
- const EMFormatHandler *handler;
- const gchar *mime_type;
-
- if (puri->mime_type) {
- mime_type = puri->mime_type;
- } else {
- mime_type = (gchar *) "plain/text";
- }
-
- handler = em_format_find_handler (puri->emf, mime_type);
- if (handler && handler->write_func) {
- handler->write_func (puri->emf,
- puri, stream, info, cancellable);
- }
- }
-}
-
-EMFormatHeader *
-em_format_header_new (const gchar *name,
- const gchar *value)
-{
- EMFormatHeader *header;
-
- g_return_val_if_fail (name && *name, NULL);
-
- header = g_new0 (EMFormatHeader, 1);
- header->name = g_strdup (name);
- if (value && *value)
- header->value = g_strdup (value);
-
- return header;
-}
-
-void
-em_format_header_free (EMFormatHeader *header)
-{
- g_return_if_fail (header != NULL);
-
- if (header->name) {
- g_free (header->name);
- header->name = NULL;
- }
-
- if (header->value) {
- g_free (header->value);
- header->value = NULL;
- }
-
- g_free (header);
-}
diff --git a/em-format/em-format.h b/em-format/em-format.h
deleted file mode 100644
index 5b97cb799c..0000000000
--- a/em-format/em-format.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef EM_FORMAT_H
-#define EM_FORMAT_H
-
-#include <camel/camel.h>
-#include <gtk/gtk.h>
-#include <webkit/webkitdom.h>
-
-/* Standard GObject macros */
-#define EM_TYPE_FORMAT \
- (em_format_get_type ())
-#define EM_FORMAT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_FORMAT, EMFormat))
-#define EM_FORMAT_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_FORMAT, EMFormatClass))
-#define EM_IS_FORMAT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_FORMAT))
-#define EM_IS_FORMAT_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_FORMAT))
-#define EM_FORMAT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_FORMAT, EMFormatClass))
-
-G_BEGIN_DECLS
-
-#define EM_FORMAT_HEADER_BOLD (1<<0)
-#define EM_FORMAT_HEADER_LAST (1<<4) /* reserve 4 slots */
-
-#define EM_FORMAT_VALIDITY_FOUND_PGP (1<<0)
-#define EM_FORMAT_VALIDITY_FOUND_SMIME (1<<1)
-#define EM_FORMAT_VALIDITY_FOUND_SIGNED (1<<2)
-#define EM_FORMAT_VALIDITY_FOUND_ENCRYPTED (1<<3)
-
-typedef struct _EMFormat EMFormat;
-typedef struct _EMFormatClass EMFormatClass;
-typedef struct _EMFormatPrivate EMFormatPrivate;
-
-typedef struct _EMFormatPURI EMFormatPURI;
-typedef struct _EMFormatHeader EMFormatHeader;
-typedef struct _EMFormatHandler EMFormatHandler;
-typedef struct _EMFormatParserInfo EMFormatParserInfo;
-typedef struct _EMFormatWriterInfo EMFormatWriterInfo;
-
-typedef void (*EMFormatParseFunc) (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable);
-typedef void (*EMFormatWriteFunc) (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable);
-typedef GtkWidget * (*EMFormatWidgetFunc) (EMFormat *emf,
- EMFormatPURI *puri,
- GCancellable *cancellable);
-typedef void (*EMailDisplayBindFunc) (WebKitDOMElement *root,
- EMFormatPURI *puri);
-
-typedef enum {
- EM_FORMAT_HANDLER_INLINE = 1 << 0,
- EM_FORMAT_HANDLER_INLINE_DISPOSITION = 1 << 1,
- EM_FORMAT_HANDLER_COMPOUND_TYPE = 1 << 2
-} EMFormatHandlerFlags;
-
-typedef enum {
- EM_FORMAT_WRITE_MODE_NORMAL= 1 << 0,
- EM_FORMAT_WRITE_MODE_ALL_HEADERS = 1 << 1,
- EM_FORMAT_WRITE_MODE_SOURCE = 1 << 2,
- EM_FORMAT_WRITE_MODE_PRINTING = 1 << 3,
- EM_FORMAT_WRITE_MODE_RAW = 1 << 4
-} EMFormatWriteMode;
-
-struct _EMFormatHandler {
- gchar *mime_type;
- EMFormatParseFunc parse_func;
- EMFormatWriteFunc write_func;
- EMFormatHandlerFlags flags;
-
- EMFormatHandler *old;
-};
-
-/**
- * Use this struct to pass additional information between
- * EMFormatParseFunc's.
- * Much cleaner then setting public property of EMFormat.
- */
-struct _EMFormatParserInfo {
- const EMFormatHandler *handler;
-
- /* EM_FORMAT_VALIDITY_* flags */
- guint32 validity_type;
- CamelCipherValidity *validity;
-
- gint is_attachment : 1;
- gint force_handler: 1;
-};
-
-struct _EMFormatWriterInfo {
- EMFormatWriteMode mode;
- gboolean headers_collapsable;
- gboolean headers_collapsed;
-};
-
-struct _EMFormatHeader {
- guint32 flags; /* E_FORMAT_HEADER_ * */
- gchar *name;
- gchar *value;
-};
-
-#define EM_FORMAT_HEADER_BOLD (1<<0)
-#define EM_FORMAT_HEADER_LAST (1<<4) /* reserve 4 slots */
-
-struct _EMFormatPURI {
- CamelMimePart *part;
-
- EMFormat *emf;
- EMFormatWriteFunc write_func;
- EMFormatWidgetFunc widget_func;
-
- /**
- * Called by #EMailDisplay whenever document/frame is reloaded.
- * Modules and plugins can create bindings to events of DOM
- * objects they created.
- */
- EMailDisplayBindFunc bind_func;
-
- gchar *uri;
- gchar *cid;
- gchar *mime_type;
-
- /* EM_FORMAT_VALIDITY_* flags */
- guint32 validity_type;
- CamelCipherValidity *validity;
- CamelCipherValidity *validity_parent;
-
- gboolean is_attachment;
-
- void (*free)(EMFormatPURI *puri); /* optional callback for freeing user-fields */
-};
-
-struct _EMFormat {
- GObject parent;
- EMFormatPrivate *priv;
-
- CamelMimeMessage *message;
- CamelFolder *folder;
- gchar *message_uid;
- gchar *uri_base;
-
- /* Defines order in which parts should be displayed */
- GList *mail_part_list;
- /* For quick search for parts by their URI/ID */
- GHashTable *mail_part_table;
-
- /* If empty, then all. */
- GQueue header_list;
-};
-
-struct _EMFormatClass {
- GObjectClass parent_class;
-
- GHashTable *type_handlers;
-
- gboolean (*is_inline) (EMFormat *emf,
- const gchar *part_id,
- CamelMimePart *part,
- const EMFormatHandler *handler);
-
- /* Write the entire message to stream */
- void (*write) (EMFormat *emf,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable);
-
- void (*preparse) (EMFormat *emf);
-
- /* signals */
- void (*redraw_requested) (EMFormat *emf);
-
-};
-
-GType em_format_get_type (void);
-EMFormat * em_format_new (void);
-void em_format_set_charset (EMFormat *emf,
- const gchar *charset);
-const gchar * em_format_get_charset (EMFormat *emf);
-const gchar * em_format_get_default_charset (EMFormat *emf);
-void em_format_set_default_charset (EMFormat *emf,
- const gchar *charset);
-gboolean em_format_get_composer (EMFormat *emf);
-void em_format_set_composer (EMFormat *emf,
- gboolean composer);
-CamelSession * em_format_get_session (EMFormat *emf);
-void em_format_set_base_url (EMFormat *emf,
- CamelURL *url);
-void em_format_set_base_url_string (EMFormat *emf,
- const gchar *url_string);
-CamelURL * em_format_get_base_url (EMFormat *emf);
-void em_format_clear_headers (EMFormat *emf);
-void em_format_default_headers (EMFormat *emf);
-void em_format_add_header (EMFormat *emf,
- const gchar *name,
- const gchar *value,
- guint32 flags);
-void em_format_add_header_struct (EMFormat *emf,
- EMFormatHeader *header);
-void em_format_remove_header (EMFormat *emf,
- const gchar *name,
- const gchar *value);
-void em_format_remove_header_struct (EMFormat *emf,
- const EMFormatHeader *header);
-void em_format_add_puri (EMFormat *emf,
- EMFormatPURI *puri);
-EMFormatPURI * em_format_find_puri (EMFormat *emf,
- const gchar *id);
-void em_format_class_add_handler (EMFormatClass *emfc,
- EMFormatHandler *handler);
-void em_format_class_remove_handler (EMFormatClass *emfc,
- EMFormatHandler *handler);
-const EMFormatHandler *
- em_format_find_handler (EMFormat *emf,
- const gchar *mime_type);
-const EMFormatHandler *
- em_format_fallback_handler (EMFormat *emf,
- const gchar *mime_type);
-void em_format_parse (EMFormat *emf,
- CamelMimeMessage *message,
- CamelFolder *folder,
- GCancellable *cancellable);
-void em_format_write (EMFormat *emf,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable);
-void em_format_parse_async (EMFormat *emf,
- CamelMimeMessage *message,
- CamelFolder *folder,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-void em_format_parse_part (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable);
-void em_format_parse_part_as (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- const gchar *mime_type,
- GCancellable *cancellable);
-gboolean em_format_is_inline (EMFormat *emf,
- const gchar *part_id,
- CamelMimePart *part,
- const EMFormatHandler *handler);
-gchar * em_format_get_error_id (EMFormat *emf);
-void em_format_format_error (EMFormat *emf,
- const gchar *format,
- ...) G_GNUC_PRINTF (2, 3);
-void em_format_format_text (EMFormat *emf,
- CamelStream *stream,
- CamelDataWrapper *dw,
- GCancellable *cancellable);
-gchar * em_format_describe_part (CamelMimePart *part,
- const gchar *mime_type);
-gint em_format_is_attachment (EMFormat *emf,
- CamelMimePart *part);
-const gchar * em_format_snoop_type (CamelMimePart *part);
-gchar * em_format_build_mail_uri (CamelFolder *folder,
- const gchar *message_uid,
- const gchar *part_uid,
- ...) G_GNUC_NULL_TERMINATED;
-
-/* EMFormatParseFunc that does nothing. Use it to disable
- * parsing of a specific mime type parts */
-void em_format_empty_parser (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable);
-
-/* EMFormatWriteFunc that does nothing. Use it to disable
- * writing of a specific mime type parts */
-void em_format_empty_writer (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable);
-
-void em_format_redraw (EMFormat *emf);
-
-EMFormatPURI * em_format_puri_new (EMFormat *emf,
- gsize puri_size,
- CamelMimePart *part,
- const gchar *uri);
-void em_format_puri_free (EMFormatPURI *puri);
-void em_format_puri_write (EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable);
-EMFormatHeader *
- em_format_header_new (const gchar *name,
- const gchar *value);
-void em_format_header_free (EMFormatHeader *header);
-
-#endif /* EM_FORMAT_H */
-
diff --git a/mail/Makefile.am b/mail/Makefile.am
index da2c0eb692..7fa3dbab9c 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -44,7 +44,6 @@ mailinclude_HEADERS = \
e-mail-account-manager.h \
e-mail-account-store.h \
e-mail-account-tree-view.h \
- e-mail-attachment-bar.h \
e-mail-autoconfig.h \
e-mail-backend.h \
e-mail-browser.h \
@@ -101,10 +100,6 @@ mailinclude_HEADERS = \
em-folder-tree-model.h \
em-folder-tree.h \
em-folder-utils.h \
- em-format-hook.h \
- em-format-html-display.h \
- em-format-html-print.h \
- em-format-html.h \
em-search-context.h \
em-subscription-editor.h \
em-utils.h \
@@ -128,7 +123,6 @@ libevolution_mail_la_SOURCES = \
e-mail-account-manager.c \
e-mail-account-store.c \
e-mail-account-tree-view.c \
- e-mail-attachment-bar.c \
e-mail-autoconfig.c \
e-mail-backend.c \
e-mail-browser.c \
@@ -185,10 +179,6 @@ libevolution_mail_la_SOURCES = \
em-folder-tree-model.c \
em-folder-tree.c \
em-folder-utils.c \
- em-format-hook.c \
- em-format-html-display.c \
- em-format-html-print.c \
- em-format-html.c \
em-search-context.c \
em-subscription-editor.c \
em-utils.c \
diff --git a/mail/e-http-request.c b/mail/e-http-request.c
index a9415b248a..95a97e62f6 100644
--- a/mail/e-http-request.c
+++ b/mail/e-http-request.c
@@ -26,10 +26,13 @@
#include <webkit/webkit.h>
#include <e-util/e-util.h>
+#include <mail/em-utils.h>
+#include <libemail-engine/e-mail-enumtypes.h>
#include <string.h>
-#include "em-format-html.h"
+#include <em-format/e-mail-formatter.h>
+#include <shell/e-shell.h>
#define d(x)
@@ -41,7 +44,7 @@ struct _EHTTPRequestPrivate {
gchar *content_type;
gint content_length;
- EMFormatHTML *efh;
+ EMailPartList *parts_list;
};
G_DEFINE_TYPE (EHTTPRequest, e_http_request, SOUP_TYPE_REQUEST)
@@ -208,9 +211,12 @@ handle_http_request (GSimpleAsyncResult *res,
EHTTPRequest *request = E_HTTP_REQUEST (object);
SoupURI *soup_uri;
gchar *evo_uri, *uri;
+ gchar *mail_uri;
GInputStream *stream;
gboolean force_load_images = FALSE;
+ EMailImageLoadingPolicy image_policy;
gchar *uri_md5;
+ EMailFormatter *formatter;
const gchar *user_cache_dir;
CamelDataCache *cache;
@@ -222,9 +228,15 @@ handle_http_request (GSimpleAsyncResult *res,
return;
}
+ formatter = e_mail_formatter_new ();
+
/* Remove the __evo-mail query */
soup_uri = soup_request_get_uri (SOUP_REQUEST (request));
query = soup_form_decode (soup_uri->query);
+ mail_uri = g_hash_table_lookup (query, "__evo-mail");
+ if (mail_uri)
+ mail_uri = g_strdup (mail_uri);
+
g_hash_table_remove (query, "__evo-mail");
/* Remove __evo-load-images if present (and in such case set
@@ -306,7 +318,36 @@ handle_http_request (GSimpleAsyncResult *res,
/* Item not found in cache, but image loading policy allows us to fetch
* it from the interwebs */
- if (force_load_images || em_format_html_can_load_images (request->priv->efh)) {
+ image_policy = e_mail_formatter_get_image_loading_policy (formatter);
+ if (!force_load_images && mail_uri &&
+ (image_policy == E_MAIL_IMAGE_LOADING_POLICY_SOMETIMES)) {
+ SoupSession *session;
+ GHashTable *parts;
+ gchar *decoded_uri;
+ EMailPartList *part_list;
+
+ session = webkit_get_default_session ();
+ parts = g_object_get_data (G_OBJECT (session), "mails");
+ decoded_uri = soup_uri_decode (mail_uri);
+
+ part_list = g_hash_table_lookup (parts, decoded_uri);
+ if (part_list) {
+ EShell *shell;
+ ESourceRegistry *registry;
+ CamelInternetAddress *addr;
+
+ shell = e_shell_get_default ();
+ registry = e_shell_get_registry (shell);
+ addr = camel_mime_message_get_from (part_list->message);
+ force_load_images = em_utils_in_addressbook (
+ registry, addr, FALSE);
+ }
+
+ g_free (decoded_uri);
+ }
+
+ if ((image_policy == E_MAIL_IMAGE_LOADING_POLICY_ALWAYS) ||
+ force_load_images) {
SoupRequester *requester;
SoupRequest *http_request;
@@ -393,6 +434,8 @@ handle_http_request (GSimpleAsyncResult *res,
cleanup:
g_free (uri);
g_free (uri_md5);
+ if (mail_uri)
+ g_free (mail_uri);
}
static void
@@ -405,9 +448,9 @@ http_request_finalize (GObject *object)
request->priv->content_type = NULL;
}
- if (request->priv->efh) {
- g_object_unref (request->priv->efh);
- request->priv->efh = NULL;
+ if (request->priv->parts_list) {
+ g_object_unref (request->priv->parts_list);
+ request->priv->parts_list = NULL;
}
G_OBJECT_CLASS (e_http_request_parent_class)->finalize (object);
@@ -434,7 +477,7 @@ http_request_send_async (SoupRequest *request,
SoupURI *uri;
const gchar *enc;
SoupSession *session;
- GHashTable *formatters, *query;
+ GHashTable *mails, *query;
ehr = E_HTTP_REQUEST (request);
uri = soup_request_get_uri (request);
@@ -452,16 +495,16 @@ http_request_send_async (SoupRequest *request,
mail_uri = soup_uri_decode (enc);
session = webkit_get_default_session ();
- formatters = g_object_get_data (G_OBJECT (session), "formatters");
- g_return_if_fail (formatters != NULL);
+ mails = g_object_get_data (G_OBJECT (session), "mails");
+ g_return_if_fail (mails != NULL);
- ehr->priv->efh = g_hash_table_lookup (formatters, mail_uri);
+ ehr->priv->parts_list = g_hash_table_lookup (mails, mail_uri);
g_free (mail_uri);
- g_return_if_fail (ehr->priv->efh);
+ g_return_if_fail (ehr->priv->parts_list);
/* Make sure the formatter lives until we are finished here */
- g_object_ref (ehr->priv->efh);
+ g_object_ref (ehr->priv->parts_list);
simple = g_simple_async_result_new (
G_OBJECT (request), callback,
diff --git a/mail/e-mail-attachment-bar.h b/mail/e-mail-attachment-bar.h
deleted file mode 100644
index b83d9733e0..0000000000
--- a/mail/e-mail-attachment-bar.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * e-mail-attachment-bar.h
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef E_MAIL_ATTACHMENT_BAR_H
-#define E_MAIL_ATTACHMENT_BAR_H
-
-#include <gtk/gtk.h>
-#include <misc/e-attachment-view.h>
-
-/* Standard GObject macros */
-#define E_TYPE_MAIL_ATTACHMENT_BAR \
- (e_mail_attachment_bar_get_type ())
-#define E_MAIL_ATTACHMENT_BAR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_MAIL_ATTACHMENT_BAR, EMailAttachmentBar))
-#define E_MAIL_ATTACHMENT_BAR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_MAIL_ATTACHMENT_BAR, EMailAttachmentBarClass))
-#define E_IS_MAIL_ATTACHMENT_BAR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_MAIL_ATTACHMENT_BAR))
-#define E_IS_MAIL_ATTACHMENT_BAR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_MAIL_ATTACHMENT_BAR))
-#define E_MAIL_ATTACHMENT_BAR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_MAIL_ATTACHMENT_BAR, EMailAttachmentBarClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EMailAttachmentBar EMailAttachmentBar;
-typedef struct _EMailAttachmentBarClass EMailAttachmentBarClass;
-typedef struct _EMailAttachmentBarPrivate EMailAttachmentBarPrivate;
-
-struct _EMailAttachmentBar {
- GtkVBox parent;
- EMailAttachmentBarPrivate *priv;
-};
-
-struct _EMailAttachmentBarClass {
- GtkVBoxClass parent_class;
-};
-
-GType e_mail_attachment_bar_get_type (void);
-GtkWidget * e_mail_attachment_bar_new (EAttachmentStore *store);
-gint e_mail_attachment_bar_get_active_view
- (EMailAttachmentBar *bar);
-void e_mail_attachment_bar_set_active_view
- (EMailAttachmentBar *bar,
- gint active_view);
-gboolean e_mail_attachment_bar_get_expanded
- (EMailAttachmentBar *bar);
-void e_mail_attachment_bar_set_expanded
- (EMailAttachmentBar *bar,
- gboolean expanded);
-EAttachmentStore *
- e_mail_attachment_bar_get_store (EMailAttachmentBar *bar);
-
-G_END_DECLS
-
-#endif /* E_MAIL_ATTACHMENT_BAR_H */
diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c
index 806980d602..eda9d6cbc3 100644
--- a/mail/e-mail-browser.c
+++ b/mail/e-mail-browser.c
@@ -39,7 +39,6 @@
#include "mail/e-mail-reader.h"
#include "mail/e-mail-reader-utils.h"
#include "mail/em-folder-tree-model.h"
-#include "mail/em-format-html-display.h"
#include "mail/message-list.h"
#define E_MAIL_BROWSER_GET_PRIVATE(obj) \
@@ -56,7 +55,7 @@ struct _EMailBrowserPrivate {
GtkUIManager *ui_manager;
EFocusTracker *focus_tracker;
- EMFormatWriteMode mode;
+ EMailFormatterMode mode;
GtkWidget *main_menu;
GtkWidget *main_toolbar;
@@ -915,7 +914,7 @@ e_mail_browser_class_init (EMailBrowserClass *class)
NULL,
0,
G_MAXINT,
- EM_FORMAT_WRITE_MODE_NORMAL,
+ E_MAIL_FORMATTER_MODE_NORMAL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
@@ -951,7 +950,7 @@ GtkWidget *
e_mail_browser_new (EMailBackend *backend,
CamelFolder *folder,
const gchar *msg_uid,
- EMFormatWriteMode mode)
+ EMailFormatterMode mode)
{
GtkWidget *widget;
diff --git a/mail/e-mail-browser.h b/mail/e-mail-browser.h
index 88f8174a9d..849daebce4 100644
--- a/mail/e-mail-browser.h
+++ b/mail/e-mail-browser.h
@@ -64,7 +64,7 @@ GType e_mail_browser_get_type (void);
GtkWidget * e_mail_browser_new (EMailBackend *backend,
CamelFolder *folder,
const gchar *message_uid,
- EMFormatWriteMode mode);
+ EMailFormatterMode mode);
void e_mail_browser_close (EMailBrowser *browser);
gboolean e_mail_browser_get_show_deleted (EMailBrowser *browser);
void e_mail_browser_set_show_deleted (EMailBrowser *browser,
diff --git a/mail/e-mail-config-lookup-page.c b/mail/e-mail-config-lookup-page.c
index 0154a053b1..d200c3cba0 100644
--- a/mail/e-mail-config-lookup-page.c
+++ b/mail/e-mail-config-lookup-page.c
@@ -29,7 +29,7 @@ G_DEFINE_TYPE_WITH_CODE (
EMailConfigLookupPage,
e_mail_config_lookup_page,
GTK_TYPE_BOX,
- G_IMPLEMENT_INTERFACE(
+ G_IMPLEMENT_INTERFACE (
E_TYPE_MAIL_CONFIG_PAGE,
e_mail_config_lookup_page_interface_init))
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index ca807a6899..4f72e843f6 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -28,6 +28,12 @@
#include <glib/gi18n.h>
#include <gdk/gdk.h>
+#include <em-format/e-mail-part-utils.h>
+#include <em-format/e-mail-formatter-extension.h>
+#include <em-format/e-mail-extension-registry.h>
+#include <em-format/e-mail-part-attachment.h>
+#include <em-format/e-mail-formatter-print.h>
+
#include "e-util/e-marshal.h"
#include "e-util/e-util.h"
#include "e-util/e-plugin-ui.h"
@@ -37,8 +43,7 @@
#include "mail/em-utils.h"
#include "mail/e-mail-request.h"
#include "mail/e-http-request.h"
-#include "mail/em-format-html-display.h"
-#include "mail/e-mail-attachment-bar.h"
+#include "widgets/misc/e-attachment-bar.h"
#include "widgets/misc/e-attachment-button.h"
#include <camel/camel.h>
@@ -54,9 +59,10 @@ G_DEFINE_TYPE (EMailDisplay, e_mail_display, E_TYPE_WEB_VIEW)
((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate))
struct _EMailDisplayPrivate {
- EMFormatHTML *formatter;
+ EMailPartList *part_list;
+ EMailFormatterMode mode;
+ EMailFormatter *formatter;
- EMFormatWriteMode mode;
gboolean headers_collapsable;
gboolean headers_collapsed;
@@ -66,12 +72,14 @@ struct _EMailDisplayPrivate {
gint force_image_load: 1;
GSettings *settings;
+
+ GHashTable *widgets;
};
enum {
PROP_0,
- PROP_FORMATTER,
PROP_MODE,
+ PROP_PART_LIST,
PROP_HEADERS_COLLAPSABLE,
PROP_HEADERS_COLLAPSED,
};
@@ -197,45 +205,15 @@ formatter_image_loading_policy_changed_cb (GObject *object,
static void
mail_display_update_formatter_colors (EMailDisplay *display)
{
- EMFormatHTMLColorType type;
- EMFormatHTML *formatter;
- GdkColor *color;
- GtkStateType state;
GtkStyle *style;
-
- state = gtk_widget_get_state (GTK_WIDGET (display));
- formatter = display->priv->formatter;
+ GtkStateType state;
if (!display->priv->formatter)
return;
style = gtk_widget_get_style (GTK_WIDGET (display));
- if (style == NULL)
- return;
-
- g_object_freeze_notify (G_OBJECT (formatter));
-
- color = &style->bg[state];
- type = EM_FORMAT_HTML_COLOR_BODY;
- em_format_html_set_color (formatter, type, color);
-
- color = &style->base[GTK_STATE_NORMAL];
- type = EM_FORMAT_HTML_COLOR_CONTENT;
- em_format_html_set_color (formatter, type, color);
-
- color = &style->dark[state];
- type = EM_FORMAT_HTML_COLOR_FRAME;
- em_format_html_set_color (formatter, type, color);
-
- color = &style->fg[state];
- type = EM_FORMAT_HTML_COLOR_HEADER;
- em_format_html_set_color (formatter, type, color);
-
- color = &style->text[state];
- type = EM_FORMAT_HTML_COLOR_TEXT;
- em_format_html_set_color (formatter, type, color);
-
- g_object_thaw_notify (G_OBJECT (formatter));
+ state = gtk_widget_get_state (GTK_WIDGET (display));
+ e_mail_formatter_set_style (display->priv->formatter, style, state);
}
static void
@@ -245,10 +223,10 @@ mail_display_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_FORMATTER:
- e_mail_display_set_formatter (
+ case PROP_PART_LIST:
+ e_mail_display_set_parts_list (
E_MAIL_DISPLAY (object),
- g_value_get_object (value));
+ g_value_get_pointer (value));
return;
case PROP_MODE:
e_mail_display_set_mode (
@@ -277,9 +255,9 @@ mail_display_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_FORMATTER:
- g_value_set_object (
- value, e_mail_display_get_formatter (
+ case PROP_PART_LIST:
+ g_value_set_pointer (
+ value, e_mail_display_get_parts_list (
E_MAIL_DISPLAY (object)));
return;
case PROP_MODE:
@@ -309,9 +287,9 @@ mail_display_dispose (GObject *object)
priv = E_MAIL_DISPLAY_GET_PRIVATE (object);
- if (priv->formatter) {
- g_object_unref (priv->formatter);
- priv->formatter = NULL;
+ if (priv->part_list) {
+ g_object_unref (priv->part_list);
+ priv->part_list = NULL;
}
if (priv->settings) {
@@ -319,6 +297,11 @@ mail_display_dispose (GObject *object)
priv->settings = NULL;
}
+ if (priv->widgets) {
+ g_hash_table_destroy (priv->widgets);
+ priv->widgets = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -353,18 +336,14 @@ mail_display_process_mailto (EWebView *web_view,
g_return_val_if_fail (mailto_uri != NULL, FALSE);
if (g_ascii_strncasecmp (mailto_uri, "mailto:", 7) == 0) {
- EMFormat *format;
- CamelFolder *folder = NULL;
EShell *shell;
+ EMailPartList *part_list;
- format = (EMFormat *) E_MAIL_DISPLAY (web_view)->priv->formatter;
-
- if (format != NULL && format->folder != NULL)
- folder = format->folder;
+ part_list = E_MAIL_DISPLAY (web_view)->priv->part_list;
shell = e_shell_get_default ();
em_utils_compose_new_message_with_mailto (
- shell, mailto_uri, folder);
+ shell, mailto_uri, part_list->folder);
return TRUE;
}
@@ -380,7 +359,6 @@ mail_display_link_clicked (WebKitWebView *web_view,
WebKitWebPolicyDecision *policy_decision,
gpointer user_data)
{
- EMailDisplay *display;
const gchar *uri = webkit_network_request_get_uri (request);
if (g_str_has_prefix (uri, "file://")) {
@@ -397,10 +375,6 @@ mail_display_link_clicked (WebKitWebView *web_view,
g_free (filename);
}
- display = E_MAIL_DISPLAY (web_view);
- if (display->priv->formatter == NULL)
- return FALSE;
-
if (mail_display_process_mailto (E_WEB_VIEW (web_view), uri, NULL)) {
/* do nothing, function handled the "mailto:" uri already */
webkit_web_policy_decision_ignore (policy_decision);
@@ -457,10 +431,11 @@ mail_display_resource_requested (WebKitWebView *web_view,
gpointer user_data)
{
EMailDisplay *display = E_MAIL_DISPLAY (web_view);
- EMFormat *formatter = EM_FORMAT (display->priv->formatter);
+ EMailPartList *part_list;
const gchar *uri = webkit_network_request_get_uri (request);
- if (!formatter) {
+ part_list = display->priv->part_list;
+ if (!part_list) {
return;
}
@@ -468,10 +443,10 @@ mail_display_resource_requested (WebKitWebView *web_view,
if (g_str_has_prefix (uri, "cid:")) {
/* Always write raw content of CID object */
- gchar *new_uri = em_format_build_mail_uri (formatter->folder,
- formatter->message_uid,
+ gchar *new_uri = e_mail_part_build_uri (
+ part_list->folder, part_list->message_uid,
"part_id", G_TYPE_STRING, uri,
- "mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW, NULL);
+ "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW, NULL);
webkit_network_request_set_uri (request, new_uri);
@@ -499,6 +474,7 @@ mail_display_resource_requested (WebKitWebView *web_view,
GHashTable *query;
gchar *uri_md5;
CamelStream *stream;
+ EMailImageLoadingPolicy image_policy;
/* Open Evolution's cache */
uri_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
@@ -509,15 +485,17 @@ mail_display_resource_requested (WebKitWebView *web_view,
/* If the URI is not cached and we are not allowed to load it
* then redirect to invalid URI, so that webkit would display
* a native placeholder for it. */
+ image_policy = e_mail_formatter_get_image_loading_policy (
+ display->priv->formatter);
if (!stream && !display->priv->force_image_load &&
- !em_format_html_can_load_images (display->priv->formatter)) {
+ (image_policy == E_MAIL_IMAGE_LOADING_POLICY_NEVER)) {
webkit_network_request_set_uri (request, "about:blank");
return;
}
new_uri = g_strconcat ("evo-", uri, NULL);
- mail_uri = em_format_build_mail_uri (formatter->folder,
- formatter->message_uid, NULL, NULL);
+ mail_uri = e_mail_part_build_uri (part_list->folder,
+ part_list->message_uid, NULL, NULL);
soup_uri = soup_uri_new (new_uri);
if (soup_uri->query) {
@@ -557,6 +535,9 @@ find_element_by_id (WebKitDOMDocument *document,
WebKitDOMElement *element;
gulong i, length;
+ if (!WEBKIT_DOM_IS_DOCUMENT (document))
+ return NULL;
+
/* Try to look up the element in this DOM document */
element = webkit_dom_document_get_element_by_id (document, id);
if (element)
@@ -595,7 +576,6 @@ mail_display_plugin_widget_resize (GObject *object,
gint height;
widget = GTK_WIDGET (object);
- gtk_widget_get_preferred_height (widget, &height, NULL);
parent_element = g_object_get_data (object, "parent_element");
if (!parent_element || !WEBKIT_DOM_IS_ELEMENT (parent_element)) {
@@ -604,6 +584,14 @@ mail_display_plugin_widget_resize (GObject *object,
return;
}
+ /* For attachment bar, we need to ask for height it's parent,
+ * GtkBox, because EAttachmentBar itself lies about it's real height. */
+ if (E_IS_ATTACHMENT_BAR (widget)) {
+ widget = gtk_widget_get_parent (widget);
+ }
+
+ gtk_widget_get_preferred_height (widget, &height, NULL);
+
/* Int -> Str */
dim = g_strdup_printf ("%d", height);
@@ -618,6 +606,31 @@ static void
mail_display_plugin_widget_realize_cb (GtkWidget *widget,
gpointer user_data)
{
+ WebKitDOMHTMLElement *el;
+
+ if (GTK_IS_BOX (widget)) {
+ GList *children;
+
+ children = gtk_container_get_children (GTK_CONTAINER (widget));
+ if (children && children->data &&
+ E_IS_ATTACHMENT_BAR (children->data)) {
+ widget = children->data;
+ }
+
+ g_list_free (children);
+ }
+
+ /* First check if we are actually supposed to be visible */
+ el = g_object_get_data (G_OBJECT (widget), "parent_element");
+ if (!el || !WEBKIT_DOM_IS_HTML_ELEMENT (el)) {
+ g_warning ("UAAAAA");
+ } else {
+ if (webkit_dom_html_element_get_hidden (el)) {
+ gtk_widget_hide (widget);
+ return;
+ }
+ }
+
/* Initial resize of the <object> element when the widget
* is displayed for the first time. */
mail_display_plugin_widget_resize (G_OBJECT (widget), NULL, user_data);
@@ -647,166 +660,184 @@ plugin_widget_set_parent_element (GtkWidget *widget,
* and the GtkWidget to "widget" data of the DOM Element */
g_object_set_data (G_OBJECT (widget), "parent_element", element);
g_object_set_data (G_OBJECT (element), "widget", widget);
+
+ g_object_bind_property (
+ element, "hidden",
+ widget, "visible",
+ G_BINDING_SYNC_CREATE |
+ G_BINDING_INVERT_BOOLEAN);
}
static void
-attachment_button_expanded (GObject *object,
- GParamSpec *pspec,
- gpointer user_data)
+toggle_widget_visibility (EAttachmentButton *button,
+ EMailDisplay *display,
+ WebKitDOMElement *element)
{
- EAttachmentButton *button = E_ATTACHMENT_BUTTON (object);
- WebKitDOMElement *attachment = user_data;
- WebKitDOMCSSStyleDeclaration *css;
- gboolean expanded;
+ gchar *id;
+ GtkWidget *widget;
- d(printf("Attachment button %s (%p) expansion state toggled!\n",
- (gchar *) g_object_get_data (object, "uri"), object));
+ id = webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT (element));
+ if (!id || !*id) {
+ return;
+ }
- expanded = e_attachment_button_get_expanded (button) &&
- gtk_widget_get_visible (GTK_WIDGET (button));
+ if (!display->priv->widgets) {
+ g_free (id);
+ return;
+ }
- if (!WEBKIT_DOM_IS_ELEMENT (attachment)) {
- d(printf("%s: Parent element for button %s does not exist!\n",
- G_STRFUNC, (gchar *) g_object_get_data (object, "uri")));
+ widget = g_hash_table_lookup (display->priv->widgets, id);
+ g_free (id);
+ if (!widget) {
return;
}
- /* Show or hide the DIV which contains the attachment (iframe, image...) */
- css = webkit_dom_element_get_style (attachment);
- webkit_dom_css_style_declaration_set_property (
- css, "display", expanded ? "block" : "none", "", NULL);
-}
+ /* If the widget encapsulates EAttachmentBar then check, whether
+ * the attachment bar is not empty. We want to display it only
+ * when there's at least one attachment */
+ if (GTK_IS_BOX (widget)) {
+ GList *children;
-static void
-constraint_widget_visibility (GObject *object,
- GParamSpec *pspec,
- gpointer user_data)
-{
- GtkWidget *widget = GTK_WIDGET (object);
- EAttachmentButton *button = user_data;
+ children = gtk_container_get_children (GTK_CONTAINER (widget));
+ if (children && children->data && E_IS_ATTACHMENT_BAR (children->data)) {
+ EAttachmentStore *store;
- gboolean can_show = e_attachment_button_get_expanded (button);
- gboolean is_visible = gtk_widget_get_visible (widget);
+ store = e_attachment_bar_get_store (
+ E_ATTACHMENT_BAR (children->data));
- if (is_visible && !can_show)
- gtk_widget_hide (widget);
- else if (!is_visible && can_show)
- gtk_widget_show (widget);
+ g_list_free (children);
+
+ /* Don't allow to display such attachment bar,
+ * but always allow to hide it */
+ if (e_attachment_button_get_expanded (button) &&
+ (e_attachment_store_get_num_attachments (store) == 0)) {
+ return;
+ }
+ }
+ }
- /* Otherwise it's OK */
+ webkit_dom_html_element_set_hidden (
+ WEBKIT_DOM_HTML_ELEMENT (element),
+ !e_attachment_button_get_expanded (button));
+
+ if (e_attachment_button_get_expanded (button)) {
+ gtk_widget_show (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
}
+/**
+ * @button: An #EAttachmentButton
+ * @iframe: An iframe element containing document with an attachment
+ * represented by the @button
+ */
static void
-bind_iframe_content_visibility (EAttachmentButton *button,
- WebKitDOMElement *iframe)
+bind_iframe_content_visibility (WebKitDOMElement *iframe,
+ EMailDisplay *display,
+ EAttachmentButton *button)
{
WebKitDOMDocument *document;
WebKitDOMNodeList *nodes;
gulong i, length;
- if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (iframe))
+ if (!iframe || !WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (iframe))
return;
document = webkit_dom_html_iframe_element_get_content_document (
WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
+ if (!WEBKIT_DOM_IS_DOCUMENT (document))
+ return;
+
nodes = webkit_dom_document_get_elements_by_tag_name (document, "object");
length = webkit_dom_node_list_get_length (nodes);
- d(printf("Found %ld objects within iframe %s\n", length,
- webkit_dom_html_iframe_element_get_name (
- WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe))));
+ d ({
+ gchar *name = webkit_dom_html_iframe_element_get_name (
+ WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
+ printf("Found %ld objects within iframe %s\n", length, name);
+ g_free (name);
+ });
/* Iterate through all <object>s and bind visibility of their widget
* with expanded-state of related attachment button */
for (i = 0; i < length; i++) {
WebKitDOMNode *node = webkit_dom_node_list_item (nodes, i);
- GtkWidget *widget;
-
- widget = g_object_get_data (G_OBJECT (node), "widget");
- if (!widget)
- continue;
-
- d(printf("Binding visibility of widget %s (%p) with button %s (%p)\n",
- (gchar *) g_object_get_data (G_OBJECT (widget), "uri"), widget,
- (gchar *) g_object_get_data (G_OBJECT (button), "uri"), button));
-
- g_object_bind_property (
- button, "expanded",
- widget, "visible",
- G_BINDING_SYNC_CREATE);
- /* Ensure that someone won't attempt to _show() the widget when
- * it is supposed to be hidden and vice versa. */
- g_signal_connect (widget, "notify::visible",
- G_CALLBACK (constraint_widget_visibility), button);
+ /* Initial sync */
+ toggle_widget_visibility (button, display, WEBKIT_DOM_ELEMENT (node));
}
}
static void
-bind_attachment_iframe_visibility (GObject *object,
- GParamSpec *pspec,
- gpointer user_data)
+attachment_button_expanded (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
- WebKitWebFrame *webframe;
- const gchar *frame_name;
- gchar *button_uri;
+ EAttachmentButton *button = E_ATTACHMENT_BUTTON (object);
+ EMailDisplay *display = user_data;
WebKitDOMDocument *document;
- WebKitDOMElement *attachment;
- WebKitDOMElement *button_element;
- WebKitDOMNodeList *nodes;
- gulong i, length;
- GtkWidget *button;
-
- /* Whenever an <iframe> is loaded, bind visibility of all GtkWidgets
- * the document within the <iframe> contains with "expanded" property
- * of the EAttachmentButton */
+ WebKitDOMElement *element;
+ WebKitDOMCSSStyleDeclaration *css;
+ gboolean expanded;
+ gchar *id;
- webframe = WEBKIT_WEB_FRAME (object);
- if (webkit_web_frame_get_load_status (webframe) != WEBKIT_LOAD_FINISHED)
- return;
+ d(printf("Attachment button %s has been %s!\n",
+ (gchar *) g_object_get_data (object, "uri"),
+ (e_attachment_button_get_expanded (button) ? "expanded" : "collapsed")));
- frame_name = webkit_web_frame_get_name (webframe);
+ expanded = e_attachment_button_get_expanded (button) &&
+ gtk_widget_get_visible (GTK_WIDGET (button));
- d(printf("Rebinding visibility of frame %s because it's URL changed\n",
- frame_name));
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
+ element = find_element_by_id (document, g_object_get_data (object, "attachment_id"));
- /* Get DOMDocument of the main document */
- document = webkit_web_view_get_dom_document (
- webkit_web_frame_get_web_view (webframe));
- if (!document)
+ if (!WEBKIT_DOM_IS_ELEMENT (element)) {
+ d(printf("%s: Content <div> of attachment %s does not exist!!\n",
+ G_STRFUNC, (gchar *) g_object_get_data (object, "uri")));
return;
+ }
- /* Find the <DIV> containing the <iframe> and related EAttachmentButton
- * within the DOM */
- attachment = find_element_by_id (document, frame_name);
- if (!attachment)
- return;
+ /* Show or hide the DIV which contains the attachment (iframe, image...) */
+ css = webkit_dom_element_get_style (element);
+ webkit_dom_css_style_declaration_set_property (
+ css, "display", expanded ? "block" : "none", "", NULL);
+
+ id = g_strconcat (g_object_get_data (object, "attachment_id"), ".iframe", NULL);
+ element = find_element_by_id (document, id);
+ g_free (id);
- button_uri = g_strconcat (frame_name, ".attachment_button", NULL);
- button_element = find_element_by_id (document, button_uri);
- g_free (button_uri);
- if (!button_element)
+ if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (element)) {
+ d(printf("%s: No <iframe> found\n",
+ (gchar *) g_object_get_data (object, "attachment_id")));
return;
+ }
+ bind_iframe_content_visibility (element, display, button);
+}
- button = g_object_get_data (G_OBJECT (button_element), "widget");
+static void
+mail_display_attachment_count_changed (EAttachmentStore *store,
+ GParamSpec *pspec,
+ GtkWidget *box)
+{
+ WebKitDOMHTMLElement *element;
+ GList *children;
- /* Get <iframe> representing the attachment content */
- nodes = webkit_dom_element_get_elements_by_tag_name (attachment, "iframe");
- length = webkit_dom_node_list_get_length (nodes);
- for (i = 0; i < length; i++) {
+ children = gtk_container_get_children (GTK_CONTAINER (box));
+ g_return_if_fail (children && children->data);
- WebKitDOMNode *node =
- webkit_dom_node_list_item (nodes, i);
+ element = g_object_get_data (children->data, "parent_element");
+ g_list_free (children);
- if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (node))
- continue;
+ g_return_if_fail (WEBKIT_DOM_IS_HTML_ELEMENT (element));
- /* Bind visibility of all GtkWidget within the
- * iframe with "expanded" property of the button */
- bind_iframe_content_visibility (
- E_ATTACHMENT_BUTTON (button),
- WEBKIT_DOM_ELEMENT (node));
+ if (e_attachment_store_get_num_attachments (store) == 0) {
+ gtk_widget_hide (box);
+ webkit_dom_html_element_set_hidden (element, TRUE);
+ } else {
+ gtk_widget_show (box);
+ webkit_dom_html_element_set_hidden (element, FALSE);
}
}
@@ -817,44 +848,91 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
GHashTable *param,
gpointer user_data)
{
- EMFormat *emf;
EMailDisplay *display;
- EMFormatPURI *puri;
+ EMailExtensionRegistry *reg;
+ EMailFormatterExtension *extension;
+ GQueue *extensions;
+ GList *iter;
+ EMailPart *part;
GtkWidget *widget;
- gchar *puri_uri;
+ gchar *part_id, *type, *object_uri;
- puri_uri = g_hash_table_lookup (param, "data");
- if (!puri_uri || !g_str_has_prefix (uri, "mail://"))
+ part_id = g_hash_table_lookup (param, "data");
+ if (!part_id || !g_str_has_prefix (uri, "mail://"))
+ return NULL;
+
+ type = g_hash_table_lookup (param, "type");
+ if (!type)
return NULL;
display = E_MAIL_DISPLAY (web_view);
- emf = (EMFormat *) display->priv->formatter;
- puri = em_format_find_puri (emf, puri_uri);
- if (!puri) {
+ if ((widget = g_hash_table_lookup (display->priv->widgets, part_id)) != NULL) {
+ d(printf("Handeled %s widget request from cache\n", part_id));
+ return widget;
+ }
+
+ /* Findt EMailPart representing requested widget */
+ part = e_mail_part_list_find_part (display->priv->part_list, part_id);
+ if (!part) {
return NULL;
}
- if (puri->widget_func)
- widget = puri->widget_func (emf, puri, NULL);
- else
- widget = NULL;
+ reg = e_mail_formatter_get_extension_registry (display->priv->formatter);
+ extensions = e_mail_extension_registry_get_for_mime_type (reg, type);
+ if (!extensions)
+ return NULL;
+
+ extension = NULL;
+ for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) {
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+ if (e_mail_formatter_extension_has_widget (extension))
+ break;
+ }
+
+ if (!extension)
+ return NULL;
+
+ /* Get the widget from formatter */
+ widget = e_mail_formatter_extension_get_widget (
+ extension, display->priv->part_list, part, param);
+ d(printf("Created widget %s (%p) for part %s\n",
+ G_OBJECT_TYPE_NAME (widget), widget, part_id));
+
+ /* Should not happen! WebKit will display an ugly 'Plug-in not available'
+ * placeholder instead of hiding the <object> element */
if (!widget)
return NULL;
+ /* Attachment button has URI different then the actual PURI because
+ * that URI identifies the attachment itself */
if (E_IS_ATTACHMENT_BUTTON (widget)) {
- /* Attachment button has URI different then the actual PURI because
- * that URI identifies the attachment itself */
- gchar *button_uri = g_strconcat (puri_uri, ".attachment_button", NULL);
- g_object_set_data_full (G_OBJECT (widget), "uri",
- button_uri, (GDestroyNotify) g_free);
+ EMailPartAttachment *empa = (EMailPartAttachment *) part;
+ gchar *attachment_part_id;
+
+ if (empa->attachment_view_part_id)
+ attachment_part_id = empa->attachment_view_part_id;
+ else
+ attachment_part_id = part_id;
+
+ object_uri = g_strconcat (attachment_part_id, ".attachment_button", NULL);
+ g_object_set_data_full (G_OBJECT (widget), "attachment_id",
+ g_strdup (attachment_part_id), (GDestroyNotify) g_free);
} else {
- g_object_set_data_full (G_OBJECT (widget), "uri",
- g_strdup (puri_uri), (GDestroyNotify) g_free);
+ object_uri = g_strdup (part_id);
}
- /* Set widget's <object> container as GObject data "parent_element" */
+ /* Store the uri as data of the widget */
+ g_object_set_data_full (G_OBJECT (widget), "uri",
+ object_uri, (GDestroyNotify) g_free);
+
+ /* Set pointer to the <object> element as GObject data "parent_element"
+ * and set pointer to the widget as GObject data "widget" to the <object>
+ * element */
plugin_widget_set_parent_element (widget, display);
/* Resizing a GtkWidget requires changing size of parent
@@ -864,26 +942,32 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
g_signal_connect (widget, "size-allocate",
G_CALLBACK (mail_display_plugin_widget_resize), display);
- /* Embed the attachment bar into the GtkBox before we do anything
- * further with the widget. */
- if (E_IS_MAIL_ATTACHMENT_BAR (widget)) {
-
- /* When EMailAttachmentBar is expanded/collapsed it does not
- * emit size-allocate signal despite it changes it's height. */
+ if (E_IS_ATTACHMENT_BAR (widget)) {
GtkWidget *box = NULL;
+ EAttachmentStore *store;
- /* Only when packed in box, EMailAttachmentBar reports correct
- * height */
- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+ /* Only when packed in box (grid does not work),
+ * EAttachmentBar reports correct height */
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
+ /* When EAttachmentBar is expanded/collapsed it does not
+ * emit size-allocate signal despite it changes it's height. */
g_signal_connect (widget, "notify::expanded",
G_CALLBACK (mail_display_plugin_widget_resize), display);
g_signal_connect (widget, "notify::active-view",
G_CALLBACK (mail_display_plugin_widget_resize), display);
- /* Show the EAttachmentBar but not the containing layout */
+ /* Always hide an attachment bar without attachments */
+ store = e_attachment_bar_get_store (E_ATTACHMENT_BAR (widget));
+ g_signal_connect (store, "notify::num-attachments",
+ G_CALLBACK (mail_display_attachment_count_changed), box);
+
gtk_widget_show (widget);
+ gtk_widget_show (box);
+
+ /* Initial sync */
+ mail_display_attachment_count_changed (store, NULL, box);
widget = box;
@@ -894,61 +978,63 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
* attachment button. */
WebKitDOMElement *attachment;
WebKitDOMDocument *document;
+ EMailPartAttachment *empa = (EMailPartAttachment *) part;
+ gchar *attachment_part_id;
+
+ if (empa->attachment_view_part_id)
+ attachment_part_id = empa->attachment_view_part_id;
+ else
+ attachment_part_id = part_id;
+ /* Find attachment-wrapper div which contains the content of the
+ * attachment (iframe) */
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
- attachment = find_element_by_id (document, puri_uri);
+ attachment = find_element_by_id (document, attachment_part_id);
+
+ /* None found? Attachment cannot be expanded */
if (!attachment) {
e_attachment_button_set_expandable (
E_ATTACHMENT_BUTTON (widget), FALSE);
} else {
const CamelContentDisposition *disposition;
- WebKitDOMNodeList *nodes;
- gulong i, length;
-
- /* Show/hide the attachment when the EAttachmentButton
- * is expanded/collapsed or shown/hidden */
- g_signal_connect_data (widget, "notify::expanded",
- G_CALLBACK (attachment_button_expanded),
- g_object_ref (attachment), (GClosureNotify) g_object_unref, 0);
- g_signal_connect_data (widget, "notify::visible",
- G_CALLBACK (attachment_button_expanded),
- g_object_ref (attachment), (GClosureNotify) g_object_unref, 0);
- /* Initial synchronization */
- attachment_button_expanded (G_OBJECT (widget),
- NULL, attachment);
-
- /* Find all <iframes> within the attachment and bind
- * it's visiblity to expanded state of the attachment btn */
- nodes = webkit_dom_element_get_elements_by_tag_name (
- attachment, "iframe");
- length = webkit_dom_node_list_get_length (nodes);
- for (i = 0; i < length; i++) {
-
- WebKitDOMNode *node =
- webkit_dom_node_list_item (nodes, i);
-
- if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (node))
- continue;
-
- bind_iframe_content_visibility (
- E_ATTACHMENT_BUTTON (widget),
- WEBKIT_DOM_ELEMENT (node));
- }
- /* Expand inlined attachments */
+ e_attachment_button_set_expandable (
+ E_ATTACHMENT_BUTTON (widget), TRUE);
+
+ /* Show/hide the attachment when the EAttachmentButton
+ * * is expanded/collapsed or shown/hidden */
+ g_signal_connect (widget, "notify::expanded",
+ G_CALLBACK (attachment_button_expanded), display);
+ g_signal_connect (widget, "notify::visible",
+ G_CALLBACK (attachment_button_expanded), display);
+
+ /* Automatically expand attachments that have inline
+ * disposition or the EMailParts have specific force_inline
+ * flag set */
disposition =
- camel_mime_part_get_content_disposition (puri->part);
- if (disposition &&
- g_ascii_strncasecmp (
- disposition->disposition, "inline", 6) == 0) {
+ camel_mime_part_get_content_disposition (part->part);
+ if (!part->force_collapse &&
+ (part->force_inline ||
+ (g_strcmp0 (empa->snoop_mime_type, "message/rfc822") == 0) ||
+ (disposition && disposition->disposition &&
+ g_ascii_strncasecmp (
+ disposition->disposition, "inline", 6) == 0))) {
e_attachment_button_set_expanded (
E_ATTACHMENT_BUTTON (widget), TRUE);
+ } else {
+ e_attachment_button_set_expanded (
+ E_ATTACHMENT_BUTTON (widget), FALSE);
+ attachment_button_expanded (
+ G_OBJECT (widget), NULL, display);
}
}
}
- d(printf("Created widget %s (%p)\n", puri_uri, widget));
+ g_hash_table_insert (
+ display->priv->widgets,
+ g_strdup (object_uri), g_object_ref (widget));
+
return widget;
}
@@ -1123,18 +1209,17 @@ setup_DOM_bindings (GObject *object,
}
static void
-puri_bind_dom (GObject *object,
- GParamSpec *pspec,
- gpointer user_data)
+mail_parts_bind_dom (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
WebKitWebFrame *frame;
WebKitLoadStatus load_status;
WebKitWebView *web_view;
WebKitDOMDocument *document;
EMailDisplay *display;
- GList *iter;
- EMFormat *emf;
- const gchar *frame_puri;
+ GSList *iter;
+ const gchar *frame_name;
frame = WEBKIT_WEB_FRAME (object);
load_status = webkit_web_frame_get_load_status (frame);
@@ -1142,36 +1227,40 @@ puri_bind_dom (GObject *object,
if (load_status != WEBKIT_LOAD_FINISHED)
return;
- frame_puri = webkit_web_frame_get_name (frame);
web_view = webkit_web_frame_get_web_view (frame);
display = E_MAIL_DISPLAY (web_view);
-
- emf = EM_FORMAT (display->priv->formatter);
- if (!emf)
+ if (display->priv->part_list == NULL)
return;
- iter = g_hash_table_lookup (
- emf->mail_part_table,
- webkit_web_frame_get_name (frame));
+ frame_name = webkit_web_frame_get_name (frame);
+ for (iter = display->priv->part_list->list; iter; iter = iter->next) {
+
+ EMailPart *part = iter->data;
+ if (!part)
+ continue;
- document = webkit_web_view_get_dom_document (web_view);
+ if (g_strcmp0 (part->id, frame_name) == 0)
+ break;
+ }
+ document = webkit_web_view_get_dom_document (web_view);
while (iter) {
- EMFormatPURI *puri = iter->data;
-
- if (!puri)
+ EMailPart *part = iter->data;
+ if (!part) {
+ iter = iter->next;
continue;
+ }
- /* Iterate only the PURI rendered in the frame and all it's "subPURIs" */
- if (!g_str_has_prefix (puri->uri, frame_puri))
+ /* Iterate only the parts rendered in the frame and all it's subparts */
+ if (!g_str_has_prefix (part->id, frame_name))
break;
- if (puri->bind_func) {
- WebKitDOMElement *el = find_element_by_id (document, puri->uri);
+ if (part->bind_func) {
+ WebKitDOMElement *el = find_element_by_id (document, part->id);
if (el) {
- d(printf("bind_func for %s\n", puri->uri));
- puri->bind_func (el, puri);
+ d(printf("/*bind_func*/ for %s\n", part->id));
+ part->bind_func (part, el);
}
}
@@ -1186,15 +1275,25 @@ mail_display_frame_created (WebKitWebView *web_view,
{
d(printf("Frame %s created!\n", webkit_web_frame_get_name (frame)));
- /* Re-bind visibility of this newly created <iframe> with
- * related EAttachmentButton whenever content of this <iframe> is
- * (re)loaded */
+ /* Call bind_func of all parts written in this frame */
g_signal_connect (frame, "notify::load-status",
- G_CALLBACK (bind_attachment_iframe_visibility), NULL);
+ G_CALLBACK (mail_parts_bind_dom), NULL);
+}
- /* Call bind_func of all PURIs written in this frame */
- g_signal_connect (frame, "notify::load-status",
- G_CALLBACK (puri_bind_dom), NULL);
+static void
+mail_display_uri_changed (EMailDisplay *display,
+ GParamSpec *pspec,
+ gpointer dummy)
+{
+ d(printf("EMailDisplay URI changed, recreating widgets hashtable\n"));
+
+ if (display->priv->widgets)
+ g_hash_table_destroy (display->priv->widgets);
+
+ display->priv->widgets = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
}
static void
@@ -1253,12 +1352,11 @@ e_mail_display_class_init (EMailDisplayClass *class)
g_object_class_install_property (
object_class,
- PROP_FORMATTER,
- g_param_spec_object (
- "formatter",
- "HTML Formatter",
+ PROP_PART_LIST,
+ g_param_spec_pointer (
+ "part-list",
+ "Part List",
NULL,
- EM_TYPE_FORMAT_HTML,
G_PARAM_READWRITE));
g_object_class_install_property (
@@ -1268,9 +1366,9 @@ e_mail_display_class_init (EMailDisplayClass *class)
"mode",
"Display Mode",
NULL,
- 0,
+ E_MAIL_FORMATTER_MODE_INVALID,
G_MAXINT,
- EM_FORMAT_WRITE_MODE_NORMAL,
+ E_MAIL_FORMATTER_MODE_NORMAL,
G_PARAM_READWRITE));
g_object_class_install_property (
@@ -1305,6 +1403,10 @@ e_mail_display_init (EMailDisplay *display)
display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
+ /* Set invalid mode so that MODE property initialization is run
+ * completely (see e_mail_display_set_mode) */
+ display->priv->mode = E_MAIL_FORMATTER_MODE_INVALID;
+ e_mail_display_set_mode (display, E_MAIL_FORMATTER_MODE_NORMAL);
display->priv->force_image_load = FALSE;
display->priv->mailto_actions = gtk_action_group_new ("mailto");
gtk_action_group_add_actions (display->priv->mailto_actions, mailto_entries,
@@ -1331,6 +1433,8 @@ e_mail_display_init (EMailDisplay *display)
G_CALLBACK (mail_display_plugin_widget_requested), NULL);
g_signal_connect (display, "frame-created",
G_CALLBACK (mail_display_frame_created), NULL);
+ g_signal_connect (display, "notify::uri",
+ G_CALLBACK (mail_display_uri_changed), NULL);
display->priv->settings = g_settings_new ("org.gnome.evolution.mail");
g_signal_connect_swapped (
@@ -1350,7 +1454,7 @@ e_mail_display_init (EMailDisplay *display)
G_CALLBACK (setup_DOM_bindings), NULL);
main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (display));
g_signal_connect (main_frame, "notify::load-status",
- G_CALLBACK (puri_bind_dom), NULL);
+ G_CALLBACK (mail_parts_bind_dom), NULL);
/* Because we are loading from a hard-coded string, there is
* no chance of I/O errors. Failure here implies a malformed
@@ -1387,75 +1491,99 @@ e_mail_display_init (EMailDisplay *display)
}
}
-EMFormatHTML *
-e_mail_display_get_formatter (EMailDisplay *display)
+EMailFormatterMode
+e_mail_display_get_mode (EMailDisplay *display)
{
- g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+ g_return_val_if_fail (E_IS_MAIL_DISPLAY (display),
+ E_MAIL_FORMATTER_MODE_NORMAL);
- return display->priv->formatter;
+ return display->priv->mode;
}
void
-e_mail_display_set_formatter (EMailDisplay *display,
- EMFormatHTML *formatter)
+e_mail_display_set_mode (EMailDisplay *display,
+ EMailFormatterMode mode)
{
+ EMailFormatter *formatter;
g_return_if_fail (E_IS_MAIL_DISPLAY (display));
- if (formatter) {
- g_return_if_fail (EM_IS_FORMAT_HTML (formatter));
- g_object_ref (formatter);
- }
-
- if (display->priv->formatter != NULL) {
- /* The formatter might still exist after unrefing it, so
- * we need to stop listening to it's request for redrawing */
- g_signal_handlers_disconnect_by_func (
- display->priv->formatter, e_mail_display_reload, display);
- g_object_unref (display->priv->formatter);
- }
+ if (display->priv->mode == mode)
+ return;
- display->priv->formatter = formatter;
+ display->priv->mode = mode;
- if (!formatter) {
- e_web_view_clear (E_WEB_VIEW (display));
- return;
+ if (display->priv->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
+ formatter = e_mail_formatter_print_new ();
+ } else {
+ formatter = e_mail_formatter_new ();
}
+ g_clear_object (&display->priv->formatter);
+ display->priv->formatter = formatter;
mail_display_update_formatter_colors (display);
g_signal_connect (formatter, "notify::image-loading-policy",
G_CALLBACK (formatter_image_loading_policy_changed_cb), display);
- g_signal_connect_swapped (formatter, "redraw-requested",
- G_CALLBACK (e_mail_display_reload), display);
- g_signal_connect_swapped (formatter, "notify::charset",
- G_CALLBACK (e_mail_display_reload), display);
- g_object_notify (G_OBJECT (display), "formatter");
+ g_object_connect (formatter,
+ "swapped-signal::notify::charset",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::image-loading-policy",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::mark-citations",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::only-local-photos",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::show-sender-photo",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::show-real-date",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::animate-images",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::text-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::body-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::citation-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::content-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::frame-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ "swapped-signal::notify::header-color",
+ G_CALLBACK (e_mail_display_reload), display,
+ NULL);
+
+ e_mail_display_reload (display);
+
+ g_object_notify (G_OBJECT (display), "mode");
}
-EMFormatWriteMode
-e_mail_display_get_mode (EMailDisplay *display)
+EMailPartList *
+e_mail_display_get_parts_list (EMailDisplay *display)
{
- g_return_val_if_fail (E_IS_MAIL_DISPLAY (display),
- EM_FORMAT_WRITE_MODE_NORMAL);
+ g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
- return display->priv->mode;
+ return display->priv->part_list;
}
void
-e_mail_display_set_mode (EMailDisplay *display,
- EMFormatWriteMode mode)
+e_mail_display_set_parts_list (EMailDisplay *display,
+ EMailPartList *part_list)
{
g_return_if_fail (E_IS_MAIL_DISPLAY (display));
- if (display->priv->mode == mode)
- return;
+ if (part_list) {
+ g_return_if_fail (E_IS_MAIL_PART_LIST (part_list));
+ g_object_ref (part_list);
+ }
- display->priv->mode = mode;
+ if (display->priv->part_list)
+ g_object_unref (display->priv->part_list);
- e_mail_display_reload (display);
+ display->priv->part_list = part_list;
- g_object_notify (G_OBJECT (display), "mode");
+ g_object_notify (G_OBJECT (display), "part-list");
}
gboolean
@@ -1510,16 +1638,21 @@ void
e_mail_display_load (EMailDisplay *display,
const gchar *msg_uri)
{
- EMFormat *emf;
gchar *uri;
+ EMailPartList *part_list;
g_return_if_fail (E_IS_MAIL_DISPLAY (display));
display->priv->force_image_load = FALSE;
- emf = EM_FORMAT (display->priv->formatter);
+ part_list = display->priv->part_list;
+ if (!part_list) {
+ e_web_view_clear (E_WEB_VIEW (display));
+ return;
+ }
- uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
+ uri = e_mail_part_build_uri (
+ part_list->folder, part_list->message_uid,
"mode", G_TYPE_INT, display->priv->mode,
"headers_collapsable", G_TYPE_BOOLEAN, display->priv->headers_collapsable,
"headers_collapsed", G_TYPE_BOOLEAN, display->priv->headers_collapsed,
diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h
index 9865a3ee37..e19895623a 100644
--- a/mail/e-mail-display.h
+++ b/mail/e-mail-display.h
@@ -24,7 +24,8 @@
#include <misc/e-web-view.h>
#include <misc/e-search-bar.h>
-#include "em-format-html.h"
+
+#include <em-format/e-mail-formatter.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_DISPLAY \
@@ -62,13 +63,16 @@ struct _EMailDisplayClass {
};
GType e_mail_display_get_type (void);
-EMFormatHTML * e_mail_display_get_formatter (EMailDisplay *display);
-void e_mail_display_set_formatter (EMailDisplay *display,
- EMFormatHTML *formatter);
void e_mail_display_set_mode (EMailDisplay *display,
- EMFormatWriteMode mode);
-EMFormatWriteMode e_mail_display_get_mode (EMailDisplay *display);
+ EMailFormatterMode mode);
+EMailFormatterMode e_mail_display_get_mode (EMailDisplay *display);
+
+EMailPartList * e_mail_display_get_parts_list (EMailDisplay *display);
+
+void e_mail_display_set_parts_list (EMailDisplay *display,
+ EMailPartList *parts_list);
+
void e_mail_display_set_headers_collapsable
(EMailDisplay *display,
gboolean collapsable);
diff --git a/mail/e-mail-folder-pane.c b/mail/e-mail-folder-pane.c
index 03168cec18..e6c0e9213b 100644
--- a/mail/e-mail-folder-pane.c
+++ b/mail/e-mail-folder-pane.c
@@ -43,7 +43,6 @@
#include "mail/e-mail-reader.h"
#include "mail/e-mail-reader-utils.h"
#include "mail/em-folder-tree-model.h"
-#include "mail/em-format-html-display.h"
#include "mail/em-composer-utils.h"
#include "mail/em-utils.h"
#include "mail/message-list.h"
diff --git a/mail/e-mail-paned-view.h b/mail/e-mail-paned-view.h
index 5e6879ae94..dbea57b99f 100644
--- a/mail/e-mail-paned-view.h
+++ b/mail/e-mail-paned-view.h
@@ -28,8 +28,6 @@
#include <shell/e-shell-searchbar.h>
#include <shell/e-shell-view.h>
-#include <mail/em-format-html-display.h>
-
/* Standard GObject macros */
#define E_TYPE_MAIL_PANED_VIEW \
(e_mail_paned_view_get_type ())
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 0a52a0a5b2..f90414f02d 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -24,13 +24,15 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include <em-format/e-mail-formatter-print.h>
+#include <em-format/e-mail-part-utils.h>
+
#include <e-util/e-print.h>
#include <e-util/e-marshal.h>
#include <webkit/webkitdom.h>
#include "e-mail-printer.h"
-#include "em-format-html-print.h"
#include "e-mail-display.h"
static gpointer parent_class = NULL;
@@ -48,9 +50,11 @@ enum {
#define w(x)
struct _EMailPrinterPrivate {
- EMFormatHTMLPrint *efhp;
+ EMailFormatterPrint *formatter;
+ EMailPartList *parts_list;
gboolean export_mode;
+ gchar *export_filename;
GtkListStore *headers;
@@ -69,7 +73,7 @@ G_DEFINE_TYPE (
enum {
PROP_0,
- PROP_PRINT_FORMATTER
+ PROP_PART_LIST
};
enum {
@@ -88,8 +92,8 @@ enum {
static guint signals[LAST_SIGNAL];
static gint
-emp_header_name_equal (const EMFormatHeader *h1,
- const EMFormatHeader *h2)
+emp_header_name_equal (const EMailFormatterHeader *h1,
+ const EMailFormatterHeader *h2)
{
if ((h2->value == NULL) || (h1->value == NULL)) {
return g_strcmp0 (h1->name, h2->name);
@@ -169,8 +173,7 @@ emp_start_printing (GObject *object,
if (emp->priv->export_mode) {
gtk_print_operation_set_export_filename (
- emp->priv->operation,
- emp->priv->efhp->export_filename);
+ emp->priv->operation, emp->priv->export_filename);
webkit_web_frame_print_full (
frame, emp->priv->operation,
GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
@@ -185,32 +188,23 @@ emp_start_printing (GObject *object,
static void
emp_run_print_operation (EMailPrinter *emp)
{
- EMFormat *emf;
- SoupSession *session;
- GHashTable *formatters;
gchar *mail_uri;
- emf = EM_FORMAT (emp->priv->efhp);
- mail_uri = em_format_build_mail_uri (emf->folder, emf->message_uid, NULL, NULL);
-
- /* It's safe to assume that session exists and contains formatters table,
- * because at least the message we are about to print now must be already
- * there */
- session = webkit_get_default_session ();
- formatters = g_object_get_data (G_OBJECT (session), "formatters");
- g_hash_table_insert (formatters, g_strdup (mail_uri), emp->priv->efhp);
+ mail_uri = e_mail_part_build_uri (emp->priv->parts_list->folder,
+ emp->priv->parts_list->message_uid,
+ "__evo-load-image", G_TYPE_BOOLEAN, TRUE,
+ "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_PRINTING,
+ NULL);
/* Print_layout is a special EMPart created by EMFormatHTMLPrint */
- if (emp->priv->uri)
- g_free (emp->priv->uri);
-
- emp->priv->uri = g_strconcat (mail_uri, "?part_id=print_layout&__evo-load-images=1", NULL);
-
if (emp->priv->webview == NULL) {
- emp->priv->webview = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
+ emp->priv->webview = g_object_new (
+ E_TYPE_MAIL_DISPLAY,
+ "mode", E_MAIL_FORMATTER_MODE_PRINTING, NULL);
e_web_view_set_enable_frame_flattening (E_WEB_VIEW (emp->priv->webview), FALSE);
e_mail_display_set_force_load_images (
- E_MAIL_DISPLAY (emp->priv->webview), TRUE);
+ E_MAIL_DISPLAY (emp->priv->webview), TRUE);
+
g_object_ref_sink (emp->priv->webview);
g_signal_connect (emp->priv->webview, "notify::load-status",
G_CALLBACK (emp_start_printing), emp);
@@ -224,18 +218,16 @@ emp_run_print_operation (EMailPrinter *emp)
gtk_widget_show_all (window);
});
}
-
- e_mail_display_set_formatter (E_MAIL_DISPLAY (emp->priv->webview),
- (EMFormatHTML *) emp->priv->efhp);
-
- webkit_web_view_load_uri (emp->priv->webview, emp->priv->uri);
+ e_mail_display_set_parts_list (
+ E_MAIL_DISPLAY (emp->priv->webview), emp->priv->parts_list);
+ webkit_web_view_load_uri (emp->priv->webview, mail_uri);
g_free (mail_uri);
}
static void
set_header_visible (EMailPrinter *emp,
- EMFormatHeader *header,
+ EMailFormatterHeader *header,
gint index,
gboolean visible)
{
@@ -263,7 +255,7 @@ header_active_renderer_toggled_cb (GtkCellRendererToggle *renderer,
GtkTreeIter iter;
GtkTreePath *p;
gboolean active;
- EMFormatHeader *header;
+ EMailFormatterHeader *header;
gint *indices;
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (emp->priv->headers),
@@ -301,7 +293,7 @@ emp_headers_tab_toggle_selection (GtkWidget *button,
return;
do {
- EMFormatHeader *header;
+ EMailFormatterHeader *header;
GtkTreePath *path;
gint *indices;
@@ -594,47 +586,44 @@ emp_create_headers_tab (GtkPrintOperation *operation,
}
static void
-emp_set_formatter (EMailPrinter *emp,
- EMFormatHTMLPrint *formatter)
+emp_set_parts_list (EMailPrinter *emp,
+ EMailPartList *parts_list)
{
- EMFormat *emf = (EMFormat *) formatter;
CamelMediumHeader *header;
GArray *headers;
gint i;
GtkTreeIter last_known;
- g_return_if_fail (EM_IS_FORMAT_HTML_PRINT (formatter));
-
- g_object_ref (formatter);
+ g_return_if_fail (parts_list);
- if (emp->priv->efhp)
- g_object_unref (emp->priv->efhp);
-
- emp->priv->efhp = formatter;
+ emp->priv->parts_list = g_object_ref (parts_list);
if (emp->priv->headers)
g_object_unref (emp->priv->headers);
emp->priv->headers = gtk_list_store_new (5,
G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
- headers = camel_medium_get_headers (CAMEL_MEDIUM (emf->message));
+ headers = camel_medium_get_headers (CAMEL_MEDIUM (parts_list->message));
if (!headers)
return;
for (i = 0; i < headers->len; i++) {
GtkTreeIter iter;
GList *found_header;
- EMFormatHeader *emfh;
+ EMailFormatterHeader *emfh;
header = &g_array_index (headers, CamelMediumHeader, i);
- emfh = em_format_header_new (header->name, header->value);
+ emfh = e_mail_formatter_header_new (header->name, header->value);
- found_header = g_queue_find_custom (&EM_FORMAT (formatter)->header_list,
+ found_header = g_queue_find_custom (
+ (GQueue *) e_mail_formatter_get_headers (
+ E_MAIL_FORMATTER (emp->priv->formatter)),
emfh, (GCompareFunc) emp_header_name_equal);
if (!found_header) {
- emfh->flags |= EM_FORMAT_HTML_HEADER_HIDDEN;
- em_format_add_header_struct (EM_FORMAT (formatter), emfh);
+ emfh->flags |= E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN;
+ e_mail_formatter_add_header_struct (
+ E_MAIL_FORMATTER (emp->priv->formatter), emfh);
gtk_list_store_append (emp->priv->headers, &iter);
} else {
if (gtk_list_store_iter_is_valid (emp->priv->headers, &last_known))
@@ -652,7 +641,7 @@ emp_set_formatter (EMailPrinter *emp,
COLUMN_HEADER_STRUCT, emfh, -1);
}
- camel_medium_free_headers (CAMEL_MEDIUM (emf->message), headers);
+ camel_medium_free_headers (CAMEL_MEDIUM (parts_list->message), headers);
}
static void
@@ -665,8 +654,8 @@ emp_set_property (GObject *object,
switch (property_id) {
- case PROP_PRINT_FORMATTER:
- emp_set_formatter (emp, g_value_get_object (value));
+ case PROP_PART_LIST:
+ emp_set_parts_list (emp, g_value_get_pointer (value));
return;
}
@@ -683,9 +672,9 @@ emp_get_property (GObject *object,
switch (property_id) {
- case PROP_PRINT_FORMATTER:
- g_value_set_object (value,
- e_mail_printer_get_print_formatter (emp));
+ case PROP_PART_LIST:
+ g_value_set_pointer (value,
+ emp->priv->parts_list);
return;
}
@@ -697,9 +686,9 @@ emp_finalize (GObject *object)
{
EMailPrinterPrivate *priv = E_MAIL_PRINTER (object)->priv;
- if (priv->efhp) {
- g_object_unref (priv->efhp);
- priv->efhp = NULL;
+ if (priv->formatter) {
+ g_object_unref (priv->formatter);
+ priv->formatter = NULL;
}
if (priv->headers) {
@@ -707,10 +696,10 @@ emp_finalize (GObject *object)
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->headers), &iter)) {
do {
- EMFormatHeader *header = NULL;
+ EMailFormatterHeader *header = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (priv->headers), &iter,
COLUMN_HEADER_STRUCT, &header, -1);
- em_format_header_free (header);
+ e_mail_formatter_header_free (header);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->headers), &iter));
}
g_object_unref (priv->headers);
@@ -732,6 +721,11 @@ emp_finalize (GObject *object)
priv->operation = NULL;
}
+ if (priv->parts_list) {
+ g_object_unref (priv->parts_list);
+ priv->parts_list = NULL;
+ }
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -751,13 +745,13 @@ e_mail_printer_class_init (EMailPrinterClass *klass)
g_object_class_install_property (
object_class,
- PROP_PRINT_FORMATTER,
- g_param_spec_object (
- "print-formatter",
- NULL,
+ PROP_PART_LIST,
+ g_param_spec_pointer (
+ "parts-list",
+ "Parts List",
NULL,
- EM_TYPE_FORMAT_HTML_PRINT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
signals[SIGNAL_DONE] = g_signal_new ("done",
G_TYPE_FROM_CLASS (klass),
@@ -775,23 +769,18 @@ e_mail_printer_init (EMailPrinter *emp)
emp->priv = G_TYPE_INSTANCE_GET_PRIVATE (
emp, E_TYPE_MAIL_PRINTER, EMailPrinterPrivate);
- emp->priv->efhp = NULL;
+ emp->priv->formatter = (EMailFormatterPrint *) e_mail_formatter_print_new ();
emp->priv->headers = NULL;
emp->priv->webview = NULL;
}
EMailPrinter *
-e_mail_printer_new (EMFormatHTML *source)
+e_mail_printer_new (EMailPartList *source)
{
EMailPrinter *emp;
- EMFormatHTMLPrint *efhp;
-
- efhp = em_format_html_print_new (source);
emp = g_object_new (E_TYPE_MAIL_PRINTER,
- "print-formatter", efhp, NULL);
-
- g_object_unref (efhp);
+ "parts-list", source, NULL);
return emp;
}
@@ -830,10 +819,7 @@ e_mail_printer_get_export_filename (EMailPrinter *printer)
{
g_return_val_if_fail (E_IS_MAIL_PRINTER (printer), NULL);
- if (!printer->priv->efhp)
- return NULL;
-
- return printer->priv->efhp->export_filename;
+ return printer->priv->export_filename;
}
void
@@ -841,19 +827,9 @@ e_mail_printer_set_export_filename (EMailPrinter *printer,
const gchar *filename)
{
g_return_if_fail (E_IS_MAIL_PRINTER (printer));
- g_return_if_fail (printer->priv->efhp != NULL);
- if (printer->priv->efhp->export_filename && *printer->priv->efhp->export_filename)
- g_free (printer->priv->efhp->export_filename);
+ if (printer->priv->export_filename)
+ g_free (printer->priv->export_filename);
- printer->priv->efhp->export_filename = g_strdup (filename);
+ printer->priv->export_filename = g_strdup (filename);
}
-
-EMFormatHTMLPrint *
-e_mail_printer_get_print_formatter (EMailPrinter *emp)
-{
- g_return_val_if_fail (E_IS_MAIL_PRINTER (emp), NULL);
-
- return emp->priv->efhp;
-}
-
diff --git a/mail/e-mail-printer.h b/mail/e-mail-printer.h
index fcd163ec78..a0721ea9d4 100644
--- a/mail/e-mail-printer.h
+++ b/mail/e-mail-printer.h
@@ -20,7 +20,7 @@
#ifndef E_MAIL_PRINTER_H
#define E_MAIL_PRINTER_H
-#include "mail/em-format-html-print.h"
+#include <em-format/e-mail-part-list.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_PRINTER \
@@ -63,7 +63,7 @@ struct _EMailPrinterClass {
GType e_mail_printer_get_type (void);
-EMailPrinter * e_mail_printer_new (EMFormatHTML *source);
+EMailPrinter * e_mail_printer_new (EMailPartList *source);
void e_mail_printer_print (EMailPrinter *printer,
gboolean export,
@@ -76,10 +76,6 @@ void e_mail_printer_set_export_filename
const gchar * e_mail_printer_get_export_filename
(EMailPrinter *printer);
-EMFormatHTMLPrint *
- e_mail_printer_get_print_formatter
- (EMailPrinter *printer);
-
G_END_DECLS
#endif /* E_MAIL_PRINTER_H */
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 2240523beb..f56b094e14 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -46,13 +46,20 @@
#include "mail/e-mail-backend.h"
#include "mail/e-mail-browser.h"
#include "mail/e-mail-printer.h"
+#include "mail/e-mail-display.h"
#include "mail/em-composer-utils.h"
-#include "mail/em-format-html-print.h"
#include "mail/em-utils.h"
#include "mail/mail-autofilter.h"
#include "mail/mail-vfolder-ui.h"
#include "mail/message-list.h"
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+
+#define d(x)
+
+static GHashTable * mail_reader_get_mail_register (void);
+
typedef struct _AsyncContext AsyncContext;
struct _AsyncContext {
@@ -434,7 +441,7 @@ e_mail_reader_open_selected (EMailReader *reader)
MessageList *ml;
browser = e_mail_browser_new (backend, folder, uid,
- EM_FORMAT_WRITE_MODE_NORMAL);
+ E_MAIL_FORMATTER_MODE_NORMAL);
e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
e_mail_reader_set_message (E_MAIL_READER (browser), uid);
@@ -508,30 +515,109 @@ printing_done_cb (EMailPrinter *printer,
(GSourceFunc) destroy_printing_activity, activity, NULL);
}
-void
-e_mail_reader_print (EMailReader *reader,
- GtkPrintOperationAction action)
-{
- EMailDisplay *display;
- EMailPrinter *printer;
- EMFormatHTML *formatter;
+struct _MessagePrintingContext {
+ EMailReader *reader;
+ CamelFolder *folder;
+ gchar *message_uid;
+
EActivity *activity;
- GCancellable *cancellable;
+};
- g_return_if_fail (E_IS_MAIL_READER (reader));
+static void
+free_message_printing_context (struct _MessagePrintingContext *context)
+{
+ g_return_if_fail (context != NULL);
- display = e_mail_reader_get_mail_display (reader);
- formatter = e_mail_display_get_formatter (display);
+ g_clear_object (&context->reader);
+ g_clear_object (&context->folder);
+ g_clear_object (&context->activity);
- activity = e_mail_reader_new_activity (reader);
+ if (context->message_uid)
+ g_free (context->message_uid);
+
+ g_free (context);
+}
+
+static void
+mail_reader_do_print_message (EMailPartList *part_list,
+ gpointer user_data)
+{
+ EActivity *activity;
+ GCancellable *cancellable;
+ EMailPrinter *printer;
+ struct _MessagePrintingContext *context = user_data;
+
+ activity = e_mail_reader_new_activity (context->reader);
e_activity_set_text (activity, _("Printing"));
e_activity_set_state (activity, E_ACTIVITY_RUNNING);
cancellable = e_activity_get_cancellable (activity);
- printer = e_mail_printer_new (formatter);
+ printer = e_mail_printer_new (part_list);
g_signal_connect (printer, "done",
G_CALLBACK (printing_done_cb), activity);
e_mail_printer_print (printer, FALSE, cancellable);
+
+ free_message_printing_context (context);
+}
+
+static void
+mail_reader_get_message_to_print_ready_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CamelMimeMessage *message;
+ struct _MessagePrintingContext *context = user_data;
+
+ message = camel_folder_get_message_finish (CAMEL_FOLDER (object), result, NULL);
+ if (!CAMEL_IS_MIME_MESSAGE (message)) {
+ free_message_printing_context (context);
+ return;
+ }
+
+ /* "Retrieving message" activity (or NULL) */
+ g_clear_object (&context->activity);
+
+ e_mail_reader_parse_message (
+ context->reader, context->folder, context->message_uid,
+ message, (GFunc) mail_reader_do_print_message, context);
+}
+
+void
+e_mail_reader_print (EMailReader *reader,
+ GtkPrintOperationAction action)
+{
+ EMailPartList *parts;
+ struct _MessagePrintingContext *context;
+ MessageList *message_list;
+ gchar *uri;
+
+ context = g_new0 (struct _MessagePrintingContext, 1);
+
+ message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
+ context->reader = g_object_ref (reader);
+ context->message_uid = g_strdup (message_list->cursor_uid);
+ context->folder = g_object_ref (e_mail_reader_get_folder (reader));
+
+ g_return_if_fail (E_IS_MAIL_READER (reader));
+
+ uri = e_mail_part_build_uri (
+ context->folder, context->message_uid, NULL, NULL);
+ parts = e_mail_reader_lookup_part_list (reader, uri);
+ if (!parts) {
+ GCancellable *cancellable;
+
+ context->activity = e_mail_reader_new_activity (reader);
+ cancellable = e_activity_get_cancellable (context->activity);
+
+ camel_folder_get_message (
+ context->folder, context->message_uid,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) mail_reader_get_message_to_print_ready_cb,
+ context);
+
+ } else {
+ mail_reader_do_print_message (parts, context);
+ }
}
static void
@@ -770,15 +856,31 @@ html_contains_nonwhitespace (const gchar *html,
}
static void
+mail_reader_reply_message_parsed (EMailPartList *part_list,
+ gpointer user_data)
+{
+ EShell *shell;
+ EMailBackend *backend;
+ AsyncContext *context = user_data;
+
+ backend = e_mail_reader_get_backend (context->reader);
+ shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+
+ em_utils_reply_to_message (
+ shell, part_list->message,
+ context->folder, context->message_uid,
+ context->reply_type, context->reply_style,
+ part_list, context->address);
+
+ async_context_free (context);
+}
+
+static void
mail_reader_get_message_ready_cb (CamelFolder *folder,
GAsyncResult *result,
AsyncContext *context)
{
- EShell *shell;
- EMailBackend *backend;
EAlertSink *alert_sink;
- EMFormatHTML *formatter;
- EMailDisplay *display;
CamelMimeMessage *message;
GError *error = NULL;
@@ -804,22 +906,10 @@ mail_reader_get_message_ready_cb (CamelFolder *folder,
g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
- backend = e_mail_reader_get_backend (context->reader);
- shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
- display = e_mail_reader_get_mail_display (context->reader);
- formatter = e_mail_display_get_formatter (display);
-
- em_utils_reply_to_message (
- shell, message,
- context->folder, context->message_uid,
- context->reply_type, context->reply_style,
- EM_FORMAT (formatter), context->address);
-
- g_object_unref (message);
-
- e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
-
- async_context_free (context);
+ e_mail_reader_parse_message (context->reader, context->folder,
+ context->message_uid, message,
+ (GFunc) mail_reader_reply_message_parsed,
+ context);
}
void
@@ -831,7 +921,7 @@ e_mail_reader_reply_to_message (EMailReader *reader,
EMailBackend *backend;
EShellBackend *shell_backend;
EMailDisplay *display;
- EMFormatHTML *formatter;
+ EMailPartList *part_list;
GtkWidget *message_list;
CamelMimeMessage *new_message;
CamelInternetAddress *address = NULL;
@@ -842,6 +932,8 @@ e_mail_reader_reply_to_message (EMailReader *reader,
const gchar *uid;
gchar *selection = NULL;
gint length;
+ gchar *mail_uri;
+ GHashTable *mail_register;
/* This handles quoting only selected text in the reply. If
* nothing is selected or only whitespace is selected, fall
@@ -852,7 +944,6 @@ e_mail_reader_reply_to_message (EMailReader *reader,
backend = e_mail_reader_get_backend (reader);
folder = e_mail_reader_get_folder (reader);
display = e_mail_reader_get_mail_display (reader);
- formatter = e_mail_display_get_formatter (display);
message_list = e_mail_reader_get_message_list (reader);
reply_style = e_mail_reader_get_reply_style (reader);
@@ -889,11 +980,19 @@ e_mail_reader_reply_to_message (EMailReader *reader,
uid = MESSAGE_LIST (message_list)->cursor_uid;
g_return_if_fail (uid != NULL);
- if (!gtk_widget_get_mapped (GTK_WIDGET (web_view)))
+ if (!gtk_widget_get_visible (GTK_WIDGET (web_view)))
+ goto whole_message;
+
+ mail_register = mail_reader_get_mail_register ();
+ mail_uri = e_mail_part_build_uri (folder, uid, NULL, NULL);
+ part_list = g_hash_table_lookup (mail_register, mail_uri);
+ g_free (mail_uri);
+
+ if (!part_list)
goto whole_message;
if (src_message == NULL) {
- src_message = EM_FORMAT (formatter)->message;
+ src_message = part_list->message;
if (src_message != NULL)
g_object_ref (src_message);
@@ -976,7 +1075,7 @@ whole_message:
em_utils_reply_to_message (
shell, src_message, folder, uid,
- reply_type, reply_style, EM_FORMAT (formatter), address);
+ reply_type, reply_style, part_list, address);
if (address)
g_object_unref (address);
@@ -1419,43 +1518,58 @@ e_mail_reader_header_free (EMailReaderHeader *header)
g_free (header);
}
+struct headers_changed_closure {
+ EMailFormatter *formatter;
+ EMailDisplay *display;
+};
+
+static void
+free_headers_changed_closure (struct headers_changed_closure *closure)
+{
+ g_clear_object (&closure->formatter);
+ g_clear_object (&closure->display);
+
+ g_free (closure);
+}
+
static void
headers_changed_cb (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
- EMFormat *emf)
+ struct headers_changed_closure *closure)
{
GSList *header_config_list, *p;
g_return_if_fail (client != NULL);
- g_return_if_fail (EM_IS_FORMAT (emf));
header_config_list = gconf_client_get_list (
client, "/apps/evolution/mail/display/headers",
GCONF_VALUE_STRING, NULL);
- em_format_clear_headers (emf);
+ e_mail_formatter_clear_headers (closure->formatter);
for (p = header_config_list; p; p = g_slist_next (p)) {
EMailReaderHeader *h;
gchar *xml = (gchar *) p->data;
h = e_mail_reader_header_from_xml (xml);
if (h && h->enabled)
- em_format_add_header (
- emf, h->name, NULL, EM_FORMAT_HEADER_BOLD);
+ e_mail_formatter_add_header (
+ closure->formatter, h->name, NULL,
+ E_MAIL_FORMATTER_HEADER_FLAG_BOLD);
e_mail_reader_header_free (h);
}
if (!header_config_list)
- em_format_default_headers (emf);
+ e_mail_formatter_set_default_headers (closure->formatter);
g_slist_foreach (header_config_list, (GFunc) g_free, NULL);
g_slist_free (header_config_list);
/* force a redraw */
- if (emf->message)
- em_format_redraw (emf);
+ if (closure->display) {
+ e_mail_display_reload (closure->display);
+ }
}
static void
@@ -1482,26 +1596,159 @@ remove_header_notify_cb (gpointer data)
**/
void
e_mail_reader_connect_headers (EMailReader *reader,
- EMFormat *emf)
+ EMailFormatter *formatter)
{
GConfClient *client;
guint notify_id;
+ struct headers_changed_closure *closure;
client = gconf_client_get_default ();
+ closure = g_new0 (struct headers_changed_closure, 1);
+ closure->display = g_object_ref (e_mail_reader_get_mail_display (reader));
+ closure->formatter = g_object_ref (formatter);
+
gconf_client_add_dir (
client, "/apps/evolution/mail/display",
GCONF_CLIENT_PRELOAD_NONE, NULL);
notify_id = gconf_client_notify_add (
client, "/apps/evolution/mail/display/headers",
(GConfClientNotifyFunc) headers_changed_cb,
- emf, NULL, NULL);
+ closure, (GFreeFunc) free_headers_changed_closure, NULL);
g_object_set_data_full (
- G_OBJECT (emf), "reader-header-notify-id",
+ G_OBJECT (formatter), "reader-header-notify-id",
GINT_TO_POINTER (notify_id), remove_header_notify_cb);
- headers_changed_cb (client, 0, NULL, emf);
+ headers_changed_cb (client, 0, NULL, closure);
g_object_unref (client);
}
+
+static GHashTable *
+mail_reader_get_mail_register (void)
+{
+ SoupSession *session;
+ GHashTable *mails;
+
+ session = webkit_get_default_session ();
+ mails = g_object_get_data (G_OBJECT (session), "mails");
+ if (!mails) {
+ mails = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
+ g_object_set_data_full (
+ G_OBJECT (session), "mails", mails,
+ (GDestroyNotify) g_hash_table_destroy);
+ }
+
+ return mails;
+}
+
+EMailPartList *
+e_mail_reader_lookup_part_list (EMailReader *reader,
+ const gchar *uri)
+{
+ GHashTable *mails;
+
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
+ g_return_val_if_fail (uri && *uri, NULL);
+
+ mails = mail_reader_get_mail_register ();
+ return g_hash_table_lookup (mails, uri);
+}
+
+struct _formatter_weak_ref_closure {
+ GHashTable *part_lists;
+ gchar *mail_uri;
+};
+
+static void
+part_list_weak_ref_cb (gchar *mail_uri,
+ EMailPartList *part_list)
+{
+ GHashTable *mails;
+
+ mails = mail_reader_get_mail_register ();
+
+ /* When this callback is called, the partslist is being finalized
+ * so we only remove it from the parts list table. */
+ g_hash_table_remove (mails, mail_uri);
+
+ d(printf("Destroying parts list %p (%s)\n", part_list, mail_uri));
+
+ g_free (mail_uri);
+}
+
+struct format_parser_async_closure_ {
+ EActivity *activity;
+ gchar *mail_uri;
+
+ GFunc user_callback;
+ gpointer user_data;
+};
+
+static void
+format_parser_async_done_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EMailParser *parser = E_MAIL_PARSER (source);
+ EMailPartList *part_list;
+ GHashTable *mails;
+ struct format_parser_async_closure_ *closure = user_data;
+
+ part_list = e_mail_parser_parse_finish (parser, result, NULL);
+
+ /* When no EMailDisplay holds reference to the part list, then
+ * the list can be destroyed. */
+ g_object_weak_ref (G_OBJECT (part_list),
+ (GWeakNotify) part_list_weak_ref_cb, g_strdup (closure->mail_uri));
+
+ mails = mail_reader_get_mail_register ();
+ g_hash_table_insert (mails, g_strdup (closure->mail_uri), part_list);
+ d(printf("Registered EMailPartList %s\n", closure->mail_uri));
+
+ if (closure->user_callback)
+ closure->user_callback (part_list, closure->user_data);
+
+ g_object_unref (closure->activity);
+ g_free (closure->mail_uri);
+ g_free (closure);
+
+ g_object_unref (result);
+ g_object_unref (parser);
+}
+
+void
+e_mail_reader_parse_message (EMailReader *reader,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GFunc ready_callback,
+ gpointer user_data)
+{
+ EMailParser *parser;
+ EMailBackend *mail_backend;
+ EMailSession *mail_session;
+ gchar *mail_uri;
+ struct format_parser_async_closure_ *closure;
+
+ mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
+
+ mail_backend = e_mail_reader_get_backend (reader);
+ mail_session = e_mail_backend_get_session (mail_backend);
+
+ closure = g_new0 (struct format_parser_async_closure_, 1);
+ parser = e_mail_parser_new (CAMEL_SESSION (mail_session));
+
+ closure->activity = e_mail_reader_new_activity (reader);
+ e_activity_set_text (closure->activity, _("Parsing message"));
+ closure->mail_uri = mail_uri;
+ closure->user_callback = ready_callback;
+ closure->user_data = user_data;
+
+ e_mail_parser_parse (parser, folder, message_uid,
+ message, format_parser_async_done_cb,
+ e_activity_get_cancellable (closure->activity),
+ closure);
+}
diff --git a/mail/e-mail-reader-utils.h b/mail/e-mail-reader-utils.h
index 6913d0964c..887e399451 100644
--- a/mail/e-mail-reader-utils.h
+++ b/mail/e-mail-reader-utils.h
@@ -68,7 +68,22 @@ gchar * e_mail_reader_header_to_xml (EMailReaderHeader *header);
void e_mail_reader_header_free (EMailReaderHeader *header);
void e_mail_reader_connect_headers (EMailReader *reader,
- EMFormat *emf);
+ EMailFormatter *formatter);
+
+EMailPartList * e_mail_reader_lookup_part_list (EMailReader *reader,
+ const gchar *uri);
+
+void e_mail_reader_store_part_list (EMailReader *reader,
+ const gchar *uri,
+ EMailPartList *part_list);
+
+void e_mail_reader_parse_message
+ (EMailReader *reader,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GFunc ready_callback,
+ gpointer user_data);
G_END_DECLS
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index af8a0eea94..3d0911b1fc 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -53,12 +53,15 @@
#include "mail/em-event.h"
#include "mail/em-folder-selector.h"
#include "mail/em-folder-tree.h"
-#include "mail/em-format-html-display.h"
#include "mail/em-utils.h"
#include "mail/mail-autofilter.h"
#include "mail/mail-vfolder-ui.h"
#include "mail/message-list.h"
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-part-utils.h>
+
#if HAVE_CLUTTER
#include <clutter/clutter.h>
#include <mx/mx.h>
@@ -69,7 +72,7 @@
((EMailReaderPrivate *) g_object_get_qdata \
(G_OBJECT (obj), quark_private))
-#define d(x)
+#define d(x) x
typedef struct _EMailReaderClosure EMailReaderClosure;
typedef struct _EMailReaderPrivate EMailReaderPrivate;
@@ -85,6 +88,8 @@ struct _EMailReaderPrivate {
EMailForwardStyle forward_style;
EMailReplyStyle reply_style;
+ EMailFormatter *formatter;
+
/* This timer runs when the user selects a single message. */
guint message_selected_timeout_id;
@@ -280,7 +285,7 @@ action_mail_image_save_cb (GtkAction *action,
{
EMailDisplay *display;
EWebView *web_view;
- EMFormat *emf;
+ EMailPartList *parts;
const gchar *image_src;
CamelMimePart *part;
EAttachment *attachment;
@@ -296,13 +301,13 @@ action_mail_image_save_cb (GtkAction *action,
if (!image_src)
return;
- emf = EM_FORMAT (e_mail_display_get_formatter (display));
- g_return_if_fail (emf != NULL);
- g_return_if_fail (emf->message != NULL);
+ parts = e_mail_display_get_parts_list (display);
+ g_return_if_fail (parts != NULL);
+ g_return_if_fail (parts->message != NULL);
if (g_str_has_prefix (image_src, "cid:")) {
part = camel_mime_message_get_part_by_content_id (
- emf->message, image_src + 4);
+ parts->message, image_src + 4);
g_return_if_fail (part != NULL);
g_object_ref (part);
@@ -371,20 +376,18 @@ action_mail_charset_cb (GtkRadioAction *action,
GtkRadioAction *current,
EMailReader *reader)
{
- EMailDisplay *display;
- EMFormatHTML *formatter;
+ EMailFormatter *formatter;
const gchar *charset;
if (action != current)
return;
- display = e_mail_reader_get_mail_display (reader);
- formatter = e_mail_display_get_formatter (display);
+ formatter = e_mail_reader_get_formatter (reader);
charset = g_object_get_data (G_OBJECT (action), "charset");
/* Charset for "Default" action will be NULL. */
if (formatter)
- em_format_set_charset (EM_FORMAT (formatter), charset);
+ e_mail_formatter_set_charset (formatter, charset);
}
static void
@@ -1711,9 +1714,9 @@ action_mail_show_all_headers_cb (GtkToggleAction *action,
display = e_mail_reader_get_mail_display (reader);
if (gtk_toggle_action_get_active (action))
- e_mail_display_set_mode (display, EM_FORMAT_WRITE_MODE_ALL_HEADERS);
+ e_mail_display_set_mode (display, E_MAIL_FORMATTER_MODE_ALL_HEADERS);
else
- e_mail_display_set_mode (display, EM_FORMAT_WRITE_MODE_NORMAL);
+ e_mail_display_set_mode (display, E_MAIL_FORMATTER_MODE_NORMAL);
}
struct _source_retrieval_closure {
@@ -1782,13 +1785,13 @@ action_mail_show_source_cb (GtkAction *action,
g_return_if_fail (uids != NULL && uids->len == 1);
message_uid = g_ptr_array_index (uids, 0);
- browser = e_mail_browser_new (backend, NULL, NULL, EM_FORMAT_WRITE_MODE_SOURCE);
+ browser = e_mail_browser_new (backend, NULL, NULL, E_MAIL_FORMATTER_MODE_SOURCE);
e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
string = g_strdup_printf (_("Retrieving message '%s'"), message_uid);
- e_mail_display_set_formatter (display, NULL);
+ e_mail_display_set_parts_list (display, NULL);
e_mail_display_set_status (display, string);
gtk_widget_show (browser);
@@ -2664,7 +2667,7 @@ mail_reader_message_seen_cb (EMailReaderClosure *closure)
{
EMailReader *reader;
GtkWidget *message_list;
- EMFormatHTML *formatter;
+ EMailPartList *parts;
EMailDisplay *display;
CamelMimeMessage *message;
const gchar *current_uid;
@@ -2675,7 +2678,7 @@ mail_reader_message_seen_cb (EMailReaderClosure *closure)
message_uid = closure->message_uid;
display = e_mail_reader_get_mail_display (reader);
- formatter = e_mail_display_get_formatter (display);
+ parts = e_mail_display_get_parts_list (display);
message_list = e_mail_reader_get_message_list (reader);
if (e_tree_is_dragging (E_TREE (message_list)))
@@ -2684,8 +2687,8 @@ mail_reader_message_seen_cb (EMailReaderClosure *closure)
current_uid = MESSAGE_LIST (message_list)->cursor_uid;
uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
- if (formatter)
- message = EM_FORMAT (formatter)->message;
+ if (parts)
+ message = parts->message;
else
message = NULL;
@@ -2846,7 +2849,7 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
CamelFolder *folder;
const gchar *cursor_uid;
const gchar *format_uid;
- EMFormat *formatter;
+ EMailPartList *parts;
priv = E_MAIL_READER_GET_PRIVATE (reader);
@@ -2854,10 +2857,10 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
message_list = e_mail_reader_get_message_list (reader);
display = e_mail_reader_get_mail_display (reader);
- formatter = EM_FORMAT (e_mail_display_get_formatter (display));
+ parts = e_mail_display_get_parts_list (display);
cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
- format_uid = formatter ? formatter->message_uid : NULL;
+ format_uid = parts ? parts->message_uid : NULL;
if (MESSAGE_LIST (message_list)->last_sel_single) {
GtkWidget *widget;
@@ -2877,7 +2880,7 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
gchar *string;
string = g_strdup_printf (_("Retrieving message '%s'"), cursor_uid);
- e_mail_display_set_formatter (display, NULL);
+ e_mail_display_set_parts_list (display, NULL);
e_mail_display_set_status (display, string);
g_free (string);
@@ -2900,7 +2903,7 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
priv->retrieving_message = g_object_ref (cancellable);
}
} else {
- e_mail_display_set_formatter (display, NULL);
+ e_mail_display_set_parts_list (display, NULL);
priv->restoring_message_selection = FALSE;
}
@@ -3100,52 +3103,25 @@ mail_reader_folder_loaded (EMailReader *reader)
e_mail_reader_update_actions (reader, state);
}
-struct _formatter_weak_ref_closure {
- GHashTable *formatters;
- gchar *mail_uri;
-};
-
-static void
-formatter_weak_ref_cb (struct _formatter_weak_ref_closure *data,
- EMFormat *formatter)
-{
- /* When this callback is called, the formatter is being finalized
- * so we only remove it from the formatters table. */
- g_hash_table_remove (data->formatters,
- data->mail_uri);
-
- d(printf("Destroying formatter %p (%s)\n", formatter, data->mail_uri));
-
- /* Destroying the formatter will prevent this callback
- * being called, so we can remove the closure data as well */
- g_hash_table_unref (data->formatters);
- g_free (data->mail_uri);
- g_free (data);
-}
-
struct format_parser_async_closure_ {
+ struct _formatter_weak_ref_closure *weak_ref_closure;
EMailDisplay *display;
EActivity *activity;
};
static void
-format_parser_async_done_cb (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+set_mail_display_part_list (EMailPartList *part_list,
+ gpointer user_data)
{
- EMFormat *emf = EM_FORMAT (source);
- struct format_parser_async_closure_ *closure = user_data;
-
- e_mail_display_set_formatter (closure->display, EM_FORMAT_HTML (emf));
- e_mail_display_load (closure->display, emf->uri_base);
+ EMailDisplay *display = user_data;
- g_object_unref (closure->activity);
- g_object_unref (closure->display);
- g_free (closure);
+ e_mail_display_set_parts_list (display, part_list);
+ e_mail_display_load (display, NULL);
- /* Remove the reference added when formatter was created,
+ g_object_unref (display);
+ /* Remove the reference added when parts list was created,
* so that only owners are EMailDisplays */
- g_object_unref (emf);
+ g_object_unref (part_list);
}
static void
@@ -3155,67 +3131,23 @@ mail_reader_set_display_formatter_for_message (EMailReader *reader,
CamelMimeMessage *message,
CamelFolder *folder)
{
- SoupSession *session;
- GHashTable *formatters;
- EMFormat *formatter;
+ EMailPartList *parts;
gchar *mail_uri;
- mail_uri = em_format_build_mail_uri (folder, message_uid, NULL, NULL);
+ mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
+ parts = e_mail_reader_lookup_part_list (reader, mail_uri);
+ g_free (mail_uri);
- session = webkit_get_default_session ();
- formatters = g_object_get_data (G_OBJECT (session), "formatters");
- if (!formatters) {
- formatters = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free, NULL);
- g_object_set_data_full (
- G_OBJECT (session), "formatters", formatters,
- (GDestroyNotify) g_hash_table_destroy);
- }
-
- if ((formatter = g_hash_table_lookup (formatters, mail_uri)) == NULL) {
- EMailBackend *mail_backend;
- EMailSession *mail_session;
- struct _formatter_weak_ref_closure *formatter_data =
- g_new0 (struct _formatter_weak_ref_closure, 1);
-
- struct format_parser_async_closure_ *closure;
-
- formatter_data->formatters = g_hash_table_ref (formatters);
- formatter_data->mail_uri = g_strdup (mail_uri);
-
- mail_backend = e_mail_reader_get_backend (reader);
- mail_session = e_mail_backend_get_session (mail_backend);
-
- formatter = EM_FORMAT (
- em_format_html_display_new (
- CAMEL_SESSION (mail_session)));
-
- /* When no EMailDisplay holds reference to the formatter, then
- * the formatter can be destroyed. */
- g_object_weak_ref (G_OBJECT (formatter),
- (GWeakNotify) formatter_weak_ref_cb, formatter_data);
-
- formatter->message_uid = g_strdup (message_uid);
- formatter->uri_base = g_strdup (mail_uri);
-
- e_mail_reader_connect_headers (reader, formatter);
+ if (parts == NULL) {
- closure = g_new0 (struct format_parser_async_closure_, 1);
- closure->activity = e_mail_reader_new_activity (reader);
- e_activity_set_text (closure->activity, _("Parsing message"));
- closure->display = g_object_ref (display);
+ e_mail_reader_parse_message (
+ reader, folder, message_uid, message,
+ (GFunc) set_mail_display_part_list,
+ g_object_ref (display));
- em_format_parse_async (formatter, message, folder,
- e_activity_get_cancellable (closure->activity),
- format_parser_async_done_cb, closure);
-
- /* Don't free the mail_uri!! */
- g_hash_table_insert (formatters, mail_uri, formatter);
} else {
- e_mail_display_set_formatter (display, EM_FORMAT_HTML (formatter));
- e_mail_display_load (display, formatter->uri_base);
-
- g_free (mail_uri);
+ e_mail_display_set_parts_list (display, parts);
+ e_mail_display_load (display, NULL);
}
}
@@ -3895,6 +3827,12 @@ e_mail_reader_init (EMailReader *reader,
message_list = e_mail_reader_get_message_list (reader);
display = e_mail_reader_get_mail_display (reader);
+ /* Initialize a private struct. */
+ g_object_set_qdata_full (
+ G_OBJECT (reader), quark_private,
+ g_slice_new0 (EMailReaderPrivate),
+ (GDestroyNotify) mail_reader_private_free);
+
if (!init_actions)
goto connect_signals;
@@ -4114,7 +4052,7 @@ e_mail_reader_init (EMailReader *reader,
connect_signals:
if (!connect_signals)
- goto init_private;
+ return;
/* Connect signals. */
g_signal_connect_swapped (
@@ -4158,15 +4096,6 @@ connect_signals:
g_signal_connect_swapped (
message_list, "selection-change",
G_CALLBACK (e_mail_reader_changed), reader);
-
-init_private:
-
- /* Initialize a private struct. */
-
- g_object_set_qdata_full (
- G_OBJECT (reader), quark_private,
- g_slice_new0 (EMailReaderPrivate),
- (GDestroyNotify) mail_reader_private_free);
}
void
@@ -4805,3 +4734,39 @@ e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader)
priv->avoid_next_mark_as_seen = TRUE;
}
+
+EMailFormatter *
+e_mail_reader_get_formatter (EMailReader *reader)
+{
+ EMailReaderPrivate *priv;
+
+ g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
+
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
+ g_return_val_if_fail (priv != NULL, NULL);
+
+ return priv->formatter;
+}
+
+void
+e_mail_reader_set_formatter (EMailReader *reader,
+ EMailFormatter *formatter)
+{
+ EMailReaderPrivate *priv;
+
+ g_return_if_fail (E_IS_MAIL_READER (reader));
+ g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
+
+ priv = E_MAIL_READER_GET_PRIVATE (reader);
+ g_return_if_fail (priv != NULL);
+
+ g_object_ref (formatter);
+
+ if (priv->formatter) {
+ g_object_unref (priv->formatter);
+ }
+
+ priv->formatter = formatter;
+
+ e_mail_reader_connect_headers (reader, formatter);
+}
diff --git a/mail/e-mail-reader.h b/mail/e-mail-reader.h
index 6f03fc0cfe..b33aee7554 100644
--- a/mail/e-mail-reader.h
+++ b/mail/e-mail-reader.h
@@ -179,6 +179,10 @@ void e_mail_reader_enable_show_folder
void e_mail_reader_avoid_next_mark_as_seen
(EMailReader *reader);
+EMailFormatter * e_mail_reader_get_formatter (EMailReader *reader);
+void e_mail_reader_set_formatter (EMailReader *reader,
+ EMailFormatter *formatter);
+
G_END_DECLS
#endif /* E_MAIL_READER_H */
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 7522bc5e7e..01c114405d 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -24,10 +24,14 @@
#include <libsoup/soup-requester.h>
#include <libsoup/soup-request-http.h>
+#include <webkit/webkit.h>
+
#include <glib/gi18n.h>
#include <camel/camel.h>
-#include "em-format-html.h"
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-formatter-utils.h>
+#include <em-format/e-mail-formatter-print.h>
#include <e-util/e-icon-factory.h>
#include <e-util/e-util.h>
@@ -40,15 +44,13 @@
((obj), E_TYPE_MAIL_REQUEST, EMailRequestPrivate))
struct _EMailRequestPrivate {
- EMFormatHTML *efh;
-
CamelStream *output_stream;
- EMFormatPURI *puri;
gchar *mime_type;
gint content_length;
GHashTable *uri_query;
+ gchar *uri_base;
gchar *ret_mime_type;
};
@@ -61,14 +63,17 @@ handle_mail_request (GSimpleAsyncResult *res,
GCancellable *cancellable)
{
EMailRequest *request = E_MAIL_REQUEST (object);
- EMFormatHTML *efh = request->priv->efh;
- EMFormat *emf = EM_FORMAT (efh);
GInputStream *stream;
+ EMailFormatter *formatter;
+ EMailPartList *part_list;
+ SoupSession *session;
+ GHashTable *mails;
GByteArray *ba;
gchar *part_id;
- EMFormatWriterInfo info = {0};
gchar *val;
+ EMailFormatterContext context = { 0 };
+
if (g_cancellable_is_cancelled (cancellable))
return;
@@ -76,39 +81,67 @@ handle_mail_request (GSimpleAsyncResult *res,
g_object_unref (request->priv->output_stream);
}
+ session = webkit_get_default_session ();
+ mails = g_object_get_data (G_OBJECT (session), "mails");
+ part_list = g_hash_table_lookup (mails, request->priv->uri_base);
+ g_return_if_fail (part_list != NULL);
+
request->priv->output_stream = camel_stream_mem_new ();
val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsed");
- if (val)
- info.headers_collapsed = atoi (val);
+ if (val && atoi (val) == 1)
+ context.flags |= E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSED;
val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsable");
- if (val)
- info.headers_collapsable = atoi (val);
+ if (val && atoi (val) == 1)
+ context.flags |= E_MAIL_FORMATTER_HEADER_FLAG_COLLAPSABLE;
val = g_hash_table_lookup (request->priv->uri_query, "mode");
if (val)
- info.mode = atoi (val);
+ context.mode = atoi (val);
+
+ context.message = part_list->message;
+ context.message_uid = part_list->message_uid;
+ context.folder = part_list->folder;
+ context.parts = part_list->list;
+
+ if (context.mode == E_MAIL_FORMATTER_MODE_PRINTING)
+ formatter = e_mail_formatter_print_new ();
+ else
+ formatter = e_mail_formatter_new ();
part_id = g_hash_table_lookup (request->priv->uri_query, "part_id");
if (part_id) {
+ EMailPart *part;
+ const gchar *mime_type;
/* original part_id is owned by the GHashTable */
part_id = soup_uri_decode (part_id);
- request->priv->puri = em_format_find_puri (emf, part_id);
+ part = e_mail_part_list_find_part (part_list, part_id);
- if (request->priv->puri) {
- em_format_puri_write (request->priv->puri,
- request->priv->output_stream, &info, cancellable);
+ val = g_hash_table_lookup (request->priv->uri_query, "mime_type");
+ if (val) {
+ mime_type = val;
+ } else {
+ mime_type = NULL;
+ }
+
+ if (context.mode == E_MAIL_FORMATTER_MODE_SOURCE) {
+ mime_type = "application/vnd.evolution.source";
+ }
+
+ if (part) {
+ e_mail_formatter_format_as (
+ formatter, &context, part, request->priv->output_stream,
+ mime_type ? mime_type : part->mime_type, cancellable);
} else {
g_warning ("Failed to lookup requested part '%s' - this should not happen!", part_id);
}
g_free (part_id);
} else {
- if (info.mode == 0)
- info.mode = EM_FORMAT_WRITE_MODE_NORMAL;
-
- em_format_write (emf, request->priv->output_stream, &info, cancellable);
+ e_mail_formatter_format_sync (
+ formatter, part_list, request->priv->output_stream,
+ context.flags, context.mode, cancellable);
}
/* Convert the GString to GInputStream and send it back to WebKit */
@@ -136,10 +169,7 @@ mail_request_finalize (GObject *object)
{
EMailRequest *request = E_MAIL_REQUEST (object);
- if (request->priv->output_stream) {
- g_object_unref (request->priv->output_stream);
- request->priv->output_stream = NULL;
- }
+ g_clear_object (&request->priv->output_stream);
if (request->priv->mime_type) {
g_free (request->priv->mime_type);
@@ -156,9 +186,9 @@ mail_request_finalize (GObject *object)
request->priv->ret_mime_type = NULL;
}
- if (request->priv->efh) {
- g_object_unref (request->priv->efh);
- request->priv->efh = NULL;
+ if (request->priv->uri_base) {
+ g_free (request->priv->uri_base);
+ request->priv->uri_base = NULL;
}
G_OBJECT_CLASS (e_mail_request_parent_class)->finalize (object);
@@ -178,14 +208,11 @@ mail_request_send_async (SoupRequest *request,
GAsyncReadyCallback callback,
gpointer user_data)
{
- SoupSession *session;
EMailRequest *emr = E_MAIL_REQUEST (request);
GSimpleAsyncResult *simple;
SoupURI *uri;
- GHashTable *formatters;
gchar *uri_str;
- session = soup_request_get_session (request);
uri = soup_request_get_uri (request);
d(printf("received request for %s\n", soup_uri_to_string (uri, FALSE)));
@@ -196,18 +223,9 @@ mail_request_send_async (SoupRequest *request,
emr->priv->uri_query = NULL;
}
- formatters = g_object_get_data (G_OBJECT (session), "formatters");
- g_return_if_fail (formatters != NULL);
-
uri_str = g_strdup_printf (
"%s://%s%s", uri->scheme, uri->host, uri->path);
- emr->priv->efh = g_hash_table_lookup (formatters, uri_str);
- g_free (uri_str);
-
- g_return_if_fail (emr->priv->efh);
-
- /* Make sure the formatter lives until we are finished here */
- g_object_ref (emr->priv->efh);
+ emr->priv->uri_base = uri_str;
simple = g_simple_async_result_new (
G_OBJECT (request), callback,
@@ -229,10 +247,11 @@ mail_request_send_finish (SoupRequest *request,
{
GInputStream *stream;
- stream = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ stream = g_simple_async_result_get_op_res_gpointer (
+ G_SIMPLE_ASYNC_RESULT (result));
/* Reset the stream before passing it back to webkit */
- if (stream && G_IS_SEEKABLE (stream))
+ if (G_IS_INPUT_STREAM (stream) && G_IS_SEEKABLE (stream))
g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
if (!stream) /* We must always return something */
@@ -269,13 +288,8 @@ mail_request_get_content_type (SoupRequest *request)
if (emr->priv->mime_type) {
mime_type = g_strdup (emr->priv->mime_type);
- } else if (!emr->priv->puri) {
- mime_type = g_strdup ("text/html");
- } else if (!emr->priv->puri->mime_type) {
- CamelContentType *ct = camel_mime_part_get_content_type (emr->priv->puri->part);
- mime_type = camel_content_type_simple (ct);
} else {
- mime_type = g_strdup (emr->priv->puri->mime_type);
+ mime_type = g_strdup ("text/html");
}
if (g_strcmp0 (mime_type, "text/html") == 0) {
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 4fe141447a..71754a6d0d 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -43,6 +43,9 @@
#include <libemail-engine/mail-ops.h>
#include <libemail-engine/mail-tools.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-formatter-quote.h>
+
#include <shell/e-shell.h>
#include <composer/e-msg-composer.h>
@@ -54,10 +57,6 @@
#include "em-composer-utils.h"
#include "em-folder-selector.h"
#include "em-folder-tree.h"
-#include "em-format-html.h"
-#include "em-format-html-print.h"
-#include "em-format-html-display.h"
-#include "em-format-quote.h"
#include "em-event.h"
#include "mail-send-recv.h"
@@ -958,8 +957,6 @@ composer_print_done_cb (EMailPrinter *emp,
GtkPrintOperationResult result,
gpointer user_data)
{
- EMFormat *emf = user_data;
- g_object_unref (emf);
g_object_unref (emp);
}
@@ -971,23 +968,23 @@ em_utils_composer_print_cb (EMsgComposer *composer,
EMailSession *session)
{
EMailPrinter *emp;
- EMFormatHTMLDisplay *efhd;
+ EMailParser *parser;
+ EMailPartList *parts;
const gchar *message_id;
- efhd = em_format_html_display_new (CAMEL_SESSION (session));
+ parser = e_mail_parser_new (CAMEL_SESSION (session));
message_id = camel_mime_message_get_message_id (message);
- ((EMFormat *) efhd)->message_uid = g_strdup (message_id);
-
- /* Parse the message */
- em_format_parse ((EMFormat *) efhd, message, NULL, NULL);
+ parts = e_mail_parser_parse_sync (parser, NULL, g_strdup (message_id), message, NULL);
/* Use EMailPrinter and WebKit to print the message */
- emp = e_mail_printer_new ((EMFormatHTML *) efhd);
+ emp = e_mail_printer_new (parts);
g_signal_connect (emp, "done",
- G_CALLBACK (composer_print_done_cb), efhd);
+ G_CALLBACK (composer_print_done_cb), NULL);
e_mail_printer_print (emp, FALSE, NULL);
+
+ g_object_unref (parts);
}
/* Composing messages... */
@@ -1543,13 +1540,13 @@ emu_update_composers_security (EMsgComposer *composer,
shell_settings = e_shell_get_shell_settings (shell);
sign_by_default =
- (validity_found & EM_FORMAT_VALIDITY_FOUND_SIGNED) != 0 &&
+ (validity_found & E_MAIL_PART_VALIDITY_SIGNED) != 0 &&
e_shell_settings_get_boolean (
shell_settings, "composer-sign-reply-if-signed");
/* Pre-set only for encrypted messages, not for signed */
if (sign_by_default) {
- if (validity_found & EM_FORMAT_VALIDITY_FOUND_SMIME)
+ if (validity_found & E_MAIL_PART_VALIDITY_SMIME)
action = E_COMPOSER_ACTION_SMIME_SIGN (composer);
else
action = E_COMPOSER_ACTION_PGP_SIGN (composer);
@@ -1558,8 +1555,8 @@ emu_update_composers_security (EMsgComposer *composer,
GTK_TOGGLE_ACTION (action), TRUE);
}
- if (validity_found & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED) {
- if (validity_found & EM_FORMAT_VALIDITY_FOUND_SMIME)
+ if (validity_found & E_MAIL_PART_VALIDITY_ENCRYPTED) {
+ if (validity_found & E_MAIL_PART_VALIDITY_SMIME)
action = E_COMPOSER_ACTION_SMIME_ENCRYPT (composer);
else
action = E_COMPOSER_ACTION_PGP_ENCRYPT (composer);
@@ -1703,9 +1700,9 @@ forward_non_attached (EShell *shell,
guint32 validity_found = 0;
guint32 flags;
- flags = EM_FORMAT_QUOTE_HEADERS | EM_FORMAT_QUOTE_KEEP_SIG;
+ flags = E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS | E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG;
if (style == E_MAIL_FORWARD_STYLE_QUOTED)
- flags |= EM_FORMAT_QUOTE_CITE;
+ flags |= E_MAIL_FORMATTER_QUOTE_FLAG_CITE;
forward = quoting_text (QUOTING_FORWARD);
text = em_utils_message_to_html (
@@ -2760,7 +2757,7 @@ static void
composer_set_body (EMsgComposer *composer,
CamelMimeMessage *message,
EMailReplyStyle style,
- EMFormat *source)
+ EMailPartList *parts_list)
{
gchar *text, *credits, *original;
CamelMimePart *part;
@@ -2788,8 +2785,8 @@ composer_set_body (EMsgComposer *composer,
case E_MAIL_REPLY_STYLE_OUTLOOK:
original = quoting_text (QUOTING_ORIGINAL);
text = em_utils_message_to_html (
- session, message, original, EM_FORMAT_QUOTE_HEADERS,
- source, start_bottom ? "<BR>" : NULL, &validity_found);
+ session, message, original, E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS,
+ parts_list, start_bottom ? "<BR>" : NULL, &validity_found);
e_msg_composer_set_body_text (composer, text, TRUE);
has_body_text = text && *text;
g_free (text);
@@ -2802,8 +2799,8 @@ composer_set_body (EMsgComposer *composer,
/* do what any sane user would want when replying... */
credits = attribution_format (message);
text = em_utils_message_to_html (
- session, message, credits, EM_FORMAT_QUOTE_CITE,
- source, start_bottom ? "<BR>" : NULL, &validity_found);
+ session, message, credits, E_MAIL_FORMATTER_QUOTE_FLAG_CITE,
+ parts_list, start_bottom ? "<BR>" : NULL, &validity_found);
g_free (credits);
e_msg_composer_set_body_text (composer, text, TRUE);
has_body_text = text && *text;
@@ -2842,7 +2839,7 @@ composer_set_body (EMsgComposer *composer,
gchar *
em_utils_construct_composer_text (CamelSession *session,
CamelMimeMessage *message,
- EMFormat *source)
+ EMailPartList *parts_list)
{
gchar *text, *credits;
gboolean start_bottom = 0;
@@ -2851,8 +2848,8 @@ em_utils_construct_composer_text (CamelSession *session,
credits = attribution_format (message);
text = em_utils_message_to_html (
- session, message, credits, EM_FORMAT_QUOTE_CITE,
- source, start_bottom ? "<BR>" : NULL, NULL);
+ session, message, credits, E_MAIL_FORMATTER_QUOTE_FLAG_CITE,
+ parts_list, start_bottom ? "<BR>" : NULL, NULL);
g_free (credits);
return text;
@@ -2881,7 +2878,7 @@ em_utils_reply_to_message (EShell *shell,
const gchar *message_uid,
EMailReplyType type,
EMailReplyStyle style,
- EMFormat *source_formatter,
+ EMailPartList *parts_list,
CamelInternetAddress *address)
{
ESourceRegistry *registry;
@@ -2956,7 +2953,7 @@ em_utils_reply_to_message (EShell *shell,
g_object_unref (to);
g_object_unref (cc);
- composer_set_body (composer, message, style, source_formatter);
+ composer_set_body (composer, message, style, parts_list);
if (folder != NULL) {
gchar *folder_uri;
diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h
index a525cec2a2..93d87bfb2e 100644
--- a/mail/em-composer-utils.h
+++ b/mail/em-composer-utils.h
@@ -24,7 +24,7 @@
#ifndef EM_COMPOSER_UTILS_H
#define EM_COMPOSER_UTILS_H
-#include <em-format/em-format.h>
+#include <em-format/e-mail-part.h>
#include <mail/e-mail-backend.h>
#include <mail/e-mail-reader.h>
#include <composer/e-msg-composer.h>
@@ -62,7 +62,7 @@ void em_utils_redirect_message (EShell *shell,
gchar * em_utils_construct_composer_text
(CamelSession *session,
CamelMimeMessage *message,
- EMFormat *source_formatter);
+ EMailPartList *source_formatter);
gboolean em_utils_is_munged_list_message (CamelMimeMessage *message);
void em_utils_get_reply_sender (CamelMimeMessage *message,
CamelInternetAddress *to,
@@ -78,7 +78,7 @@ EMsgComposer * em_utils_reply_to_message (EShell *shell,
const gchar *message_uid,
EMailReplyType type,
EMailReplyStyle style,
- EMFormat *source,
+ EMailPartList *source,
CamelInternetAddress *address);
EDestination ** em_utils_camel_address_to_destination
(CamelInternetAddress *iaddr);
diff --git a/mail/em-format-hook.c b/mail/em-format-hook.c
deleted file mode 100644
index 7ceeb20e4d..0000000000
--- a/mail/em-format-hook.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "em-format-hook.h"
-
-#include <glib/gi18n.h>
-
-/* class name -> class map for EMFormat and subclasses */
-static GHashTable *emfh_types;
-
-/* ********************************************************************** */
-
-/* Mail formatter handler plugin */
-
-/*
- * <hook class="org.gnome.evolution.mail.format:1.0">
- * <group id="EMFormatHTML">
- * <item flags="inline,inline_disposition"
- * mime_type="text/vcard"
- * format="format_vcard"/>
- * </group>
- * </hook>
- */
-
-#define emfh ((EMFormatHook *)eph)
-
-#define d(x)
-
-static const EPluginHookTargetKey emfh_flag_map[] = {
- { "inline", EM_FORMAT_HANDLER_INLINE },
- { "inline_disposition", EM_FORMAT_HANDLER_INLINE_DISPOSITION },
- { NULL }
-};
-
-G_DEFINE_TYPE (EMFormatHook, em_format_hook, E_TYPE_PLUGIN_HOOK)
-
-static void
-emfh_parse_part (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- struct _EMFormatHookItem *item = (EMFormatHookItem *) info->handler;
-
- if (item->hook->hook.plugin->enabled) {
- EMFormatHookTarget target = {
- emf, part, part_id, info
- };
-
- e_plugin_invoke (item->hook->hook.plugin, item->format, &target);
- } else if (info->handler->old) {
- info->handler->old->parse_func (
- emf, part, part_id, info, cancellable);
- }
-}
-
-static void
-emfh_free_item (struct _EMFormatHookItem *item)
-{
- /* FIXME: remove from formatter class */
-
- g_free (item->handler.mime_type);
- g_free (item->format);
- g_free (item);
-}
-
-static void
-emfh_free_group (struct _EMFormatHookGroup *group)
-{
- g_slist_foreach (group->items, (GFunc) emfh_free_item, NULL);
- g_slist_free (group->items);
-
- g_free (group->id);
- g_free (group);
-}
-
-static struct _EMFormatHookItem *
-emfh_construct_item (EPluginHook *eph,
- EMFormatHookGroup *group,
- xmlNodePtr root)
-{
- struct _EMFormatHookItem *item;
-
- d(printf(" loading group item\n"));
- item = g_malloc0 (sizeof (*item));
-
- item->handler.mime_type = e_plugin_xml_prop(root, "mime_type");
- item->handler.flags = e_plugin_hook_mask(root, emfh_flag_map, "flags");
- item->format = e_plugin_xml_prop(root, "format");
-
- item->handler.parse_func = emfh_parse_part;
- item->hook = emfh;
-
- if (item->handler.mime_type == NULL || item->format == NULL)
- goto error;
-
- d(printf(" type='%s' format='%s'\n", item->handler.mime_type, item->format));
-
- return item;
-error:
- d(printf("error!\n"));
- emfh_free_item (item);
- return NULL;
-}
-
-static struct _EMFormatHookGroup *
-emfh_construct_group (EPluginHook *eph,
- xmlNodePtr root)
-{
- struct _EMFormatHookGroup *group;
- xmlNodePtr node;
-
- d(printf(" loading group\n"));
- group = g_malloc0 (sizeof (*group));
-
- group->id = e_plugin_xml_prop(root, "id");
- if (group->id == NULL)
- goto error;
-
- node = root->children;
- while (node) {
- if (0 == strcmp((gchar *)node->name, "item")) {
- struct _EMFormatHookItem *item;
-
- item = emfh_construct_item (eph, group, node);
- if (item)
- group->items = g_slist_append (group->items, item);
- }
- node = node->next;
- }
-
- return group;
-error:
- emfh_free_group (group);
- return NULL;
-}
-
-static gint
-emfh_construct (EPluginHook *eph,
- EPlugin *ep,
- xmlNodePtr root)
-{
- xmlNodePtr node;
-
- d(printf("loading format hook\n"));
-
- if (((EPluginHookClass *) em_format_hook_parent_class)->
- construct (eph, ep, root) == -1)
- return -1;
-
- node = root->children;
- while (node) {
- if (strcmp((gchar *)node->name, "group") == 0) {
- struct _EMFormatHookGroup *group;
-
- group = emfh_construct_group (eph, node);
- if (group) {
- EMFormatClass *class;
-
- if (emfh_types
- && (class = g_hash_table_lookup (emfh_types, group->id))) {
- GSList *l = group->items;
-
- for (; l; l = g_slist_next (l)) {
- EMFormatHookItem *item = l->data;
- /* TODO: only add handlers if enabled? */
- /* Well, disabling is handled by the callback,
- * if we leave as is, then we can enable the
- * plugin after startup and it will start
- * working automagically */
- em_format_class_add_handler (class, &item->handler);
- }
- }
- /* We don't actually need to keep this
- * around once its set on the class. */
- emfh->groups = g_slist_append (emfh->groups, group);
- }
- }
- node = node->next;
- }
-
- eph->plugin = ep;
-
- /* Load the plugin as it does a few thing in the formatter thread. */
- ((EPluginClass *) G_OBJECT_GET_CLASS (ep))->enable (ep, 1);
- return 0;
-}
-
-static void
-emfh_enable (EPluginHook *eph,
- gint state)
-{
- GSList *g, *l;
- EMFormatClass *class;
-
- g = emfh->groups;
- if (emfh_types == NULL)
- return;
-
- for (; g; g = g_slist_next (g)) {
- struct _EMFormatHookGroup *group = g->data;
-
- class = g_hash_table_lookup (emfh_types, group->id);
- for (l = group->items; l; l = g_slist_next (l)) {
- EMFormatHookItem *item = l->data;
-
- if (state)
- em_format_class_add_handler (class, &item->handler);
- else
- em_format_class_remove_handler (class, &item->handler);
- }
- }
-}
-
-static void
-format_hook_finalize (GObject *object)
-{
- EPluginHook *eph = (EPluginHook *) object;
-
- g_slist_foreach (emfh->groups, (GFunc) emfh_free_group, NULL);
- g_slist_free (emfh->groups);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (em_format_hook_parent_class)->finalize (object);
-}
-
-static void
-em_format_hook_class_init (EMFormatHookClass *class)
-{
- GObjectClass *object_class;
- EPluginHookClass *hook_class;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = format_hook_finalize;
-
- hook_class = E_PLUGIN_HOOK_CLASS (class);
- hook_class->construct = emfh_construct;
- hook_class->enable = emfh_enable;
- hook_class->id = "org.gnome.evolution.mail.format:1.0";
-}
-
-static void
-em_format_hook_init (EMFormatHook *hook)
-{
-}
-
-void
-em_format_hook_register_type (GType type)
-{
- EMFormatClass *class;
-
- if (emfh_types == NULL)
- emfh_types = g_hash_table_new (g_str_hash, g_str_equal);
-
- d(printf("registering formatter type '%s'\n", g_type_name(type)));
-
- class = g_type_class_ref (type);
- g_hash_table_insert (emfh_types, (gpointer) g_type_name (type), class);
-}
diff --git a/mail/em-format-hook.h b/mail/em-format-hook.h
deleted file mode 100644
index 09076c2f48..0000000000
--- a/mail/em-format-hook.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michel Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __EM_FORMAT_HOOK_H__
-#define __EM_FORMAT_HOOK_H__
-
-#include <e-util/e-plugin.h>
-#include <em-format/em-format.h>
-
-G_BEGIN_DECLS
-
-typedef struct _EMFormatHookItem EMFormatHookItem;
-typedef struct _EMFormatHookGroup EMFormatHookGroup;
-typedef struct _EMFormatHook EMFormatHook;
-typedef struct _EMFormatHookClass EMFormatHookClass;
-
-typedef struct _EMFormatHookTarget EMFormatHookTarget;
-
-typedef void (*EMFormatHookFunc)(struct _EPlugin *plugin, EMFormatHookTarget *data);
-
-struct _EMFormatHookTarget {
- struct _EMFormat *format;
- CamelMimePart *part;
- GString *part_id;
- EMFormatParserInfo *info;
-};
-
-struct _EMFormatHookItem {
- EMFormatHandler handler;
-
- struct _EMFormatHook *hook; /* parent pointer */
- gchar *format; /* format handler */
-};
-
-struct _EMFormatHookGroup {
- struct _EMFormatHook *hook; /* parent pointer */
- gchar *id; /* target formatter id */
- GSList *items; /* items to consider */
-};
-
-/**
- * struct _EMFormatHook - Mail formatter hook.
- *
- * @hook:
- * @groups:
- *
- * The Mail formatter hook links all of the plugin formatter hooks
- * into the relevent formatter classes.
- **/
-struct _EMFormatHook {
- EPluginHook hook;
-
- GSList *groups;
-};
-
-struct _EMFormatHookClass {
- EPluginHookClass hook_class;
-
- /* which class to add matching items to */
- GHashTable *format_classes;
-};
-
-GType em_format_hook_get_type (void);
-
-/* register a type as a possible formatter hook point */
-void em_format_hook_register_type (GType type);
-
-G_END_DECLS
-
-#endif /* __EM_FORMAT_HOOK_H__ */
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
deleted file mode 100644
index efa5881542..0000000000
--- a/mail/em-format-html-display.c
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glib/gstdio.h>
-#include <gdk/gdkkeysyms.h>
-
-#ifdef G_OS_WIN32
-/* Work around 'DATADIR' and 'interface' lossage in <windows.h> */
-#define DATADIR crap_DATADIR
-#include <windows.h>
-#undef DATADIR
-#undef interface
-#endif
-
-#include <glib/gi18n.h>
-
-#include <e-util/e-util.h>
-#include <e-util/e-util-private.h>
-
-#include "e-util/e-datetime-format.h"
-#include <e-util/e-dialog-utils.h>
-#include <e-util/e-icon-factory.h>
-
-#include <shell/e-shell.h>
-#include <shell/e-shell-utils.h>
-
-#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
-#include "certificate-viewer.h"
-#include "e-cert-db.h"
-#endif
-
-#include "e-mail-display.h"
-#include "e-mail-attachment-bar.h"
-#include "em-format-html-display.h"
-#include "em-utils.h"
-#include "widgets/misc/e-attachment.h"
-#include "widgets/misc/e-attachment-button.h"
-#include "widgets/misc/e-attachment-view.h"
-#include "shell/e-shell.h"
-#include "shell/e-shell-window.h"
-
-#define EM_FORMAT_HTML_DISPLAY_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayPrivate))
-
-#define d(x)
-
-#define EM_FORMAT_HTML_DISPLAY_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayPrivate))
-
-struct _EMFormatHTMLDisplayPrivate {
-
- EAttachmentView *last_view;
-
-};
-
-/* TODO: move the dialogue elsehwere */
-/* FIXME: also in em-format-html.c */
-static const struct {
- const gchar *icon, *shortdesc, *description;
-} smime_sign_table[5] = {
- { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") },
- { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") },
- { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") },
- { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") },
- { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") },
-
-};
-
-static const struct {
- const gchar *icon, *shortdesc, *description;
-} smime_encrypt_table[4] = {
- { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") },
- { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") },
- { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") },
- { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") },
-};
-
-static const GdkRGBA smime_sign_colour[5] = {
- { 0 }, { 0.53, 0.73, 0.53, 1 }, { 0.73, 0.53, 0.53, 1 }, { 0.91, 0.82, 0.13, 1 }, { 0 },
-};
-
-static void efhd_message_prefix (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efhd_message_add_bar (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efhd_parse_attachment (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efhd_parse_secure (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-
-static GtkWidget * efhd_attachment_bar (EMFormat *emf, EMFormatPURI *puri, GCancellable *cancellable);
-static GtkWidget * efhd_attachment_button (EMFormat *emf, EMFormatPURI *puri, GCancellable *cancellable);
-
-static void efhd_write_attachment_bar (EMFormat *emf, EMFormatPURI *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhd_write_attachment (EMFormat *emf, EMFormatPURI *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhd_write_secure_button (EMFormat *emf, EMFormatPURI *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-static void efhd_free_attach_puri_data (EMFormatPURI *puri);
-
-static void efhd_builtin_init (EMFormatHTMLDisplayClass *efhc);
-
-static gpointer parent_class;
-
-static EAttachmentStore *
-find_parent_attachment_store (EMFormatHTMLDisplay *efhd,
- const gchar *part_id)
-{
- EMFormat *emf = (EMFormat *) efhd;
- EMFormatAttachmentBarPURI *abp;
- gchar *tmp, *pos;
- GList *item;
-
- tmp = g_strdup (part_id);
-
- do {
- gchar *id;
-
- pos = g_strrstr (tmp, ".");
- if (!pos)
- break;
-
- g_free (tmp);
- tmp = g_strndup (part_id, pos - tmp);
- id = g_strdup_printf ("%s.attachment-bar", tmp);
-
- item = g_hash_table_lookup (emf->mail_part_table, id);
-
- g_free (id);
-
- } while (pos && !item);
-
- g_free (tmp);
-
- abp = (EMFormatAttachmentBarPURI *) item->data;
-
- if (abp)
- return abp->store;
- else
- return NULL;
-}
-
-static void
-efhd_attachment_bar_puri_free (EMFormatPURI *puri)
-{
- EMFormatAttachmentBarPURI *abp;
-
- abp = (EMFormatAttachmentBarPURI *) puri;
-
- if (abp->store) {
- g_object_unref (abp->store);
- abp->store = NULL;
- }
-}
-
-static void
-efhd_xpkcs7mime_free (EMFormatPURI *puri)
-{
- EMFormatSMIMEPURI *sp = (EMFormatSMIMEPURI *) puri;
-
- if (sp->widget)
- gtk_widget_destroy (sp->widget);
-
- if (sp->description)
- g_free (sp->description);
-
- if (sp->valid)
- camel_cipher_validity_free (sp->valid);
-}
-
-static void
-efhd_xpkcs7mime_info_response (GtkWidget *widget,
- guint button,
- EMFormatSMIMEPURI *po)
-{
- gtk_widget_destroy (widget);
- po->widget = NULL;
-}
-
-#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
-static void
-efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
- EMFormatSMIMEPURI *po)
-{
- CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info");
- ECert *ec = NULL;
-
- if (info->cert_data)
- ec = e_cert_new (CERT_DupCertificate (info->cert_data));
-
- if (ec != NULL) {
- GtkWidget *w = certificate_viewer_show (ec);
-
- /* oddly enough certificate_viewer_show doesn't ... */
- gtk_widget_show (w);
- g_signal_connect (
- w, "response",
- G_CALLBACK (gtk_widget_destroy), NULL);
-
- if (w && po->widget)
- gtk_window_set_transient_for ((GtkWindow *) w, (GtkWindow *) po->widget);
-
- g_object_unref (ec);
- } else {
- g_warning("can't find certificate for %s <%s>", info->name?info->name:"", info->email?info->email:"");
- }
-}
-#endif
-
-static void
-efhd_xpkcs7mime_add_cert_table (GtkWidget *grid,
- GQueue *certlist,
- EMFormatSMIMEPURI *po)
-{
- GList *head, *link;
- GtkTable *table;
- gint n = 0;
-
- table = (GtkTable *) gtk_table_new (certlist->length, 2, FALSE);
-
- head = g_queue_peek_head_link (certlist);
-
- for (link = head; link != NULL; link = g_list_next (link)) {
- CamelCipherCertInfo *info = link->data;
- gchar *la = NULL;
- const gchar *l = NULL;
-
- if (info->name) {
- if (info->email && strcmp (info->name, info->email) != 0)
- l = la = g_strdup_printf("%s <%s>", info->name, info->email);
- else
- l = info->name;
- } else {
- if (info->email)
- l = info->email;
- }
-
- if (l) {
- GtkWidget *w;
-#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
- ECert *ec = NULL;
-#endif
- w = gtk_label_new (l);
- gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
- g_free (la);
- gtk_table_attach (table, w, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 3, 3);
-#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
- w = gtk_button_new_with_mnemonic(_("_View Certificate"));
- gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
- g_object_set_data((GObject *)w, "e-cert-info", info);
- g_signal_connect (
- w, "clicked",
- G_CALLBACK (efhd_xpkcs7mime_viewcert_clicked), po);
-
- if (info->cert_data)
- ec = e_cert_new (CERT_DupCertificate (info->cert_data));
-
- if (ec == NULL)
- gtk_widget_set_sensitive (w, FALSE);
- else
- g_object_unref (ec);
-#else
- w = gtk_label_new (_("This certificate is not viewable"));
- gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
-#endif
- n++;
- }
- }
-
- gtk_container_add (GTK_CONTAINER (grid), GTK_WIDGET (table));
-}
-
-static void
-efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
- EMFormatPURI *puri)
-{
- EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
- GtkBuilder *builder;
- GtkWidget *grid, *w;
-
- if (po->widget)
- /* FIXME: window raise? */
- return;
-
- builder = gtk_builder_new ();
- e_load_ui_builder_definition (builder, "mail-dialogs.ui");
-
- po->widget = e_builder_get_widget(builder, "message_security_dialog");
-
- grid = e_builder_get_widget(builder, "signature_grid");
- w = gtk_label_new (_(smime_sign_table[po->valid->sign.status].description));
- gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
- gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
- gtk_container_add (GTK_CONTAINER (grid), w);
- if (po->valid->sign.description) {
- GtkTextBuffer *buffer;
-
- buffer = gtk_text_buffer_new (NULL);
- gtk_text_buffer_set_text (buffer, po->valid->sign.description, strlen (po->valid->sign.description));
- w = g_object_new (gtk_scrolled_window_get_type (),
- "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "shadow_type", GTK_SHADOW_IN,
- "expand", TRUE,
- "child", g_object_new(gtk_text_view_get_type(),
- "buffer", buffer,
- "cursor_visible", FALSE,
- "editable", FALSE,
- "width_request", 500,
- "height_request", 160,
- NULL),
- NULL);
- g_object_unref (buffer);
-
- gtk_container_add (GTK_CONTAINER (grid), w);
- }
-
- if (!g_queue_is_empty (&po->valid->sign.signers))
- efhd_xpkcs7mime_add_cert_table (grid, &po->valid->sign.signers, po);
-
- gtk_widget_show_all (grid);
-
- grid = e_builder_get_widget(builder, "encryption_grid");
- w = gtk_label_new (_(smime_encrypt_table[po->valid->encrypt.status].description));
- gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
- gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
- gtk_container_add (GTK_CONTAINER (grid), w);
- if (po->valid->encrypt.description) {
- GtkTextBuffer *buffer;
-
- buffer = gtk_text_buffer_new (NULL);
- gtk_text_buffer_set_text (buffer, po->valid->encrypt.description, strlen (po->valid->encrypt.description));
- w = g_object_new (gtk_scrolled_window_get_type (),
- "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "shadow_type", GTK_SHADOW_IN,
- "expand", TRUE,
- "child", g_object_new(gtk_text_view_get_type(),
- "buffer", buffer,
- "cursor_visible", FALSE,
- "editable", FALSE,
- "width_request", 500,
- "height_request", 160,
- NULL),
- NULL);
- g_object_unref (buffer);
-
- gtk_container_add (GTK_CONTAINER (grid), w);
- }
-
- if (!g_queue_is_empty (&po->valid->encrypt.encrypters))
- efhd_xpkcs7mime_add_cert_table (grid, &po->valid->encrypt.encrypters, po);
-
- gtk_widget_show_all (grid);
-
- g_object_unref (builder);
-
- g_signal_connect (
- po->widget, "response",
- G_CALLBACK (efhd_xpkcs7mime_info_response), po);
-
- gtk_widget_show (po->widget);
-}
-
-static GtkWidget *
-efhd_xpkcs7mime_button (EMFormat *emf,
- EMFormatPURI *puri,
- GCancellable *cancellable)
-{
- GtkWidget *box, *button, *layout, *widget;
- EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
- const gchar *icon_name;
-
- /* FIXME: need to have it based on encryption and signing too */
- if (po->valid->sign.status != 0)
- icon_name = smime_sign_table[po->valid->sign.status].icon;
- else
- icon_name = smime_encrypt_table[po->valid->encrypt.status].icon;
-
- box = gtk_event_box_new ();
- if (po->valid->sign.status != 0)
- gtk_widget_override_background_color (box, GTK_STATE_FLAG_NORMAL,
- &smime_sign_colour[po->valid->sign.status]);
-
- layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
- gtk_container_add (GTK_CONTAINER (box), layout);
-
- button = gtk_button_new ();
- gtk_box_pack_start (GTK_BOX (layout), button, FALSE, FALSE, 0);
- g_signal_connect (button, "clicked",
- G_CALLBACK (efhd_xpkcs7mime_validity_clicked), puri);
-
- widget = gtk_image_new_from_icon_name (
- icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
- gtk_button_set_image (GTK_BUTTON (button), widget);
-
- widget = gtk_label_new (po->description);
- gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0);
-
- gtk_widget_show_all (box);
-
- return box;
-}
-
-struct attachment_load_data {
- EAttachment *attachment;
- EFlag *flag;
-};
-
-static void
-attachment_loaded (EAttachment *attachment,
- GAsyncResult *res,
- gpointer user_data)
-{
- struct attachment_load_data *data = user_data;
- EShell *shell;
- GtkWindow *window;
-
- shell = e_shell_get_default ();
- window = e_shell_get_active_window (shell);
-
- e_attachment_load_handle_error (data->attachment, res, window);
-
- e_flag_set (data->flag);
-}
-
-/* Idle callback */
-static gboolean
-load_attachment_idle (struct attachment_load_data *data)
-{
- e_attachment_load_async (data->attachment,
- (GAsyncReadyCallback) attachment_loaded, data);
-
- return FALSE;
-}
-
-static void
-efhd_parse_attachment (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- gchar *text, *html;
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
- EMFormatAttachmentPURI *puri;
- EAttachmentStore *store;
- const EMFormatHandler *handler;
- CamelContentType *ct;
- gchar *mime_type;
- gint len;
- const gchar *cid;
- guint32 size;
- struct attachment_load_data *load_data;
- gboolean can_show = FALSE;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- len = part_id->len;
- g_string_append (part_id, ".attachment");
-
- /* Try to find handler for the mime part */
- ct = camel_mime_part_get_content_type (part);
- if (ct) {
- mime_type = camel_content_type_simple (ct);
- handler = em_format_find_handler (emf, mime_type);
- }
-
- /* FIXME: should we look up mime_type from object again? */
- text = em_format_describe_part (part, mime_type);
- html = camel_text_to_html (
- text, EM_FORMAT_HTML (emf)->text_html_flags &
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- g_free (text);
- g_free (mime_type);
-
- puri = (EMFormatAttachmentPURI *) em_format_puri_new (
- emf, sizeof (EMFormatAttachmentPURI), part, part_id->str);
- puri->puri.free = efhd_free_attach_puri_data;
- puri->puri.write_func = efhd_write_attachment;
- puri->puri.widget_func = efhd_attachment_button;
- puri->shown = (handler && em_format_is_inline (emf, part_id->str, part, handler));
- puri->snoop_mime_type = em_format_snoop_type (part);
- puri->attachment = e_attachment_new ();
- puri->attachment_view_part_id = NULL;
- puri->description = html;
- puri->handle = handler;
- if (info->validity)
- puri->puri.validity = camel_cipher_validity_clone (info->validity);
-
- cid = camel_mime_part_get_content_id (part);
- if (cid)
- puri->puri.cid = g_strdup_printf ("cid:%s", cid);
-
- if (handler) {
- CamelContentType *ct;
-
- /* This mime_type is important for WebKit to determine content type.
- * We have converted text/ * to text/html, other (binary) formats remained
- * untouched. */
- ct = camel_content_type_decode (handler->mime_type);
- if (g_strcmp0 (ct->type, "text") == 0)
- puri->puri.mime_type = g_strdup ("text/html");
- else
- puri->puri.mime_type = camel_content_type_simple (ct);
- camel_content_type_unref (ct);
- }
-
- em_format_add_puri (emf, (EMFormatPURI *) puri);
-
- /* Though it is an attachment, we still might be able to parse it and
- * so discover some parts that we might be even able to display. */
- if (handler && handler->parse_func && (handler->parse_func != efhd_parse_attachment) &&
- ((handler->flags & EM_FORMAT_HANDLER_COMPOUND_TYPE) ||
- (handler->flags & EM_FORMAT_HANDLER_INLINE_DISPOSITION))) {
- GList *i;
- EMFormatParserInfo attachment_info = { .handler = handler,
- .is_attachment = TRUE };
- handler->parse_func (emf, puri->puri.part, part_id, &attachment_info, cancellable);
-
- i = g_hash_table_lookup (emf->mail_part_table, part_id->str);
- if (i->next && i->next->data) {
- EMFormatPURI *p = i->next->data;
- puri->attachment_view_part_id = g_strdup (p->uri);
- can_show = TRUE;
- }
- }
-
- e_attachment_set_mime_part (puri->attachment, part);
- e_attachment_set_shown (puri->attachment, puri->shown);
- if (puri->puri.validity) {
- e_attachment_set_signed (puri->attachment, puri->puri.validity->sign.status);
- e_attachment_set_encrypted (puri->attachment, puri->puri.validity->encrypt.status);
- }
- e_attachment_set_can_show (puri->attachment,
- can_show || (puri->handle && puri->handle->write_func));
-
- store = find_parent_attachment_store (efhd, part_id->str);
- e_attachment_store_add_attachment (store, puri->attachment);
-
- if (emf->folder && emf->folder->summary && emf->message_uid) {
- CamelDataWrapper *dw = camel_medium_get_content (CAMEL_MEDIUM (puri->puri.part));
- GByteArray *ba;
- ba = camel_data_wrapper_get_byte_array (dw);
- if (ba) {
- size = ba->len;
-
- if (camel_mime_part_get_encoding (puri->puri.part) == CAMEL_TRANSFER_ENCODING_BASE64)
- size = size / 1.37;
- }
- }
-
- load_data = g_new0 (struct attachment_load_data, 1);
- load_data->attachment = g_object_ref (puri->attachment);
- load_data->flag = e_flag_new ();
-
- e_flag_clear (load_data->flag);
-
- /* e_attachment_load_async must be called from main thread */
- g_idle_add ((GSourceFunc) load_attachment_idle, load_data);
-
- e_flag_wait (load_data->flag);
-
- e_flag_free (load_data->flag);
- g_object_unref (load_data->attachment);
- g_free (load_data);
-
- if (size != 0) {
- GFileInfo *fileinfo;
-
- fileinfo = e_attachment_get_file_info (puri->attachment);
- g_file_info_set_size (fileinfo, size);
- e_attachment_set_file_info (puri->attachment, fileinfo);
- }
-
- g_string_truncate (part_id, len);
-}
-
-static void
-efhd_parse_secure (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- if (info->validity
- && (info->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
- || info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) {
- GString *buffer;
- EMFormatSMIMEPURI *pobj;
-
- pobj = (EMFormatSMIMEPURI *) em_format_puri_new (
- emf, sizeof (EMFormatSMIMEPURI), part, part_id->str);
- pobj->puri.free = efhd_xpkcs7mime_free;
- pobj->valid = camel_cipher_validity_clone (info->validity);
- pobj->puri.widget_func = efhd_xpkcs7mime_button;
- pobj->puri.write_func = efhd_write_secure_button;
-
- em_format_add_puri (emf, (EMFormatPURI *) pobj);
-
- buffer = g_string_new ("");
-
- if (info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
- const gchar *desc;
- gint status;
-
- status = info->validity->sign.status;
- desc = smime_sign_table[status].shortdesc;
-
- g_string_append (buffer, gettext (desc));
-
- em_format_html_format_cert_infos (
- &info->validity->sign.signers, buffer);
- }
-
- if (info->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
- const gchar *desc;
- gint status;
-
- if (info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)
- g_string_append (buffer, "\n");
-
- status = info->validity->encrypt.status;
- desc = smime_encrypt_table[status].shortdesc;
- g_string_append (buffer, gettext (desc));
- }
-
- pobj->description = g_string_free (buffer, FALSE);
- }
-}
-
-/******************************************************************************/
-static void
-efhd_write_attachment_bar (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatAttachmentBarPURI *efab = (EMFormatAttachmentBarPURI *) puri;
- gchar *str;
-
- if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING)
- return;
-
- if (e_attachment_store_get_num_attachments (efab->store) == 0)
- return;
-
- str = g_strdup_printf (
- "<object type=\"application/x-attachment-bar\" "
- "height=\"20\" width=\"100%%\" "
- "id=\"%s\"data=\"%s\"></object>", puri->uri, puri->uri);
-
- camel_stream_write_string (stream, str, cancellable, NULL);
-
- g_free (str);
-}
-
-static void
-efhd_write_attachment (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- gchar *str, *desc;
- const gchar *mime_type;
- gchar *button_id;
-
- EMFormatAttachmentPURI *efa = (EMFormatAttachmentPURI *) puri;
-
- /* If the attachment is requested as RAW, then call the handler directly
- * and do not append any other code. */
- if ((info->mode == EM_FORMAT_WRITE_MODE_RAW) &&
- efa->handle && efa->handle->write_func) {
-
- efa->handle->write_func (emf, puri, stream, info, cancellable);
- return;
- }
-
- if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
-
- if (efa->handle && efa->handle->write_func)
- efa->handle->write_func (emf, puri, stream, info, cancellable);
-
- return;
- }
-
- if (efa->handle)
- mime_type = efa->handle->mime_type;
- else
- mime_type = efa->snoop_mime_type;
-
- button_id = g_strconcat (puri->uri, ".attachment_button", NULL);
-
- desc = em_format_describe_part (puri->part, mime_type);
- str = g_strdup_printf (
- "<div class=\"attachment\">"
- "<table width=\"100%%\" border=\"0\">"
- "<tr valign=\"middle\">"
- "<td align=\"left\" width=\"100\">"
- "<object type=\"application/x-attachment-button\" "
- "height=\"20\" width=\"100\" data=\"%s\" id=\"%s\"></object>"
- "</td>"
- "<td align=\"left\">%s</td>"
- "</tr>", puri->uri, button_id, desc);
-
- camel_stream_write_string (stream, str, cancellable, NULL);
- g_free (desc);
- g_free (button_id);
- g_free (str);
-
- /* If we know how to write the attachment, then do it */
- if ((efa->handle && efa->handle->write_func) ||
- (efa->attachment_view_part_id)) {
-
- str = g_strdup_printf (
- "<tr><td colspan=\"2\">"
- "<div class=\"attachment-wrapper\" id=\"%s\">",
- puri->uri);
-
- camel_stream_write_string (stream, str, cancellable, NULL);
- g_free (str);
-
- if (efa->handle->write_func) {
- efa->handle->write_func (
- emf, puri, stream, info, cancellable);
- } else if (efa->attachment_view_part_id) {
- EMFormatPURI *p;
-
- p = em_format_find_puri (
- emf, efa->attachment_view_part_id);
- if (p && p->write_func)
- p->write_func (emf, p, stream, info, cancellable);
- }
-
- camel_stream_write_string (stream, "</div></td></tr>", cancellable, NULL);
- }
-
- camel_stream_write_string (stream, "</table></div>", cancellable, NULL);
-}
-
-static void
-efhd_write_secure_button (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- gchar *str;
-
- if ((info->mode != EM_FORMAT_WRITE_MODE_NORMAL) &&
- (info->mode != EM_FORMAT_WRITE_MODE_RAW))
- return;
-
- str = g_strdup_printf (
- "<object type=\"application/x-secure-button\" "
- "height=\"20\" width=\"100%%\" "
- "data=\"%s\" id=\"%s\"></object>", puri->uri, puri->uri);
-
- camel_stream_write_string (stream, str, cancellable, NULL);
-
- g_free (str);
-}
-
-static void
-efhd_finalize (GObject *object)
-{
- EMFormatHTMLDisplay *efhd;
-
- efhd = EM_FORMAT_HTML_DISPLAY (object);
- g_return_if_fail (efhd != NULL);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-efhd_preparse (EMFormat *emf)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
-
- efhd->priv->last_view = NULL;
-}
-
-static void
-efhd_class_init (EMFormatHTMLDisplayClass *class)
-{
- GObjectClass *object_class;
- EMFormatHTMLClass *format_html_class;
- EMFormatClass *format_class;
-
- parent_class = g_type_class_peek_parent (class);
- g_type_class_add_private (class, sizeof (EMFormatHTMLDisplayPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = efhd_finalize;
-
- format_html_class = EM_FORMAT_HTML_CLASS (class);
- format_html_class->html_widget_type = E_TYPE_MAIL_DISPLAY;
-
- format_class = EM_FORMAT_CLASS (class);
- format_class->preparse = efhd_preparse;
-
- efhd_builtin_init (class);
-}
-
-static void
-efhd_init (EMFormatHTMLDisplay *efhd)
-{
- efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efhd);
-
- /* we want to convert url's etc */
- EM_FORMAT_HTML (efhd)->text_html_flags |=
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
-
-}
-
-GType
-em_format_html_display_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EMFormatHTMLDisplayClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) efhd_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EMFormatHTMLDisplay),
- 0, /* n_preallocs */
- (GInstanceInitFunc) efhd_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- EM_TYPE_FORMAT_HTML, "EMFormatHTMLDisplay",
- &type_info, 0);
- }
-
- return type;
-}
-
-EMFormatHTMLDisplay *
-em_format_html_display_new (CamelSession *session)
-{
- g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-
- return g_object_new (
- EM_TYPE_FORMAT_HTML_DISPLAY,
- "session", session, NULL);
-}
-
-/* ********************************************************************** */
-
-static EMFormatHandler type_builtin_table[] = {
- { (gchar *) "x-evolution/message/prefix", efhd_message_prefix, },
- { (gchar *) "x-evolution/message/attachment-bar", (EMFormatParseFunc) efhd_message_add_bar, efhd_write_attachment_bar, },
- { (gchar *) "x-evolution/message/attachment", efhd_parse_attachment, efhd_write_attachment, },
- { (gchar *) "x-evolution/message/x-secure-button", efhd_parse_secure, efhd_write_secure_button, },
-};
-
-static void
-efhd_builtin_init (EMFormatHTMLDisplayClass *efhc)
-{
- gint i;
-
- EMFormatClass *emfc = (EMFormatClass *) efhc;
-
- for (i = 0; i < G_N_ELEMENTS (type_builtin_table); i++)
- em_format_class_add_handler (emfc, &type_builtin_table[i]);
-}
-
-static void
-efhd_message_prefix (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- const gchar *flag, *comp, *due;
- time_t date;
- gchar *iconpath, *due_date_str;
- GString *buffer;
- EMFormatAttachmentPURI *puri;
-
- if (emf->folder == NULL || emf->message_uid == NULL
- || (flag = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "follow-up")) == NULL
- || flag[0] == 0)
- return;
-
- puri = (EMFormatAttachmentPURI *) em_format_puri_new (
- emf, sizeof (EMFormatAttachmentPURI), part, ".message_prefix");
-
- puri->attachment_view_part_id = g_strdup (part_id->str);
-
- comp = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "completed-on");
- iconpath = e_icon_factory_get_icon_filename (comp && comp[0] ? "stock_mail-flag-for-followup-done" : "stock_mail-flag-for-followup", GTK_ICON_SIZE_MENU);
- if (iconpath) {
- gchar *classid;
-
- classid = g_strdup_printf (
- "icon:///em-format-html-display/%s/%s",
- part_id->str,
- comp && comp[0] ? "comp" : "uncomp");
-
- puri->puri.uri = classid;
-
- g_free (classid);
- }
-
- buffer = g_string_new ("");
-
- if (comp && comp[0]) {
- date = camel_header_decode_date (comp, NULL);
- due_date_str = e_datetime_format_format (
- "mail", "header", DTFormatKindDateTime, date);
- g_string_append_printf (
- buffer, "%s, %s %s",
- flag, _("Completed on"),
- due_date_str ? due_date_str : "???");
- g_free (due_date_str);
- } else if ((due = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "due-by")) != NULL && due[0]) {
- time_t now;
-
- date = camel_header_decode_date (due, NULL);
- now = time (NULL);
- if (now > date)
- g_string_append_printf (
- buffer,
- "<b>%s</b> ",
- _("Overdue:"));
-
- due_date_str = e_datetime_format_format (
- "mail", "header", DTFormatKindDateTime, date);
- /* Translators: the "by" is part of the string,
- * like "Follow-up by Tuesday, January 13, 2009" */
- g_string_append_printf (
- buffer, "%s %s %s",
- flag, _("by"),
- due_date_str ? due_date_str : "???");
- g_free (due_date_str);
- } else {
- g_string_append (buffer, flag);
- }
-
- puri->description = g_string_free (buffer, FALSE);
-}
-
-/* ********************************************************************** */
-
-/* attachment button callback */
-static GtkWidget *
-efhd_attachment_button (EMFormat *emf,
- EMFormatPURI *puri,
- GCancellable *cancellable)
-{
- EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
- GtkWidget *widget;
-
- /* FIXME: handle default shown case */
- d(printf("adding attachment button/content\n"));
-
- if (g_cancellable_is_cancelled (cancellable))
- return NULL;
-
- if (!info || info->forward) {
- g_warning ("unable to expand the attachment\n");
- return NULL;
- }
-
- widget = e_attachment_button_new ();
- g_object_set_data (G_OBJECT (widget), "uri", puri->uri);
- e_attachment_button_set_attachment (
- E_ATTACHMENT_BUTTON (widget), info->attachment);
- e_attachment_button_set_view (
- E_ATTACHMENT_BUTTON (widget),
- EM_FORMAT_HTML_DISPLAY (emf)->priv->last_view);
-
- gtk_widget_set_can_focus (widget, TRUE);
- gtk_widget_show (widget);
-
- return widget;
-}
-
-static GtkWidget *
-efhd_attachment_bar (EMFormat *emf,
- EMFormatPURI *puri,
- GCancellable *cancellable)
-{
- EMFormatAttachmentBarPURI *abp = (EMFormatAttachmentBarPURI *) puri;
- GtkWidget *widget;
-
- widget = e_mail_attachment_bar_new (abp->store);
- EM_FORMAT_HTML_DISPLAY (emf)->priv->last_view = (EAttachmentView *) widget;
-
- return widget;
-}
-
-static void
-efhd_message_add_bar (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatAttachmentBarPURI *puri;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- len = part_id->len;
- g_string_append (part_id, ".attachment-bar");
- puri = (EMFormatAttachmentBarPURI *) em_format_puri_new (
- emf, sizeof (EMFormatAttachmentBarPURI), part, part_id->str);
- puri->puri.write_func = efhd_write_attachment_bar;
- puri->puri.widget_func = efhd_attachment_bar;
- puri->puri.free = efhd_attachment_bar_puri_free;
- puri->store = E_ATTACHMENT_STORE (e_attachment_store_new ());
-
- em_format_add_puri (emf, (EMFormatPURI *) puri);
-
- g_string_truncate (part_id, len);
-}
-
-static void
-efhd_free_attach_puri_data (EMFormatPURI *puri)
-{
- EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
-
- g_return_if_fail (puri != NULL);
-
- if (info->attachment) {
- g_object_unref (info->attachment);
- info->attachment = NULL;
- }
-
- if (info->description) {
- g_free (info->description);
- info->description = NULL;
- }
-
- if (info->attachment_view_part_id) {
- g_free (info->attachment_view_part_id);
- info->attachment_view_part_id = NULL;
- }
-
- if (info->mstream) {
- g_object_unref (info->mstream);
- info->mstream = NULL;
- }
-}
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
deleted file mode 100644
index 7c0d7a9fd5..0000000000
--- a/mail/em-format-html-display.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- Concrete class for formatting mails to displayed html
-*/
-
-#ifndef EM_FORMAT_HTML_DISPLAY_H
-#define EM_FORMAT_HTML_DISPLAY_H
-
-#include <mail/em-format-html.h>
-#include <misc/e-attachment-view.h>
-
-/* Standard GObject macros */
-#define EM_TYPE_FORMAT_HTML_DISPLAY \
- (em_format_html_display_get_type ())
-#define EM_FORMAT_HTML_DISPLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplay))
-#define EM_FORMAT_HTML_DISPLAY_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayClass))
-#define EM_IS_FORMAT_HTML_DISPLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_FORMAT_HTML_DISPLAY))
-#define EM_IS_FORMAT_HTML_DISPLAY_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_FORMAT_HTML_DISPLAY))
-#define EM_FORMAT_HTML_DISPLAY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EMFormatHTMLDisplay EMFormatHTMLDisplay;
-typedef struct _EMFormatHTMLDisplayClass EMFormatHTMLDisplayClass;
-typedef struct _EMFormatHTMLDisplayPrivate EMFormatHTMLDisplayPrivate;
-typedef struct _EMFormatAttachmentBarPURI EMFormatAttachmentBarPURI;
-typedef struct _EMFormatAttachmentPURI EMFormatAttachmentPURI;
-typedef struct _EMFormatSMIMEPURI EMFormatSMIMEPURI;
-
-struct _EMFormatAttachmentBarPURI {
- EMFormatPURI puri;
-
- EAttachmentStore *store;
-};
-
-struct _EMFormatAttachmentPURI {
- EMFormatPURI puri;
-
- const EMFormatHandler *handle;
-
- const gchar *snoop_mime_type;
-
- /* for the > and V buttons */
- GtkWidget *forward, *down;
- guint shown : 1;
-
- /* Attachment */
- EAttachment *attachment;
- gchar *attachment_view_part_id;
- gchar *description;
-
- /* image stuff */
- gint fit_width;
- gint fit_height;
- GtkImage *image;
- GtkWidget *event_box;
-
- /* Optional Text Mem Stream */
- CamelStreamMem *mstream;
-};
-
-struct _EMFormatSMIMEPURI {
- EMFormatPURI puri;
-
- gchar *description;
-
- gint signature;
- CamelCipherValidity *valid;
- GtkWidget *widget;
-};
-
-struct _EMFormatHTMLDisplay {
- EMFormatHTML parent;
- EMFormatHTMLDisplayPrivate *priv;
-
- struct _ESearchingTokenizer *search_tok;
-};
-
-struct _EMFormatHTMLDisplayClass {
- EMFormatHTMLClass parent_class;
-};
-
-GType em_format_html_display_get_type (void);
-EMFormatHTMLDisplay *
- em_format_html_display_new (CamelSession *session);
-G_END_DECLS
-
-#endif /* EM_FORMAT_HTML_DISPLAY_H */
diff --git a/mail/em-format-html-print.c b/mail/em-format-html-print.c
deleted file mode 100644
index 150c16dbf5..0000000000
--- a/mail/em-format-html-print.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-
-#include "em-format-html-print.h"
-#include "em-format-html-display.h"
-#include "e-mail-attachment-bar.h"
-#include <e-util/e-print.h>
-#include <e-util/e-util.h>
-#include <widgets/misc/e-attachment-store.h>
-#include <libemail-engine/mail-ops.h>
-
-#include "em-format-html-print.h"
-
-#define d(x)
-
-static gpointer parent_class = NULL;
-
-struct _EMFormatHTMLPrintPrivate {
-
- EMFormatHTML *original_formatter;
- EMFormatPURI *top_level_puri;
-
- /* List of attachment PURIs */
- GList *attachments;
-
-};
-
-enum {
- PROP_0,
- PROP_ORIGINAL_FORMATTER
-};
-
-static void efhp_write_print_layout (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhp_write_headers (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhp_write_inline_attachment (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-static void
-efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GString *str;
- GList *iter;
-
- if (!efhp->priv->attachments)
- return;
-
- str = g_string_new (
- "<table border=\"0\" cellspacing=\"5\" cellpadding=\"0\" "
- "class=\"attachments-list\" >\n");
- g_string_append_printf (str,
- "<tr><th colspan=\"2\"><h1>%s</h1></td></tr>\n"
- "<tr><th>%s</th><th>%s</th></tr>\n",
- _("Attachments"), _("Name"), _("Size"));
-
- for (iter = efhp->priv->attachments; iter; iter = iter->next) {
- EMFormatPURI *puri = iter->data;
- EAttachment *attachment;
- GFileInfo *fi;
- gchar *name, *size;
- GByteArray *ba;
- CamelDataWrapper *dw;
-
- attachment = ((EMFormatAttachmentPURI *) puri)->attachment;
- fi = e_attachment_get_file_info (attachment);
- if (!fi)
- continue;
-
- if (e_attachment_get_description (attachment) &&
- *e_attachment_get_description (attachment)) {
- name = g_strdup_printf ("%s (%s)",
- e_attachment_get_description (attachment),
- g_file_info_get_display_name (fi));
- } else {
- name = g_strdup (g_file_info_get_display_name (fi));
- }
-
- dw = camel_medium_get_content ((CamelMedium *) puri->part);
- ba = camel_data_wrapper_get_byte_array (dw);
- size = g_format_size (ba->len);
-
- g_string_append_printf (str, "<tr><td>%s</td><td>%s</td></tr>\n",
- name, size);
-
- g_free (name);
- g_free (size);
- }
-
- g_string_append (str, "</table>\n");
-
- camel_stream_write_string (stream, str->str, cancellable, NULL);
- g_string_free (str, TRUE);
-}
-
-static void
-efhp_write_headers (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- struct _camel_header_raw raw_header;
- GString *str, *tmp;
- gchar *subject;
- const gchar *buf;
- EMFormatPURI *p;
- GList *iter;
- gint attachments_count;
- gchar *puri_prefix;
-
- buf = camel_medium_get_header (CAMEL_MEDIUM (puri->part), "subject");
- subject = camel_header_decode_string (buf, "UTF-8");
- str = g_string_new ("<table border=\"0\" cellspacing=\"5\" " \
- "cellpadding=\"0\" class=\"printing-header\">\n");
- g_string_append_printf (
- str,
- "<tr class=\"header-item\">"
- "<td colspan=\"2\"><h1>%s</h1></td>"
- "</tr>\n",
- subject);
- g_free (subject);
-
- for (iter = g_queue_peek_head_link (&emf->header_list); iter; iter = iter->next) {
-
- EMFormatHeader *header = iter->data;
- raw_header.name = header->name;
-
- /* Skip 'Subject' header, it's already displayed. */
- if (g_ascii_strncasecmp (header->name, "Subject", 7) == 0)
- continue;
-
- if (header->value && *header->value) {
- raw_header.value = header->value;
- em_format_html_format_header (emf, str,
- CAMEL_MEDIUM (puri->part), &raw_header,
- header->flags | EM_FORMAT_HTML_HEADER_NOLINKS,
- "UTF-8");
- } else {
- raw_header.value = g_strdup (camel_medium_get_header (
- CAMEL_MEDIUM (emf->message), header->name));
-
- if (raw_header.value && *raw_header.value) {
- em_format_html_format_header (emf, str,
- CAMEL_MEDIUM (puri->part), &raw_header,
- header->flags | EM_FORMAT_HTML_HEADER_NOLINKS,
- "UTF-8");
- }
-
- if (raw_header.value)
- g_free (raw_header.value);
- }
- }
-
- /* Get prefix of this PURI */
- puri_prefix = g_strndup (puri->uri, g_strrstr (puri->uri, ".") - puri->uri);
-
- /* Add encryption/signature header */
- raw_header.name = _("Security");
- tmp = g_string_new ("");
- /* Find first secured part. */
- for (iter = emf->mail_part_list, puri; iter; iter = iter->next) {
-
- p = iter->data;
-
- if (p->validity_type == 0)
- continue;
-
- if (!g_str_has_prefix (p->uri, puri_prefix))
- continue;
-
- if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
- (p->validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
- g_string_append (tmp, _("GPG signed"));
- }
- if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
- (p->validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
- if (tmp->len > 0) g_string_append (tmp, ", ");
- g_string_append (tmp, _("GPG encrpyted"));
- }
- if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
- (p->validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
-
- if (tmp->len > 0) g_string_append (tmp, ", ");
- g_string_append (tmp, _("S/MIME signed"));
- }
- if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
- (p->validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
-
- if (tmp->len > 0) g_string_append (tmp, ", ");
- g_string_append (tmp, _("S/MIME encrpyted"));
- }
-
- break;
- }
-
- if (tmp->len > 0) {
- raw_header.value = tmp->str;
- em_format_html_format_header (emf, str, CAMEL_MEDIUM (p->part),
- &raw_header, EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_NOLINKS, "UTF-8");
- }
- g_string_free (tmp, TRUE);
-
- /* Count attachments and display the number as a header */
- attachments_count = 0;
-
- for (iter = emf->mail_part_list; iter; iter = iter ? iter->next : iter) {
-
- p = iter->data;
-
- if (!g_str_has_prefix (p->uri, puri_prefix))
- continue;
-
- if ((p->is_attachment || g_str_has_suffix(p->uri, ".attachment")) &&
- (!p->cid)) {
- attachments_count++;
- /* EFHD sometimes creates two PURIs per attachment! */
- if (iter->next && iter->next->data) {
- EMFormatPURI *p2 = iter->next->data;
- if (g_str_has_prefix (p2->uri, p->uri))
- iter = iter->next;
- }
- }
- }
- if (attachments_count > 0) {
- raw_header.name = _("Attachments");
- raw_header.value = g_strdup_printf ("%d", attachments_count);
- em_format_html_format_header (emf, str, CAMEL_MEDIUM (puri->part),
- &raw_header, EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_NOLINKS, "UTF-8");
- g_free (raw_header.value);
- }
-
- g_string_append (str, "</table>");
-
- camel_stream_write_string (stream, str->str, cancellable, NULL);
- g_string_free (str, TRUE);
- g_free (puri_prefix);
-}
-
-static void
-efhp_write_inline_attachment (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- gchar *name;
- EMFormatAttachmentPURI *att_puri = (EMFormatAttachmentPURI *) puri;
- EAttachment *attachment;
- GFileInfo *fi;
-
- attachment = att_puri->attachment;
- fi = e_attachment_get_file_info (attachment);
-
- if (e_attachment_get_description (attachment) &&
- *e_attachment_get_description (attachment)) {
- name = g_strdup_printf ("<h2>Attachment: %s (%s)</h2>\n",
- e_attachment_get_description (attachment),
- g_file_info_get_display_name (fi));
- } else {
- name = g_strdup_printf ("<h2>Attachment: %s</h2>\n",
- g_file_info_get_display_name (fi));
- }
-
- camel_stream_write_string (stream, name, cancellable, NULL);
- g_free (name);
-}
-
-static void
-efhp_write_print_layout (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GList *iter;
- EMFormatWriterInfo print_info = {
- EM_FORMAT_WRITE_MODE_PRINTING, FALSE, FALSE };
- EMFormatHTMLPrint *efhp = EM_FORMAT_HTML_PRINT (emf);
-
- g_list_free (efhp->priv->attachments);
- efhp->priv->attachments = NULL;
-
- camel_stream_write_string (stream,
- "<!DOCTYPE HTML>\n<html>\n"
- "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\" />\n"
- "<title>Evolution Mail Display</title>\n"
- "<link type=\"text/css\" rel=\"stylesheet\" media=\"print\" "
- "href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview-print.css\" />\n"
- "</head>\n"
- "<body style=\"background: #FFF; color: #000;\">",
- cancellable, NULL);
-
- for (iter = emf->mail_part_list; iter != NULL; iter = iter ? iter->next : iter) {
-
- EMFormatPURI *puri = iter->data;
-
- if (g_str_has_suffix (puri->uri, "print_layout"))
- continue;
-
- /* To late to change .headers writer_func, do it manually. */
- if (g_str_has_suffix (puri->uri, ".headers")) {
- efhp_write_headers (emf, puri, stream, &print_info, cancellable);
- continue;
- }
-
- if (g_str_has_suffix (puri->uri, ".rfc822")) {
-
- puri->write_func (emf, puri, stream, &print_info, cancellable);
-
- while (iter && !g_str_has_suffix (puri->uri, ".rfc822.end")) {
-
- iter = iter->next;
- if (iter)
- puri = iter->data;
- }
-
- if (!iter)
- break;
-
- continue;
-
- }
-
- if (puri->is_attachment || g_str_has_suffix (puri->uri, ".attachment")) {
- const EMFormatHandler *handler;
- CamelContentType *ct;
- gchar *mime_type;
-
- if (puri->cid && g_ascii_strncasecmp (puri->cid, "cid:", 4) == 0)
- continue;
-
- ct = camel_mime_part_get_content_type (puri->part);
- mime_type = camel_content_type_simple (ct);
-
- handler = em_format_find_handler (puri->emf, mime_type);
- d(printf("Handler for PURI %s (%s): %s\n", puri->uri, mime_type,
- handler ? handler->mime_type : "(null)"));
- g_free (mime_type);
-
- efhp->priv->attachments =
- g_list_append (efhp->priv->attachments, puri);
-
- /* If we can't inline this attachment, skip it */
- if (handler && puri->write_func) {
- efhp_write_inline_attachment (puri->emf, puri,
- stream, &print_info, cancellable);
-
- if (iter->next && iter->next->data) {
- EMFormatPURI *p;
- p = iter->next->data;
-
- /* Has the next PURI the same prefix? */
- if (p->write_func &&
- g_str_has_prefix (p->uri, puri->uri)) {
- p->write_func (emf, p, stream,
- &print_info, cancellable);
- iter = iter->next;
- } else {
- if (puri->write_func) {
- puri->write_func (emf, puri,
- stream, &print_info,
- cancellable);
- }
- }
- }
- }
-
- continue;
- }
-
- /* Ignore widget parts and unwritable non-attachment parts */
- if (puri->write_func == NULL)
- continue;
-
- /* Passed all tests, probably a regular part - display it */
- puri->write_func (puri->emf, puri, stream, &print_info, cancellable);
-
- }
-
- efhp_write_attachments_list (efhp, stream, &print_info, cancellable);
-
- camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
-}
-
-static void
-efhp_finalize (GObject *object)
-{
- EMFormatHTMLPrint *efhp = EM_FORMAT_HTML_PRINT (object);
-
- if (efhp->priv->original_formatter) {
- g_object_unref (efhp->priv->original_formatter);
- efhp->priv->original_formatter = NULL;
- }
-
- if (efhp->priv->top_level_puri) {
- em_format_puri_free (efhp->priv->top_level_puri);
- efhp->priv->top_level_puri = NULL;
- }
-
- if (efhp->priv->attachments) {
- g_list_free (efhp->priv->attachments);
- efhp->priv->attachments = NULL;
- }
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-efhp_is_inline (EMFormat *emf,
- const gchar *part_id,
- CamelMimePart *mime_part,
- const EMFormatHandler *handle)
-{
- /* When printing, inline any part that has a handler. */
- return (handle != NULL);
-}
-
-static void
-efhp_set_orig_formatter (EMFormatHTMLPrint *efhp,
- EMFormat *formatter)
-{
- EMFormat *emfp, *emfs;
- EMFormatPURI *puri;
- GHashTableIter iter;
- gpointer key, value;
-
- efhp->priv->original_formatter = g_object_ref (formatter);
-
- emfp = EM_FORMAT (efhp);
- emfs = EM_FORMAT (formatter);
-
- emfp->mail_part_list = g_list_copy (emfs->mail_part_list);
-
- /* Make a shallow copy of the table. This table will NOT destroy
- * the PURIs when free'd! */
- if (emfp->mail_part_table)
- g_hash_table_unref (emfp->mail_part_table);
-
- emfp->mail_part_table = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_iter_init (&iter, emfs->mail_part_table);
- while (g_hash_table_iter_next (&iter, &key, &value))
- g_hash_table_insert (emfp->mail_part_table, key, value);
-
- if (emfs->folder)
- emfp->folder = g_object_ref (emfs->folder);
- emfp->message_uid = g_strdup (emfs->message_uid);
- emfp->message = g_object_ref (emfs->message);
-
- /* Add a generic PURI that will write a HTML layout
- * for all the parts */
- puri = em_format_puri_new (EM_FORMAT (efhp),
- sizeof (EMFormatPURI), NULL, "print_layout");
- puri->write_func = efhp_write_print_layout;
- puri->mime_type = g_strdup ("text/html");
- em_format_add_puri (EM_FORMAT (efhp), puri);
- efhp->priv->top_level_puri = puri;
-}
-
-static EMFormatHandler type_builtin_table[] = {
- { (gchar *) "x-evolution/message/headers", 0, efhp_write_headers, },
-};
-
-static void
-efhp_builtin_init (EMFormatHTMLPrintClass *efhc)
-{
- EMFormatClass *emfc;
- gint ii;
-
- emfc = (EMFormatClass *) efhc;
-
- for (ii = 0; ii < G_N_ELEMENTS (type_builtin_table); ii++)
- em_format_class_add_handler (
- emfc, &type_builtin_table[ii]);
-}
-
-static void
-efhp_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (prop_id) {
-
- case PROP_ORIGINAL_FORMATTER:
- efhp_set_orig_formatter (
- EM_FORMAT_HTML_PRINT (object),
- (EMFormat *) g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
-
-static void
-efhp_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EMFormatHTMLPrintPrivate *priv;
-
- priv = EM_FORMAT_HTML_PRINT (object)->priv;
-
- switch (prop_id) {
-
- case PROP_ORIGINAL_FORMATTER:
- g_value_set_pointer (value,
- priv->original_formatter);
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
-
-static void
-em_format_html_print_base_init (EMFormatHTMLPrintClass *klass)
-{
- efhp_builtin_init (klass);
-}
-
-static void
-em_format_html_print_class_init (EMFormatHTMLPrintClass *klass)
-{
- GObjectClass *object_class;
- EMFormatClass *format_class;
-
- parent_class = g_type_class_peek_parent (klass);
- g_type_class_add_private (klass, sizeof (EMFormatHTMLPrintPrivate));
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = efhp_finalize;
- object_class->set_property = efhp_set_property;
- object_class->get_property = efhp_get_property;
-
- format_class = EM_FORMAT_CLASS (klass);
- format_class->is_inline = efhp_is_inline;
-
- g_object_class_install_property (
- object_class,
- PROP_ORIGINAL_FORMATTER,
- g_param_spec_object (
- "original-formatter",
- NULL,
- NULL,
- EM_TYPE_FORMAT,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-em_format_html_print_init (EMFormatHTMLPrint *efhp)
-{
- efhp->priv = G_TYPE_INSTANCE_GET_PRIVATE (
- efhp, EM_TYPE_FORMAT_HTML_PRINT, EMFormatHTMLPrintPrivate);
-
- efhp->priv->attachments = NULL;
- efhp->export_filename = NULL;
-}
-
-GType
-em_format_html_print_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EMFormatHTMLPrintClass),
- (GBaseInitFunc) em_format_html_print_base_init,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) em_format_html_print_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EMFormatHTMLPrint),
- 0, /* n_preallocs */
- (GInstanceInitFunc) em_format_html_print_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- em_format_html_get_type(), "EMFormatHTMLPrint",
- &type_info, 0);
- }
-
- return type;
-}
-
-EMFormatHTMLPrint *
-em_format_html_print_new (EMFormatHTML *source)
-{
- EMFormatHTMLPrint *efhp;
- CamelSession *session;
-
- g_return_val_if_fail (EM_IS_FORMAT_HTML (source), NULL);
-
- session = em_format_get_session (EM_FORMAT (source));
-
- efhp = g_object_new (
- EM_TYPE_FORMAT_HTML_PRINT,
- "session", session,
- "original-formatter", source,
- NULL);
-
- return efhp;
-}
diff --git a/mail/em-format-html-print.h b/mail/em-format-html-print.h
deleted file mode 100644
index d9fe1ff6d4..0000000000
--- a/mail/em-format-html-print.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Concrete class for formatting mails to displayed html
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- */
-
-#ifndef EM_FORMAT_HTML_PRINT_H
-#define EM_FORMAT_HTML_PRINT_H
-
-#include "mail/em-format-html.h"
-
-/* Standard GObject macros */
-#define EM_TYPE_FORMAT_HTML_PRINT \
- (em_format_html_print_get_type ())
-#define EM_FORMAT_HTML_PRINT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_FORMAT_HTML_PRINT, EMFormatHTMLPrint))
-#define EM_FORMAT_HTML_PRINT_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_FORMAT_HTML_PRINT, EMFormatHTMLPrintClass))
-#define EM_IS_FORMAT_HTML_PRINT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_FORMAT_HTML_PRINT))
-#define EM_IS_FORMAT_HTML_PRINT_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_FORMAT_HTML_PRINT))
-#define EM_FORMAT_HTML_PRINT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_FORMAT_HTML_PRINT, EMFormatHTMLPrintClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EMFormatHTMLPrint EMFormatHTMLPrint;
-typedef struct _EMFormatHTMLPrintClass EMFormatHTMLPrintClass;
-typedef struct _EMFormatHTMLPrintPrivate EMFormatHTMLPrintPrivate;
-
-struct _EMFormatHTMLPrint {
- EMFormatHTML parent;
- EMFormatHTMLPrintPrivate *priv;
- gchar *export_filename;
-};
-
-struct _EMFormatHTMLPrintClass {
- EMFormatHTMLClass parent_class;
-};
-
-GType em_format_html_print_get_type (void);
-EMFormatHTMLPrint *
- em_format_html_print_new (EMFormatHTML *source);
-
-G_END_DECLS
-
-#endif /* EM_FORMAT_HTML_PRINT_H */
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
deleted file mode 100644
index bb80d3957b..0000000000
--- a/mail/em-format-html.c
+++ /dev/null
@@ -1,3011 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE /* Enable strcasestr in string.h */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include <gtk/gtk.h>
-#ifdef G_OS_WIN32
-/* Work around 'DATADIR' and 'interface' lossage in <windows.h> */
-#define DATADIR crap_DATADIR
-#include <windows.h>
-#undef DATADIR
-#undef interface
-#endif
-
-#include <libebackend/libebackend.h>
-
-#include "e-util/e-datetime-format.h"
-#include "e-util/e-icon-factory.h"
-#include "e-util/e-util-private.h"
-#include "e-util/e-util.h"
-#include "misc/e-web-view.h"
-
-#include <shell/e-shell.h>
-
-#include <glib/gi18n.h>
-
-#include <JavaScriptCore/JavaScript.h>
-#include <webkit/webkit.h>
-
-#include <libemail-utils/mail-mt.h>
-#include <libemail-engine/e-mail-enumtypes.h>
-#include <libemail-engine/e-mail-utils.h>
-#include <libemail-engine/mail-config.h>
-
-#include "em-format-html.h"
-#include "em-utils.h"
-#include "e-mail-display.h"
-#include <em-format/em-inline-filter.h>
-
-#define EM_FORMAT_HTML_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), EM_TYPE_FORMAT_HTML, EMFormatHTMLPrivate))
-
-#define d(x)
-
-struct _EMFormatHTMLPrivate {
- GdkColor colors[EM_FORMAT_HTML_NUM_COLOR_TYPES];
- EMailImageLoadingPolicy image_loading_policy;
-
- guint can_load_images : 1;
- guint only_local_photos : 1;
- guint show_sender_photo : 1;
- guint show_real_date : 1;
- guint animate_images : 1;
-};
-
-static gpointer parent_class;
-
-enum {
- PROP_0,
- PROP_BODY_COLOR,
- PROP_CITATION_COLOR,
- PROP_CONTENT_COLOR,
- PROP_FRAME_COLOR,
- PROP_HEADER_COLOR,
- PROP_IMAGE_LOADING_POLICY,
- PROP_MARK_CITATIONS,
- PROP_ONLY_LOCAL_PHOTOS,
- PROP_SHOW_SENDER_PHOTO,
- PROP_SHOW_REAL_DATE,
- PROP_TEXT_COLOR,
- PROP_ANIMATE_IMAGES
-};
-
-#define EFM_MESSAGE_START_ANAME "evolution_message_start"
-#define EFH_MESSAGE_START "<A name=\"" EFM_MESSAGE_START_ANAME "\"></A>"
-
-static void efh_parse_image (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_text_enriched (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_text_plain (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_text_html (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_message_external (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_message_deliverystatus (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-static void efh_parse_message_rfc822 (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
-
-static void efh_write_image (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_enriched (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_plain (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_html (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_source (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_headers (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_attachment (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_error (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_message_rfc822 (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-static void efh_format_full_headers (EMFormatHTML *efh, GString *buffer, CamelMedium *part, gboolean all_headers, gboolean visible, GCancellable *cancellable);
-static void efh_format_short_headers (EMFormatHTML *efh, GString *buffer, CamelMedium *part, gboolean visible, GCancellable *cancellable);
-
-static void efh_write_message (EMFormat *emf, GList *puris, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-
-/*****************************************************************************/
-static void
-efh_parse_image (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- const gchar *tmp;
- gchar *cid;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- tmp = camel_mime_part_get_content_id (part);
- if (!tmp) {
- em_format_parse_part_as (emf, part, part_id, info,
- "x-evolution/message/attachment", cancellable);
- return;
- }
-
- cid = g_strdup_printf ("cid:%s", tmp);
- len = part_id->len;
- g_string_append (part_id, ".image");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->cid = cid;
- puri->write_func = efh_write_image;
- puri->mime_type = g_strdup (info->handler->mime_type);
- puri->is_attachment = TRUE;
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
-
- em_format_add_puri (emf, puri);
- g_string_truncate (part_id, len);
-}
-
-static void
-efh_parse_text_enriched (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- const gchar *tmp;
- gchar *cid;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- tmp = camel_mime_part_get_content_id (part);
- if (!tmp) {
- cid = g_strdup_printf ("em-no-cid:%s", part_id->str);
- } else {
- cid = g_strdup_printf ("cid:%s", tmp);
- }
-
- len = part_id->len;
- g_string_append (part_id, ".text_enriched");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->cid = cid;
- puri->mime_type = g_strdup (info->handler->mime_type);
- puri->write_func = efh_write_text_enriched;
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
- puri->is_attachment = info->is_attachment;
-
- em_format_add_puri (emf, puri);
- g_string_truncate (part_id, len);
-}
-
-static void
-efh_parse_text_plain (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- CamelStream *filtered_stream, *null;
- CamelMultipart *mp;
- CamelDataWrapper *dw;
- CamelContentType *type;
- gint i, count, len;
- EMInlineFilter *inline_filter;
- gboolean charset_added = FALSE;
- const gchar *snoop_type = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- dw = camel_medium_get_content ((CamelMedium *) part);
- if (!dw)
- return;
-
- /* 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 */
-
- /* TODO: We could probably put this in the superclass, since
- * no knowledge of html is required - but this messes with
- * filters a bit. Perhaps the superclass should just deal with
- * html anyway and be done with it ... */
-
- if (!dw->mime_type)
- snoop_type = em_format_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 = em_inline_filter_new (camel_mime_part_get_encoding (part), type);
- 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);
-
- mp = em_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 */
- len = part_id->len;
- count = camel_multipart_get_number (mp);
- for (i = 0; i < count; i++) {
- CamelMimePart *newpart = camel_multipart_get_part (mp, i);
-
- if (!newpart)
- continue;
-
- type = camel_mime_part_get_content_type (newpart);
- if (camel_content_type_is (type, "text", "*") && (!camel_content_type_is (type, "text", "calendar"))) {
- gint s_len = part_id->len;
-
- g_string_append (part_id, ".plain_text");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), newpart, part_id->str);
- puri->write_func = efh_write_text_plain;
- puri->mime_type = g_strdup ("text/html");
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
- puri->is_attachment = info->is_attachment;
- g_string_truncate (part_id, s_len);
- em_format_add_puri (emf, puri);
- } else {
- g_string_append_printf (part_id, ".inline.%d", i);
- em_format_parse_part (emf, CAMEL_MIME_PART (newpart), part_id, info, cancellable);
- g_string_truncate (part_id, len);
- }
- }
-
- g_object_unref (mp);
-}
-
-static void
-efh_parse_text_html (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- const gchar *location;
- gchar *cid = NULL;
- CamelURL *base;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- base = em_format_get_base_url (emf);
- location = camel_mime_part_get_content_location (part);
- if (location == NULL) {
- if (base)
- cid = camel_url_to_string (base, 0);
- else
- cid = g_strdup (part_id->str);
- } else {
- if (strchr (location, ':') == NULL && base != NULL) {
- CamelURL *uri;
-
- uri = camel_url_new_with_base (base, location);
- cid = camel_url_to_string (uri, 0);
- camel_url_free (uri);
- } else {
- cid = g_strdup (location);
- }
- }
-
- len = part_id->len;
- g_string_append (part_id, ".text_html");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = efh_write_text_html;
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
- puri->is_attachment = info->is_attachment;
-
- em_format_add_puri (emf, puri);
- g_string_truncate (part_id, len);
-
- if (cid)
- g_free (cid);
-}
-
-static void
-efh_parse_message_external (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- CamelMimePart *newpart;
- CamelContentType *type;
- const gchar *access_type;
- gchar *url = NULL, *desc = NULL;
- gchar *content;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- newpart = camel_mime_part_new ();
-
- /* needs to be cleaner */
- type = camel_mime_part_get_content_type (part);
- access_type = camel_content_type_param (type, "access-type");
- if (!access_type) {
- const gchar *msg = _("Malformed external-body part");
- camel_mime_part_set_content (newpart, msg, strlen (msg),
- "text/plain");
- goto addPart;
- }
-
- if (!g_ascii_strcasecmp(access_type, "ftp") ||
- !g_ascii_strcasecmp(access_type, "anon-ftp")) {
- const gchar *name, *site, *dir, *mode;
- gchar *path;
- gchar ftype[16];
-
- name = camel_content_type_param (type, "name");
- site = camel_content_type_param (type, "site");
- dir = camel_content_type_param (type, "directory");
- mode = camel_content_type_param (type, "mode");
- if (name == NULL || site == NULL)
- goto fail;
-
- /* Generate the path. */
- if (dir)
- path = g_strdup_printf("/%s/%s", *dir=='/'?dir+1:dir, name);
- else
- path = g_strdup_printf("/%s", *name=='/'?name+1:name);
-
- if (mode && *mode)
- sprintf(ftype, ";type=%c", *mode);
- else
- ftype[0] = 0;
-
- url = g_strdup_printf ("ftp://%s%s%s", site, path, ftype);
- g_free (path);
- desc = g_strdup_printf (_("Pointer to FTP site (%s)"), url);
- } else if (!g_ascii_strcasecmp (access_type, "local-file")) {
- const gchar *name, *site;
-
- name = camel_content_type_param (type, "name");
- site = camel_content_type_param (type, "site");
- if (name == NULL)
- goto fail;
-
- url = g_filename_to_uri (name, NULL, NULL);
- if (site)
- desc = g_strdup_printf(_("Pointer to local file (%s) valid at site \"%s\""), name, site);
- else
- desc = g_strdup_printf(_("Pointer to local file (%s)"), name);
- } else if (!g_ascii_strcasecmp (access_type, "URL")) {
- const gchar *urlparam;
- gchar *s, *d;
-
- /* RFC 2017 */
- urlparam = camel_content_type_param (type, "url");
- if (urlparam == NULL)
- goto fail;
-
- /* For obscure MIMEy reasons, the URL may be split into words */
- url = g_strdup (urlparam);
- s = d = url;
- while (*s) {
- if (!isspace ((guchar) * s))
- *d++ = *s;
- s++;
- }
- *d = 0;
- desc = g_strdup_printf (_("Pointer to remote data (%s)"), url);
- } else
- goto fail;
-
- content = g_strdup_printf ("<a href=\"%s\">%s</a>", url, desc);
- camel_mime_part_set_content (newpart, content, strlen (content), "text/html");
- g_free (content);
-
- g_free (url);
- g_free (desc);
-
-fail:
- content = g_strdup_printf (
- _("Pointer to unknown external data (\"%s\" type)"),
- access_type);
- camel_mime_part_set_content (newpart, content, strlen (content), "text/plain");
- g_free (content);
-
-addPart:
- len = part_id->len;
- g_string_append (part_id, ".msg_external");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = efh_write_text_html;
- puri->mime_type = g_strdup ("text/html");
-
- em_format_add_puri (emf, puri);
- g_string_truncate (part_id, len);
-}
-
-static void
-efh_parse_message_deliverystatus (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- EMFormatPURI *puri;
- gint len;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- len = part_id->len;
- g_string_append (part_id, ".deliverystatus");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = efh_write_source;
- puri->mime_type = g_strdup ("text/html");
- puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
- puri->validity_type = info->validity_type;
- puri->is_attachment = info->is_attachment;
-
- em_format_add_puri (emf, puri);
- g_string_truncate (part_id, len);
-}
-
-static void
-efh_parse_message_rfc822 (EMFormat *emf,
- CamelMimePart *part,
- GString *part_id,
- EMFormatParserInfo *info,
- GCancellable *cancellable)
-{
- CamelDataWrapper *dw;
- CamelMimePart *opart;
- CamelStream *stream;
- CamelMimeParser *parser;
- gint len;
- EMFormatParserInfo oinfo = *info;
- EMFormatPURI *puri;
-
- len = part_id->len;
- g_string_append (part_id, ".rfc822");
-
- /* Create an empty PURI that will represent start of the RFC message */
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
- puri->write_func = efh_write_message_rfc822;
- puri->mime_type = g_strdup ("text/html");
- puri->is_attachment = info->is_attachment;
- em_format_add_puri (emf, puri);
-
- /* Now parse the message, creating multiple sub-PURIs */
- stream = camel_stream_mem_new ();
- dw = camel_medium_get_content ((CamelMedium *) part);
- camel_data_wrapper_write_to_stream_sync (dw, stream, cancellable, NULL);
- g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, cancellable, NULL);
-
- parser = camel_mime_parser_new ();
- camel_mime_parser_init_with_stream (parser, stream, NULL);
-
- opart = camel_mime_part_new ();
- camel_mime_part_construct_from_parser_sync (opart, parser, cancellable, NULL);
-
- em_format_parse_part_as (emf, opart, part_id, &oinfo,
- "x-evolution/message", cancellable);
-
- /* Add another generic PURI that represents end of the RFC message.
- * The em_format_write() function will skip all PURIs between the ".rfc822"
- * PURI and ".rfc822.end" PURI as they will be rendered in an <iframe> */
- g_string_append (part_id, ".end");
- puri = em_format_puri_new (emf, sizeof (EMFormatPURI), NULL, part_id->str);
- em_format_add_puri (emf, puri);
-
- g_string_truncate (part_id, len);
-
- g_object_unref (opart);
- g_object_unref (parser);
- g_object_unref (stream);
-}
-
-/*****************************************************************************/
-
-static void
-efh_write_image (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- gchar *content;
- EMFormatHTML *efh;
- CamelDataWrapper *dw;
- GByteArray *ba;
- CamelStream *raw_content;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- efh = (EMFormatHTML *) emf;
-
- dw = camel_medium_get_content (CAMEL_MEDIUM (puri->part));
- g_return_if_fail (dw);
-
- raw_content = camel_stream_mem_new ();
- camel_data_wrapper_decode_to_stream_sync (dw, raw_content, cancellable, NULL);
- ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (raw_content));
-
- if (info->mode == EM_FORMAT_WRITE_MODE_RAW) {
-
- if (!efh->priv->animate_images) {
-
- gchar *buff;
- gsize len;
-
- em_format_html_animation_extract_frame (ba, &buff, &len);
-
- camel_stream_write (stream, buff, len, cancellable, NULL);
-
- g_free (buff);
-
- } else {
-
- camel_stream_write_to_stream (raw_content, stream, cancellable, NULL);
- }
-
- } else {
-
- gchar *buffer;
-
- if (!efh->priv->animate_images) {
-
- gchar *buff;
- gsize len;
-
- em_format_html_animation_extract_frame (ba, &buff, &len);
-
- content = g_base64_encode ((guchar *) buff, len);
- g_free (buff);
-
- } else {
- content = g_base64_encode ((guchar *) ba->data, ba->len);
- }
-
- /* The image is already base64-encrypted so we can directly
- * paste it to the output */
- buffer = g_strdup_printf (
- "<img src=\"data:%s;base64,%s\" style=\"max-width: 100%%;\" />",
- puri->mime_type ? puri->mime_type : "image/*", content);
-
- camel_stream_write_string (stream, buffer, cancellable, NULL);
- g_free (buffer);
- g_free (content);
- }
-
- g_object_unref (raw_content);
-}
-
-static void
-efh_write_text_enriched (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatHTML *efh = EM_FORMAT_HTML (emf);
- CamelStream *filtered_stream;
- CamelMimeFilter *enriched;
- guint32 flags = 0;
- GString *buffer;
- CamelContentType *ct;
- gchar *mime_type = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- ct = camel_mime_part_get_content_type (puri->part);
- if (ct) {
- mime_type = camel_content_type_simple (ct);
- }
-
- if (!g_strcmp0(mime_type, "text/richtext")) {
- flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT;
- camel_stream_write_string (
- stream, "\n<!-- text/richtext -->\n",
- cancellable, NULL);
- } else {
- camel_stream_write_string (
- stream, "\n<!-- text/enriched -->\n",
- cancellable, NULL);
- }
-
- if (mime_type)
- g_free (mime_type);
-
- enriched = camel_mime_filter_enriched_new (flags);
- filtered_stream = camel_stream_filter_new (stream);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), enriched);
- g_object_unref (enriched);
-
- buffer = g_string_new ("");
-
- g_string_append_printf (buffer,
- "<div class=\"part-container\" style=\"border-color: #%06x; "
- "background-color: #%06x; color: #%06x;\">"
- "<div class=\"part-container-inner-margin\">\n",
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_FRAME]),
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_CONTENT]),
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_TEXT]));
-
- camel_stream_write_string (stream, buffer->str, cancellable, NULL);
- g_string_free (buffer, TRUE);
-
- em_format_format_text (
- emf, (CamelStream *) filtered_stream,
- (CamelDataWrapper *) puri->part, cancellable);
-
- g_object_unref (filtered_stream);
- camel_stream_write_string (stream, "</div></div>", cancellable, NULL);
-}
-
-static void
-efh_write_text_plain (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- CamelDataWrapper *dw;
- CamelStream *filtered_stream;
- CamelMimeFilter *html_filter;
- EMFormatHTML *efh = (EMFormatHTML *) emf;
- gchar *content;
- const gchar *format;
- guint32 flags;
- guint32 rgb;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- flags = efh->text_html_flags;
-
- dw = camel_medium_get_content (CAMEL_MEDIUM (puri->part));
-
- /* Check for RFC 2646 flowed text. */
- if (camel_content_type_is(dw->mime_type, "text", "plain")
- && (format = camel_content_type_param(dw->mime_type, "format"))
- && !g_ascii_strcasecmp(format, "flowed"))
- flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED;
-
- rgb = e_color_to_value (
- &efh->priv->colors[EM_FORMAT_HTML_COLOR_CITATION]);
- filtered_stream = camel_stream_filter_new (stream);
- html_filter = camel_mime_filter_tohtml_new (flags, rgb);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), html_filter);
- g_object_unref (html_filter);
-
- content = g_strdup_printf (
- "<div class=\"part-container\" style=\"border-color: #%06x; "
- "background-color: #%06x; color: #%06x;\">"
- "<div class=\"part-container-inner-margin pre\">\n",
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_FRAME]),
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_CONTENT]),
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_TEXT]));
-
- camel_stream_write_string (stream, content, cancellable, NULL);
- em_format_format_text (emf, filtered_stream, (CamelDataWrapper *) puri->part, cancellable);
- camel_stream_flush (filtered_stream, cancellable, NULL);
-
- g_object_unref (filtered_stream);
- g_free (content);
-
- camel_stream_write_string (stream, "</div></div>\n", cancellable, NULL);
-}
-
-static gchar *
-get_tag (const gchar *tag_name,
- gchar *opening,
- gchar *closing)
-{
- gchar *t;
- gboolean has_end;
-
- for (t = closing - 1; t != opening; t--) {
- if (*t != ' ')
- break;
- }
-
- /* Not a pair tag */
- if (*t == '/')
- return g_strndup (opening, closing - opening + 1);
-
- for (t = closing; t && *t; t++) {
- if (*t == '<')
- break;
- }
-
- do {
- if (*t == '/') {
- has_end = TRUE;
- break;
- }
-
- if (*t == '>') {
- has_end = FALSE;
- break;
- }
-
- t++;
-
- } while (t && *t);
-
- /* Broken HTML? */
- if (!has_end)
- return g_strndup (opening, closing - opening + 1);
-
- do {
- if ((*t != ' ') && (*t != '/'))
- break;
-
- t++;
- } while (t && *t);
-
- if (g_strncasecmp (t, tag_name, strlen (tag_name)) == 0) {
-
- closing = strstr (t, ">");
-
- return g_strndup (opening, closing - opening + strlen (tag_name));
- }
-
- /* Broken HTML? */
- return g_strndup (opening, closing - opening + 1);
-}
-
-static void
-efh_write_text_html (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatHTML *efh = (EMFormatHTML *) emf;
-
- if (g_cancellable_is_cancelled (cancellable))
- return;
-
- if (info->mode == EM_FORMAT_WRITE_MODE_RAW) {
- em_format_format_text (emf, stream,
- (CamelDataWrapper *) puri->part, cancellable);
-
- } else if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
- GString *string;
- GByteArray *ba;
- gchar *pos;
- GList *tags, *iter;
- gboolean valid;
- gchar *tag;
- const gchar *document_end;
- gint length;
- gint i;
- CamelStream *decoded_stream;
-
- decoded_stream = camel_stream_mem_new ();
- em_format_format_text (emf, decoded_stream,
- (CamelDataWrapper *) puri->part, cancellable);
- g_seekable_seek (G_SEEKABLE (decoded_stream), 0, G_SEEK_SET, cancellable, NULL);
-
- ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (decoded_stream));
- string = g_string_new_len ((gchar *) ba->data, ba->len);
-
- g_object_unref (decoded_stream);
-
- tags = NULL;
- pos = string->str;
- valid = FALSE;
- do {
- gchar *closing;
- gchar *opening;
-
- pos = strstr (pos + 1, "<");
- if (!pos)
- break;
-
- opening = pos;
- closing = strstr (pos, ">");
-
- /* Find where the actual tag name begins */
- for (tag = pos + 1; tag && *tag; tag++) {
- if (*tag != ' ')
- break;
- }
-
- if (g_ascii_strncasecmp (tag, "style", 5) == 0) {
- tags = g_list_append (
- tags,
- get_tag ("style", opening, closing));
- } else if (g_ascii_strncasecmp (tag, "script", 6) == 0) {
- tags = g_list_append (
- tags,
- get_tag ("script", opening, closing));
- } else if (g_ascii_strncasecmp (tag, "link", 4) == 0) {
- tags = g_list_append (
- tags,
- get_tag ("link", opening, closing));
- } else if (g_ascii_strncasecmp (tag, "body", 4) == 0) {
- valid = TRUE;
- break;
- }
-
- } while (TRUE);
-
- /* Something's wrong, let's write the entire HTML and hope
- * that WebKit can handle it */
- if (!valid) {
- EMFormatWriterInfo i = *info;
- i.mode = EM_FORMAT_WRITE_MODE_RAW;
- efh_write_text_html (emf, puri, stream, &i, cancellable);
- return;
- }
-
- /* include the "body" as well -----v */
- g_string_erase (string, 0, tag - string->str + 4);
- g_string_prepend (string, "<div ");
-
- for (iter = tags; iter; iter = iter->next) {
- g_string_prepend (string, iter->data);
- }
-
- g_list_free_full (tags, g_free);
-
- /* that's reversed </body></html>... */
- document_end = ">lmth/<>ydob/<";
- length = strlen (document_end);
- tag = string->str + string->len - 1;
- i = 0;
- valid = FALSE;
- while (i < length - 1) {
- gchar c;
-
- if (g_ascii_isspace (*tag)) {
- tag--;
- continue;
- }
-
- if ((*tag >= 'A') && (*tag <= 'Z'))
- c = *tag + 32;
- else
- c = *tag;
-
- if (c == document_end[i]) {
- tag--;
- i++;
- valid = TRUE;
- continue;
- }
-
- valid = FALSE;
- }
-
- if (valid)
- g_string_truncate (string, tag - string->str);
-
- camel_stream_write_string (stream, string->str, cancellable, NULL);
-
- g_string_free (string, TRUE);
- } else {
- gchar *str;
- gchar *uri;
-
- uri = em_format_build_mail_uri (
- emf->folder, emf->message_uid,
- "part_id", G_TYPE_STRING, puri->uri,
- "mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW,
- NULL);
-
- str = g_strdup_printf (
- "<div class=\"part-container-nostyle\">"
- "<iframe width=\"100%%\" height=\"auto\""
- " frameborder=\"0\" src=\"%s\" "
- " style=\"border: 1px solid #%06x; background-color: #%06x;\">"
- "</iframe>"
- "</div>",
- uri,
- e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_FRAME]),
- e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT]));
-
- camel_stream_write_string (stream, str, cancellable, NULL);
-
- g_free (str);
- g_free (uri);
- }
-}
-
-static void
-efh_write_source (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- EMFormatHTML *efh = (EMFormatHTML *) emf;
- GString *buffer;
- CamelStream *filtered_stream;
- CamelMimeFilter *filter;
- CamelDataWrapper *dw = (CamelDataWrapper *) puri->part;
-
- filtered_stream = camel_stream_filter_new (stream);
-
- filter = camel_mime_filter_tohtml_new (
- CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
- CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0);
- camel_stream_filter_add (
- CAMEL_STREAM_FILTER (filtered_stream), filter);
- g_object_unref (filter);
-
- buffer = g_string_new ("");
-
- g_string_append_printf (
- buffer, "<div class=\"part-container\" style=\"border: 0; background: #%06x; color: #%06x;\" >",
- e_color_to_value (
- &efh->priv->colors[
- EM_FORMAT_HTML_COLOR_BODY]),
- e_color_to_value (
- &efh->priv->colors[
- EM_FORMAT_HTML_COLOR_TEXT]));
-
- camel_stream_write_string (
- stream, buffer->str, cancellable, NULL);
- camel_stream_write_string (
- stream, "<code class=\"pre\">", cancellable, NULL);
- camel_data_wrapper_write_to_stream_sync (dw, filtered_stream,
- cancellable, NULL);
- camel_stream_write_string (
- stream, "</code>", cancellable, NULL);
-
- g_object_unref (filtered_stream);
- g_string_free (buffer, TRUE);
-}
-
-static void
-efh_write_headers (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GString *buffer;
- EMFormatHTML *efh = (EMFormatHTML *) emf;
- gint bg_color;
-
- if (!puri->part)
- return;
-
- buffer = g_string_new ("");
-
- if (info->mode & EM_FORMAT_WRITE_MODE_PRINTING) {
- GdkColor white = { 0, G_MAXUINT16, G_MAXUINT16, G_MAXUINT16 };
- bg_color = e_color_to_value (&white);
- } else {
- bg_color = e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_BODY]);
- }
-
- g_string_append_printf (
- buffer,
- "<div class=\"headers\" style=\"background: #%06x;\">"
- "<table border=\"0\" width=\"100%%\" style=\"color: #%06x;\">\n"
- "<tr><td valign=\"top\" width=\"16\">\n",
- bg_color,
- e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_HEADER]));
-
- if (info->headers_collapsable) {
- g_string_append_printf (buffer,
- "<img src=\"evo-file://%s/%s\" class=\"navigable\" "
- "id=\"__evo-collapse-headers-img\" />"
- "</td><td>",
- EVOLUTION_IMAGESDIR,
- (info->headers_collapsed) ? "plus.png" : "minus.png");
-
- efh_format_short_headers (efh, buffer, (CamelMedium *) puri->part,
- info->headers_collapsed,
- cancellable);
- }
-
- efh_format_full_headers (efh, buffer, (CamelMedium *) puri->part,
- (info->mode == EM_FORMAT_WRITE_MODE_ALL_HEADERS),
- !info->headers_collapsed,
- cancellable);
-
- g_string_append (buffer, "</td></tr></table></div>");
-
- camel_stream_write_string (stream, buffer->str, cancellable, NULL);
-
- g_string_free (buffer, true);
-}
-
-static void
-efh_write_error (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- CamelStream *filtered_stream;
- CamelMimeFilter *filter;
- CamelDataWrapper *dw;
-
- dw = camel_medium_get_content ((CamelMedium *) puri->part);
-
- camel_stream_write_string (stream, "<em><font color=\"red\">", cancellable, NULL);
-
- filtered_stream = camel_stream_filter_new (stream);
- filter = camel_mime_filter_tohtml_new (CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered_stream), filter);
- g_object_unref (filter);
-
- camel_data_wrapper_decode_to_stream_sync (dw, filtered_stream, cancellable, NULL);
-
- g_object_unref (filtered_stream);
-
- camel_stream_write_string (stream, "</font></em><br>", cancellable, NULL);
-}
-
-static void
-efh_write_message_rfc822 (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- if (info->mode == EM_FORMAT_WRITE_MODE_RAW) {
-
- GList *puris;
- GList *iter;
- EMFormatWriterInfo msgInfo = *info;
- msgInfo.mode = EM_FORMAT_WRITE_MODE_NORMAL;
-
- /* Create a new fake list of PURIs which will contain only
- * PURIs from this message. */
- iter = g_hash_table_lookup (emf->mail_part_table, puri->uri);
- if (!iter || !iter->next)
- return;
-
- iter = iter->next;
- puris = NULL;
- while (iter) {
-
- EMFormatPURI *p;
- p = iter->data;
-
- if (g_str_has_suffix (p->uri, ".rfc822.end"))
- break;
-
- puris = g_list_append (puris, p);
- iter = iter->next;
-
- };
-
- efh_write_message (emf, puris, stream, &msgInfo, cancellable);
-
- g_list_free (puris);
-
- } else if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
-
- GList *iter;
- gboolean can_write = FALSE;
-
- iter = g_hash_table_lookup (emf->mail_part_table, puri->uri);
- if (!iter || !iter->next)
- return;
-
- /* Skip everything before attachment bar, inclusive */\
- iter = iter->next;
- while (iter) {
-
- EMFormatPURI *p = iter->data;
-
- /* EMFormatHTMLPrint has registered a special writer
- * for headers, try to find it and use it. */
- if (g_str_has_suffix (p->uri, ".headers")) {
-
- const EMFormatHandler *handler;
-
- handler = em_format_find_handler (
- emf, "x-evolution/message/headers");
- if (handler && handler->write_func)
- handler->write_func (emf, p, stream, info, cancellable);
-
- iter = iter->next;
- continue;
- }
-
- if (g_str_has_suffix (p->uri, ".rfc822.end"))
- break;
-
- if (g_str_has_suffix (p->uri, ".attachment-bar"))
- can_write = TRUE;
-
- if (can_write && p->write_func) {
- p->write_func (
- emf, p, stream, info, cancellable);
- }
-
- iter = iter->next;
- }
-
- } else {
- gchar *str;
- gchar *uri;
-
- EMFormatHTML *efh = (EMFormatHTML *) emf;
- EMFormatPURI *p;
- GList *iter;
-
- iter = g_hash_table_lookup (emf->mail_part_table, puri->uri);
- if (!iter || !iter->next)
- return;
-
- iter = iter->next;
- p = iter->data;
-
- uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
- "part_id", G_TYPE_STRING, p->uri,
- "mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW,
- NULL);
-
- str = g_strdup_printf (
- "<div class=\"part-container\" style=\"border-color: #%06x; "
- "background-color: #%06x;\">"
- "<div class=\"part-container-inner-margin\">\n"
- "<iframe width=\"100%%\" height=\"auto\""
- " frameborder=\"0\" src=\"%s\" name=\"%s\"></iframe>"
- "</div></div>",
- e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_FRAME]),
- e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT]),
- uri, puri->uri);
-
- camel_stream_write_string (stream, str, cancellable, NULL);
-
- g_free (str);
- g_free (uri);
- }
-
-}
-
-/*****************************************************************************/
-
-/* Notes:
- *
- * image/tiff is omitted because it's a multi-page image format, but
- * gdk-pixbuf unconditionally renders the first page only, and doesn't
- * even indicate through meta-data whether multiple pages are present
- * (see bug 335959). Therefore, make no attempt to render TIFF images
- * inline and defer to an application that can handle multi-page TIFF
- * files properly like Evince or Gimp. Once the referenced bug is
- * fixed we can reevaluate this policy.
- */
-static EMFormatHandler type_builtin_table[] = {
- { (gchar *) "image/gif", efh_parse_image, efh_write_image, },
- { (gchar *) "image/jpeg", efh_parse_image, efh_write_image, },
- { (gchar *) "image/png", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-png", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-bmp", efh_parse_image, efh_write_image, },
- { (gchar *) "image/bmp", efh_parse_image, efh_write_image, },
- { (gchar *) "image/svg", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-cmu-raster", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-ico", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-portable-anymap", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-portable-bitmap", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-portable-graymap", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-portable-pixmap", efh_parse_image, efh_write_image, },
- { (gchar *) "image/x-xpixmap", efh_parse_image, efh_write_image, },
- { (gchar *) "text/enriched", efh_parse_text_enriched, efh_write_text_enriched, },
- { (gchar *) "text/plain", efh_parse_text_plain, efh_write_text_plain, },
- { (gchar *) "text/html", efh_parse_text_html, efh_write_text_html, },
- { (gchar *) "text/richtext", efh_parse_text_enriched, efh_write_text_enriched, },
- { (gchar *) "text/*", efh_parse_text_plain, efh_write_text_plain, },
- { (gchar *) "message/rfc822", efh_parse_message_rfc822, efh_write_message_rfc822, EM_FORMAT_HANDLER_INLINE | EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "message/news", efh_parse_message_rfc822, 0, EM_FORMAT_HANDLER_INLINE | EM_FORMAT_HANDLER_COMPOUND_TYPE },
- { (gchar *) "message/delivery-status", efh_parse_message_deliverystatus, efh_write_text_plain, },
- { (gchar *) "message/external-body", efh_parse_message_external, efh_write_text_plain, },
- { (gchar *) "message/*", efh_parse_message_rfc822, 0, EM_FORMAT_HANDLER_INLINE },
-
- /* This is where one adds those busted, non-registered types,
- * that some idiot mailer writers out there decide to pull out
- * of their proverbials at random. */
- { (gchar *) "image/jpg", efh_parse_image, efh_write_image, },
- { (gchar *) "image/pjpeg", efh_parse_image, efh_write_image, },
-
- /* special internal types */
- { (gchar *) "x-evolution/message/rfc822", 0, efh_write_text_plain, },
- { (gchar *) "x-evolution/message/headers", 0, efh_write_headers, },
- { (gchar *) "x-evolution/message/source", 0, efh_write_source, },
- { (gchar *) "x-evolution/message/attachment", 0, efh_write_attachment, },
- { (gchar *) "x-evolution/message/error", 0, efh_write_error, },
-};
-
-static void
-efh_builtin_init (EMFormatHTMLClass *efhc)
-{
- EMFormatClass *emfc;
- gint ii;
-
- emfc = (EMFormatClass *) efhc;
-
- for (ii = 0; ii < G_N_ELEMENTS (type_builtin_table); ii++)
- em_format_class_add_handler (
- emfc, &type_builtin_table[ii]);
-}
-
-static void
-efh_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_BODY_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_BODY,
- g_value_get_boxed (value));
- return;
-
- case PROP_CITATION_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_CITATION,
- g_value_get_boxed (value));
- return;
-
- case PROP_CONTENT_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_CONTENT,
- g_value_get_boxed (value));
- return;
-
- case PROP_FRAME_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_FRAME,
- g_value_get_boxed (value));
- return;
-
- case PROP_HEADER_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_HEADER,
- g_value_get_boxed (value));
- return;
-
- case PROP_IMAGE_LOADING_POLICY:
- em_format_html_set_image_loading_policy (
- EM_FORMAT_HTML (object),
- g_value_get_enum (value));
- return;
-
- case PROP_MARK_CITATIONS:
- em_format_html_set_mark_citations (
- EM_FORMAT_HTML (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_ONLY_LOCAL_PHOTOS:
- em_format_html_set_only_local_photos (
- EM_FORMAT_HTML (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_SHOW_SENDER_PHOTO:
- em_format_html_set_show_sender_photo (
- EM_FORMAT_HTML (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_SHOW_REAL_DATE:
- em_format_html_set_show_real_date (
- EM_FORMAT_HTML (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_TEXT_COLOR:
- em_format_html_set_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_TEXT,
- g_value_get_boxed (value));
- return;
-
- case PROP_ANIMATE_IMAGES:
- em_format_html_set_animate_images (
- EM_FORMAT_HTML (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-efh_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GdkColor color;
-
- switch (property_id) {
- case PROP_BODY_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_BODY,
- &color);
- g_value_set_boxed (value, &color);
- return;
-
- case PROP_CITATION_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_CITATION,
- &color);
- g_value_set_boxed (value, &color);
- return;
-
- case PROP_CONTENT_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_CONTENT,
- &color);
- g_value_set_boxed (value, &color);
- return;
-
- case PROP_FRAME_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_FRAME,
- &color);
- g_value_set_boxed (value, &color);
- return;
-
- case PROP_HEADER_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_HEADER,
- &color);
- g_value_set_boxed (value, &color);
- return;
-
- case PROP_IMAGE_LOADING_POLICY:
- g_value_set_enum (
- value,
- em_format_html_get_image_loading_policy (
- EM_FORMAT_HTML (object)));
- return;
-
- case PROP_MARK_CITATIONS:
- g_value_set_boolean (
- value, em_format_html_get_mark_citations (
- EM_FORMAT_HTML (object)));
- return;
-
- case PROP_ONLY_LOCAL_PHOTOS:
- g_value_set_boolean (
- value, em_format_html_get_only_local_photos (
- EM_FORMAT_HTML (object)));
- return;
-
- case PROP_SHOW_SENDER_PHOTO:
- g_value_set_boolean (
- value, em_format_html_get_show_sender_photo (
- EM_FORMAT_HTML (object)));
- return;
-
- case PROP_SHOW_REAL_DATE:
- g_value_set_boolean (
- value, em_format_html_get_show_real_date (
- EM_FORMAT_HTML (object)));
- return;
-
- case PROP_TEXT_COLOR:
- em_format_html_get_color (
- EM_FORMAT_HTML (object),
- EM_FORMAT_HTML_COLOR_TEXT,
- &color);
- g_value_set_boxed (value, &color);
- return;
- case PROP_ANIMATE_IMAGES:
- g_value_set_boolean (
- value, em_format_html_get_animate_images (
- EM_FORMAT_HTML (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-efh_finalize (GObject *object)
-{
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-efh_constructed (GObject *object)
-{
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (parent_class)->constructed (object);
-
- e_extensible_load_extensions (E_EXTENSIBLE (object));
-}
-
-static void
-efh_write_attachment (EMFormat *emf,
- EMFormatPURI *puri,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- gchar *text, *html;
- CamelContentType *ct;
- gchar *mime_type;
- const EMFormatHandler *handler;
-
- /* we display all inlined attachments only */
-
- /* this could probably be cleaned up ... */
- camel_stream_write_string (
- stream,
- "<table border=1 cellspacing=0 cellpadding=0><tr><td>"
- "<table width=10 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td>"
- "<td><table width=3 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td><td><font size=-1>\n",
- cancellable, NULL);
-
- ct = camel_mime_part_get_content_type (puri->part);
- mime_type = camel_content_type_simple (ct);
-
- /* output some info about it */
- text = em_format_describe_part (puri->part, mime_type);
- html = camel_text_to_html (
- text, ((EMFormatHTML *) emf)->text_html_flags &
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- camel_stream_write_string (stream, html, cancellable, NULL);
- g_free (html);
- g_free (text);
-
- camel_stream_write_string (
- stream, "</font></td></tr><tr></table>", cancellable, NULL);
-
- handler = em_format_find_handler (emf, mime_type);
- if (handler && handler->write_func && handler->write_func != efh_write_attachment) {
- if (em_format_is_inline (emf, puri->uri, puri->part, handler))
- handler->write_func (emf, puri, stream, info, cancellable);
- }
-
- g_free (mime_type);
-}
-
-static void
-efh_preparse (EMFormat *emf)
-{
- EMFormatHTML *efh = EM_FORMAT_HTML (emf);
- CamelInternetAddress *addr;
- CamelSession *session;
- ESourceRegistry *registry;
-
- if (!emf->message) {
- efh->priv->can_load_images = FALSE;
- return;
- }
-
- session = em_format_get_session (emf);
- registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
-
- addr = camel_mime_message_get_from (emf->message);
- efh->priv->can_load_images = em_utils_in_addressbook (
- registry, addr, FALSE);
-}
-
-static void
-efh_write_message (EMFormat *emf,
- GList *puris,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- GList *iter;
- EMFormatHTML *efh;
- gchar *header;
-
- efh = (EMFormatHTML *) emf;
-
- header = g_strdup_printf (
- "<!DOCTYPE HTML>\n<html>\n"
- "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\" />\n"
- "<title>Evolution Mail Display</title>\n"
- "<link type=\"text/css\" rel=\"stylesheet\" href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview.css\" />\n"
- "<style type=\"text/css\">\n"
- " table th { color: #000; font-weight: bold; }\n"
- "</style>\n"
- "</head><body bgcolor=\"#%06x\">",
- e_color_to_value (&efh->priv->colors[
- EM_FORMAT_HTML_COLOR_BODY]));
-
- camel_stream_write_string (stream, header, cancellable, NULL);
- g_free (header);
-
- if (info->mode == EM_FORMAT_WRITE_MODE_SOURCE) {
-
- efh_write_source (emf, emf->mail_part_list->data,
- stream, info, cancellable);
-
- camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
- return;
- }
-
- for (iter = puris; iter; iter = iter->next) {
-
- EMFormatPURI *puri = iter->data;
-
- if (!puri)
- continue;
-
- /* If current PURI has suffix .rfc822 then iterate through all
- * subsequent PURIs until PURI with suffix .rfc822.end is found.
- * These skipped PURIs contain entire RFC message which will
- * be written in <iframe> as attachment.
- */
- if (g_str_has_suffix (puri->uri, ".rfc822")) {
-
- /* If the PURI is not an attachment, then we must
- * inline it here otherwise it would not be displayed. */
- if (!puri->is_attachment && puri->write_func) {
- /* efh_write_message_rfc822 starts parsing _after_
- * the passed PURI, so we must give it previous PURI here */
- EMFormatPURI *p;
- if (!iter->prev)
- continue;
-
- p = iter->prev->data;
- puri->write_func (emf, p, stream, info, cancellable);
- }
-
- while (iter && !g_str_has_suffix (puri->uri, ".rfc822.end")) {
-
- iter = iter->next;
- if (iter)
- puri = iter->data;
-
- d(printf(".rfc822 - skipping %s\n", puri->uri));
- }
-
- /* Skip the .rfc822.end PURI as well. */
- if (!iter)
- break;
-
- continue;
- }
-
- if (puri->write_func && !puri->is_attachment) {
- puri->write_func (emf, puri, stream, info, cancellable);
- d(printf("Writing PURI %s\n", puri->uri));
- } else {
- d(printf("Skipping PURI %s\n", puri->uri));
- }
- }
-
- camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
-}
-
-static void
-efh_write (EMFormat *emf,
- CamelStream *stream,
- EMFormatWriterInfo *info,
- GCancellable *cancellable)
-{
- efh_write_message (emf, emf->mail_part_list, stream, info, cancellable);
-}
-
-static void
-efh_base_init (EMFormatHTMLClass *klass)
-{
- efh_builtin_init (klass);
-}
-
-static void
-efh_class_init (EMFormatHTMLClass *klass)
-{
- GObjectClass *object_class;
- EMFormatClass *emf_class;
-
- parent_class = g_type_class_peek_parent (klass);
- g_type_class_add_private (klass, sizeof (EMFormatHTMLPrivate));
-
- emf_class = EM_FORMAT_CLASS (klass);
- emf_class->preparse = efh_preparse;
- emf_class->write = efh_write;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->constructed = efh_constructed;
- object_class->set_property = efh_set_property;
- object_class->get_property = efh_get_property;
- object_class->finalize = efh_finalize;
-
- g_object_class_install_property (
- object_class,
- PROP_BODY_COLOR,
- g_param_spec_boxed (
- "body-color",
- "Body Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_CITATION_COLOR,
- g_param_spec_boxed (
- "citation-color",
- "Citation Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_CONTENT_COLOR,
- g_param_spec_boxed (
- "content-color",
- "Content Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_FRAME_COLOR,
- g_param_spec_boxed (
- "frame-color",
- "Frame Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_HEADER_COLOR,
- g_param_spec_boxed (
- "header-color",
- "Header Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- /* FIXME Make this a proper enum property. */
- g_object_class_install_property (
- object_class,
- PROP_IMAGE_LOADING_POLICY,
- g_param_spec_enum (
- "image-loading-policy",
- "Image Loading Policy",
- NULL,
- E_TYPE_MAIL_IMAGE_LOADING_POLICY,
- E_MAIL_IMAGE_LOADING_POLICY_ALWAYS,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_MARK_CITATIONS,
- g_param_spec_boolean (
- "mark-citations",
- "Mark Citations",
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_ONLY_LOCAL_PHOTOS,
- g_param_spec_boolean (
- "only-local-photos",
- "Only Local Photos",
- NULL,
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_SENDER_PHOTO,
- g_param_spec_boolean (
- "show-sender-photo",
- "Show Sender Photo",
- NULL,
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_REAL_DATE,
- g_param_spec_boolean (
- "show-real-date",
- "Show real Date header value",
- NULL,
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (
- object_class,
- PROP_TEXT_COLOR,
- g_param_spec_boxed (
- "text-color",
- "Text Color",
- NULL,
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_ANIMATE_IMAGES,
- g_param_spec_boolean (
- "animate-images",
- "Animate images",
- NULL,
- FALSE,
- G_PARAM_READWRITE));
-}
-
-static void
-efh_init (EMFormatHTML *efh,
- EMFormatHTMLClass *klass)
-{
- GdkColor *color;
-
- efh->priv = EM_FORMAT_HTML_GET_PRIVATE (efh);
-
- g_queue_init (&efh->pending_object_list);
-
- color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_BODY];
- gdk_color_parse ("#eeeeee", color);
-
- color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT];
- gdk_color_parse ("#ffffff", color);
-
- color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_FRAME];
- gdk_color_parse ("#3f3f3f", color);
-
- color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_HEADER];
- gdk_color_parse ("#eeeeee", color);
-
- color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_TEXT];
- gdk_color_parse ("#000000", color);
-
- efh->text_html_flags =
- CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
- CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
- CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
- efh->show_icon = TRUE;
-}
-
-GType
-em_format_html_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EMFormatHTMLClass),
- (GBaseInitFunc) efh_base_init,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) efh_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EMFormatHTML),
- 0, /* n_preallocs */
- (GInstanceInitFunc) efh_init,
- NULL /* value_table */
- };
-
- static const GInterfaceInfo extensible_info = {
- (GInterfaceInitFunc) NULL,
- (GInterfaceFinalizeFunc) NULL,
- NULL /* interface_data */
- };
-
- type = g_type_register_static (
- em_format_get_type(), "EMFormatHTML",
- &type_info, G_TYPE_FLAG_ABSTRACT);
-
- g_type_add_interface_static (
- type, E_TYPE_EXTENSIBLE, &extensible_info);
- }
-
- return type;
-}
-
-/*****************************************************************************/
-void
-em_format_html_get_color (EMFormatHTML *efh,
- EMFormatHTMLColorType type,
- GdkColor *color)
-{
- GdkColor *format_color;
-
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
- g_return_if_fail (type < EM_FORMAT_HTML_NUM_COLOR_TYPES);
- g_return_if_fail (color != NULL);
-
- format_color = &efh->priv->colors[type];
-
- color->red = format_color->red;
- color->green = format_color->green;
- color->blue = format_color->blue;
-}
-
-void
-em_format_html_set_color (EMFormatHTML *efh,
- EMFormatHTMLColorType type,
- const GdkColor *color)
-{
- GdkColor *format_color;
- const gchar *property_name;
-
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
- g_return_if_fail (type < EM_FORMAT_HTML_NUM_COLOR_TYPES);
- g_return_if_fail (color != NULL);
-
- format_color = &efh->priv->colors[type];
-
- if (gdk_color_equal (color, format_color))
- return;
-
- format_color->red = color->red;
- format_color->green = color->green;
- format_color->blue = color->blue;
-
- switch (type) {
- case EM_FORMAT_HTML_COLOR_BODY:
- property_name = "body-color";
- break;
- case EM_FORMAT_HTML_COLOR_CITATION:
- property_name = "citation-color";
- break;
- case EM_FORMAT_HTML_COLOR_CONTENT:
- property_name = "content-color";
- break;
- case EM_FORMAT_HTML_COLOR_FRAME:
- property_name = "frame-color";
- break;
- case EM_FORMAT_HTML_COLOR_HEADER:
- property_name = "header-color";
- break;
- case EM_FORMAT_HTML_COLOR_TEXT:
- property_name = "text-color";
- break;
- default:
- g_return_if_reached ();
- }
-
- g_object_notify (G_OBJECT (efh), property_name);
-}
-
-EMailImageLoadingPolicy
-em_format_html_get_image_loading_policy (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), 0);
-
- return efh->priv->image_loading_policy;
-}
-
-void
-em_format_html_set_image_loading_policy (EMFormatHTML *efh,
- EMailImageLoadingPolicy policy)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- if (policy == efh->priv->image_loading_policy)
- return;
-
- efh->priv->image_loading_policy = policy;
-
- g_object_notify (G_OBJECT (efh), "image-loading-policy");
-}
-
-gboolean
-em_format_html_get_mark_citations (EMFormatHTML *efh)
-{
- guint32 flags;
-
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- flags = efh->text_html_flags;
-
- return ((flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) != 0);
-}
-
-void
-em_format_html_set_mark_citations (EMFormatHTML *efh,
- gboolean mark_citations)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- if (mark_citations)
- efh->text_html_flags |=
- CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
- else
- efh->text_html_flags &=
- ~CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
-
- g_object_notify (G_OBJECT (efh), "mark-citations");
-}
-
-gboolean
-em_format_html_get_only_local_photos (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- return efh->priv->only_local_photos;
-}
-
-void
-em_format_html_set_only_local_photos (EMFormatHTML *efh,
- gboolean only_local_photos)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- efh->priv->only_local_photos = only_local_photos;
-
- g_object_notify (G_OBJECT (efh), "only-local-photos");
-}
-
-gboolean
-em_format_html_get_show_sender_photo (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- return efh->priv->show_sender_photo;
-}
-
-void
-em_format_html_set_show_sender_photo (EMFormatHTML *efh,
- gboolean show_sender_photo)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- efh->priv->show_sender_photo = show_sender_photo;
-
- g_object_notify (G_OBJECT (efh), "show-sender-photo");
-}
-
-gboolean
-em_format_html_get_show_real_date (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- return efh->priv->show_real_date;
-}
-
-void
-em_format_html_set_show_real_date (EMFormatHTML *efh,
- gboolean show_real_date)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- efh->priv->show_real_date = show_real_date;
-
- g_object_notify (G_OBJECT (efh), "show-real-date");
-}
-
-gboolean
-em_format_html_get_animate_images (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- return efh->priv->animate_images;
-}
-
-void
-em_format_html_set_animate_images (EMFormatHTML *efh,
- gboolean animate_images)
-{
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- efh->priv->animate_images = animate_images;
-
- g_object_notify (G_OBJECT (efh), "animate-images");
-}
-
-CamelMimePart *
-em_format_html_file_part (EMFormatHTML *efh,
- const gchar *mime_type,
- const gchar *filename,
- GCancellable *cancellable)
-{
- CamelMimePart *part;
- CamelStream *stream;
- CamelDataWrapper *dw;
- gchar *basename;
-
- stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0, NULL);
- if (stream == NULL)
- return NULL;
-
- dw = camel_data_wrapper_new ();
- camel_data_wrapper_construct_from_stream_sync (
- dw, stream, cancellable, NULL);
- g_object_unref (stream);
- if (mime_type)
- camel_data_wrapper_set_mime_type (dw, mime_type);
- part = camel_mime_part_new ();
- camel_medium_set_content ((CamelMedium *) part, dw);
- g_object_unref (dw);
- basename = g_path_get_basename (filename);
- camel_mime_part_set_filename (part, basename);
- g_free (basename);
-
- return part;
-}
-
-void
-em_format_html_format_cert_infos (GQueue *cert_infos,
- GString *output_buffer)
-{
- GQueue valid = G_QUEUE_INIT;
- GList *head, *link;
-
- g_return_if_fail (cert_infos != NULL);
- g_return_if_fail (output_buffer != NULL);
-
- head = g_queue_peek_head_link (cert_infos);
-
- /* Make sure we have a valid CamelCipherCertInfo before
- * appending anything to the output buffer, so we don't
- * end up with "()". */
- for (link = head; link != NULL; link = g_list_next (link)) {
- CamelCipherCertInfo *cinfo = link->data;
-
- if ((cinfo->name != NULL && *cinfo->name != '\0') ||
- (cinfo->email != NULL && *cinfo->email != '\0')) {
- g_queue_push_tail (&valid, cinfo);
- }
- }
-
- if (g_queue_is_empty (&valid))
- return;
-
- g_string_append (output_buffer, " (");
-
- while (!g_queue_is_empty (&valid)) {
- CamelCipherCertInfo *cinfo;
-
- cinfo = g_queue_pop_head (&valid);
-
- if (cinfo->name != NULL && *cinfo->name != '\0') {
- g_string_append (output_buffer, cinfo->name);
-
- if (cinfo->email != NULL && *cinfo->email != '\0') {
- g_string_append (output_buffer, " <");
- g_string_append (output_buffer, cinfo->email);
- g_string_append (output_buffer, ">");
- }
-
- } else if (cinfo->email != NULL && *cinfo->email != '\0') {
- g_string_append (output_buffer, cinfo->email);
- }
-
- if (!g_queue_is_empty (&valid))
- g_string_append (output_buffer, ", ");
- }
-
- g_string_append_c (output_buffer, ')');
-}
-
-static void
-efh_format_text_header (EMFormatHTML *emfh,
- GString *buffer,
- const gchar *label,
- const gchar *value,
- guint32 flags)
-{
- const gchar *fmt, *html;
- gchar *mhtml = NULL;
- gboolean is_rtl;
-
- if (value == NULL)
- return;
-
- while (*value == ' ')
- value++;
-
- if (!(flags & EM_FORMAT_HTML_HEADER_HTML))
- html = mhtml = camel_text_to_html (value, emfh->text_html_flags, 0);
- else
- html = value;
-
- is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
-
- if (flags & EM_FORMAT_HTML_HEADER_NOCOLUMNS) {
- if (flags & EM_FORMAT_HEADER_BOLD) {
- fmt = "<tr class=\"header-item\" style=\"display: %s\"><td><b>%s:</b> %s</td></tr>";
- } else {
- fmt = "<tr class=\"header-item\" style=\"display: %s\"><td>%s: %s</td></tr>";
- }
- } else if (flags & EM_FORMAT_HTML_HEADER_NODEC) {
- if (is_rtl)
- fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th valign=top align=\"left\" nowrap>%1$s<b>&nbsp;</b></th></tr>";
- else
- fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s<b>&nbsp;</b></th><td valign=top>%s</td></tr>";
- } else {
- if (flags & EM_FORMAT_HEADER_BOLD) {
- if (is_rtl)
- fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th align=\"left\" nowrap>%1$s:<b>&nbsp;</b></th></tr>";
- else
- fmt = "<tr class=\"header-item\" style=\"display: %s\"><th align=\"right\" valign=\"top\" nowrap>%s:<b>&nbsp;</b></th><td>%s</td></tr>";
- } else {
- if (is_rtl)
- fmt = "<tr class=\"header-item rtl\" style=\"display: %s\"><td align=\"right\" valign=\"top\" width=\"100%\">%2$s</td><td align=\"left\" nowrap>%1$s:<b>&nbsp;</b></td></tr>";
- else
- fmt = "<tr class=\"header-item\" style=\"display: %s\"><td align=\"right\" valign=\"top\" nowrap>%s:<b>&nbsp;</b></td><td>%s</td></tr>";
- }
- }
-
- g_string_append_printf (buffer, fmt,
- (flags & EM_FORMAT_HTML_HEADER_HIDDEN ? "none" : "table-row"), label, html);
-
- g_free (mhtml);
-}
-
-static const gchar *addrspec_hdrs[] = {
- "Sender", "From", "Reply-To", "To", "Cc", "Bcc",
- "Resent-Sender", "Resent-From", "Resent-Reply-To",
- "Resent-To", "Resent-Cc", "Resent-Bcc", NULL
-};
-
-static gchar *
-efh_format_address (EMFormatHTML *efh,
- GString *out,
- struct _camel_header_address *a,
- gchar *field,
- gboolean no_links)
-{
- guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
- gchar *name, *mailto, *addr;
- gint i = 0;
- gchar *str = NULL;
- gint limit = mail_config_get_address_count ();
-
- while (a) {
- if (a->name)
- name = camel_text_to_html (a->name, flags, 0);
- else
- name = NULL;
-
- switch (a->type) {
- case CAMEL_HEADER_ADDRESS_NAME:
- if (name && *name) {
- gchar *real, *mailaddr;
-
- if (strchr (a->name, ',') || strchr (a->name, ';'))
- g_string_append_printf (out, "&quot;%s&quot;", name);
- else
- g_string_append (out, name);
-
- g_string_append (out, " &lt;");
-
- /* rfc2368 for mailto syntax and url encoding extras */
- if ((real = camel_header_encode_phrase ((guchar *) a->name))) {
- mailaddr = g_strdup_printf("%s <%s>", real, a->v.addr);
- g_free (real);
- mailto = camel_url_encode (mailaddr, "?=&()");
- g_free (mailaddr);
- } else {
- mailto = camel_url_encode (a->v.addr, "?=&()");
- }
- } else {
- mailto = camel_url_encode (a->v.addr, "?=&()");
- }
- addr = camel_text_to_html (a->v.addr, flags, 0);
- if (no_links)
- g_string_append_printf (out, "%s", addr);
- else
- g_string_append_printf (out, "<a href=\"mailto:%s\">%s</a>", mailto, addr);
- g_free (mailto);
- g_free (addr);
-
- if (name && *name)
- g_string_append (out, "&gt;");
- break;
- case CAMEL_HEADER_ADDRESS_GROUP:
- g_string_append_printf (out, "%s: ", name);
- efh_format_address (efh, out, a->v.members, field, no_links);
- g_string_append_printf (out, ";");
- break;
- default:
- g_warning ("Invalid address type");
- break;
- }
-
- g_free (name);
-
- i++;
- a = a->next;
- if (a)
- g_string_append (out, ", ");
-
- /* Let us add a '...' if we have more addresses */
- if (limit > 0 && (i == limit - 1)) {
- const gchar *id = NULL;
-
- if (strcmp (field, _("To")) == 0) {
- id = "to";
- } else if (strcmp (field, _("Cc")) == 0) {
- id = "cc";
- } else if (strcmp (field, _("Bcc")) == 0) {
- id = "bcc";
- }
-
- if (id) {
- g_string_append_printf (out,
- "<span id=\"__evo-moreaddr-%s\" "
- "style=\"display: none;\">", id);
- str = g_strdup_printf (
- "<img src=\"evo-file://%s/plus.png\" "
- "id=\"__evo-moreaddr-img-%s\" class=\"navigable\">",
- EVOLUTION_IMAGESDIR, id);
- }
- }
- }
-
- if (str) {
- const gchar *id = NULL;
-
- if (strcmp (field, _("To")) == 0) {
- id = "to";
- } else if (strcmp (field, _("Cc")) == 0) {
- id = "cc";
- } else if (strcmp (field, _("Bcc")) == 0) {
- id = "bcc";
- }
-
- if (id) {
- g_string_append_printf (out,
- "</span>"
- "<span class=\"navigable\" "
- "id=\"__evo-moreaddr-ellipsis-%s\" "
- "style=\"display: inline;\">...</span>",
- id);
- }
- }
-
- return str;
-}
-
-static void
-canon_header_name (gchar *name)
-{
- gchar *inptr = name;
-
- /* canonicalise the header name... first letter is
- * capitalised and any letter following a '-' also gets
- * capitalised */
-
- if (*inptr >= 'a' && *inptr <= 'z')
- *inptr -= 0x20;
-
- inptr++;
-
- while (*inptr) {
- if (inptr[-1] == '-' && *inptr >= 'a' && *inptr <= 'z')
- *inptr -= 0x20;
- else if (*inptr >= 'A' && *inptr <= 'Z')
- *inptr += 0x20;
-
- inptr++;
- }
-}
-
-void
-em_format_html_format_header (EMFormat *emf,
- GString *buffer,
- CamelMedium *part,
- struct _camel_header_raw *header,
- guint32 flags,
- const gchar *charset)
-{
- EMFormatHTML *efh = EM_FORMAT_HTML (emf);
- gchar *name, *buf, *value = NULL;
- const gchar *label, *txt;
- gboolean addrspec = FALSE;
- gchar *str_field = NULL;
- gint i;
-
- name = g_alloca (strlen (header->name) + 1);
- strcpy (name, header->name);
- canon_header_name (name);
-
- for (i = 0; addrspec_hdrs[i]; i++) {
- if (!strcmp (name, addrspec_hdrs[i])) {
- addrspec = TRUE;
- break;
- }
- }
-
- label = _(name);
-
- if (addrspec) {
- struct _camel_header_address *addrs;
- GString *html;
- gchar *img;
- const gchar *charset = em_format_get_charset (emf) ?
- em_format_get_charset (emf) : em_format_get_default_charset (emf);
-
- buf = camel_header_unfold (header->value);
- if (!(addrs = camel_header_address_decode (buf, charset))) {
- g_free (buf);
- return;
- }
-
- g_free (buf);
-
- html = g_string_new("");
- img = efh_format_address (efh, html, addrs, (gchar *) label,
- (flags & EM_FORMAT_HTML_HEADER_NOLINKS));
-
- if (img) {
- str_field = g_strdup_printf ("%s%s:", img, label);
- label = str_field;
- flags |= EM_FORMAT_HTML_HEADER_NODEC;
- g_free (img);
- }
-
- camel_header_address_list_clear (&addrs);
- txt = value = html->str;
- g_string_free (html, FALSE);
-
- flags |= EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_HTML;
- } else if (!strcmp (name, "Subject")) {
- buf = camel_header_unfold (header->value);
- txt = value = camel_header_decode_string (buf, charset);
- g_free (buf);
-
- flags |= EM_FORMAT_HEADER_BOLD;
- } else if (!strcmp(name, "X-evolution-mailer")) {
- /* pseudo-header */
- label = _("Mailer");
- txt = value = camel_header_format_ctext (header->value, charset);
- flags |= EM_FORMAT_HEADER_BOLD;
- } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) {
- gint msg_offset, local_tz;
- time_t msg_date;
- struct tm local;
- gchar *html;
- gboolean hide_real_date;
-
- hide_real_date = !em_format_html_get_show_real_date (efh);
-
- txt = header->value;
- while (*txt == ' ' || *txt == '\t')
- txt++;
-
- html = camel_text_to_html (txt, efh->text_html_flags, 0);
-
- msg_date = camel_header_decode_date (txt, &msg_offset);
- e_localtime_with_offset (msg_date, &local, &local_tz);
-
- /* Convert message offset to minutes (e.g. -0400 --> -240) */
- msg_offset = ((msg_offset / 100) * 60) + (msg_offset % 100);
- /* Turn into offset from localtime, not UTC */
- msg_offset -= local_tz / 60;
-
- /* value will be freed at the end */
- if (!hide_real_date && !msg_offset) {
- /* No timezone difference; just show the real Date: header */
- txt = value = html;
- } else {
- gchar *date_str;
-
- date_str = e_datetime_format_format ("mail", "header",
- DTFormatKindDateTime, msg_date);
-
- if (hide_real_date) {
- /* Show only the local-formatted date, losing all timezone
- * information like Outlook does. Should we attempt to show
- * it somehow? */
- txt = value = date_str;
- } else {
- txt = value = g_strdup_printf ("%s (<I>%s</I>)", html, date_str);
- g_free (date_str);
- }
- g_free (html);
- }
- flags |= EM_FORMAT_HTML_HEADER_HTML | EM_FORMAT_HEADER_BOLD;
- } else if (!strcmp(name, "Newsgroups")) {
- struct _camel_header_newsgroup *ng, *scan;
- GString *html;
-
- buf = camel_header_unfold (header->value);
-
- if (!(ng = camel_header_newsgroups_decode (buf))) {
- g_free (buf);
- return;
- }
-
- g_free (buf);
-
- html = g_string_new("");
- scan = ng;
- while (scan) {
- if (flags & EM_FORMAT_HTML_HEADER_NOLINKS)
- g_string_append_printf (html, "%s", scan->newsgroup);
- else
- g_string_append_printf(html, "<a href=\"news:%s\">%s</a>",
- scan->newsgroup, scan->newsgroup);
- scan = scan->next;
- if (scan)
- g_string_append_printf(html, ", ");
- }
-
- camel_header_newsgroups_free (ng);
-
- txt = html->str;
- g_string_free (html, FALSE);
- flags |= EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_HTML;
- } else if (!strcmp (name, "Received") || !strncmp (name, "X-", 2)) {
- /* don't unfold Received nor extension headers */
- txt = value = camel_header_decode_string (header->value, charset);
- } else {
- /* don't unfold Received nor extension headers */
- buf = camel_header_unfold (header->value);
- txt = value = camel_header_decode_string (buf, charset);
- g_free (buf);
- }
-
- efh_format_text_header (efh, buffer, label, txt, flags);
-
- g_free (value);
- g_free (str_field);
-}
-
-static void
-efh_format_short_headers (EMFormatHTML *efh,
- GString *buffer,
- CamelMedium *part,
- gboolean visible,
- GCancellable *cancellable)
-{
- EMFormat *emf = EM_FORMAT (efh);
- const gchar *charset;
- CamelContentType *ct;
- const gchar *hdr_charset;
- gchar *evolution_imagesdir;
- gchar *subject = NULL;
- struct _camel_header_address *addrs = NULL;
- struct _camel_header_raw *header;
- GString *from;
- gboolean is_rtl;
-
- if (cancellable && g_cancellable_is_cancelled (cancellable))
- return;
-
- ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
- charset = camel_content_type_param (ct, "charset");
- charset = camel_iconv_charset_name (charset);
- hdr_charset = em_format_get_charset (emf) ?
- em_format_get_charset (emf) : em_format_get_default_charset (emf);
-
- evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
- from = g_string_new ("");
-
- g_string_append_printf (buffer,
- "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" "
- "id=\"__evo-short-headers\" style=\"display: %s\">",
- visible ? "block" : "none");
-
- header = ((CamelMimePart *) part)->headers;
- while (header) {
- if (!g_ascii_strcasecmp (header->name, "From")) {
- GString *tmp;
- if (!(addrs = camel_header_address_decode (header->value, hdr_charset))) {
- header = header->next;
- continue;
- }
- tmp = g_string_new ("");
- efh_format_address (efh, tmp, addrs, header->name, FALSE);
-
- if (tmp->len)
- g_string_printf (from, _("From: %s"), tmp->str);
- g_string_free (tmp, TRUE);
-
- } else if (!g_ascii_strcasecmp (header->name, "Subject")) {
- gchar *buf = NULL;
- subject = camel_header_unfold (header->value);
- buf = camel_header_decode_string (subject, hdr_charset);
- g_free (subject);
- subject = camel_text_to_html (buf, CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0);
- g_free (buf);
- }
- header = header->next;
- }
-
- is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
- if (is_rtl) {
- g_string_append_printf (
- buffer,
- "<tr><td width=\"100%%\" align=\"right\">%s%s%s <strong>%s</strong></td></tr>",
- from->len ? "(" : "", from->str, from->len ? ")" : "",
- subject ? subject : _("(no subject)"));
- } else {
- g_string_append_printf (
- buffer,
- "<tr><td><strong>%s</strong> %s%s%s</td></tr>",
- subject ? subject : _("(no subject)"),
- from->len ? "(" : "", from->str, from->len ? ")" : "");
- }
-
- g_string_append (buffer, "</table>");
-
- g_free (subject);
- if (addrs)
- camel_header_address_list_clear (&addrs);
-
- g_string_free (from, TRUE);
- g_free (evolution_imagesdir);
-}
-
-static void
-write_contact_picture (CamelMimePart *part,
- gint size,
- GString *buffer)
-{
- gchar *b64, *content_type;
- CamelDataWrapper *dw;
- CamelContentType *ct;
- GByteArray *ba;
-
- ba = NULL;
- dw = camel_medium_get_content (CAMEL_MEDIUM (part));
- if (dw) {
- ba = camel_data_wrapper_get_byte_array (dw);
- }
-
- if (!ba || ba->len == 0) {
-
- if (camel_mime_part_get_filename (part)) {
-
- if (size >= 0) {
- g_string_append_printf (
- buffer,
- "<img width=\"%d\" src=\"evo-file://%s\" />",
- size, camel_mime_part_get_filename (part));
- } else {
- g_string_append_printf (
- buffer,
- "<img src=\"evo-file://%s\" />",
- camel_mime_part_get_filename (part));
- }
- }
-
- return;
- }
-
- b64 = g_base64_encode (ba->data, ba->len);
- ct = camel_mime_part_get_content_type (part);
- content_type = camel_content_type_simple (ct);
-
- if (size >= 0) {
- g_string_append_printf (
- buffer,
- "<img width=\"%d\" src=\"data:%s;base64,%s\">",
- size, content_type, b64);
- } else {
- g_string_append_printf (
- buffer,
- "<img src=\"data:%s;base64,%s\">",
- content_type, b64);
- }
-
- g_free (b64);
- g_free (content_type);
-}
-
-static void
-efh_format_full_headers (EMFormatHTML *efh,
- GString *buffer,
- CamelMedium *part,
- gboolean all_headers,
- gboolean visible,
- GCancellable *cancellable)
-{
- EMFormat *emf = EM_FORMAT (efh);
- const gchar *charset;
- CamelContentType *ct;
- struct _camel_header_raw *header;
- gboolean have_icon = FALSE;
- const gchar *photo_name = NULL;
- CamelInternetAddress *cia = NULL;
- CamelSession *session;
- ESourceRegistry *registry;
- gboolean face_decoded = FALSE, contact_has_photo = FALSE;
- guchar *face_header_value = NULL;
- gsize face_header_len = 0;
- gchar *header_sender = NULL, *header_from = NULL, *name;
- gboolean mail_from_delegate = FALSE;
- const gchar *hdr_charset;
- gchar *evolution_imagesdir;
-
- if (cancellable && g_cancellable_is_cancelled (cancellable))
- return;
-
- session = em_format_get_session (emf);
- registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
-
- ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
- charset = camel_content_type_param (ct, "charset");
- charset = camel_iconv_charset_name (charset);
- hdr_charset = em_format_get_charset (emf) ?
- em_format_get_charset (emf) : em_format_get_default_charset (emf);
-
- evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
-
- g_string_append_printf (buffer,
- "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" "
- "id=\"__evo-full-headers\" style=\"display: %s\" width=\"100%%\">",
- visible ? "block" : "none");
-
- header = ((CamelMimePart *) part)->headers;
- while (header) {
- if (!g_ascii_strcasecmp (header->name, "Sender")) {
- struct _camel_header_address *addrs;
- GString *html;
-
- if (!(addrs = camel_header_address_decode (header->value, hdr_charset)))
- break;
-
- html = g_string_new("");
- name = efh_format_address (efh, html, addrs, header->name, FALSE);
-
- header_sender = html->str;
- camel_header_address_list_clear (&addrs);
-
- g_string_free (html, FALSE);
- g_free (name);
- } else if (!g_ascii_strcasecmp (header->name, "From")) {
- struct _camel_header_address *addrs;
- GString *html;
-
- if (!(addrs = camel_header_address_decode (header->value, hdr_charset)))
- break;
-
- html = g_string_new("");
- name = efh_format_address (efh, html, addrs, header->name, FALSE);
-
- header_from = html->str;
- camel_header_address_list_clear (&addrs);
-
- g_string_free (html, FALSE);
- g_free (name);
- } else if (!g_ascii_strcasecmp (header->name, "X-Evolution-Mail-From-Delegate")) {
- mail_from_delegate = TRUE;
- }
-
- header = header->next;
- }
-
- if (header_sender && header_from && mail_from_delegate) {
- gchar *bold_sender, *bold_from;
-
- g_string_append (
- buffer,
- "<tr><td><table border=1 width=\"100%%\" "
- "cellspacing=2 cellpadding=2><tr>");
- if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
- g_string_append (
- buffer, "<td align=\"right\" width=\"100%%\">");
- else
- g_string_append (
- buffer, "<td align=\"left\" width=\"100%%\">");
- bold_sender = g_strconcat ("<b>", header_sender, "</b>", NULL);
- bold_from = g_strconcat ("<b>", header_from, "</b>", NULL);
- /* Translators: This message suggests to the receipients
- * that the sender of the mail is different from the one
- * listed in From field. */
- g_string_append_printf (
- buffer,
- _("This message was sent by %s on behalf of %s"),
- bold_sender, bold_from);
- g_string_append (buffer, "</td></tr></table></td></tr>");
- g_free (bold_sender);
- g_free (bold_from);
- }
-
- g_free (header_sender);
- g_free (header_from);
-
- g_string_append (buffer, "<tr><td width=\"100%%\"><table border=0 cellpadding=\"0\">\n");
-
- g_free (evolution_imagesdir);
-
- /* dump selected headers */
- if (all_headers) {
- header = ((CamelMimePart *) part)->headers;
- while (header) {
- em_format_html_format_header (
- emf, buffer, part, header,
- EM_FORMAT_HTML_HEADER_NOCOLUMNS, charset);
- header = header->next;
- }
- } else {
- GList *link;
- gint mailer_shown = FALSE;
-
- link = g_queue_peek_head_link (&emf->header_list);
-
- while (link != NULL) {
- EMFormatHeader *h = link->data;
- gint mailer, face;
-
- header = ((CamelMimePart *) part)->headers;
- mailer = !g_ascii_strcasecmp (h->name, "X-Evolution-Mailer");
- face = !g_ascii_strcasecmp (h->name, "Face");
-
- while (header) {
- if (em_format_html_get_show_sender_photo (efh) &&
- !photo_name && !g_ascii_strcasecmp (header->name, "From"))
- photo_name = header->value;
-
- if (!mailer_shown && mailer && (
- !g_ascii_strcasecmp (header->name, "X-Mailer") ||
- !g_ascii_strcasecmp (header->name, "User-Agent") ||
- !g_ascii_strcasecmp (header->name, "X-Newsreader") ||
- !g_ascii_strcasecmp (header->name, "X-MimeOLE"))) {
- struct _camel_header_raw xmailer, *use_header = NULL;
-
- if (!g_ascii_strcasecmp (header->name, "X-MimeOLE")) {
- for (use_header = header->next; use_header; use_header = use_header->next) {
- if (!g_ascii_strcasecmp (use_header->name, "X-Mailer") ||
- !g_ascii_strcasecmp (use_header->name, "User-Agent") ||
- !g_ascii_strcasecmp (use_header->name, "X-Newsreader")) {
- /* even we have X-MimeOLE, then use rather the standard one, when available */
- break;
- }
- }
- }
-
- if (!use_header)
- use_header = header;
-
- xmailer.name = (gchar *) "X-Evolution-Mailer";
- xmailer.value = use_header->value;
- mailer_shown = TRUE;
-
- em_format_html_format_header (
- emf, buffer, part,
- &xmailer, h->flags, charset);
- if (strstr(use_header->value, "Evolution"))
- have_icon = TRUE;
- } else if (!face_decoded && face && !g_ascii_strcasecmp (header->name, "Face")) {
- gchar *cp = header->value;
-
- /* Skip over spaces */
- while (*cp == ' ')
- cp++;
-
- face_header_value = g_base64_decode (
- cp, &face_header_len);
- face_header_value = g_realloc (
- face_header_value,
- face_header_len + 1);
- face_header_value[face_header_len] = 0;
- face_decoded = TRUE;
- /* Showing an encoded "Face" header makes little sense */
- } else if (!g_ascii_strcasecmp (header->name, h->name) && !face) {
- em_format_html_format_header (
- emf, buffer, part,
- header, h->flags, charset);
- }
-
- header = header->next;
- }
-
- link = g_list_next (link);
- }
- }
-
- g_string_append (buffer, "</table></td>");
-
- if (photo_name) {
- CamelMimePart *photopart;
- gboolean only_local_photo;
-
- cia = camel_internet_address_new ();
- camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
- only_local_photo =
- em_format_html_get_only_local_photos (efh);
- photopart = em_utils_contact_photo (
- registry, cia, only_local_photo);
-
- if (photopart) {
- g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
- write_contact_picture (photopart, -1, buffer);
- g_string_append (buffer, "</td>");
- g_object_unref (photopart);
- }
- g_object_unref (cia);
- }
-
- if (!contact_has_photo && face_decoded) {
- CamelMimePart *part;
-
- part = camel_mime_part_new ();
- camel_mime_part_set_content (
- (CamelMimePart *) part,
- (const gchar *) face_header_value,
- face_header_len, "image/png");
-
- g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
- write_contact_picture (part, 48, buffer);
- g_string_append (buffer, "</td>");
-
- g_object_unref (part);
- g_free (face_header_value);
- }
-
- if (have_icon && efh->show_icon) {
- GtkIconInfo *icon_info;
- CamelMimePart *iconpart = NULL;
-
- icon_info = gtk_icon_theme_lookup_icon (
- gtk_icon_theme_get_default (),
- "evolution", 16, GTK_ICON_LOOKUP_NO_SVG);
- if (icon_info != NULL) {
- iconpart = em_format_html_file_part (
- (EMFormatHTML *) emf, "image/png",
- gtk_icon_info_get_filename (icon_info),
- cancellable);
- gtk_icon_info_free (icon_info);
- }
- if (iconpart) {
- g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
- write_contact_picture (iconpart, 16, buffer);
- g_string_append (buffer, "</td>");
-
- g_object_unref (iconpart);
- }
- }
-
- g_string_append (buffer, "</tr></table>");
-}
-
-gboolean
-em_format_html_can_load_images (EMFormatHTML *efh)
-{
- g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
- return ((efh->priv->image_loading_policy == E_MAIL_IMAGE_LOADING_POLICY_ALWAYS) ||
- ((efh->priv->image_loading_policy == E_MAIL_IMAGE_LOADING_POLICY_SOMETIMES) &&
- efh->priv->can_load_images));
-}
-
-void
-em_format_html_animation_extract_frame (const GByteArray *anim,
- gchar **frame,
- gsize *len)
-{
- GdkPixbufLoader *loader;
- GdkPixbufAnimation *animation;
- GdkPixbuf *frame_buf;
-
- /* GIF89a (GIF image signature) */
- const gchar GIF_HEADER[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
- const gint GIF_HEADER_LEN = sizeof (GIF_HEADER);
-
- /* NETSCAPE2.0 (extension describing animated GIF, starts on 0x310) */
- const gchar GIF_APPEXT[] = { 0x4E, 0x45, 0x54, 0x53, 0x43, 0x41,
- 0x50, 0x45, 0x32, 0x2E, 0x30 };
- const gint GIF_APPEXT_LEN = sizeof (GIF_APPEXT);
-
- if ((anim == NULL) || (anim->data == NULL)) {
- *frame = NULL;
- *len = 0;
- return;
- }
-
- /* Check if the image is an animated GIF. We don't care about any
- * other animated formats (APNG or MNG) as WebKit does not support them
- * and displays only the first frame. */
- if ((anim->len < 0x331)
- || (memcmp (anim->data, GIF_HEADER, GIF_HEADER_LEN) != 0)
- || (memcmp (&anim->data[0x310], GIF_APPEXT, GIF_APPEXT_LEN) != 0)) {
-
- *frame = g_memdup (anim->data, anim->len);
- *len = anim->len;
- return;
- }
-
- loader = gdk_pixbuf_loader_new ();
- gdk_pixbuf_loader_write (loader, (guchar *) anim->data, anim->len, NULL);
- gdk_pixbuf_loader_close (loader, NULL);
- animation = gdk_pixbuf_loader_get_animation (loader);
- if (!animation) {
-
- *frame = g_memdup (anim->data, anim->len);
- *len = anim->len;
- g_object_unref (loader);
- return;
- }
-
- /* Extract first frame */
- frame_buf = gdk_pixbuf_animation_get_static_image (animation);
- if (!frame_buf) {
- *frame = g_memdup (anim->data, anim->len);
- *len = anim->len;
- g_object_unref (loader);
- g_object_unref (animation);
- return;
- }
-
- /* Unforunatelly, GdkPixbuf cannot save to GIF, but WebKit does not
- * have any trouble displaying PNG image despite the part having
- * image/gif mime-type */
- gdk_pixbuf_save_to_buffer (frame_buf, frame, len, "png", NULL, NULL);
-
- g_object_unref (loader);
-}
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
deleted file mode 100644
index 9749c37f31..0000000000
--- a/mail/em-format-html.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/*
- Abstract class for formatting mails to html
-*/
-
-#ifndef EM_FORMAT_HTML_H
-#define EM_FORMAT_HTML_H
-
-#include <em-format/em-format.h>
-#include <misc/e-web-view.h>
-#include <libemail-engine/e-mail-enums.h>
-
-/* Standard GObject macros */
-#define EM_TYPE_FORMAT_HTML \
- (em_format_html_get_type ())
-#define EM_FORMAT_HTML(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), EM_TYPE_FORMAT_HTML, EMFormatHTML))
-#define EM_FORMAT_HTML_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), EM_TYPE_FORMAT_HTML, EMFormatHTMLClass))
-#define EM_IS_FORMAT_HTML(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), EM_TYPE_FORMAT_HTML))
-#define EM_IS_FORMAT_HTML_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), EM_TYPE_FORMAT_HTML))
-#define EM_FORMAT_HTML_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), EM_TYPE_FORMAT_HTML, EMFormatHTMLClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EMFormatHTML EMFormatHTML;
-typedef struct _EMFormatHTMLClass EMFormatHTMLClass;
-typedef struct _EMFormatHTMLPrivate EMFormatHTMLPrivate;
-typedef struct _EMFormatWidgetPURI EMFormatWidgetPURI;
-
-enum _em_format_html_header_flags {
- EM_FORMAT_HTML_HEADER_TO = 1 << 0,
- EM_FORMAT_HTML_HEADER_CC = 1 << 1,
- EM_FORMAT_HTML_HEADER_BCC = 1 << 2
-};
-
-typedef enum {
- EM_FORMAT_HTML_COLOR_BODY, /* header area background */
- EM_FORMAT_HTML_COLOR_CITATION, /* citation font color */
- EM_FORMAT_HTML_COLOR_CONTENT, /* message area background */
- EM_FORMAT_HTML_COLOR_FRAME, /* frame around message area */
- EM_FORMAT_HTML_COLOR_HEADER, /* header font color */
- EM_FORMAT_HTML_COLOR_TEXT, /* message font color */
- EM_FORMAT_HTML_NUM_COLOR_TYPES
-} EMFormatHTMLColorType;
-
-#define EM_FORMAT_HTML_HEADER_NOCOLUMNS (EM_FORMAT_HEADER_LAST)
-
-/* header already in html format */
-#define EM_FORMAT_HTML_HEADER_HTML (EM_FORMAT_HEADER_LAST<<1)
-#define EM_FORMAT_HTML_HEADER_NODEC (EM_FORMAT_HEADER_LAST<<2)
-#define EM_FORMAT_HTML_HEADER_NOLINKS (EM_FORMAT_HEADER_LAST<<3)
-#define EM_FORMAT_HTML_HEADER_HIDDEN (EM_FORMAT_HEADER_LAST<<4)
-
-#define EM_FORMAT_HTML_HEADER_LAST (EM_FORMAT_HEADER_LAST<<8)
-
-#define EM_FORMAT_HTML_VPAD \
- "<table cellspacing=0 cellpadding=3><tr><td>" \
- "<a name=\"padding\"></a></td></tr></table>\n"
-
-/**
- * struct _EMFormatHTML - HTML formatter object.
- *
- * @format:
- * @priv:
- * @html:
- * @pending_object_list:
- * @headers:
- * @text_html_flags:
- * @body_colour:
- * @header_colour:
- * @text_colour:
- * @frame_colour:
- * @content_colour:
- * @citation_color:
- * @load_http:2:
- * @load_http_now:1:
- * @mark_citations:1:
- * @hide_headers:1:
- * @show_icon:1:
- *
- * Most of these fields are private or read-only.
- *
- * The base HTML formatter object. This object drives HTML generation
- * into a WebKit parser. It also handles text to HTML conversion,
- * multipart/related objects and inline images.
- **/
-struct _EMFormatHTML {
- EMFormat parent;
- EMFormatHTMLPrivate *priv;
-
- GQueue pending_object_list;
-
- GSList *headers;
-
- guint32 text_html_flags; /* default flags for text to html conversion */
- guint hide_headers:1; /* no headers at all */
- guint show_icon:1; /* show an icon when the sender used Evo */
- guint32 header_wrap_flags;
-};
-
-struct _EMFormatHTMLClass {
- EMFormatClass parent_class;
-
- GType html_widget_type;
-};
-
-GType em_format_html_get_type (void);
-void em_format_html_get_color (EMFormatHTML *efh,
- EMFormatHTMLColorType type,
- GdkColor *color);
-void em_format_html_set_color (EMFormatHTML *efh,
- EMFormatHTMLColorType type,
- const GdkColor *color);
-EMailImageLoadingPolicy
- em_format_html_get_image_loading_policy
- (EMFormatHTML *efh);
-void em_format_html_set_image_loading_policy
- (EMFormatHTML *efh,
- EMailImageLoadingPolicy policy);
-gboolean em_format_html_get_mark_citations
- (EMFormatHTML *efh);
-void em_format_html_set_mark_citations
- (EMFormatHTML *efh,
- gboolean mark_citations);
-gboolean em_format_html_get_only_local_photos
- (EMFormatHTML *efh);
-void em_format_html_set_only_local_photos
- (EMFormatHTML *efh,
- gboolean only_local_photos);
-gboolean em_format_html_get_show_sender_photo
- (EMFormatHTML *efh);
-void em_format_html_set_show_sender_photo
- (EMFormatHTML *efh,
- gboolean show_sender_photo);
-gboolean em_format_html_get_animate_images
- (EMFormatHTML *efh);
-void em_format_html_set_animate_images
- (EMFormatHTML *efh,
- gboolean animate_images);
-void em_format_html_clone_sync (CamelFolder *folder,
- const gchar *message_uid,
- CamelMimeMessage *message,
- EMFormatHTML *efh,
- EMFormat *source);
-gboolean em_format_html_get_show_real_date
- (EMFormatHTML *efh);
-void em_format_html_set_show_real_date
- (EMFormatHTML *efh,
- gboolean show_real_date);
-
-/* retrieves a pseudo-part icon wrapper for a file */
-CamelMimePart * em_format_html_file_part (EMFormatHTML *efh,
- const gchar *mime_type,
- const gchar *filename,
- GCancellable *cancellable);
-
-void em_format_html_format_cert_infos
- (GQueue *cert_infos,
- GString *output_buffer);
-
-void em_format_html_format_message (EMFormatHTML *efh,
- CamelStream *stream,
- GCancellable *cancellable);
-
-void em_format_html_format_message_part
- (EMFormatHTML *efh,
- const gchar *part_id,
- CamelStream *stream,
- GCancellable *cancellable);
-
-void em_format_html_format_headers (EMFormatHTML *efh,
- CamelStream *stream,
- CamelMedium *part,
- gboolean all_headers,
- GCancellable *cancellable);
-void em_format_html_format_header (EMFormat *emf,
- GString *buffer,
- CamelMedium *part,
- struct _camel_header_raw *header,
- guint32 flags,
- const gchar *charset);
-
-gboolean em_format_html_can_load_images (EMFormatHTML *efh);
-
-void em_format_html_animation_extract_frame
- (const GByteArray *anim,
- gchar **frame,
- gsize *len);
-
-G_END_DECLS
-
-#endif /* EM_FORMAT_HTML_H */
diff --git a/mail/em-utils.c b/mail/em-utils.c
index bf75253d34..9be80fbf79 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -56,6 +56,9 @@
#include <shell/e-shell.h>
#include <widgets/misc/e-attachment.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-formatter-quote.h>
+
#include <libemail-utils/mail-mt.h>
#include <libemail-engine/e-mail-folder-utils.h>
@@ -65,13 +68,11 @@
#include "e-mail-tag-editor.h"
#include "em-composer-utils.h"
-#include "em-format-html-display.h"
-#include "em-format-html-print.h"
#include "em-utils.h"
#include "e-mail-printer.h"
-#include "em-format/em-format-quote.h"
/* XXX This is a dirty hack on a dirty hack. We really need
+#include <em-format/e-mail-print-formatter.h>
* to rework or get rid of the functions that use this. */
extern const gchar *shell_builtin_backend;
@@ -616,20 +617,22 @@ do_print_msg_to_file (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
-
- EMFormatHTML *efh = EM_FORMAT_HTML (source);
+ EMailParser *parser;
+ EMailPartList *parts_list;
gchar *filename = user_data;
-
EMailPrinter *printer;
- printer = e_mail_printer_new (efh);
+ parser = E_MAIL_PARSER (source);
+ parts_list = e_mail_parser_parse_finish (parser, result, NULL);
+
+ printer = e_mail_printer_new (parts_list);
e_mail_printer_set_export_filename (printer, filename);
g_signal_connect_swapped (printer, "done",
G_CALLBACK (g_object_unref), printer);
e_mail_printer_print (printer, TRUE, NULL);
- g_object_unref (efh);
+ g_object_unref (parser);
}
static gboolean
@@ -637,7 +640,7 @@ em_utils_print_messages_to_file (CamelFolder *folder,
const gchar *uid,
const gchar *filename)
{
- EMFormatHTMLDisplay *efhd;
+ EMailParser *parser;
CamelMimeMessage *message;
CamelStore *parent_store;
CamelSession *session;
@@ -649,11 +652,10 @@ em_utils_print_messages_to_file (CamelFolder *folder,
parent_store = camel_folder_get_parent_store (folder);
session = camel_service_get_session (CAMEL_SERVICE (parent_store));
- efhd = em_format_html_display_new (session);
- ((EMFormat *) efhd)->message_uid = g_strdup (uid);
+ parser = e_mail_parser_new (session);
- em_format_parse_async ((EMFormat *) efhd, message, folder, NULL,
- (GAsyncReadyCallback) do_print_msg_to_file, g_strdup (filename));
+ e_mail_parser_parse (parser, folder, uid, message,
+ (GAsyncReadyCallback) do_print_msg_to_file, NULL, g_strdup (filename));
return TRUE;
}
@@ -1180,13 +1182,19 @@ em_utils_message_to_html (CamelSession *session,
CamelMimeMessage *message,
const gchar *credits,
guint32 flags,
- EMFormat *source,
+ EMailPartList *parts_list,
const gchar *append,
guint32 *validity_found)
{
- EMFormatQuote *emfq;
+ EMailFormatter *formatter;
+ EMailParser *parser;
CamelStream *mem;
GByteArray *buf;
+ EShell *shell;
+ GtkWindow *window;
+
+ shell = e_shell_get_default ();
+ window = e_shell_get_active_window (shell);
g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
@@ -1194,10 +1202,12 @@ em_utils_message_to_html (CamelSession *session,
mem = camel_stream_mem_new ();
camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), buf);
- emfq = em_format_quote_new (session, credits, mem, flags);
- em_format_set_composer ((EMFormat *) emfq, TRUE);
+ formatter = e_mail_formatter_quote_new (credits, flags);
+ e_mail_formatter_set_style (formatter,
+ gtk_widget_get_style (GTK_WIDGET (window)),
+ gtk_widget_get_state (GTK_WIDGET (window)));
- if (!source) {
+ if (!parts_list) {
GSettings *settings;
gchar *charset;
@@ -1205,37 +1215,38 @@ em_utils_message_to_html (CamelSession *session,
* current view, not the global setting. */
settings = g_settings_new ("org.gnome.evolution.mail");
charset = g_settings_get_string (settings, "charset");
- em_format_set_default_charset ((EMFormat *) emfq, charset);
+ if (charset && *charset)
+ e_mail_formatter_set_default_charset (formatter, charset);
g_object_unref (settings);
g_free (charset);
- }
- /* FIXME Not passing a GCancellable here. */
- em_format_parse (EM_FORMAT (emfq), message, NULL, NULL);
+ parser = e_mail_parser_new (session);
+ parts_list = e_mail_parser_parse_sync (parser, NULL, NULL, message, NULL);
+ }
if (validity_found) {
- GList *iter;
- EMFormat *emf = (EMFormat *) emfq;
+ GSList *iter;
if (validity_found)
*validity_found = 0;
/* Return all found validities */
- for (iter = emf->mail_part_list; iter; iter = iter->next) {
+ for (iter = parts_list->list; iter; iter = iter->next) {
- EMFormatPURI *puri = iter->data;
- if (!puri)
+ EMailPart *part = iter->data;
+ if (!part)
continue;
- if (*validity_found && puri->validity_type)
- *validity_found |= puri->validity_type;
+ if (*validity_found && part->validity_type)
+ *validity_found |= part->validity_type;
}
}
- em_format_quote_write (emfq, mem, NULL);
-
- g_object_unref (emfq);
+ e_mail_formatter_format_sync (
+ formatter, parts_list, mem, 0,
+ E_MAIL_FORMATTER_MODE_PRINTING, NULL);
+ g_object_unref (formatter);
if (append && *append)
camel_stream_write_string (mem, append, NULL, NULL);
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 092b75933c..db286eb55b 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -35,7 +35,7 @@
G_BEGIN_DECLS
-struct _EMFormat;
+struct _EMailPartList;
struct _EShell;
gboolean em_utils_ask_open_many (GtkWindow *parent, gint how_many);
@@ -66,7 +66,7 @@ void em_utils_selection_get_urilist (GtkSelectionData *data, CamelFolder *folder
EProxy * em_utils_get_proxy (void);
/* FIXME: should this have an override charset? */
-gchar *em_utils_message_to_html (CamelSession *session, CamelMimeMessage *msg, const gchar *credits, guint32 flags, struct _EMFormat *source, const gchar *append, guint32 *validity_found);
+gchar *em_utils_message_to_html (CamelSession *session, CamelMimeMessage *msg, const gchar *credits, guint32 flags, struct _EMailPartList *parts_list, const gchar *append, guint32 *validity_found);
void em_utils_empty_trash (GtkWidget *parent,
EMailSession *session);
diff --git a/modules/mail/e-mail-config-format-html.c b/modules/mail/e-mail-config-format-html.c
index 527f720159..cbedecf914 100644
--- a/modules/mail/e-mail-config-format-html.c
+++ b/modules/mail/e-mail-config-format-html.c
@@ -26,7 +26,7 @@
#include <shell/e-shell.h>
#include <e-util/e-util.h>
-#include <mail/em-format-html.h>
+#include <em-format/e-mail-formatter.h>
static gpointer parent_class;
@@ -95,7 +95,7 @@ mail_config_format_html_class_init (EExtensionClass *class)
object_class = G_OBJECT_CLASS (class);
object_class->constructed = mail_config_format_html_constructed;
- class->extensible_type = EM_TYPE_FORMAT_HTML;
+ class->extensible_type = E_TYPE_MAIL_FORMATTER;
}
void
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index f5bb100c39..3aecfd91d8 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -53,14 +53,16 @@
#include <mail/e-mail-reader.h>
#include <mail/em-composer-utils.h>
#include <mail/em-folder-utils.h>
-#include <mail/em-format-hook.h>
-#include <mail/em-format-html-display.h>
#include <mail/em-utils.h>
#include <mail/mail-send-recv.h>
#include <mail/mail-vfolder-ui.h>
#include <mail/importers/mail-importer.h>
#include <mail/e-mail-ui-session.h>
+#include <em-format/e-mail-parser.h>
+#include <em-format/e-mail-formatter.h>
+#include <em-format/e-mail-part-utils.h>
+
#include "e-mail-shell-settings.h"
#include "e-mail-shell-sidebar.h"
#include "e-mail-shell-view.h"
@@ -447,14 +449,6 @@ mail_shell_backend_constructed (GObject *object)
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_mail_shell_backend_parent_class)->constructed (object);
- /* Register format types for EMFormatHook. */
- em_format_hook_register_type (em_format_get_type ());
- em_format_hook_register_type (em_format_html_get_type ());
- em_format_hook_register_type (em_format_html_display_get_type ());
-
- /* Register plugin hook types. */
- em_format_hook_get_type ();
-
mail_shell_backend_init_importers ();
g_signal_connect (
@@ -851,13 +845,35 @@ message_parsed_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- EMFormatHTML *formatter = EM_FORMAT_HTML (source_object);
+ EMailParser *parser = E_MAIL_PARSER (source_object);
+ EMailPartList *parts_list;
GObject *preview = user_data;
EMailDisplay *display;
+ SoupSession *soup_session;
+ GHashTable *mails;
+ gchar *mail_uri;
display = g_object_get_data (preview, "mbox-imp-display");
- e_mail_display_set_formatter (display, formatter);
- e_mail_display_load (display, EM_FORMAT (formatter)->uri_base);
+
+ parts_list = e_mail_parser_parse_finish (parser, res, NULL);
+
+ soup_session = webkit_get_default_session ();
+ mails = g_object_get_data (G_OBJECT (soup_session), "mails");
+ if (!mails) {
+ mails = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
+ g_object_set_data (
+ G_OBJECT (soup_session), "mails", mails);
+ }
+ mail_uri = e_mail_part_build_uri (
+ parts_list->folder, parts_list->message_uid, NULL, NULL);
+
+ g_hash_table_insert (mails, mail_uri, parts_list);
+
+ e_mail_display_set_parts_list (display, parts_list);
+ e_mail_display_load (display, NULL);
+
+ g_object_unref (parts_list);
}
/* utility functions for mbox importer */
@@ -883,12 +899,9 @@ mbox_fill_preview_cb (GObject *preview,
{
EShell *shell;
EMailDisplay *display;
- EMFormat *formatter;
- GHashTable *formatters;
- SoupSession *soup_session;
+ EMailParser *parser;
EMailSession *mail_session;
ESourceRegistry *registry;
- gchar *mail_uri;
g_return_if_fail (preview != NULL);
g_return_if_fail (msg != NULL);
@@ -896,33 +909,13 @@ mbox_fill_preview_cb (GObject *preview,
display = g_object_get_data (preview, "mbox-imp-display");
g_return_if_fail (display != NULL);
- soup_session = webkit_get_default_session ();
- formatters = g_object_get_data (G_OBJECT (soup_session), "formatters");
- if (!formatters) {
- formatters = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free, NULL);
- g_object_set_data (
- G_OBJECT (soup_session), "formatters", formatters);
- }
-
- mail_uri = em_format_build_mail_uri (NULL, msg->message_id, NULL, NULL);
-
shell = e_shell_get_default ();
registry = e_shell_get_registry (shell);
mail_session = e_mail_session_new (registry);
- formatter = EM_FORMAT (
- em_format_html_display_new (
- CAMEL_SESSION (mail_session)));
- formatter->message_uid = g_strdup (msg->message_id);
- formatter->uri_base = g_strdup (mail_uri);
-
- /* Don't free the mail_uri!! */
- g_hash_table_insert (formatters, mail_uri, formatter);
-
- em_format_parse_async (
- formatter, msg, NULL, NULL,
- message_parsed_cb, preview);
+ parser = e_mail_parser_new (CAMEL_SESSION (mail_session));
+ e_mail_parser_parse (parser, NULL, msg->message_id, msg,
+ message_parsed_cb, NULL, preview);
g_object_unref (mail_session);
}
diff --git a/modules/mail/e-mail-shell-content.h b/modules/mail/e-mail-shell-content.h
index b3eecbef63..ff8fb94bf8 100644
--- a/modules/mail/e-mail-shell-content.h
+++ b/modules/mail/e-mail-shell-content.h
@@ -26,7 +26,6 @@
#include <shell/e-shell-searchbar.h>
#include <shell/e-shell-view.h>
#include <mail/e-mail-view.h>
-#include <mail/em-format-html-display.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_SHELL_CONTENT \
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index afe347cae6..3468339200 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -145,7 +145,7 @@ action_mail_account_properties_cb (GtkAction *action,
registry = e_shell_get_registry (shell);
source = e_source_registry_ref_source (registry, uid);
g_return_if_fail (source != NULL);
-
+
e_mail_shell_backend_edit_account (
E_MAIL_SHELL_BACKEND (shell_backend),
GTK_WINDOW (shell_window), source);
diff --git a/modules/mail/em-mailer-prefs.c b/modules/mail/em-mailer-prefs.c
index 00334d7559..9262ff8bb0 100644
--- a/modules/mail/em-mailer-prefs.c
+++ b/modules/mail/em-mailer-prefs.c
@@ -28,7 +28,6 @@
#include <glib/gi18n-lib.h>
#include "em-mailer-prefs.h"
-#include "em-format/em-format.h"
#include <gtkhtml/gtkhtml-properties.h>
#include <libxml/tree.h>
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 68b37b9693..6b81d16089 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -11,6 +11,7 @@ widgetsinclude_HEADERS = \
e-alarm-selector.h \
e-alert-bar.h \
e-attachment.h \
+ e-attachment-bar.h \
e-attachment-button.h \
e-attachment-dialog.h \
e-attachment-handler.h \
@@ -100,6 +101,7 @@ libemiscwidgets_la_SOURCES = \
e-alarm-selector.c \
e-alert-bar.c \
e-attachment.c \
+ e-attachment-bar.c \
e-attachment-button.c \
e-attachment-dialog.c \
e-attachment-handler.c \
diff --git a/mail/e-mail-attachment-bar.c b/widgets/misc/e-attachment-bar.c
index 495e327a3e..d7c90df330 100644
--- a/mail/e-mail-attachment-bar.c
+++ b/widgets/misc/e-attachment-bar.c
@@ -1,5 +1,5 @@
/*
- * e-mail-attachment-bar.c
+ * e-attachment-bar.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,7 @@
#include <config.h>
#endif
-#include "e-mail-attachment-bar.h"
+#include "e-attachment-bar.h"
#include <glib/gi18n.h>
@@ -31,13 +31,13 @@
#include "e-attachment-icon-view.h"
#include "e-attachment-tree-view.h"
-#define E_MAIL_ATTACHMENT_BAR_GET_PRIVATE(obj) \
+#define E_ATTACHMENT_BAR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_MAIL_ATTACHMENT_BAR, EMailAttachmentBarPrivate))
+ ((obj), E_TYPE_ATTACHMENT_BAR, EAttachmentBarPrivate))
#define NUM_VIEWS 2
-struct _EMailAttachmentBarPrivate {
+struct _EAttachmentBarPrivate {
GtkTreeModel *model;
GtkWidget *vbox;
GtkWidget *expander;
@@ -65,19 +65,19 @@ enum {
};
/* Forward Declarations */
-static void e_mail_attachment_bar_interface_init
+static void e_attachment_bar_interface_init
(EAttachmentViewInterface *interface);
G_DEFINE_TYPE_WITH_CODE (
- EMailAttachmentBar,
- e_mail_attachment_bar,
+ EAttachmentBar,
+ e_attachment_bar,
GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE (
E_TYPE_ATTACHMENT_VIEW,
- e_mail_attachment_bar_interface_init))
+ e_attachment_bar_interface_init))
static void
-mail_attachment_bar_update_status (EMailAttachmentBar *bar)
+attachment_bar_update_status (EAttachmentBar *bar)
{
EAttachmentStore *store;
GtkActivatable *activatable;
@@ -119,8 +119,8 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar)
}
static void
-mail_attachment_bar_set_store (EMailAttachmentBar *bar,
- EAttachmentStore *store)
+attachment_bar_set_store (EAttachmentBar *bar,
+ EAttachmentStore *store)
{
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
@@ -131,28 +131,30 @@ mail_attachment_bar_set_store (EMailAttachmentBar *bar,
gtk_tree_view_set_model (GTK_TREE_VIEW (bar->priv->tree_view),
bar->priv->model);
- g_signal_connect_swapped (
+ g_signal_connect_object (
bar->priv->model, "notify::num-attachments",
- G_CALLBACK (mail_attachment_bar_update_status), bar);
+ G_CALLBACK (attachment_bar_update_status), bar,
+ G_CONNECT_SWAPPED);
- g_signal_connect_swapped (
+ g_signal_connect_object (
bar->priv->model, "notify::total-size",
- G_CALLBACK (mail_attachment_bar_update_status), bar);
+ G_CALLBACK (attachment_bar_update_status), bar,
+ G_CONNECT_SWAPPED);
/* Initialize */
- mail_attachment_bar_update_status (bar);
+ attachment_bar_update_status (bar);
}
static void
-mail_attachment_bar_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+attachment_bar_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
switch (property_id) {
case PROP_ACTIVE_VIEW:
- e_mail_attachment_bar_set_active_view (
- E_MAIL_ATTACHMENT_BAR (object),
+ e_attachment_bar_set_active_view (
+ E_ATTACHMENT_BAR (object),
g_value_get_int (value));
return;
@@ -169,13 +171,13 @@ mail_attachment_bar_set_property (GObject *object,
return;
case PROP_EXPANDED:
- e_mail_attachment_bar_set_expanded (
- E_MAIL_ATTACHMENT_BAR (object),
+ e_attachment_bar_set_expanded (
+ E_ATTACHMENT_BAR (object),
g_value_get_boolean (value));
return;
case PROP_STORE:
- mail_attachment_bar_set_store (
- E_MAIL_ATTACHMENT_BAR (object),
+ attachment_bar_set_store (
+ E_ATTACHMENT_BAR (object),
g_value_get_object (value));
return;
}
@@ -184,17 +186,17 @@ mail_attachment_bar_set_property (GObject *object,
}
static void
-mail_attachment_bar_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+attachment_bar_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
switch (property_id) {
case PROP_ACTIVE_VIEW:
g_value_set_int (
value,
- e_mail_attachment_bar_get_active_view (
- E_MAIL_ATTACHMENT_BAR (object)));
+ e_attachment_bar_get_active_view (
+ E_ATTACHMENT_BAR (object)));
return;
case PROP_DRAGGING:
@@ -214,25 +216,25 @@ mail_attachment_bar_get_property (GObject *object,
case PROP_EXPANDED:
g_value_set_boolean (
value,
- e_mail_attachment_bar_get_expanded (
- E_MAIL_ATTACHMENT_BAR (object)));
+ e_attachment_bar_get_expanded (
+ E_ATTACHMENT_BAR (object)));
return;
case PROP_STORE:
g_value_set_object (
value,
- e_mail_attachment_bar_get_store (
- E_MAIL_ATTACHMENT_BAR (object)));
+ e_attachment_bar_get_store (
+ E_ATTACHMENT_BAR (object)));
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
-mail_attachment_bar_dispose (GObject *object)
+attachment_bar_dispose (GObject *object)
{
- EMailAttachmentBarPrivate *priv;
+ EAttachmentBarPrivate *priv;
- priv = E_MAIL_ATTACHMENT_BAR_GET_PRIVATE (object);
+ priv = E_ATTACHMENT_BAR_GET_PRIVATE (object);
if (priv->model != NULL) {
g_object_unref (priv->model);
@@ -295,16 +297,16 @@ mail_attachment_bar_dispose (GObject *object)
}
/* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_mail_attachment_bar_parent_class)->dispose (object);
+ G_OBJECT_CLASS (e_attachment_bar_parent_class)->dispose (object);
}
static void
-mail_attachment_bar_constructed (GObject *object)
+attachment_bar_constructed (GObject *object)
{
- EMailAttachmentBarPrivate *priv;
+ EAttachmentBarPrivate *priv;
GSettings *settings;
- priv = E_MAIL_ATTACHMENT_BAR_GET_PRIVATE (object);
+ priv = E_ATTACHMENT_BAR_GET_PRIVATE (object);
/* Set up property-to-property bindings. */
@@ -365,131 +367,131 @@ mail_attachment_bar_constructed (GObject *object)
g_object_unref (settings);
/* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_mail_attachment_bar_parent_class)->constructed (object);
+ G_OBJECT_CLASS (e_attachment_bar_parent_class)->constructed (object);
}
static EAttachmentViewPrivate *
-mail_attachment_bar_get_private (EAttachmentView *view)
+attachment_bar_get_private (EAttachmentView *view)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
return e_attachment_view_get_private (view);
}
static GtkTreePath *
-mail_attachment_bar_get_path_at_pos (EAttachmentView *view,
- gint x,
- gint y)
+attachment_bar_get_path_at_pos (EAttachmentView *view,
+ gint x,
+ gint y)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
return e_attachment_view_get_path_at_pos (view, x, y);
}
static EAttachmentStore *
-mail_attachment_bar_get_store (EAttachmentView *view)
+attachment_bar_get_store (EAttachmentView *view)
{
- return e_mail_attachment_bar_get_store (E_MAIL_ATTACHMENT_BAR (view));
+ return e_attachment_bar_get_store (E_ATTACHMENT_BAR (view));
}
static GList *
-mail_attachment_bar_get_selected_paths (EAttachmentView *view)
+attachment_bar_get_selected_paths (EAttachmentView *view)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
return e_attachment_view_get_selected_paths (view);
}
static gboolean
-mail_attachment_bar_path_is_selected (EAttachmentView *view,
- GtkTreePath *path)
+attachment_bar_path_is_selected (EAttachmentView *view,
+ GtkTreePath *path)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
return e_attachment_view_path_is_selected (view, path);
}
static void
-mail_attachment_bar_select_path (EAttachmentView *view,
- GtkTreePath *path)
+attachment_bar_select_path (EAttachmentView *view,
+ GtkTreePath *path)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
e_attachment_view_select_path (view, path);
}
static void
-mail_attachment_bar_unselect_path (EAttachmentView *view,
- GtkTreePath *path)
+attachment_bar_unselect_path (EAttachmentView *view,
+ GtkTreePath *path)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
e_attachment_view_unselect_path (view, path);
}
static void
-mail_attachment_bar_select_all (EAttachmentView *view)
+attachment_bar_select_all (EAttachmentView *view)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
e_attachment_view_select_all (view);
}
static void
-mail_attachment_bar_unselect_all (EAttachmentView *view)
+attachment_bar_unselect_all (EAttachmentView *view)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
e_attachment_view_unselect_all (view);
}
static void
-mail_attachment_bar_update_actions (EAttachmentView *view)
+attachment_bar_update_actions (EAttachmentView *view)
{
- EMailAttachmentBar *bar;
+ EAttachmentBar *bar;
- bar = E_MAIL_ATTACHMENT_BAR (view);
+ bar = E_ATTACHMENT_BAR (view);
view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
e_attachment_view_update_actions (view);
}
static void
-e_mail_attachment_bar_class_init (EMailAttachmentBarClass *class)
+e_attachment_bar_class_init (EAttachmentBarClass *class)
{
GObjectClass *object_class;
- g_type_class_add_private (class, sizeof (EMailAttachmentBarPrivate));
+ g_type_class_add_private (class, sizeof (EAttachmentBarPrivate));
object_class = G_OBJECT_CLASS (class);
- object_class->set_property = mail_attachment_bar_set_property;
- object_class->get_property = mail_attachment_bar_get_property;
- object_class->dispose = mail_attachment_bar_dispose;
- object_class->constructed = mail_attachment_bar_constructed;
+ object_class->set_property = attachment_bar_set_property;
+ object_class->get_property = attachment_bar_get_property;
+ object_class->dispose = attachment_bar_dispose;
+ object_class->constructed = attachment_bar_constructed;
g_object_class_install_property (
object_class,
@@ -534,22 +536,22 @@ e_mail_attachment_bar_class_init (EMailAttachmentBarClass *class)
}
static void
-e_mail_attachment_bar_interface_init (EAttachmentViewInterface *interface)
+e_attachment_bar_interface_init (EAttachmentViewInterface *interface)
{
- interface->get_private = mail_attachment_bar_get_private;
- interface->get_store = mail_attachment_bar_get_store;
- interface->get_path_at_pos = mail_attachment_bar_get_path_at_pos;
- interface->get_selected_paths = mail_attachment_bar_get_selected_paths;
- interface->path_is_selected = mail_attachment_bar_path_is_selected;
- interface->select_path = mail_attachment_bar_select_path;
- interface->unselect_path = mail_attachment_bar_unselect_path;
- interface->select_all = mail_attachment_bar_select_all;
- interface->unselect_all = mail_attachment_bar_unselect_all;
- interface->update_actions = mail_attachment_bar_update_actions;
+ interface->get_private = attachment_bar_get_private;
+ interface->get_store = attachment_bar_get_store;
+ interface->get_path_at_pos = attachment_bar_get_path_at_pos;
+ interface->get_selected_paths = attachment_bar_get_selected_paths;
+ interface->path_is_selected = attachment_bar_path_is_selected;
+ interface->select_path = attachment_bar_select_path;
+ interface->unselect_path = attachment_bar_unselect_path;
+ interface->select_all = attachment_bar_select_all;
+ interface->unselect_all = attachment_bar_unselect_all;
+ interface->update_actions = attachment_bar_update_actions;
}
static void
-e_mail_attachment_bar_init (EMailAttachmentBar *bar)
+e_attachment_bar_init (EAttachmentBar *bar)
{
EAttachmentView *view;
GtkSizeGroup *size_group;
@@ -557,7 +559,7 @@ e_mail_attachment_bar_init (EMailAttachmentBar *bar)
GtkWidget *widget;
GtkAction *action;
- bar->priv = E_MAIL_ATTACHMENT_BAR_GET_PRIVATE (bar);
+ bar->priv = E_ATTACHMENT_BAR_GET_PRIVATE (bar);
gtk_box_set_spacing (GTK_BOX (bar), 6);
@@ -685,32 +687,32 @@ e_mail_attachment_bar_init (EMailAttachmentBar *bar)
}
GtkWidget *
-e_mail_attachment_bar_new (EAttachmentStore *store)
+e_attachment_bar_new (EAttachmentStore *store)
{
g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), NULL);
return g_object_new (
- E_TYPE_MAIL_ATTACHMENT_BAR,
+ E_TYPE_ATTACHMENT_BAR,
"editable", FALSE,
"store", store, NULL);
}
gint
-e_mail_attachment_bar_get_active_view (EMailAttachmentBar *bar)
+e_attachment_bar_get_active_view (EAttachmentBar *bar)
{
- g_return_val_if_fail (E_IS_MAIL_ATTACHMENT_BAR (bar), 0);
+ g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
return bar->priv->active_view;
}
void
-e_mail_attachment_bar_set_active_view (EMailAttachmentBar *bar,
- gint active_view)
+e_attachment_bar_set_active_view (EAttachmentBar *bar,
+ gint active_view)
{
EAttachmentView *source;
EAttachmentView *target;
- g_return_if_fail (E_IS_MAIL_ATTACHMENT_BAR (bar));
+ g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
g_return_if_fail (active_view >= 0 && active_view < NUM_VIEWS);
if (active_view == bar->priv->active_view)
@@ -744,18 +746,18 @@ e_mail_attachment_bar_set_active_view (EMailAttachmentBar *bar,
}
gboolean
-e_mail_attachment_bar_get_expanded (EMailAttachmentBar *bar)
+e_attachment_bar_get_expanded (EAttachmentBar *bar)
{
- g_return_val_if_fail (E_IS_MAIL_ATTACHMENT_BAR (bar), FALSE);
+ g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), FALSE);
return bar->priv->expanded;
}
void
-e_mail_attachment_bar_set_expanded (EMailAttachmentBar *bar,
+e_attachment_bar_set_expanded (EAttachmentBar *bar,
gboolean expanded)
{
- g_return_if_fail (E_IS_MAIL_ATTACHMENT_BAR (bar));
+ g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
bar->priv->expanded = expanded;
@@ -763,9 +765,9 @@ e_mail_attachment_bar_set_expanded (EMailAttachmentBar *bar,
}
EAttachmentStore *
-e_mail_attachment_bar_get_store (EMailAttachmentBar *bar)
+e_attachment_bar_get_store (EAttachmentBar *bar)
{
- g_return_val_if_fail (E_IS_MAIL_ATTACHMENT_BAR (bar), NULL);
+ g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
return E_ATTACHMENT_STORE (bar->priv->model);
}
diff --git a/widgets/misc/e-attachment-bar.h b/widgets/misc/e-attachment-bar.h
new file mode 100644
index 0000000000..9f40973fe9
--- /dev/null
+++ b/widgets/misc/e-attachment-bar.h
@@ -0,0 +1,79 @@
+/*
+ * e-attachment-bar.h
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_ATTACHMENT_BAR_H
+#define E_ATTACHMENT_BAR_H
+
+#include <gtk/gtk.h>
+#include <misc/e-attachment-view.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ATTACHMENT_BAR \
+ (e_attachment_bar_get_type ())
+#define E_ATTACHMENT_BAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ATTACHMENT_BAR, EAttachmentBar))
+#define E_ATTACHMENT_BAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ATTACHMENT_BAR, EAttachmentBarClass))
+#define E_IS_ATTACHMENT_BAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ATTACHMENT_BAR))
+#define E_IS_ATTACHMENT_BAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ATTACHMENT_BAR))
+#define E_ATTACHMENT_BAR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ATTACHMENT_BAR, EAttachmentBarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAttachmentBar EAttachmentBar;
+typedef struct _EAttachmentBarClass EAttachmentBarClass;
+typedef struct _EAttachmentBarPrivate EAttachmentBarPrivate;
+
+struct _EAttachmentBar {
+ GtkVBox parent;
+ EAttachmentBarPrivate *priv;
+};
+
+struct _EAttachmentBarClass {
+ GtkVBoxClass parent_class;
+};
+
+GType e_attachment_bar_get_type (void);
+GtkWidget * e_attachment_bar_new (EAttachmentStore *store);
+gint e_attachment_bar_get_active_view
+ (EAttachmentBar *bar);
+void e_attachment_bar_set_active_view
+ (EAttachmentBar *bar,
+ gint active_view);
+gboolean e_attachment_bar_get_expanded
+ (EAttachmentBar *bar);
+void e_attachment_bar_set_expanded
+ (EAttachmentBar *bar,
+ gboolean expanded);
+EAttachmentStore *
+ e_attachment_bar_get_store (EAttachmentBar *bar);
+
+G_END_DECLS
+
+#endif /* E_ATTACHMENT_BAR_H */
diff --git a/widgets/misc/e-attachment-button.c b/widgets/misc/e-attachment-button.c
index 0d46807307..d3aa4a6350 100644
--- a/widgets/misc/e-attachment-button.c
+++ b/widgets/misc/e-attachment-button.c
@@ -701,9 +701,10 @@ e_attachment_button_set_view (EAttachmentButton *button,
g_return_if_fail (button->priv->view == NULL);
+ g_object_ref (view);
if (button->priv->view)
g_object_unref (button->priv->view);
- button->priv->view = g_object_ref (view);
+ button->priv->view = view;
popup_menu = e_attachment_view_get_popup_menu (view);