3d97c99d03a554b36e3b3e2a6c83e8f975d1da95
[claws.git] / src / plugins / litehtml_viewer / http.cpp
1 /*
2  * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
3  * Copyright(C) 2019 the Claws Mail Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write tothe Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <string.h>
23 #include "http.h"
24
25 extern "C" {
26 #include "ssl.h"
27 #include "utils.h"
28 }
29
30 struct Data {
31   GInputStream *memory;
32   size_t size;
33 };
34
35 static size_t write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr) {
36         struct Data* data = (struct Data *) data_ptr;
37         size_t realsize = size * nmemb;
38
39         g_memory_input_stream_add_data((GMemoryInputStream *)data->memory,
40 #if !GLIB_CHECK_VERSION (2, 68, 0)
41                 g_memdup(ptr, realsize),
42 #else
43                 g_memdup2(ptr, realsize),
44 #endif
45                 realsize,
46                 g_free);
47         data->size += realsize;
48     
49         return realsize;
50 }
51
52 http::http()
53 {
54     curl = curl_easy_init();
55     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
56     curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT);
57     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
58     curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
59     curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
60     curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
61     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
62 #ifdef G_OS_WIN32
63     curl_easy_setopt(curl, CURLOPT_CAINFO, claws_ssl_get_cert_file());
64 #endif
65     stream = NULL;
66 }
67
68 http::~http()
69 {
70     curl_easy_cleanup(curl);
71     destroy_giostream();
72 }
73
74 void http::destroy_giostream() {
75     debug_print("destroy_giostream called.\n");
76     if (stream) {
77         debug_print("Freeing input_stream\n");
78         g_input_stream_close(stream, NULL, NULL);
79         g_object_unref(stream);
80     }
81 }
82
83 GInputStream *http::load_url(const gchar *url, GError **error)
84 {
85         GError* _error = NULL;
86         CURLcode res = CURLE_OK;
87         gsize len;
88         gchar* content;
89     
90         if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
91                 gchar* newurl = g_filename_from_uri(url, NULL, NULL);
92                 if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
93                         stream = g_memory_input_stream_new_from_data(content, len, g_free);
94                 } else {
95                         debug_print("Got error: %s\n", _error->message);
96                 }
97                 g_free(newurl);
98         } else {
99                 struct Data data;
100
101                 if (!curl) return NULL;
102
103                 data.memory = g_memory_input_stream_new();
104                 data.size = 0;
105
106                 curl_easy_setopt(curl, CURLOPT_URL, url);
107                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data);
108                 res = curl_easy_perform(curl);
109
110                 if (res != CURLE_OK) {
111                         _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
112                         g_object_unref(data.memory);
113                 } else {
114                         debug_print("Image size: %" G_GSIZE_FORMAT "\n", data.size);
115                         stream = data.memory;
116                 }
117         }
118
119         if (error && _error) *error = _error;
120
121         return stream;
122 }