[evolution/webkit: 177/182] Fix printing of text/html emails (support external CSS, load images)
- From: Dan VrÃtil <dvratil src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit: 177/182] Fix printing of text/html emails (support external CSS, load images)
- Date: Tue, 6 Mar 2012 16:23:36 +0000 (UTC)
commit 23fc6e4fa2bddda0a410fde53b8cc3defd200557
Author: Dan VrÃtil <dvratil redhat com>
Date: Thu Mar 1 18:35:15 2012 +0100
Fix printing of text/html emails (support external CSS, load images)
mail/e-mail-display.c | 9 ++
mail/e-mail-display.h | 4 +
mail/e-mail-printer.c | 67 ++++++++++++----
mail/em-format-html.c | 204 ++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 248 insertions(+), 36 deletions(-)
---
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index cd1d02c..48bb2c4 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -1581,3 +1581,12 @@ e_mail_display_load_images (EMailDisplay * display)
display->priv->force_image_load = TRUE;
e_web_view_reload (E_WEB_VIEW (display));
}
+
+void
+e_mail_display_set_force_load_images (EMailDisplay *display,
+ gboolean force_load_images)
+{
+ g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+ display->priv->force_image_load = force_load_images;
+}
diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h
index 37a1c8c..0cf9645 100644
--- a/mail/e-mail-display.h
+++ b/mail/e-mail-display.h
@@ -96,6 +96,10 @@ gchar* e_mail_display_get_selection_plain_text
void e_mail_display_load_images (EMailDisplay *display);
+void e_mail_display_set_force_load_images
+ (EMailDisplay *display,
+ gboolean force_load_images);
+
G_END_DECLS
#endif /* E_MAIL_DISPLAY_H */
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 3396769..d5638ab 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -31,6 +31,7 @@
#include "e-mail-printer.h"
#include "em-format-html-print.h"
+#include "e-mail-display.h"
static gpointer parent_class = NULL;
@@ -49,6 +50,8 @@ enum {
struct _EMailPrinterPrivate {
EMFormatHTMLPrint *efhp;
+ gboolean export_mode;
+
GtkListStore *headers;
WebKitWebView *webview; /* WebView to print from */
@@ -147,13 +150,44 @@ emp_printing_done (GtkPrintOperation *operation,
}
static void
-emp_run_print_operation (EMailPrinter *emp,
- gboolean export)
+emp_start_printing (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ WebKitWebView *web_view;
+ WebKitWebFrame *frame;
+ WebKitLoadStatus load_status;
+ EMailPrinter *emp = user_data;
+
+ web_view = WEBKIT_WEB_VIEW (object);
+ load_status = webkit_web_view_get_load_status (web_view);
+
+ if (load_status != WEBKIT_LOAD_FINISHED)
+ return;
+
+ frame = webkit_web_view_get_main_frame (web_view);
+
+ if (emp->priv->export_mode) {
+ gtk_print_operation_set_export_filename (
+ emp->priv->operation,
+ emp->priv->efhp->export_filename);
+ webkit_web_frame_print_full (
+ frame, emp->priv->operation,
+ GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
+ } else {
+ webkit_web_frame_print_full
+ (frame, emp->priv->operation,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL);
+ }
+
+}
+
+static void
+emp_run_print_operation (EMailPrinter *emp)
{
EMFormat *emf;
SoupSession *session;
GHashTable *formatters;
- WebKitWebFrame *frame;
gchar *mail_uri;
emf = EM_FORMAT (emp->priv->efhp);
@@ -169,12 +203,17 @@ emp_run_print_operation (EMailPrinter *emp,
/* 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", NULL);
+
+ emp->priv->uri = g_strconcat (mail_uri, "?part_id=print_layout&__evo-load-images=1", NULL);
if (emp->priv->webview == NULL) {
- emp->priv->webview = WEBKIT_WEB_VIEW (e_web_view_new ());
+ emp->priv->webview = g_object_new (E_TYPE_MAIL_DISPLAY, 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);
g_object_ref_sink (emp->priv->webview);
+ g_signal_connect (emp->priv->webview, "notify::load-status",
+ G_CALLBACK (emp_start_printing), emp);
w({
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -186,16 +225,10 @@ emp_run_print_operation (EMailPrinter *emp,
});
}
- webkit_web_view_load_uri (emp->priv->webview, emp->priv->uri);
-
- frame = webkit_web_view_get_main_frame (emp->priv->webview);
+ e_mail_display_set_formatter (E_MAIL_DISPLAY (emp->priv->webview),
+ (EMFormatHTML *) emp->priv->efhp);
- if (export) {
- gtk_print_operation_set_export_filename (emp->priv->operation, emp->priv->efhp->export_filename);
- webkit_web_frame_print_full (frame, emp->priv->operation, GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
- } else {
- webkit_web_frame_print_full (frame, emp->priv->operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL);
- }
+ webkit_web_view_load_uri (emp->priv->webview, emp->priv->uri);
g_free (mail_uri);
}
@@ -764,7 +797,7 @@ e_mail_printer_new (EMFormatHTML* source)
void
e_mail_printer_print (EMailPrinter *emp,
- gboolean export,
+ gboolean export_mode,
GCancellable *cancellable)
{
g_return_if_fail (E_IS_MAIL_PRINTER (emp));
@@ -782,11 +815,13 @@ e_mail_printer_print (EMailPrinter *emp,
g_signal_connect (emp->priv->operation, "draw-page",
G_CALLBACK (emp_draw_footer), NULL);
+ emp->priv->export_mode = export_mode;
+
if (cancellable)
g_signal_connect_swapped (cancellable, "cancelled",
G_CALLBACK (gtk_print_operation_cancel), emp->priv->operation);
- emp_run_print_operation (emp, export);
+ emp_run_print_operation (emp);
}
const gchar*
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index e70e622..373aeda 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -730,6 +730,65 @@ efh_write_text_plain (EMFormat *emf,
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,
@@ -746,31 +805,136 @@ efh_write_text_html (EMFormat *emf,
em_format_format_text (emf, stream,
(CamelDataWrapper *) puri->part, cancellable);
- } else {
- gchar *str;
- gchar *uri;
+ } else if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
+ GString *string;
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ gchar *pos;
+ GList *tags, *iter;
+ gboolean valid;
+ gchar *tag;
+ const gchar *document_end;
+ gint length;
+ gint i;
+
+ dw = camel_medium_get_content ((CamelMedium *) puri->part);
+ ba = camel_data_wrapper_get_byte_array (dw);
+
+ string = g_string_new_len ((gchar *) ba->data, ba->len);
+
+ tags = NULL;
+ pos = string->str;
+ valid = FALSE;
+ do {
+ gchar *closing;
+ gchar *opening;
+
+ pos = strstr (pos + 1, "<");
+ if (!pos)
+ break;
- 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);
+ opening = pos;
+ closing = strstr (pos, ">");
- str = g_strdup_printf (
- "<div class=\"part-container\" style=\"border: solid #%06x 1px; "
- "background-color: #%06x;\">"
- "<div class=\"part-container-inner-margin\">\n"
- "<iframe width=\"100%%\" height=\"auto\""
- " frameborder=\"0\" src=\"%s\"></iframe>"
+ /* 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) {
+
+ if (g_ascii_isspace (*tag)) {
+ tag--;
+ continue;
+ }
+
+ if (*tag == 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\" style=\"border-color: #%06x; "
+ "background-color: #%06x;\">"
+ "<div class=\"part-container-inner-margin\">\n"
+ "<iframe width=\"100%%\" height=\"auto\""
+ " frameborder=\"0\" src=\"%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);
+ uri);
- camel_stream_write_string (stream, str, cancellable, NULL);
+ camel_stream_write_string (stream, str, cancellable, NULL);
- g_free (str);
- g_free (uri);
- }
+ g_free (str);
+ g_free (uri);
+ }
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]