diff options
author | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
commit | 07274513e984f0b5544586c74508ccd16e7dcafa (patch) | |
tree | b32ff2a9136fbc1a4a6a0ed1e4d79cde0f5f16d9 /libraries/ecore/src/lib/ecore_con/ecore_con_url.c | |
parent | Added Irrlicht 1.8, but without all the Windows binaries. (diff) | |
download | SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.zip SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.gz SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.bz2 SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.xz |
Remove EFL, since it's been released now.
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_url.c | 1635 |
1 files changed, 0 insertions, 1635 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c deleted file mode 100644 index 05f0678..0000000 --- a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c +++ /dev/null | |||
@@ -1,1635 +0,0 @@ | |||
1 | /* | ||
2 | * For info on how to use libcurl, see: | ||
3 | * http://curl.haxx.se/libcurl/c/libcurl-tutorial.html | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * FIXME: Support more CURL features... | ||
8 | */ | ||
9 | |||
10 | #ifdef HAVE_CONFIG_H | ||
11 | # include <config.h> | ||
12 | #endif | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <errno.h> | ||
16 | #include <sys/stat.h> | ||
17 | #include <sys/types.h> | ||
18 | #include <unistd.h> | ||
19 | |||
20 | #ifdef HAVE_WS2TCPIP_H | ||
21 | # include <ws2tcpip.h> | ||
22 | #endif | ||
23 | |||
24 | #ifdef HAVE_ESCAPE | ||
25 | # include <Escape.h> | ||
26 | #endif | ||
27 | |||
28 | #include "Ecore.h" | ||
29 | #include "ecore_private.h" | ||
30 | #include "Ecore_Con.h" | ||
31 | #include "ecore_con_private.h" | ||
32 | |||
33 | #define CURL_MIN_TIMEOUT 100 | ||
34 | |||
35 | int ECORE_CON_EVENT_URL_DATA = 0; | ||
36 | int ECORE_CON_EVENT_URL_COMPLETE = 0; | ||
37 | int ECORE_CON_EVENT_URL_PROGRESS = 0; | ||
38 | |||
39 | #ifdef HAVE_CURL | ||
40 | static void _ecore_con_url_event_url_complete(Ecore_Con_Url *url_con, CURLMsg *curlmsg); | ||
41 | static void _ecore_con_url_multi_remove(Ecore_Con_Url *url_con); | ||
42 | static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con); | ||
43 | static size_t _ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream); | ||
44 | static size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp); | ||
45 | static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); | ||
46 | static size_t _ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream); | ||
47 | static void _ecore_con_event_url_free(Ecore_Con_Url *url_con, void *ev); | ||
48 | static Eina_Bool _ecore_con_url_timer(void *data); | ||
49 | static Eina_Bool _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); | ||
50 | static Eina_Bool _ecore_con_url_timeout_cb(void *data); | ||
51 | static void _ecore_con_url_status_get(Ecore_Con_Url *url_con); | ||
52 | |||
53 | static Eina_List *_url_con_list = NULL; | ||
54 | static Eina_List *_fd_hd_list = NULL; | ||
55 | static CURLM *_curlm = NULL; | ||
56 | static int _init_count = 0; | ||
57 | static Ecore_Timer *_curl_timer = NULL; | ||
58 | static Eina_Bool pipelining = EINA_FALSE; | ||
59 | |||
60 | #endif | ||
61 | |||
62 | /** | ||
63 | * @addtogroup Ecore_Con_Url_Group Ecore URL Connection Functions | ||
64 | * | ||
65 | * @{ | ||
66 | */ | ||
67 | |||
68 | EAPI int | ||
69 | ecore_con_url_init(void) | ||
70 | { | ||
71 | #ifdef HAVE_CURL | ||
72 | long ms; | ||
73 | if (++_init_count > 1) return _init_count; | ||
74 | |||
75 | ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); | ||
76 | ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); | ||
77 | ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new(); | ||
78 | |||
79 | // curl_global_init() is not thread safe! | ||
80 | if (curl_global_init(CURL_GLOBAL_ALL)) return --_init_count; | ||
81 | |||
82 | _curlm = curl_multi_init(); | ||
83 | if (!_curlm) | ||
84 | { | ||
85 | curl_global_cleanup(); | ||
86 | return --_init_count; | ||
87 | } | ||
88 | |||
89 | curl_multi_timeout(_curlm, &ms); | ||
90 | if (ms >= CURL_MIN_TIMEOUT || ms <= 0) ms = CURL_MIN_TIMEOUT; | ||
91 | |||
92 | _curl_timer = ecore_timer_add((double)ms / 1000, _ecore_con_url_timer, NULL); | ||
93 | ecore_timer_freeze(_curl_timer); | ||
94 | |||
95 | return _init_count; | ||
96 | #else | ||
97 | return 0; | ||
98 | #endif | ||
99 | } | ||
100 | |||
101 | EAPI int | ||
102 | ecore_con_url_shutdown(void) | ||
103 | { | ||
104 | #ifdef HAVE_CURL | ||
105 | Ecore_Con_Url *url_con; | ||
106 | Ecore_Fd_Handler *fd_handler; | ||
107 | if (_init_count == 0) return 0; | ||
108 | --_init_count; | ||
109 | if (_init_count) return _init_count; | ||
110 | |||
111 | if (_curl_timer) | ||
112 | { | ||
113 | ecore_timer_del(_curl_timer); | ||
114 | _curl_timer = NULL; | ||
115 | } | ||
116 | |||
117 | EINA_LIST_FREE(_url_con_list, url_con) | ||
118 | ecore_con_url_free(url_con); | ||
119 | EINA_LIST_FREE(_fd_hd_list, fd_handler) | ||
120 | ecore_main_fd_handler_del(fd_handler); | ||
121 | |||
122 | if (_curlm) | ||
123 | { | ||
124 | curl_multi_cleanup(_curlm); | ||
125 | _curlm = NULL; | ||
126 | } | ||
127 | curl_global_cleanup(); | ||
128 | return 0; | ||
129 | #endif | ||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | EAPI void | ||
134 | ecore_con_url_pipeline_set(Eina_Bool enable) | ||
135 | { | ||
136 | #ifdef HAVE_CURL | ||
137 | if (enable == pipelining) return; | ||
138 | curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, !!enable); | ||
139 | pipelining = enable; | ||
140 | #else | ||
141 | return; | ||
142 | (void)enable; | ||
143 | #endif | ||
144 | } | ||
145 | |||
146 | EAPI Eina_Bool | ||
147 | ecore_con_url_pipeline_get(void) | ||
148 | { | ||
149 | #ifdef HAVE_CURL | ||
150 | return pipelining; | ||
151 | #endif | ||
152 | return EINA_FALSE; | ||
153 | } | ||
154 | |||
155 | extern Ecore_Con_Socks *_ecore_con_proxy_global; | ||
156 | |||
157 | EAPI Ecore_Con_Url * | ||
158 | ecore_con_url_new(const char *url) | ||
159 | { | ||
160 | #ifdef HAVE_CURL | ||
161 | Ecore_Con_Url *url_con; | ||
162 | CURLcode ret; | ||
163 | |||
164 | if (!_init_count) | ||
165 | return NULL; | ||
166 | |||
167 | url_con = calloc(1, sizeof(Ecore_Con_Url)); | ||
168 | if (!url_con) | ||
169 | return NULL; | ||
170 | |||
171 | url_con->write_fd = -1; | ||
172 | |||
173 | url_con->curl_easy = curl_easy_init(); | ||
174 | if (!url_con->curl_easy) | ||
175 | { | ||
176 | free(url_con); | ||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | ECORE_MAGIC_SET(url_con, ECORE_MAGIC_CON_URL); | ||
181 | |||
182 | if (!ecore_con_url_url_set(url_con, url)) | ||
183 | { | ||
184 | ecore_con_url_free(url_con); | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | // Read socks proxy | ||
189 | url_con->proxy_type = -1; | ||
190 | if (_ecore_con_proxy_global && _ecore_con_proxy_global->ip && | ||
191 | (_ecore_con_proxy_global->version == 4 || | ||
192 | _ecore_con_proxy_global->version == 5)) | ||
193 | { | ||
194 | char proxy[256]; | ||
195 | char host[256]; | ||
196 | |||
197 | if (_ecore_con_proxy_global->version == 5) | ||
198 | { | ||
199 | if (_ecore_con_proxy_global->lookup) | ||
200 | snprintf(host, sizeof(host), "socks5h://%s", | ||
201 | _ecore_con_proxy_global->ip); | ||
202 | else snprintf(host, sizeof(host), "socks5://%s", | ||
203 | _ecore_con_proxy_global->ip); | ||
204 | } | ||
205 | else if (_ecore_con_proxy_global->version == 4) | ||
206 | { | ||
207 | if (_ecore_con_proxy_global->lookup) | ||
208 | snprintf(host, sizeof(host), "socks4a://%s", | ||
209 | _ecore_con_proxy_global->ip); | ||
210 | else snprintf(host, sizeof(host), "socks4://%s", | ||
211 | _ecore_con_proxy_global->ip); | ||
212 | } | ||
213 | |||
214 | if (_ecore_con_proxy_global->port > 0 && | ||
215 | _ecore_con_proxy_global->port <= 65535) | ||
216 | snprintf(proxy, sizeof(proxy), "%s:%d", host, | ||
217 | _ecore_con_proxy_global->port); | ||
218 | else snprintf(proxy, sizeof(proxy), "%s", host); | ||
219 | |||
220 | ecore_con_url_proxy_set(url_con, proxy); | ||
221 | ecore_con_url_proxy_username_set(url_con, | ||
222 | _ecore_con_proxy_global->username); | ||
223 | } | ||
224 | |||
225 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate"); | ||
226 | if (ret != CURLE_OK) | ||
227 | { | ||
228 | ERR("Could not set CURLOPT_ENCODING to \"gzip,deflate\": %s", | ||
229 | curl_easy_strerror(ret)); | ||
230 | ecore_con_url_free(url_con); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEFUNCTION, | ||
235 | _ecore_con_url_data_cb); | ||
236 | curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEDATA, url_con); | ||
237 | |||
238 | curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, | ||
239 | _ecore_con_url_progress_cb); | ||
240 | curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSDATA, url_con); | ||
241 | curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_FALSE); | ||
242 | |||
243 | curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERFUNCTION, | ||
244 | _ecore_con_url_header_cb); | ||
245 | curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERDATA, url_con); | ||
246 | |||
247 | /* | ||
248 | * FIXME: Check that these timeouts are sensible defaults | ||
249 | * FIXME: Provide a means to change these timeouts | ||
250 | */ | ||
251 | curl_easy_setopt(url_con->curl_easy, CURLOPT_CONNECTTIMEOUT, 30); | ||
252 | curl_easy_setopt(url_con->curl_easy, CURLOPT_FOLLOWLOCATION, 1); | ||
253 | |||
254 | return url_con; | ||
255 | #else | ||
256 | return NULL; | ||
257 | url = NULL; | ||
258 | #endif | ||
259 | } | ||
260 | |||
261 | EAPI Ecore_Con_Url * | ||
262 | ecore_con_url_custom_new(const char *url, | ||
263 | const char *custom_request) | ||
264 | { | ||
265 | #ifdef HAVE_CURL | ||
266 | Ecore_Con_Url *url_con; | ||
267 | CURLcode ret; | ||
268 | |||
269 | if (!url) | ||
270 | return NULL; | ||
271 | |||
272 | if (!custom_request) | ||
273 | return NULL; | ||
274 | |||
275 | url_con = ecore_con_url_new(url); | ||
276 | |||
277 | if (!url_con) | ||
278 | return NULL; | ||
279 | |||
280 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_CUSTOMREQUEST, custom_request); | ||
281 | if (ret != CURLE_OK) | ||
282 | { | ||
283 | ERR("Could not set a custom request string: %s", | ||
284 | curl_easy_strerror(ret)); | ||
285 | ecore_con_url_free(url_con); | ||
286 | return NULL; | ||
287 | } | ||
288 | |||
289 | return url_con; | ||
290 | #else | ||
291 | return NULL; | ||
292 | url = NULL; | ||
293 | custom_request = NULL; | ||
294 | #endif | ||
295 | } | ||
296 | |||
297 | EAPI void | ||
298 | ecore_con_url_free(Ecore_Con_Url *url_con) | ||
299 | { | ||
300 | #ifdef HAVE_CURL | ||
301 | char *s; | ||
302 | |||
303 | if (!url_con) return; | ||
304 | |||
305 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
306 | { | ||
307 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_free"); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | if (url_con->curl_easy) | ||
312 | { | ||
313 | // FIXME : How can we delete curl_easy's fds ?? (Curl do not give this info.) | ||
314 | // This cause "Failed to delete epoll fd xx!" error messages | ||
315 | curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL); | ||
316 | curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE); | ||
317 | |||
318 | if (url_con->multi) | ||
319 | { | ||
320 | _ecore_con_url_multi_remove(url_con); | ||
321 | _url_con_list = eina_list_remove(_url_con_list, url_con); | ||
322 | } | ||
323 | |||
324 | curl_easy_cleanup(url_con->curl_easy); | ||
325 | } | ||
326 | if (url_con->timer) ecore_timer_del(url_con->timer); | ||
327 | |||
328 | url_con->curl_easy = NULL; | ||
329 | url_con->timer = NULL; | ||
330 | url_con->dead = EINA_TRUE; | ||
331 | if (url_con->event_count) return; | ||
332 | ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE); | ||
333 | |||
334 | curl_slist_free_all(url_con->headers); | ||
335 | EINA_LIST_FREE(url_con->additional_headers, s) | ||
336 | free(s); | ||
337 | EINA_LIST_FREE(url_con->response_headers, s) | ||
338 | free(s); | ||
339 | eina_stringshare_del(url_con->url); | ||
340 | if (url_con->post_data) free(url_con->post_data); | ||
341 | free(url_con); | ||
342 | #else | ||
343 | return; | ||
344 | (void)url_con; | ||
345 | #endif | ||
346 | } | ||
347 | |||
348 | EAPI const char * | ||
349 | ecore_con_url_url_get(Ecore_Con_Url *url_con) | ||
350 | { | ||
351 | #ifdef HAVE_CURL | ||
352 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
353 | { | ||
354 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, __func__); | ||
355 | return NULL; | ||
356 | } | ||
357 | return url_con->url; | ||
358 | #else | ||
359 | return NULL; | ||
360 | (void)url_con; | ||
361 | #endif | ||
362 | } | ||
363 | |||
364 | EAPI int | ||
365 | ecore_con_url_status_code_get(Ecore_Con_Url *url_con) | ||
366 | { | ||
367 | #ifdef HAVE_CURL | ||
368 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
369 | { | ||
370 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, __func__); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | if (url_con->status) return url_con->status; | ||
375 | _ecore_con_url_status_get(url_con); | ||
376 | return url_con->status; | ||
377 | #else | ||
378 | return -1; | ||
379 | (void)url_con; | ||
380 | #endif | ||
381 | } | ||
382 | |||
383 | EAPI Eina_Bool | ||
384 | ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url) | ||
385 | { | ||
386 | #ifdef HAVE_CURL | ||
387 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
388 | { | ||
389 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_url_set"); | ||
390 | return EINA_FALSE; | ||
391 | } | ||
392 | |||
393 | if (url_con->dead) return EINA_FALSE; | ||
394 | eina_stringshare_replace(&url_con->url, url); | ||
395 | |||
396 | if (url_con->url) | ||
397 | curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, | ||
398 | url_con->url); | ||
399 | else | ||
400 | curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, ""); | ||
401 | |||
402 | return EINA_TRUE; | ||
403 | #else | ||
404 | return EINA_FALSE; | ||
405 | (void)url; | ||
406 | (void)url_con; | ||
407 | #endif | ||
408 | } | ||
409 | |||
410 | EAPI void | ||
411 | ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data) | ||
412 | { | ||
413 | #ifdef HAVE_CURL | ||
414 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
415 | { | ||
416 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_set"); | ||
417 | return; | ||
418 | } | ||
419 | |||
420 | url_con->data = data; | ||
421 | #else | ||
422 | return; | ||
423 | url_con = NULL; | ||
424 | data = NULL; | ||
425 | #endif | ||
426 | } | ||
427 | |||
428 | EAPI void | ||
429 | ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, const char *key, const char *value) | ||
430 | { | ||
431 | #ifdef HAVE_CURL | ||
432 | char *tmp; | ||
433 | |||
434 | if (url_con->dead) return; | ||
435 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
436 | { | ||
437 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
438 | "ecore_con_url_additional_header_add"); | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | if (url_con->dead) return; | ||
443 | tmp = malloc(strlen(key) + strlen(value) + 3); | ||
444 | if (!tmp) | ||
445 | return; | ||
446 | |||
447 | sprintf(tmp, "%s: %s", key, value); | ||
448 | url_con->additional_headers = eina_list_append(url_con->additional_headers, | ||
449 | tmp); | ||
450 | #else | ||
451 | return; | ||
452 | url_con = NULL; | ||
453 | key = NULL; | ||
454 | value = NULL; | ||
455 | #endif | ||
456 | } | ||
457 | |||
458 | EAPI void | ||
459 | ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con) | ||
460 | { | ||
461 | #ifdef HAVE_CURL | ||
462 | char *s; | ||
463 | |||
464 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
465 | { | ||
466 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
467 | "ecore_con_url_additional_headers_clear"); | ||
468 | return; | ||
469 | } | ||
470 | |||
471 | EINA_LIST_FREE(url_con->additional_headers, s) | ||
472 | free(s); | ||
473 | #else | ||
474 | return; | ||
475 | url_con = NULL; | ||
476 | #endif | ||
477 | } | ||
478 | |||
479 | EAPI void * | ||
480 | ecore_con_url_data_get(Ecore_Con_Url *url_con) | ||
481 | { | ||
482 | #ifdef HAVE_CURL | ||
483 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
484 | { | ||
485 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_get"); | ||
486 | return NULL; | ||
487 | } | ||
488 | |||
489 | return url_con->data; | ||
490 | #else | ||
491 | return NULL; | ||
492 | url_con = NULL; | ||
493 | #endif | ||
494 | } | ||
495 | |||
496 | EAPI void | ||
497 | ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, double timestamp) | ||
498 | { | ||
499 | #ifdef HAVE_CURL | ||
500 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
501 | { | ||
502 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_time"); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | if (url_con->dead) return; | ||
507 | url_con->time_condition = condition; | ||
508 | url_con->timestamp = timestamp; | ||
509 | #else | ||
510 | return; | ||
511 | (void)url_con; | ||
512 | (void)condition; | ||
513 | (void)timestamp; | ||
514 | #endif | ||
515 | } | ||
516 | |||
517 | EAPI void | ||
518 | ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd) | ||
519 | { | ||
520 | #ifdef HAVE_CURL | ||
521 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
522 | { | ||
523 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_set"); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | if (url_con->dead) return; | ||
528 | url_con->write_fd = fd; | ||
529 | #else | ||
530 | return; | ||
531 | (void)url_con; | ||
532 | (void)fd; | ||
533 | #endif | ||
534 | } | ||
535 | |||
536 | EAPI int | ||
537 | ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con) | ||
538 | { | ||
539 | #ifdef HAVE_CURL | ||
540 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
541 | { | ||
542 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
543 | "ecore_con_url_received_bytes_get"); | ||
544 | return -1; | ||
545 | } | ||
546 | |||
547 | return url_con->received; | ||
548 | #else | ||
549 | return 0; | ||
550 | (void)url_con; | ||
551 | #endif | ||
552 | } | ||
553 | |||
554 | EAPI const Eina_List * | ||
555 | ecore_con_url_response_headers_get(Ecore_Con_Url *url_con) | ||
556 | { | ||
557 | #ifdef HAVE_CURL | ||
558 | return url_con->response_headers; | ||
559 | #else | ||
560 | return NULL; | ||
561 | (void)url_con; | ||
562 | #endif | ||
563 | } | ||
564 | |||
565 | EAPI Eina_Bool | ||
566 | ecore_con_url_httpauth_set(Ecore_Con_Url *url_con, const char *username, const char *password, Eina_Bool safe) | ||
567 | { | ||
568 | #ifdef HAVE_CURL | ||
569 | CURLcode ret; | ||
570 | |||
571 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
572 | { | ||
573 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
574 | "ecore_con_url_httpauth_set"); | ||
575 | return EINA_FALSE; | ||
576 | } | ||
577 | |||
578 | if (url_con->dead) return EINA_FALSE; | ||
579 | # if LIBCURL_VERSION_NUM >= 0x071301 | ||
580 | if ((username) && (password)) | ||
581 | { | ||
582 | if (safe) | ||
583 | curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH, | ||
584 | CURLAUTH_ANYSAFE); | ||
585 | else | ||
586 | curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH, CURLAUTH_ANY); | ||
587 | |||
588 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERNAME, username); | ||
589 | if (ret != CURLE_OK) | ||
590 | { | ||
591 | ERR("Could not set username for HTTP authentication: %s", | ||
592 | curl_easy_strerror(ret)); | ||
593 | return EINA_FALSE; | ||
594 | } | ||
595 | |||
596 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_PASSWORD, password); | ||
597 | if (ret != CURLE_OK) | ||
598 | { | ||
599 | ERR("Could not set password for HTTP authentication: %s", | ||
600 | curl_easy_strerror(ret)); | ||
601 | return EINA_FALSE; | ||
602 | } | ||
603 | |||
604 | return EINA_TRUE; | ||
605 | } | ||
606 | # endif | ||
607 | #else | ||
608 | return EINA_FALSE; | ||
609 | (void)url_con; | ||
610 | (void)username; | ||
611 | (void)password; | ||
612 | (void)safe; | ||
613 | #endif | ||
614 | |||
615 | return EINA_FALSE; | ||
616 | } | ||
617 | |||
618 | #define MODE_AUTO 0 | ||
619 | #define MODE_GET 1 | ||
620 | #define MODE_POST 2 | ||
621 | |||
622 | static Eina_Bool | ||
623 | _ecore_con_url_send(Ecore_Con_Url *url_con, int mode, const void *data, long length, const char *content_type) | ||
624 | { | ||
625 | #ifdef HAVE_CURL | ||
626 | Eina_List *l; | ||
627 | const char *s; | ||
628 | char tmp[512]; | ||
629 | |||
630 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
631 | { | ||
632 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_send"); | ||
633 | return EINA_FALSE; | ||
634 | } | ||
635 | |||
636 | if (!url_con->url) return EINA_FALSE; | ||
637 | if (url_con->dead) return EINA_FALSE; | ||
638 | |||
639 | /* Free response headers from previous send() calls */ | ||
640 | EINA_LIST_FREE(url_con->response_headers, s) | ||
641 | free((char *)s); | ||
642 | url_con->response_headers = NULL; | ||
643 | url_con->status = 0; | ||
644 | |||
645 | curl_slist_free_all(url_con->headers); | ||
646 | url_con->headers = NULL; | ||
647 | |||
648 | if ((mode == MODE_POST) || (mode == MODE_AUTO)) | ||
649 | { | ||
650 | if (url_con->post_data) free(url_con->post_data); | ||
651 | url_con->post_data = NULL; | ||
652 | if ((data) && (length > 0)) | ||
653 | { | ||
654 | url_con->post_data = malloc(length); | ||
655 | if (url_con->post_data) | ||
656 | { | ||
657 | memcpy(url_con->post_data, data, length); | ||
658 | if ((content_type) && (strlen(content_type) < 450)) | ||
659 | { | ||
660 | snprintf(tmp, sizeof(tmp), "Content-Type: %s", content_type); | ||
661 | url_con->headers = curl_slist_append(url_con->headers, tmp); | ||
662 | } | ||
663 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, url_con->post_data); | ||
664 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length); | ||
665 | } | ||
666 | else | ||
667 | return EINA_FALSE; | ||
668 | } | ||
669 | else curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, 0); | ||
670 | if (mode == MODE_POST) | ||
671 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POST, 1); | ||
672 | } | ||
673 | |||
674 | switch (url_con->time_condition) | ||
675 | { | ||
676 | case ECORE_CON_URL_TIME_NONE: | ||
677 | curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, | ||
678 | CURL_TIMECOND_NONE); | ||
679 | break; | ||
680 | |||
681 | case ECORE_CON_URL_TIME_IFMODSINCE: | ||
682 | curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, | ||
683 | CURL_TIMECOND_IFMODSINCE); | ||
684 | curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, | ||
685 | (long)url_con->timestamp); | ||
686 | break; | ||
687 | |||
688 | case ECORE_CON_URL_TIME_IFUNMODSINCE: | ||
689 | curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, | ||
690 | CURL_TIMECOND_IFUNMODSINCE); | ||
691 | curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, | ||
692 | (long)url_con->timestamp); | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | /* Additional headers */ | ||
697 | EINA_LIST_FOREACH(url_con->additional_headers, l, s) | ||
698 | url_con->headers = curl_slist_append(url_con->headers, s); | ||
699 | |||
700 | curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPHEADER, url_con->headers); | ||
701 | |||
702 | url_con->received = 0; | ||
703 | |||
704 | return _ecore_con_url_perform(url_con); | ||
705 | #else | ||
706 | return EINA_FALSE; | ||
707 | (void)url_con; | ||
708 | (void)mode; | ||
709 | (void)data; | ||
710 | (void)length; | ||
711 | (void)content_type; | ||
712 | #endif | ||
713 | } | ||
714 | |||
715 | EAPI Eina_Bool | ||
716 | ecore_con_url_get(Ecore_Con_Url *url_con) | ||
717 | { | ||
718 | return _ecore_con_url_send(url_con, MODE_GET, NULL, 0, NULL); | ||
719 | } | ||
720 | |||
721 | EAPI Eina_Bool | ||
722 | ecore_con_url_post(Ecore_Con_Url *url_con, const void *data, long length, const char *content_type) | ||
723 | { | ||
724 | return _ecore_con_url_send(url_con, MODE_POST, data, length, content_type); | ||
725 | } | ||
726 | |||
727 | EAPI Eina_Bool | ||
728 | ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, const char *filename, const char *user, const char *pass, const char *upload_dir) | ||
729 | { | ||
730 | #ifdef HAVE_CURL | ||
731 | char url[4096]; | ||
732 | char userpwd[4096]; | ||
733 | FILE *fd; | ||
734 | struct stat file_info; | ||
735 | CURLcode ret; | ||
736 | |||
737 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
738 | { | ||
739 | ECORE_MAGIC_FAIL(url_con, | ||
740 | ECORE_MAGIC_CON_URL, | ||
741 | "ecore_con_url_ftp_upload"); | ||
742 | return EINA_FALSE; | ||
743 | } | ||
744 | |||
745 | if (url_con->dead) return EINA_FALSE; | ||
746 | if (!url_con->url) return EINA_FALSE; | ||
747 | if ((!filename) || (!filename[0])) return EINA_FALSE; | ||
748 | |||
749 | if (stat(filename, &file_info)) | ||
750 | return EINA_FALSE; | ||
751 | |||
752 | snprintf(userpwd, sizeof(userpwd), "%s:%s", user, pass); | ||
753 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERPWD, userpwd); | ||
754 | if (ret != CURLE_OK) | ||
755 | { | ||
756 | ERR("Could not set username and password for FTP upload: %s", | ||
757 | curl_easy_strerror(ret)); | ||
758 | return EINA_FALSE; | ||
759 | } | ||
760 | |||
761 | char tmp[PATH_MAX]; | ||
762 | snprintf(tmp, PATH_MAX, "%s", filename); | ||
763 | |||
764 | if (upload_dir) | ||
765 | snprintf(url, sizeof(url), "ftp://%s/%s/%s", url_con->url, | ||
766 | upload_dir, basename(tmp)); | ||
767 | else | ||
768 | snprintf(url, sizeof(url), "ftp://%s/%s", url_con->url, | ||
769 | basename(tmp)); | ||
770 | |||
771 | if (!ecore_con_url_url_set(url_con, url)) | ||
772 | return EINA_FALSE; | ||
773 | |||
774 | curl_easy_setopt(url_con->curl_easy, CURLOPT_INFILESIZE_LARGE, | ||
775 | (curl_off_t)file_info.st_size); | ||
776 | curl_easy_setopt(url_con->curl_easy, CURLOPT_UPLOAD, 1); | ||
777 | curl_easy_setopt(url_con->curl_easy, CURLOPT_READFUNCTION, | ||
778 | _ecore_con_url_read_cb); | ||
779 | |||
780 | fd = fopen(filename, "rb"); | ||
781 | if (!fd) | ||
782 | { | ||
783 | ERR("Could not open \"%s\" for FTP upload", filename); | ||
784 | return EINA_FALSE; | ||
785 | } | ||
786 | curl_easy_setopt(url_con->curl_easy, CURLOPT_READDATA, fd); | ||
787 | |||
788 | return _ecore_con_url_perform(url_con); | ||
789 | #else | ||
790 | return EINA_FALSE; | ||
791 | (void)url_con; | ||
792 | (void)filename; | ||
793 | (void)user; | ||
794 | (void)pass; | ||
795 | (void)upload_dir; | ||
796 | #endif | ||
797 | } | ||
798 | |||
799 | EAPI void | ||
800 | ecore_con_url_cookies_init(Ecore_Con_Url *url_con) | ||
801 | { | ||
802 | #ifdef HAVE_CURL | ||
803 | if (!url_con) | ||
804 | return; | ||
805 | |||
806 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
807 | { | ||
808 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
809 | "ecore_con_url_cookies_init"); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | if (url_con->dead) return; | ||
814 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, ""); | ||
815 | #else | ||
816 | return; | ||
817 | (void)url_con; | ||
818 | #endif | ||
819 | } | ||
820 | |||
821 | EAPI void | ||
822 | ecore_con_url_cookies_ignore_old_session_set(Ecore_Con_Url *url_con, Eina_Bool ignore) | ||
823 | { | ||
824 | #ifdef HAVE_CURL | ||
825 | if (!url_con) | ||
826 | return; | ||
827 | |||
828 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
829 | { | ||
830 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
831 | "ecore_con_url_cookies_ignore_old_session_set"); | ||
832 | return; | ||
833 | } | ||
834 | |||
835 | if (url_con->dead) return; | ||
836 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIESESSION, ignore); | ||
837 | #else | ||
838 | return; | ||
839 | (void)url_con; | ||
840 | (void)ignore; | ||
841 | #endif | ||
842 | } | ||
843 | |||
844 | EAPI void | ||
845 | ecore_con_url_cookies_clear(Ecore_Con_Url *url_con) | ||
846 | { | ||
847 | #ifdef HAVE_CURL | ||
848 | if (!url_con) | ||
849 | return; | ||
850 | |||
851 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
852 | { | ||
853 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
854 | "ecore_con_url_cookies_clear"); | ||
855 | return; | ||
856 | } | ||
857 | |||
858 | if (url_con->dead) return; | ||
859 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "ALL"); | ||
860 | #else | ||
861 | return; | ||
862 | (void)url_con; | ||
863 | #endif | ||
864 | } | ||
865 | |||
866 | EAPI void | ||
867 | ecore_con_url_cookies_session_clear(Ecore_Con_Url *url_con) | ||
868 | { | ||
869 | #ifdef HAVE_CURL | ||
870 | if (!url_con) | ||
871 | return; | ||
872 | |||
873 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
874 | { | ||
875 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
876 | "ecore_con_url_cookies_session_clear"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | if (url_con->dead) return; | ||
881 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "SESS"); | ||
882 | #else | ||
883 | return; | ||
884 | (void)url_con; | ||
885 | #endif | ||
886 | } | ||
887 | |||
888 | EAPI void | ||
889 | ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char *const file_name) | ||
890 | { | ||
891 | #ifdef HAVE_CURL | ||
892 | if (!url_con) | ||
893 | return; | ||
894 | |||
895 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
896 | { | ||
897 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
898 | "ecore_con_url_cookies_file_add"); | ||
899 | return; | ||
900 | } | ||
901 | |||
902 | if (url_con->dead) return; | ||
903 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, file_name); | ||
904 | #else | ||
905 | return; | ||
906 | (void)url_con; | ||
907 | (void)file_name; | ||
908 | #endif | ||
909 | } | ||
910 | |||
911 | EAPI Eina_Bool | ||
912 | ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con, const char *const cookiejar_file) | ||
913 | { | ||
914 | #ifdef HAVE_CURL | ||
915 | CURLcode ret; | ||
916 | |||
917 | if (!url_con) | ||
918 | return EINA_FALSE; | ||
919 | |||
920 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
921 | { | ||
922 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
923 | "ecore_con_url_cookies_jar_file_set"); | ||
924 | return EINA_FALSE; | ||
925 | } | ||
926 | |||
927 | if (url_con->dead) return EINA_FALSE; | ||
928 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEJAR, | ||
929 | cookiejar_file); | ||
930 | if (ret != CURLE_OK) | ||
931 | { | ||
932 | ERR("Setting the cookie-jar name failed: %s", | ||
933 | curl_easy_strerror(ret)); | ||
934 | return EINA_FALSE; | ||
935 | } | ||
936 | |||
937 | return EINA_TRUE; | ||
938 | #else | ||
939 | return EINA_FALSE; | ||
940 | (void)url_con; | ||
941 | (void)cookiejar_file; | ||
942 | #endif | ||
943 | } | ||
944 | |||
945 | EAPI void | ||
946 | ecore_con_url_cookies_jar_write(Ecore_Con_Url *url_con) | ||
947 | { | ||
948 | #ifdef HAVE_CURL | ||
949 | if (!url_con) | ||
950 | return; | ||
951 | |||
952 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
953 | { | ||
954 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
955 | "ecore_con_url_cookies_jar_write"); | ||
956 | return; | ||
957 | } | ||
958 | |||
959 | if (url_con->dead) return; | ||
960 | curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "FLUSH"); | ||
961 | #else | ||
962 | return; | ||
963 | (void)url_con; | ||
964 | #endif | ||
965 | } | ||
966 | |||
967 | EAPI void | ||
968 | ecore_con_url_verbose_set(Ecore_Con_Url *url_con, Eina_Bool verbose) | ||
969 | { | ||
970 | #ifdef HAVE_CURL | ||
971 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
972 | { | ||
973 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
974 | "ecore_con_url_verbose_set"); | ||
975 | return; | ||
976 | } | ||
977 | |||
978 | if (!url_con->url) | ||
979 | return; | ||
980 | |||
981 | if (url_con->dead) return; | ||
982 | curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, (int)verbose); | ||
983 | #else | ||
984 | return; | ||
985 | (void)url_con; | ||
986 | (void)verbose; | ||
987 | #endif | ||
988 | } | ||
989 | |||
990 | EAPI void | ||
991 | ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, Eina_Bool use_epsv) | ||
992 | { | ||
993 | #ifdef HAVE_CURL | ||
994 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
995 | { | ||
996 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
997 | "ecore_con_url_ftp_use_epsv_set"); | ||
998 | return; | ||
999 | } | ||
1000 | |||
1001 | if (!url_con->url) | ||
1002 | return; | ||
1003 | |||
1004 | if (url_con->dead) return; | ||
1005 | curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, (int)use_epsv); | ||
1006 | #else | ||
1007 | return; | ||
1008 | (void)url_con; | ||
1009 | (void)use_epsv; | ||
1010 | #endif | ||
1011 | } | ||
1012 | |||
1013 | /** | ||
1014 | * Toggle libcurl's verify peer's certificate option. | ||
1015 | * | ||
1016 | * If @p verify is @c EINA_TRUE, libcurl will verify | ||
1017 | * the authenticity of the peer's certificate, otherwise | ||
1018 | * it will not. Default behavior of libcurl is to check | ||
1019 | * peer's certificate. | ||
1020 | * | ||
1021 | * @param url_con Ecore_Con_Url instance which will be acted upon. | ||
1022 | * @param verify Whether or not libcurl will check peer's certificate. | ||
1023 | * @since 1.1.0 | ||
1024 | */ | ||
1025 | EAPI void | ||
1026 | ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con, Eina_Bool verify) | ||
1027 | { | ||
1028 | #ifdef HAVE_CURL | ||
1029 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1030 | { | ||
1031 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, | ||
1032 | "ecore_con_url_ssl_verify_peer_set"); | ||
1033 | return; | ||
1034 | } | ||
1035 | |||
1036 | if (!url_con->url) | ||
1037 | return; | ||
1038 | |||
1039 | if (url_con->dead) return; | ||
1040 | curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, (int)verify); | ||
1041 | #else | ||
1042 | return; | ||
1043 | (void)url_con; | ||
1044 | (void)verify; | ||
1045 | #endif | ||
1046 | } | ||
1047 | |||
1048 | /** | ||
1049 | * Set a custom CA to trust for SSL/TLS connections. | ||
1050 | * | ||
1051 | * Specify the path of a file (in PEM format) containing one or more | ||
1052 | * CA certificate(s) to use for the validation of the server certificate. | ||
1053 | * | ||
1054 | * This function can also disable CA validation if @p ca_path is @c NULL. | ||
1055 | * However, the server certificate still needs to be valid for the connection | ||
1056 | * to succeed (i.e., the certificate must concern the server the | ||
1057 | * connection is made to). | ||
1058 | * | ||
1059 | * @param url_con Connection object that will use the custom CA. | ||
1060 | * @param ca_path Path to a CA certificate(s) file or @c NULL to disable | ||
1061 | * CA validation. | ||
1062 | * | ||
1063 | * @return @c 0 on success. When cURL is used, non-zero return values | ||
1064 | * are equal to cURL error codes. | ||
1065 | */ | ||
1066 | EAPI int | ||
1067 | ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path) | ||
1068 | { | ||
1069 | int res = -1; | ||
1070 | |||
1071 | #ifdef HAVE_CURL | ||
1072 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1073 | { | ||
1074 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ssl_ca_set"); | ||
1075 | return -1; | ||
1076 | } | ||
1077 | |||
1078 | if (!url_con->url) return -1; | ||
1079 | if (url_con->dead) return -1; | ||
1080 | if (ca_path == NULL) | ||
1081 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0); | ||
1082 | else | ||
1083 | { | ||
1084 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 1); | ||
1085 | if (!res) | ||
1086 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_CAINFO, ca_path); | ||
1087 | } | ||
1088 | #else | ||
1089 | return -1; | ||
1090 | (void)url_con; | ||
1091 | (void)ca_path; | ||
1092 | #endif | ||
1093 | |||
1094 | return res; | ||
1095 | } | ||
1096 | |||
1097 | EAPI Eina_Bool | ||
1098 | ecore_con_url_http_version_set(Ecore_Con_Url *url_con, Ecore_Con_Url_Http_Version version) | ||
1099 | { | ||
1100 | #ifdef HAVE_CURL | ||
1101 | int res = -1; | ||
1102 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1103 | { | ||
1104 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_http_version_set"); | ||
1105 | return EINA_FALSE; | ||
1106 | } | ||
1107 | if (url_con->dead) return EINA_FALSE; | ||
1108 | switch (version) | ||
1109 | { | ||
1110 | case ECORE_CON_URL_HTTP_VERSION_1_0: | ||
1111 | res = curl_easy_setopt(url_con->curl_easy, | ||
1112 | CURLOPT_HTTP_VERSION, | ||
1113 | CURL_HTTP_VERSION_1_0); | ||
1114 | break; | ||
1115 | |||
1116 | case ECORE_CON_URL_HTTP_VERSION_1_1: | ||
1117 | res = curl_easy_setopt(url_con->curl_easy, | ||
1118 | CURLOPT_HTTP_VERSION, | ||
1119 | CURL_HTTP_VERSION_1_1); | ||
1120 | break; | ||
1121 | |||
1122 | default: | ||
1123 | break; | ||
1124 | } | ||
1125 | if (res != CURLE_OK) | ||
1126 | { | ||
1127 | ERR("curl http version setting failed: %s", curl_easy_strerror(res)); | ||
1128 | return EINA_FALSE; | ||
1129 | } | ||
1130 | return EINA_TRUE; | ||
1131 | #else | ||
1132 | (void)url_con; | ||
1133 | (void)version; | ||
1134 | return EINA_FALSE; | ||
1135 | #endif | ||
1136 | } | ||
1137 | |||
1138 | EAPI Eina_Bool | ||
1139 | ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy) | ||
1140 | { | ||
1141 | #ifdef HAVE_CURL | ||
1142 | int res = -1; | ||
1143 | curl_version_info_data *vers = NULL; | ||
1144 | |||
1145 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1146 | { | ||
1147 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_set"); | ||
1148 | return EINA_FALSE; | ||
1149 | } | ||
1150 | |||
1151 | if (!url_con->url) return EINA_FALSE; | ||
1152 | if (url_con->dead) return EINA_FALSE; | ||
1153 | |||
1154 | if (!proxy) res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, ""); | ||
1155 | else | ||
1156 | { | ||
1157 | // before curl version 7.21.7, socks protocol:// prefix is not supported | ||
1158 | // (e.g. socks4://, socks4a://, socks5:// or socks5h://, etc.) | ||
1159 | vers = curl_version_info(CURLVERSION_NOW); | ||
1160 | if (vers->version_num < 0x71507) | ||
1161 | { | ||
1162 | url_con->proxy_type = CURLPROXY_HTTP; | ||
1163 | if (strstr(proxy, "socks4a")) | ||
1164 | url_con->proxy_type = CURLPROXY_SOCKS4A; | ||
1165 | else if (strstr(proxy, "socks4")) | ||
1166 | url_con->proxy_type = CURLPROXY_SOCKS4; | ||
1167 | else if (strstr(proxy, "socks5h")) | ||
1168 | url_con->proxy_type = CURLPROXY_SOCKS5_HOSTNAME; | ||
1169 | else if (strstr(proxy, "socks5")) | ||
1170 | url_con->proxy_type = CURLPROXY_SOCKS5; | ||
1171 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXYTYPE, | ||
1172 | url_con->proxy_type); | ||
1173 | if (res != CURLE_OK) | ||
1174 | { | ||
1175 | ERR("curl proxy type setting failed: %s", | ||
1176 | curl_easy_strerror(res)); | ||
1177 | url_con->proxy_type = -1; | ||
1178 | return EINA_FALSE; | ||
1179 | } | ||
1180 | } | ||
1181 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, proxy); | ||
1182 | } | ||
1183 | if (res != CURLE_OK) | ||
1184 | { | ||
1185 | ERR("curl proxy setting failed: %s", curl_easy_strerror(res)); | ||
1186 | url_con->proxy_type = -1; | ||
1187 | return EINA_FALSE; | ||
1188 | } | ||
1189 | return EINA_TRUE; | ||
1190 | #else | ||
1191 | return EINA_FALSE; | ||
1192 | (void)url_con; | ||
1193 | (void)proxy; | ||
1194 | #endif | ||
1195 | } | ||
1196 | |||
1197 | EAPI void | ||
1198 | ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout) | ||
1199 | { | ||
1200 | #ifdef HAVE_CURL | ||
1201 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1202 | { | ||
1203 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_timeout_set"); | ||
1204 | return; | ||
1205 | } | ||
1206 | |||
1207 | if (url_con->dead) return; | ||
1208 | if (!url_con->url || timeout < 0) return; | ||
1209 | if (url_con->timer) ecore_timer_del(url_con->timer); | ||
1210 | url_con->timer = ecore_timer_add(timeout, _ecore_con_url_timeout_cb, url_con); | ||
1211 | #else | ||
1212 | return; | ||
1213 | (void)url_con; | ||
1214 | (void)timeout; | ||
1215 | #endif | ||
1216 | } | ||
1217 | |||
1218 | EAPI Eina_Bool | ||
1219 | ecore_con_url_proxy_username_set(Ecore_Con_Url *url_con, const char *username) | ||
1220 | { | ||
1221 | #ifdef HAVE_CURL | ||
1222 | int res = -1; | ||
1223 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1224 | { | ||
1225 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_username_set"); | ||
1226 | return EINA_FALSE; | ||
1227 | } | ||
1228 | |||
1229 | if (url_con->dead) return EINA_FALSE; | ||
1230 | if (!url_con->url) return EINA_FALSE; | ||
1231 | if ((!username) || (!username[0])) return EINA_FALSE; | ||
1232 | if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) | ||
1233 | { | ||
1234 | ERR("Proxy type should be socks5 and above"); | ||
1235 | return EINA_FALSE; | ||
1236 | } | ||
1237 | |||
1238 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERNAME, username); | ||
1239 | if (res != CURLE_OK) | ||
1240 | { | ||
1241 | ERR("curl_easy_setopt() failed: %s", curl_easy_strerror(res)); | ||
1242 | return EINA_FALSE; | ||
1243 | } | ||
1244 | return EINA_TRUE; | ||
1245 | #else | ||
1246 | return EINA_FALSE; | ||
1247 | (void)url_con; | ||
1248 | (void)username; | ||
1249 | #endif | ||
1250 | } | ||
1251 | |||
1252 | EAPI Eina_Bool | ||
1253 | ecore_con_url_proxy_password_set(Ecore_Con_Url *url_con, const char *password) | ||
1254 | { | ||
1255 | #ifdef HAVE_CURL | ||
1256 | int res = -1; | ||
1257 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1258 | { | ||
1259 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_password_set"); | ||
1260 | return EINA_FALSE; | ||
1261 | } | ||
1262 | if (!url_con->url) return EINA_FALSE; | ||
1263 | if (url_con->dead) return EINA_FALSE; | ||
1264 | if (!password) return EINA_FALSE; | ||
1265 | if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) | ||
1266 | { | ||
1267 | ERR("Proxy type should be socks5 and above"); | ||
1268 | return EINA_FALSE; | ||
1269 | } | ||
1270 | |||
1271 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PASSWORD, password); | ||
1272 | if (res != CURLE_OK) | ||
1273 | { | ||
1274 | ERR("curl_easy_setopt() failed: %s", curl_easy_strerror(res)); | ||
1275 | return EINA_FALSE; | ||
1276 | } | ||
1277 | return EINA_TRUE; | ||
1278 | #else | ||
1279 | return EINA_FALSE; | ||
1280 | (void)url_con; | ||
1281 | (void)password; | ||
1282 | #endif | ||
1283 | } | ||
1284 | |||
1285 | /** | ||
1286 | * @} | ||
1287 | */ | ||
1288 | |||
1289 | #ifdef HAVE_CURL | ||
1290 | static void | ||
1291 | _ecore_con_url_status_get(Ecore_Con_Url *url_con) | ||
1292 | { | ||
1293 | long status = 0; | ||
1294 | |||
1295 | if (!url_con->curl_easy) return; | ||
1296 | if (!curl_easy_getinfo(url_con->curl_easy, CURLINFO_RESPONSE_CODE, &status)) | ||
1297 | url_con->status = status; | ||
1298 | else | ||
1299 | url_con->status = 0; | ||
1300 | } | ||
1301 | |||
1302 | static void | ||
1303 | _ecore_con_url_event_url_complete(Ecore_Con_Url *url_con, CURLMsg *curlmsg) | ||
1304 | { | ||
1305 | Ecore_Con_Event_Url_Complete *e; | ||
1306 | |||
1307 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); | ||
1308 | if (!e) return; | ||
1309 | |||
1310 | if (curlmsg && (curlmsg->data.result == CURLE_OK)) | ||
1311 | { | ||
1312 | if (!url_con->status) | ||
1313 | _ecore_con_url_status_get(url_con); | ||
1314 | } | ||
1315 | else if (curlmsg) | ||
1316 | ERR("Curl message have errors: %d", curlmsg->data.result); | ||
1317 | else | ||
1318 | CRIT("THIS IS BAD."); | ||
1319 | |||
1320 | e->status = url_con->status; | ||
1321 | e->url_con = url_con; | ||
1322 | url_con->event_count++; | ||
1323 | ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con); | ||
1324 | } | ||
1325 | |||
1326 | static void | ||
1327 | _ecore_con_url_multi_remove(Ecore_Con_Url *url_con) | ||
1328 | { | ||
1329 | CURLMcode ret; | ||
1330 | |||
1331 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); | ||
1332 | url_con->multi = EINA_FALSE; | ||
1333 | if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret)); | ||
1334 | } | ||
1335 | |||
1336 | static Eina_Bool | ||
1337 | _ecore_con_url_timeout_cb(void *data) | ||
1338 | { | ||
1339 | Ecore_Con_Url *url_con = data; | ||
1340 | |||
1341 | if (!url_con) return ECORE_CALLBACK_CANCEL; | ||
1342 | if (!url_con->curl_easy) return ECORE_CALLBACK_CANCEL; | ||
1343 | |||
1344 | _ecore_con_url_multi_remove(url_con); | ||
1345 | _url_con_list = eina_list_remove(_url_con_list, url_con); | ||
1346 | |||
1347 | curl_slist_free_all(url_con->headers); | ||
1348 | url_con->headers = NULL; | ||
1349 | |||
1350 | url_con->timer = NULL; | ||
1351 | |||
1352 | _ecore_con_url_event_url_complete(url_con, NULL); | ||
1353 | return ECORE_CALLBACK_CANCEL; | ||
1354 | } | ||
1355 | |||
1356 | static size_t | ||
1357 | _ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp) | ||
1358 | { | ||
1359 | Ecore_Con_Url *url_con; | ||
1360 | Ecore_Con_Event_Url_Data *e; | ||
1361 | size_t real_size = size * nitems; | ||
1362 | |||
1363 | url_con = (Ecore_Con_Url *)userp; | ||
1364 | |||
1365 | if (!url_con) | ||
1366 | return -1; | ||
1367 | |||
1368 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1369 | { | ||
1370 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_cb"); | ||
1371 | return -1; | ||
1372 | } | ||
1373 | |||
1374 | url_con->received += real_size; | ||
1375 | |||
1376 | INF("reading from %s", url_con->url); | ||
1377 | if (url_con->write_fd < 0) | ||
1378 | { | ||
1379 | e = | ||
1380 | malloc(sizeof(Ecore_Con_Event_Url_Data) + sizeof(unsigned char) * | ||
1381 | (real_size - 1)); | ||
1382 | if (e) | ||
1383 | { | ||
1384 | e->url_con = url_con; | ||
1385 | e->size = real_size; | ||
1386 | memcpy(e->data, buffer, real_size); | ||
1387 | url_con->event_count++; | ||
1388 | ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con); | ||
1389 | } | ||
1390 | } | ||
1391 | else | ||
1392 | { | ||
1393 | ssize_t count = 0; | ||
1394 | size_t total_size = real_size; | ||
1395 | size_t offset = 0; | ||
1396 | |||
1397 | while (total_size > 0) | ||
1398 | { | ||
1399 | count = write(url_con->write_fd, | ||
1400 | (char *)buffer + offset, | ||
1401 | total_size); | ||
1402 | if (count < 0) | ||
1403 | { | ||
1404 | if (errno != EAGAIN && errno != EINTR) | ||
1405 | return -1; | ||
1406 | } | ||
1407 | else | ||
1408 | { | ||
1409 | total_size -= count; | ||
1410 | offset += count; | ||
1411 | } | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | return real_size; | ||
1416 | } | ||
1417 | |||
1418 | static size_t | ||
1419 | _ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream) | ||
1420 | { | ||
1421 | size_t real_size = size * nitems; | ||
1422 | Ecore_Con_Url *url_con = stream; | ||
1423 | |||
1424 | char *header = malloc(sizeof(char) * (real_size + 1)); | ||
1425 | if (!header) | ||
1426 | return real_size; | ||
1427 | |||
1428 | memcpy(header, ptr, real_size); | ||
1429 | header[real_size] = '\0'; | ||
1430 | |||
1431 | url_con->response_headers = eina_list_append(url_con->response_headers, | ||
1432 | header); | ||
1433 | |||
1434 | return real_size; | ||
1435 | } | ||
1436 | |||
1437 | static int | ||
1438 | _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) | ||
1439 | { | ||
1440 | Ecore_Con_Event_Url_Progress *e; | ||
1441 | Ecore_Con_Url *url_con; | ||
1442 | |||
1443 | url_con = clientp; | ||
1444 | |||
1445 | e = malloc(sizeof(Ecore_Con_Event_Url_Progress)); | ||
1446 | if (e) | ||
1447 | { | ||
1448 | e->url_con = url_con; | ||
1449 | e->down.total = dltotal; | ||
1450 | e->down.now = dlnow; | ||
1451 | e->up.total = ultotal; | ||
1452 | e->up.now = ulnow; | ||
1453 | url_con->event_count++; | ||
1454 | ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con); | ||
1455 | } | ||
1456 | |||
1457 | return 0; | ||
1458 | } | ||
1459 | |||
1460 | static size_t | ||
1461 | _ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream) | ||
1462 | { | ||
1463 | size_t retcode = fread(ptr, size, nitems, stream); | ||
1464 | |||
1465 | if (ferror((FILE *)stream)) | ||
1466 | { | ||
1467 | fclose(stream); | ||
1468 | return CURL_READFUNC_ABORT; | ||
1469 | } | ||
1470 | else if (retcode == 0) | ||
1471 | { | ||
1472 | fclose((FILE *)stream); | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | #ifdef _WIN32 | ||
1477 | INF("*** We read %Iu bytes from file", retcode); | ||
1478 | #else | ||
1479 | INF("*** We read %zu bytes from file", retcode); | ||
1480 | #endif | ||
1481 | return retcode; | ||
1482 | } | ||
1483 | |||
1484 | static void | ||
1485 | _ecore_con_url_info_read(void) | ||
1486 | { | ||
1487 | CURLMsg *curlmsg; | ||
1488 | int n_remaining; | ||
1489 | |||
1490 | while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining))) | ||
1491 | { | ||
1492 | Eina_List *l, *ll; | ||
1493 | Ecore_Con_Url *url_con = NULL; | ||
1494 | DBG("Curl message: %d", curlmsg->msg); | ||
1495 | |||
1496 | if (curlmsg->msg == CURLMSG_DONE) | ||
1497 | { | ||
1498 | EINA_LIST_FOREACH_SAFE(_url_con_list, l, ll, url_con) | ||
1499 | { | ||
1500 | if (curlmsg->easy_handle == url_con->curl_easy) | ||
1501 | _ecore_con_url_event_url_complete(url_con, curlmsg); | ||
1502 | } | ||
1503 | } | ||
1504 | } | ||
1505 | } | ||
1506 | |||
1507 | static void | ||
1508 | _ecore_con_url_curl_clear(void) | ||
1509 | { | ||
1510 | Ecore_Fd_Handler *fdh; | ||
1511 | Ecore_Con_Url *url_con; | ||
1512 | |||
1513 | EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh); | ||
1514 | EINA_LIST_FREE(_url_con_list, url_con) _ecore_con_url_multi_remove(url_con); | ||
1515 | } | ||
1516 | |||
1517 | static Eina_Bool | ||
1518 | _ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) | ||
1519 | { | ||
1520 | Ecore_Fd_Handler *fdh; | ||
1521 | EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh); | ||
1522 | ecore_timer_interval_set(_curl_timer, 0.1); | ||
1523 | return ECORE_CALLBACK_CANCEL; | ||
1524 | } | ||
1525 | |||
1526 | static void | ||
1527 | _ecore_con_url_fdset(void) | ||
1528 | { | ||
1529 | CURLMcode ret; | ||
1530 | fd_set read_set, write_set, exc_set; | ||
1531 | int fd, fd_max; | ||
1532 | |||
1533 | FD_ZERO(&read_set); | ||
1534 | FD_ZERO(&write_set); | ||
1535 | FD_ZERO(&exc_set); | ||
1536 | |||
1537 | ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set, &fd_max); | ||
1538 | if (ret != CURLM_OK) | ||
1539 | { | ||
1540 | ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret)); | ||
1541 | return; | ||
1542 | } | ||
1543 | |||
1544 | for (fd = 0; fd <= fd_max; fd++) | ||
1545 | { | ||
1546 | int flags = 0; | ||
1547 | if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; | ||
1548 | if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; | ||
1549 | if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; | ||
1550 | if (flags) | ||
1551 | { | ||
1552 | // FIXME: Who is owner (easy_handle) of this fd?? (Curl do not give this info.) | ||
1553 | // This cause "Failed to delete epoll fd xx!" error messages | ||
1554 | Ecore_Fd_Handler *fd_handler; | ||
1555 | fd_handler = ecore_main_fd_handler_add(fd, flags, | ||
1556 | _ecore_con_url_fd_handler, | ||
1557 | NULL, NULL, NULL); | ||
1558 | if (fd_handler) | ||
1559 | _fd_hd_list = eina_list_append(_fd_hd_list, fd_handler); | ||
1560 | } | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | static Eina_Bool | ||
1565 | _ecore_con_url_timer(void *data __UNUSED__) | ||
1566 | { | ||
1567 | Ecore_Fd_Handler *fdh; | ||
1568 | int still_running; | ||
1569 | CURLMcode ret; | ||
1570 | |||
1571 | EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh); | ||
1572 | _ecore_con_url_info_read(); | ||
1573 | |||
1574 | ret = curl_multi_perform(_curlm, &still_running); | ||
1575 | if (ret == CURLM_CALL_MULTI_PERFORM) | ||
1576 | { | ||
1577 | DBG("curl_multi_perform() again immediately"); | ||
1578 | return ECORE_CALLBACK_RENEW; | ||
1579 | } | ||
1580 | else if (ret != CURLM_OK) | ||
1581 | { | ||
1582 | ERR("curl_multi_perform() failed: %s", curl_multi_strerror(ret)); | ||
1583 | _ecore_con_url_curl_clear(); | ||
1584 | ecore_timer_freeze(_curl_timer); | ||
1585 | } | ||
1586 | |||
1587 | if (still_running) | ||
1588 | { | ||
1589 | long ms; | ||
1590 | _ecore_con_url_fdset(); | ||
1591 | curl_multi_timeout(_curlm, &ms); | ||
1592 | DBG("multiperform is still running: %d, timeout: %ld", still_running, ms); | ||
1593 | if (ms >= CURL_MIN_TIMEOUT || ms <= 0) ms = CURL_MIN_TIMEOUT; | ||
1594 | ecore_timer_interval_set(_curl_timer, (double)ms / 1000); | ||
1595 | } | ||
1596 | else | ||
1597 | { | ||
1598 | DBG("multiperform ended"); | ||
1599 | _ecore_con_url_info_read(); | ||
1600 | _ecore_con_url_curl_clear(); | ||
1601 | ecore_timer_freeze(_curl_timer); | ||
1602 | } | ||
1603 | |||
1604 | return ECORE_CALLBACK_RENEW; | ||
1605 | } | ||
1606 | |||
1607 | static Eina_Bool | ||
1608 | _ecore_con_url_perform(Ecore_Con_Url *url_con) | ||
1609 | { | ||
1610 | CURLMcode ret; | ||
1611 | |||
1612 | ret = curl_multi_add_handle(_curlm, url_con->curl_easy); | ||
1613 | if (ret != CURLM_OK) | ||
1614 | { | ||
1615 | ERR("curl_multi_add_handle() failed: %s", curl_multi_strerror(ret)); | ||
1616 | return EINA_FALSE; | ||
1617 | } | ||
1618 | |||
1619 | url_con->multi = EINA_TRUE; | ||
1620 | _url_con_list = eina_list_append(_url_con_list, url_con); | ||
1621 | ecore_timer_thaw(_curl_timer); | ||
1622 | |||
1623 | return EINA_TRUE; | ||
1624 | } | ||
1625 | |||
1626 | static void | ||
1627 | _ecore_con_event_url_free(Ecore_Con_Url *url_con, void *ev) | ||
1628 | { | ||
1629 | free(ev); | ||
1630 | url_con->event_count--; | ||
1631 | if (url_con->dead && (!url_con->event_count)) | ||
1632 | ecore_con_url_free(url_con); | ||
1633 | } | ||
1634 | |||
1635 | #endif | ||