From: Michael Rasmussen Date: Wed, 7 Nov 2018 22:49:35 +0000 (+0100) Subject: Refactor image loading to a separate class. Add dependency to curl X-Git-Tag: 3.17.4~144 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=0a5c4155c189513caba6e2d79b1bf3b0643f169c Refactor image loading to a separate class. Add dependency to curl Signed-off-by: Michael Rasmussen --- diff --git a/configure.ac b/configure.ac index 6b4b94641..09b0fde1c 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/src/plugins/litehtml_viewer/Makefile.am b/src/plugins/litehtml_viewer/Makefile.am index 15cb479b3..648960ce5 100644 --- a/src/plugins/litehtml_viewer/Makefile.am +++ b/src/plugins/litehtml_viewer/Makefile.am @@ -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 index 000000000..46882e1c3 --- /dev/null +++ b/src/plugins/litehtml_viewer/http.cpp @@ -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 index 000000000..4c4b03f72 --- /dev/null +++ b/src/plugins/litehtml_viewer/http.h @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include + +#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); +}; + + diff --git a/src/plugins/litehtml_viewer/lh_widget.cpp b/src/plugins/litehtml_viewer/lh_widget.cpp index 5c90005c7..ba423a09a 100644 --- a/src/plugins/litehtml_viewer/lh_widget.cpp +++ b/src/plugins/litehtml_viewer/lh_widget.cpp @@ -30,24 +30,16 @@ #include #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" { diff --git a/src/plugins/litehtml_viewer/lh_widget.h b/src/plugins/litehtml_viewer/lh_widget.h index b17b6262a..0cb97c639 100644 --- a/src/plugins/litehtml_viewer/lh_widget.h +++ b/src/plugins/litehtml_viewer/lh_widget.h @@ -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;