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)
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 ***********************************************************************/
15 #include <fc_config.h>
18 #include <curl/curl.h>
20 #ifdef FREECIV_MSWINDOWS
34 struct curl_httppost
*first
;
35 struct curl_httppost
*last
;
38 typedef size_t (*netfile_write_cb
)(char *ptr
, size_t size
, size_t nmemb
, void *userdata
);
40 static char error_buf_curl
[CURL_ERROR_SIZE
];
42 /**********************************************************************
43 Set handle to usable state.
44 ***********************************************************************/
45 static CURL
*netfile_init_handle(void)
47 /* Consecutive transfers can use same handle for better performance */
48 static CURL
*handle
= NULL
;
51 handle
= curl_easy_init();
53 curl_easy_reset(handle
);
56 error_buf_curl
[0] = '\0';
57 curl_easy_setopt(handle
, CURLOPT_ERRORBUFFER
, error_buf_curl
);
62 /**********************************************************************
63 curl write callback to store received file to memory.
64 ***********************************************************************/
65 static size_t netfile_memwrite_cb(char *ptr
, size_t size
, size_t nmemb
, void *userdata
)
67 struct netfile_write_cb_data
*data
= (struct netfile_write_cb_data
*)userdata
;
70 data
->mem
= fc_realloc(data
->mem
, data
->size
+ size
* nmemb
);
71 memcpy(data
->mem
+ data
->size
, ptr
, size
* nmemb
);
72 data
->size
+= size
* nmemb
;
78 /**********************************************************************
79 Fetch file from given URL to given file stream. This is core
80 function of netfile module.
81 ***********************************************************************/
82 static bool netfile_download_file_core(const char *URL
, FILE *fp
,
83 struct netfile_write_cb_data
*mem_data
,
84 nf_errmsg cb
, void *data
)
87 struct curl_slist
*headers
= NULL
;
91 handle
= netfile_init_handle();
93 headers
= curl_slist_append(headers
,"User-Agent: Freeciv/" VERSION_STRING
);
95 curl_easy_setopt(handle
, CURLOPT_URL
, URL
);
96 if (mem_data
!= NULL
) {
99 curl_easy_setopt(handle
, CURLOPT_WRITEFUNCTION
, netfile_memwrite_cb
);
100 curl_easy_setopt(handle
, CURLOPT_WRITEDATA
, mem_data
);
102 curl_easy_setopt(handle
, CURLOPT_WRITEDATA
, fp
);
104 curl_easy_setopt(handle
, CURLOPT_HTTPHEADER
, headers
);
105 curl_easy_setopt(handle
, CURLOPT_FAILONERROR
, 1);
107 curlret
= curl_easy_perform(handle
);
109 curl_slist_free_all(headers
);
111 if (curlret
!= CURLE_OK
) {
113 char buf
[2048 + CURL_ERROR_SIZE
];
115 fc_snprintf(buf
, sizeof(buf
),
116 /* TRANS: first %s is URL, second is Curl error message
117 * (not in Freeciv translation domain) */
118 _("Failed to fetch %s: %s"), URL
,
119 error_buf_curl
[0] != '\0' ? error_buf_curl
: curl_easy_strerror(curlret
));
129 /**********************************************************************
130 Fetch section file from net
131 ***********************************************************************/
132 struct section_file
*netfile_get_section_file(const char *URL
,
133 nf_errmsg cb
, void *data
)
136 struct section_file
*out
= NULL
;
137 struct netfile_write_cb_data mem_data
;
140 success
= netfile_download_file_core(URL
, NULL
, &mem_data
, cb
, data
);
143 file
= fz_from_memory(mem_data
.mem
, mem_data
.size
, TRUE
);
145 out
= secfile_from_stream(file
, TRUE
);
151 /**********************************************************************
152 Fetch file from given URL and save as given filename.
153 ***********************************************************************/
154 bool netfile_download_file(const char *URL
, const char *filename
,
155 nf_errmsg cb
, void *data
)
160 fp
= fc_fopen(filename
, "w+b");
166 fc_snprintf(buf
, sizeof(buf
),
167 _("Could not open %s for writing"), filename
);
173 success
= netfile_download_file_core(URL
, fp
, NULL
, cb
, data
);
180 /**********************************************************************
181 Allocate netfile_post
182 ***********************************************************************/
183 struct netfile_post
*netfile_start_post(void)
185 return fc_calloc(1, sizeof(struct netfile_post
));
188 /**********************************************************************
189 Add one entry to netfile post form
190 ***********************************************************************/
191 void netfile_add_form_str(struct netfile_post
*post
,
192 const char *name
, const char *val
)
194 curl_formadd(&post
->first
, &post
->last
,
195 CURLFORM_COPYNAME
, name
,
196 CURLFORM_COPYCONTENTS
, val
,
200 /**********************************************************************
201 Add one integer entry to netfile post form
202 ***********************************************************************/
203 void netfile_add_form_int(struct netfile_post
*post
,
204 const char *name
, const int val
)
208 fc_snprintf(buf
, sizeof(buf
), "%d", val
);
209 netfile_add_form_str(post
, name
, buf
);
212 /**********************************************************************
213 Free netfile_post resources
214 ***********************************************************************/
215 void netfile_close_post(struct netfile_post
*post
)
217 curl_formfree(post
->first
);
221 /**********************************************************************
222 Dummy write callback used only to make sure curl's default write
223 function does not get used as we don't want reply to stdout
224 ***********************************************************************/
225 static size_t dummy_write(void *buffer
, size_t size
, size_t nmemb
, void *userp
)
230 /**********************************************************************
232 ***********************************************************************/
233 bool netfile_send_post(const char *URL
, struct netfile_post
*post
,
234 FILE *reply_fp
, struct netfile_write_cb_data
*mem_data
,
239 struct curl_slist
*headers
= NULL
;
242 handle
= netfile_init_handle();
244 headers
= curl_slist_append(headers
,"User-Agent: Freeciv/" VERSION_STRING
);
246 curl_easy_setopt(handle
, CURLOPT_URL
, URL
);
247 curl_easy_setopt(handle
, CURLOPT_HTTPPOST
, post
->first
);
248 if (mem_data
!= NULL
) {
249 mem_data
->mem
= NULL
;
251 curl_easy_setopt(handle
, CURLOPT_WRITEFUNCTION
, netfile_memwrite_cb
);
252 curl_easy_setopt(handle
, CURLOPT_WRITEDATA
, mem_data
);
253 } else if (reply_fp
== NULL
) {
254 curl_easy_setopt(handle
, CURLOPT_WRITEFUNCTION
, dummy_write
);
256 curl_easy_setopt(handle
, CURLOPT_WRITEDATA
, reply_fp
);
259 curl_easy_setopt(handle
, CURLOPT_INTERFACE
, addr
);
261 curl_easy_setopt(handle
, CURLOPT_HTTPHEADER
, headers
);
263 curlret
= curl_easy_perform(handle
);
265 curl_slist_free_all(headers
);
267 if (curlret
!= CURLE_OK
) {
271 curl_easy_getinfo(handle
, CURLINFO_RESPONSE_CODE
, &http_resp
);
273 if (http_resp
!= 200) {