No need to configure CURLOPT_WRITEFUNCTION twice
[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   char *memory;
12   size_t size;
13 };
14
15 http::http()
16 {
17     curl = curl_easy_init();
18     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
19     curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
20     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
21     curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
22     curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
23     curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
24     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http::curl_write_data);
25 }
26
27 http::~http()
28 {
29     curl_easy_cleanup(curl);
30 }
31
32 size_t http::curl_write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr) {
33     struct Data* data = (struct Data *) data_ptr;
34     size_t realsize = size * nmemb;
35     
36     char *input = (char *) g_realloc(data->memory, data->size + realsize + 1);
37     if(input == NULL) {
38         /* out of memory! */
39         g_warning("not enough memory (realloc returned NULL)");
40         return 0;
41     }
42     
43     data->memory = input;
44     memcpy(&(data->memory[data->size]), ptr, realsize);
45     data->size += realsize;
46     data->memory[data->size] = 0;
47     
48     return realsize;
49 }
50
51 void http::destroy_giostream(gpointer data) {
52     GInputStream* gio;
53     if (data) {
54         gio = G_INPUT_STREAM(data);
55         g_input_stream_close(gio, NULL, NULL);
56         gio = NULL;
57     }
58 }
59
60 GInputStream *http::load_url(const gchar *url, GError **error)
61 {
62     GError* _error = NULL;
63     CURLcode res = CURLE_OK;
64     gsize len;
65     gchar* content;
66     GInputStream* stream = NULL;
67     struct Data data;
68
69     data.memory = (char *) g_malloc(1);
70     data.size = 0;
71     
72     if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
73         gchar* newurl = g_filename_from_uri(url, NULL, NULL);
74         if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
75             stream = g_memory_input_stream_new_from_data(content, len, http::destroy_giostream);
76         } else {
77             debug_print("Got error: %s\n", _error->message);
78         }
79         g_free(newurl);
80     } else {
81         if (!curl) return NULL;
82         curl_easy_setopt(curl, CURLOPT_URL, url);
83         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data);
84         res = curl_easy_perform(curl);
85         if (res != CURLE_OK) {
86             _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
87         } else {
88             debug_print("Image size: %d\n", data.size);
89             stream = g_memory_input_stream_new_from_data(g_memdup(data.memory, data.size), data.size, http::destroy_giostream);
90             g_free(data.memory);
91         }
92     }
93
94     if (error && _error) *error = _error;
95
96     return stream;
97 }
98