Cleaner code a fix memory leak
[claws.git] / src / plugins / litehtml_viewer / http.cpp
1 #include "http.h"
2
3 struct Data {
4   char *memory;
5   size_t size;
6 };
7
8 http::http()
9 {
10     curl = curl_easy_init();
11     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
12     curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
13     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
14     curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
15     curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
16     curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
17     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http::curl_write_data);
18 }
19
20 http::~http()
21 {
22     curl_easy_cleanup(curl);
23 }
24
25 size_t http::curl_write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr) {
26     struct Data* data = (struct Data *) data_ptr;
27     size_t realsize = size * nmemb;
28     
29     char *input = (char *) realloc(data->memory, data->size + realsize + 1);
30     if(ptr == NULL) {
31         /* out of memory! */
32         g_log(NULL, G_LOG_LEVEL_ERROR, "not enough memory (realloc returned NULL)");
33         return 0;
34     }
35     
36     data->memory = input;
37     memcpy(&(data->memory[data->size]), ptr, realsize);
38     data->size += realsize;
39     data->memory[data->size] = 0;
40     
41     return realsize;
42 }
43
44 void http::destroy_giostream(gpointer data) {
45         GInputStream* gio;
46         if (data) {
47                 gio = G_INPUT_STREAM(data);
48                 g_input_stream_close(gio, NULL, NULL);
49                 gio = NULL;
50         }
51 }
52
53 GInputStream *http::load_url(const gchar *url, GError **error)
54 {
55         GError* _error = NULL;
56         CURLcode res = CURLE_OK;
57         gsize len;
58         gchar* content;
59     GInputStream* stream = NULL;
60     struct Data data;
61
62     data.memory = (char *) malloc(1);
63     data.size = 0;
64     
65         if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
66                 gchar* newurl = g_filename_from_uri(url, NULL, NULL);
67                 if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
68                         stream = g_memory_input_stream_new_from_data(content, len, http::destroy_giostream);
69                 } else {
70                         g_log(NULL, G_LOG_LEVEL_MESSAGE, "%s", _error->message);
71                 }
72                 g_free(newurl);
73         } else {
74                 if (!curl) return NULL;
75             curl_easy_setopt(curl, CURLOPT_URL, url);
76             curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_data);
77             curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data);
78             res = curl_easy_perform(curl);
79             if (res != CURLE_OK) {
80                     _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
81             } else {
82                 stream = g_memory_input_stream_new_from_data(g_memdup(data.memory, data.size), data.size, http::destroy_giostream);
83                 g_free(data.memory);
84             }
85         }
86
87         if (error && _error) *error = _error;
88
89         return stream;
90 }
91