aboutsummaryrefslogtreecommitdiffstats
path: root/mail/em-format-html-display.c
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2012-03-29 00:38:11 +0800
committerDan Vrátil <dvratil@redhat.com>2012-03-29 00:38:25 +0800
commit6d2c382788a4042d53f49a080acd11b499aa52f6 (patch)
tree3834f0836340918ba17594a603ba61c13b9929a0 /mail/em-format-html-display.c
parent6bd1c6833a2c51898ac45865767dd01ba66a95c5 (diff)
downloadgsoc2013-evolution-6d2c382788a4042d53f49a080acd11b499aa52f6.tar.gz
gsoc2013-evolution-6d2c382788a4042d53f49a080acd11b499aa52f6.tar.zst
gsoc2013-evolution-6d2c382788a4042d53f49a080acd11b499aa52f6.zip
WebKit port - port formatter and mail module
Diffstat (limited to 'mail/em-format-html-display.c')
-rw-r--r--mail/em-format-html-display.c1350
1 files changed, 552 insertions, 798 deletions
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 013e1ac731..8f20169636 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -38,9 +38,6 @@
#undef interface
#endif
-#include <gtkhtml/gtkhtml.h>
-#include <gtkhtml/gtkhtml-embedded.h>
-
#include <glib/gi18n.h>
#include <e-util/e-util.h>
@@ -53,6 +50,8 @@
#include <shell/e-shell.h>
#include <shell/e-shell-utils.h>
+#include <libedataserver/e-flag.h>
+
#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
#include "certificate-viewer.h"
#include "e-cert-db.h"
@@ -65,6 +64,8 @@
#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 \
@@ -77,16 +78,9 @@
((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayPrivate))
struct _EMFormatHTMLDisplayPrivate {
- GHashTable *attachment_views; /* weak reference; message_part_id->EAttachmentView */
- gboolean attachment_expanded;
-};
-struct _smime_pobject {
- EMFormatHTMLPObject object;
+ EAttachmentView *last_view;
- gint signature;
- CamelCipherValidity *valid;
- GtkWidget *widget;
};
/* TODO: move the dialogue elsehwere */
@@ -111,78 +105,100 @@ static const struct {
{ "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 gchar *smime_sign_colour[5] = {
- "", " bgcolor=\"#88bb88\"", " bgcolor=\"#bb8888\"", " bgcolor=\"#e8d122\"",""
+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_attachment_frame (EMFormat *emf, CamelStream *stream, EMFormatPURI *puri, GCancellable *cancellable);
-static void efhd_message_add_bar (EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
-static gboolean efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
-static gboolean efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *object);
+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 void efhd_parse_optional (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 GtkWidget * efhd_attachment_optional (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);
-struct _attach_puri {
- EMFormatPURI puri;
+static void efhd_builtin_init (EMFormatHTMLDisplayClass *efhc);
+
+static gpointer parent_class;
- const EMFormatHandler *handle;
+static EAttachmentStore *
+find_parent_attachment_store (EMFormatHTMLDisplay *efhd,
+ const gchar *part_id)
+{
+ EMFormat *emf = (EMFormat *) efhd;
+ EMFormatAttachmentBarPURI *abp;
+ gchar *tmp, *pos;
+ GList *item;
- const gchar *snoop_mime_type;
+ tmp = g_strdup (part_id);
- /* for the > and V buttons */
- GtkWidget *forward, *down;
- /* currently no way to correlate this data to the frame :( */
- GtkHTML *frame;
- guint shown : 1;
+ do {
+ gchar *id;
- /* Embedded Frame */
- GtkHTMLEmbedded *html;
+ pos = g_strrstr (tmp, ".");
+ if (!pos)
+ break;
- /* Attachment */
- EAttachment *attachment;
- gchar *attachment_view_part_id;
+ g_free (tmp);
+ tmp = g_strndup (part_id, pos - tmp);
+ id = g_strdup_printf ("%s.attachment-bar", tmp);
- /* image stuff */
- gint fit_width;
- gint fit_height;
- GtkImage *image;
- GtkWidget *event_box;
+ item = g_hash_table_lookup (emf->mail_part_table, id);
- /* Optional Text Mem Stream */
- CamelStreamMem *mstream;
+ g_free (id);
- /* Signed / Encrypted */
- camel_cipher_validity_sign_t sign;
- camel_cipher_validity_encrypt_t encrypt;
-};
+ } while (pos && !item);
-static void efhd_message_prefix (EMFormat *emf,
- CamelStream *stream,
- CamelMimePart *part,
- const EMFormatHandler *info,
- GCancellable *cancellable,
- gboolean is_fallback);
+ g_free (tmp);
-static void efhd_builtin_init (EMFormatHTMLDisplayClass *efhc);
+ abp = (EMFormatAttachmentBarPURI *) item->data;
-G_DEFINE_TYPE (
- EMFormatHTMLDisplay,
- em_format_html_display,
- EM_TYPE_FORMAT_HTML)
+ if (abp)
+ return abp->store;
+ else
+ return NULL;
+}
static void
-efhd_xpkcs7mime_free (EMFormatHTMLPObject *o)
+efhd_attachment_bar_puri_free (EMFormatPURI *puri)
{
- struct _smime_pobject *po = (struct _smime_pobject *) o;
+ EMFormatAttachmentBarPURI *abp;
- if (po->widget)
- gtk_widget_destroy (po->widget);
- camel_cipher_validity_free (po->valid);
+ 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,
- struct _smime_pobject *po)
+ EMFormatSMIMEPURI *po)
{
gtk_widget_destroy (widget);
po->widget = NULL;
@@ -191,7 +207,7 @@ efhd_xpkcs7mime_info_response (GtkWidget *widget,
#if defined (HAVE_NSS) && defined (ENABLE_SMIME)
static void
efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
- struct _smime_pobject *po)
+ EMFormatSMIMEPURI *po)
{
CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info");
ECert *ec = NULL;
@@ -221,7 +237,7 @@ efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
static void
efhd_xpkcs7mime_add_cert_table (GtkWidget *grid,
GQueue *certlist,
- struct _smime_pobject *po)
+ EMFormatSMIMEPURI *po)
{
GList *head, *link;
GtkTable *table;
@@ -283,9 +299,9 @@ efhd_xpkcs7mime_add_cert_table (GtkWidget *grid,
static void
efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
- EMFormatHTMLPObject *pobject)
+ EMFormatPURI *puri)
{
- struct _smime_pobject *po = (struct _smime_pobject *) pobject;
+ EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
GtkBuilder *builder;
GtkWidget *grid, *w;
@@ -367,20 +383,19 @@ efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
g_object_unref (builder);
g_signal_connect (
- po->widget, "response",
+ po->widget, "response",
G_CALLBACK (efhd_xpkcs7mime_info_response), po);
gtk_widget_show (po->widget);
}
-static gboolean
-efhd_xpkcs7mime_button (EMFormatHTML *efh,
- GtkHTMLEmbedded *eb,
- EMFormatHTMLPObject *pobject)
+static GtkWidget *
+efhd_xpkcs7mime_button (EMFormat *emf,
+ EMFormatPURI *puri,
+ GCancellable *cancellable)
{
- GtkWidget *container;
- GtkWidget *widget;
- struct _smime_pobject *po = (struct _smime_pobject *) pobject;
+ GtkWidget *box, *button, *layout, *widget;
+ EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
const gchar *icon_name;
/* FIXME: need to have it based on encryption and signing too */
@@ -389,450 +404,436 @@ efhd_xpkcs7mime_button (EMFormatHTML *efh,
else
icon_name = smime_encrypt_table[po->valid->encrypt.status].icon;
- container = GTK_WIDGET (eb);
+ 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]);
- widget = gtk_button_new ();
- g_signal_connect (
- widget, "clicked",
- G_CALLBACK (efhd_xpkcs7mime_validity_clicked), pobject);
- gtk_container_add (GTK_CONTAINER (container), widget);
- gtk_widget_show (widget);
+ layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+ gtk_container_add (GTK_CONTAINER (box), layout);
- container = widget;
+ 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_container_add (GTK_CONTAINER (container), widget);
- gtk_widget_show (widget);
+ icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_button_set_image (GTK_BUTTON (button), widget);
- return TRUE;
-}
+ widget = gtk_label_new (po->description);
+ gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0);
-static gboolean
-remove_attachment_view_cb (gpointer message_part_id,
- gpointer attachment_view,
- gpointer gone_attachment_view)
-{
- return attachment_view == gone_attachment_view;
+ gtk_widget_show_all (box);
+
+ return box;
}
+struct attachment_load_data {
+ EAttachment *attachment;
+ EFlag *flag;
+};
+
static void
-efhd_attachment_view_gone_cb (gpointer efh,
- GObject *gone_attachment_view)
+attachment_loaded (EAttachment *attachment,
+ GAsyncResult *res,
+ gpointer user_data)
{
- EMFormatHTMLDisplay *efhd = EM_FORMAT_HTML_DISPLAY (efh);
+ struct attachment_load_data *data = user_data;
+ EShell *shell;
+ GtkWindow *window;
- g_return_if_fail (efhd != NULL);
+ shell = e_shell_get_default ();
+ window = e_shell_get_active_window (shell);
+ if (!E_IS_SHELL_WINDOW (window))
+ window = NULL;
- g_hash_table_foreach_remove (
- efhd->priv->attachment_views,
- remove_attachment_view_cb,
- gone_attachment_view);
-}
+ e_attachment_load_handle_error (data->attachment, res, window);
-static void
-weak_unref_attachment_view_cb (gpointer message_part_id,
- gpointer attachment_view,
- gpointer efh)
-{
- g_object_weak_unref (
- G_OBJECT (attachment_view),
- efhd_attachment_view_gone_cb, efh);
+ e_flag_set (data->flag);
}
-static void
-efhd_format_clone (EMFormat *emf,
- CamelFolder *folder,
- const gchar *uid,
- CamelMimeMessage *msg,
- EMFormat *src,
- GCancellable *cancellable)
+/* Idle callback */
+static gboolean
+load_attachment_idle (struct attachment_load_data *data)
{
- EMFormatHTMLDisplay *efhd;
-
- efhd = EM_FORMAT_HTML_DISPLAY (emf);
- g_return_if_fail (efhd != NULL);
+ e_attachment_load_async (data->attachment,
+ (GAsyncReadyCallback) attachment_loaded, data);
- g_hash_table_foreach (efhd->priv->attachment_views, weak_unref_attachment_view_cb, efhd);
- g_hash_table_remove_all (efhd->priv->attachment_views);
-
- if (emf != src)
- EM_FORMAT_HTML (emf)->header_wrap_flags = 0;
-
- /* Chain up to parent's format_clone() method. */
- EM_FORMAT_CLASS (em_format_html_display_parent_class)->
- format_clone (emf, folder, uid, msg, src, cancellable);
+ return FALSE;
}
static void
-efhd_format_attachment (EMFormat *emf,
- CamelStream *stream,
- CamelMimePart *part,
- const gchar *mime_type,
- const EMFormatHandler *handle,
- GCancellable *cancellable)
+efhd_parse_attachment (EMFormat *emf,
+ CamelMimePart *part,
+ GString *part_id,
+ EMFormatParserInfo *info,
+ GCancellable *cancellable)
{
- GString *buffer;
- gchar *classid, *text, *html;
- struct _attach_puri *info;
-
- classid = g_strdup_printf ("attachment%s", emf->part_id->str);
- info = (struct _attach_puri *) em_format_add_puri (
- emf, sizeof (*info), classid, part, efhd_attachment_frame);
- info->puri.free = efhd_free_attach_puri_data;
- info->attachment_view_part_id = g_strdup (emf->current_message_part_id);
- em_format_html_add_pobject (
- EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject),
- classid, part, efhd_attachment_button);
- info->handle = handle;
- info->shown = em_format_is_inline (
- emf, info->puri.part_id, info->puri.part, handle);
- info->snoop_mime_type = emf->snoop_mime_type;
- info->attachment = e_attachment_new ();
- e_attachment_set_mime_part (info->attachment, info->puri.part);
-
- if (emf->valid) {
- info->sign = emf->valid->sign.status;
- info->encrypt = emf->valid->encrypt.status;
+ 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);
}
- buffer = g_string_sized_new (1024);
-
- g_string_append_printf (
- buffer, EM_FORMAT_HTML_VPAD
- "<table cellspacing=0 cellpadding=0>"
- "<tr><td>"
- "<table width=10 cellspacing=0 cellpadding=0>"
- "<tr><td></td><tr>"
- "</table>"
- "</td>"
- "<td><object classid=\"%s\"></object></td>"
- "<td><table width=3 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr>"
- "</table></td>"
- "<td><font size=-1>",
- classid);
-
- /* output some info about it */
/* 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_string_append (buffer, html);
- g_free (html);
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);
+ }
- g_string_append (
- buffer,
- "</font></td>"
- "</tr><tr></table>\n"
- EM_FORMAT_HTML_VPAD);
-
- camel_stream_write (
- stream, buffer->str, buffer->len, cancellable, NULL);
-
- g_string_free (buffer, TRUE);
+ 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;
+ }
+ }
- if (handle && info->shown)
- handle->handler (
- emf, stream, part, handle, cancellable, FALSE);
+ 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));
- g_free (classid);
-}
+ store = find_parent_attachment_store (efhd, part_id->str);
+ e_attachment_store_add_attachment (store, puri->attachment);
-static void
-efhd_format_optional (EMFormat *emf,
- CamelStream *fstream,
- CamelMimePart *part,
- CamelStream *mstream,
- GCancellable *cancellable)
-{
- gchar *classid, *html;
- struct _attach_puri *info;
- CamelStream *stream = NULL;
- GString *buffer;
+ 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_IS_STREAM_FILTER (fstream))
- stream = camel_stream_filter_get_source (
- CAMEL_STREAM_FILTER (fstream));
- if (stream == NULL)
- stream = fstream;
-
- classid = g_strdup_printf ("optional%s", emf->part_id->str);
- info = (struct _attach_puri *) em_format_add_puri (
- emf, sizeof (*info), classid, part, efhd_attachment_frame);
- info->puri.free = efhd_free_attach_puri_data;
- info->attachment_view_part_id = g_strdup (emf->current_message_part_id);
- em_format_html_add_pobject (
- EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject),
- classid, part, efhd_attachment_optional);
- info->handle = em_format_find_handler (emf, "text/plain");
- info->shown = FALSE;
- info->snoop_mime_type = "text/plain";
- info->attachment = e_attachment_new ();
- e_attachment_set_mime_part (info->attachment, info->puri.part);
- info->mstream = (CamelStreamMem *) g_object_ref (mstream);
- if (emf->valid) {
- info->sign = emf->valid->sign.status;
- info->encrypt = emf->valid->encrypt.status;
+ if (camel_mime_part_get_encoding (puri->puri.part) == CAMEL_TRANSFER_ENCODING_BASE64)
+ size = size / 1.37;
+ }
}
- buffer = g_string_sized_new (1024);
+ load_data = g_new0 (struct attachment_load_data, 1);
+ load_data->attachment = g_object_ref (puri->attachment);
+ load_data->flag = e_flag_new ();
- g_string_append (
- buffer, EM_FORMAT_HTML_VPAD
- "<table cellspacing=0 cellpadding=0><tr><td>"
- "<h3><font size=-1 color=red>");
+ e_flag_clear (load_data->flag);
- html = camel_text_to_html (
- _("Evolution cannot render this email as it is too "
- "large to process. You can view it unformatted or "
- "with an external text editor."),
- EM_FORMAT_HTML (emf)->text_html_flags &
- CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- g_string_append (buffer, html);
- g_free (html);
+ /* e_attachment_load_async must be called from main thread */
+ g_idle_add ((GSourceFunc) load_attachment_idle, load_data);
- g_string_append_printf (
- buffer,
- "</font></h3></td></tr></table>\n"
- "<table cellspacing=0 cellpadding=0><tr>"
- "<td><object classid=\"%s\"></object>"
- "</td></tr></table>" EM_FORMAT_HTML_VPAD,
- classid);
+ e_flag_wait (load_data->flag);
- camel_stream_write (
- stream, buffer->str, buffer->len, cancellable, NULL);
+ e_flag_free (load_data->flag);
+ g_object_unref (load_data->attachment);
+ g_free (load_data);
- g_string_free (buffer, TRUE);
+ 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_free (classid);
+ g_string_truncate (part_id, len);
}
static void
-efhd_format_secure (EMFormat *emf,
- CamelStream *stream,
- CamelMimePart *part,
- CamelCipherValidity *valid,
- GCancellable *cancellable)
+efhd_parse_optional (EMFormat *emf,
+ CamelMimePart *part,
+ GString *part_id,
+ EMFormatParserInfo *info,
+ GCancellable *cancellable)
{
- EMFormatClass *format_class;
+ EMFormatAttachmentPURI *puri;
+ gint len;
+
+ len = part_id->len;
+ g_string_append (part_id, ".optional");
+
+ 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_optional;
+ puri->attachment_view_part_id = g_strdup (part_id->str);
+ puri->handle = em_format_find_handler (emf, "text/plain");
+ puri->shown = FALSE;
+ puri->snoop_mime_type = "text/plain";
+ puri->attachment = e_attachment_new ();
+ e_attachment_set_mime_part (puri->attachment, puri->puri.part);
+ puri->description = g_strdup(_("Evolution cannot render this email as it is too "
+ "large to process. You can view it unformatted or "
+ "with an external text editor."));
+
+ puri->mstream = CAMEL_STREAM_MEM (camel_stream_mem_new ());
+ camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) part,
+ (CamelStream *) puri->mstream, cancellable, NULL);
+
+ if (info->validity) {
+ puri->puri.validity = camel_cipher_validity_clone (info->validity);
+ }
- format_class = g_type_class_peek (EM_TYPE_FORMAT);
- format_class->format_secure (emf, stream, part, valid, cancellable);
+ em_format_add_puri (emf, (EMFormatPURI *) puri);
- if (emf->valid == valid
- && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
- || valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) {
+ 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;
- gchar *classid;
- struct _smime_pobject *pobj;
+ EMFormatSMIMEPURI *pobj;
- buffer = g_string_sized_new (1024);
+ 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;
- g_string_append_printf (
- buffer,
- "<table border=0 width=\"100%%\" "
- "cellpadding=3 cellspacing=0%s><tr>",
- smime_sign_colour[valid->sign.status]);
+ em_format_add_puri (emf, (EMFormatPURI *) pobj);
- classid = g_strdup_printf (
- "smime:///em-format-html/%s/icon/signed",
- emf->part_id->str);
- pobj = (struct _smime_pobject *) em_format_html_add_pobject (
- EM_FORMAT_HTML (emf), sizeof (*pobj),
- classid, part, efhd_xpkcs7mime_button);
- pobj->valid = camel_cipher_validity_clone (valid);
- pobj->object.free = efhd_xpkcs7mime_free;
- g_string_append_printf (
- buffer,
- "<td valign=center><object classid=\"%s\">"
- "</object></td><td width=100%% valign=center>",
- classid);
- g_free (classid);
+ buffer = g_string_new ("");
- if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
+ if (info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
const gchar *desc;
gint status;
- status = valid->sign.status;
+ status = info->validity->sign.status;
desc = smime_sign_table[status].shortdesc;
g_string_append (buffer, gettext (desc));
em_format_html_format_cert_infos (
- &valid->sign.signers, buffer);
+ &info->validity->sign.signers, buffer);
}
- if (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
+ if (info->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
const gchar *desc;
gint status;
- if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)
- g_string_append (buffer, "<br>");
+ if (info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)
+ g_string_append (buffer, "\n");
- status = valid->encrypt.status;
+ status = info->validity->encrypt.status;
desc = smime_encrypt_table[status].shortdesc;
g_string_append (buffer, gettext (desc));
}
- g_string_append (buffer, "</td></tr></table>");
-
- camel_stream_write (
- stream, buffer->str, buffer->len, cancellable, NULL);
-
- g_string_free (buffer, TRUE);
+ pobj->description = g_string_free (buffer, FALSE);
}
}
+/******************************************************************************/
static void
-attachment_load_finish (EAttachment *attachment,
- GAsyncResult *result,
- GFile *file)
+efhd_write_attachment_bar (EMFormat *emf,
+ EMFormatPURI *puri,
+ CamelStream *stream,
+ EMFormatWriterInfo *info,
+ GCancellable *cancellable)
{
- EShell *shell;
- GtkWindow *parent;
+ EMFormatAttachmentBarPURI *efab = (EMFormatAttachmentBarPURI *) puri;
+ gchar *str;
- e_attachment_load_finish (attachment, result, NULL);
+ if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING)
+ return;
- shell = e_shell_get_default ();
- parent = e_shell_get_active_window (shell);
+ if (e_attachment_store_get_num_attachments (efab->store) == 0)
+ return;
- e_attachment_save_async (
- attachment, file, (GAsyncReadyCallback)
- e_attachment_save_handle_error, parent);
+ str = g_strdup_printf (
+ "<object type=\"application/x-attachment-bar\" "
+ "height=\"20\" width=\"100%%\" "
+ "id=\"%s\"data=\"%s\"></object>", puri->uri, puri->uri);
- g_object_unref (file);
+ camel_stream_write_string (stream, str, cancellable, NULL);
+
+ g_free (str);
}
static void
-action_image_save_cb (GtkAction *action,
- EMFormatHTMLDisplay *efhd)
+efhd_write_attachment (EMFormat *emf,
+ EMFormatPURI *puri,
+ CamelStream *stream,
+ EMFormatWriterInfo *info,
+ GCancellable *cancellable)
{
- EWebView *web_view;
- EMFormat *emf;
- const gchar *image_src;
- CamelMimePart *part;
- EAttachment *attachment;
- GFile *file;
+ gchar *str, *desc;
+ const gchar *mime_type;
+ gchar *button_id;
- web_view = em_format_html_get_web_view (EM_FORMAT_HTML (efhd));
- g_return_if_fail (web_view != NULL);
+ EMFormatAttachmentPURI *efa = (EMFormatAttachmentPURI *) puri;
- image_src = e_web_view_get_cursor_image_src (web_view);
- if (!image_src)
- return;
+ /* 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) {
- emf = EM_FORMAT (efhd);
- g_return_if_fail (emf != NULL);
- g_return_if_fail (emf->message != NULL);
+ efa->handle->write_func (emf, puri, stream, info, cancellable);
+ return;
+ }
- if (g_str_has_prefix (image_src, "cid:")) {
- part = camel_mime_message_get_part_by_content_id (
- emf->message, image_src + 4);
- g_return_if_fail (part != NULL);
+ if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
- g_object_ref (part);
- } else {
- CamelStream *image_stream;
- CamelDataWrapper *dw;
- const gchar *filename;
-
- image_stream = em_format_html_get_cached_image (
- EM_FORMAT_HTML (efhd), image_src);
- if (!image_stream)
- return;
-
- filename = strrchr (image_src, '/');
- if (filename && strchr (filename, '?'))
- filename = NULL;
- else if (filename)
- filename = filename + 1;
-
- part = camel_mime_part_new ();
- if (filename)
- camel_mime_part_set_filename (part, filename);
-
- dw = camel_data_wrapper_new ();
- camel_data_wrapper_set_mime_type (
- dw, "application/octet-stream");
- camel_data_wrapper_construct_from_stream_sync (
- dw, image_stream, NULL, NULL);
- camel_medium_set_content (CAMEL_MEDIUM (part), dw);
- g_object_unref (dw);
-
- camel_mime_part_set_encoding (
- part, CAMEL_TRANSFER_ENCODING_BASE64);
-
- g_object_unref (image_stream);
- }
+ if (efa->handle && efa->handle->write_func)
+ efa->handle->write_func (emf, puri, stream, info, cancellable);
- file = e_shell_run_save_dialog (
- e_shell_get_default (),
- _("Save Image"), camel_mime_part_get_filename (part),
- NULL, NULL, NULL);
- if (file == NULL) {
- g_object_unref (part);
return;
}
- attachment = e_attachment_new ();
- e_attachment_set_mime_part (attachment, part);
+ 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);
+ }
- e_attachment_load_async (
- attachment, (GAsyncReadyCallback)
- attachment_load_finish, file);
+ camel_stream_write_string (stream, "</div></td></tr>", cancellable, NULL);
+ }
- g_object_unref (part);
+ camel_stream_write_string (stream, "</table></div>", cancellable, NULL);
}
static void
-efhd_web_view_update_actions_cb (EWebView *web_view,
- EMFormatHTMLDisplay *efhd)
+efhd_write_secure_button (EMFormat *emf,
+ EMFormatPURI *puri,
+ CamelStream *stream,
+ EMFormatWriterInfo *info,
+ GCancellable *cancellable)
{
- const gchar *image_src;
- gboolean visible;
- GtkAction *action;
-
- g_return_if_fail (web_view != NULL);
+ gchar *str;
- image_src = e_web_view_get_cursor_image_src (web_view);
- visible = image_src && g_str_has_prefix (image_src, "cid:");
- if (!visible && image_src) {
- CamelStream *image_stream;
+ if ((info->mode != EM_FORMAT_WRITE_MODE_NORMAL) &&
+ (info->mode != EM_FORMAT_WRITE_MODE_RAW))
+ return;
- image_stream = em_format_html_get_cached_image (
- EM_FORMAT_HTML (efhd), image_src);
- visible = image_stream != NULL;
+ str = g_strdup_printf (
+ "<object type=\"application/x-secure-button\" "
+ "height=\"20\" width=\"100%%\" "
+ "data=\"%s\" id=\"%s\"></object>", puri->uri, puri->uri);
- if (image_stream)
- g_object_unref (image_stream);
- }
+ camel_stream_write_string (stream, str, cancellable, NULL);
- action = e_web_view_get_action (web_view, "efhd-image-save");
- if (action)
- gtk_action_set_visible (action, visible);
+ g_free (str);
}
-static GtkActionEntry image_entries[] = {
- { "efhd-image-save",
- GTK_STOCK_SAVE,
- N_("Save _Image..."),
- NULL,
- N_("Save the image to a file"),
- G_CALLBACK (action_image_save_cb) }
-};
-
-static const gchar *image_ui =
- "<ui>"
- " <popup name='context'>"
- " <placeholder name='custom-actions-2'>"
- " <menuitem action='efhd-image-save'/>"
- " </placeholder>"
- " </popup>"
- "</ui>";
-
static void
efhd_finalize (GObject *object)
{
@@ -841,84 +842,77 @@ efhd_finalize (GObject *object)
efhd = EM_FORMAT_HTML_DISPLAY (object);
g_return_if_fail (efhd != NULL);
- if (efhd->priv->attachment_views) {
- g_hash_table_foreach (
- efhd->priv->attachment_views,
- weak_unref_attachment_view_cb, efhd);
- g_hash_table_destroy (efhd->priv->attachment_views);
- efhd->priv->attachment_views = NULL;
- }
-
/* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (em_format_html_display_parent_class)->
- finalize (object);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
-em_format_html_display_class_init (EMFormatHTMLDisplayClass *class)
+efhd_preparse (EMFormat *emf)
+{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
+
+ efhd->priv->last_view = NULL;
+}
+
+static void
+efhd_class_init (EMFormatHTMLDisplayClass *class)
{
GObjectClass *object_class;
- EMFormatClass *format_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_class = EM_FORMAT_CLASS (class);
- format_class->format_clone = efhd_format_clone;
- format_class->format_attachment = efhd_format_attachment;
- format_class->format_optional = efhd_format_optional;
- format_class->format_secure = efhd_format_secure;
-
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
-em_format_html_display_init (EMFormatHTMLDisplay *efhd)
+efhd_init (EMFormatHTMLDisplay *efhd)
{
- EWebView *web_view;
- GtkActionGroup *image_actions;
- GtkUIManager *ui_manager;
- GError *error = NULL;
-
- web_view = em_format_html_get_web_view (EM_FORMAT_HTML (efhd));
-
efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efhd);
- efhd->priv->attachment_views = g_hash_table_new_full (
- g_str_hash, g_str_equal, g_free, NULL);
- efhd->priv->attachment_expanded = FALSE;
-
- e_mail_display_set_formatter (
- E_MAIL_DISPLAY (web_view), EM_FORMAT_HTML (efhd));
- /* we want to convert url's etc */
+ /* 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;
- image_actions = e_web_view_get_action_group (web_view, "image");
- g_return_if_fail (image_actions != NULL);
-
- gtk_action_group_add_actions (
- image_actions, image_entries,
- G_N_ELEMENTS (image_entries), efhd);
+}
- /* Because we are loading from a hard-coded string, there is
- * no chance of I/O errors. Failure here implies a malformed
- * UI definition. Full stop. */
- ui_manager = e_web_view_get_ui_manager (web_view);
- gtk_ui_manager_add_ui_from_string (ui_manager, image_ui, -1, &error);
- if (error != NULL)
- g_error ("%s", error->message);
+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);
+ }
- g_signal_connect (
- web_view, "update-actions",
- G_CALLBACK (efhd_web_view_update_actions_cb), efhd);
+ return type;
}
EMFormatHTMLDisplay *
@@ -930,8 +924,11 @@ em_format_html_display_new (void)
/* ********************************************************************** */
static EMFormatHandler type_builtin_table[] = {
- { (gchar *) "x-evolution/message/prefix", efhd_message_prefix },
- { (gchar *) "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar }
+ { (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, },
+ { (gchar *) "x-evolution/message/optional", efhd_parse_optional, },
};
static void
@@ -939,81 +936,51 @@ efhd_builtin_init (EMFormatHTMLDisplayClass *efhc)
{
gint i;
- for (i = 0; i < G_N_ELEMENTS (type_builtin_table); i++)
- em_format_class_add_handler ((EMFormatClass *) efhc, &type_builtin_table[i]);
-}
-
-static void
-efhd_write_image (EMFormat *emf,
- CamelStream *stream,
- EMFormatPURI *puri,
- GCancellable *cancellable)
-{
- CamelDataWrapper *dw = camel_medium_get_content ((CamelMedium *) puri->part);
+ EMFormatClass *emfc = (EMFormatClass *) efhc;
- /* TODO: identical to efh_write_image */
- d(printf("writing image '%s'\n", puri->cid));
- camel_data_wrapper_decode_to_stream_sync (
- dw, stream, cancellable, NULL);
- camel_stream_close (stream, cancellable, NULL);
+ 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,
- CamelStream *stream,
CamelMimePart *part,
- const EMFormatHandler *info,
- GCancellable *cancellable,
- gboolean is_fallback)
+ 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->uid == NULL
- || (flag = camel_folder_get_message_user_tag(emf->folder, emf->uid, "follow-up")) == NULL
+ 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;
- buffer = g_string_sized_new (1024);
+ puri = (EMFormatAttachmentPURI *) em_format_puri_new (
+ emf, sizeof (EMFormatAttachmentPURI), part, ".message_prefix");
- /* header displayed for message-flags in mail display */
- g_string_append (
- buffer,
- "<table border=1 width=\"100%%\" "
- "cellspacing=2 cellpadding=2><tr>");
+ puri->attachment_view_part_id = g_strdup (part_id->str);
- comp = camel_folder_get_message_user_tag(emf->folder, emf->uid, "completed-on");
+ 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) {
- CamelMimePart *iconpart;
-
- iconpart = em_format_html_file_part (
- (EMFormatHTML *)emf, "image/png",
- iconpath, cancellable);
- g_free (iconpath);
- if (iconpart) {
- gchar *classid;
-
- classid = g_strdup_printf (
- "icon:///em-format-html-display/%s/%s",
- emf->part_id->str,
- comp && comp[0] ? "comp" : "uncomp");
- g_string_append_printf (
- buffer,
- "<td align=\"left\">"
- "<img src=\"%s\"></td>",
- classid);
- (void) em_format_add_puri (
- emf, sizeof (EMFormatPURI),
- classid, iconpart, efhd_write_image);
- g_free (classid);
- g_object_unref (iconpart);
- }
+ 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);
}
- g_string_append (buffer, "<td align=\"left\" width=\"100%%\">");
+ buffer = g_string_new ("");
if (comp && comp[0]) {
date = camel_header_decode_date (comp, NULL);
@@ -1024,7 +991,7 @@ efhd_message_prefix (EMFormat *emf,
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->uid, "due-by")) != NULL && due[0]) {
+ } 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);
@@ -1032,7 +999,7 @@ efhd_message_prefix (EMFormat *emf,
if (now > date)
g_string_append_printf (
buffer,
- "<b>%s</b>&nbsp;",
+ "<b>%s</b> ",
_("Overdue:"));
due_date_str = e_datetime_format_format (
@@ -1048,270 +1015,84 @@ efhd_message_prefix (EMFormat *emf,
g_string_append (buffer, flag);
}
- g_string_append (buffer, "</td></tr></table>");
-
- camel_stream_write (
- stream, buffer->str, buffer->len, cancellable, NULL);
-
- g_string_free (buffer, TRUE);
-}
-
-/* ********************************************************************** */
-
-static void
-efhd_attachment_button_expanded (EAttachmentButton *button,
- GParamSpec *pspec,
- struct _attach_puri *info)
-{
- EMFormatHTML *efh;
- EMFormatHTMLDisplay *efhd;
-
- /* FIXME The PURI struct seems to have some lifecycle issues,
- * because casting info->puri.format to an EMFormatHTML
- * can lead to crashes. So we hack around it. */
- efh = g_object_get_data (G_OBJECT (button), "efh");
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- if (efh->state == EM_FORMAT_HTML_STATE_RENDERING)
- return;
-
- info->shown = e_attachment_button_get_expanded (button);
-
- em_format_set_inline (
- info->puri.format, info->puri.part_id, info->shown);
-
- efhd = (EMFormatHTMLDisplay *) efh;
- g_return_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd));
-
- efhd->priv->attachment_expanded = TRUE;
-}
-
-/* ********************************************************************** */
-
-static void
-attachment_button_realized (GtkWidget *widget)
-{
- EMFormatHTML *efh = g_object_get_data (G_OBJECT (widget), "efh");
- EMFormatHTMLDisplay *efhd;
- g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
- efhd = (EMFormatHTMLDisplay *) efh;
- g_return_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd));
-
- gtk_widget_grab_focus (widget);
- efhd->priv->attachment_expanded = FALSE;
+ puri->description = g_string_free (buffer, FALSE);
}
/* ********************************************************************** */
/* attachment button callback */
-static gboolean
-efhd_attachment_button (EMFormatHTML *efh,
- GtkHTMLEmbedded *eb,
- EMFormatHTMLPObject *pobject)
+static GtkWidget *
+efhd_attachment_button (EMFormat *emf,
+ EMFormatPURI *puri,
+ GCancellable *cancellable)
{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh;
- struct _attach_puri *info;
- EAttachmentView *view;
- EAttachmentStore *store;
- EAttachment *attachment;
- EWebView *web_view;
+ EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
GtkWidget *widget;
- gpointer parent;
- EMFormat *emf = (EMFormat *) efh;
- guint32 size = 0;
/* FIXME: handle default shown case */
d(printf("adding attachment button/content\n"));
- if (emf->folder && emf->folder->summary && emf->uid) {
- CamelMessageInfo *mi;
-
- mi = camel_folder_summary_get (emf->folder->summary, emf->uid);
- if (mi) {
- const CamelMessageContentInfo *ci;
-
- ci = camel_folder_summary_guess_content_info (mi, camel_mime_part_get_content_type (pobject->part));
- if (ci) {
- size = ci->size;
- /* what if its not encoded in base64 ? is it a case to consider? */
- if (ci->encoding && !g_ascii_strcasecmp (ci->encoding, "base64"))
- size = size / 1.37;
- }
- camel_message_info_free (mi);
- }
- }
-
- info = (struct _attach_puri *) em_format_find_puri ((EMFormat *) efh, pobject->classid);
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
if (!info || info->forward) {
g_warning ("unable to expand the attachment\n");
- return TRUE;
+ return NULL;
}
- attachment = info->attachment;
- e_attachment_set_shown (attachment, info->shown);
- e_attachment_set_signed (attachment, info->sign);
- e_attachment_set_encrypted (attachment, info->encrypt);
- e_attachment_set_can_show (attachment, info->handle != NULL);
-
- web_view = em_format_html_get_web_view (efh);
- g_return_val_if_fail (web_view != NULL, TRUE);
- parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
- parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
-
- view = em_format_html_display_get_attachment_view (efhd, info->attachment_view_part_id);
- g_return_val_if_fail (view != NULL, TRUE);
- gtk_widget_show (GTK_WIDGET (view));
-
- store = e_attachment_view_get_store (view);
- e_attachment_store_add_attachment (store, info->attachment);
-
- e_attachment_load_async (
- info->attachment, (GAsyncReadyCallback)
- e_attachment_load_handle_error, parent);
- if (size != 0) {
- GFileInfo *fileinfo;
-
- fileinfo = e_attachment_get_file_info (info->attachment);
- g_file_info_set_size (fileinfo, size);
- e_attachment_set_file_info (info->attachment, fileinfo);
- }
-
- widget = e_attachment_button_new (view);
+ widget = e_attachment_button_new ();
+ g_object_set_data (G_OBJECT (widget), "uri", puri->uri);
e_attachment_button_set_attachment (
- E_ATTACHMENT_BUTTON (widget), 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_container_add (GTK_CONTAINER (eb), widget);
gtk_widget_show (widget);
- /* FIXME Not sure why the expanded callback can't just use
- * info->puri.format, but there seems to be lifecycle
- * issues with the PURI struct. Maybe it should have
- * a reference count? */
- g_object_set_data (G_OBJECT (widget), "efh", efh);
-
- g_signal_connect (
- widget, "notify::expanded",
- G_CALLBACK (efhd_attachment_button_expanded), info);
-
- /* If the button is created, then give it focus after
- * it is realized, so that user can use arrow keys to scroll
- * message */
- if (efhd->priv->attachment_expanded) {
- g_signal_connect (
- widget, "realize",
- G_CALLBACK (attachment_button_realized), NULL);
- }
-
- return TRUE;
-}
-
-static void
-efhd_attachment_frame (EMFormat *emf,
- CamelStream *stream,
- EMFormatPURI *puri,
- GCancellable *cancellable)
-{
- struct _attach_puri *info = (struct _attach_puri *) puri;
-
- if (info->shown)
- info->handle->handler (
- emf, stream, info->puri.part,
- info->handle, cancellable, FALSE);
-
- camel_stream_close (stream, cancellable, NULL);
-}
-
-static void
-set_size_request_cb (gpointer message_part_id,
- gpointer widget,
- gpointer width)
-{
- gtk_widget_set_size_request (widget, GPOINTER_TO_INT (width), -1);
+ return widget;
}
-static void
-efhd_bar_resize (EMFormatHTML *efh,
- GtkAllocation *event)
+static GtkWidget *
+efhd_attachment_bar (EMFormat *emf,
+ EMFormatPURI *puri,
+ GCancellable *cancellable)
{
- EMFormatHTMLDisplayPrivate *priv;
- GtkAllocation allocation;
- EWebView *web_view;
+ EMFormatAttachmentBarPURI *abp = (EMFormatAttachmentBarPURI *) puri;
GtkWidget *widget;
- gint width;
- priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efh);
+ widget = e_mail_attachment_bar_new (abp->store);
+ EM_FORMAT_HTML_DISPLAY (emf)->priv->last_view = (EAttachmentView *) widget;
- web_view = em_format_html_get_web_view (efh);
-
- widget = GTK_WIDGET (web_view);
- gtk_widget_get_allocation (widget, &allocation);
- width = allocation.width - 12;
-
- if (width > 0) {
- g_hash_table_foreach (priv->attachment_views, set_size_request_cb, GINT_TO_POINTER (width));
- }
+ return widget;
}
-static gboolean
-efhd_add_bar (EMFormatHTML *efh,
- GtkHTMLEmbedded *eb,
- EMFormatHTMLPObject *pobject)
+static void
+efhd_message_add_bar (EMFormat *emf,
+ CamelMimePart *part,
+ GString *part_id,
+ EMFormatParserInfo *info,
+ GCancellable *cancellable)
{
- EMFormatHTMLDisplayPrivate *priv;
- GtkWidget *widget;
-
- /* XXX See note in efhd_message_add_bar(). */
- if (!EM_IS_FORMAT_HTML_DISPLAY (efh))
- return FALSE;
-
- g_return_val_if_fail (pobject != NULL && pobject->classid != NULL, FALSE);
- g_return_val_if_fail (g_str_has_prefix (pobject->classid, "attachment-bar:"), FALSE);
-
- priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efh);
+ EMFormatAttachmentBarPURI *puri;
+ gint len;
- widget = e_mail_attachment_bar_new ();
- gtk_container_add (GTK_CONTAINER (eb), widget);
-
- g_hash_table_insert (priv->attachment_views, g_strdup (strchr (pobject->classid, ':') + 1), widget);
- g_object_weak_ref (G_OBJECT (widget), efhd_attachment_view_gone_cb, efh);
- gtk_widget_hide (widget);
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
- g_signal_connect_swapped (
- eb, "size-allocate",
- G_CALLBACK (efhd_bar_resize), efh);
+ 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 ());
- return TRUE;
-}
+ em_format_add_puri (emf, (EMFormatPURI *) puri);
-static void
-efhd_message_add_bar (EMFormat *emf,
- CamelStream *stream,
- CamelMimePart *part,
- const EMFormatHandler *info)
-{
- gchar *classid;
- gchar *content;
-
- classid = g_strdup_printf (
- "attachment-bar:%s", emf->current_message_part_id);
-
- /* XXX Apparently this installs the callback for -all-
- * EMFormatHTML subclasses, not just this subclass.
- * Bad idea. So we have to filter out other types
- * in the callback. */
- em_format_html_add_pobject (
- EM_FORMAT_HTML (emf),
- sizeof (EMFormatHTMLPObject),
- classid, part, efhd_add_bar);
-
- content = g_strdup_printf (
- "<td><object classid=\"%s\"></object></td>", classid);
- camel_stream_write_string (stream, content, NULL, NULL);
- g_free (content);
-
- g_free (classid);
+ g_string_truncate (part_id, len);
}
static void
@@ -1329,41 +1110,28 @@ efhd_optional_button_show (GtkWidget *widget,
}
}
-static void
-efhd_resize (GtkWidget *w,
- GtkAllocation *event,
- EMFormatHTML *efh)
-{
- EWebView *web_view;
- GtkAllocation allocation;
-
- web_view = em_format_html_get_web_view (efh);
- gtk_widget_get_allocation (GTK_WIDGET (web_view), &allocation);
- gtk_widget_set_size_request (w, allocation.width - 48, 250);
-}
-
/* optional render attachment button callback */
-static gboolean
-efhd_attachment_optional (EMFormatHTML *efh,
- GtkHTMLEmbedded *eb,
- EMFormatHTMLPObject *pobject)
+static GtkWidget *
+efhd_attachment_optional (EMFormat *efh,
+ EMFormatPURI *puri,
+ GCancellable *cancellable)
{
- struct _attach_puri *info;
GtkWidget *hbox, *vbox, *button, *mainbox, *scroll, *label, *img;
AtkObject *a11y;
GtkWidget *view;
- GtkAllocation allocation;
GtkTextBuffer *buffer;
GByteArray *byte_array;
- EWebView *web_view;
+ EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return NULL;
/* FIXME: handle default shown case */
d(printf("adding attachment button/content for optional rendering\n"));
- info = (struct _attach_puri *) em_format_find_puri ((EMFormat *) efh, pobject->classid);
if (!info || info->forward) {
g_warning ("unable to expand the attachment\n");
- return TRUE;
+ return NULL;
}
scroll = gtk_scrolled_window_new (NULL, NULL);
@@ -1428,28 +1196,19 @@ efhd_attachment_optional (EMFormatHTML *efh,
gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 6);
gtk_widget_show (GTK_WIDGET (view));
- web_view = em_format_html_get_web_view (efh);
- gtk_widget_get_allocation (GTK_WIDGET (web_view), &allocation);
- gtk_widget_set_size_request (scroll, allocation.width - 48, 250);
- g_signal_connect (
- scroll, "size_allocate",
- G_CALLBACK (efhd_resize), efh);
- gtk_widget_show (scroll);
-
if (!info->shown)
gtk_widget_hide (scroll);
gtk_widget_show (vbox);
- gtk_container_add (GTK_CONTAINER (eb), vbox);
info->handle = NULL;
- return TRUE;
+ return view;
}
static void
efhd_free_attach_puri_data (EMFormatPURI *puri)
{
- struct _attach_puri *info = (struct _attach_puri *) puri;
+ EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
g_return_if_fail (puri != NULL);
@@ -1458,23 +1217,18 @@ efhd_free_attach_puri_data (EMFormatPURI *puri)
info->attachment = NULL;
}
- g_free (info->attachment_view_part_id);
- info->attachment_view_part_id = NULL;
-}
-
-/* returned object owned by html_display, thus do not unref it */
-EAttachmentView *
-em_format_html_display_get_attachment_view (EMFormatHTMLDisplay *html_display,
- const gchar *message_part_id)
-{
- gpointer aview;
-
- g_return_val_if_fail (EM_IS_FORMAT_HTML_DISPLAY (html_display), NULL);
- g_return_val_if_fail (message_part_id != NULL, NULL);
+ if (info->description) {
+ g_free (info->description);
+ info->description = NULL;
+ }
- /* it should be added in efhd_add_bar() with this message_part_id */
- aview = g_hash_table_lookup (html_display->priv->attachment_views, message_part_id);
- g_return_val_if_fail (aview != NULL, NULL);
+ if (info->attachment_view_part_id) {
+ g_free (info->attachment_view_part_id);
+ info->attachment_view_part_id = NULL;
+ }
- return E_ATTACHMENT_VIEW (aview);
+ if (info->mstream) {
+ g_object_unref (info->mstream);
+ info->mstream = NULL;
+ }
}