Refactor image loading to a separate class. Add dependency to curl
authorMichael Rasmussen <mir@datanom.net>
Wed, 7 Nov 2018 22:49:35 +0000 (23:49 +0100)
committerAndrej Kacian <ticho@claws-mail.org>
Tue, 12 Feb 2019 18:38:09 +0000 (19:38 +0100)
Signed-off-by: Michael Rasmussen <mir@datanom.net>
configure.ac
src/plugins/litehtml_viewer/Makefile.am
src/plugins/litehtml_viewer/http.cpp [new file with mode: 0644]
src/plugins/litehtml_viewer/http.h [new file with mode: 0644]
src/plugins/litehtml_viewer/lh_widget.cpp
src/plugins/litehtml_viewer/lh_widget.h

index 6b4b946..09b0fde 100644 (file)
@@ -1124,7 +1124,7 @@ dnl either yes or no, and do the AC_SUBST calls.
 dnl Archive:           libarchive
 dnl Fancy:             Webkit, curl, optionally libsoup-gnome
 dnl Gdata:             libgdata
-dnl Litehtml           cairo, fontconfig, gumbo
+dnl Litehtml           cairo, fontconfig, gumbo, curl
 dnl Libravatar:                libcurl
 dnl Notification:      optionally libnotify  unity/messaging-menu
 dnl                               libcanberra_gtk hotkey
@@ -1636,6 +1636,10 @@ if test x"$enable_litehtml_viewer_plugin" != xno; then
        if test x"$HAVE_LIBGUMBO" = xno; then
                dependencies_missing="libgumbo $dependencies_missing"
        fi
+        if test x"$HAVE_CURL" = xno; then
+                dependencies_missing="libcurl $dependencies_missing"
+        fi
+
 
         if test x"$dependencies_missing" = x; then
                 PLUGINS="$PLUGINS litehtml_viewer"
index 15cb479..648960c 100644 (file)
@@ -46,7 +46,9 @@ litehtml_viewer_la_SOURCES = \
        container_linux.h \
        lh_viewer.h \
        lh_widget.h \
-       lh_widget_wrapped.h
+       lh_widget_wrapped.h \
+       http.h \
+       http.cpp
 
 litehtml_viewer_la_LDFLAGS = \
        $(plugin_res_ldflag) $(no_undefined) $(export_symbols) \
diff --git a/src/plugins/litehtml_viewer/http.cpp b/src/plugins/litehtml_viewer/http.cpp
new file mode 100644 (file)
index 0000000..46882e1
--- /dev/null
@@ -0,0 +1,79 @@
+#include "http.h"
+
+http::http()
+{
+    curl = curl_easy_init();
+    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+    curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
+    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
+    curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+    curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
+    curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http::curl_write_data);
+    response_data = NULL;
+    response_size = 0;;
+}
+
+http::~http()
+{
+    curl_easy_cleanup(curl);
+    if (response_data) {
+        g_free(response_data);
+    }
+}
+
+size_t http::curl_write_data(char* ptr, size_t size, size_t nmemb, void* data) {
+       if (!response_data)
+               response_data = (char *) malloc(size * nmemb);
+       else
+               response_data = (char *) realloc(response_data, response_size + size * nmemb);
+       if (response_data) {
+               memcpy(response_data + response_size, ptr, size * nmemb);
+               response_size += size * nmemb;
+       }
+       return size * nmemb;
+}
+
+void http::destroy_giostream(gpointer data) {
+       GInputStream* gio;
+       if (data) {
+               gio = G_INPUT_STREAM(data);
+               g_input_stream_close(gio, NULL, NULL);
+               gio = NULL;
+       }
+}
+
+GInputStream *http::load_url(const gchar *url, GError **error)
+{
+       GError* _error = NULL;
+       CURLcode res = CURLE_OK;
+       gsize len;
+       gchar* content;
+    GInputStream* stream = NULL;
+
+
+       if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
+               gchar* newurl = g_filename_from_uri(url, NULL, NULL);
+               if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
+                       stream = g_memory_input_stream_new_from_data(content, len, http::destroy_giostream);
+               } else {
+                       g_log(NULL, G_LOG_LEVEL_MESSAGE, "%s", _error->message);
+               }
+               g_free(newurl);
+       } else {
+               if (!curl) return NULL;
+           curl_easy_setopt(curl, CURLOPT_URL, url);
+           curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_data);
+           res = curl_easy_perform(curl);
+           if (res != CURLE_OK) {
+                   _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
+           } else {
+               stream = g_memory_input_stream_new_from_data(response_data, response_size, http::destroy_giostream);
+           }
+       }
+
+       if (error && _error) *error = _error;
+
+       return stream;
+}
+
diff --git a/src/plugins/litehtml_viewer/http.h b/src/plugins/litehtml_viewer/http.h
new file mode 100644 (file)
index 0000000..4c4b03f
--- /dev/null
@@ -0,0 +1,28 @@
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <curl/curl.h>
+#include <gio/gio.h>
+
+#define HTTP_GET_TIMEOUT 5L
+
+class http
+{
+    CURL*           curl;
+    static gchar*   response_data;
+    static size_t   response_size;
+
+public:
+    http();
+    ~http();
+
+    GInputStream *load_url(const gchar *url, GError **error);
+
+private:
+    static size_t curl_write_data(char* ptr, size_t size, size_t nmemb, void* data);
+    static void destroy_giostream(gpointer data);
+};
+
+
index 5c90005..ba423a0 100644 (file)
 #include <curl/curl.h>
 #include "lh_widget.h"
 #include "lh_widget_wrapped.h"
+#include "http.h"
 
 char master_css[] = {
 #include "css.inc"
 };
 
-/**
-  * curl callback
-  */
-static char* response_mime = NULL;     /* response content-type. ex: "text/html" */
-static char* response_data = NULL;     /* response data from server. */
-static size_t response_size = 0;       /* response size of data */
-
 static gboolean expose_event_cb(GtkWidget *widget, GdkEvent *event,
                gpointer user_data);
 static void size_allocate_cb(GtkWidget *widget, GdkRectangle *allocation,
                gpointer user_data);
-static size_t handle_returned_data(char* ptr, size_t size, size_t nmemb, void* stream);
-static size_t handle_returned_header(void* ptr, size_t size, size_t nmemb, void* stream);
 
 lh_widget::lh_widget()
 {
@@ -76,7 +68,6 @@ lh_widget::lh_widget()
        m_html = NULL;
        m_rendered_width = 0;
        m_context.load_master_stylesheet(master_css);
-       stream = NULL;
 }
 
 lh_widget::~lh_widget()
@@ -86,10 +77,6 @@ lh_widget::~lh_widget()
        g_object_unref(m_scrolled_window);
        m_scrolled_window = NULL;
        m_html = NULL;
-       if (stream) {
-           g_input_stream_close(stream, NULL, NULL);
-           stream = NULL;
-       }
 }
 
 GtkWidget *lh_widget::get_widget() const
@@ -149,27 +136,20 @@ GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_rea
 
        g_log(NULL, G_LOG_LEVEL_MESSAGE, "Loading... %s", url);
 
-       GInputStream *image = load_url(url, &error);
+    http http_loader;
+    GInputStream *image = http_loader.load_url(url, &error);
+    
+       if (!image) return NULL;
+       
+       pixbuf = gdk_pixbuf_new_from_stream(image, NULL, &error);
        if (error) {
-               g_log(NULL, G_LOG_LEVEL_MESSAGE, "Error: %s", error->message);
-               g_error_free(error);
-               return NULL;
+           g_log(NULL, G_LOG_LEVEL_ERROR, "lh_widget::get_image: Could not create pixbuf %s", error->message);
+           pixbuf = NULL;
        }
 
-       GdkPixbufLoader* loader = gdk_pixbuf_loader_new();
-       if (gdk_pixbuf_loader_write(loader, (const guchar*)response_data, response_size, &error)) {
-               pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
-       } else {
-               g_log(NULL, G_LOG_LEVEL_ERROR, "lh_widget::get_image: Could not create pixbuf");
-       }
-       gdk_pixbuf_loader_close(loader, NULL);
-
-        /* cleanup callback data */
-        if (response_mime) g_free(response_mime);
-        if (response_data) g_free(response_data);
-        response_data = NULL;
-        response_mime = NULL;
-        response_size = 0;
+/*     if (redraw_on_ready) {
+               redraw();
+       }*/
        
        return pixbuf;
 }
@@ -282,57 +262,6 @@ void lh_widget::clear()
        m_rendered_width = 0;
 }
 
-GInputStream *lh_widget::load_url(const gchar *url, GError **error)
-{
-       GError* _error = NULL;
-       CURL* curl = NULL;
-       CURLcode res = CURLE_OK;
-       gsize len;
-       gchar* content;
-
-       /* initialize callback data */
-       response_mime = NULL;
-       response_data = NULL;
-       response_size = 0;
-       if (stream) {
-               g_input_stream_close(stream, NULL, &_error);
-               if (_error) {
-                       if (error) *error = _error;
-                       return NULL;
-               }
-       }
-               
-       stream = NULL;
-
-       if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
-               gchar* newurl = g_filename_from_uri(url, NULL, NULL);
-               if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
-                       stream = g_memory_input_stream_new_from_data(content, len, g_free);
-               } else {
-                       g_log(NULL, G_LOG_LEVEL_MESSAGE, "%s", _error->message);
-               }
-               g_free(newurl);
-       } else {
-               curl = curl_easy_init();
-               if (!curl) return NULL;
-               curl_easy_setopt(curl, CURLOPT_URL, url);
-               curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
-               curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
-               curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
-               curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
-               curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
-               res = curl_easy_perform(curl);
-               curl_easy_cleanup(curl);
-               if (res == CURLE_OK) {
-                       stream = g_memory_input_stream_new_from_data(content, response_size, g_free);
-               } else
-                       _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
-       }
-
-       if (error && _error) *error = _error;
-
-       return stream;
-}
 
 static gboolean expose_event_cb(GtkWidget *widget, GdkEvent *event,
                gpointer user_data)
@@ -354,34 +283,6 @@ static void size_allocate_cb(GtkWidget *widget, GdkRectangle *allocation,
        w->redraw();
 }
 
-static size_t handle_returned_data(char* ptr, size_t size, size_t nmemb, void* stream) {
-       if (!response_data)
-               response_data = (char*)malloc(size*nmemb);
-       else
-               response_data = (char*)realloc(response_data, response_size+size*nmemb);
-       if (response_data) {
-               memcpy(response_data+response_size, ptr, size*nmemb);
-               response_size += size*nmemb;
-       }
-       return size*nmemb;
-}
-
-static size_t handle_returned_header(void* ptr, size_t size, size_t nmemb, void* stream) {
-       char* header = NULL;
-
-       header = (char*) malloc(size*nmemb + 1);
-       memcpy(header, ptr, size*nmemb);
-       header[size*nmemb] = 0;
-       if (strncmp(header, "Content-Type: ", 14) == 0) {
-               char* stop = header + 14;
-               stop = strpbrk(header + 14, "\r\n;");
-               if (stop) *stop = 0;
-               response_mime = strdup(header + 14);
-       }
-       free(header);
-       return size*nmemb;
-}
-
 ///////////////////////////////////////////////////////////
 extern "C" {
 
index b17b626..0cb97c6 100644 (file)
@@ -4,7 +4,7 @@
 
 #include "container_linux.h"
 
-#define HTTP_GET_TIMEOUT 60L
+#define HTTP_GET_TIMEOUT 5L
 
 class lh_widget : public container_linux
 {
@@ -33,7 +33,6 @@ class lh_widget : public container_linux
                void paint_white();
                GInputStream *load_url(const gchar *url, GError **error);
 
-               GInputStream *stream;
                litehtml::document::ptr m_html;
                gint m_rendered_width;
                GtkWidget *m_drawing_area;