Commit 1b6cad11 authored by Andrea Corbellini's avatar Andrea Corbellini Committed by Jim Nelson

Load external images based on scheme, not extension: Closes #6099

Squashed commit of the following:

commit 2e7b026f5865d84f369288a70d86c44e07e8c3b1
Merge: 08c6691 c476669f
Author: Jim Nelson <jim@yorba.org>
Date:   Wed Jan 16 15:24:35 2013 -0800

    Merge branch 'master' into bug/6099-view-images

commit 08c6691c5c466448710a5b055676778348650b86
Author: Jim Nelson <jim@yorba.org>
Date:   Wed Jan 16 15:06:00 2013 -0800

    Updates in response to Eric's code review

commit 9694e0a4d678b3b0674e9970b8f3b840937955f3
Author: Jim Nelson <jim@yorba.org>
Date:   Wed Jan 16 14:17:12 2013 -0800

    Merge of Andrea Corbellini's patch for #6099

    The merge had to be done by hand because of a recent refactoring of
    the ConversationViewer and ConversationWebView.
parent c476669f
......@@ -2,6 +2,7 @@ The Geary team would like to thank the following contributors:
Robert Ancell <robert.ancell@canonical.com>
Jürg Billeter <j@bitron.ch>
Andrea Corbellini <corbellini.andrea@gmail.com>
Sergey Shnatsel Davidoff <sergey@elementaryos.org>
Joanmarie Diggs <jdiggs@igalia.com>
Christian Dywan <christian@twotoasts.de>
......
......@@ -192,19 +192,6 @@ public WebKit.DOM.HTMLElement? closest_ancestor(WebKit.DOM.Element element, stri
}
}
public bool is_image(string? uri) {
if (uri == null)
return false;
try {
Regex regex = new Regex("(?:jpe?g|gif|png)$", RegexCompileFlags.CASELESS);
return regex.match(uri);
} catch (RegexError err) {
debug("Error creating image-matching regex: %s", err.message);
return false;
}
}
public string decorate_quotes(string text) throws Error {
int level = 0;
string outtext = "";
......
......@@ -110,7 +110,7 @@ public class ConversationViewer : Gtk.Box {
}
private void on_external_images_info_bar_response(Gtk.InfoBar sender, int response_id) {
web_view.set_load_external_images(response_id == Gtk.ResponseType.OK);
web_view.apply_load_external_images(response_id == Gtk.ResponseType.OK);
sender.hide();
}
......@@ -162,7 +162,7 @@ public class ConversationViewer : Gtk.Box {
}
public void add_message(Geary.Email email) {
web_view.set_load_external_images(false);
web_view.apply_load_external_images(false);
// Make sure the message container is showing and the multi-message counter hidden.
try {
......@@ -871,25 +871,39 @@ public class ConversationViewer : Gtk.Box {
// Now look for the signature.
wrap_html_signature(ref container);
// Then get all inline images and replace them with data URLs.
WebKit.DOM.NodeList inline_list = container.query_selector_all("img[src^=\"cid:\"]");
for (int i = 0; i < inline_list.length; ++i) {
// Then look for all <img> tags. Inline images are replaced with
// data URLs, while external images are added to
// external_images_uri (to be used later by is_image()).
Gee.ArrayList<string> external_images_uri = new Gee.ArrayList<string>();
WebKit.DOM.NodeList inline_list = container.query_selector_all("img");
for (ulong i = 0; i < inline_list.length; ++i) {
// Get the MIME content for the image.
WebKit.DOM.HTMLImageElement img = (WebKit.DOM.HTMLImageElement) inline_list.item(i);
string mime_id = img.get_attribute("src").substring(4);
Geary.Memory.AbstractBuffer image_content =
email.get_message().get_content_by_mime_id(mime_id);
uint8[] image_data = image_content.get_array();
// Get the content type.
bool uncertain_content_type;
string mimetype = ContentType.get_mime_type(ContentType.guess(null, image_data,
out uncertain_content_type));
// Then set the source to a data url.
web_view.set_data_url(img, mimetype, image_data);
string? src = img.get_attribute("src");
if (Geary.String.is_empty(src)) {
continue;
} else if (src.has_prefix("cid:")) {
string mime_id = src.substring(4);
Geary.Memory.AbstractBuffer image_content =
email.get_message().get_content_by_mime_id(mime_id);
uint8[] image_data = image_content.get_array();
// Get the content type.
bool uncertain_content_type;
string mimetype = ContentType.get_mime_type(ContentType.guess(null, image_data,
out uncertain_content_type));
// Then set the source to a data url.
web_view.set_data_url(img, mimetype, image_data);
} else if (!src.has_prefix("data:")) {
external_images_uri.add(src);
if (!web_view.load_external_images)
external_images_info_bar.show();
}
}
web_view.set_external_images_uris(external_images_uri);
// Now return the whole message.
return set_up_quotes(container.get_inner_html());
} catch (Error e) {
......
......@@ -12,16 +12,19 @@ public class ConversationWebView : WebKit.WebView {
private const string USER_CSS = "user-message.css";
private const string STYLE_NAME = "STYLE";
public signal void image_load_requested();
public signal void link_selected(string link);
private bool load_external_images = false;
private FileMonitor? user_style_monitor = null;
public bool load_external_images { get; private set; default = false; }
// HTML element that contains message DIVs.
public WebKit.DOM.HTMLDivElement? container { get; private set; default = null; }
private Gee.ArrayList<string>? external_images_uri = null;
private FileMonitor? user_style_monitor = null;
public signal void image_load_requested();
public signal void link_selected(string link);
public ConversationWebView() {
// Set defaults.
set_border_width(0);
......@@ -79,15 +82,31 @@ public class ConversationWebView : WebKit.WebView {
private void on_resource_request_starting(WebKit.WebFrame web_frame,
WebKit.WebResource web_resource, WebKit.NetworkRequest request,
WebKit.NetworkResponse? response) {
if (response != null) {
// A request that was previously approved resulted in a redirect.
return;
}
string? uri = request.get_uri();
bool uri_is_image = is_image(uri);
if (uri_is_image && !load_external_images)
image_load_requested();
if (!is_always_loaded(uri) && !(uri_is_image && load_external_images))
if (!is_always_loaded(uri) && !(is_image(uri) && load_external_images))
request.set_uri("about:blank");
}
public void set_external_images_uris(Gee.ArrayList<string> uris) {
external_images_uri = uris;
}
public bool is_image(string? uri) {
if (Geary.String.is_empty_or_whitespace(uri))
return false;
if (uri.has_prefix("data:image/"))
return true;
// check if external_images_uri is null in case this is called before a page is loaded
return (external_images_uri != null) ? (uri in external_images_uri) : false;
}
private bool is_always_loaded(string? uri) {
if (uri == null)
return false;
......@@ -100,7 +119,7 @@ public class ConversationWebView : WebKit.WebView {
return false;
}
public void set_load_external_images(bool load_external_images) {
public void apply_load_external_images(bool load_external_images) {
this.load_external_images = load_external_images;
// Refreshing the images would do nothing in this case--the resource has already been
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment