Added support for local image attachments to the Litehtml plugin
authorAndrej Kacian <ticho@claws-mail.org>
Sat, 9 Mar 2019 21:32:32 +0000 (22:32 +0100)
committerAndrej Kacian <ticho@claws-mail.org>
Sat, 4 May 2019 14:56:07 +0000 (16:56 +0200)
src/plugins/litehtml_viewer/container_linux.cpp
src/plugins/litehtml_viewer/container_linux.h
src/plugins/litehtml_viewer/container_linux_images.cpp
src/plugins/litehtml_viewer/lh_viewer.c
src/plugins/litehtml_viewer/lh_widget.cpp
src/plugins/litehtml_viewer/lh_widget.h
src/plugins/litehtml_viewer/lh_widget_wrapped.h

index 923ce769f7238e23b0e604f89954459f4ef8b8f3..ac0f40e0e8651a81a01a6502a9fabfc9a5a68d98 100644 (file)
@@ -127,15 +127,14 @@ void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::b
        litehtml::tstring url;
        make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
 
-       lock_images_cache();
-       bool found = false;
        const image *img_i = NULL;
 
+       lock_images_cache();
+
        for (auto ii = m_images.cbegin(); ii != m_images.cend(); ++ii) {
                const image *i = &(*ii);
                if (i->first == url) {
                        img_i = i;
-                       found = true;
                        break;
                }
        }
index 627bda611e4cdc53aaf728d8429d51c019418979..f35ffeab1d36b175d8f892ee4078f540b0126513 100644 (file)
@@ -96,6 +96,7 @@ public:
 
        void                                                            add_image_to_cache(const gchar *url, GdkPixbuf *image);
        virtual void                            redraw(gboolean force_render) = 0;
+       virtual GdkPixbuf *get_local_image(const litehtml::tstring url) const = 0;
 
 protected:
        virtual void                                            draw_ellipse(cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color, int line_width);
index eeefd40795b1e28fa98ce38eb315989f8ca4d0f2..2c9d91d90533d4d0604d006e7e1f7cfdeecbd7b2 100644 (file)
@@ -32,13 +32,6 @@ static GdkPixbuf *lh_get_image(const litehtml::tchar_t* url)
        GdkPixbuf *pixbuf = NULL;
        http* http_loader = NULL;
 
-       if (!lh_prefs_get()->enable_remote_content) {
-               debug_print("blocking download of image from '%s'\n", url);
-               return NULL;
-       }
-
-       debug_print("allowing download of image from '%s'\n", url);
-
        http_loader = new http();
        GInputStream *image = http_loader->load_url(url, &error);
 
@@ -115,8 +108,26 @@ void container_linux::load_image( const litehtml::tchar_t* src, const litehtml::
 
        unlock_images_cache();
 
-       if(!found) {
+       if (!found) {
                struct FetchCtx *ctx = g_new(struct FetchCtx, 1);
+
+               /* Attached images can be loaded into cache right here. */
+               if (!strncmp(src, "cid:", 4)) {
+                       GdkPixbuf *pixbuf = get_local_image(src);
+
+                       if (pixbuf != NULL)
+                               add_image_to_cache(src, pixbuf);
+
+                       return;
+               }
+
+               if (!lh_prefs_get()->enable_remote_content) {
+                       debug_print("blocking download of image from '%s'\n", src);
+                       return;
+               }
+
+               debug_print("allowing download of image from '%s'\n", src);
+
                ctx->url = g_strdup(url.c_str());
                ctx->container = this;
 
index e3e1fdbc786f97e3dafd3a1ec625d76eb53d02c9..cf22959d5e24215b5da3afbc4832ee32fd15ae19 100644 (file)
@@ -93,6 +93,7 @@ static void lh_show_mimepart(MimeViewer *_viewer, const gchar *infile,
                return;
        }
 
+       lh_widget_set_partinfo(viewer->widget, partinfo);
        lh_widget_open_html(viewer->widget, utf8);
        g_free(utf8);
 }
index 759b46e062f94ee15df64bf784218910a1d0e1eb..64fdbdd7356f289e1be281b6135e0965a6b31aa1 100644 (file)
@@ -104,6 +104,8 @@ lh_widget::lh_widget()
        m_font_name = NULL;
        m_font_size = 0;
 
+       m_partinfo = NULL;
+
        gtk_widget_set_events(m_drawing_area,
                                GDK_BUTTON_RELEASE_MASK
                              | GDK_BUTTON_PRESS_MASK
@@ -406,6 +408,58 @@ const litehtml::tstring lh_widget::fullurl(const litehtml::tchar_t *url) const
        return _t(url);
 }
 
+void lh_widget::set_partinfo(MimeInfo *partinfo)
+{
+       m_partinfo = partinfo;
+}
+
+GdkPixbuf *lh_widget::get_local_image(const litehtml::tstring url) const
+{
+       GdkPixbuf *pixbuf;
+       const gchar *name;
+       MimeInfo *p = m_partinfo;
+
+       if (strncmp(url.c_str(), "cid:", 4) != 0) {
+               debug_print("lh_widget::get_local_image: '%s' is not a local URI, ignoring\n", url.c_str());
+               return NULL;
+       }
+
+       name = url.c_str() + 4;
+       debug_print("getting message part '%s'\n", name);
+
+       while ((p = procmime_mimeinfo_next(p)) != NULL) {
+               size_t len = strlen(name);
+
+               /* p->id is in format "<partname>" */
+               if (!strncasecmp(name, p->id + 1, len) &&
+                               strlen(p->id) >= len + 2 &&
+                               *(p->id + len + 1) == '>') {
+                       GInputStream *stream;
+                       GError *error = NULL;
+
+                       stream = procmime_get_part_as_inputstream(p, &error);
+                       if (error != NULL) {
+                               g_warning("Couldn't get image MIME part: %s\n", error->message);
+                               g_error_free(error);
+                               return NULL;
+                       }
+
+                       pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, &error);
+                       g_object_unref(stream);
+                       if (error != NULL) {
+                               g_warning("Couldn't load image: %s\n", error->message);
+                               g_error_free(error);
+                               return NULL;
+                       }
+
+                       return pixbuf;
+               }
+       }
+
+       /* MIME part with requested name was not found */
+       return NULL;
+}
+
 ////////////////////////////////////////////////
 static gboolean expose_event_cb(GtkWidget *widget, GdkEvent *event,
                gpointer user_data)
@@ -563,4 +617,9 @@ void lh_widget_print(lh_widget_wrapped *w) {
        w->print();
 }
 
+void lh_widget_set_partinfo(lh_widget_wrapped *w, MimeInfo *partinfo)
+{
+       w->set_partinfo(partinfo);
+}
+
 } /* extern "C" */
index 204d612732acc706b6a02ee4e05ee98a09ceb181..e6b784a5ce6b30f16ee802173246597e6bbba922 100644 (file)
@@ -19,6 +19,8 @@
 #include <glib.h>
 #include <gio/gio.h>
 
+#include "procmime.h"
+
 #include "container_linux.h"
 
 struct pango_font
@@ -63,6 +65,9 @@ class lh_widget : public container_linux
                void popup_context_menu(const litehtml::tchar_t *url, GdkEventButton *event);
                const litehtml::tstring fullurl(const litehtml::tchar_t *url) const;
 
+               void set_partinfo(MimeInfo *partinfo);
+               GdkPixbuf *get_local_image(const litehtml::tstring url) const;
+
                litehtml::document::ptr m_html;
                litehtml::tstring m_clicked_url;
                litehtml::tstring m_base_url;
@@ -78,6 +83,7 @@ class lh_widget : public container_linux
                litehtml::context m_context;
                gint m_height;
                litehtml::tstring m_cursor;
+               MimeInfo *m_partinfo;
 
                litehtml::tchar_t *m_font_name;
                int m_font_size;
index 8d3e2eb1e3b304e6594ac4507d6fcb7ff27831a8..2f1581262b5f712ec5ada8dc92bdd77f96109979 100644 (file)
@@ -32,6 +32,7 @@ void lh_widget_destroy(lh_widget_wrapped *w);
 void lh_widget_statusbar_push(const gchar* msg);
 void lh_widget_statusbar_pop();
 void lh_widget_print(lh_widget_wrapped *w);
+void lh_widget_set_partinfo(lh_widget_wrapped *w, MimeInfo *partinfo);
 
 #ifdef __cplusplus
 } /* extern "C" */