Freeciv-3.3: /fast/freeciv/nightly/main/utility/netfile.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
netfile.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#ifndef __EMSCRIPTEN__
19
20#include <curl/curl.h>
21
22#ifdef FREECIV_MSWINDOWS
23#include <windows.h>
24#endif
25
26/* utility */
27#include "fcintl.h"
28#include "ioz.h"
29#include "mem.h"
30#include "rand.h"
31#include "registry.h"
32
33#endif /* __EMSCRIPTEN__ */
34
35#include "netfile.h"
36
37#ifndef __EMSCRIPTEN__
38
39 struct netfile_post {
40#ifdef HAVE_CURL_MIME_API
41 curl_mime *mime;
42#else /* HAVE_CURL_MIME_API */
43 struct curl_httppost *first;
44 struct curl_httppost *last;
45#endif /* HAVE_CURL_MIME_API */
46};
47
48 typedef size_t (*netfile_write_cb)(char *ptr, size_t size, size_t nmemb, void *userdata);
49
50 static char error_buf_curl[CURL_ERROR_SIZE];
51
52/* Consecutive transfers can use same handle for better performance */
53 static CURL *chandle = nullptr;
54
55/*******************************************************************/
58 static CURL *netfile_init_handle(void)
59{
60 if (chandle == nullptr) {
61 chandle = curl_easy_init();
62 } else {
63 curl_easy_reset(chandle);
64 }
65
66 error_buf_curl[0] = '\0';
67 curl_easy_setopt(chandle, CURLOPT_ERRORBUFFER, error_buf_curl);
68
69#ifdef CUSTOM_CACERT_PATH
70 curl_easy_setopt(chandle, CURLOPT_CAINFO, CUSTOM_CACERT_PATH);
71#endif /* CUSTOM_CERT_PATH */
72
73 return chandle;
74}
75
76/*******************************************************************/
79 static size_t netfile_memwrite_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
80{
81 struct netfile_write_cb_data *data = (struct netfile_write_cb_data *)userdata;
82
83 if (size > 0) {
84 data->mem = fc_realloc(data->mem, data->size + size * nmemb);
85 memcpy(data->mem + data->size, ptr, size * nmemb);
86 data->size += size * nmemb;
87 }
88
89 return size * nmemb;
90}
91
92/*******************************************************************/
96 static bool netfile_download_file_core(const char *URL, FILE *fp,
97 struct netfile_write_cb_data *mem_data,
98 nf_errmsg cb, void *data)
99{
100 CURLcode curlret;
101 struct curl_slist *headers = nullptr;
102 static CURL *handle;
103 bool ret = TRUE;
104
105 handle = netfile_init_handle();
106
107 headers = curl_slist_append(headers, "User-Agent: Freeciv/" VERSION_STRING);
108
109 curl_easy_setopt(handle, CURLOPT_URL, URL);
110 if (mem_data != nullptr) {
111 mem_data->mem = nullptr;
112 mem_data->size = 0;
113 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, netfile_memwrite_cb);
114 curl_easy_setopt(handle, CURLOPT_WRITEDATA, mem_data);
115 } else {
116 curl_easy_setopt(handle, CURLOPT_WRITEDATA, fp);
117 }
118 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
119 curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
120
121 curlret = curl_easy_perform(handle);
122
123 curl_slist_free_all(headers);
124
125 if (curlret != CURLE_OK) {
126 if (cb != nullptr) {
127 char buf[2048 + CURL_ERROR_SIZE];
128
129 fc_snprintf(buf, sizeof(buf),
130 /* TRANS: first %s is URL, second is Curl error message
131 * (not in Freeciv translation domain) */
132 _("Failed to fetch %s: %s"), URL,
133 error_buf_curl[0] != '\0' ? error_buf_curl : curl_easy_strerror(curlret));
134 cb(buf, data);
135 }
136
137 ret = FALSE;
138 }
139
140 return ret;
141}
142
143/*******************************************************************/
146 struct section_file *netfile_get_section_file(const char *URL,
147 nf_errmsg cb, void *data)
148{
149 bool success;
150 struct section_file *out = nullptr;
151 struct netfile_write_cb_data mem_data;
152 fz_FILE *file;
153
154 success = netfile_download_file_core(URL, nullptr, &mem_data, cb, data);
155
156 if (success) {
157 file = fz_from_memory(mem_data.mem, mem_data.size, TRUE);
158
159 out = secfile_from_stream(file, TRUE);
160 }
161
162 return out;
163}
164
165/*******************************************************************/
168 bool netfile_download_file(const char *URL, const char *filename,
169 nf_errmsg cb, void *data)
170{
171 bool success;
172 FILE *fp;
173
174 fp = fc_fopen(filename, "w+b");
175
176 if (fp == nullptr) {
177 if (cb != nullptr) {
178 char buf[2048];
179
180 fc_snprintf(buf, sizeof(buf),
181 _("Could not open %s for writing"), filename);
182 cb(buf, data);
183 }
184 return FALSE;
185 }
186
187 success = netfile_download_file_core(URL, fp, nullptr, cb, data);
188
189 fclose(fp);
190
191 return success;
192}
193
194/*******************************************************************/
197 struct netfile_post *netfile_start_post(void)
198{
199 struct netfile_post *post = fc_calloc(1, sizeof(struct netfile_post));
200
201#ifdef HAVE_CURL_MIME_API
202 post->mime = curl_mime_init(chandle);
203#endif
204
205 return post;
206}
207
208/*******************************************************************/
211 void netfile_add_form_str(struct netfile_post *post,
212 const char *name, const char *val)
213{
214#ifdef HAVE_CURL_MIME_API
215 curl_mimepart *part;
216
217 part = curl_mime_addpart(post->mime);
218
219 curl_mime_data(part, val, CURL_ZERO_TERMINATED);
220 curl_mime_name(part, name);
221#else /* HAVE_CURL_MIME_API */
222 curl_formadd(&post->first, &post->last,
223 CURLFORM_COPYNAME, name,
224 CURLFORM_COPYCONTENTS, val,
225 CURLFORM_END);
226#endif /* HAVE_CURL_MIME_API */
227}
228
229/*******************************************************************/
232 void netfile_add_form_int(struct netfile_post *post,
233 const char *name, const int val)
234{
235 char buf[50];
236
237 fc_snprintf(buf, sizeof(buf), "%d", val);
238 netfile_add_form_str(post, name, buf);
239}
240
241/*******************************************************************/
244 void netfile_close_post(struct netfile_post *post)
245{
246#ifdef HAVE_CURL_MIME_API
247 curl_mime_free(post->mime);
248#else /* HAVE_CURL_MIME_API */
249 curl_formfree(post->first);
250#endif /* HAVE_CURL_MIME_API */
251
252 FC_FREE(post);
253}
254
255/*******************************************************************/
259 static size_t dummy_write(void *buffer, size_t size, size_t nmemb,
260 void *userp)
261{
262 return size * nmemb;
263}
264
265/*******************************************************************/
268 bool netfile_send_post(const char *URL, struct netfile_post *post,
269 FILE *reply_fp,
270 struct netfile_write_cb_data *mem_data,
271 const char *addr)
272{
273 CURLcode curlret;
274 long http_resp;
275 struct curl_slist *headers = nullptr;
276 static CURL *handle;
277
278 handle = netfile_init_handle();
279
280 headers = curl_slist_append(headers, "User-Agent: Freeciv/" VERSION_STRING);
281
282 curl_easy_setopt(handle, CURLOPT_URL, URL);
283
284#ifdef HAVE_CURL_MIME_API
285 curl_easy_setopt(handle, CURLOPT_MIMEPOST, post->mime);
286#else /* HAVE_CURL_MIME_API */
287 curl_easy_setopt(handle, CURLOPT_HTTPPOST, post->first);
288#endif /* HAVE_CURL_MIME_API */
289
290 if (mem_data != nullptr) {
291 mem_data->mem = nullptr;
292 mem_data->size = 0;
293 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, netfile_memwrite_cb);
294 curl_easy_setopt(handle, CURLOPT_WRITEDATA, mem_data);
295 } else if (reply_fp == nullptr) {
296 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write);
297 } else {
298 curl_easy_setopt(handle, CURLOPT_WRITEDATA, reply_fp);
299 }
300 if (addr != nullptr) {
301 curl_easy_setopt(handle, CURLOPT_INTERFACE, addr);
302 }
303 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
304
305 curlret = curl_easy_perform(handle);
306
307 curl_slist_free_all(headers);
308
309 if (curlret != CURLE_OK) {
310 return FALSE;
311 }
312
313 curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_resp);
314
315 if (http_resp != 200) {
316 return FALSE;
317 }
318
319 return TRUE;
320}
321
322#endif /* __EMSCRIPTEN__ */
323
324/*******************************************************************/
327 void netfile_free(void)
328{
329#ifndef __EMSCRIPTEN__
330 if (chandle != nullptr) {
331 curl_easy_cleanup(chandle);
332 chandle = nullptr;
333 }
334#endif /* __EMSCRIPTEN__ */
335}
incite_cost
char * incite_cost
Definition comments.c:74
fcintl.h
_
#define _(String)
Definition fcintl.h:67
name
const char * name
Definition inputfile.c:127
fz_from_memory
fz_FILE * fz_from_memory(char *buffer, int size, bool control)
Definition ioz.c:207
ioz.h
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_realloc
#define fc_realloc(ptr, sz)
Definition mem.h:36
netfile_init_handle
static CURL * netfile_init_handle(void)
Definition netfile.c:58
netfile_close_post
void netfile_close_post(struct netfile_post *post)
Definition netfile.c:244
error_buf_curl
static char error_buf_curl[CURL_ERROR_SIZE]
Definition netfile.c:50
netfile_start_post
struct netfile_post * netfile_start_post(void)
Definition netfile.c:197
netfile_send_post
bool netfile_send_post(const char *URL, struct netfile_post *post, FILE *reply_fp, struct netfile_write_cb_data *mem_data, const char *addr)
Definition netfile.c:268
netfile_free
void netfile_free(void)
Definition netfile.c:327
netfile_get_section_file
struct section_file * netfile_get_section_file(const char *URL, nf_errmsg cb, void *data)
Definition netfile.c:146
netfile_add_form_int
void netfile_add_form_int(struct netfile_post *post, const char *name, const int val)
Definition netfile.c:232
netfile_download_file_core
static bool netfile_download_file_core(const char *URL, FILE *fp, struct netfile_write_cb_data *mem_data, nf_errmsg cb, void *data)
Definition netfile.c:96
netfile_write_cb
size_t(* netfile_write_cb)(char *ptr, size_t size, size_t nmemb, void *userdata)
Definition netfile.c:48
netfile_add_form_str
void netfile_add_form_str(struct netfile_post *post, const char *name, const char *val)
Definition netfile.c:211
chandle
static CURL * chandle
Definition netfile.c:53
netfile_download_file
bool netfile_download_file(const char *URL, const char *filename, nf_errmsg cb, void *data)
Definition netfile.c:168
netfile_memwrite_cb
static size_t netfile_memwrite_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
Definition netfile.c:79
dummy_write
static size_t dummy_write(void *buffer, size_t size, size_t nmemb, void *userp)
Definition netfile.c:259
netfile.h
nf_errmsg
void(* nf_errmsg)(const char *msg, void *data)
Definition netfile.h:32
rand.h
registry.h
secfile_from_stream
struct section_file * secfile_from_stream(fz_FILE *stream, bool allow_duplicates)
Definition registry_ini.c:610
size
size_t size
Definition specvec.h:72
fz_FILE_s
Definition ioz.c:149
netfile_post
Definition netfile.c:39
netfile_post::first
struct curl_httppost * first
Definition netfile.c:43
netfile_post::last
struct curl_httppost * last
Definition netfile.c:44
netfile_write_cb_data
Definition netfile.h:27
netfile_write_cb_data::mem
char * mem
Definition netfile.h:28
netfile_write_cb_data::size
int size
Definition netfile.h:29
part
Definition goto.c:52
section_file
Definition section_file.h:36
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
fc_fopen
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:505
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47