Fixed: CURLOPT_DNS_SERVERS in connection to Curl.duphandle in curl-helper.c
[ocurl.git] / curl-helper.c
blobb86d7f5428d367551c5e3755ef80eae93d6ab2e8
1 /***
2 *** curl-helper.c
3 ***
4 *** Copyright (c) 2003-2008, Lars Nilsson, <lars@quantumchamaeleon.com>
5 *** Copyright (c) 2009, ygrek, <ygrek@autistici.org>
6 ***/
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 /* suppress false gcc warning on seekFunction */
14 #define CURL_DISABLE_TYPECHECK
15 #include <curl/curl.h>
17 #include <caml/alloc.h>
18 #include <caml/memory.h>
19 #include <caml/mlvalues.h>
20 #include <caml/callback.h>
21 #include <caml/fail.h>
22 #include <caml/unixsupport.h>
23 #include <caml/custom.h>
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #else
28 #pragma message("No config file given.")
29 #endif
31 void leave_blocking_section(void);
32 void enter_blocking_section(void);
34 #define Val_none Val_int(0)
36 static __inline value
37 Val_some( value v )
39 CAMLparam1( v );
40 CAMLlocal1( some );
41 some = caml_alloc(1, 0);
42 Store_field( some, 0, v );
43 CAMLreturn( some );
46 static value Val_pair(value v1, value v2)
48 CAMLparam2(v1,v2);
49 CAMLlocal1(pair);
50 pair = caml_alloc_small(2,0);
51 Field(pair,0) = v1;
52 Field(pair,1) = v2;
53 CAMLreturn(pair);
56 static value Val_cons(value list, value v) { return Val_pair(v,list); }
58 typedef struct Connection Connection;
59 typedef struct ConnectionList ConnectionList;
61 #define Connection_val(v) (*(Connection**)Data_custom_val(v))
63 enum OcamlValues
65 OcamlWriteCallback,
66 OcamlReadCallback,
67 OcamlErrorBuffer,
68 OcamlPostFields,
69 OcamlHTTPHeader,
70 OcamlHTTPPost,
71 OcamlQuote,
72 OcamlPostQuote,
73 OcamlHeaderCallback,
74 OcamlProgressCallback,
75 OcamlDebugCallback,
76 OcamlHTTP200Aliases,
77 OcamlIOCTLCallback,
78 OcamlSeekFunctionCallback,
79 OcamlOpenSocketFunctionCallback,
81 OcamlURL,
82 OcamlProxy,
83 OcamlUserPWD,
84 OcamlProxyUserPWD,
85 OcamlRange,
86 OcamlReferer,
87 OcamlUserAgent,
88 OcamlFTPPort,
89 OcamlCookie,
90 OcamlHTTPPostStrings,
91 OcamlSSLCert,
92 OcamlSSLCertType,
93 OcamlSSLCertPasswd,
94 OcamlSSLKey,
95 OcamlSSLKeyType,
96 OcamlSSLKeyPasswd,
97 OcamlSSLEngine,
98 OcamlCookieFile,
99 OcamlCustomRequest,
100 OcamlInterface,
101 OcamlCAInfo,
102 OcamlCAPath,
103 OcamlRandomFile,
104 OcamlEGDSocket,
105 OcamlCookieJar,
106 OcamlSSLCipherList,
107 OcamlPrivate,
108 OcamlNETRCFile,
109 OcamlFTPAccount,
110 OcamlCookieList,
111 OcamlFTPAlternativeToUser,
112 OcamlSSHPublicKeyFile,
113 OcamlSSHPrivateKeyFile,
114 OcamlSSHHostPublicKeyMD5,
115 OcamlCopyPostFields,
117 OcamlDNSServers,
119 /* Not used, last for size */
120 OcamlValuesSize
123 struct Connection
125 CURL *connection;
126 Connection *next;
127 Connection *prev;
129 value ocamlValues;
131 size_t refcount; /* number of references to this structure */
133 char *url;
134 char *proxy;
135 char *userPwd;
136 char *proxyUserPwd;
137 char *range;
138 char *errorBuffer;
139 char *postFields;
140 int postFieldSize;
141 char *referer;
142 char *userAgent;
143 char *ftpPort;
144 char *cookie;
145 struct curl_slist *httpHeader;
146 struct curl_httppost *httpPostFirst;
147 struct curl_httppost *httpPostLast;
148 struct curl_slist *httpPostStrings;
149 struct curl_slist *resolve;
150 char *sslCert;
151 char *sslCertType;
152 char *sslCertPasswd;
153 char *sslKey;
154 char *sslKeyType;
155 char *sslKeyPasswd;
156 char *sslEngine;
157 struct curl_slist *quote;
158 struct curl_slist *postQuote;
159 char *cookieFile;
160 char *customRequest;
161 char *interface_; /* `interface` gives problems on windows */
162 char *caInfo;
163 char *caPath;
164 char *randomFile;
165 char *egdSocket;
166 char *cookieJar;
167 char *sslCipherList;
168 char *private;
169 struct curl_slist *http200Aliases;
170 char *netrcFile;
171 char *ftpaccount;
172 char *cookielist;
173 char *ftpAlternativeToUser;
174 char *sshPublicKeyFile;
175 char *sshPrivateKeyFile;
176 char *sshHostPublicKeyMD5;
177 char *copyPostFields;
178 char *dns_servers;
181 struct ConnectionList
183 Connection *head;
184 Connection *tail;
187 static ConnectionList connectionList = {NULL, NULL};
189 typedef struct CURLErrorMapping CURLErrorMapping;
191 struct CURLErrorMapping
193 char *name;
194 CURLcode error;
197 CURLErrorMapping errorMap[] =
199 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
200 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
201 #else
202 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
203 #endif
204 #if HAVE_DECL_CURLE_FAILED_INIT
205 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
206 #else
207 {"CURLE_FAILED_INIT", -1},
208 #endif
209 #if HAVE_DECL_CURLE_URL_MALFORMAT
210 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
211 #else
212 {"CURLE_URL_MALFORMAT", -1},
213 #endif
214 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
215 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
216 #else
217 {"CURLE_URL_MALFORMAT_USER", -1},
218 #endif
219 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
220 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
221 #else
222 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
223 #endif
224 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
225 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
226 #else
227 {"CURLE_COULDNT_RESOLVE_HOST", -1},
228 #endif
229 #if HAVE_DECL_CURLE_COULDNT_CONNECT
230 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
231 #else
232 {"CURLE_COULDNT_CONNECT", -1},
233 #endif
234 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
235 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
236 #else
237 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
238 #endif
239 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
240 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
241 #else
242 {"CURLE_FTP_ACCESS_DENIED", -1},
243 #endif
244 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
245 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
246 #else
247 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
248 #endif
249 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
250 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
251 #else
252 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
253 #endif
254 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
255 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
256 #else
257 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
258 #endif
259 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
260 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
261 #else
262 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
263 #endif
264 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
265 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
266 #else
267 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
268 #endif
269 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
270 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
271 #else
272 {"CURLE_FTP_CANT_GET_HOST", -1},
273 #endif
274 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
275 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
276 #else
277 {"CURLE_FTP_CANT_RECONNECT", -1},
278 #endif
279 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
280 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
281 #else
282 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
283 #endif
284 #if HAVE_DECL_CURLE_PARTIAL_FILE
285 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
286 #else
287 {"CURLE_PARTIAL_FILE", -1},
288 #endif
289 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
290 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
291 #else
292 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
293 #endif
294 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
295 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
296 #else
297 {"CURLE_FTP_WRITE_ERROR", -1},
298 #endif
299 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
300 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
301 #else
302 {"CURLE_FTP_QUOTE_ERROR", -1},
303 #endif
304 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
305 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
306 #else
307 {"CURLE_HTTP_NOT_FOUND", -1},
308 #endif
309 #if HAVE_DECL_CURLE_WRITE_ERROR
310 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
311 #else
312 {"CURLE_WRITE_ERROR", -1},
313 #endif
314 #if HAVE_DECL_CURLE_MALFORMAT_USER
315 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
316 #else
317 {"CURLE_MALFORMAT_USER", -1},
318 #endif
319 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
320 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
321 #else
322 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
323 #endif
324 #if HAVE_DECL_CURLE_READ_ERROR
325 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
326 #else
327 {"CURLE_READ_ERROR", -1},
328 #endif
329 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
330 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
331 #else
332 {"CURLE_OUT_OF_MEMORY", -1},
333 #endif
334 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
335 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
336 #else
337 {"CURLE_OPERATION_TIMEOUTED", -1},
338 #endif
339 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
340 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
341 #else
342 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
343 #endif
344 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
345 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
346 #else
347 {"CURLE_FTP_PORT_FAILED", -1},
348 #endif
349 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
350 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
351 #else
352 {"CURLE_FTP_COULDNT_USE_REST", -1},
353 #endif
354 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
355 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
356 #else
357 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
358 #endif
359 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
360 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
361 #else
362 {"CURLE_HTTP_RANGE_ERROR", -1},
363 #endif
364 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
365 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
366 #else
367 {"CURLE_HTTP_POST_ERROR", -1},
368 #endif
369 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
370 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
371 #else
372 {"CURLE_SSL_CONNECT_ERROR", -1},
373 #endif
374 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
375 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
376 #else
377 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
378 #endif
379 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
380 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
381 #else
382 {"CURLE_FILE_COULDNT_READ_FILE", -1},
383 #endif
384 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
385 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
386 #else
387 {"CURLE_LDAP_CANNOT_BIND", -1},
388 #endif
389 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
390 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
391 #else
392 {"CURLE_LDAP_SEARCH_FAILED", -1},
393 #endif
394 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
395 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
396 #else
397 {"CURLE_LIBRARY_NOT_FOUND", -1},
398 #endif
399 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
400 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
401 #else
402 {"CURLE_FUNCTION_NOT_FOUND", -1},
403 #endif
404 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
405 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
406 #else
407 {"CURLE_ABORTED_BY_CALLBACK", -1},
408 #endif
409 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
410 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
411 #else
412 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
413 #endif
414 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
415 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
416 #else
417 {"CURLE_BAD_CALLING_ORDER", -1},
418 #endif
419 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
420 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
421 #else
422 {"CURLE_HTTP_PORT_FAILED", -1},
423 #endif
424 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
425 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
426 #else
427 {"CURLE_BAD_PASSWORD_ENTERED", -1},
428 #endif
429 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
430 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
431 #else
432 {"CURLE_TOO_MANY_REDIRECTS", -1},
433 #endif
434 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
435 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
436 #else
437 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
438 #endif
439 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
440 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
441 #else
442 {"CURLE_TELNET_OPTION_SYNTAX", -1},
443 #endif
444 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
445 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
446 #else
447 {"CURLE_SSL_PEER_CERTIFICATE", -1},
448 #endif
449 #if HAVE_DECL_CURLE_GOT_NOTHING
450 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
451 #else
452 {"CURLE_GOT_NOTHING", -1},
453 #endif
454 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
455 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
456 #else
457 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
458 #endif
459 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
460 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
461 #else
462 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
463 #endif
464 #if HAVE_DECL_CURLE_SEND_ERROR
465 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
466 #else
467 {"CURLE_SEND_ERROR", -1},
468 #endif
469 #if HAVE_DECL_CURLE_RECV_ERROR
470 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
471 #else
472 {"CURLE_RECV_ERROR", -1},
473 #endif
474 #if HAVE_DECL_CURLE_SHARE_IN_USE
475 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
476 #else
477 {"CURLE_SHARE_IN_USE", -1},
478 #endif
479 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
480 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
481 #else
482 {"CURLE_SSL_CERTPROBLEN", -1},
483 #endif
484 #if HAVE_DECL_CURLE_SSL_CIPHER
485 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
486 #else
487 {"CURLE_SSL_CIPHER", -1},
488 #endif
489 #if HAVE_DECL_CURLE_SSL_CACERT
490 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
491 #else
492 {"CURLE_SSL_CACERT", -1},
493 #endif
494 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
495 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
496 #else
497 {"CURLE_BAD_CONTENT_ENCODING", -1},
498 #endif
499 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
500 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
501 #else
502 {"CURLE_LDAP_INVALID_URL", -1},
503 #endif
504 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
505 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
506 #else
507 {"CURLE_FILESIZE_EXCEEDED", -1},
508 #endif
509 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
510 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
511 #else
512 {"CURLE_FTP_SSL_FAILED", -1},
513 #endif
514 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
515 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
516 #else
517 {"CURLE_SEND_FAIL_REWIND", -1},
518 #endif
519 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
520 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
521 #else
522 {"CURLE_SSL_ENGINE_INITFAILED", -1},
523 #endif
524 #if HAVE_DECL_CURLE_LOGIN_DENIED
525 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
526 #else
527 {"CURLE_LOGIN_DENIED", -1},
528 #endif
529 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
530 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
531 #else
532 {"CURLE_TFTP_NOTFOUND", -1},
533 #endif
534 #if HAVE_DECL_CURLE_TFTP_PERM
535 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
536 #else
537 {"CURLE_TFTP_PERM", -1},
538 #endif
539 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
540 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
541 #else
542 {"CURLE_REMOTE_DISK_FULL", -1},
543 #endif
544 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
545 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
546 #else
547 {"CURLE_TFTP_ILLEGAL", -1},
548 #endif
549 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
550 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
551 #else
552 {"CURLE_TFTP_UNKNOWNID", -1},
553 #endif
554 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
555 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
556 #else
557 {"CURLE_REMOTE_FILE_EXISTS", -1},
558 #endif
559 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
560 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
561 #else
562 {"CURLE_TFTP_NOSUCHUSER", -1},
563 #endif
564 #if HAVE_DECL_CURLE_CONV_FAILED
565 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
566 #else
567 {"CURLE_CONV_FAILED", -1},
568 #endif
569 #if HAVE_DECL_CURLE_CONV_REQUIRED
570 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
571 #else
572 {"CURLE_CONV_REQUIRED", -1},
573 #endif
574 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
575 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
576 #else
577 {"CURLE_SSL_CACERT_BADFILE", -1},
578 #endif
579 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
580 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
581 #else
582 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
583 #endif
584 #if HAVE_DECL_CURLE_SSH
585 {"CURLE_SSH", CURLE_SSH},
586 #else
587 {"CURLE_SSH", -1},
588 #endif
589 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
590 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
591 #else
592 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
593 #endif
594 #if HAVE_DECL_CURLE_AGAIN
595 {"CURLE_AGAIN", CURLE_AGAIN},
596 #else
597 {"CURLE_AGAIN", -1},
598 #endif
599 {"CURLE_OK", CURLE_OK},
600 {NULL, 0}
603 typedef struct CURLOptionMapping CURLOptionMapping;
605 struct CURLOptionMapping
607 void (*optionHandler)(Connection *, value);
608 char *name;
609 CURLoption option;
612 CURLOptionMapping unimplementedOptionMap[] =
614 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
615 {NULL, NULL, 0}
618 static void handleWriteFunction(Connection *, value);
619 static void handleReadFunction(Connection *, value);
620 static void handleInFileSize(Connection *, value);
621 static void handleURL(Connection *, value);
622 static void handleProxy(Connection *, value);
623 static void handleProxyPort(Connection *, value);
624 static void handleHTTPProxyTunnel(Connection *, value);
625 static void handleVerbose(Connection *, value);
626 static void handleHeader(Connection *, value);
627 static void handleNoProgress(Connection *, value);
628 static void handleNoSignal(Connection *, value);
629 static void handleNoBody(Connection *, value);
630 static void handleFailOnError(Connection *, value);
631 static void handleUpload(Connection *, value);
632 static void handlePost(Connection *, value);
633 static void handleFTPListOnly(Connection *, value);
634 static void handleFTPAppend(Connection *, value);
635 static void handleNETRC(Connection *, value);
636 static void handleEncoding(Connection *, value);
637 static void handleFollowLocation(Connection *, value);
638 static void handleTransferText(Connection *, value);
639 static void handlePut(Connection *, value);
640 static void handleUserPwd(Connection *, value);
641 static void handleProxyUserPwd(Connection *, value);
642 static void handleRange(Connection *, value);
643 static void handleErrorBuffer(Connection *, value);
644 static void handleTimeout(Connection *, value);
645 static void handlePostFields(Connection *, value);
646 static void handlePostFieldSize(Connection *, value);
647 static void handleReferer(Connection *, value);
648 static void handleUserAgent(Connection *, value);
649 static void handleFTPPort(Connection *, value);
650 static void handleLowSpeedLimit(Connection *, value);
651 static void handleLowSpeedTime(Connection *, value);
652 static void handleResumeFrom(Connection *, value);
653 static void handleCookie(Connection *, value);
654 static void handleHTTPHeader(Connection *, value);
655 static void handleHTTPPost(Connection *, value);
656 static void handleSSLCert(Connection *, value);
657 static void handleSSLCertType(Connection *, value);
658 static void handleSSLCertPasswd(Connection *, value);
659 static void handleSSLKey(Connection *, value);
660 static void handleSSLKeyType(Connection *, value);
661 static void handleSSLKeyPasswd(Connection *, value);
662 static void handleSSLEngine(Connection *, value);
663 static void handleSSLEngineDefault(Connection *, value);
664 static void handleCRLF(Connection *, value);
665 static void handleQuote(Connection *, value);
666 static void handlePostQuote(Connection *, value);
667 static void handleHeaderFunction(Connection *, value);
668 static void handleCookieFile(Connection *, value);
669 static void handleSSLVersion(Connection *, value);
670 static void handleTimeCondition(Connection *, value);
671 static void handleTimeValue(Connection *, value);
672 static void handleCustomRequest(Connection *, value);
673 static void handleInterface(Connection *, value);
674 static void handleKRB4Level(Connection *, value);
675 static void handleProgressFunction(Connection *, value);
676 static void handleSSLVerifyPeer(Connection *, value);
677 static void handleCAInfo(Connection *, value);
678 static void handleCAPath(Connection *, value);
679 static void handleFileTime(Connection *, value);
680 static void handleMaxRedirs(Connection *, value);
681 static void handleMaxConnects(Connection *, value);
682 static void handleClosePolicy(Connection *, value);
683 static void handleFreshConnect(Connection *, value);
684 static void handleForbidReuse(Connection *, value);
685 static void handleRandomFile(Connection *, value);
686 static void handleEGDSocket(Connection *, value);
687 static void handleConnectTimeout(Connection *, value);
688 static void handleHTTPGet(Connection *, value);
689 static void handleSSLVerifyHost(Connection *, value);
690 static void handleCookieJar(Connection *, value);
691 static void handleSSLCipherList(Connection *, value);
692 static void handleHTTPVersion(Connection *, value);
693 static void handleFTPUseEPSV(Connection *, value);
694 static void handleDNSCacheTimeout(Connection *, value);
695 static void handleDNSUseGlobalCache(Connection *, value);
696 static void handleDebugFunction(Connection *, value);
697 static void handlePrivate(Connection *, value);
698 static void handleHTTP200Aliases(Connection *, value);
699 static void handleUnrestrictedAuth(Connection *, value);
700 static void handleFTPUseEPRT(Connection *, value);
701 static void handleHTTPAuth(Connection *, value);
702 static void handleFTPCreateMissingDirs(Connection *, value);
703 static void handleProxyAuth(Connection *, value);
704 static void handleFTPResponseTimeout(Connection *, value);
705 static void handleIPResolve(Connection *, value);
706 static void handleMaxFileSize(Connection *, value);
707 static void handleInFileSizeLarge(Connection *, value);
708 static void handleResumeFromLarge(Connection *, value);
709 static void handleMaxFileSizeLarge(Connection *, value);
710 static void handleNETRCFile(Connection *, value);
711 static void handleFTPSSL(Connection *, value);
712 static void handlePostFieldSizeLarge(Connection *, value);
713 static void handleTCPNoDelay(Connection *, value);
714 static void handleFTPSSLAuth(Connection *, value);
715 static void handleIOCTLFunction(Connection *, value);
716 static void handleFTPAccount(Connection *, value);
717 static void handleCookieList(Connection *, value);
718 static void handleIgnoreContentLength(Connection *, value);
719 static void handleFTPSkipPASVIP(Connection *, value);
720 static void handleFTPFileMethod(Connection *, value);
721 static void handleLocalPort(Connection *, value);
722 static void handleLocalPortRange(Connection *, value);
723 static void handleConnectOnly(Connection *, value);
724 static void handleMaxSendSpeedLarge(Connection *, value);
725 static void handleMaxRecvSpeedLarge(Connection *, value);
726 static void handleFTPAlternativeToUser(Connection *, value);
727 static void handleSSLSessionIdCache(Connection *, value);
728 static void handleSSHAuthTypes(Connection *, value);
729 static void handleSSHPublicKeyFile(Connection *, value);
730 static void handleSSHPrivateKeyFile(Connection *, value);
731 static void handleFTPSSLCCC(Connection *, value);
732 static void handleTimeoutMS(Connection *, value);
733 static void handleConnectTimeoutMS(Connection *, value);
734 static void handleHTTPTransferDecoding(Connection *, value);
735 static void handleHTTPContentDecoding(Connection *, value);
736 static void handleNewFilePerms(Connection *, value);
737 static void handleNewDirectoryPerms(Connection *, value);
738 static void handlePost301(Connection *, value);
739 static void handleSSHHostPublicKeyMD5(Connection *, value);
740 static void handleCopyPostFields(Connection *, value);
741 static void handleProxyTransferMode(Connection *, value);
742 static void handleSeekFunction(Connection *, value);
743 static void handleAutoReferer(Connection *, value);
744 static void handleOpenSocketFunction(Connection *, value);
745 static void handleProxyType(Connection *, value);
746 static void handleProtocols(Connection *, value);
747 static void handleRedirProtocols(Connection *, value);
748 static void handleResolve(Connection *, value);
749 static void handleDnsServers(Connection *, value);
751 CURLOptionMapping implementedOptionMap[] =
753 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
754 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
755 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
756 {handleURL, "CURLOPT_URL", CURLOPT_URL},
757 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
758 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
759 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
760 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
761 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
762 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
763 #if HAVE_DECL_CURLOPT_NOSIGNAL
764 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
765 #else
766 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
767 #endif
768 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
769 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
770 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
771 {handlePost, "CURLOPT_POST", CURLOPT_POST},
772 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
773 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
774 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
775 #if HAVE_DECL_CURLOPT_ENCODING
776 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
777 #else
778 {handleEncoding, "CURLOPT_ENCODING", 0},
779 #endif
780 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
781 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
782 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
783 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
784 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
785 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
786 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
787 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
788 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
789 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
790 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
791 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
792 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
793 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
794 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
795 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
796 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
797 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
798 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
799 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
800 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
801 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
802 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
803 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
804 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
805 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
806 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
807 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
808 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
809 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
810 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
811 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
812 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
813 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
814 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
815 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
816 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
817 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
818 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
819 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
820 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
821 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
822 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
823 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
824 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
825 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
826 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
827 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
828 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
829 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
830 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
831 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
832 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
833 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
834 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
835 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
836 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
837 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
838 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
839 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
840 #if HAVE_DECL_CURLOPT_PRIVATE
841 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
842 #else
843 {handlePrivate, "CURLOPT_PRIVATE", 0},
844 #endif
845 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
846 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
847 #else
848 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
849 #endif
850 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
851 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
852 #else
853 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
854 #endif
855 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
856 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
857 #else
858 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
859 #endif
860 #if HAVE_DECL_CURLOPT_HTTPAUTH
861 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
862 #else
863 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
864 #endif
865 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
866 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
867 #else
868 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
869 #endif
870 #if HAVE_DECL_CURLOPT_PROXYAUTH
871 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
872 #else
873 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
874 #endif
875 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
876 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
877 #else
878 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
879 #endif
880 #if HAVE_DECL_CURLOPT_IPRESOLVE
881 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
882 #else
883 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
884 #endif
885 #if HAVE_DECL_CURLOPT_MAXFILESIZE
886 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
887 #else
888 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
889 #endif
890 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
891 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
892 #else
893 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
894 #endif
895 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
896 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
897 #else
898 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
899 #endif
900 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
901 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
902 #else
903 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
904 #endif
905 #if HAVE_DECL_CURLOPT_NETRC_FILE
906 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
907 #else
908 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
909 #endif
910 #if HAVE_DECL_CURLOPT_FTP_SSL
911 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
912 #else
913 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
914 #endif
915 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
916 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
917 #else
918 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
919 #endif
920 #if HAVE_DECL_CURLOPT_TCP_NODELAY
921 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
922 #else
923 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
924 #endif
925 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
926 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
927 #else
928 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
929 #endif
930 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
931 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
932 #else
933 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
934 #endif
935 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
936 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
937 #else
938 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
939 #endif
940 #if HAVE_DECL_CURLOPT_COOKIELIST
941 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
942 #else
943 {handleCookieList, "CURLOPT_COOKIELIST", 0},
944 #endif
945 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
946 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
947 #else
948 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
949 #endif
950 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
951 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
952 #else
953 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
954 #endif
955 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
956 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
957 #else
958 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
959 #endif
960 #if HAVE_DECL_CURLOPT_LOCALPORT
961 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
962 #else
963 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
964 #endif
965 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
966 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
967 #else
968 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
969 #endif
970 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
971 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
972 #else
973 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
974 #endif
975 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
976 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
977 #else
978 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
979 #endif
980 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
981 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
982 #else
983 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
984 #endif
985 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
986 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
987 #else
988 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
989 #endif
990 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
991 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
992 #else
993 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
994 #endif
995 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
996 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
997 #else
998 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
999 #endif
1000 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
1001 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
1002 #else
1003 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
1004 #endif
1005 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
1006 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
1007 #else
1008 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
1009 #endif
1010 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
1011 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
1012 #else
1013 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
1014 #endif
1015 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
1016 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
1017 #else
1018 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
1019 #endif
1020 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
1021 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
1022 #else
1023 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
1024 #endif
1025 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1026 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1027 #else
1028 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1029 #endif
1030 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1031 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1032 #else
1033 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1034 #endif
1035 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1036 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1037 #else
1038 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1039 #endif
1040 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1041 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1042 #else
1043 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1044 #endif
1045 #if HAVE_DECL_CURLOPT_POST301
1046 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1047 #else
1048 {handlePost301, "CURLOPT_POST301", 0},
1049 #endif
1050 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1051 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1052 #else
1053 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1054 #endif
1055 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1056 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1057 #else
1058 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1059 #endif
1060 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1061 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1062 #else
1063 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1064 #endif
1065 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1066 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1067 #else
1068 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1069 #endif
1070 #if HAVE_DECL_CURLOPT_AUTOREFERER
1071 {handleAutoReferer, "CURLOPT_AUTOREFERER", CURLOPT_AUTOREFERER},
1072 #else
1073 {handleAutoReferer, "CURLOPT_AUTOREFERER", 0},
1074 #endif
1075 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1076 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION},
1077 #else
1078 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", 0},
1079 #endif
1080 #if HAVE_DECL_CURLOPT_PROXYTYPE
1081 {handleProxyType, "CURLOPT_PROXYTYPE", CURLOPT_PROXYTYPE},
1082 #else
1083 {handleProxyType, "CURLOPT_PROXYTYPE", 0},
1084 #endif
1085 #if HAVE_DECL_CURLOPT_PROTOCOLS
1086 {handleProtocols, "CURLOPT_PROTOCOLS", CURLOPT_PROTOCOLS},
1087 #else
1088 {handleProtocols, "CURLOPT_PROTOCOLS", 0},
1089 #endif
1090 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
1091 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS},
1092 #else
1093 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", 0},
1094 #endif
1095 #if HAVE_DECL_CURLOPT_RESOLVE
1096 {handleResolve, "CURLOPT_RESOLVE", CURLOPT_RESOLVE},
1097 #else
1098 {handleResolve, "CURLOPT_RESOLVE", 0},
1099 #endif
1100 #if HAVE_DECL_CURLOPT_DNS_SERVERS
1101 {handleDnsServers, "CURLOPT_DNS_SERVERS", CURLOPT_DNS_SERVERS},
1102 #else
1103 {handleDnsServers, "CURLOPT_DNS_SERVERS", 0},
1104 #endif
1107 static char *findOption(CURLOptionMapping optionMap[],
1108 CURLoption option)
1110 return optionMap[option].name;
1113 static void free_curl_slist(struct curl_slist *slist)
1115 if (NULL == slist)
1116 return;
1118 curl_slist_free_all(slist);
1121 static void raiseError(Connection *conn, CURLcode code)
1123 CAMLparam0();
1124 CAMLlocal1(exceptionData);
1125 value *exception;
1126 char *errorString = "Unknown Error";
1127 int i;
1129 for (i = 0; errorMap[i].name != NULL; i++)
1131 if (errorMap[i].error == code)
1133 errorString = errorMap[i].name;
1134 break;
1138 exceptionData = caml_alloc(3, 0);
1140 Store_field(exceptionData, 0, Val_int(code));
1141 Store_field(exceptionData, 1, Val_int(code));
1142 Store_field(exceptionData, 2, copy_string(errorString));
1144 if (conn != NULL && conn->errorBuffer != NULL)
1146 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1147 copy_string(conn->errorBuffer));
1150 exception = caml_named_value("CurlException");
1152 if (exception == NULL)
1153 caml_failwith("CurlException not registered");
1155 raise_with_arg(*exception, exceptionData);
1157 CAMLreturn0;
1160 static void resetOcamlValues(Connection* connection)
1162 int i;
1164 for (i = 0; i < OcamlValuesSize; i++)
1165 Store_field(connection->ocamlValues, i, Val_unit);
1168 static Connection* allocConnection(CURL* h)
1170 Connection* connection = (Connection *)malloc(sizeof(Connection));
1172 connection->ocamlValues = caml_alloc(OcamlValuesSize, 0);
1173 resetOcamlValues(connection);
1174 register_global_root(&connection->ocamlValues);
1176 connection->connection = h;
1178 connection->next = NULL;
1179 connection->prev = NULL;
1181 if (connectionList.tail == NULL)
1183 connectionList.tail = connection;
1184 connectionList.head = connection;
1186 else
1188 connection->prev = connectionList.head;
1189 connectionList.head->next = connection;
1190 connectionList.head = connection;
1193 connection->refcount = 0;
1195 connection->url = NULL;
1196 connection->proxy = NULL;
1197 connection->userPwd = NULL;
1198 connection->proxyUserPwd = NULL;
1199 connection->range = NULL;
1200 connection->errorBuffer = NULL;
1201 connection->postFields = NULL;
1202 connection->postFieldSize = -1;
1203 connection->referer = NULL;
1204 connection->userAgent = NULL;
1205 connection->ftpPort = NULL;
1206 connection->cookie = NULL;
1207 connection->httpHeader = NULL;
1208 connection->httpPostFirst = NULL;
1209 connection->httpPostLast = NULL;
1210 connection->httpPostStrings = NULL;
1211 connection->sslCert = NULL;
1212 connection->sslCertType = NULL;
1213 connection->sslCertPasswd = NULL;
1214 connection->sslKey = NULL;
1215 connection->sslKeyType = NULL;
1216 connection->sslKeyPasswd = NULL;
1217 connection->sslEngine = NULL;
1218 connection->quote = NULL;
1219 connection->postQuote = NULL;
1220 connection->cookieFile = NULL;
1221 connection->customRequest = NULL;
1222 connection->interface_ = NULL;
1223 connection->caInfo = NULL;
1224 connection->caPath = NULL;
1225 connection->randomFile = NULL;
1226 connection->egdSocket = NULL;
1227 connection->cookieJar = NULL;
1228 connection->sslCipherList = NULL;
1229 connection->private = NULL;
1230 connection->http200Aliases = NULL;
1231 connection->netrcFile = NULL;
1232 connection->ftpaccount = NULL;
1233 connection->cookielist = NULL;
1234 connection->ftpAlternativeToUser = NULL;
1235 connection->sshPublicKeyFile = NULL;
1236 connection->sshPrivateKeyFile = NULL;
1237 connection->copyPostFields = NULL;
1238 connection->resolve = NULL;
1239 connection->dns_servers = NULL;
1241 return connection;
1244 static Connection *newConnection(void)
1246 CURL* h;
1248 caml_enter_blocking_section();
1249 h = curl_easy_init();
1250 caml_leave_blocking_section();
1252 return allocConnection(h);
1255 static Connection *duplicateConnection(Connection *original)
1257 Connection *connection;
1258 CURL* h;
1260 caml_enter_blocking_section();
1261 h = curl_easy_duphandle(original->connection);
1262 caml_leave_blocking_section();
1264 connection = allocConnection(h);
1266 Store_field(connection->ocamlValues, OcamlWriteCallback,
1267 Field(original->ocamlValues, OcamlWriteCallback));
1268 Store_field(connection->ocamlValues, OcamlReadCallback,
1269 Field(original->ocamlValues, OcamlReadCallback));
1270 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1271 Field(original->ocamlValues, OcamlErrorBuffer));
1272 Store_field(connection->ocamlValues, OcamlPostFields,
1273 Field(original->ocamlValues, OcamlPostFields));
1274 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1275 Field(original->ocamlValues, OcamlHTTPHeader));
1276 Store_field(connection->ocamlValues, OcamlQuote,
1277 Field(original->ocamlValues, OcamlQuote));
1278 Store_field(connection->ocamlValues, OcamlPostQuote,
1279 Field(original->ocamlValues, OcamlPostQuote));
1280 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1281 Field(original->ocamlValues, OcamlHeaderCallback));
1282 Store_field(connection->ocamlValues, OcamlProgressCallback,
1283 Field(original->ocamlValues, OcamlProgressCallback));
1284 Store_field(connection->ocamlValues, OcamlDebugCallback,
1285 Field(original->ocamlValues, OcamlDebugCallback));
1286 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1287 Field(original->ocamlValues, OcamlHTTP200Aliases));
1288 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1289 Field(original->ocamlValues, OcamlIOCTLCallback));
1290 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1291 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1293 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1294 handleURL(connection, Field(original->ocamlValues,
1295 OcamlURL));
1296 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1297 handleProxy(connection, Field(original->ocamlValues,
1298 OcamlProxy));
1299 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1300 handleUserPwd(connection, Field(original->ocamlValues,
1301 OcamlUserPWD));
1302 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1303 handleProxyUserPwd(connection, Field(original->ocamlValues,
1304 OcamlProxyUserPWD));
1305 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1306 handleRange(connection, Field(original->ocamlValues,
1307 OcamlRange));
1308 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1309 handleErrorBuffer(connection, Field(original->ocamlValues,
1310 OcamlErrorBuffer));
1311 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1312 handlePostFields(connection, Field(original->ocamlValues,
1313 OcamlPostFields));
1314 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1315 handleReferer(connection, Field(original->ocamlValues,
1316 OcamlReferer));
1317 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1318 handleUserAgent(connection, Field(original->ocamlValues,
1319 OcamlUserAgent));
1320 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1321 handleFTPPort(connection, Field(original->ocamlValues,
1322 OcamlFTPPort));
1323 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1324 handleCookie(connection, Field(original->ocamlValues,
1325 OcamlCookie));
1326 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1327 handleHTTPHeader(connection, Field(original->ocamlValues,
1328 OcamlHTTPHeader));
1329 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1330 handleHTTPPost(connection, Field(original->ocamlValues,
1331 OcamlHTTPPost));
1332 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1333 handleSSLCert(connection, Field(original->ocamlValues,
1334 OcamlSSLCert));
1335 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1336 handleSSLCertType(connection, Field(original->ocamlValues,
1337 OcamlSSLCertType));
1338 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1339 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1340 OcamlSSLCertPasswd));
1341 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1342 handleSSLKey(connection, Field(original->ocamlValues,
1343 OcamlSSLKey));
1344 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1345 handleSSLKeyType(connection, Field(original->ocamlValues,
1346 OcamlSSLKeyType));
1347 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1348 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1349 OcamlSSLKeyPasswd));
1350 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1351 handleSSLEngine(connection, Field(original->ocamlValues,
1352 OcamlSSLEngine));
1353 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1354 handleQuote(connection, Field(original->ocamlValues,
1355 OcamlQuote));
1356 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1357 handlePostQuote(connection, Field(original->ocamlValues,
1358 OcamlPostQuote));
1359 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1360 handleCookieFile(connection, Field(original->ocamlValues,
1361 OcamlCookieFile));
1362 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1363 handleCustomRequest(connection, Field(original->ocamlValues,
1364 OcamlCustomRequest));
1365 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1366 handleInterface(connection, Field(original->ocamlValues,
1367 OcamlInterface));
1368 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1369 handleCAInfo(connection, Field(original->ocamlValues,
1370 OcamlCAInfo));
1371 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1372 handleCAPath(connection, Field(original->ocamlValues,
1373 OcamlCAPath));
1374 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1375 handleRandomFile(connection, Field(original->ocamlValues,
1376 OcamlRandomFile));
1377 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1378 handleEGDSocket(connection, Field(original->ocamlValues,
1379 OcamlEGDSocket));
1380 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1381 handleCookieJar(connection, Field(original->ocamlValues,
1382 OcamlCookieJar));
1383 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1384 handleSSLCipherList(connection, Field(original->ocamlValues,
1385 OcamlSSLCipherList));
1386 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1387 handlePrivate(connection, Field(original->ocamlValues,
1388 OcamlPrivate));
1389 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1390 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1391 OcamlHTTP200Aliases));
1392 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1393 handleNETRCFile(connection, Field(original->ocamlValues,
1394 OcamlNETRCFile));
1395 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1396 handleFTPAccount(connection, Field(original->ocamlValues,
1397 OcamlFTPAccount));
1398 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1399 handleCookieList(connection, Field(original->ocamlValues,
1400 OcamlCookieList));
1401 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1402 handleFTPAlternativeToUser(connection,
1403 Field(original->ocamlValues,
1404 OcamlFTPAlternativeToUser));
1405 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1406 handleSSHPublicKeyFile(connection,
1407 Field(original->ocamlValues,
1408 OcamlSSHPublicKeyFile));
1409 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1410 handleSSHPrivateKeyFile(connection,
1411 Field(original->ocamlValues,
1412 OcamlSSHPrivateKeyFile));
1413 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1414 handleCopyPostFields(connection,
1415 Field(original->ocamlValues,
1416 OcamlCopyPostFields));
1417 if (Field(original->ocamlValues, OcamlDNSServers) != Val_unit)
1418 handleDnsServers(connection,
1419 Field(original->ocamlValues,
1420 OcamlDNSServers));
1422 return connection;
1425 static void free_if(void* p) { if (NULL != p) free(p); }
1427 static void removeConnection(Connection *connection, int finalization)
1429 const char* fin_url = NULL;
1431 if (!connection->connection)
1433 return; /* already cleaned up */
1436 if (finalization)
1438 /* cannot engage OCaml runtime at finalization, just report leak */
1439 if (CURLE_OK != curl_easy_getinfo(connection->connection, CURLINFO_EFFECTIVE_URL, &fin_url) || NULL == fin_url)
1441 fin_url = "unknown";
1443 fprintf(stderr,"Curl: handle %p leaked, conn %p, url %s\n", connection->connection, connection, fin_url);
1444 fflush(stderr);
1446 else
1448 enter_blocking_section();
1449 curl_easy_cleanup(connection->connection);
1450 leave_blocking_section();
1453 connection->connection = NULL;
1455 if (connectionList.tail == connection)
1456 connectionList.tail = connectionList.tail->next;
1457 if (connectionList.head == connection)
1458 connectionList.head = connectionList.head->prev;
1460 if (connection->next != NULL)
1461 connection->next->prev = connection->prev;
1462 if (connection->prev != NULL)
1463 connection->prev->next = connection->next;
1465 remove_global_root(&connection->ocamlValues);
1467 free_if(connection->url);
1468 free_if(connection->proxy);
1469 free_if(connection->userPwd);
1470 free_if(connection->proxyUserPwd);
1471 free_if(connection->range);
1472 free_if(connection->errorBuffer);
1473 free_if(connection->postFields);
1474 free_if(connection->referer);
1475 free_if(connection->userAgent);
1476 free_if(connection->ftpPort);
1477 free_if(connection->cookie);
1478 free_curl_slist(connection->httpHeader);
1479 if (connection->httpPostFirst != NULL)
1480 curl_formfree(connection->httpPostFirst);
1481 free_curl_slist(connection->httpPostStrings);
1482 free_curl_slist(connection->resolve);
1483 free_if(connection->sslCert);
1484 free_if(connection->sslCertType);
1485 free_if(connection->sslCertPasswd);
1486 free_if(connection->sslKey);
1487 free_if(connection->sslKeyType);
1488 free_if(connection->sslKeyPasswd);
1489 free_if(connection->sslEngine);
1490 free_curl_slist(connection->quote);
1491 free_curl_slist(connection->postQuote);
1492 free_if(connection->cookieFile);
1493 free_if(connection->customRequest);
1494 free_if(connection->interface_);
1495 free_if(connection->caInfo);
1496 free_if(connection->caPath);
1497 free_if(connection->randomFile);
1498 free_if(connection->egdSocket);
1499 free_if(connection->cookieJar);
1500 free_if(connection->sslCipherList);
1501 free_if(connection->private);
1502 free_curl_slist(connection->http200Aliases);
1503 free_if(connection->netrcFile);
1504 free_if(connection->ftpaccount);
1505 free_if(connection->cookielist);
1506 free_if(connection->ftpAlternativeToUser);
1507 free_if(connection->sshPublicKeyFile);
1508 free_if(connection->sshPrivateKeyFile);
1509 free_if(connection->copyPostFields);
1510 free_if(connection->dns_servers);
1513 #if 1
1514 static void checkConnection(Connection * connection)
1516 (void)connection;
1518 #else
1519 static void checkConnection(Connection *connection)
1521 Connection *listIter;
1523 listIter = connectionList.tail;
1525 while (listIter != NULL)
1527 if (listIter == connection)
1528 return;
1530 listIter = listIter->next;
1533 failwith("Invalid Connection");
1535 #endif
1537 static Connection* findConnection(CURL* h)
1539 Connection *listIter;
1541 listIter = connectionList.tail;
1543 while (listIter != NULL)
1545 if (listIter->connection == h)
1546 return listIter;
1548 listIter = listIter->next;
1551 failwith("Unknown handle");
1554 void op_curl_easy_finalize(value v)
1556 Connection* conn = Connection_val(v);
1557 /* same connection may be referenced by several different
1558 OCaml values, see e.g. caml_curl_multi_remove_finished */
1559 conn->refcount--;
1560 if (0 == conn->refcount)
1562 removeConnection(conn, 1);
1563 free(conn);
1567 int op_curl_easy_compare(value v1, value v2)
1569 size_t p1 = (size_t)Connection_val(v1);
1570 size_t p2 = (size_t)Connection_val(v2);
1571 return (p1 == p2 ? 0 : (p1 > p2 ? 1 : -1)); /* compare addresses */
1574 intnat op_curl_easy_hash(value v)
1576 return (size_t)Connection_val(v); /* address */
1579 static struct custom_operations curl_easy_ops = {
1580 "ygrek.curl_easy",
1581 op_curl_easy_finalize,
1582 op_curl_easy_compare,
1583 op_curl_easy_hash,
1584 custom_serialize_default,
1585 custom_deserialize_default,
1586 #if defined(custom_compare_ext_default)
1587 custom_compare_ext_default,
1588 #endif
1591 value caml_curl_alloc(Connection* conn)
1593 value v = caml_alloc_custom(&curl_easy_ops, sizeof(Connection*), 0, 1);
1594 Connection_val(v) = conn;
1595 conn->refcount++;
1596 return v;
1599 #define WRAP_DATA_CALLBACK(f) \
1600 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1602 size_t result;\
1603 leave_blocking_section();\
1604 result = f##_nolock(ptr,size,nmemb,data);\
1605 enter_blocking_section();\
1606 return result;\
1609 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1611 CAMLparam0();
1612 CAMLlocal2(result, str);
1613 Connection *conn = (Connection *)data;
1614 size_t i;
1616 checkConnection(conn);
1618 str = alloc_string(size*nmemb);
1620 for (i = 0; i < size*nmemb; i++)
1621 Byte(str, i) = ptr[i];
1623 result = callback_exn(Field(conn->ocamlValues, OcamlWriteCallback), str);
1625 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1628 WRAP_DATA_CALLBACK(writeFunction)
1630 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1632 CAMLparam0();
1633 CAMLlocal1(result);
1634 Connection *conn = (Connection *)data;
1635 size_t length;
1637 checkConnection(conn);
1639 result = callback_exn(Field(conn->ocamlValues, OcamlReadCallback),
1640 Val_int(size*nmemb));
1642 if (Is_exception_result(result))
1644 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
1647 length = string_length(result);
1649 if (length <= size*nmemb)
1651 memcpy(ptr, String_val(result), length);
1653 CAMLreturnT(size_t,length);
1655 else
1657 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
1661 WRAP_DATA_CALLBACK(readFunction)
1663 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1665 CAMLparam0();
1666 CAMLlocal2(result,str);
1667 Connection *conn = (Connection *)data;
1668 size_t i;
1670 checkConnection(conn);
1672 str = alloc_string(size*nmemb);
1674 for (i = 0; i < size*nmemb; i++)
1675 Byte(str, i) = ptr[i];
1677 result = callback_exn(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1679 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1682 WRAP_DATA_CALLBACK(headerFunction)
1684 static int progressFunction_nolock(void *data,
1685 double dlTotal,
1686 double dlNow,
1687 double ulTotal,
1688 double ulNow)
1690 CAMLparam0();
1691 CAMLlocal1(result);
1692 CAMLlocalN(callbackData, 4);
1693 Connection *conn = (Connection *)data;
1695 checkConnection(conn);
1697 callbackData[0] = copy_double(dlTotal);
1698 callbackData[1] = copy_double(dlNow);
1699 callbackData[2] = copy_double(ulTotal);
1700 callbackData[3] = copy_double(ulNow);
1702 result = callbackN_exn(Field(conn->ocamlValues, OcamlProgressCallback),
1703 4, callbackData);
1705 CAMLreturnT(int, Is_exception_result(result) ? 1 : Bool_val(result));
1708 static int progressFunction(void *data,
1709 double dlTotal,
1710 double dlNow,
1711 double ulTotal,
1712 double ulNow)
1714 int r;
1715 leave_blocking_section();
1716 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1717 enter_blocking_section();
1718 return r;
1721 static int debugFunction_nolock(CURL *debugConnection,
1722 curl_infotype infoType,
1723 char *buffer,
1724 size_t bufferLength,
1725 void *data)
1727 CAMLparam0();
1728 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1729 size_t i;
1730 Connection *conn = (Connection *)data;
1731 (void)debugConnection; /* not used */
1733 checkConnection(conn);
1735 camlDebugConnection = (value)conn;
1736 camlInfoType = Val_long(infoType);
1737 camlMessage = alloc_string(bufferLength);
1739 for (i = 0; i < bufferLength; i++)
1740 Byte(camlMessage, i) = buffer[i];
1742 callback3_exn(Field(conn->ocamlValues, OcamlDebugCallback),
1743 camlDebugConnection,
1744 camlInfoType,
1745 camlMessage);
1747 CAMLreturnT(int, 0);
1750 static int debugFunction(CURL *debugConnection,
1751 curl_infotype infoType,
1752 char *buffer,
1753 size_t bufferLength,
1754 void *data)
1756 int r;
1757 leave_blocking_section();
1758 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1759 enter_blocking_section();
1760 return r;
1763 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1764 int cmd,
1765 void *data)
1767 CAMLparam0();
1768 CAMLlocal3(camlResult, camlConnection, camlCmd);
1769 Connection *conn = (Connection *)data;
1770 curlioerr result = CURLIOE_OK;
1771 (void)ioctl; /* not used */
1773 checkConnection(conn);
1775 if (cmd == CURLIOCMD_NOP)
1776 camlCmd = Val_long(0);
1777 else if (cmd == CURLIOCMD_RESTARTREAD)
1778 camlCmd = Val_long(1);
1779 else
1780 failwith("Invalid IOCTL Cmd!");
1782 camlConnection = caml_curl_alloc(conn);
1784 camlResult = callback2_exn(Field(conn->ocamlValues, OcamlIOCTLCallback),
1785 camlConnection,
1786 camlCmd);
1788 if (Is_exception_result(camlResult))
1790 result = CURLIOE_FAILRESTART;
1792 else
1793 switch (Long_val(camlResult))
1795 case 0: /* CURLIOE_OK */
1796 result = CURLIOE_OK;
1797 break;
1799 case 1: /* CURLIOE_UNKNOWNCMD */
1800 result = CURLIOE_UNKNOWNCMD;
1801 break;
1803 case 2: /* CURLIOE_FAILRESTART */
1804 result = CURLIOE_FAILRESTART;
1805 break;
1807 default: /* Incorrect return value, but let's handle it */
1808 result = CURLIOE_FAILRESTART;
1809 break;
1812 CAMLreturnT(curlioerr, result);
1815 static curlioerr ioctlFunction(CURL *ioctl,
1816 int cmd,
1817 void *data)
1819 curlioerr r;
1820 leave_blocking_section();
1821 r = ioctlFunction_nolock(ioctl, cmd, data);
1822 enter_blocking_section();
1823 return r;
1826 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1827 static int seekFunction_nolock(void *data,
1828 curl_off_t offset,
1829 int origin)
1831 CAMLparam0();
1832 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1833 Connection *conn = (Connection *)data;
1835 camlOffset = copy_int64(offset);
1837 if (origin == SEEK_SET)
1838 camlOrigin = Val_long(0);
1839 else if (origin == SEEK_CUR)
1840 camlOrigin = Val_long(1);
1841 else if (origin == SEEK_END)
1842 camlOrigin = Val_long(2);
1843 else
1844 failwith("Invalid seek code");
1846 camlResult = callback2_exn(Field(conn->ocamlValues,
1847 OcamlSeekFunctionCallback),
1848 camlOffset,
1849 camlOrigin);
1851 int result;
1852 if (Is_exception_result(camlResult))
1853 result = CURL_SEEKFUNC_FAIL;
1854 else
1855 switch (Int_val(camlResult))
1857 case 0: result = CURL_SEEKFUNC_OK; break;
1858 case 1: result = CURL_SEEKFUNC_FAIL; break;
1859 case 2: result = CURL_SEEKFUNC_CANTSEEK; break;
1860 default: failwith("Invalid seek result");
1863 CAMLreturnT(int, result);
1866 static int seekFunction(void *data,
1867 curl_off_t offset,
1868 int origin)
1870 int r;
1871 leave_blocking_section();
1872 r = seekFunction_nolock(data,offset,origin);
1873 enter_blocking_section();
1874 return r;
1877 #endif
1879 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1880 static int openSocketFunction_nolock(void *data,
1881 curlsocktype purpose,
1882 struct curl_sockaddr *addr)
1884 CAMLparam0();
1885 CAMLlocal1(result);
1886 Connection *conn = (Connection *)data;
1887 int sock = -1;
1888 (void)purpose; /* not used */
1890 sock = socket(addr->family, addr->socktype, addr->protocol);
1892 if (-1 != sock)
1894 /* FIXME windows */
1895 result = callback_exn(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1896 if (Is_exception_result(result))
1898 close(sock);
1899 sock = -1;
1903 CAMLreturnT(int, (sock == -1) ? CURL_SOCKET_BAD : sock);
1906 static int openSocketFunction(void *data,
1907 curlsocktype purpose,
1908 struct curl_sockaddr *address)
1910 int r;
1911 leave_blocking_section();
1912 r = openSocketFunction_nolock(data,purpose,address);
1913 enter_blocking_section();
1914 return r;
1917 #endif
1920 ** curl_global_init helper function
1923 CAMLprim value helper_curl_global_init(value initOption)
1925 CAMLparam1(initOption);
1927 switch (Long_val(initOption))
1929 case 0: /* CURLINIT_GLOBALALL */
1930 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1931 break;
1933 case 1: /* CURLINIT_GLOBALSSL */
1934 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1935 break;
1937 case 2: /* CURLINIT_GLOBALWIN32 */
1938 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1939 break;
1941 case 3: /* CURLINIT_GLOBALNOTHING */
1942 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1943 break;
1945 default:
1946 failwith("Invalid Initialization Option");
1947 break;
1950 /* Keep compiler happy, we should never get here due to failwith() */
1951 CAMLreturn(Val_unit);
1955 ** curl_global_cleanup helper function
1958 CAMLprim value helper_curl_global_cleanup(void)
1960 CAMLparam0();
1962 curl_global_cleanup();
1964 CAMLreturn(Val_unit);
1968 ** curl_easy_init helper function
1970 CAMLprim value helper_curl_easy_init(void)
1972 CAMLparam0();
1973 CAMLlocal1(result);
1975 result = caml_curl_alloc(newConnection());
1977 CAMLreturn(result);
1980 CAMLprim value helper_curl_easy_reset(value conn)
1982 CAMLparam1(conn);
1983 Connection *connection = Connection_val(conn);
1985 checkConnection(connection);
1986 curl_easy_reset(connection->connection);
1987 resetOcamlValues(connection);
1989 CAMLreturn(Val_unit);
1993 ** curl_easy_setopt helper utility functions
1996 static void handleWriteFunction(Connection *conn, value option)
1998 CAMLparam1(option);
1999 CURLcode result = CURLE_OK;
2001 if (Tag_val(option) == Closure_tag)
2002 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
2003 else
2004 failwith("Not a proper closure");
2006 result = curl_easy_setopt(conn->connection,
2007 CURLOPT_WRITEFUNCTION,
2008 writeFunction);
2010 if (result != CURLE_OK)
2011 raiseError(conn, result);
2013 result = curl_easy_setopt(conn->connection,
2014 CURLOPT_WRITEDATA,
2015 conn);
2017 if (result != CURLE_OK)
2018 raiseError(conn, result);
2020 CAMLreturn0;
2023 static void handleReadFunction(Connection *conn, value option)
2025 CAMLparam1(option);
2026 CURLcode result = CURLE_OK;
2028 if (Tag_val(option) == Closure_tag)
2029 Store_field(conn->ocamlValues, OcamlReadCallback, option);
2030 else
2031 failwith("Not a proper closure");
2033 result = curl_easy_setopt(conn->connection,
2034 CURLOPT_READFUNCTION,
2035 readFunction);
2037 if (result != CURLE_OK)
2038 raiseError(conn, result);
2040 result = curl_easy_setopt(conn->connection,
2041 CURLOPT_READDATA,
2042 conn);
2044 if (result != CURLE_OK)
2045 raiseError(conn, result);
2047 CAMLreturn0;
2050 static void handleURL(Connection *conn, value option)
2052 CAMLparam1(option);
2053 CURLcode result = CURLE_OK;
2055 Store_field(conn->ocamlValues, OcamlURL, option);
2057 if (conn->url != NULL)
2058 free(conn->url);
2060 conn->url = strdup(String_val(option));
2062 result = curl_easy_setopt(conn->connection,
2063 CURLOPT_URL,
2064 conn->url);
2066 if (result != CURLE_OK)
2067 raiseError(conn, result);
2069 CAMLreturn0;
2072 static void handleInFileSize(Connection *conn, value option)
2074 CAMLparam1(option);
2075 CURLcode result = CURLE_OK;
2077 result = curl_easy_setopt(conn->connection,
2078 CURLOPT_INFILESIZE,
2079 Long_val(option));
2081 if (result != CURLE_OK)
2082 raiseError(conn, result);
2084 CAMLreturn0;
2087 static void handleProxy(Connection *conn, value option)
2089 CAMLparam1(option);
2090 CURLcode result = CURLE_OK;
2092 Store_field(conn->ocamlValues, OcamlProxy, option);
2094 if (conn->proxy != NULL)
2095 free(conn->proxy);
2097 conn->proxy = strdup(String_val(option));
2099 result = curl_easy_setopt(conn->connection,
2100 CURLOPT_PROXY,
2101 conn->proxy);
2103 if (result != CURLE_OK)
2104 raiseError(conn, result);
2106 CAMLreturn0;
2109 static void handleProxyPort(Connection *conn, value option)
2111 CAMLparam1(option);
2112 CURLcode result = CURLE_OK;
2114 result = curl_easy_setopt(conn->connection,
2115 CURLOPT_PROXYPORT,
2116 Long_val(option));
2118 if (result != CURLE_OK)
2119 raiseError(conn, result);
2121 CAMLreturn0;
2124 static void handleHTTPProxyTunnel(Connection *conn, value option)
2126 CAMLparam1(option);
2127 CURLcode result = CURLE_OK;
2129 result = curl_easy_setopt(conn->connection,
2130 CURLOPT_HTTPPROXYTUNNEL,
2131 Bool_val(option));
2133 if (result != CURLE_OK)
2134 raiseError(conn, result);
2136 CAMLreturn0;
2139 static void handleVerbose(Connection *conn, value option)
2141 CAMLparam1(option);
2142 CURLcode result = CURLE_OK;
2144 result = curl_easy_setopt(conn->connection,
2145 CURLOPT_VERBOSE,
2146 Bool_val(option));
2148 if (result != CURLE_OK)
2149 raiseError(conn, result);
2151 CAMLreturn0;
2154 static void handleHeader(Connection *conn, value option)
2156 CAMLparam1(option);
2157 CURLcode result = CURLE_OK;
2159 result = curl_easy_setopt(conn->connection,
2160 CURLOPT_HEADER,
2161 Bool_val(option));
2163 if (result != CURLE_OK)
2164 raiseError(conn, result);
2166 CAMLreturn0;
2169 static void handleNoProgress(Connection *conn, value option)
2171 CAMLparam1(option);
2172 CURLcode result = CURLE_OK;
2174 result = curl_easy_setopt(conn->connection,
2175 CURLOPT_NOPROGRESS,
2176 Bool_val(option));
2178 if (result != CURLE_OK)
2179 raiseError(conn, result);
2181 CAMLreturn0;
2184 static void handleNoSignal(Connection *conn, value option)
2186 #if HAVE_DECL_CURLOPT_NOSIGNAL
2187 CAMLparam1(option);
2188 CURLcode result = CURLE_OK;
2190 result = curl_easy_setopt(conn->connection,
2191 CURLOPT_NOSIGNAL,
2192 Bool_val(option));
2194 if (result != CURLE_OK)
2195 raiseError(conn, result);
2197 CAMLreturn0;
2198 #else
2199 #pragma message("libcurl does not implement CURLOPT_NOSIGNAL")
2200 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2201 #endif
2204 static void handleNoBody(Connection *conn, value option)
2206 CAMLparam1(option);
2207 CURLcode result = CURLE_OK;
2209 result = curl_easy_setopt(conn->connection,
2210 CURLOPT_NOBODY,
2211 Bool_val(option));
2213 if (result != CURLE_OK)
2214 raiseError(conn, result);
2216 CAMLreturn0;
2219 static void handleFailOnError(Connection *conn, value option)
2221 CAMLparam1(option);
2222 CURLcode result = CURLE_OK;
2224 result = curl_easy_setopt(conn->connection,
2225 CURLOPT_FAILONERROR,
2226 Bool_val(option));
2228 if (result != CURLE_OK)
2229 raiseError(conn, result);
2231 CAMLreturn0;
2234 static void handleUpload(Connection *conn, value option)
2236 CAMLparam1(option);
2237 CURLcode result = CURLE_OK;
2239 result = curl_easy_setopt(conn->connection,
2240 CURLOPT_UPLOAD,
2241 Bool_val(option));
2243 if (result != CURLE_OK)
2244 raiseError(conn, result);
2246 CAMLreturn0;
2249 static void handlePost(Connection *conn, value option)
2251 CAMLparam1(option);
2252 CURLcode result = CURLE_OK;
2254 result = curl_easy_setopt(conn->connection,
2255 CURLOPT_POST,
2256 Bool_val(option));
2258 if (result != CURLE_OK)
2259 raiseError(conn, result);
2261 CAMLreturn0;
2264 static void handleFTPListOnly(Connection *conn, value option)
2266 CAMLparam1(option);
2267 CURLcode result = CURLE_OK;
2269 result = curl_easy_setopt(conn->connection,
2270 CURLOPT_FTPLISTONLY,
2271 Bool_val(option));
2273 if (result != CURLE_OK)
2274 raiseError(conn, result);
2276 CAMLreturn0;
2279 static void handleFTPAppend(Connection *conn, value option)
2281 CAMLparam1(option);
2282 CURLcode result = CURLE_OK;
2284 result = curl_easy_setopt(conn->connection,
2285 CURLOPT_FTPAPPEND,
2286 Bool_val(option));
2288 if (result != CURLE_OK)
2289 raiseError(conn, result);
2291 CAMLreturn0;
2294 static void handleNETRC(Connection *conn, value option)
2296 CAMLparam1(option);
2297 CURLcode result = CURLE_OK;
2298 long netrc;
2300 switch (Long_val(option))
2302 case 0: /* CURL_NETRC_OPTIONAL */
2303 netrc = CURL_NETRC_OPTIONAL;
2304 break;
2306 case 1:/* CURL_NETRC_IGNORED */
2307 netrc = CURL_NETRC_IGNORED;
2308 break;
2310 case 2: /* CURL_NETRC_REQUIRED */
2311 netrc = CURL_NETRC_REQUIRED;
2312 break;
2314 default:
2315 failwith("Invalid NETRC Option");
2316 break;
2319 result = curl_easy_setopt(conn->connection,
2320 CURLOPT_NETRC,
2321 netrc);
2323 if (result != CURLE_OK)
2324 raiseError(conn, result);
2326 CAMLreturn0;
2329 static void handleEncoding(Connection *conn, value option)
2331 #if HAVE_DECL_CURLOPT_ENCODING
2332 CAMLparam1(option);
2333 CURLcode result = CURLE_OK;
2335 switch (Long_val(option))
2337 case 0: /* CURL_ENCODING_NONE */
2338 result = curl_easy_setopt(conn->connection,
2339 CURLOPT_ENCODING,
2340 "identity");
2341 break;
2343 case 1: /* CURL_ENCODING_DEFLATE */
2344 result = curl_easy_setopt(conn->connection,
2345 CURLOPT_ENCODING,
2346 "deflate");
2347 break;
2349 case 2: /* CURL_ENCODING_GZIP */
2350 result = curl_easy_setopt(conn->connection,
2351 CURLOPT_ENCODING,
2352 "gzip");
2353 break;
2355 case 3: /* CURL_ENCODING_ANY */
2356 result = curl_easy_setopt(conn->connection,
2357 CURLOPT_ENCODING,
2358 "");
2359 break;
2361 default:
2362 failwith("Invalid Encoding Option");
2363 break;
2366 if (result != CURLE_OK)
2367 raiseError(conn, result);
2369 CAMLreturn0;
2370 #else
2371 #pragma message("libcurl does not implement CURLOPT_ENCODING")
2372 failwith("libcurl does not implement CURLOPT_ENCODING");
2373 #endif
2376 static void handleFollowLocation(Connection *conn, value option)
2378 CAMLparam1(option);
2379 CURLcode result = CURLE_OK;
2381 result = curl_easy_setopt(conn->connection,
2382 CURLOPT_FOLLOWLOCATION,
2383 Bool_val(option));
2385 if (result != CURLE_OK)
2386 raiseError(conn, result);
2388 CAMLreturn0;
2391 static void handleTransferText(Connection *conn, value option)
2393 CAMLparam1(option);
2394 CURLcode result = CURLE_OK;
2396 result = curl_easy_setopt(conn->connection,
2397 CURLOPT_TRANSFERTEXT,
2398 Bool_val(option));
2400 if (result != CURLE_OK)
2401 raiseError(conn, result);
2403 CAMLreturn0;
2406 static void handlePut(Connection *conn, value option)
2408 CAMLparam1(option);
2409 CURLcode result = CURLE_OK;
2411 result = curl_easy_setopt(conn->connection,
2412 CURLOPT_PUT,
2413 Bool_val(option));
2415 if (result != CURLE_OK)
2416 raiseError(conn, result);
2418 CAMLreturn0;
2421 static void handleUserPwd(Connection *conn, value option)
2423 CAMLparam1(option);
2424 CURLcode result = CURLE_OK;
2426 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2428 if (conn->userPwd != NULL)
2429 free(conn->userPwd);
2431 conn->userPwd = strdup(String_val(option));
2433 result = curl_easy_setopt(conn->connection,
2434 CURLOPT_USERPWD,
2435 conn->userPwd);
2437 if (result != CURLE_OK)
2438 raiseError(conn, result);
2440 CAMLreturn0;
2443 static void handleProxyUserPwd(Connection *conn, value option)
2445 CAMLparam1(option);
2446 CURLcode result = CURLE_OK;
2448 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2450 if (conn->proxyUserPwd != NULL)
2451 free(conn->proxyUserPwd);
2453 conn->proxyUserPwd = strdup(String_val(option));
2455 result = curl_easy_setopt(conn->connection,
2456 CURLOPT_PROXYUSERPWD,
2457 conn->proxyUserPwd);
2459 if (result != CURLE_OK)
2460 raiseError(conn, result);
2462 CAMLreturn0;
2465 static void handleRange(Connection *conn, value option)
2467 CAMLparam1(option);
2468 CURLcode result = CURLE_OK;
2470 Store_field(conn->ocamlValues, OcamlRange, option);
2472 if (conn->range != NULL)
2473 free(conn->range);
2475 conn->range = strdup(String_val(option));
2477 result = curl_easy_setopt(conn->connection,
2478 CURLOPT_RANGE,
2479 conn->range);
2481 if (result != CURLE_OK)
2482 raiseError(conn, result);
2484 CAMLreturn0;
2487 static void handleErrorBuffer(Connection *conn, value option)
2489 CAMLparam1(option);
2490 CURLcode result = CURLE_OK;
2492 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2494 if (conn->errorBuffer != NULL)
2495 free(conn->errorBuffer);
2497 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2499 result = curl_easy_setopt(conn->connection,
2500 CURLOPT_ERRORBUFFER,
2501 conn->errorBuffer);
2503 if (result != CURLE_OK)
2504 raiseError(conn, result);
2506 CAMLreturn0;
2509 static void handleTimeout(Connection *conn, value option)
2511 CAMLparam1(option);
2512 CURLcode result = CURLE_OK;
2514 result = curl_easy_setopt(conn->connection,
2515 CURLOPT_TIMEOUT,
2516 Long_val(option));
2518 if (result != CURLE_OK)
2519 raiseError(conn, result);
2521 CAMLreturn0;
2524 static void handlePostFields(Connection *conn, value option)
2526 CAMLparam1(option);
2527 CURLcode result = CURLE_OK;
2529 Store_field(conn->ocamlValues, OcamlPostFields, option);
2531 if (conn->postFields != NULL)
2532 free(conn->postFields);
2534 conn->postFields = malloc(string_length(option)+1);
2535 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2537 result = curl_easy_setopt(conn->connection,
2538 CURLOPT_POSTFIELDS,
2539 conn->postFields);
2541 if (result != CURLE_OK)
2542 raiseError(conn, result);
2544 CAMLreturn0;
2547 static void handlePostFieldSize(Connection *conn, value option)
2549 CAMLparam1(option);
2550 CURLcode result = CURLE_OK;
2552 result = curl_easy_setopt(conn->connection,
2553 CURLOPT_POSTFIELDSIZE,
2554 Long_val(option));
2556 if (result != CURLE_OK)
2557 raiseError(conn, result);
2559 CAMLreturn0;
2562 static void handleReferer(Connection *conn, value option)
2564 CAMLparam1(option);
2565 CURLcode result = CURLE_OK;
2567 Store_field(conn->ocamlValues, OcamlReferer, option);
2569 if (conn->referer != NULL)
2570 free(conn->referer);
2572 conn->referer = strdup(String_val(option));
2574 result = curl_easy_setopt(conn->connection,
2575 CURLOPT_REFERER,
2576 conn->referer);
2578 if (result != CURLE_OK)
2579 raiseError(conn, result);
2581 CAMLreturn0;
2584 static void handleUserAgent(Connection *conn, value option)
2586 CAMLparam1(option);
2587 CURLcode result = CURLE_OK;
2589 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2591 if (conn->userAgent != NULL)
2592 free(conn->userAgent);
2594 conn->userAgent = strdup(String_val(option));
2596 result = curl_easy_setopt(conn->connection,
2597 CURLOPT_USERAGENT,
2598 conn->userAgent);
2600 if (result != CURLE_OK)
2601 raiseError(conn, result);
2603 CAMLreturn0;
2606 static void handleFTPPort(Connection *conn, value option)
2608 CAMLparam1(option);
2609 CURLcode result = CURLE_OK;
2611 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2613 if (conn->ftpPort != NULL)
2614 free(conn->ftpPort);
2616 conn->ftpPort = strdup(String_val(option));
2618 result = curl_easy_setopt(conn->connection,
2619 CURLOPT_FTPPORT,
2620 conn->ftpPort);
2622 if (result != CURLE_OK)
2623 raiseError(conn, result);
2625 CAMLreturn0;
2628 static void handleLowSpeedLimit(Connection *conn, value option)
2630 CAMLparam1(option);
2631 CURLcode result = CURLE_OK;
2633 result = curl_easy_setopt(conn->connection,
2634 CURLOPT_LOW_SPEED_LIMIT,
2635 Long_val(option));
2637 if (result != CURLE_OK)
2638 raiseError(conn, result);
2640 CAMLreturn0;
2643 static void handleLowSpeedTime(Connection *conn, value option)
2645 CAMLparam1(option);
2646 CURLcode result = CURLE_OK;
2648 result = curl_easy_setopt(conn->connection,
2649 CURLOPT_LOW_SPEED_TIME,
2650 Long_val(option));
2652 if (result != CURLE_OK)
2653 raiseError(conn, result);
2655 CAMLreturn0;
2658 static void handleResumeFrom(Connection *conn, value option)
2660 CAMLparam1(option);
2661 CURLcode result = CURLE_OK;
2663 result = curl_easy_setopt(conn->connection,
2664 CURLOPT_RESUME_FROM,
2665 Long_val(option));
2667 if (result != CURLE_OK)
2668 raiseError(conn, result);
2670 CAMLreturn0;
2673 static void handleCookie(Connection *conn, value option)
2675 CAMLparam1(option);
2676 CURLcode result = CURLE_OK;
2678 Store_field(conn->ocamlValues, OcamlCookie, option);
2680 if (conn->cookie != NULL)
2681 free(conn->cookie);
2683 conn->cookie = strdup(String_val(option));
2685 result = curl_easy_setopt(conn->connection,
2686 CURLOPT_COOKIE,
2687 conn->cookie);
2689 if (result != CURLE_OK)
2690 raiseError(conn, result);
2692 CAMLreturn0;
2695 static void handleHTTPHeader(Connection *conn, value option)
2697 CAMLparam1(option);
2698 CAMLlocal1(listIter);
2699 CURLcode result = CURLE_OK;
2701 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2703 free_curl_slist(conn->httpHeader);
2704 conn->httpHeader = NULL;
2706 listIter = option;
2708 while (!Is_long(listIter))
2710 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2712 listIter = Field(listIter, 1);
2715 result = curl_easy_setopt(conn->connection,
2716 CURLOPT_HTTPHEADER,
2717 conn->httpHeader);
2719 if (result != CURLE_OK)
2720 raiseError(conn, result);
2722 CAMLreturn0;
2725 static void handleHTTPPost(Connection *conn, value option)
2727 CAMLparam1(option);
2728 CAMLlocal3(listIter, formItem, contentType);
2729 CURLcode result = CURLE_OK;
2730 char *str1, *str2, *str3, *str4;
2732 listIter = option;
2734 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2736 if (conn->httpPostFirst != NULL)
2737 curl_formfree(conn->httpPostFirst);
2739 conn->httpPostFirst = NULL;
2740 conn->httpPostLast = NULL;
2742 free_curl_slist(conn->httpPostStrings);
2743 conn->httpPostStrings = NULL;
2745 while (!Is_long(listIter))
2747 formItem = Field(listIter, 0);
2749 switch (Tag_val(formItem))
2751 case 0: /* CURLFORM_CONTENT */
2752 if (Wosize_val(formItem) < 3)
2754 failwith("Incorrect CURLFORM_CONTENT parameters");
2757 if (Is_long(Field(formItem, 2)) &&
2758 Long_val(Field(formItem, 2)) == 0)
2760 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2761 memcpy(str1,
2762 String_val(Field(formItem, 0)),
2763 string_length(Field(formItem, 0)));
2764 str1[string_length(Field(formItem, 0))] = 0;
2765 conn->httpPostStrings =
2766 curl_slist_append(conn->httpPostStrings, str1);
2768 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2769 memcpy(str2,
2770 String_val(Field(formItem, 1)),
2771 string_length(Field(formItem, 1)));
2772 str2[string_length(Field(formItem, 1))] = 0;
2773 conn->httpPostStrings =
2774 curl_slist_append(conn->httpPostStrings, str2);
2776 curl_formadd(&conn->httpPostFirst,
2777 &conn->httpPostLast,
2778 CURLFORM_PTRNAME,
2779 str1,
2780 CURLFORM_NAMELENGTH,
2781 string_length(Field(formItem, 0)),
2782 CURLFORM_PTRCONTENTS,
2783 str2,
2784 CURLFORM_CONTENTSLENGTH,
2785 string_length(Field(formItem, 1)),
2786 CURLFORM_END);
2788 else if (Is_block(Field(formItem, 2)))
2790 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2791 memcpy(str1,
2792 String_val(Field(formItem, 0)),
2793 string_length(Field(formItem, 0)));
2794 str1[string_length(Field(formItem, 0))] = 0;
2795 conn->httpPostStrings =
2796 curl_slist_append(conn->httpPostStrings, str1);
2798 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2799 memcpy(str2,
2800 String_val(Field(formItem, 1)),
2801 string_length(Field(formItem, 1)));
2802 str2[string_length(Field(formItem, 1))] = 0;
2803 conn->httpPostStrings =
2804 curl_slist_append(conn->httpPostStrings, str2);
2806 contentType = Field(formItem, 2);
2808 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2809 memcpy(str3,
2810 String_val(Field(contentType, 0)),
2811 string_length(Field(contentType, 0)));
2812 str3[string_length(Field(contentType, 0))] = 0;
2813 conn->httpPostStrings =
2814 curl_slist_append(conn->httpPostStrings, str3);
2816 curl_formadd(&conn->httpPostFirst,
2817 &conn->httpPostLast,
2818 CURLFORM_PTRNAME,
2819 str1,
2820 CURLFORM_NAMELENGTH,
2821 string_length(Field(formItem, 0)),
2822 CURLFORM_PTRCONTENTS,
2823 str2,
2824 CURLFORM_CONTENTSLENGTH,
2825 string_length(Field(formItem, 1)),
2826 CURLFORM_CONTENTTYPE,
2827 str3,
2828 CURLFORM_END);
2830 else
2832 failwith("Incorrect CURLFORM_CONTENT parameters");
2834 break;
2836 case 1: /* CURLFORM_FILECONTENT */
2837 if (Wosize_val(formItem) < 3)
2839 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2842 if (Is_long(Field(formItem, 2)) &&
2843 Long_val(Field(formItem, 2)) == 0)
2845 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2846 memcpy(str1,
2847 String_val(Field(formItem, 0)),
2848 string_length(Field(formItem, 0)));
2849 str1[string_length(Field(formItem, 0))] = 0;
2850 conn->httpPostStrings =
2851 curl_slist_append(conn->httpPostStrings, str1);
2853 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2854 memcpy(str2,
2855 String_val(Field(formItem, 1)),
2856 string_length(Field(formItem, 1)));
2857 str2[string_length(Field(formItem, 1))] = 0;
2858 conn->httpPostStrings =
2859 curl_slist_append(conn->httpPostStrings, str2);
2861 curl_formadd(&conn->httpPostFirst,
2862 &conn->httpPostLast,
2863 CURLFORM_PTRNAME,
2864 str1,
2865 CURLFORM_NAMELENGTH,
2866 string_length(Field(formItem, 0)),
2867 CURLFORM_FILECONTENT,
2868 str2,
2869 CURLFORM_END);
2871 else if (Is_block(Field(formItem, 2)))
2873 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2874 memcpy(str1,
2875 String_val(Field(formItem, 0)),
2876 string_length(Field(formItem, 0)));
2877 str1[string_length(Field(formItem, 0))] = 0;
2878 conn->httpPostStrings =
2879 curl_slist_append(conn->httpPostStrings, str1);
2881 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2882 memcpy(str2,
2883 String_val(Field(formItem, 1)),
2884 string_length(Field(formItem, 1)));
2885 str2[string_length(Field(formItem, 1))] = 0;
2886 conn->httpPostStrings =
2887 curl_slist_append(conn->httpPostStrings, str2);
2889 contentType = Field(formItem, 2);
2891 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2892 memcpy(str3,
2893 String_val(Field(contentType, 0)),
2894 string_length(Field(contentType, 0)));
2895 str3[string_length(Field(contentType, 0))] = 0;
2896 conn->httpPostStrings =
2897 curl_slist_append(conn->httpPostStrings, str3);
2899 curl_formadd(&conn->httpPostFirst,
2900 &conn->httpPostLast,
2901 CURLFORM_PTRNAME,
2902 str1,
2903 CURLFORM_NAMELENGTH,
2904 string_length(Field(formItem, 0)),
2905 CURLFORM_FILECONTENT,
2906 str2,
2907 CURLFORM_CONTENTTYPE,
2908 str3,
2909 CURLFORM_END);
2911 else
2913 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2915 break;
2917 case 2: /* CURLFORM_FILE */
2918 if (Wosize_val(formItem) < 3)
2920 failwith("Incorrect CURLFORM_FILE parameters");
2923 if (Is_long(Field(formItem, 2)) &&
2924 Long_val(Field(formItem, 2)) == 0)
2926 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2927 memcpy(str1,
2928 String_val(Field(formItem, 0)),
2929 string_length(Field(formItem, 0)));
2930 str1[string_length(Field(formItem, 0))] = 0;
2931 conn->httpPostStrings =
2932 curl_slist_append(conn->httpPostStrings, str1);
2934 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2935 memcpy(str2,
2936 String_val(Field(formItem, 1)),
2937 string_length(Field(formItem, 1)));
2938 str2[string_length(Field(formItem, 1))] = 0;
2939 conn->httpPostStrings =
2940 curl_slist_append(conn->httpPostStrings, str2);
2942 curl_formadd(&conn->httpPostFirst,
2943 &conn->httpPostLast,
2944 CURLFORM_PTRNAME,
2945 str1,
2946 CURLFORM_NAMELENGTH,
2947 string_length(Field(formItem, 0)),
2948 CURLFORM_FILE,
2949 str2,
2950 CURLFORM_END);
2952 else if (Is_block(Field(formItem, 2)))
2954 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2955 memcpy(str1,
2956 String_val(Field(formItem, 0)),
2957 string_length(Field(formItem, 0)));
2958 str1[string_length(Field(formItem, 0))] = 0;
2959 conn->httpPostStrings =
2960 curl_slist_append(conn->httpPostStrings, str1);
2962 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2963 memcpy(str2,
2964 String_val(Field(formItem, 1)),
2965 string_length(Field(formItem, 1)));
2966 str2[string_length(Field(formItem, 1))] = 0;
2967 conn->httpPostStrings =
2968 curl_slist_append(conn->httpPostStrings, str2);
2970 contentType = Field(formItem, 2);
2972 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2973 memcpy(str3,
2974 String_val(Field(contentType, 0)),
2975 string_length(Field(contentType, 0)));
2976 str3[string_length(Field(contentType, 0))] = 0;
2977 conn->httpPostStrings =
2978 curl_slist_append(conn->httpPostStrings, str3);
2980 curl_formadd(&conn->httpPostFirst,
2981 &conn->httpPostLast,
2982 CURLFORM_PTRNAME,
2983 str1,
2984 CURLFORM_NAMELENGTH,
2985 string_length(Field(formItem, 0)),
2986 CURLFORM_FILE,
2987 str2,
2988 CURLFORM_CONTENTTYPE,
2989 str3,
2990 CURLFORM_END);
2992 else
2994 failwith("Incorrect CURLFORM_FILE parameters");
2996 break;
2998 case 3: /* CURLFORM_BUFFER */
2999 if (Wosize_val(formItem) < 4)
3001 failwith("Incorrect CURLFORM_BUFFER parameters");
3004 if (Is_long(Field(formItem, 3)) &&
3005 Long_val(Field(formItem, 3)) == 0)
3007 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3008 memcpy(str1,
3009 String_val(Field(formItem, 0)),
3010 string_length(Field(formItem, 0)));
3011 str1[string_length(Field(formItem, 0))] = 0;
3012 conn->httpPostStrings =
3013 curl_slist_append(conn->httpPostStrings, str1);
3015 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3016 memcpy(str2,
3017 String_val(Field(formItem, 1)),
3018 string_length(Field(formItem, 1)));
3019 str2[string_length(Field(formItem, 1))] = 0;
3020 conn->httpPostStrings =
3021 curl_slist_append(conn->httpPostStrings, str2);
3023 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3024 memcpy(str3,
3025 String_val(Field(formItem, 2)),
3026 string_length(Field(formItem, 2)));
3027 str3[string_length(Field(formItem, 2))] = 0;
3028 conn->httpPostStrings =
3029 curl_slist_append(conn->httpPostStrings, str3);
3031 curl_formadd(&conn->httpPostFirst,
3032 &conn->httpPostLast,
3033 CURLFORM_PTRNAME,
3034 str1,
3035 CURLFORM_NAMELENGTH,
3036 string_length(Field(formItem, 0)),
3037 CURLFORM_BUFFER,
3038 str2,
3039 CURLFORM_BUFFERPTR,
3040 str3,
3041 CURLFORM_BUFFERLENGTH,
3042 string_length(Field(formItem, 2)),
3043 CURLFORM_END);
3045 else if (Is_block(Field(formItem, 3)))
3047 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3048 memcpy(str1,
3049 String_val(Field(formItem, 0)),
3050 string_length(Field(formItem, 0)));
3051 str1[string_length(Field(formItem, 0))] = 0;
3052 conn->httpPostStrings =
3053 curl_slist_append(conn->httpPostStrings, str1);
3055 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3056 memcpy(str2,
3057 String_val(Field(formItem, 1)),
3058 string_length(Field(formItem, 1)));
3059 str2[string_length(Field(formItem, 1))] = 0;
3060 conn->httpPostStrings =
3061 curl_slist_append(conn->httpPostStrings, str2);
3063 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3064 memcpy(str3,
3065 String_val(Field(formItem, 2)),
3066 string_length(Field(formItem, 2)));
3067 str3[string_length(Field(formItem, 2))] = 0;
3068 conn->httpPostStrings =
3069 curl_slist_append(conn->httpPostStrings, str3);
3071 contentType = Field(formItem, 3);
3073 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
3074 memcpy(str4,
3075 String_val(Field(contentType, 0)),
3076 string_length(Field(contentType, 0)));
3077 str4[string_length(Field(contentType, 0))] = 0;
3078 conn->httpPostStrings =
3079 curl_slist_append(conn->httpPostStrings, str4);
3081 curl_formadd(&conn->httpPostFirst,
3082 &conn->httpPostLast,
3083 CURLFORM_PTRNAME,
3084 str1,
3085 CURLFORM_NAMELENGTH,
3086 string_length(Field(formItem, 0)),
3087 CURLFORM_BUFFER,
3088 str2,
3089 CURLFORM_BUFFERPTR,
3090 str3,
3091 CURLFORM_BUFFERLENGTH,
3092 string_length(Field(formItem, 2)),
3093 CURLFORM_CONTENTTYPE,
3094 str4,
3095 CURLFORM_END);
3097 else
3099 failwith("Incorrect CURLFORM_BUFFER parameters");
3101 break;
3104 listIter = Field(listIter, 1);
3107 result = curl_easy_setopt(conn->connection,
3108 CURLOPT_HTTPPOST,
3109 conn->httpPostFirst);
3111 if (result != CURLE_OK)
3112 raiseError(conn, result);
3114 CAMLreturn0;
3117 static void handleSSLCert(Connection *conn, value option)
3119 CAMLparam1(option);
3120 CURLcode result = CURLE_OK;
3122 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3124 if (conn->sslCert != NULL)
3125 free(conn->sslCert);
3127 conn->sslCert = strdup(String_val(option));
3129 result = curl_easy_setopt(conn->connection,
3130 CURLOPT_SSLCERT,
3131 conn->sslCert);
3133 if (result != CURLE_OK)
3134 raiseError(conn, result);
3136 CAMLreturn0;
3139 static void handleSSLCertType(Connection *conn, value option)
3141 CAMLparam1(option);
3142 CURLcode result = CURLE_OK;
3144 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3146 if (conn->sslCertType != NULL)
3147 free(conn->sslCertType);
3149 conn->sslCertType = strdup(String_val(option));
3151 result = curl_easy_setopt(conn->connection,
3152 CURLOPT_SSLCERTTYPE,
3153 conn->sslCertType);
3155 if (result != CURLE_OK)
3156 raiseError(conn, result);
3158 CAMLreturn0;
3161 static void handleSSLCertPasswd(Connection *conn, value option)
3163 CAMLparam1(option);
3164 CURLcode result = CURLE_OK;
3166 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3168 if (conn->sslCertPasswd != NULL)
3169 free(conn->sslCertPasswd);
3171 conn->sslCertPasswd = strdup(String_val(option));
3173 result = curl_easy_setopt(conn->connection,
3174 CURLOPT_SSLCERTPASSWD,
3175 conn->sslCertPasswd);
3177 if (result != CURLE_OK)
3178 raiseError(conn, result);
3180 CAMLreturn0;
3183 static void handleSSLKey(Connection *conn, value option)
3185 CAMLparam1(option);
3186 CURLcode result = CURLE_OK;
3188 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3190 if (conn->sslKey != NULL)
3191 free(conn->sslKey);
3193 conn->sslKey = strdup(String_val(option));
3195 result = curl_easy_setopt(conn->connection,
3196 CURLOPT_SSLKEY,
3197 conn->sslKey);
3199 if (result != CURLE_OK)
3200 raiseError(conn, result);
3202 CAMLreturn0;
3205 static void handleSSLKeyType(Connection *conn, value option)
3207 CAMLparam1(option);
3208 CURLcode result = CURLE_OK;
3210 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3212 if (conn->sslKeyType != NULL)
3213 free(conn->sslKeyType);
3215 conn->sslKeyType = strdup(String_val(option));
3217 result = curl_easy_setopt(conn->connection,
3218 CURLOPT_SSLKEYTYPE,
3219 conn->sslKeyType);
3221 if (result != CURLE_OK)
3222 raiseError(conn, result);
3224 CAMLreturn0;
3227 static void handleSSLKeyPasswd(Connection *conn, value option)
3229 CAMLparam1(option);
3230 CURLcode result = CURLE_OK;
3232 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3234 if (conn->sslKeyPasswd != NULL)
3235 free(conn->sslKeyPasswd);
3237 conn->sslKeyPasswd = strdup(String_val(option));
3239 result = curl_easy_setopt(conn->connection,
3240 CURLOPT_SSLKEYPASSWD,
3241 conn->sslKeyPasswd);
3243 if (result != CURLE_OK)
3244 raiseError(conn, result);
3246 CAMLreturn0;
3249 static void handleSSLEngine(Connection *conn, value option)
3251 CAMLparam1(option);
3252 CURLcode result = CURLE_OK;
3254 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3256 if (conn->sslEngine != NULL)
3257 free(conn->sslEngine);
3259 conn->sslEngine = strdup(String_val(option));
3261 result = curl_easy_setopt(conn->connection,
3262 CURLOPT_SSLENGINE,
3263 conn->sslEngine);
3265 if (result != CURLE_OK)
3266 raiseError(conn, result);
3268 CAMLreturn0;
3271 static void handleSSLEngineDefault(Connection *conn, value option)
3273 CAMLparam1(option);
3274 CURLcode result = CURLE_OK;
3276 result = curl_easy_setopt(conn->connection,
3277 CURLOPT_SSLENGINE_DEFAULT,
3278 Bool_val(option));
3280 if (result != CURLE_OK)
3281 raiseError(conn, result);
3283 CAMLreturn0;
3286 static void handleCRLF(Connection *conn, value option)
3288 CAMLparam1(option);
3289 CURLcode result = CURLE_OK;
3291 result = curl_easy_setopt(conn->connection,
3292 CURLOPT_CRLF,
3293 Bool_val(option));
3295 if (result != CURLE_OK)
3296 raiseError(conn, result);
3298 CAMLreturn0;
3301 static void handleQuote(Connection *conn, value option)
3303 CAMLparam1(option);
3304 CAMLlocal1(listIter);
3305 CURLcode result = CURLE_OK;
3307 Store_field(conn->ocamlValues, OcamlQuote, option);
3309 free_curl_slist(conn->quote);
3310 conn->quote = NULL;
3312 listIter = option;
3314 while (!Is_long(listIter))
3316 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3318 listIter = Field(listIter, 1);
3321 result = curl_easy_setopt(conn->connection,
3322 CURLOPT_QUOTE,
3323 conn->quote);
3325 if (result != CURLE_OK)
3326 raiseError(conn, result);
3328 CAMLreturn0;
3331 static void handlePostQuote(Connection *conn, value option)
3333 CAMLparam1(option);
3334 CAMLlocal1(listIter);
3335 CURLcode result = CURLE_OK;
3337 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3339 free_curl_slist(conn->postQuote);
3340 conn->postQuote = NULL;
3342 listIter = option;
3344 while (!Is_long(listIter))
3346 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3348 listIter = Field(listIter, 1);
3351 result = curl_easy_setopt(conn->connection,
3352 CURLOPT_POSTQUOTE,
3353 conn->postQuote);
3355 if (result != CURLE_OK)
3356 raiseError(conn, result);
3358 CAMLreturn0;
3361 static void handleHeaderFunction(Connection *conn, value option)
3363 CAMLparam1(option);
3364 CURLcode result = CURLE_OK;
3366 if (Tag_val(option) == Closure_tag)
3367 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3368 else
3369 failwith("Not a proper closure");
3371 result = curl_easy_setopt(conn->connection,
3372 CURLOPT_HEADERFUNCTION,
3373 headerFunction);
3375 if (result != CURLE_OK)
3376 raiseError(conn, result);
3378 result = curl_easy_setopt(conn->connection,
3379 CURLOPT_WRITEHEADER,
3380 conn);
3382 if (result != CURLE_OK)
3383 raiseError(conn, result);
3385 CAMLreturn0;
3388 static void handleCookieFile(Connection *conn, value option)
3390 CAMLparam1(option);
3391 CURLcode result = CURLE_OK;
3393 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3395 if (conn->cookieFile != NULL)
3396 free(conn->cookieFile);
3398 conn->cookieFile = strdup(String_val(option));
3400 result = curl_easy_setopt(conn->connection,
3401 CURLOPT_COOKIEFILE,
3402 conn->cookieFile);
3404 if (result != CURLE_OK)
3405 raiseError(conn, result);
3407 CAMLreturn0;
3410 static void handleSSLVersion(Connection *conn, value option)
3412 CAMLparam1(option);
3413 CURLcode result = CURLE_OK;
3415 result = curl_easy_setopt(conn->connection,
3416 CURLOPT_SSLVERSION,
3417 Long_val(option));
3419 if (result != CURLE_OK)
3420 raiseError(conn, result);
3422 CAMLreturn0;
3425 static void handleTimeCondition(Connection *conn, value option)
3427 CAMLparam1(option);
3428 CURLcode result = CURLE_OK;
3429 int timecond = CURL_TIMECOND_NONE;
3431 switch (Long_val(option))
3433 case 0: timecond = CURL_TIMECOND_NONE; break;
3434 case 1: timecond = CURL_TIMECOND_IFMODSINCE; break;
3435 case 2: timecond = CURL_TIMECOND_IFUNMODSINCE; break;
3436 case 3: timecond = CURL_TIMECOND_LASTMOD; break;
3437 default:
3438 failwith("Invalid TIMECOND Option");
3439 break;
3442 result = curl_easy_setopt(conn->connection, CURLOPT_TIMECONDITION, timecond);
3444 if (result != CURLE_OK)
3445 raiseError(conn, result);
3447 CAMLreturn0;
3450 static void handleTimeValue(Connection *conn, value option)
3452 CAMLparam1(option);
3453 CURLcode result = CURLE_OK;
3455 result = curl_easy_setopt(conn->connection,
3456 CURLOPT_TIMEVALUE,
3457 Int32_val(option));
3459 if (result != CURLE_OK)
3460 raiseError(conn, result);
3462 CAMLreturn0;
3465 static void handleCustomRequest(Connection *conn, value option)
3467 CAMLparam1(option);
3468 CURLcode result = CURLE_OK;
3470 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3472 if (conn->customRequest != NULL)
3473 free(conn->customRequest);
3475 conn->customRequest = strdup(String_val(option));
3477 result = curl_easy_setopt(conn->connection,
3478 CURLOPT_CUSTOMREQUEST,
3479 conn->customRequest);
3481 if (result != CURLE_OK)
3482 raiseError(conn, result);
3484 CAMLreturn0;
3487 static void handleInterface(Connection *conn, value option)
3489 CAMLparam1(option);
3490 CURLcode result = CURLE_OK;
3492 Store_field(conn->ocamlValues, OcamlInterface, option);
3494 if (conn->interface_ != NULL)
3495 free(conn->interface_);
3497 conn->interface_ = strdup(String_val(option));
3499 result = curl_easy_setopt(conn->connection,
3500 CURLOPT_INTERFACE,
3501 conn->interface_);
3503 if (result != CURLE_OK)
3504 raiseError(conn, result);
3506 CAMLreturn0;
3509 static void handleKRB4Level(Connection *conn, value option)
3511 CAMLparam1(option);
3512 CURLcode result = CURLE_OK;
3514 switch (Long_val(option))
3516 case 0: /* KRB4_NONE */
3517 result = curl_easy_setopt(conn->connection,
3518 CURLOPT_KRB4LEVEL,
3519 NULL);
3520 break;
3522 case 1: /* KRB4_CLEAR */
3523 result = curl_easy_setopt(conn->connection,
3524 CURLOPT_KRB4LEVEL,
3525 "clear");
3526 break;
3528 case 2: /* KRB4_SAFE */
3529 result = curl_easy_setopt(conn->connection,
3530 CURLOPT_KRB4LEVEL,
3531 "safe");
3532 break;
3534 case 3: /* KRB4_CONFIDENTIAL */
3535 result = curl_easy_setopt(conn->connection,
3536 CURLOPT_KRB4LEVEL,
3537 "confidential");
3538 break;
3540 case 4: /* KRB4_PRIVATE */
3541 result = curl_easy_setopt(conn->connection,
3542 CURLOPT_KRB4LEVEL,
3543 "private");
3544 break;
3546 default:
3547 failwith("Invalid KRB4 Option");
3548 break;
3551 if (result != CURLE_OK)
3552 raiseError(conn, result);
3554 CAMLreturn0;
3557 static void handleProgressFunction(Connection *conn, value option)
3559 CAMLparam1(option);
3560 CURLcode result = CURLE_OK;
3562 if (Tag_val(option) == Closure_tag)
3563 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3564 else
3565 failwith("Not a proper closure");
3567 result = curl_easy_setopt(conn->connection,
3568 CURLOPT_PROGRESSFUNCTION,
3569 progressFunction);
3570 if (result != CURLE_OK)
3571 raiseError(conn, result);
3573 result = curl_easy_setopt(conn->connection,
3574 CURLOPT_PROGRESSDATA,
3575 conn);
3577 if (result != CURLE_OK)
3578 raiseError(conn, result);
3580 CAMLreturn0;
3583 static void handleSSLVerifyPeer(Connection *conn, value option)
3585 CAMLparam1(option);
3586 CURLcode result = CURLE_OK;
3588 result = curl_easy_setopt(conn->connection,
3589 CURLOPT_SSL_VERIFYPEER,
3590 Bool_val(option));
3592 if (result != CURLE_OK)
3593 raiseError(conn, result);
3595 CAMLreturn0;
3598 static void handleCAInfo(Connection *conn, value option)
3600 CAMLparam1(option);
3601 CURLcode result = CURLE_OK;
3603 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3605 if (conn->caInfo != NULL)
3606 free(conn->caInfo);
3608 conn->caInfo = strdup(String_val(option));
3610 result = curl_easy_setopt(conn->connection,
3611 CURLOPT_CAINFO,
3612 conn->caInfo);
3614 if (result != CURLE_OK)
3615 raiseError(conn, result);
3617 CAMLreturn0;
3620 static void handleCAPath(Connection *conn, value option)
3622 CAMLparam1(option);
3623 CURLcode result = CURLE_OK;
3625 Store_field(conn->ocamlValues, OcamlCAPath, option);
3627 if (conn->caPath != NULL)
3628 free(conn->caPath);
3630 conn->caPath = strdup(String_val(option));
3632 result = curl_easy_setopt(conn->connection,
3633 CURLOPT_CAPATH,
3634 conn->caPath);
3636 if (result != CURLE_OK)
3637 raiseError(conn, result);
3639 CAMLreturn0;
3642 static void handleFileTime(Connection *conn, value option)
3644 CAMLparam1(option);
3645 CURLcode result = CURLE_OK;
3647 result = curl_easy_setopt(conn->connection,
3648 CURLOPT_FILETIME,
3649 Bool_val(option));
3651 if (result != CURLE_OK)
3652 raiseError(conn, result);
3654 CAMLreturn0;
3657 static void handleMaxRedirs(Connection *conn, value option)
3659 CAMLparam1(option);
3660 CURLcode result = CURLE_OK;
3662 result = curl_easy_setopt(conn->connection,
3663 CURLOPT_MAXREDIRS,
3664 Long_val(option));
3666 if (result != CURLE_OK)
3667 raiseError(conn, result);
3669 CAMLreturn0;
3672 static void handleMaxConnects(Connection *conn, value option)
3674 CAMLparam1(option);
3675 CURLcode result = CURLE_OK;
3677 result = curl_easy_setopt(conn->connection,
3678 CURLOPT_MAXCONNECTS,
3679 Long_val(option));
3681 if (result != CURLE_OK)
3682 raiseError(conn, result);
3684 CAMLreturn0;
3687 static void handleClosePolicy(Connection *conn, value option)
3689 CAMLparam1(option);
3690 CURLcode result = CURLE_OK;
3692 switch (Long_val(option))
3694 case 0: /* CLOSEPOLICY_OLDEST */
3695 result = curl_easy_setopt(conn->connection,
3696 CURLOPT_CLOSEPOLICY,
3697 CURLCLOSEPOLICY_OLDEST);
3698 break;
3700 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3701 result = curl_easy_setopt(conn->connection,
3702 CURLOPT_CLOSEPOLICY,
3703 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3704 break;
3706 default:
3707 failwith("Invalid CLOSEPOLICY Option");
3708 break;
3711 if (result != CURLE_OK)
3712 raiseError(conn, result);
3714 CAMLreturn0;
3717 static void handleFreshConnect(Connection *conn, value option)
3719 CAMLparam1(option);
3720 CURLcode result = CURLE_OK;
3722 result = curl_easy_setopt(conn->connection,
3723 CURLOPT_FRESH_CONNECT,
3724 Bool_val(option));
3726 if (result != CURLE_OK)
3727 raiseError(conn, result);
3729 CAMLreturn0;
3732 static void handleForbidReuse(Connection *conn, value option)
3734 CAMLparam1(option);
3735 CURLcode result = CURLE_OK;
3737 result = curl_easy_setopt(conn->connection,
3738 CURLOPT_FORBID_REUSE,
3739 Bool_val(option));
3741 if (result != CURLE_OK)
3742 raiseError(conn, result);
3744 CAMLreturn0;
3747 static void handleRandomFile(Connection *conn, value option)
3749 CAMLparam1(option);
3750 CURLcode result = CURLE_OK;
3752 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3754 if (conn->randomFile != NULL)
3755 free(conn->randomFile);
3757 conn->randomFile = strdup(String_val(option));
3759 result = curl_easy_setopt(conn->connection,
3760 CURLOPT_RANDOM_FILE,
3761 conn->randomFile);
3763 if (result != CURLE_OK)
3764 raiseError(conn, result);
3766 CAMLreturn0;
3769 static void handleEGDSocket(Connection *conn, value option)
3771 CAMLparam1(option);
3772 CURLcode result = CURLE_OK;
3774 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3776 if (conn->egdSocket != NULL)
3777 free(conn->egdSocket);
3779 conn->egdSocket = strdup(String_val(option));
3781 result = curl_easy_setopt(conn->connection,
3782 CURLOPT_EGDSOCKET,
3783 conn->egdSocket);
3785 if (result != CURLE_OK)
3786 raiseError(conn, result);
3788 CAMLreturn0;
3791 static void handleConnectTimeout(Connection *conn, value option)
3793 CAMLparam1(option);
3794 CURLcode result = CURLE_OK;
3796 result = curl_easy_setopt(conn->connection,
3797 CURLOPT_CONNECTTIMEOUT,
3798 Long_val(option));
3800 if (result != CURLE_OK)
3801 raiseError(conn, result);
3803 CAMLreturn0;
3806 static void handleHTTPGet(Connection *conn, value option)
3808 CAMLparam1(option);
3809 CURLcode result = CURLE_OK;
3811 result = curl_easy_setopt(conn->connection,
3812 CURLOPT_HTTPGET,
3813 Bool_val(option));
3815 if (result != CURLE_OK)
3816 raiseError(conn, result);
3818 CAMLreturn0;
3821 static void handleSSLVerifyHost(Connection *conn, value option)
3823 CAMLparam1(option);
3824 CURLcode result = CURLE_OK;
3826 switch (Long_val(option))
3828 case 0: /* SSLVERIFYHOST_NONE */
3829 case 1: /* SSLVERIFYHOST_EXISTENCE */
3830 case 2: /* SSLVERIFYHOST_HOSTNAME */
3831 result = curl_easy_setopt(conn->connection,
3832 CURLOPT_SSL_VERIFYHOST,
3833 /* map EXISTENCE to HOSTNAME */
3834 Long_val(option) == 0 ? 0 : 2);
3835 break;
3837 default:
3838 failwith("Invalid SSLVERIFYHOST Option");
3839 break;
3842 if (result != CURLE_OK)
3843 raiseError(conn, result);
3845 CAMLreturn0;
3848 static void handleCookieJar(Connection *conn, value option)
3850 CAMLparam1(option);
3851 CURLcode result = CURLE_OK;
3853 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3855 if (conn->cookieJar != NULL)
3856 free(conn->cookieJar);
3858 conn->cookieJar = strdup(String_val(option));
3860 result = curl_easy_setopt(conn->connection,
3861 CURLOPT_COOKIEJAR,
3862 conn->cookieJar);
3864 if (result != CURLE_OK)
3865 raiseError(conn, result);
3867 CAMLreturn0;
3870 static void handleSSLCipherList(Connection *conn, value option)
3872 CAMLparam1(option);
3873 CURLcode result = CURLE_OK;
3875 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3877 if (conn->sslCipherList != NULL)
3878 free(conn->sslCipherList);
3880 conn->sslCipherList = strdup(String_val(option));
3882 result = curl_easy_setopt(conn->connection,
3883 CURLOPT_SSL_CIPHER_LIST,
3884 conn->sslCipherList);
3886 if (result != CURLE_OK)
3887 raiseError(conn, result);
3889 CAMLreturn0;
3892 static void handleHTTPVersion(Connection *conn, value option)
3894 CAMLparam1(option);
3895 CURLcode result = CURLE_OK;
3897 switch (Long_val(option))
3899 case 0: /* HTTP_VERSION_NONE */
3900 result = curl_easy_setopt(conn->connection,
3901 CURLOPT_HTTP_VERSION,
3902 CURL_HTTP_VERSION_NONE);
3903 break;
3905 case 1: /* HTTP_VERSION_1_0 */
3906 result = curl_easy_setopt(conn->connection,
3907 CURLOPT_HTTP_VERSION,
3908 CURL_HTTP_VERSION_1_0);
3909 break;
3911 case 2: /* HTTP_VERSION_1_1 */
3912 result = curl_easy_setopt(conn->connection,
3913 CURLOPT_HTTP_VERSION,
3914 CURL_HTTP_VERSION_1_1);
3915 break;
3917 default:
3918 failwith("Invalid HTTP_VERSION Option");
3919 break;
3922 if (result != CURLE_OK)
3923 raiseError(conn, result);
3925 CAMLreturn0;
3928 static void handleFTPUseEPSV(Connection *conn, value option)
3930 CAMLparam1(option);
3931 CURLcode result = CURLE_OK;
3933 result = curl_easy_setopt(conn->connection,
3934 CURLOPT_FTP_USE_EPSV,
3935 Bool_val(option));
3937 if (result != CURLE_OK)
3938 raiseError(conn, result);
3940 CAMLreturn0;
3943 static void handleDNSCacheTimeout(Connection *conn, value option)
3945 CAMLparam1(option);
3946 CURLcode result = CURLE_OK;
3948 result = curl_easy_setopt(conn->connection,
3949 CURLOPT_DNS_CACHE_TIMEOUT,
3950 Long_val(option));
3952 if (result != CURLE_OK)
3953 raiseError(conn, result);
3955 CAMLreturn0;
3958 static void handleDNSUseGlobalCache(Connection *conn, value option)
3960 CAMLparam1(option);
3961 CURLcode result = CURLE_OK;
3963 result = curl_easy_setopt(conn->connection,
3964 CURLOPT_DNS_USE_GLOBAL_CACHE,
3965 Bool_val(option));
3967 if (result != CURLE_OK)
3968 raiseError(conn, result);
3970 CAMLreturn0;
3973 static void handleDebugFunction(Connection *conn, value option)
3975 CAMLparam1(option);
3976 CURLcode result = CURLE_OK;
3978 if (Tag_val(option) == Closure_tag)
3979 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3980 else
3981 failwith("Not a proper closure");
3983 result = curl_easy_setopt(conn->connection,
3984 CURLOPT_DEBUGFUNCTION,
3985 debugFunction);
3986 if (result != CURLE_OK)
3987 raiseError(conn, result);
3989 result = curl_easy_setopt(conn->connection,
3990 CURLOPT_DEBUGDATA,
3991 conn);
3993 if (result != CURLE_OK)
3994 raiseError(conn, result);
3996 CAMLreturn0;
3999 static void handlePrivate(Connection *conn, value option)
4001 #if HAVE_DECL_CURLOPT_PRIVATE
4002 CAMLparam1(option);
4003 CURLcode result = CURLE_OK;
4005 Store_field(conn->ocamlValues, OcamlPrivate, option);
4007 if (conn->private != NULL)
4008 free(conn->private);
4010 conn->private = strdup(String_val(option));
4012 result = curl_easy_setopt(conn->connection,
4013 CURLOPT_PRIVATE,
4014 conn->private);
4016 if (result != CURLE_OK)
4017 raiseError(conn, result);
4019 CAMLreturn0;
4020 #else
4021 #pragma message("libcurl does not implement CURLOPT_PRIVATE")
4022 failwith("libcurl does not implement CURLOPT_PRIVATE");
4023 #endif
4026 static void handleHTTP200Aliases(Connection *conn, value option)
4028 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
4029 CAMLparam1(option);
4030 CAMLlocal1(listIter);
4031 CURLcode result = CURLE_OK;
4033 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
4035 free_curl_slist(conn->http200Aliases);
4036 conn->http200Aliases = NULL;
4038 listIter = option;
4040 while (!Is_long(listIter))
4042 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
4044 listIter = Field(listIter, 1);
4047 result = curl_easy_setopt(conn->connection,
4048 CURLOPT_HTTP200ALIASES,
4049 conn->http200Aliases);
4051 if (result != CURLE_OK)
4052 raiseError(conn, result);
4054 CAMLreturn0;
4055 #else
4056 #pragma message("libcurl does not implement CURLOPT_HTTP200ALIASES")
4057 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
4058 #endif
4061 static void handleUnrestrictedAuth(Connection *conn, value option)
4063 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4064 CAMLparam1(option);
4065 CURLcode result = CURLE_OK;
4067 result = curl_easy_setopt(conn->connection,
4068 CURLOPT_UNRESTRICTED_AUTH,
4069 Bool_val(option));
4071 if (result != CURLE_OK)
4072 raiseError(conn, result);
4074 CAMLreturn0;
4075 #else
4076 #pragma message("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH")
4077 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4078 #endif
4081 static void handleFTPUseEPRT(Connection *conn, value option)
4083 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4084 CAMLparam1(option);
4085 CURLcode result = CURLE_OK;
4087 result = curl_easy_setopt(conn->connection,
4088 CURLOPT_FTP_USE_EPRT,
4089 Bool_val(option));
4091 if (result != CURLE_OK)
4092 raiseError(conn, result);
4094 CAMLreturn0;
4095 #else
4096 #pragma message("libcurl does not implement CURLOPT_FTP_USE_EPRT")
4097 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4098 #endif
4101 static void handleHTTPAuth(Connection *conn, value option)
4103 #if HAVE_DECL_CURLOPT_HTTPAUTH
4104 CAMLparam1(option);
4105 CAMLlocal1(listIter);
4106 CURLcode result = CURLE_OK;
4107 long auth = CURLAUTH_NONE;
4109 listIter = option;
4111 while (!Is_long(listIter))
4113 switch (Long_val(Field(listIter, 0)))
4115 case 0: /* CURLAUTH_BASIC */
4116 auth |= CURLAUTH_BASIC;
4117 break;
4119 case 1: /* CURLAUTH_DIGEST */
4120 auth |= CURLAUTH_DIGEST;
4121 break;
4123 case 2: /* CURLAUTH_GSSNEGOTIATE */
4124 auth |= CURLAUTH_GSSNEGOTIATE;
4125 break;
4127 case 3: /* CURLAUTH_NTLM */
4128 auth |= CURLAUTH_NTLM;
4129 break;
4131 case 4: /* CURLAUTH_ANY */
4132 auth |= CURLAUTH_ANY;
4133 break;
4135 case 5: /* CURLAUTH_ANYSAFE */
4136 auth |= CURLAUTH_ANYSAFE;
4137 break;
4139 default:
4140 failwith("Invalid HTTPAUTH Value");
4141 break;
4144 listIter = Field(listIter, 1);
4147 result = curl_easy_setopt(conn->connection,
4148 CURLOPT_HTTPAUTH,
4149 auth);
4151 if (result != CURLE_OK)
4152 raiseError(conn, result);
4154 CAMLreturn0;
4155 #else
4156 #pragma message("libcurl does not implement CURLOPT_HTTPAUTH")
4157 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4158 #endif
4161 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4163 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4164 CAMLparam1(option);
4165 CURLcode result = CURLE_OK;
4167 result = curl_easy_setopt(conn->connection,
4168 CURLOPT_FTP_CREATE_MISSING_DIRS,
4169 Bool_val(option));
4171 if (result != CURLE_OK)
4172 raiseError(conn, result);
4174 CAMLreturn0;
4175 #else
4176 #pragma message("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS")
4177 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4178 #endif
4181 static void handleProxyAuth(Connection *conn, value option)
4183 #if HAVE_DECL_CURLOPT_PROXYAUTH
4184 CAMLparam1(option);
4185 CAMLlocal1(listIter);
4186 CURLcode result = CURLE_OK;
4187 long auth = CURLAUTH_NONE;
4189 listIter = option;
4191 while (!Is_long(listIter))
4193 switch (Long_val(Field(listIter, 0)))
4195 case 0: /* CURLAUTH_BASIC */
4196 auth |= CURLAUTH_BASIC;
4197 break;
4199 case 1: /* CURLAUTH_DIGEST */
4200 auth |= CURLAUTH_DIGEST;
4201 break;
4203 case 2: /* CURLAUTH_GSSNEGOTIATE */
4204 auth |= CURLAUTH_GSSNEGOTIATE;
4205 break;
4207 case 3: /* CURLAUTH_NTLM */
4208 auth |= CURLAUTH_NTLM;
4209 break;
4211 case 4: /* CURLAUTH_ANY */
4212 auth |= CURLAUTH_ANY;
4213 break;
4215 case 5: /* CURLAUTH_ANYSAFE */
4216 auth |= CURLAUTH_ANYSAFE;
4217 break;
4219 default:
4220 failwith("Invalid HTTPAUTH Value");
4221 break;
4224 listIter = Field(listIter, 1);
4227 result = curl_easy_setopt(conn->connection,
4228 CURLOPT_PROXYAUTH,
4229 auth);
4231 if (result != CURLE_OK)
4232 raiseError(conn, result);
4234 CAMLreturn0;
4235 #else
4236 #pragma message("libcurl does not implement CURLOPT_PROXYAUTH")
4237 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4238 #endif
4241 static void handleFTPResponseTimeout(Connection *conn, value option)
4243 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4244 CAMLparam1(option);
4245 CURLcode result = CURLE_OK;
4247 result = curl_easy_setopt(conn->connection,
4248 CURLOPT_FTP_RESPONSE_TIMEOUT,
4249 Long_val(option));
4251 if (result != CURLE_OK)
4252 raiseError(conn, result);
4254 CAMLreturn0;
4255 #else
4256 #pragma message("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT")
4257 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4258 #endif
4261 static void handleIPResolve(Connection *conn, value option)
4263 #if HAVE_DECL_CURLOPT_IPRESOLVE
4264 CAMLparam1(option);
4265 CURLcode result = CURLE_OK;
4267 switch (Long_val(option))
4269 case 0: /* CURL_IPRESOLVE_WHATEVER */
4270 result = curl_easy_setopt(conn->connection,
4271 CURLOPT_IPRESOLVE,
4272 CURL_IPRESOLVE_WHATEVER);
4273 break;
4275 case 1: /* CURL_IPRESOLVE_V4 */
4276 result = curl_easy_setopt(conn->connection,
4277 CURLOPT_IPRESOLVE,
4278 CURL_IPRESOLVE_V4);
4279 break;
4281 case 2: /* CURL_IPRESOLVE_V6 */
4282 result = curl_easy_setopt(conn->connection,
4283 CURLOPT_IPRESOLVE,
4284 CURL_IPRESOLVE_V6);
4285 break;
4287 default:
4288 failwith("Invalid IPRESOLVE Value");
4289 break;
4292 if (result != CURLE_OK)
4293 raiseError(conn, result);
4295 CAMLreturn0;
4296 #else
4297 #pragma message("libcurl does not implement CURLOPT_IPRESOLVE")
4298 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4299 #endif
4302 static void handleMaxFileSize(Connection *conn, value option)
4304 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4305 CAMLparam1(option);
4306 CURLcode result = CURLE_OK;
4308 result = curl_easy_setopt(conn->connection,
4309 CURLOPT_MAXFILESIZE,
4310 Int32_val(option));
4312 if (result != CURLE_OK)
4313 raiseError(conn, result);
4315 CAMLreturn0;
4316 #else
4317 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE")
4318 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4319 #endif
4322 static void handleInFileSizeLarge(Connection *conn, value option)
4324 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4325 CAMLparam1(option);
4326 CURLcode result = CURLE_OK;
4328 result = curl_easy_setopt(conn->connection,
4329 CURLOPT_INFILESIZE_LARGE,
4330 Int64_val(option));
4332 if (result != CURLE_OK)
4333 raiseError(conn, result);
4335 CAMLreturn0;
4336 #else
4337 #pragma message("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4338 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4339 #endif
4342 static void handleResumeFromLarge(Connection *conn, value option)
4344 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4345 CAMLparam1(option);
4346 CURLcode result = CURLE_OK;
4348 result = curl_easy_setopt(conn->connection,
4349 CURLOPT_RESUME_FROM_LARGE,
4350 Int64_val(option));
4352 if (result != CURLE_OK)
4353 raiseError(conn, result);
4355 CAMLreturn0;
4356 #else
4357 #pragma message("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4358 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4359 #endif
4362 static void handleMaxFileSizeLarge(Connection *conn, value option)
4364 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4365 CAMLparam1(option);
4366 CURLcode result = CURLE_OK;
4368 result = curl_easy_setopt(conn->connection,
4369 CURLOPT_MAXFILESIZE_LARGE,
4370 Int64_val(option));
4372 if (result != CURLE_OK)
4373 raiseError(conn, result);
4375 CAMLreturn0;
4376 #else
4377 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE")
4378 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4379 #endif
4382 static void handleNETRCFile(Connection *conn, value option)
4384 #if HAVE_DECL_CURLOPT_NETRC_FILE
4385 CAMLparam1(option);
4386 CURLcode result = CURLE_OK;
4388 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4390 if (conn->netrcFile != NULL)
4391 free(conn->netrcFile);
4393 conn->netrcFile = strdup(String_val(option));
4395 result = curl_easy_setopt(conn->connection,
4396 CURLOPT_NETRC_FILE,
4397 conn->netrcFile);
4399 if (result != CURLE_OK)
4400 raiseError(conn, result);
4402 CAMLreturn0;
4403 #else
4404 #pragma message("libcurl does not implement CURLOPT_NETRC_FILE")
4405 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4406 #endif
4409 static void handleFTPSSL(Connection *conn, value option)
4411 #if HAVE_DECL_CURLOPT_FTP_SSL
4412 CAMLparam1(option);
4413 CURLcode result = CURLE_OK;
4415 switch (Long_val(option))
4417 case 0: /* CURLFTPSSL_NONE */
4418 result = curl_easy_setopt(conn->connection,
4419 CURLOPT_FTP_SSL,
4420 CURLFTPSSL_NONE);
4421 break;
4423 case 1: /* CURLFTPSSL_TRY */
4424 result = curl_easy_setopt(conn->connection,
4425 CURLOPT_FTP_SSL,
4426 CURLFTPSSL_TRY);
4427 break;
4429 case 2: /* CURLFTPSSL_CONTROL */
4430 result = curl_easy_setopt(conn->connection,
4431 CURLOPT_FTP_SSL,
4432 CURLFTPSSL_CONTROL);
4433 break;
4435 case 3: /* CURLFTPSSL_ALL */
4436 result = curl_easy_setopt(conn->connection,
4437 CURLOPT_FTP_SSL,
4438 CURLFTPSSL_ALL);
4439 break;
4441 default:
4442 failwith("Invalid FTP_SSL Value");
4443 break;
4446 if (result != CURLE_OK)
4447 raiseError(conn, result);
4449 CAMLreturn0;
4450 #else
4451 #pragma message("libcurl does not implement CURLOPT_FTP_SSL")
4452 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4453 #endif
4456 static void handlePostFieldSizeLarge(Connection *conn, value option)
4458 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4459 CAMLparam1(option);
4460 CURLcode result = CURLE_OK;
4462 result = curl_easy_setopt(conn->connection,
4463 CURLOPT_POSTFIELDSIZE_LARGE,
4464 Int64_val(option));
4466 if (result != CURLE_OK)
4467 raiseError(conn, result);
4469 CAMLreturn0;
4470 #else
4471 #pragma message("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE")
4472 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4473 #endif
4476 static void handleTCPNoDelay(Connection *conn, value option)
4478 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4479 CAMLparam1(option);
4480 CURLcode result = CURLE_OK;
4482 result = curl_easy_setopt(conn->connection,
4483 CURLOPT_TCP_NODELAY,
4484 Bool_val(option));
4486 if (result != CURLE_OK)
4487 raiseError(conn, result);
4489 CAMLreturn0;
4490 #else
4491 #pragma message("libcurl does not implement CURLOPT_TCP_NODELAY")
4492 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4493 #endif
4496 static void handleFTPSSLAuth(Connection *conn, value option)
4498 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4499 CAMLparam1(option);
4500 CURLcode result = CURLE_OK;
4502 switch (Long_val(option))
4504 case 0: /* CURLFTPAUTH_DEFAULT */
4505 result = curl_easy_setopt(conn->connection,
4506 CURLOPT_FTPSSLAUTH,
4507 CURLFTPAUTH_DEFAULT);
4508 break;
4510 case 1: /* CURLFTPAUTH_SSL */
4511 result = curl_easy_setopt(conn->connection,
4512 CURLOPT_FTPSSLAUTH,
4513 CURLFTPAUTH_SSL);
4514 break;
4516 case 2: /* CURLFTPAUTH_TLS */
4517 result = curl_easy_setopt(conn->connection,
4518 CURLOPT_FTPSSLAUTH,
4519 CURLFTPAUTH_TLS);
4520 break;
4522 default:
4523 failwith("Invalid FTPSSLAUTH value");
4524 break;
4527 if (result != CURLE_OK)
4528 raiseError(conn, result);
4530 CAMLreturn0;
4531 #else
4532 #pragma message("libcurl does not implement CURLOPT_FTPSSLAUTH")
4533 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4534 #endif
4537 static void handleIOCTLFunction(Connection *conn, value option)
4539 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4540 CAMLparam1(option);
4541 CURLcode result = CURLE_OK;
4543 if (Tag_val(option) == Closure_tag)
4544 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4545 else
4546 failwith("Not a proper closure");
4548 result = curl_easy_setopt(conn->connection,
4549 CURLOPT_IOCTLFUNCTION,
4550 ioctlFunction);
4551 if (result != CURLE_OK)
4552 raiseError(conn, result);
4554 result = curl_easy_setopt(conn->connection,
4555 CURLOPT_DEBUGDATA,
4556 conn);
4558 if (result != CURLE_OK)
4559 raiseError(conn, result);
4561 CAMLreturn0;
4562 #else
4563 #pragma message("libcurl does not implement CURLOPT_IOCTLFUNCTION")
4564 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4565 #endif
4568 static void handleFTPAccount(Connection *conn, value option)
4570 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4571 CAMLparam1(option);
4572 CURLcode result = CURLE_OK;
4574 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4576 if (conn->ftpaccount != NULL)
4577 free(conn->ftpaccount);
4579 conn->ftpaccount = strdup(String_val(option));
4581 result = curl_easy_setopt(conn->connection,
4582 CURLOPT_FTP_ACCOUNT,
4583 conn->ftpaccount);
4585 if (result != CURLE_OK)
4586 raiseError(conn, result);
4588 CAMLreturn0;
4589 #else
4590 #pragma message("libcurl does not implement CURLOPT_FTP_ACCOUNT")
4591 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4592 #endif
4595 static void handleCookieList(Connection *conn, value option)
4597 #if HAVE_DECL_CURLOPT_COOKIELIST
4598 CAMLparam1(option);
4599 CURLcode result = CURLE_OK;
4601 Store_field(conn->ocamlValues, OcamlCookieList, option);
4603 if (conn->cookielist != NULL)
4604 free(conn->cookielist);
4606 conn->cookielist = strdup(String_val(option));
4608 result = curl_easy_setopt(conn->connection,
4609 CURLOPT_COOKIELIST,
4610 conn->cookielist);
4612 if (result != CURLE_OK)
4613 raiseError(conn, result);
4615 CAMLreturn0;
4616 #else
4617 #pragma message("libcurl does not implement CURLOPT_COOKIELIST")
4618 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4619 #endif
4622 static void handleIgnoreContentLength(Connection *conn, value option)
4624 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4625 CAMLparam1(option);
4626 CURLcode result = CURLE_OK;
4628 result = curl_easy_setopt(conn->connection,
4629 CURLOPT_IGNORE_CONTENT_LENGTH,
4630 Bool_val(option));
4632 if (result != CURLE_OK)
4633 raiseError(conn, result);
4635 CAMLreturn0;
4636 #else
4637 #pragma message("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH")
4638 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4639 #endif
4642 static void handleFTPSkipPASVIP(Connection *conn, value option)
4644 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4645 CAMLparam1(option);
4646 CURLcode result = CURLE_OK;
4648 result = curl_easy_setopt(conn->connection,
4649 CURLOPT_FTP_SKIP_PASV_IP,
4650 Bool_val(option));
4652 if (result != CURLE_OK)
4653 raiseError(conn, result);
4655 CAMLreturn0;
4656 #else
4657 #pragma message("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP")
4658 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4659 #endif
4662 static void handleFTPFileMethod(Connection *conn, value option)
4664 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4665 CAMLparam1(option);
4666 CURLcode result = CURLE_OK;
4668 switch (Long_val(option))
4670 case 0: /* CURLFTPMETHOD_DEFAULT */
4671 result = curl_easy_setopt(conn->connection,
4672 CURLOPT_FTP_FILEMETHOD,
4673 CURLFTPMETHOD_DEFAULT);
4674 break;
4676 case 1: /* CURLFTMETHOD_MULTICWD */
4677 result = curl_easy_setopt(conn->connection,
4678 CURLOPT_FTP_FILEMETHOD,
4679 CURLFTPMETHOD_MULTICWD);
4680 break;
4682 case 2: /* CURLFTPMETHOD_NOCWD */
4683 result = curl_easy_setopt(conn->connection,
4684 CURLOPT_FTP_FILEMETHOD,
4685 CURLFTPMETHOD_NOCWD);
4686 break;
4688 case 3: /* CURLFTPMETHOD_SINGLECWD */
4689 result = curl_easy_setopt(conn->connection,
4690 CURLOPT_FTP_FILEMETHOD,
4691 CURLFTPMETHOD_SINGLECWD);
4693 default:
4694 failwith("Invalid FTP_FILEMETHOD value");
4695 break;
4698 if (result != CURLE_OK)
4699 raiseError(conn, result);
4701 CAMLreturn0;
4702 #else
4703 #pragma message("libcurl does not implement CURLOPT_FTP_FILEMETHOD")
4704 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4705 #endif
4708 static void handleLocalPort(Connection *conn, value option)
4710 #if HAVE_DECL_CURLOPT_LOCALPORT
4711 CAMLparam1(option);
4712 CURLcode result = CURLE_OK;
4714 result = curl_easy_setopt(conn->connection,
4715 CURLOPT_LOCALPORT,
4716 Long_val(option));
4718 if (result != CURLE_OK)
4719 raiseError(conn, result);
4721 CAMLreturn0;
4722 #else
4723 #pragma message("libcurl does not implement CURLOPT_LOCALPORT")
4724 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4725 #endif
4728 static void handleLocalPortRange(Connection *conn, value option)
4730 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4731 CAMLparam1(option);
4732 CURLcode result = CURLE_OK;
4734 result = curl_easy_setopt(conn->connection,
4735 CURLOPT_LOCALPORTRANGE,
4736 Long_val(option));
4738 if (result != CURLE_OK)
4739 raiseError(conn, result);
4741 CAMLreturn0;
4742 #else
4743 #pragma message("libcurl does not implement CURLOPT_LOCALPORTRANGE")
4744 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4745 #endif
4748 static void handleConnectOnly(Connection *conn, value option)
4750 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4751 CAMLparam1(option);
4752 CURLcode result = CURLE_OK;
4754 result = curl_easy_setopt(conn->connection,
4755 CURLOPT_CONNECT_ONLY,
4756 Bool_val(option));
4758 if (result != CURLE_OK)
4759 raiseError(conn, result);
4761 CAMLreturn0;
4762 #else
4763 #pragma message("libcurl does not implement CURLOPT_CONNECT_ONLY")
4764 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4765 #endif
4768 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4770 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4771 CAMLparam1(option);
4772 CURLcode result = CURLE_OK;
4774 result = curl_easy_setopt(conn->connection,
4775 CURLOPT_MAX_SEND_SPEED_LARGE,
4776 Int64_val(option));
4778 if (result != CURLE_OK)
4779 raiseError(conn, result);
4781 CAMLreturn0;
4782 #else
4783 #pragma message("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE")
4784 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4785 #endif
4788 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4790 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4791 CAMLparam1(option);
4792 CURLcode result = CURLE_OK;
4794 result = curl_easy_setopt(conn->connection,
4795 CURLOPT_MAX_RECV_SPEED_LARGE,
4796 Int64_val(option));
4798 if (result != CURLE_OK)
4799 raiseError(conn, result);
4801 CAMLreturn0;
4802 #else
4803 #pragma message("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE")
4804 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4805 #endif
4808 static void handleFTPAlternativeToUser(Connection *conn, value option)
4810 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4811 CAMLparam1(option);
4812 CURLcode result = CURLE_OK;
4814 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4816 if (conn->ftpAlternativeToUser != NULL)
4817 free(conn->ftpAlternativeToUser);
4819 conn->ftpAlternativeToUser = strdup(String_val(option));
4821 result = curl_easy_setopt(conn->connection,
4822 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4823 conn->ftpAlternativeToUser);
4825 if (result != CURLE_OK)
4826 raiseError(conn, result);
4828 CAMLreturn0;
4829 #else
4830 #pragma message("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER")
4831 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4832 #endif
4835 static void handleSSLSessionIdCache(Connection *conn, value option)
4837 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4838 CAMLparam1(option);
4839 CURLcode result = CURLE_OK;
4841 result = curl_easy_setopt(conn->connection,
4842 CURLOPT_SSL_SESSIONID_CACHE,
4843 Bool_val(option));
4845 if (result != CURLE_OK)
4846 raiseError(conn, result);
4848 CAMLreturn0;
4849 #else
4850 #pragma message("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE")
4851 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4852 #endif
4855 static void handleSSHAuthTypes(Connection *conn, value option)
4857 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4858 CAMLparam1(option);
4859 CAMLlocal1(listIter);
4860 CURLcode result = CURLE_OK;
4861 long authTypes = CURLSSH_AUTH_NONE;
4863 listIter = option;
4865 while (!Is_long(listIter))
4867 switch (Long_val(Field(listIter, 0)))
4869 case 0: /* CURLSSH_AUTH_ANY */
4870 authTypes |= CURLSSH_AUTH_ANY;
4871 break;
4873 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4874 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4875 break;
4877 case 2: /* CURLSSH_AUTH_PASSWORD */
4878 authTypes |= CURLSSH_AUTH_PASSWORD;
4879 break;
4881 case 3: /* CURLSSH_AUTH_HOST */
4882 authTypes |= CURLSSH_AUTH_HOST;
4883 break;
4885 case 4: /* CURLSSH_AUTH_KEYBOARD */
4886 authTypes |= CURLSSH_AUTH_KEYBOARD;
4887 break;
4889 default:
4890 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4891 break;
4894 listIter = Field(listIter, 1);
4897 result = curl_easy_setopt(conn->connection,
4898 CURLOPT_SSH_AUTH_TYPES,
4899 authTypes);
4901 if (result != CURLE_OK)
4902 raiseError(conn, result);
4904 CAMLreturn0;
4905 #else
4906 #pragma message("libcurl does not implement CURLOPT_SSH_AUTH_TYPES")
4907 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4908 #endif
4911 static void handleSSHPublicKeyFile(Connection *conn, value option)
4913 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4914 CAMLparam1(option);
4915 CURLcode result = CURLE_OK;
4917 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4919 if (conn->sshPublicKeyFile != NULL)
4920 free(conn->sshPublicKeyFile);
4922 conn->sshPublicKeyFile = strdup(String_val(option));
4924 result = curl_easy_setopt(conn->connection,
4925 CURLOPT_SSH_PUBLIC_KEYFILE,
4926 conn->sshPublicKeyFile);
4928 if (result != CURLE_OK)
4929 raiseError(conn, result);
4931 CAMLreturn0;
4932 #else
4933 #pragma message("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE")
4934 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4935 #endif
4938 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4940 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4941 CAMLparam1(option);
4942 CURLcode result = CURLE_OK;
4944 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4946 if (conn->sshPrivateKeyFile != NULL)
4947 free(conn->sshPrivateKeyFile);
4949 conn->sshPrivateKeyFile = strdup(String_val(option));
4951 result = curl_easy_setopt(conn->connection,
4952 CURLOPT_SSH_PRIVATE_KEYFILE,
4953 conn->sshPrivateKeyFile);
4955 if (result != CURLE_OK)
4956 raiseError(conn, result);
4958 CAMLreturn0;
4959 #else
4960 #pragma message("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE")
4961 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4962 #endif
4965 static void handleFTPSSLCCC(Connection *conn, value option)
4967 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4968 CAMLparam1(option);
4969 CURLcode result = CURLE_OK;
4971 switch (Long_val(option))
4973 case 0: /* CURLFTPSSL_CCC_NONE */
4974 result = curl_easy_setopt(conn->connection,
4975 CURLOPT_FTP_SSL_CCC,
4976 CURLFTPSSL_CCC_NONE);
4977 break;
4979 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4980 result = curl_easy_setopt(conn->connection,
4981 CURLOPT_FTP_SSL_CCC,
4982 CURLFTPSSL_CCC_PASSIVE);
4983 break;
4985 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4986 result = curl_easy_setopt(conn->connection,
4987 CURLOPT_FTP_SSL_CCC,
4988 CURLFTPSSL_CCC_ACTIVE);
4989 break;
4991 default:
4992 failwith("Invalid FTPSSL_CCC value");
4993 break;
4996 if (result != CURLE_OK)
4997 raiseError(conn, result);
4999 CAMLreturn0;
5000 #else
5001 #pragma message("libcurl does not implement CURLOPT_FTP_SSL_CCC")
5002 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
5003 #endif
5006 static void handleTimeoutMS(Connection *conn, value option)
5008 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
5009 CAMLparam1(option);
5010 CURLcode result = CURLE_OK;
5012 result = curl_easy_setopt(conn->connection,
5013 CURLOPT_TIMEOUT_MS,
5014 Long_val(option));
5016 if (result != CURLE_OK)
5017 raiseError(conn, result);
5019 CAMLreturn0;
5020 #else
5021 #pragma message("libcurl does not implement CURLOPT_TIMEOUT_MS")
5022 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
5023 #endif
5026 static void handleConnectTimeoutMS(Connection *conn, value option)
5028 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
5029 CAMLparam1(option);
5030 CURLcode result = CURLE_OK;
5032 result = curl_easy_setopt(conn->connection,
5033 CURLOPT_CONNECTTIMEOUT_MS,
5034 Long_val(option));
5036 if (result != CURLE_OK)
5037 raiseError(conn, result);
5039 CAMLreturn0;
5040 #else
5041 #pragma message("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS")
5042 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
5043 #endif
5046 static void handleHTTPTransferDecoding(Connection *conn, value option)
5048 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5049 CAMLparam1(option);
5050 CURLcode result = CURLE_OK;
5052 result = curl_easy_setopt(conn->connection,
5053 CURLOPT_HTTP_TRANSFER_DECODING,
5054 Bool_val(option));
5056 if (result != CURLE_OK)
5057 raiseError(conn, result);
5059 CAMLreturn0;
5060 #else
5061 #pragma message("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING")
5062 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
5063 #endif
5066 static void handleHTTPContentDecoding(Connection *conn, value option)
5068 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5069 CAMLparam1(option);
5070 CURLcode result = CURLE_OK;
5072 result = curl_easy_setopt(conn->connection,
5073 CURLOPT_HTTP_CONTENT_DECODING,
5074 Bool_val(option));
5076 if (result != CURLE_OK)
5077 raiseError(conn, result);
5079 CAMLreturn0;
5080 #else
5081 #pragma message("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING")
5082 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5083 #endif
5086 static void handleNewFilePerms(Connection *conn, value option)
5088 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5089 CAMLparam1(option);
5090 CURLcode result = CURLE_OK;
5092 result = curl_easy_setopt(conn->connection,
5093 CURLOPT_NEW_FILE_PERMS,
5094 Long_val(option));
5096 if (result != CURLE_OK)
5097 raiseError(conn, result);
5099 CAMLreturn0;
5100 #else
5101 #pragma message("libcurl does not implement CURLOPT_NEW_FILE_PERMS")
5102 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5103 #endif
5106 static void handleNewDirectoryPerms(Connection *conn, value option)
5108 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5109 CAMLparam1(option);
5110 CURLcode result = CURLE_OK;
5112 result = curl_easy_setopt(conn->connection,
5113 CURLOPT_NEW_DIRECTORY_PERMS,
5114 Long_val(option));
5116 if (result != CURLE_OK)
5117 raiseError(conn, result);
5119 CAMLreturn0;
5120 #else
5121 #pragma message("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS")
5122 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5123 #endif
5126 static void handlePost301(Connection *conn, value option)
5128 #if HAVE_DECL_CURLOPT_POST301
5129 CAMLparam1(option);
5130 CURLcode result = CURLE_OK;
5132 result = curl_easy_setopt(conn->connection,
5133 CURLOPT_POST301,
5134 Bool_val(option));
5136 if (result != CURLE_OK)
5137 raiseError(conn, result);
5139 CAMLreturn0;
5140 #else
5141 #pragma message("libcurl does not implement CURLOPT_POST301")
5142 failwith("libcurl does not implement CURLOPT_POST301");
5143 #endif
5146 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5148 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5149 CAMLparam1(option);
5150 CURLcode result = CURLE_OK;
5152 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5154 if (conn->sshHostPublicKeyMD5 != NULL)
5155 free(conn->sshHostPublicKeyMD5);
5157 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5159 result = curl_easy_setopt(conn->connection,
5160 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5161 conn->sshHostPublicKeyMD5);
5163 if (result != CURLE_OK)
5164 raiseError(conn, result);
5166 CAMLreturn0;
5167 #else
5168 #pragma message("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5")
5169 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5170 #endif
5173 static void handleCopyPostFields(Connection *conn, value option)
5175 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5176 CAMLparam1(option);
5177 CURLcode result = CURLE_OK;
5179 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5181 if (conn->copyPostFields != NULL)
5182 free(conn->copyPostFields);
5184 conn->copyPostFields = strdup(String_val(option));
5186 result = curl_easy_setopt(conn->connection,
5187 CURLOPT_COPYPOSTFIELDS,
5188 conn->copyPostFields);
5190 if (result != CURLE_OK)
5191 raiseError(conn, result);
5193 CAMLreturn0;
5194 #else
5195 #pragma message("libcurl does not implement CURLOPT_COPYPOSTFIELDS")
5196 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5197 #endif
5200 static void handleProxyTransferMode(Connection *conn, value option)
5202 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5203 CAMLparam1(option);
5204 CURLcode result = CURLE_OK;
5206 result = curl_easy_setopt(conn->connection,
5207 CURLOPT_PROXY_TRANSFER_MODE,
5208 Bool_val(option));
5210 if (result != CURLE_OK)
5211 raiseError(conn, result);
5213 CAMLreturn0;
5214 #else
5215 #pragma message("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE")
5216 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5217 #endif
5220 static void handleSeekFunction(Connection *conn, value option)
5222 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5223 CAMLparam1(option);
5224 CURLcode result = CURLE_OK;
5226 if (Tag_val(option) == Closure_tag)
5227 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5228 else
5229 failwith("Not a proper closure");
5231 result = curl_easy_setopt(conn->connection,
5232 CURLOPT_SEEKFUNCTION,
5233 seekFunction);
5235 if (result != CURLE_OK)
5236 raiseError(conn, result);
5238 result = curl_easy_setopt(conn->connection,
5239 CURLOPT_SEEKDATA,
5240 conn);
5242 if (result != CURLE_OK)
5243 raiseError(conn, result);
5245 CAMLreturn0;
5246 #else
5247 #pragma message("libcurl does not implement CURLOPT_SEEKFUNCTION")
5248 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5249 #endif
5252 static void handleAutoReferer(Connection *conn, value option)
5254 #if HAVE_DECL_CURLOPT_AUTOREFERER
5255 CAMLparam1(option);
5256 CURLcode result = curl_easy_setopt(conn->connection,
5257 CURLOPT_AUTOREFERER,
5258 Bool_val(option));
5260 if (result != CURLE_OK)
5261 raiseError(conn, result);
5263 CAMLreturn0;
5264 #else
5265 #pragma message("libcurl does not implement CURLOPT_AUTOREFERER")
5266 failwith("libcurl does not implement CURLOPT_AUTOREFERER");
5267 #endif
5270 static void handleOpenSocketFunction(Connection *conn, value option)
5272 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5273 CAMLparam1(option);
5274 CURLcode result = CURLE_OK;
5276 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5278 result = curl_easy_setopt(conn->connection,
5279 CURLOPT_OPENSOCKETDATA,
5280 conn);
5282 if (result != CURLE_OK)
5283 raiseError(conn, result);
5285 result = curl_easy_setopt(conn->connection,
5286 CURLOPT_OPENSOCKETFUNCTION,
5287 openSocketFunction);
5289 if (result != CURLE_OK)
5290 raiseError(conn, result);
5292 CAMLreturn0;
5293 #else
5294 #pragma message("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION")
5295 failwith("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION");
5296 #endif
5299 static void handleProxyType(Connection *conn, value option)
5301 #if HAVE_DECL_CURLOPT_PROXYTYPE
5302 CAMLparam1(option);
5303 CURLcode result = CURLE_OK;
5304 long proxy_type;
5306 switch (Long_val(option))
5308 case 0: proxy_type = CURLPROXY_HTTP; break;
5309 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5310 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5311 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5312 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5313 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5314 default:
5315 failwith("Invalid curl proxy type");
5318 result = curl_easy_setopt(conn->connection,
5319 CURLOPT_PROXYTYPE,
5320 proxy_type);
5322 if (result != CURLE_OK)
5323 raiseError(conn, result);
5325 CAMLreturn0;
5326 #else
5327 #pragma message("libcurl does not implement CURLOPT_PROXYTYPE")
5328 failwith("libcurl does not implement CURLOPT_PROXYTYPE");
5329 #endif
5332 #if HAVE_DECL_CURLOPT_PROTOCOLS && HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5334 long protoMap[] =
5336 CURLPROTO_ALL,
5337 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
5338 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
5339 /* factor out with autoconf? */
5340 #if defined(CURLPROTO_IMAP)
5341 CURLPROTO_IMAP,
5342 #else
5344 #endif
5345 #if defined(CURLPROTO_IMAPS)
5346 CURLPROTO_IMAPS,
5347 #else
5349 #endif
5350 #if defined(CURLPROTO_POP3)
5351 CURLPROTO_POP3,
5352 #else
5354 #endif
5355 #if defined(CURLPROTO_POP3S)
5356 CURLPROTO_POP3S,
5357 #else
5359 #endif
5360 #if defined(CURLPROTO_SMTP)
5361 CURLPROTO_SMTP,
5362 #else
5364 #endif
5365 #if defined(CURLPROTO_SMTPS)
5366 CURLPROTO_SMTPS,
5367 #else
5369 #endif
5370 #if defined(CURLPROTO_RTSP)
5371 CURLPROTO_RTSP,
5372 #else
5374 #endif
5375 #if defined(CURLPROTO_RTMP)
5376 CURLPROTO_RTMP,
5377 #else
5379 #endif
5380 #if defined(CURLPROTO_RTMPT)
5381 CURLPROTO_RTMPT,
5382 #else
5384 #endif
5385 #if defined(CURLPROTO_RTMPE)
5386 CURLPROTO_RTMPE,
5387 #else
5389 #endif
5390 #if defined(CURLPROTO_RTMPTE)
5391 CURLPROTO_RTMPTE,
5392 #else
5394 #endif
5395 #if defined(CURLPROTO_RTMPS)
5396 CURLPROTO_RTMPS,
5397 #else
5399 #endif
5400 #if defined(CURLPROTO_RTMPTS)
5401 CURLPROTO_RTMPTS,
5402 #else
5404 #endif
5405 #if defined(CURLPROTO_GOPHER)
5406 CURLPROTO_GOPHER,
5407 #else
5409 #endif
5412 static void handleProtocolsOption(CURLoption curlopt, Connection *conn, value option)
5414 CAMLparam1(option);
5415 CURLcode result = CURLE_OK;
5416 long protocols = 0;
5417 int index;
5419 while (Val_emptylist != option)
5421 index = Int_val(Field(option, 0));
5422 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
5423 failwith("Invalid curl protocol");
5425 protocols = protocols | protoMap[index];
5427 option = Field(option, 1);
5430 result = curl_easy_setopt(conn->connection,
5431 curlopt,
5432 protocols);
5434 if (result != CURLE_OK)
5435 raiseError(conn, result);
5437 CAMLreturn0;
5440 static void handleProtocols(Connection *conn, value option)
5442 handleProtocolsOption(CURLOPT_PROTOCOLS, conn, option);
5445 static void handleRedirProtocols(Connection *conn, value option)
5447 handleProtocolsOption(CURLOPT_REDIR_PROTOCOLS, conn, option);
5450 #else
5451 #pragma message("libcurl does not implement CURLOPT_PROTOCOLS or CURLOPT_REDIR_PROTOCOLS")
5452 static void handleProtocols(Connection *conn, value option)
5454 failwith("libcurl does not implement CURLOPT_PROTOCOLS");
5456 static void handleRedirProtocols(Connection *conn, value option)
5458 failwith("libcurl does not implement CURLOPT_REDIR_PROTOCOLS");
5460 #endif
5462 #if HAVE_DECL_CURLOPT_RESOLVE
5463 static void handleResolve(Connection *conn, value option)
5465 CAMLparam1(option);
5466 CAMLlocal1(head);
5468 CURLcode result = CURLE_OK;
5470 free_curl_slist(conn->resolve);
5471 conn->resolve = NULL;
5473 head = option;
5475 while (head != Val_emptylist)
5477 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
5478 head = Field(head, 1);
5481 result = curl_easy_setopt(conn->connection,
5482 CURLOPT_RESOLVE,
5483 conn->resolve);
5485 if (result != CURLE_OK)
5486 raiseError(conn, result);
5488 CAMLreturn0;
5491 #else
5492 #pragma message("libcurl does not implement CURLOPT_RESOLVE")
5493 static void handleResolve(Connection *conn, value option)
5495 failwith("libcurl does not implement CURLOPT_RESOLVE");
5497 #endif
5499 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5500 static void handleDnsServers(Connection *conn, value option)
5502 CAMLparam1(option);
5504 Store_field(conn->ocamlValues, OcamlDNSServers, option);
5506 CURLcode result = CURLE_OK;
5507 free_if(conn->dns_servers);
5509 conn->dns_servers = strdup(String_val(option));
5511 result = curl_easy_setopt(conn->connection,
5512 CURLOPT_DNS_SERVERS,
5513 conn->dns_servers);
5515 if (result != CURLE_OK)
5516 raiseError(conn, result);
5518 CAMLreturn0;
5520 #else
5521 #pragma message("libcurl does not implement CURLOPT_DNS_SERVERS")
5522 static void handleDnsServers(Connection *conn, value option)
5524 failwith("libcurl does not implement CURLOPT_DNS_SERVERS");
5526 #endif
5529 ** curl_easy_setopt helper function
5532 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5534 CAMLparam2(conn, option);
5535 CAMLlocal1(data);
5536 Connection *connection = Connection_val(conn);
5538 checkConnection(connection);
5540 if (Is_long(option))
5542 char error[128];
5544 sprintf(error, "Unimplemented Option: %s",
5545 findOption(unimplementedOptionMap,
5546 (CURLoption)(Long_val(option))));
5548 failwith(error);
5551 if (!Is_block(option))
5552 failwith("Not a block");
5554 if (Wosize_val(option) < 1)
5555 failwith("Insufficient data in block");
5557 data = Field(option, 0);
5559 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5560 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5561 data);
5562 else
5563 failwith("Invalid CURLOPT Option");
5565 CAMLreturn(Val_unit);
5569 ** curl_easy_perform helper function
5572 CAMLprim value helper_curl_easy_perform(value conn)
5574 CAMLparam1(conn);
5575 CURLcode result = CURLE_OK;
5576 Connection *connection = Connection_val(conn);
5578 checkConnection(connection);
5580 enter_blocking_section();
5581 result = curl_easy_perform(connection->connection);
5582 leave_blocking_section();
5584 if (result != CURLE_OK)
5585 raiseError(connection, result);
5587 CAMLreturn(Val_unit);
5591 ** curl_easy_cleanup helper function
5594 CAMLprim value helper_curl_easy_cleanup(value conn)
5596 CAMLparam1(conn);
5597 Connection *connection = Connection_val(conn);
5599 checkConnection(connection);
5601 removeConnection(connection, 0);
5603 CAMLreturn(Val_unit);
5607 ** curl_easy_duphandle helper function
5610 CAMLprim value helper_curl_easy_duphandle(value conn)
5612 CAMLparam1(conn);
5613 CAMLlocal1(result);
5614 Connection *connection = Connection_val(conn);
5616 checkConnection(connection);
5618 result = caml_curl_alloc(duplicateConnection(connection));
5620 CAMLreturn(result);
5624 ** curl_easy_getinfo helper function
5627 enum GetInfoResultType {
5628 StringValue, LongValue, DoubleValue, StringListValue
5631 value convertStringList(struct curl_slist *slist)
5633 CAMLparam0();
5634 CAMLlocal3(result, current, next);
5635 struct curl_slist *p = slist;
5637 result = Val_int(0);
5638 current = Val_int(0);
5639 next = Val_int(0);
5641 while (p != NULL)
5643 next = alloc_tuple(2);
5644 Store_field(next, 0, copy_string(p->data));
5645 Store_field(next, 1, Val_int(0));
5647 if (result == Val_int(0))
5648 result = next;
5650 if (current != Val_int(0))
5651 Store_field(current, 1, next);
5653 current = next;
5655 p = p->next;
5658 curl_slist_free_all(slist);
5660 CAMLreturn(result);
5663 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5665 CAMLparam2(conn, option);
5666 CAMLlocal1(result);
5667 CURLcode curlResult;
5668 Connection *connection = Connection_val(conn);
5669 enum GetInfoResultType resultType;
5670 char *strValue = NULL;
5671 double doubleValue;
5672 long longValue;
5673 struct curl_slist *stringListValue = NULL;
5675 checkConnection(connection);
5677 switch(Long_val(option))
5679 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5680 case 0: /* CURLINFO_EFFECTIVE_URL */
5681 resultType = StringValue;
5683 curlResult = curl_easy_getinfo(connection->connection,
5684 CURLINFO_EFFECTIVE_URL,
5685 &strValue);
5686 break;
5687 #else
5688 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5689 #endif
5691 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5692 case 1: /* CURLINFO_HTTP_CODE */
5693 case 2: /* CURLINFO_RESPONSE_CODE */
5694 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5695 resultType = LongValue;
5697 curlResult = curl_easy_getinfo(connection->connection,
5698 CURLINFO_RESPONSE_CODE,
5699 &longValue);
5700 #else
5701 resultType = LongValue;
5703 curlResult = curl_easy_getinfo(connection->connection,
5704 CURLINFO_HTTP_CODE,
5705 &longValue);
5706 #endif
5707 break;
5708 #endif
5710 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5711 case 3: /* CURLINFO_TOTAL_TIME */
5712 resultType = DoubleValue;
5714 curlResult = curl_easy_getinfo(connection->connection,
5715 CURLINFO_TOTAL_TIME,
5716 &doubleValue);
5717 break;
5718 #endif
5720 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5721 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5722 resultType = DoubleValue;
5724 curlResult = curl_easy_getinfo(connection->connection,
5725 CURLINFO_NAMELOOKUP_TIME,
5726 &doubleValue);
5727 break;
5728 #endif
5730 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5731 case 5: /* CURLINFO_CONNECT_TIME */
5732 resultType = DoubleValue;
5734 curlResult = curl_easy_getinfo(connection->connection,
5735 CURLINFO_CONNECT_TIME,
5736 &doubleValue);
5737 break;
5738 #endif
5740 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5741 case 6: /* CURLINFO_PRETRANSFER_TIME */
5742 resultType = DoubleValue;
5744 curlResult = curl_easy_getinfo(connection->connection,
5745 CURLINFO_PRETRANSFER_TIME,
5746 &doubleValue);
5747 break;
5748 #endif
5750 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5751 case 7: /* CURLINFO_SIZE_UPLOAD */
5752 resultType = DoubleValue;
5754 curlResult = curl_easy_getinfo(connection->connection,
5755 CURLINFO_SIZE_UPLOAD,
5756 &doubleValue);
5757 break;
5758 #endif
5760 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5761 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5762 resultType = DoubleValue;
5764 curlResult = curl_easy_getinfo(connection->connection,
5765 CURLINFO_SIZE_DOWNLOAD,
5766 &doubleValue);
5767 break;
5768 #endif
5770 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5771 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5772 resultType = DoubleValue;
5774 curlResult = curl_easy_getinfo(connection->connection,
5775 CURLINFO_SPEED_DOWNLOAD,
5776 &doubleValue);
5777 break;
5778 #endif
5780 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5781 case 10: /* CURLINFO_SPEED_UPLOAD */
5782 resultType = DoubleValue;
5784 curlResult = curl_easy_getinfo(connection->connection,
5785 CURLINFO_SPEED_UPLOAD,
5786 &doubleValue);
5787 break;
5789 #endif
5791 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5792 case 11: /* CURLINFO_HEADER_SIZE */
5793 resultType = LongValue;
5795 curlResult = curl_easy_getinfo(connection->connection,
5796 CURLINFO_HEADER_SIZE,
5797 &longValue);
5798 break;
5799 #endif
5801 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5802 case 12: /* CURLINFO_REQUEST_SIZE */
5803 resultType = LongValue;
5805 curlResult = curl_easy_getinfo(connection->connection,
5806 CURLINFO_REQUEST_SIZE,
5807 &longValue);
5808 break;
5809 #endif
5811 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5812 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5813 resultType = LongValue;
5815 curlResult = curl_easy_getinfo(connection->connection,
5816 CURLINFO_SSL_VERIFYRESULT,
5817 &longValue);
5818 break;
5819 #endif
5821 #if HAVE_DECL_CURLINFO_FILETIME
5822 case 14: /* CURLINFO_FILETIME */
5823 resultType = DoubleValue;
5825 curlResult = curl_easy_getinfo(connection->connection,
5826 CURLINFO_FILETIME,
5827 &longValue);
5829 doubleValue = longValue;
5830 break;
5831 #endif
5833 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5834 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5835 resultType = DoubleValue;
5837 curlResult = curl_easy_getinfo(connection->connection,
5838 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5839 &doubleValue);
5840 break;
5841 #endif
5843 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5844 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5845 resultType = DoubleValue;
5847 curlResult = curl_easy_getinfo(connection->connection,
5848 CURLINFO_CONTENT_LENGTH_UPLOAD,
5849 &doubleValue);
5850 break;
5851 #endif
5853 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5854 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5855 resultType = DoubleValue;
5857 curlResult = curl_easy_getinfo(connection->connection,
5858 CURLINFO_STARTTRANSFER_TIME,
5859 &doubleValue);
5860 break;
5861 #endif
5863 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5864 case 18: /* CURLINFO_CONTENT_TYPE */
5865 resultType = StringValue;
5867 curlResult = curl_easy_getinfo(connection->connection,
5868 CURLINFO_CONTENT_TYPE,
5869 &strValue);
5870 break;
5871 #endif
5873 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5874 case 19: /* CURLINFO_REDIRECT_TIME */
5875 resultType = DoubleValue;
5877 curlResult = curl_easy_getinfo(connection->connection,
5878 CURLINFO_REDIRECT_TIME,
5879 &doubleValue);
5880 break;
5881 #endif
5883 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5884 case 20: /* CURLINFO_REDIRECT_COUNT */
5885 resultType = LongValue;
5887 curlResult = curl_easy_getinfo(connection->connection,
5888 CURLINFO_REDIRECT_COUNT,
5889 &longValue);
5890 break;
5891 #endif
5893 #if HAVE_DECL_CURLINFO_PRIVATE
5894 case 21: /* CURLINFO_PRIVATE */
5895 resultType = StringValue;
5897 curlResult = curl_easy_getinfo(connection->connection,
5898 CURLINFO_PRIVATE,
5899 &strValue);
5900 break;
5901 #endif
5903 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5904 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5905 resultType = LongValue;
5907 curlResult = curl_easy_getinfo(connection->connection,
5908 CURLINFO_HTTP_CONNECTCODE,
5909 &longValue);
5910 break;
5911 #endif
5913 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5914 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5915 resultType = LongValue;
5917 curlResult = curl_easy_getinfo(connection->connection,
5918 CURLINFO_HTTPAUTH_AVAIL,
5919 &longValue);
5920 break;
5921 #endif
5923 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5924 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5925 resultType = LongValue;
5927 curlResult = curl_easy_getinfo(connection->connection,
5928 CURLINFO_PROXYAUTH_AVAIL,
5929 &longValue);
5930 break;
5931 #endif
5933 #if HAVE_DECL_CURLINFO_OS_ERRNO
5934 case 25: /* CURLINFO_OS_ERRNO */
5935 resultType = LongValue;
5937 curlResult = curl_easy_getinfo(connection->connection,
5938 CURLINFO_OS_ERRNO,
5939 &longValue);
5940 break;
5941 #endif
5943 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5944 case 26: /* CURLINFO_NUM_CONNECTS */
5945 resultType = LongValue;
5947 curlResult = curl_easy_getinfo(connection->connection,
5948 CURLINFO_NUM_CONNECTS,
5949 &longValue);
5950 break;
5951 #endif
5953 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5954 case 27: /* CURLINFO_SSL_ENGINES */
5955 resultType = StringListValue;
5957 curlResult = curl_easy_getinfo(connection->connection,
5958 CURLINFO_SSL_ENGINES,
5959 &stringListValue);
5960 break;
5961 #endif
5963 #if HAVE_DECL_CURLINFO_COOKIELIST
5964 case 28: /* CURLINFO_COOKIELIST */
5965 resultType = StringListValue;
5967 curlResult = curl_easy_getinfo(connection->connection,
5968 CURLINFO_COOKIELIST,
5969 &stringListValue);
5970 break;
5971 #endif
5973 #if HAVE_DECL_CURLINFO_LASTSOCKET
5974 case 29: /* CURLINFO_LASTSOCKET */
5975 resultType = LongValue;
5977 curlResult = curl_easy_getinfo(connection->connection,
5978 CURLINFO_LASTSOCKET,
5979 &longValue);
5980 break;
5981 #endif
5983 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5984 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5985 resultType = StringValue;
5987 curlResult = curl_easy_getinfo(connection->connection,
5988 CURLINFO_FTP_ENTRY_PATH,
5989 &strValue);
5990 break;
5991 #endif
5993 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5994 case 31: /* CURLINFO_REDIRECT_URL */
5995 resultType = StringValue;
5997 curlResult = curl_easy_getinfo(connection->connection,
5998 CURLINFO_REDIRECT_URL,
5999 &strValue);
6000 break;
6001 #else
6002 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
6003 #endif
6005 #if HAVE_DECL_CURLINFO_PRIMARY_IP
6006 case 32: /* CURLINFO_PRIMARY_IP */
6007 resultType = StringValue;
6009 curlResult = curl_easy_getinfo(connection->connection,
6010 CURLINFO_PRIMARY_IP,
6011 &strValue);
6012 break;
6013 #else
6014 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
6015 #endif
6017 #if HAVE_DECL_CURLINFO_LOCAL_IP
6018 case 33: /* CURLINFO_LOCAL_IP */
6019 resultType = StringValue;
6021 curlResult = curl_easy_getinfo(connection->connection,
6022 CURLINFO_LOCAL_IP,
6023 &strValue);
6024 break;
6025 #else
6026 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
6027 #endif
6029 #if HAVE_DECL_CURLINFO_LOCAL_PORT
6030 case 34: /* CURLINFO_LOCAL_PORT */
6031 resultType = LongValue;
6033 curlResult = curl_easy_getinfo(connection->connection,
6034 CURLINFO_LOCAL_PORT,
6035 &longValue);
6036 break;
6037 #else
6038 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
6039 #endif
6041 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
6042 case 35: /* CURLINFO_CONDITION_UNMET */
6043 resultType = LongValue;
6045 curlResult = curl_easy_getinfo(connection->connection,
6046 CURLINFO_CONDITION_UNMET,
6047 &longValue);
6048 break;
6049 #else
6050 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
6051 #endif
6053 default:
6054 failwith("Invalid CURLINFO Option");
6055 break;
6058 if (curlResult != CURLE_OK)
6059 raiseError(connection, curlResult);
6061 switch (resultType)
6063 case StringValue:
6064 result = alloc(1, StringValue);
6065 Store_field(result, 0, copy_string(strValue?strValue:""));
6066 break;
6068 case LongValue:
6069 result = alloc(1, LongValue);
6070 Store_field(result, 0, Val_long(longValue));
6071 break;
6073 case DoubleValue:
6074 result = alloc(1, DoubleValue);
6075 Store_field(result, 0, copy_double(doubleValue));
6076 break;
6078 case StringListValue:
6079 result = alloc(1, StringListValue);
6080 Store_field(result, 0, convertStringList(stringListValue));
6081 break;
6084 CAMLreturn(result);
6088 ** curl_escape helper function
6091 CAMLprim value helper_curl_escape(value str)
6093 CAMLparam1(str);
6094 CAMLlocal1(result);
6095 char *curlResult;
6097 curlResult = curl_escape(String_val(str), string_length(str));
6098 result = copy_string(curlResult);
6099 free(curlResult);
6101 CAMLreturn(result);
6105 ** curl_unescape helper function
6108 CAMLprim value helper_curl_unescape(value str)
6110 CAMLparam1(str);
6111 CAMLlocal1(result);
6112 char *curlResult;
6114 curlResult = curl_unescape(String_val(str), string_length(str));
6115 result = copy_string(curlResult);
6116 free(curlResult);
6118 CAMLreturn(result);
6122 ** curl_getdate helper function
6125 CAMLprim value helper_curl_getdate(value str, value now)
6127 CAMLparam2(str, now);
6128 CAMLlocal1(result);
6129 time_t curlResult;
6130 time_t curlNow;
6132 curlNow = (time_t)Double_val(now);
6133 curlResult = curl_getdate(String_val(str), &curlNow);
6134 result = copy_double((double)curlResult);
6136 CAMLreturn(result);
6140 ** curl_version helper function
6143 CAMLprim value helper_curl_version(void)
6145 CAMLparam0();
6146 CAMLlocal1(result);
6147 char *str;
6149 str = curl_version();
6150 result = copy_string(str);
6152 CAMLreturn(result);
6155 struct CURLVersionBitsMapping
6157 int code;
6158 char *name;
6161 struct CURLVersionBitsMapping versionBitsMap[] =
6163 {CURL_VERSION_IPV6, "ipv6"},
6164 {CURL_VERSION_KERBEROS4, "kerberos4"},
6165 {CURL_VERSION_SSL, "ssl"},
6166 {CURL_VERSION_LIBZ, "libz"},
6167 {CURL_VERSION_NTLM, "ntlm"},
6168 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
6169 {CURL_VERSION_DEBUG, "debug"},
6170 {CURL_VERSION_CURLDEBUG, "curldebug"},
6171 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
6172 {CURL_VERSION_SPNEGO, "spnego"},
6173 {CURL_VERSION_LARGEFILE, "largefile"},
6174 {CURL_VERSION_IDN, "idn"},
6175 {CURL_VERSION_SSPI, "sspi"},
6176 {CURL_VERSION_CONV, "conv"},
6177 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
6178 {CURL_VERSION_TLSAUTH_SRP, "srp"},
6179 #endif
6180 #if HAVE_DECL_CURL_VERSION_NTLM_WB
6181 {CURL_VERSION_NTLM_WB, "wb"},
6182 #endif
6185 CAMLprim value caml_curl_version_info(value unit)
6187 CAMLparam1(unit);
6188 CAMLlocal4(v, vlist, vnum, vfeatures);
6189 const char* const* p = NULL;
6190 size_t i = 0;
6192 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
6193 if (NULL == data) caml_failwith("curl_version_info");
6195 vlist = Val_emptylist;
6196 for (p = data->protocols; NULL != *p; p++)
6198 vlist = Val_cons(vlist, caml_copy_string(*p));
6201 vfeatures = Val_emptylist;
6202 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
6204 if (0 != (versionBitsMap[i].code & data->features))
6205 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
6208 vnum = caml_alloc_tuple(3);
6209 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
6210 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
6211 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
6213 v = caml_alloc_tuple(12);
6214 Store_field(v,0,caml_copy_string(data->version));
6215 Store_field(v,1,vnum);
6216 Store_field(v,2,caml_copy_string(data->host));
6217 Store_field(v,3,vfeatures);
6218 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
6219 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
6220 Store_field(v,6,vlist);
6221 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
6222 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
6223 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
6224 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
6225 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
6227 CAMLreturn(v);
6230 CAMLprim value caml_curl_pause(value conn, value opts)
6232 CAMLparam2(conn, opts);
6233 CAMLlocal4(v, vlist, vnum, vfeatures);
6234 Connection *connection = Connection_val(conn);
6235 int bitmask = 0;
6236 CURLcode result;
6238 while (Val_emptylist != opts)
6240 switch (Int_val(Field(opts,0)))
6242 case 0: bitmask |= CURLPAUSE_SEND; break;
6243 case 1: bitmask |= CURLPAUSE_RECV; break;
6244 case 2: bitmask |= CURLPAUSE_ALL; break;
6245 default: caml_failwith("wrong pauseOption");
6247 opts = Field(opts,1);
6250 result = curl_easy_pause(connection->connection,bitmask);
6251 if (result != CURLE_OK)
6252 raiseError(connection, result);
6254 CAMLreturn(Val_unit);
6258 * Curl multi stack support
6260 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6261 * Other exported functions are prefixed with caml_curlm_, some of them
6262 * can/should be decomposed into smaller parts.
6265 struct ml_multi_handle
6267 CURLM* handle;
6268 value values; /* callbacks */
6271 enum
6273 curlmopt_socket_function,
6274 curlmopt_timer_function,
6276 /* last, not used */
6277 multi_values_total
6280 typedef struct ml_multi_handle ml_multi_handle;
6282 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6283 #define CURLM_val(v) (Multi_val(v)->handle)
6285 static struct custom_operations curl_multi_ops = {
6286 "ygrek.curl_multi",
6287 custom_finalize_default,
6288 custom_compare_default,
6289 custom_hash_default,
6290 custom_serialize_default,
6291 custom_deserialize_default,
6292 #if defined(custom_compare_ext_default)
6293 custom_compare_ext_default,
6294 #endif
6297 CAMLprim value caml_curl_multi_init(value unit)
6299 CAMLparam1(unit);
6300 CAMLlocal1(v);
6301 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6302 CURLM* h = curl_multi_init();
6304 if (!h)
6306 caml_stat_free(multi);
6307 failwith("caml_curl_multi_init");
6310 multi->handle = h;
6311 multi->values = caml_alloc(multi_values_total, 0);
6312 caml_register_generational_global_root(&multi->values);
6314 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6315 Multi_val(v) = multi;
6317 CAMLreturn(v);
6320 CAMLprim value caml_curl_multi_cleanup(value handle)
6322 CAMLparam1(handle);
6323 ml_multi_handle* h = Multi_val(handle);
6325 if (NULL == h)
6326 CAMLreturn(Val_unit);
6328 caml_remove_generational_global_root(&h->values);
6330 if (CURLM_OK != curl_multi_cleanup(h->handle))
6331 failwith("caml_curl_multi_cleanup");
6333 Multi_val(handle) = (ml_multi_handle*)NULL;
6335 CAMLreturn(Val_unit);
6338 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6340 int msgs_in_queue = 0;
6342 while (1)
6344 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6345 if (NULL == msg) return NULL;
6346 if (CURLMSG_DONE == msg->msg)
6348 CURL* easy_handle = msg->easy_handle;
6349 if (result) *result = msg->data.result;
6350 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6352 /*failwith("curlm_remove_finished");*/
6354 return easy_handle;
6359 CAMLprim value caml_curlm_remove_finished(value v_multi)
6361 CAMLparam1(v_multi);
6362 CAMLlocal2(v_easy, v_tuple);
6363 CURL* handle;
6364 CURLM* multi_handle;
6365 CURLcode result;
6366 Connection* conn = NULL;
6368 multi_handle = CURLM_val(v_multi);
6370 caml_enter_blocking_section();
6371 handle = curlm_remove_finished(multi_handle,&result);
6372 caml_leave_blocking_section();
6374 if (NULL == handle)
6376 CAMLreturn(Val_none);
6378 else
6380 conn = findConnection(handle);
6381 if (conn->errorBuffer != NULL)
6383 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0, caml_copy_string(conn->errorBuffer));
6385 conn->refcount--;
6386 /* NB: same handle, but different block */
6387 v_easy = caml_curl_alloc(conn);
6388 v_tuple = caml_alloc(2, 0);
6389 Store_field(v_tuple,0,v_easy);
6390 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6391 CAMLreturn(Val_some(v_tuple));
6395 static int curlm_wait_data(CURLM* multi_handle)
6397 struct timeval timeout;
6398 CURLMcode ret;
6400 fd_set fdread;
6401 fd_set fdwrite;
6402 fd_set fdexcep;
6403 int maxfd = -1;
6405 FD_ZERO(&fdread);
6406 FD_ZERO(&fdwrite);
6407 FD_ZERO(&fdexcep);
6409 /* set a suitable timeout */
6410 timeout.tv_sec = 1;
6411 timeout.tv_usec = 0;
6413 /* get file descriptors from the transfers */
6414 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6416 if (ret == CURLM_OK && maxfd >= 0)
6418 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6419 if (-1 != rc) return 0;
6421 return 1;
6424 CAMLprim value caml_curlm_wait_data(value v_multi)
6426 CAMLparam1(v_multi);
6427 int ret;
6428 CURLM* h = CURLM_val(v_multi);
6430 caml_enter_blocking_section();
6431 ret = curlm_wait_data(h);
6432 caml_leave_blocking_section();
6434 CAMLreturn(Val_bool(0 == ret));
6437 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6439 CAMLparam2(v_multi,v_easy);
6440 CURLM* multi = CURLM_val(v_multi);
6441 Connection* conn = Connection_val(v_easy);
6443 /* prevent collection of OCaml value while the easy handle is used
6444 and may invoke callbacks registered on OCaml side */
6445 conn->refcount++;
6447 /* may invoke callbacks so need to be consistent with locks */
6448 caml_enter_blocking_section();
6449 if (CURLM_OK != curl_multi_add_handle(multi, conn->connection))
6451 conn->refcount--; /* not added, revert */
6452 caml_leave_blocking_section();
6453 failwith("caml_curl_multi_add_handle");
6455 caml_leave_blocking_section();
6457 CAMLreturn(Val_unit);
6460 CAMLprim value caml_curl_multi_remove_handle(value v_multi, value v_easy)
6462 CAMLparam2(v_multi,v_easy);
6463 CURLM* multi = CURLM_val(v_multi);
6464 Connection* conn = Connection_val(v_easy);
6466 /* may invoke callbacks so need to be consistent with locks */
6467 caml_enter_blocking_section();
6468 if (CURLM_OK != curl_multi_remove_handle(multi, conn->connection))
6470 caml_leave_blocking_section();
6471 failwith("caml_curl_multi_remove_handle");
6473 conn->refcount--;
6474 caml_leave_blocking_section();
6476 CAMLreturn(Val_unit);
6479 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6481 CAMLparam1(v_multi);
6482 int still_running = 0;
6483 CURLM* h = CURLM_val(v_multi);
6485 caml_enter_blocking_section();
6486 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6487 caml_leave_blocking_section();
6489 CAMLreturn(Val_int(still_running));
6492 CAMLprim value helper_curl_easy_strerror(value v_code)
6494 CAMLparam1(v_code);
6495 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6499 * Wrappers for the curl_multi_socket_action infrastructure
6500 * Based on curl hiperfifo.c example
6503 #ifdef _WIN32
6504 #ifndef Val_socket
6505 #define Val_socket(v) win_alloc_socket(v)
6506 #endif
6507 #ifndef Socket_val
6508 #error Socket_val not defined in unixsupport.h
6509 #endif
6510 #else /* _WIN32 */
6511 #ifndef Socket_val
6512 #define Socket_val(v) Long_val(v)
6513 #endif
6514 #ifndef Val_socket
6515 #define Val_socket(v) Val_int(v)
6516 #endif
6517 #endif /* _WIN32 */
6519 static void raise_error(char const* msg)
6521 static value* exception = NULL;
6523 if (NULL == exception)
6525 exception = caml_named_value("Curl.Multi.Error");
6526 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6529 caml_raise_with_string(*exception, msg);
6532 static void check_mcode(CURLMcode code)
6534 char const *s = NULL;
6535 switch (code)
6537 case CURLM_OK : return;
6538 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6539 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6540 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6541 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6542 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6543 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6544 case CURLM_LAST : s="CURLM_LAST"; break;
6545 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6546 default : s="CURLM_unknown"; break;
6548 raise_error(s);
6551 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6553 CAMLparam3(v_multi, v_fd, v_kind);
6554 CURLM* h = CURLM_val(v_multi);
6555 int still_running = 0;
6556 CURLMcode rc = CURLM_OK;
6557 curl_socket_t socket;
6558 int kind = 0;
6560 if (Val_none == v_fd)
6562 socket = CURL_SOCKET_TIMEOUT;
6564 else
6566 socket = Socket_val(Field(v_fd, 0));
6569 switch (Int_val(v_kind))
6571 case 0 : break;
6572 case 1 : kind |= CURL_CSELECT_IN; break;
6573 case 2 : kind |= CURL_CSELECT_OUT; break;
6574 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6575 default:
6576 raise_error("caml_curl_multi_socket_action");
6579 /* fprintf(stdout,"fd %u kind %u\n",socket, kind); fflush(stdout); */
6581 caml_enter_blocking_section();
6582 do {
6583 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6584 } while (rc == CURLM_CALL_MULTI_PERFORM);
6585 caml_leave_blocking_section();
6587 check_mcode(rc);
6589 CAMLreturn(Val_int(still_running));
6592 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6594 CAMLparam1(v_multi);
6595 int still_running = 0;
6596 CURLMcode rc = CURLM_OK;
6597 CURLM* h = CURLM_val(v_multi);
6599 caml_enter_blocking_section();
6600 do {
6601 rc = curl_multi_socket_all(h, &still_running);
6602 } while (rc == CURLM_CALL_MULTI_PERFORM);
6603 caml_leave_blocking_section();
6605 check_mcode(rc);
6607 CAMLreturn(Val_int(still_running));
6610 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6612 CAMLparam0();
6613 CAMLlocal2(v_what,csock);
6614 (void)e;
6615 (void)sockp; /* not used */
6617 /* v_what = Val_int(what); */
6618 switch (what)
6620 case CURL_POLL_NONE : v_what = Val_int(0); break;
6621 case CURL_POLL_IN : v_what = Val_int(1); break;
6622 case CURL_POLL_OUT : v_what = Val_int(2); break;
6623 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6624 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6625 default:
6626 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6627 fflush(stderr);
6628 raise_error("curlm_sock_cb"); /* FIXME exception from callback */
6630 csock=Val_socket(sock);
6631 caml_callback2(Field(multi->values,curlmopt_socket_function),
6632 csock, v_what);
6634 CAMLreturn(0);
6637 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6639 int ret;
6640 caml_leave_blocking_section();
6641 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6642 caml_enter_blocking_section();
6643 return ret;
6646 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6648 CAMLparam2(v_multi, v_cb);
6649 ml_multi_handle* multi = Multi_val(v_multi);
6651 Store_field(multi->values, curlmopt_socket_function, v_cb);
6653 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6654 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6656 CAMLreturn(Val_unit);
6659 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6661 CAMLparam0();
6662 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6663 CAMLreturn0;
6666 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6668 (void)multi;
6670 caml_leave_blocking_section();
6671 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6672 caml_enter_blocking_section();
6673 return 0;
6676 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6678 CAMLparam2(v_multi, v_cb);
6679 ml_multi_handle* multi = Multi_val(v_multi);
6681 Store_field(multi->values, curlmopt_timer_function, v_cb);
6683 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6684 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6686 CAMLreturn(Val_unit);
6689 CAMLprim value caml_curl_multi_timeout(value v_multi)
6691 CAMLparam1(v_multi);
6692 long ms = 0;
6693 CURLMcode rc = CURLM_OK;
6694 ml_multi_handle* multi = Multi_val(v_multi);
6696 rc = curl_multi_timeout(multi->handle, &ms);
6698 check_mcode(rc);
6700 CAMLreturn(Val_long(ms));