diff --git a/src/mail/e-http-request.c b/src/mail/e-http-request.c index d8690b7545..bd5f8d44e4 100644 --- a/src/mail/e-http-request.c +++ b/src/mail/e-http-request.c @@ -188,6 +188,7 @@ e_http_request_process_sync (EContentRequest *request, gchar *mail_uri = NULL; GInputStream *stream; gboolean force_load_images = FALSE; + gboolean disable_remote_content = FALSE; EImageLoadingPolicy image_policy; gchar *uri_md5; EShell *shell; @@ -341,9 +342,17 @@ e_http_request_process_sync (EContentRequest *request, if (!e_shell_get_online (shell)) goto cleanup; - settings = e_util_ref_settings ("org.gnome.evolution.mail"); - image_policy = g_settings_get_enum (settings, "image-loading-policy"); - g_object_unref (settings); + if (WEBKIT_IS_WEB_VIEW (requester)) + disable_remote_content = g_strcmp0 (webkit_web_view_get_uri (WEBKIT_WEB_VIEW (requester)), "evo://disable-remote-content") == 0; + + if (disable_remote_content) { + force_load_images = FALSE; + image_policy = E_IMAGE_LOADING_POLICY_NEVER; + } else { + settings = e_util_ref_settings ("org.gnome.evolution.mail"); + image_policy = g_settings_get_enum (settings, "image-loading-policy"); + g_object_unref (settings); + } /* Item not found in cache, but image loading policy allows us to fetch * it from the interwebs */ diff --git a/src/modules/prefer-plain/e-mail-parser-prefer-plain.c b/src/modules/prefer-plain/e-mail-parser-prefer-plain.c index af84ef9af6..823b4240a1 100644 --- a/src/modules/prefer-plain/e-mail-parser-prefer-plain.c +++ b/src/modules/prefer-plain/e-mail-parser-prefer-plain.c @@ -18,8 +18,6 @@ #include #include -#include "e-mail-parser-prefer-plain.h" - #include #include #include @@ -28,14 +26,11 @@ #include #include -#define d(x) +#include "e-mail-parser-prefer-plain.h" typedef struct _EMailParserPreferPlain EMailParserPreferPlain; typedef struct _EMailParserPreferPlainClass EMailParserPreferPlainClass; -typedef EExtension EMailParserPreferPlainLoader; -typedef EExtensionClass EMailParserPreferPlainLoaderClass; - struct _EMailParserPreferPlain { EMailParserExtension parent; @@ -57,10 +52,7 @@ enum { ONLY_PLAIN }; -G_DEFINE_DYNAMIC_TYPE ( - EMailParserPreferPlain, - e_mail_parser_prefer_plain, - E_TYPE_MAIL_PARSER_EXTENSION) +G_DEFINE_DYNAMIC_TYPE (EMailParserPreferPlain, e_mail_parser_prefer_plain, E_TYPE_MAIL_PARSER_EXTENSION) static const gchar *parser_mime_types[] = { "multipart/alternative", @@ -196,6 +188,150 @@ hide_parts (GQueue *work_queue) } } +static gchar * +mail_parser_prefer_plain_dup_part_text (CamelMimePart *mime_part, + GCancellable *cancellable) +{ + CamelDataWrapper *data_wrapper; + CamelMedium *medium; + CamelStream *stream; + GByteArray *array; + gchar *content; + + if (!mime_part) + return NULL; + + array = g_byte_array_new (); + medium = CAMEL_MEDIUM (mime_part); + + /* Stream takes ownership of the byte array. */ + stream = camel_stream_mem_new_with_byte_array (array); + data_wrapper = camel_medium_get_content (medium); + camel_data_wrapper_decode_to_stream_sync ( + data_wrapper, stream, NULL, NULL); + + content = g_strndup ((gchar *) array->data, array->len); + + g_object_unref (stream); + + return content; +} + +typedef struct _AsyncContext { + gchar *text_input; + gchar *text_output; + GCancellable *cancellable; + EFlag *flag; + WebKitWebView *web_view; +} AsyncContext; + +static void +mail_parser_prefer_plain_convert_jsc_call_done_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + WebKitJavascriptResult *js_result; + AsyncContext *async_context = user_data; + GError *error = NULL; + + g_return_if_fail (async_context != NULL); + + js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (source), result, &error); + + if (error) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + (!g_error_matches (error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED) || + /* WebKit can return empty error message, thus ignore those. */ + (error->message && *(error->message)))) + g_warning ("%s: JSC call failed: %s:%d: %s", G_STRFUNC, g_quark_to_string (error->domain), error->code, error->message); + g_clear_error (&error); + } + + if (js_result) { + JSCException *exception; + JSCValue *value; + + value = webkit_javascript_result_get_js_value (js_result); + exception = jsc_context_get_exception (jsc_value_get_context (value)); + + if (exception) { + g_warning ("%s: JSC call failed: %s", G_STRFUNC, jsc_exception_get_message (exception)); + jsc_context_clear_exception (jsc_value_get_context (value)); + } else if (jsc_value_is_string (value)) { + async_context->text_output = jsc_value_to_string (value); + } + + webkit_javascript_result_unref (js_result); + } + + g_clear_object (&async_context->web_view); + + e_flag_set (async_context->flag); +} + +static gboolean +mail_parser_prefer_plain_convert_text (gpointer user_data) +{ + AsyncContext *async_context = user_data; + gchar *script; + + g_return_val_if_fail (async_context != NULL, FALSE); + + async_context->web_view = g_object_ref_sink (e_web_view_new ()); + + e_web_view_load_uri (E_WEB_VIEW (async_context->web_view), "evo://disable-remote-content"); + + script = e_web_view_jsc_printf_script ( + "var elem;\n" + "elem = document.createElement('X-EVO-CONVERT');\n" + "elem.innerHTML = %s;\n" + "EvoConvert.ToPlainText(elem, -1);", + async_context->text_input); + + webkit_web_view_run_javascript (async_context->web_view, script, async_context->cancellable, + mail_parser_prefer_plain_convert_jsc_call_done_cb, async_context); + + g_free (script); + + return FALSE; +} + +static gchar * +mail_parser_prefer_plain_convert_content_sync (CamelMimePart *mime_part, + GCancellable *cancellable) +{ + AsyncContext async_context; + gchar *res = NULL; + + memset (&async_context, 0, sizeof (AsyncContext)); + + async_context.text_input = mail_parser_prefer_plain_dup_part_text (mime_part, cancellable); + + if (!async_context.text_input || g_cancellable_is_cancelled (cancellable)) { + g_free (async_context.text_input); + return NULL; + } + + async_context.flag = e_flag_new (); + async_context.cancellable = cancellable; + + /* Run it in the main/GUI thread */ + g_timeout_add (1, mail_parser_prefer_plain_convert_text, &async_context); + + e_flag_wait (async_context.flag); + e_flag_free (async_context.flag); + + if (async_context.text_output) { + res = async_context.text_output; + async_context.text_output = NULL; + } + + g_free (async_context.text_input); + g_free (async_context.text_output); + + return res; +} + static gboolean empe_prefer_plain_parse (EMailParserExtension *extension, EMailParser *parser, @@ -250,12 +386,40 @@ empe_prefer_plain_parse (EMailParserExtension *extension, if (emp_pp->mode != ONLY_PLAIN) return FALSE; - /* Enforcing text/plain but got only HTML part, so add it - * as attachment to not show empty message preview, which - * is confusing. */ - make_part_attachment ( - parser, part, part_id, TRUE, - cancellable, out_mail_parts); + if (!e_mail_part_is_attachment (part)) { + gchar *content; + + partidlen = part_id->len; + + g_string_truncate (part_id, partidlen); + g_string_append_printf (part_id, ".alternative-prefer-plain.%d.converted", -1); + + content = mail_parser_prefer_plain_convert_content_sync (part, cancellable); + + if (content) { + EMailPart *mail_part; + CamelMimePart *text_part; + + text_part = camel_mime_part_new (); + camel_mime_part_set_content (text_part, content, strlen (content), "application/vnd.evolution.plaintext"); + mail_part = e_mail_part_new (text_part, part_id->str); + e_mail_part_set_mime_type (mail_part, "application/vnd.evolution.plaintext"); + g_free (content); + + g_queue_push_tail (out_mail_parts, mail_part); + } + + g_string_truncate (part_id, partidlen); + } + + if (emp_pp->show_suppressed || e_mail_part_is_attachment (part)) { + /* Enforcing text/plain but got only HTML part, so add it + * as attachment to not show empty message preview, which + * is confusing. */ + make_part_attachment ( + parser, part, part_id, TRUE, + cancellable, out_mail_parts); + } return TRUE; } @@ -565,4 +729,3 @@ e_mail_parser_prefer_plain_type_register (GTypeModule *type_module) { e_mail_parser_prefer_plain_register_type (type_module); } - diff --git a/src/web-extensions/e-web-extension.c b/src/web-extensions/e-web-extension.c index 979818a67c..deea1bdaa7 100644 --- a/src/web-extensions/e-web-extension.c +++ b/src/web-extensions/e-web-extension.c @@ -104,11 +104,14 @@ web_page_send_request_cb (WebKitWebPage *web_page, request_uri = webkit_uri_request_get_uri (request); page_uri = webkit_web_page_get_uri (web_page); + if (!request_uri) + return FALSE; + /* Always load the main resource. */ if (g_strcmp0 (request_uri, page_uri) == 0 || /* Do not influence real pages, like those with eds OAuth sign-in */ - g_str_has_prefix (page_uri, "http:") || - g_str_has_prefix (page_uri, "https:")) + (page_uri && (g_str_has_prefix (page_uri, "http:") || + g_str_has_prefix (page_uri, "https:")))) return FALSE; if (g_str_has_prefix (request_uri, "http:") ||