Make Litehtml's curl writefunction add data directly to the GInputStream
[claws.git] / src / plugins / litehtml_viewer / http.cpp
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <string.h>
6 #include "http.h"
7
8 #include "utils.h"
9
10 struct Data {
11   GInputStream *memory;
12   size_t size;
13 };
14
15 static size_t write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr) {
16     struct Data* data = (struct Data *) data_ptr;
17     size_t realsize = size * nmemb;
18
19                 g_memory_input_stream_add_data((GMemoryInputStream *)data->memory,
20                                 g_memdup(ptr, realsize), realsize,
21                                 g_free);
22                 data->size += realsize;
23     
24     return realsize;
25 }
26
27 http::http()
28 {
29     curl = curl_easy_init();
30     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
31     curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
32     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
33     curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
34     curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
35     curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
36     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
37     stream = NULL;
38 }
39
40 http::~http()
41 {
42     curl_easy_cleanup(curl);
43     destroy_giostream();
44 }
45
46 void http::destroy_giostream() {
47     debug_print("destroy_giostream called.\n");
48     if (stream) {
49         debug_print("Freeing input_stream\n");
50         g_input_stream_close(stream, NULL, NULL);
51         g_object_unref(stream);
52     }
53 }
54
55 GInputStream *http::load_url(const gchar *url, GError **error)
56 {
57         GError* _error = NULL;
58         CURLcode res = CURLE_OK;
59         gsize len;
60         gchar* content;
61     
62         if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
63                 gchar* newurl = g_filename_from_uri(url, NULL, NULL);
64                 if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
65                         stream = g_memory_input_stream_new_from_data(content, len, g_free);
66                 } else {
67                         debug_print("Got error: %s\n", _error->message);
68                 }
69                 g_free(newurl);
70         } else {
71                 struct Data data;
72
73                 data.memory = g_memory_input_stream_new();
74                 data.size = 0;
75
76                 if (!curl) return NULL;
77
78                 curl_easy_setopt(curl, CURLOPT_URL, url);
79                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data);
80                 res = curl_easy_perform(curl);
81
82                 if (res != CURLE_OK) {
83                         _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
84                         g_object_unref(data.memory);
85                 } else {
86                         debug_print("Image size: %d\n", data.size);
87                         stream = data.memory;
88                 }
89         }
90
91         if (error && _error) *error = _error;
92
93         return stream;
94 }