simplify CURLOPT mapping
[ocurl.git] / curl-helper.c
bloba69b2c47c3523183571c38280c023bbea704cb00
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 OcamlMailFrom,
120 OcamlMailRcpt,
122 /* Not used, last for size */
123 OcamlValuesSize
126 struct Connection
128 CURL *connection;
129 Connection *next;
130 Connection *prev;
132 value ocamlValues;
134 size_t refcount; /* number of references to this structure */
136 char *url;
137 char *proxy;
138 char *userPwd;
139 char *proxyUserPwd;
140 char *range;
141 char *errorBuffer;
142 char *postFields;
143 int postFieldSize;
144 char *referer;
145 char *userAgent;
146 char *ftpPort;
147 char *cookie;
148 struct curl_slist *httpHeader;
149 struct curl_httppost *httpPostFirst;
150 struct curl_httppost *httpPostLast;
151 struct curl_slist *httpPostStrings;
152 struct curl_slist *resolve;
153 char *sslCert;
154 char *sslCertType;
155 char *sslCertPasswd;
156 char *sslKey;
157 char *sslKeyType;
158 char *sslKeyPasswd;
159 char *sslEngine;
160 struct curl_slist *quote;
161 struct curl_slist *postQuote;
162 char *cookieFile;
163 char *customRequest;
164 char *interface_; /* `interface` gives problems on windows */
165 char *caInfo;
166 char *caPath;
167 char *randomFile;
168 char *egdSocket;
169 char *cookieJar;
170 char *sslCipherList;
171 char *private;
172 struct curl_slist *http200Aliases;
173 char *netrcFile;
174 char *ftpaccount;
175 char *cookielist;
176 char *ftpAlternativeToUser;
177 char *sshPublicKeyFile;
178 char *sshPrivateKeyFile;
179 char *sshHostPublicKeyMD5;
180 char *copyPostFields;
181 char *dns_servers;
182 char *mailFrom;
183 struct curl_slist *mailRcpt;
186 struct ConnectionList
188 Connection *head;
189 Connection *tail;
192 static ConnectionList connectionList = {NULL, NULL};
194 typedef struct CURLErrorMapping CURLErrorMapping;
196 struct CURLErrorMapping
198 char *name;
199 CURLcode error;
202 CURLErrorMapping errorMap[] =
204 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
205 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
206 #else
207 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
208 #endif
209 #if HAVE_DECL_CURLE_FAILED_INIT
210 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
211 #else
212 {"CURLE_FAILED_INIT", -1},
213 #endif
214 #if HAVE_DECL_CURLE_URL_MALFORMAT
215 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
216 #else
217 {"CURLE_URL_MALFORMAT", -1},
218 #endif
219 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
220 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
221 #else
222 {"CURLE_URL_MALFORMAT_USER", -1},
223 #endif
224 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
225 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
226 #else
227 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
228 #endif
229 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
230 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
231 #else
232 {"CURLE_COULDNT_RESOLVE_HOST", -1},
233 #endif
234 #if HAVE_DECL_CURLE_COULDNT_CONNECT
235 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
236 #else
237 {"CURLE_COULDNT_CONNECT", -1},
238 #endif
239 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
240 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
241 #else
242 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
243 #endif
244 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
245 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
246 #else
247 {"CURLE_FTP_ACCESS_DENIED", -1},
248 #endif
249 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
250 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
251 #else
252 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
253 #endif
254 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
255 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
256 #else
257 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
258 #endif
259 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
260 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
261 #else
262 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
263 #endif
264 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
265 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
266 #else
267 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
268 #endif
269 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
270 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
271 #else
272 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
273 #endif
274 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
275 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
276 #else
277 {"CURLE_FTP_CANT_GET_HOST", -1},
278 #endif
279 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
280 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
281 #else
282 {"CURLE_FTP_CANT_RECONNECT", -1},
283 #endif
284 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
285 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
286 #else
287 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
288 #endif
289 #if HAVE_DECL_CURLE_PARTIAL_FILE
290 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
291 #else
292 {"CURLE_PARTIAL_FILE", -1},
293 #endif
294 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
295 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
296 #else
297 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
298 #endif
299 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
300 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
301 #else
302 {"CURLE_FTP_WRITE_ERROR", -1},
303 #endif
304 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
305 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
306 #else
307 {"CURLE_FTP_QUOTE_ERROR", -1},
308 #endif
309 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
310 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
311 #else
312 {"CURLE_HTTP_NOT_FOUND", -1},
313 #endif
314 #if HAVE_DECL_CURLE_WRITE_ERROR
315 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
316 #else
317 {"CURLE_WRITE_ERROR", -1},
318 #endif
319 #if HAVE_DECL_CURLE_MALFORMAT_USER
320 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
321 #else
322 {"CURLE_MALFORMAT_USER", -1},
323 #endif
324 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
325 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
326 #else
327 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
328 #endif
329 #if HAVE_DECL_CURLE_READ_ERROR
330 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
331 #else
332 {"CURLE_READ_ERROR", -1},
333 #endif
334 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
335 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
336 #else
337 {"CURLE_OUT_OF_MEMORY", -1},
338 #endif
339 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
340 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
341 #else
342 {"CURLE_OPERATION_TIMEOUTED", -1},
343 #endif
344 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
345 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
346 #else
347 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
348 #endif
349 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
350 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
351 #else
352 {"CURLE_FTP_PORT_FAILED", -1},
353 #endif
354 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
355 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
356 #else
357 {"CURLE_FTP_COULDNT_USE_REST", -1},
358 #endif
359 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
360 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
361 #else
362 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
363 #endif
364 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
365 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
366 #else
367 {"CURLE_HTTP_RANGE_ERROR", -1},
368 #endif
369 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
370 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
371 #else
372 {"CURLE_HTTP_POST_ERROR", -1},
373 #endif
374 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
375 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
376 #else
377 {"CURLE_SSL_CONNECT_ERROR", -1},
378 #endif
379 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
380 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
381 #else
382 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
383 #endif
384 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
385 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
386 #else
387 {"CURLE_FILE_COULDNT_READ_FILE", -1},
388 #endif
389 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
390 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
391 #else
392 {"CURLE_LDAP_CANNOT_BIND", -1},
393 #endif
394 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
395 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
396 #else
397 {"CURLE_LDAP_SEARCH_FAILED", -1},
398 #endif
399 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
400 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
401 #else
402 {"CURLE_LIBRARY_NOT_FOUND", -1},
403 #endif
404 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
405 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
406 #else
407 {"CURLE_FUNCTION_NOT_FOUND", -1},
408 #endif
409 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
410 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
411 #else
412 {"CURLE_ABORTED_BY_CALLBACK", -1},
413 #endif
414 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
415 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
416 #else
417 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
418 #endif
419 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
420 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
421 #else
422 {"CURLE_BAD_CALLING_ORDER", -1},
423 #endif
424 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
425 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
426 #else
427 {"CURLE_HTTP_PORT_FAILED", -1},
428 #endif
429 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
430 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
431 #else
432 {"CURLE_BAD_PASSWORD_ENTERED", -1},
433 #endif
434 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
435 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
436 #else
437 {"CURLE_TOO_MANY_REDIRECTS", -1},
438 #endif
439 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
440 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
441 #else
442 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
443 #endif
444 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
445 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
446 #else
447 {"CURLE_TELNET_OPTION_SYNTAX", -1},
448 #endif
449 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
450 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
451 #else
452 {"CURLE_SSL_PEER_CERTIFICATE", -1},
453 #endif
454 #if HAVE_DECL_CURLE_GOT_NOTHING
455 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
456 #else
457 {"CURLE_GOT_NOTHING", -1},
458 #endif
459 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
460 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
461 #else
462 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
463 #endif
464 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
465 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
466 #else
467 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
468 #endif
469 #if HAVE_DECL_CURLE_SEND_ERROR
470 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
471 #else
472 {"CURLE_SEND_ERROR", -1},
473 #endif
474 #if HAVE_DECL_CURLE_RECV_ERROR
475 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
476 #else
477 {"CURLE_RECV_ERROR", -1},
478 #endif
479 #if HAVE_DECL_CURLE_SHARE_IN_USE
480 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
481 #else
482 {"CURLE_SHARE_IN_USE", -1},
483 #endif
484 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
485 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
486 #else
487 {"CURLE_SSL_CERTPROBLEN", -1},
488 #endif
489 #if HAVE_DECL_CURLE_SSL_CIPHER
490 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
491 #else
492 {"CURLE_SSL_CIPHER", -1},
493 #endif
494 #if HAVE_DECL_CURLE_SSL_CACERT
495 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
496 #else
497 {"CURLE_SSL_CACERT", -1},
498 #endif
499 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
500 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
501 #else
502 {"CURLE_BAD_CONTENT_ENCODING", -1},
503 #endif
504 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
505 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
506 #else
507 {"CURLE_LDAP_INVALID_URL", -1},
508 #endif
509 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
510 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
511 #else
512 {"CURLE_FILESIZE_EXCEEDED", -1},
513 #endif
514 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
515 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
516 #else
517 {"CURLE_FTP_SSL_FAILED", -1},
518 #endif
519 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
520 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
521 #else
522 {"CURLE_SEND_FAIL_REWIND", -1},
523 #endif
524 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
525 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
526 #else
527 {"CURLE_SSL_ENGINE_INITFAILED", -1},
528 #endif
529 #if HAVE_DECL_CURLE_LOGIN_DENIED
530 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
531 #else
532 {"CURLE_LOGIN_DENIED", -1},
533 #endif
534 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
535 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
536 #else
537 {"CURLE_TFTP_NOTFOUND", -1},
538 #endif
539 #if HAVE_DECL_CURLE_TFTP_PERM
540 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
541 #else
542 {"CURLE_TFTP_PERM", -1},
543 #endif
544 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
545 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
546 #else
547 {"CURLE_REMOTE_DISK_FULL", -1},
548 #endif
549 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
550 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
551 #else
552 {"CURLE_TFTP_ILLEGAL", -1},
553 #endif
554 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
555 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
556 #else
557 {"CURLE_TFTP_UNKNOWNID", -1},
558 #endif
559 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
560 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
561 #else
562 {"CURLE_REMOTE_FILE_EXISTS", -1},
563 #endif
564 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
565 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
566 #else
567 {"CURLE_TFTP_NOSUCHUSER", -1},
568 #endif
569 #if HAVE_DECL_CURLE_CONV_FAILED
570 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
571 #else
572 {"CURLE_CONV_FAILED", -1},
573 #endif
574 #if HAVE_DECL_CURLE_CONV_REQUIRED
575 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
576 #else
577 {"CURLE_CONV_REQUIRED", -1},
578 #endif
579 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
580 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
581 #else
582 {"CURLE_SSL_CACERT_BADFILE", -1},
583 #endif
584 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
585 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
586 #else
587 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
588 #endif
589 #if HAVE_DECL_CURLE_SSH
590 {"CURLE_SSH", CURLE_SSH},
591 #else
592 {"CURLE_SSH", -1},
593 #endif
594 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
595 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
596 #else
597 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
598 #endif
599 #if HAVE_DECL_CURLE_AGAIN
600 {"CURLE_AGAIN", CURLE_AGAIN},
601 #else
602 {"CURLE_AGAIN", -1},
603 #endif
604 {"CURLE_OK", CURLE_OK},
605 {NULL, 0}
608 typedef struct CURLOptionMapping CURLOptionMapping;
610 struct CURLOptionMapping
612 void (*optionHandler)(Connection *, value);
613 char *name;
614 /* CURLoption option; */
617 static void free_curl_slist(struct curl_slist *slist)
619 if (NULL == slist)
620 return;
622 curl_slist_free_all(slist);
625 static void raiseError(Connection *conn, CURLcode code)
627 CAMLparam0();
628 CAMLlocal1(exceptionData);
629 value *exception;
630 char *errorString = "Unknown Error";
631 int i;
633 for (i = 0; errorMap[i].name != NULL; i++)
635 if (errorMap[i].error == code)
637 errorString = errorMap[i].name;
638 break;
642 exceptionData = caml_alloc(3, 0);
644 Store_field(exceptionData, 0, Val_int(code));
645 Store_field(exceptionData, 1, Val_int(code));
646 Store_field(exceptionData, 2, copy_string(errorString));
648 if (conn != NULL && conn->errorBuffer != NULL)
650 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
651 copy_string(conn->errorBuffer));
654 exception = caml_named_value("CurlException");
656 if (exception == NULL)
657 caml_failwith("CurlException not registered");
659 raise_with_arg(*exception, exceptionData);
661 CAMLreturn0;
664 static void resetOcamlValues(Connection* connection)
666 int i;
668 for (i = 0; i < OcamlValuesSize; i++)
669 Store_field(connection->ocamlValues, i, Val_unit);
672 static Connection* allocConnection(CURL* h)
674 Connection* connection = (Connection *)malloc(sizeof(Connection));
676 connection->ocamlValues = caml_alloc(OcamlValuesSize, 0);
677 resetOcamlValues(connection);
678 register_global_root(&connection->ocamlValues);
680 connection->connection = h;
682 connection->next = NULL;
683 connection->prev = NULL;
685 if (connectionList.tail == NULL)
687 connectionList.tail = connection;
688 connectionList.head = connection;
690 else
692 connection->prev = connectionList.head;
693 connectionList.head->next = connection;
694 connectionList.head = connection;
697 connection->refcount = 0;
699 connection->url = NULL;
700 connection->proxy = NULL;
701 connection->userPwd = NULL;
702 connection->proxyUserPwd = NULL;
703 connection->range = NULL;
704 connection->errorBuffer = NULL;
705 connection->postFields = NULL;
706 connection->postFieldSize = -1;
707 connection->referer = NULL;
708 connection->userAgent = NULL;
709 connection->ftpPort = NULL;
710 connection->cookie = NULL;
711 connection->httpHeader = NULL;
712 connection->httpPostFirst = NULL;
713 connection->httpPostLast = NULL;
714 connection->httpPostStrings = NULL;
715 connection->sslCert = NULL;
716 connection->sslCertType = NULL;
717 connection->sslCertPasswd = NULL;
718 connection->sslKey = NULL;
719 connection->sslKeyType = NULL;
720 connection->sslKeyPasswd = NULL;
721 connection->sslEngine = NULL;
722 connection->quote = NULL;
723 connection->postQuote = NULL;
724 connection->cookieFile = NULL;
725 connection->customRequest = NULL;
726 connection->interface_ = NULL;
727 connection->caInfo = NULL;
728 connection->caPath = NULL;
729 connection->randomFile = NULL;
730 connection->egdSocket = NULL;
731 connection->cookieJar = NULL;
732 connection->sslCipherList = NULL;
733 connection->private = NULL;
734 connection->http200Aliases = NULL;
735 connection->netrcFile = NULL;
736 connection->ftpaccount = NULL;
737 connection->cookielist = NULL;
738 connection->ftpAlternativeToUser = NULL;
739 connection->sshPublicKeyFile = NULL;
740 connection->sshPrivateKeyFile = NULL;
741 connection->copyPostFields = NULL;
742 connection->resolve = NULL;
743 connection->dns_servers = NULL;
744 connection->mailFrom = NULL;
745 connection->mailRcpt = NULL;
747 return connection;
750 static Connection *newConnection(void)
752 CURL* h;
754 caml_enter_blocking_section();
755 h = curl_easy_init();
756 caml_leave_blocking_section();
758 return allocConnection(h);
761 static void free_if(void* p) { if (NULL != p) free(p); }
763 static void removeConnection(Connection *connection, int finalization)
765 const char* fin_url = NULL;
767 if (!connection->connection)
769 return; /* already cleaned up */
772 if (finalization)
774 /* cannot engage OCaml runtime at finalization, just report leak */
775 if (CURLE_OK != curl_easy_getinfo(connection->connection, CURLINFO_EFFECTIVE_URL, &fin_url) || NULL == fin_url)
777 fin_url = "unknown";
779 fprintf(stderr,"Curl: handle %p leaked, conn %p, url %s\n", connection->connection, connection, fin_url);
780 fflush(stderr);
782 else
784 enter_blocking_section();
785 curl_easy_cleanup(connection->connection);
786 leave_blocking_section();
789 connection->connection = NULL;
791 if (connectionList.tail == connection)
792 connectionList.tail = connectionList.tail->next;
793 if (connectionList.head == connection)
794 connectionList.head = connectionList.head->prev;
796 if (connection->next != NULL)
797 connection->next->prev = connection->prev;
798 if (connection->prev != NULL)
799 connection->prev->next = connection->next;
801 remove_global_root(&connection->ocamlValues);
803 free_if(connection->url);
804 free_if(connection->proxy);
805 free_if(connection->userPwd);
806 free_if(connection->proxyUserPwd);
807 free_if(connection->range);
808 free_if(connection->errorBuffer);
809 free_if(connection->postFields);
810 free_if(connection->referer);
811 free_if(connection->userAgent);
812 free_if(connection->ftpPort);
813 free_if(connection->cookie);
814 free_curl_slist(connection->httpHeader);
815 if (connection->httpPostFirst != NULL)
816 curl_formfree(connection->httpPostFirst);
817 free_curl_slist(connection->httpPostStrings);
818 free_curl_slist(connection->resolve);
819 free_if(connection->sslCert);
820 free_if(connection->sslCertType);
821 free_if(connection->sslCertPasswd);
822 free_if(connection->sslKey);
823 free_if(connection->sslKeyType);
824 free_if(connection->sslKeyPasswd);
825 free_if(connection->sslEngine);
826 free_curl_slist(connection->quote);
827 free_curl_slist(connection->postQuote);
828 free_if(connection->cookieFile);
829 free_if(connection->customRequest);
830 free_if(connection->interface_);
831 free_if(connection->caInfo);
832 free_if(connection->caPath);
833 free_if(connection->randomFile);
834 free_if(connection->egdSocket);
835 free_if(connection->cookieJar);
836 free_if(connection->sslCipherList);
837 free_if(connection->private);
838 free_curl_slist(connection->http200Aliases);
839 free_if(connection->netrcFile);
840 free_if(connection->ftpaccount);
841 free_if(connection->cookielist);
842 free_if(connection->ftpAlternativeToUser);
843 free_if(connection->sshPublicKeyFile);
844 free_if(connection->sshPrivateKeyFile);
845 free_if(connection->copyPostFields);
846 free_if(connection->dns_servers);
847 free_if(connection->mailFrom);
848 free_curl_slist(connection->mailRcpt);
851 #if 1
852 static void checkConnection(Connection * connection)
854 (void)connection;
856 #else
857 static void checkConnection(Connection *connection)
859 Connection *listIter;
861 listIter = connectionList.tail;
863 while (listIter != NULL)
865 if (listIter == connection)
866 return;
868 listIter = listIter->next;
871 failwith("Invalid Connection");
873 #endif
875 static Connection* findConnection(CURL* h)
877 Connection *listIter;
879 listIter = connectionList.tail;
881 while (listIter != NULL)
883 if (listIter->connection == h)
884 return listIter;
886 listIter = listIter->next;
889 failwith("Unknown handle");
892 void op_curl_easy_finalize(value v)
894 Connection* conn = Connection_val(v);
895 /* same connection may be referenced by several different
896 OCaml values, see e.g. caml_curl_multi_remove_finished */
897 conn->refcount--;
898 if (0 == conn->refcount)
900 removeConnection(conn, 1);
901 free(conn);
905 int op_curl_easy_compare(value v1, value v2)
907 size_t p1 = (size_t)Connection_val(v1);
908 size_t p2 = (size_t)Connection_val(v2);
909 return (p1 == p2 ? 0 : (p1 > p2 ? 1 : -1)); /* compare addresses */
912 intnat op_curl_easy_hash(value v)
914 return (size_t)Connection_val(v); /* address */
917 static struct custom_operations curl_easy_ops = {
918 "ygrek.curl_easy",
919 op_curl_easy_finalize,
920 op_curl_easy_compare,
921 op_curl_easy_hash,
922 custom_serialize_default,
923 custom_deserialize_default,
924 #if defined(custom_compare_ext_default)
925 custom_compare_ext_default,
926 #endif
929 value caml_curl_alloc(Connection* conn)
931 value v = caml_alloc_custom(&curl_easy_ops, sizeof(Connection*), 0, 1);
932 Connection_val(v) = conn;
933 conn->refcount++;
934 return v;
937 #define WRAP_DATA_CALLBACK(f) \
938 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
940 size_t result;\
941 leave_blocking_section();\
942 result = f##_nolock(ptr,size,nmemb,data);\
943 enter_blocking_section();\
944 return result;\
947 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
949 CAMLparam0();
950 CAMLlocal2(result, str);
951 Connection *conn = (Connection *)data;
952 size_t i;
954 checkConnection(conn);
956 str = alloc_string(size*nmemb);
958 for (i = 0; i < size*nmemb; i++)
959 Byte(str, i) = ptr[i];
961 result = callback_exn(Field(conn->ocamlValues, OcamlWriteCallback), str);
963 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
966 WRAP_DATA_CALLBACK(writeFunction)
968 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
970 CAMLparam0();
971 CAMLlocal1(result);
972 Connection *conn = (Connection *)data;
973 size_t length;
975 checkConnection(conn);
977 result = callback_exn(Field(conn->ocamlValues, OcamlReadCallback),
978 Val_int(size*nmemb));
980 if (Is_exception_result(result))
982 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
985 length = string_length(result);
987 if (length <= size*nmemb)
989 memcpy(ptr, String_val(result), length);
991 CAMLreturnT(size_t,length);
993 else
995 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
999 WRAP_DATA_CALLBACK(readFunction)
1001 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1003 CAMLparam0();
1004 CAMLlocal2(result,str);
1005 Connection *conn = (Connection *)data;
1006 size_t i;
1008 checkConnection(conn);
1010 str = alloc_string(size*nmemb);
1012 for (i = 0; i < size*nmemb; i++)
1013 Byte(str, i) = ptr[i];
1015 result = callback_exn(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1017 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1020 WRAP_DATA_CALLBACK(headerFunction)
1022 static int progressFunction_nolock(void *data,
1023 double dlTotal,
1024 double dlNow,
1025 double ulTotal,
1026 double ulNow)
1028 CAMLparam0();
1029 CAMLlocal1(result);
1030 CAMLlocalN(callbackData, 4);
1031 Connection *conn = (Connection *)data;
1033 checkConnection(conn);
1035 callbackData[0] = copy_double(dlTotal);
1036 callbackData[1] = copy_double(dlNow);
1037 callbackData[2] = copy_double(ulTotal);
1038 callbackData[3] = copy_double(ulNow);
1040 result = callbackN_exn(Field(conn->ocamlValues, OcamlProgressCallback),
1041 4, callbackData);
1043 CAMLreturnT(int, Is_exception_result(result) ? 1 : Bool_val(result));
1046 static int progressFunction(void *data,
1047 double dlTotal,
1048 double dlNow,
1049 double ulTotal,
1050 double ulNow)
1052 int r;
1053 leave_blocking_section();
1054 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1055 enter_blocking_section();
1056 return r;
1059 static int debugFunction_nolock(CURL *debugConnection,
1060 curl_infotype infoType,
1061 char *buffer,
1062 size_t bufferLength,
1063 void *data)
1065 CAMLparam0();
1066 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1067 size_t i;
1068 Connection *conn = (Connection *)data;
1069 (void)debugConnection; /* not used */
1071 checkConnection(conn);
1073 camlDebugConnection = (value)conn;
1074 camlInfoType = Val_long(infoType);
1075 camlMessage = alloc_string(bufferLength);
1077 for (i = 0; i < bufferLength; i++)
1078 Byte(camlMessage, i) = buffer[i];
1080 callback3_exn(Field(conn->ocamlValues, OcamlDebugCallback),
1081 camlDebugConnection,
1082 camlInfoType,
1083 camlMessage);
1085 CAMLreturnT(int, 0);
1088 static int debugFunction(CURL *debugConnection,
1089 curl_infotype infoType,
1090 char *buffer,
1091 size_t bufferLength,
1092 void *data)
1094 int r;
1095 leave_blocking_section();
1096 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1097 enter_blocking_section();
1098 return r;
1101 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1102 int cmd,
1103 void *data)
1105 CAMLparam0();
1106 CAMLlocal3(camlResult, camlConnection, camlCmd);
1107 Connection *conn = (Connection *)data;
1108 curlioerr result = CURLIOE_OK;
1109 (void)ioctl; /* not used */
1111 checkConnection(conn);
1113 if (cmd == CURLIOCMD_NOP)
1114 camlCmd = Val_long(0);
1115 else if (cmd == CURLIOCMD_RESTARTREAD)
1116 camlCmd = Val_long(1);
1117 else
1118 failwith("Invalid IOCTL Cmd!");
1120 camlConnection = caml_curl_alloc(conn);
1122 camlResult = callback2_exn(Field(conn->ocamlValues, OcamlIOCTLCallback),
1123 camlConnection,
1124 camlCmd);
1126 if (Is_exception_result(camlResult))
1128 result = CURLIOE_FAILRESTART;
1130 else
1131 switch (Long_val(camlResult))
1133 case 0: /* CURLIOE_OK */
1134 result = CURLIOE_OK;
1135 break;
1137 case 1: /* CURLIOE_UNKNOWNCMD */
1138 result = CURLIOE_UNKNOWNCMD;
1139 break;
1141 case 2: /* CURLIOE_FAILRESTART */
1142 result = CURLIOE_FAILRESTART;
1143 break;
1145 default: /* Incorrect return value, but let's handle it */
1146 result = CURLIOE_FAILRESTART;
1147 break;
1150 CAMLreturnT(curlioerr, result);
1153 static curlioerr ioctlFunction(CURL *ioctl,
1154 int cmd,
1155 void *data)
1157 curlioerr r;
1158 leave_blocking_section();
1159 r = ioctlFunction_nolock(ioctl, cmd, data);
1160 enter_blocking_section();
1161 return r;
1164 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1165 static int seekFunction_nolock(void *data,
1166 curl_off_t offset,
1167 int origin)
1169 CAMLparam0();
1170 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1171 Connection *conn = (Connection *)data;
1173 camlOffset = copy_int64(offset);
1175 if (origin == SEEK_SET)
1176 camlOrigin = Val_long(0);
1177 else if (origin == SEEK_CUR)
1178 camlOrigin = Val_long(1);
1179 else if (origin == SEEK_END)
1180 camlOrigin = Val_long(2);
1181 else
1182 failwith("Invalid seek code");
1184 camlResult = callback2_exn(Field(conn->ocamlValues,
1185 OcamlSeekFunctionCallback),
1186 camlOffset,
1187 camlOrigin);
1189 int result;
1190 if (Is_exception_result(camlResult))
1191 result = CURL_SEEKFUNC_FAIL;
1192 else
1193 switch (Int_val(camlResult))
1195 case 0: result = CURL_SEEKFUNC_OK; break;
1196 case 1: result = CURL_SEEKFUNC_FAIL; break;
1197 case 2: result = CURL_SEEKFUNC_CANTSEEK; break;
1198 default: failwith("Invalid seek result");
1201 CAMLreturnT(int, result);
1204 static int seekFunction(void *data,
1205 curl_off_t offset,
1206 int origin)
1208 int r;
1209 leave_blocking_section();
1210 r = seekFunction_nolock(data,offset,origin);
1211 enter_blocking_section();
1212 return r;
1215 #endif
1217 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1218 static int openSocketFunction_nolock(void *data,
1219 curlsocktype purpose,
1220 struct curl_sockaddr *addr)
1222 CAMLparam0();
1223 CAMLlocal1(result);
1224 Connection *conn = (Connection *)data;
1225 int sock = -1;
1226 (void)purpose; /* not used */
1228 sock = socket(addr->family, addr->socktype, addr->protocol);
1230 if (-1 != sock)
1232 /* FIXME windows */
1233 result = callback_exn(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1234 if (Is_exception_result(result))
1236 close(sock);
1237 sock = -1;
1241 CAMLreturnT(int, (sock == -1) ? CURL_SOCKET_BAD : sock);
1244 static int openSocketFunction(void *data,
1245 curlsocktype purpose,
1246 struct curl_sockaddr *address)
1248 int r;
1249 leave_blocking_section();
1250 r = openSocketFunction_nolock(data,purpose,address);
1251 enter_blocking_section();
1252 return r;
1255 #endif
1258 ** curl_global_init helper function
1261 CAMLprim value helper_curl_global_init(value initOption)
1263 CAMLparam1(initOption);
1265 switch (Long_val(initOption))
1267 case 0: /* CURLINIT_GLOBALALL */
1268 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1269 break;
1271 case 1: /* CURLINIT_GLOBALSSL */
1272 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1273 break;
1275 case 2: /* CURLINIT_GLOBALWIN32 */
1276 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1277 break;
1279 case 3: /* CURLINIT_GLOBALNOTHING */
1280 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1281 break;
1283 default:
1284 failwith("Invalid Initialization Option");
1285 break;
1288 /* Keep compiler happy, we should never get here due to failwith() */
1289 CAMLreturn(Val_unit);
1293 ** curl_global_cleanup helper function
1296 CAMLprim value helper_curl_global_cleanup(void)
1298 CAMLparam0();
1300 curl_global_cleanup();
1302 CAMLreturn(Val_unit);
1306 ** curl_easy_init helper function
1308 CAMLprim value helper_curl_easy_init(void)
1310 CAMLparam0();
1311 CAMLlocal1(result);
1313 result = caml_curl_alloc(newConnection());
1315 CAMLreturn(result);
1318 CAMLprim value helper_curl_easy_reset(value conn)
1320 CAMLparam1(conn);
1321 Connection *connection = Connection_val(conn);
1323 checkConnection(connection);
1324 curl_easy_reset(connection->connection);
1325 resetOcamlValues(connection);
1327 CAMLreturn(Val_unit);
1331 ** curl_easy_setopt helper utility functions
1334 static void handle_WRITEFUNCTION(Connection *conn, value option)
1336 CAMLparam1(option);
1337 CURLcode result = CURLE_OK;
1339 if (Tag_val(option) == Closure_tag)
1340 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1341 else
1342 failwith("Not a proper closure");
1344 result = curl_easy_setopt(conn->connection,
1345 CURLOPT_WRITEFUNCTION,
1346 writeFunction);
1348 if (result != CURLE_OK)
1349 raiseError(conn, result);
1351 result = curl_easy_setopt(conn->connection,
1352 CURLOPT_WRITEDATA,
1353 conn);
1355 if (result != CURLE_OK)
1356 raiseError(conn, result);
1358 CAMLreturn0;
1361 static void handle_READFUNCTION(Connection *conn, value option)
1363 CAMLparam1(option);
1364 CURLcode result = CURLE_OK;
1366 if (Tag_val(option) == Closure_tag)
1367 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1368 else
1369 failwith("Not a proper closure");
1371 result = curl_easy_setopt(conn->connection,
1372 CURLOPT_READFUNCTION,
1373 readFunction);
1375 if (result != CURLE_OK)
1376 raiseError(conn, result);
1378 result = curl_easy_setopt(conn->connection,
1379 CURLOPT_READDATA,
1380 conn);
1382 if (result != CURLE_OK)
1383 raiseError(conn, result);
1385 CAMLreturn0;
1388 static void handle_URL(Connection *conn, value option)
1390 CAMLparam1(option);
1391 CURLcode result = CURLE_OK;
1393 Store_field(conn->ocamlValues, OcamlURL, option);
1395 if (conn->url != NULL)
1396 free(conn->url);
1398 conn->url = strdup(String_val(option));
1400 result = curl_easy_setopt(conn->connection,
1401 CURLOPT_URL,
1402 conn->url);
1404 if (result != CURLE_OK)
1405 raiseError(conn, result);
1407 CAMLreturn0;
1410 static void handle_INFILESIZE(Connection *conn, value option)
1412 CAMLparam1(option);
1413 CURLcode result = CURLE_OK;
1415 result = curl_easy_setopt(conn->connection,
1416 CURLOPT_INFILESIZE,
1417 Long_val(option));
1419 if (result != CURLE_OK)
1420 raiseError(conn, result);
1422 CAMLreturn0;
1425 static void handle_PROXY(Connection *conn, value option)
1427 CAMLparam1(option);
1428 CURLcode result = CURLE_OK;
1430 Store_field(conn->ocamlValues, OcamlProxy, option);
1432 if (conn->proxy != NULL)
1433 free(conn->proxy);
1435 conn->proxy = strdup(String_val(option));
1437 result = curl_easy_setopt(conn->connection,
1438 CURLOPT_PROXY,
1439 conn->proxy);
1441 if (result != CURLE_OK)
1442 raiseError(conn, result);
1444 CAMLreturn0;
1447 static void handle_PROXYPORT(Connection *conn, value option)
1449 CAMLparam1(option);
1450 CURLcode result = CURLE_OK;
1452 result = curl_easy_setopt(conn->connection,
1453 CURLOPT_PROXYPORT,
1454 Long_val(option));
1456 if (result != CURLE_OK)
1457 raiseError(conn, result);
1459 CAMLreturn0;
1462 static void handle_HTTPPROXYTUNNEL(Connection *conn, value option)
1464 CAMLparam1(option);
1465 CURLcode result = CURLE_OK;
1467 result = curl_easy_setopt(conn->connection,
1468 CURLOPT_HTTPPROXYTUNNEL,
1469 Bool_val(option));
1471 if (result != CURLE_OK)
1472 raiseError(conn, result);
1474 CAMLreturn0;
1477 static void handle_VERBOSE(Connection *conn, value option)
1479 CAMLparam1(option);
1480 CURLcode result = CURLE_OK;
1482 result = curl_easy_setopt(conn->connection,
1483 CURLOPT_VERBOSE,
1484 Bool_val(option));
1486 if (result != CURLE_OK)
1487 raiseError(conn, result);
1489 CAMLreturn0;
1492 static void handle_HEADER(Connection *conn, value option)
1494 CAMLparam1(option);
1495 CURLcode result = CURLE_OK;
1497 result = curl_easy_setopt(conn->connection,
1498 CURLOPT_HEADER,
1499 Bool_val(option));
1501 if (result != CURLE_OK)
1502 raiseError(conn, result);
1504 CAMLreturn0;
1507 static void handle_NOPROGRESS(Connection *conn, value option)
1509 CAMLparam1(option);
1510 CURLcode result = CURLE_OK;
1512 result = curl_easy_setopt(conn->connection,
1513 CURLOPT_NOPROGRESS,
1514 Bool_val(option));
1516 if (result != CURLE_OK)
1517 raiseError(conn, result);
1519 CAMLreturn0;
1522 #if HAVE_DECL_CURLOPT_NOSIGNAL
1523 static void handle_NOSIGNAL(Connection *conn, value option)
1525 CAMLparam1(option);
1526 CURLcode result = CURLE_OK;
1528 result = curl_easy_setopt(conn->connection,
1529 CURLOPT_NOSIGNAL,
1530 Bool_val(option));
1532 if (result != CURLE_OK)
1533 raiseError(conn, result);
1535 CAMLreturn0;
1537 #endif
1539 static void handle_NOBODY(Connection *conn, value option)
1541 CAMLparam1(option);
1542 CURLcode result = CURLE_OK;
1544 result = curl_easy_setopt(conn->connection,
1545 CURLOPT_NOBODY,
1546 Bool_val(option));
1548 if (result != CURLE_OK)
1549 raiseError(conn, result);
1551 CAMLreturn0;
1554 static void handle_FAILONERROR(Connection *conn, value option)
1556 CAMLparam1(option);
1557 CURLcode result = CURLE_OK;
1559 result = curl_easy_setopt(conn->connection,
1560 CURLOPT_FAILONERROR,
1561 Bool_val(option));
1563 if (result != CURLE_OK)
1564 raiseError(conn, result);
1566 CAMLreturn0;
1569 static void handle_UPLOAD(Connection *conn, value option)
1571 CAMLparam1(option);
1572 CURLcode result = CURLE_OK;
1574 result = curl_easy_setopt(conn->connection,
1575 CURLOPT_UPLOAD,
1576 Bool_val(option));
1578 if (result != CURLE_OK)
1579 raiseError(conn, result);
1581 CAMLreturn0;
1584 static void handle_POST(Connection *conn, value option)
1586 CAMLparam1(option);
1587 CURLcode result = CURLE_OK;
1589 result = curl_easy_setopt(conn->connection,
1590 CURLOPT_POST,
1591 Bool_val(option));
1593 if (result != CURLE_OK)
1594 raiseError(conn, result);
1596 CAMLreturn0;
1599 static void handle_FTPLISTONLY(Connection *conn, value option)
1601 CAMLparam1(option);
1602 CURLcode result = CURLE_OK;
1604 result = curl_easy_setopt(conn->connection,
1605 CURLOPT_FTPLISTONLY,
1606 Bool_val(option));
1608 if (result != CURLE_OK)
1609 raiseError(conn, result);
1611 CAMLreturn0;
1614 static void handle_FTPAPPEND(Connection *conn, value option)
1616 CAMLparam1(option);
1617 CURLcode result = CURLE_OK;
1619 result = curl_easy_setopt(conn->connection,
1620 CURLOPT_FTPAPPEND,
1621 Bool_val(option));
1623 if (result != CURLE_OK)
1624 raiseError(conn, result);
1626 CAMLreturn0;
1629 static void handle_NETRC(Connection *conn, value option)
1631 CAMLparam1(option);
1632 CURLcode result = CURLE_OK;
1633 long netrc;
1635 switch (Long_val(option))
1637 case 0: /* CURL_NETRC_OPTIONAL */
1638 netrc = CURL_NETRC_OPTIONAL;
1639 break;
1641 case 1:/* CURL_NETRC_IGNORED */
1642 netrc = CURL_NETRC_IGNORED;
1643 break;
1645 case 2: /* CURL_NETRC_REQUIRED */
1646 netrc = CURL_NETRC_REQUIRED;
1647 break;
1649 default:
1650 failwith("Invalid NETRC Option");
1651 break;
1654 result = curl_easy_setopt(conn->connection,
1655 CURLOPT_NETRC,
1656 netrc);
1658 if (result != CURLE_OK)
1659 raiseError(conn, result);
1661 CAMLreturn0;
1664 #if HAVE_DECL_CURLOPT_ENCODING
1665 static void handle_ENCODING(Connection *conn, value option)
1667 CAMLparam1(option);
1668 CURLcode result = CURLE_OK;
1670 switch (Long_val(option))
1672 case 0: /* CURL_ENCODING_NONE */
1673 result = curl_easy_setopt(conn->connection,
1674 CURLOPT_ENCODING,
1675 "identity");
1676 break;
1678 case 1: /* CURL_ENCODING_DEFLATE */
1679 result = curl_easy_setopt(conn->connection,
1680 CURLOPT_ENCODING,
1681 "deflate");
1682 break;
1684 case 2: /* CURL_ENCODING_GZIP */
1685 result = curl_easy_setopt(conn->connection,
1686 CURLOPT_ENCODING,
1687 "gzip");
1688 break;
1690 case 3: /* CURL_ENCODING_ANY */
1691 result = curl_easy_setopt(conn->connection,
1692 CURLOPT_ENCODING,
1693 "");
1694 break;
1696 default:
1697 failwith("Invalid Encoding Option");
1698 break;
1701 if (result != CURLE_OK)
1702 raiseError(conn, result);
1704 CAMLreturn0;
1706 #endif
1708 static void handle_FOLLOWLOCATION(Connection *conn, value option)
1710 CAMLparam1(option);
1711 CURLcode result = CURLE_OK;
1713 result = curl_easy_setopt(conn->connection,
1714 CURLOPT_FOLLOWLOCATION,
1715 Bool_val(option));
1717 if (result != CURLE_OK)
1718 raiseError(conn, result);
1720 CAMLreturn0;
1723 static void handle_TRANSFERTEXT(Connection *conn, value option)
1725 CAMLparam1(option);
1726 CURLcode result = CURLE_OK;
1728 result = curl_easy_setopt(conn->connection,
1729 CURLOPT_TRANSFERTEXT,
1730 Bool_val(option));
1732 if (result != CURLE_OK)
1733 raiseError(conn, result);
1735 CAMLreturn0;
1738 static void handle_PUT(Connection *conn, value option)
1740 CAMLparam1(option);
1741 CURLcode result = CURLE_OK;
1743 result = curl_easy_setopt(conn->connection,
1744 CURLOPT_PUT,
1745 Bool_val(option));
1747 if (result != CURLE_OK)
1748 raiseError(conn, result);
1750 CAMLreturn0;
1753 static void handle_USERPWD(Connection *conn, value option)
1755 CAMLparam1(option);
1756 CURLcode result = CURLE_OK;
1758 Store_field(conn->ocamlValues, OcamlUserPWD, option);
1760 if (conn->userPwd != NULL)
1761 free(conn->userPwd);
1763 conn->userPwd = strdup(String_val(option));
1765 result = curl_easy_setopt(conn->connection,
1766 CURLOPT_USERPWD,
1767 conn->userPwd);
1769 if (result != CURLE_OK)
1770 raiseError(conn, result);
1772 CAMLreturn0;
1775 static void handle_PROXYUSERPWD(Connection *conn, value option)
1777 CAMLparam1(option);
1778 CURLcode result = CURLE_OK;
1780 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
1782 if (conn->proxyUserPwd != NULL)
1783 free(conn->proxyUserPwd);
1785 conn->proxyUserPwd = strdup(String_val(option));
1787 result = curl_easy_setopt(conn->connection,
1788 CURLOPT_PROXYUSERPWD,
1789 conn->proxyUserPwd);
1791 if (result != CURLE_OK)
1792 raiseError(conn, result);
1794 CAMLreturn0;
1797 static void handle_RANGE(Connection *conn, value option)
1799 CAMLparam1(option);
1800 CURLcode result = CURLE_OK;
1802 Store_field(conn->ocamlValues, OcamlRange, option);
1804 if (conn->range != NULL)
1805 free(conn->range);
1807 conn->range = strdup(String_val(option));
1809 result = curl_easy_setopt(conn->connection,
1810 CURLOPT_RANGE,
1811 conn->range);
1813 if (result != CURLE_OK)
1814 raiseError(conn, result);
1816 CAMLreturn0;
1819 static void handle_ERRORBUFFER(Connection *conn, value option)
1821 CAMLparam1(option);
1822 CURLcode result = CURLE_OK;
1824 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
1826 if (conn->errorBuffer != NULL)
1827 free(conn->errorBuffer);
1829 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
1831 result = curl_easy_setopt(conn->connection,
1832 CURLOPT_ERRORBUFFER,
1833 conn->errorBuffer);
1835 if (result != CURLE_OK)
1836 raiseError(conn, result);
1838 CAMLreturn0;
1841 static void handle_TIMEOUT(Connection *conn, value option)
1843 CAMLparam1(option);
1844 CURLcode result = CURLE_OK;
1846 result = curl_easy_setopt(conn->connection,
1847 CURLOPT_TIMEOUT,
1848 Long_val(option));
1850 if (result != CURLE_OK)
1851 raiseError(conn, result);
1853 CAMLreturn0;
1856 static void handle_POSTFIELDS(Connection *conn, value option)
1858 CAMLparam1(option);
1859 CURLcode result = CURLE_OK;
1861 Store_field(conn->ocamlValues, OcamlPostFields, option);
1863 if (conn->postFields != NULL)
1864 free(conn->postFields);
1866 conn->postFields = malloc(string_length(option)+1);
1867 memcpy(conn->postFields, String_val(option), string_length(option)+1);
1869 result = curl_easy_setopt(conn->connection,
1870 CURLOPT_POSTFIELDS,
1871 conn->postFields);
1873 if (result != CURLE_OK)
1874 raiseError(conn, result);
1876 CAMLreturn0;
1879 static void handle_POSTFIELDSIZE(Connection *conn, value option)
1881 CAMLparam1(option);
1882 CURLcode result = CURLE_OK;
1884 result = curl_easy_setopt(conn->connection,
1885 CURLOPT_POSTFIELDSIZE,
1886 Long_val(option));
1888 if (result != CURLE_OK)
1889 raiseError(conn, result);
1891 CAMLreturn0;
1894 static void handle_REFERER(Connection *conn, value option)
1896 CAMLparam1(option);
1897 CURLcode result = CURLE_OK;
1899 Store_field(conn->ocamlValues, OcamlReferer, option);
1901 if (conn->referer != NULL)
1902 free(conn->referer);
1904 conn->referer = strdup(String_val(option));
1906 result = curl_easy_setopt(conn->connection,
1907 CURLOPT_REFERER,
1908 conn->referer);
1910 if (result != CURLE_OK)
1911 raiseError(conn, result);
1913 CAMLreturn0;
1916 static void handle_USERAGENT(Connection *conn, value option)
1918 CAMLparam1(option);
1919 CURLcode result = CURLE_OK;
1921 Store_field(conn->ocamlValues, OcamlUserAgent, option);
1923 if (conn->userAgent != NULL)
1924 free(conn->userAgent);
1926 conn->userAgent = strdup(String_val(option));
1928 result = curl_easy_setopt(conn->connection,
1929 CURLOPT_USERAGENT,
1930 conn->userAgent);
1932 if (result != CURLE_OK)
1933 raiseError(conn, result);
1935 CAMLreturn0;
1938 static void handle_FTPPORT(Connection *conn, value option)
1940 CAMLparam1(option);
1941 CURLcode result = CURLE_OK;
1943 Store_field(conn->ocamlValues, OcamlFTPPort, option);
1945 if (conn->ftpPort != NULL)
1946 free(conn->ftpPort);
1948 conn->ftpPort = strdup(String_val(option));
1950 result = curl_easy_setopt(conn->connection,
1951 CURLOPT_FTPPORT,
1952 conn->ftpPort);
1954 if (result != CURLE_OK)
1955 raiseError(conn, result);
1957 CAMLreturn0;
1960 static void handle_LOW_SPEED_LIMIT(Connection *conn, value option)
1962 CAMLparam1(option);
1963 CURLcode result = CURLE_OK;
1965 result = curl_easy_setopt(conn->connection,
1966 CURLOPT_LOW_SPEED_LIMIT,
1967 Long_val(option));
1969 if (result != CURLE_OK)
1970 raiseError(conn, result);
1972 CAMLreturn0;
1975 static void handle_LOW_SPEED_TIME(Connection *conn, value option)
1977 CAMLparam1(option);
1978 CURLcode result = CURLE_OK;
1980 result = curl_easy_setopt(conn->connection,
1981 CURLOPT_LOW_SPEED_TIME,
1982 Long_val(option));
1984 if (result != CURLE_OK)
1985 raiseError(conn, result);
1987 CAMLreturn0;
1990 static void handle_RESUME_FROM(Connection *conn, value option)
1992 CAMLparam1(option);
1993 CURLcode result = CURLE_OK;
1995 result = curl_easy_setopt(conn->connection,
1996 CURLOPT_RESUME_FROM,
1997 Long_val(option));
1999 if (result != CURLE_OK)
2000 raiseError(conn, result);
2002 CAMLreturn0;
2005 static void handle_COOKIE(Connection *conn, value option)
2007 CAMLparam1(option);
2008 CURLcode result = CURLE_OK;
2010 Store_field(conn->ocamlValues, OcamlCookie, option);
2012 if (conn->cookie != NULL)
2013 free(conn->cookie);
2015 conn->cookie = strdup(String_val(option));
2017 result = curl_easy_setopt(conn->connection,
2018 CURLOPT_COOKIE,
2019 conn->cookie);
2021 if (result != CURLE_OK)
2022 raiseError(conn, result);
2024 CAMLreturn0;
2027 static void handle_HTTPHEADER(Connection *conn, value option)
2029 CAMLparam1(option);
2030 CAMLlocal1(listIter);
2031 CURLcode result = CURLE_OK;
2033 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2035 free_curl_slist(conn->httpHeader);
2036 conn->httpHeader = NULL;
2038 listIter = option;
2040 while (!Is_long(listIter))
2042 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2044 listIter = Field(listIter, 1);
2047 result = curl_easy_setopt(conn->connection,
2048 CURLOPT_HTTPHEADER,
2049 conn->httpHeader);
2051 if (result != CURLE_OK)
2052 raiseError(conn, result);
2054 CAMLreturn0;
2057 static void handle_HTTPPOST(Connection *conn, value option)
2059 CAMLparam1(option);
2060 CAMLlocal3(listIter, formItem, contentType);
2061 CURLcode result = CURLE_OK;
2062 char *str1, *str2, *str3, *str4;
2064 listIter = option;
2066 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2068 if (conn->httpPostFirst != NULL)
2069 curl_formfree(conn->httpPostFirst);
2071 conn->httpPostFirst = NULL;
2072 conn->httpPostLast = NULL;
2074 free_curl_slist(conn->httpPostStrings);
2075 conn->httpPostStrings = NULL;
2077 while (!Is_long(listIter))
2079 formItem = Field(listIter, 0);
2081 switch (Tag_val(formItem))
2083 case 0: /* CURLFORM_CONTENT */
2084 if (Wosize_val(formItem) < 3)
2086 failwith("Incorrect CURLFORM_CONTENT parameters");
2089 if (Is_long(Field(formItem, 2)) &&
2090 Long_val(Field(formItem, 2)) == 0)
2092 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2093 memcpy(str1,
2094 String_val(Field(formItem, 0)),
2095 string_length(Field(formItem, 0)));
2096 str1[string_length(Field(formItem, 0))] = 0;
2097 conn->httpPostStrings =
2098 curl_slist_append(conn->httpPostStrings, str1);
2100 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2101 memcpy(str2,
2102 String_val(Field(formItem, 1)),
2103 string_length(Field(formItem, 1)));
2104 str2[string_length(Field(formItem, 1))] = 0;
2105 conn->httpPostStrings =
2106 curl_slist_append(conn->httpPostStrings, str2);
2108 curl_formadd(&conn->httpPostFirst,
2109 &conn->httpPostLast,
2110 CURLFORM_PTRNAME,
2111 str1,
2112 CURLFORM_NAMELENGTH,
2113 string_length(Field(formItem, 0)),
2114 CURLFORM_PTRCONTENTS,
2115 str2,
2116 CURLFORM_CONTENTSLENGTH,
2117 string_length(Field(formItem, 1)),
2118 CURLFORM_END);
2120 else if (Is_block(Field(formItem, 2)))
2122 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2123 memcpy(str1,
2124 String_val(Field(formItem, 0)),
2125 string_length(Field(formItem, 0)));
2126 str1[string_length(Field(formItem, 0))] = 0;
2127 conn->httpPostStrings =
2128 curl_slist_append(conn->httpPostStrings, str1);
2130 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2131 memcpy(str2,
2132 String_val(Field(formItem, 1)),
2133 string_length(Field(formItem, 1)));
2134 str2[string_length(Field(formItem, 1))] = 0;
2135 conn->httpPostStrings =
2136 curl_slist_append(conn->httpPostStrings, str2);
2138 contentType = Field(formItem, 2);
2140 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2141 memcpy(str3,
2142 String_val(Field(contentType, 0)),
2143 string_length(Field(contentType, 0)));
2144 str3[string_length(Field(contentType, 0))] = 0;
2145 conn->httpPostStrings =
2146 curl_slist_append(conn->httpPostStrings, str3);
2148 curl_formadd(&conn->httpPostFirst,
2149 &conn->httpPostLast,
2150 CURLFORM_PTRNAME,
2151 str1,
2152 CURLFORM_NAMELENGTH,
2153 string_length(Field(formItem, 0)),
2154 CURLFORM_PTRCONTENTS,
2155 str2,
2156 CURLFORM_CONTENTSLENGTH,
2157 string_length(Field(formItem, 1)),
2158 CURLFORM_CONTENTTYPE,
2159 str3,
2160 CURLFORM_END);
2162 else
2164 failwith("Incorrect CURLFORM_CONTENT parameters");
2166 break;
2168 case 1: /* CURLFORM_FILECONTENT */
2169 if (Wosize_val(formItem) < 3)
2171 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2174 if (Is_long(Field(formItem, 2)) &&
2175 Long_val(Field(formItem, 2)) == 0)
2177 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2178 memcpy(str1,
2179 String_val(Field(formItem, 0)),
2180 string_length(Field(formItem, 0)));
2181 str1[string_length(Field(formItem, 0))] = 0;
2182 conn->httpPostStrings =
2183 curl_slist_append(conn->httpPostStrings, str1);
2185 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2186 memcpy(str2,
2187 String_val(Field(formItem, 1)),
2188 string_length(Field(formItem, 1)));
2189 str2[string_length(Field(formItem, 1))] = 0;
2190 conn->httpPostStrings =
2191 curl_slist_append(conn->httpPostStrings, str2);
2193 curl_formadd(&conn->httpPostFirst,
2194 &conn->httpPostLast,
2195 CURLFORM_PTRNAME,
2196 str1,
2197 CURLFORM_NAMELENGTH,
2198 string_length(Field(formItem, 0)),
2199 CURLFORM_FILECONTENT,
2200 str2,
2201 CURLFORM_END);
2203 else if (Is_block(Field(formItem, 2)))
2205 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2206 memcpy(str1,
2207 String_val(Field(formItem, 0)),
2208 string_length(Field(formItem, 0)));
2209 str1[string_length(Field(formItem, 0))] = 0;
2210 conn->httpPostStrings =
2211 curl_slist_append(conn->httpPostStrings, str1);
2213 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2214 memcpy(str2,
2215 String_val(Field(formItem, 1)),
2216 string_length(Field(formItem, 1)));
2217 str2[string_length(Field(formItem, 1))] = 0;
2218 conn->httpPostStrings =
2219 curl_slist_append(conn->httpPostStrings, str2);
2221 contentType = Field(formItem, 2);
2223 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2224 memcpy(str3,
2225 String_val(Field(contentType, 0)),
2226 string_length(Field(contentType, 0)));
2227 str3[string_length(Field(contentType, 0))] = 0;
2228 conn->httpPostStrings =
2229 curl_slist_append(conn->httpPostStrings, str3);
2231 curl_formadd(&conn->httpPostFirst,
2232 &conn->httpPostLast,
2233 CURLFORM_PTRNAME,
2234 str1,
2235 CURLFORM_NAMELENGTH,
2236 string_length(Field(formItem, 0)),
2237 CURLFORM_FILECONTENT,
2238 str2,
2239 CURLFORM_CONTENTTYPE,
2240 str3,
2241 CURLFORM_END);
2243 else
2245 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2247 break;
2249 case 2: /* CURLFORM_FILE */
2250 if (Wosize_val(formItem) < 3)
2252 failwith("Incorrect CURLFORM_FILE parameters");
2255 if (Is_long(Field(formItem, 2)) &&
2256 Long_val(Field(formItem, 2)) == 0)
2258 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2259 memcpy(str1,
2260 String_val(Field(formItem, 0)),
2261 string_length(Field(formItem, 0)));
2262 str1[string_length(Field(formItem, 0))] = 0;
2263 conn->httpPostStrings =
2264 curl_slist_append(conn->httpPostStrings, str1);
2266 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2267 memcpy(str2,
2268 String_val(Field(formItem, 1)),
2269 string_length(Field(formItem, 1)));
2270 str2[string_length(Field(formItem, 1))] = 0;
2271 conn->httpPostStrings =
2272 curl_slist_append(conn->httpPostStrings, str2);
2274 curl_formadd(&conn->httpPostFirst,
2275 &conn->httpPostLast,
2276 CURLFORM_PTRNAME,
2277 str1,
2278 CURLFORM_NAMELENGTH,
2279 string_length(Field(formItem, 0)),
2280 CURLFORM_FILE,
2281 str2,
2282 CURLFORM_END);
2284 else if (Is_block(Field(formItem, 2)))
2286 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2287 memcpy(str1,
2288 String_val(Field(formItem, 0)),
2289 string_length(Field(formItem, 0)));
2290 str1[string_length(Field(formItem, 0))] = 0;
2291 conn->httpPostStrings =
2292 curl_slist_append(conn->httpPostStrings, str1);
2294 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2295 memcpy(str2,
2296 String_val(Field(formItem, 1)),
2297 string_length(Field(formItem, 1)));
2298 str2[string_length(Field(formItem, 1))] = 0;
2299 conn->httpPostStrings =
2300 curl_slist_append(conn->httpPostStrings, str2);
2302 contentType = Field(formItem, 2);
2304 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2305 memcpy(str3,
2306 String_val(Field(contentType, 0)),
2307 string_length(Field(contentType, 0)));
2308 str3[string_length(Field(contentType, 0))] = 0;
2309 conn->httpPostStrings =
2310 curl_slist_append(conn->httpPostStrings, str3);
2312 curl_formadd(&conn->httpPostFirst,
2313 &conn->httpPostLast,
2314 CURLFORM_PTRNAME,
2315 str1,
2316 CURLFORM_NAMELENGTH,
2317 string_length(Field(formItem, 0)),
2318 CURLFORM_FILE,
2319 str2,
2320 CURLFORM_CONTENTTYPE,
2321 str3,
2322 CURLFORM_END);
2324 else
2326 failwith("Incorrect CURLFORM_FILE parameters");
2328 break;
2330 case 3: /* CURLFORM_BUFFER */
2331 if (Wosize_val(formItem) < 4)
2333 failwith("Incorrect CURLFORM_BUFFER parameters");
2336 if (Is_long(Field(formItem, 3)) &&
2337 Long_val(Field(formItem, 3)) == 0)
2339 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2340 memcpy(str1,
2341 String_val(Field(formItem, 0)),
2342 string_length(Field(formItem, 0)));
2343 str1[string_length(Field(formItem, 0))] = 0;
2344 conn->httpPostStrings =
2345 curl_slist_append(conn->httpPostStrings, str1);
2347 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2348 memcpy(str2,
2349 String_val(Field(formItem, 1)),
2350 string_length(Field(formItem, 1)));
2351 str2[string_length(Field(formItem, 1))] = 0;
2352 conn->httpPostStrings =
2353 curl_slist_append(conn->httpPostStrings, str2);
2355 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2356 memcpy(str3,
2357 String_val(Field(formItem, 2)),
2358 string_length(Field(formItem, 2)));
2359 str3[string_length(Field(formItem, 2))] = 0;
2360 conn->httpPostStrings =
2361 curl_slist_append(conn->httpPostStrings, str3);
2363 curl_formadd(&conn->httpPostFirst,
2364 &conn->httpPostLast,
2365 CURLFORM_PTRNAME,
2366 str1,
2367 CURLFORM_NAMELENGTH,
2368 string_length(Field(formItem, 0)),
2369 CURLFORM_BUFFER,
2370 str2,
2371 CURLFORM_BUFFERPTR,
2372 str3,
2373 CURLFORM_BUFFERLENGTH,
2374 string_length(Field(formItem, 2)),
2375 CURLFORM_END);
2377 else if (Is_block(Field(formItem, 3)))
2379 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2380 memcpy(str1,
2381 String_val(Field(formItem, 0)),
2382 string_length(Field(formItem, 0)));
2383 str1[string_length(Field(formItem, 0))] = 0;
2384 conn->httpPostStrings =
2385 curl_slist_append(conn->httpPostStrings, str1);
2387 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2388 memcpy(str2,
2389 String_val(Field(formItem, 1)),
2390 string_length(Field(formItem, 1)));
2391 str2[string_length(Field(formItem, 1))] = 0;
2392 conn->httpPostStrings =
2393 curl_slist_append(conn->httpPostStrings, str2);
2395 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2396 memcpy(str3,
2397 String_val(Field(formItem, 2)),
2398 string_length(Field(formItem, 2)));
2399 str3[string_length(Field(formItem, 2))] = 0;
2400 conn->httpPostStrings =
2401 curl_slist_append(conn->httpPostStrings, str3);
2403 contentType = Field(formItem, 3);
2405 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
2406 memcpy(str4,
2407 String_val(Field(contentType, 0)),
2408 string_length(Field(contentType, 0)));
2409 str4[string_length(Field(contentType, 0))] = 0;
2410 conn->httpPostStrings =
2411 curl_slist_append(conn->httpPostStrings, str4);
2413 curl_formadd(&conn->httpPostFirst,
2414 &conn->httpPostLast,
2415 CURLFORM_PTRNAME,
2416 str1,
2417 CURLFORM_NAMELENGTH,
2418 string_length(Field(formItem, 0)),
2419 CURLFORM_BUFFER,
2420 str2,
2421 CURLFORM_BUFFERPTR,
2422 str3,
2423 CURLFORM_BUFFERLENGTH,
2424 string_length(Field(formItem, 2)),
2425 CURLFORM_CONTENTTYPE,
2426 str4,
2427 CURLFORM_END);
2429 else
2431 failwith("Incorrect CURLFORM_BUFFER parameters");
2433 break;
2436 listIter = Field(listIter, 1);
2439 result = curl_easy_setopt(conn->connection,
2440 CURLOPT_HTTPPOST,
2441 conn->httpPostFirst);
2443 if (result != CURLE_OK)
2444 raiseError(conn, result);
2446 CAMLreturn0;
2449 static void handle_SSLCERT(Connection *conn, value option)
2451 CAMLparam1(option);
2452 CURLcode result = CURLE_OK;
2454 Store_field(conn->ocamlValues, OcamlSSLCert, option);
2456 if (conn->sslCert != NULL)
2457 free(conn->sslCert);
2459 conn->sslCert = strdup(String_val(option));
2461 result = curl_easy_setopt(conn->connection,
2462 CURLOPT_SSLCERT,
2463 conn->sslCert);
2465 if (result != CURLE_OK)
2466 raiseError(conn, result);
2468 CAMLreturn0;
2471 static void handle_SSLCERTTYPE(Connection *conn, value option)
2473 CAMLparam1(option);
2474 CURLcode result = CURLE_OK;
2476 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
2478 if (conn->sslCertType != NULL)
2479 free(conn->sslCertType);
2481 conn->sslCertType = strdup(String_val(option));
2483 result = curl_easy_setopt(conn->connection,
2484 CURLOPT_SSLCERTTYPE,
2485 conn->sslCertType);
2487 if (result != CURLE_OK)
2488 raiseError(conn, result);
2490 CAMLreturn0;
2493 static void handle_SSLCERTPASSWD(Connection *conn, value option)
2495 CAMLparam1(option);
2496 CURLcode result = CURLE_OK;
2498 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
2500 if (conn->sslCertPasswd != NULL)
2501 free(conn->sslCertPasswd);
2503 conn->sslCertPasswd = strdup(String_val(option));
2505 result = curl_easy_setopt(conn->connection,
2506 CURLOPT_SSLCERTPASSWD,
2507 conn->sslCertPasswd);
2509 if (result != CURLE_OK)
2510 raiseError(conn, result);
2512 CAMLreturn0;
2515 static void handle_SSLKEY(Connection *conn, value option)
2517 CAMLparam1(option);
2518 CURLcode result = CURLE_OK;
2520 Store_field(conn->ocamlValues, OcamlSSLKey, option);
2522 if (conn->sslKey != NULL)
2523 free(conn->sslKey);
2525 conn->sslKey = strdup(String_val(option));
2527 result = curl_easy_setopt(conn->connection,
2528 CURLOPT_SSLKEY,
2529 conn->sslKey);
2531 if (result != CURLE_OK)
2532 raiseError(conn, result);
2534 CAMLreturn0;
2537 static void handle_SSLKEYTYPE(Connection *conn, value option)
2539 CAMLparam1(option);
2540 CURLcode result = CURLE_OK;
2542 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
2544 if (conn->sslKeyType != NULL)
2545 free(conn->sslKeyType);
2547 conn->sslKeyType = strdup(String_val(option));
2549 result = curl_easy_setopt(conn->connection,
2550 CURLOPT_SSLKEYTYPE,
2551 conn->sslKeyType);
2553 if (result != CURLE_OK)
2554 raiseError(conn, result);
2556 CAMLreturn0;
2559 static void handle_SSLKEYPASSWD(Connection *conn, value option)
2561 CAMLparam1(option);
2562 CURLcode result = CURLE_OK;
2564 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
2566 if (conn->sslKeyPasswd != NULL)
2567 free(conn->sslKeyPasswd);
2569 conn->sslKeyPasswd = strdup(String_val(option));
2571 result = curl_easy_setopt(conn->connection,
2572 CURLOPT_SSLKEYPASSWD,
2573 conn->sslKeyPasswd);
2575 if (result != CURLE_OK)
2576 raiseError(conn, result);
2578 CAMLreturn0;
2581 static void handle_SSLENGINE(Connection *conn, value option)
2583 CAMLparam1(option);
2584 CURLcode result = CURLE_OK;
2586 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
2588 if (conn->sslEngine != NULL)
2589 free(conn->sslEngine);
2591 conn->sslEngine = strdup(String_val(option));
2593 result = curl_easy_setopt(conn->connection,
2594 CURLOPT_SSLENGINE,
2595 conn->sslEngine);
2597 if (result != CURLE_OK)
2598 raiseError(conn, result);
2600 CAMLreturn0;
2603 static void handle_SSLENGINE_DEFAULT(Connection *conn, value option)
2605 CAMLparam1(option);
2606 CURLcode result = CURLE_OK;
2608 result = curl_easy_setopt(conn->connection,
2609 CURLOPT_SSLENGINE_DEFAULT,
2610 Bool_val(option));
2612 if (result != CURLE_OK)
2613 raiseError(conn, result);
2615 CAMLreturn0;
2618 static void handle_CRLF(Connection *conn, value option)
2620 CAMLparam1(option);
2621 CURLcode result = CURLE_OK;
2623 result = curl_easy_setopt(conn->connection,
2624 CURLOPT_CRLF,
2625 Bool_val(option));
2627 if (result != CURLE_OK)
2628 raiseError(conn, result);
2630 CAMLreturn0;
2633 static void handle_QUOTE(Connection *conn, value option)
2635 CAMLparam1(option);
2636 CAMLlocal1(listIter);
2637 CURLcode result = CURLE_OK;
2639 Store_field(conn->ocamlValues, OcamlQuote, option);
2641 free_curl_slist(conn->quote);
2642 conn->quote = NULL;
2644 listIter = option;
2646 while (!Is_long(listIter))
2648 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
2650 listIter = Field(listIter, 1);
2653 result = curl_easy_setopt(conn->connection,
2654 CURLOPT_QUOTE,
2655 conn->quote);
2657 if (result != CURLE_OK)
2658 raiseError(conn, result);
2660 CAMLreturn0;
2663 static void handle_POSTQUOTE(Connection *conn, value option)
2665 CAMLparam1(option);
2666 CAMLlocal1(listIter);
2667 CURLcode result = CURLE_OK;
2669 Store_field(conn->ocamlValues, OcamlPostQuote, option);
2671 free_curl_slist(conn->postQuote);
2672 conn->postQuote = NULL;
2674 listIter = option;
2676 while (!Is_long(listIter))
2678 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
2680 listIter = Field(listIter, 1);
2683 result = curl_easy_setopt(conn->connection,
2684 CURLOPT_POSTQUOTE,
2685 conn->postQuote);
2687 if (result != CURLE_OK)
2688 raiseError(conn, result);
2690 CAMLreturn0;
2693 static void handle_HEADERFUNCTION(Connection *conn, value option)
2695 CAMLparam1(option);
2696 CURLcode result = CURLE_OK;
2698 if (Tag_val(option) == Closure_tag)
2699 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
2700 else
2701 failwith("Not a proper closure");
2703 result = curl_easy_setopt(conn->connection,
2704 CURLOPT_HEADERFUNCTION,
2705 headerFunction);
2707 if (result != CURLE_OK)
2708 raiseError(conn, result);
2710 result = curl_easy_setopt(conn->connection,
2711 CURLOPT_WRITEHEADER,
2712 conn);
2714 if (result != CURLE_OK)
2715 raiseError(conn, result);
2717 CAMLreturn0;
2720 static void handle_COOKIEFILE(Connection *conn, value option)
2722 CAMLparam1(option);
2723 CURLcode result = CURLE_OK;
2725 Store_field(conn->ocamlValues, OcamlCookieFile, option);
2727 if (conn->cookieFile != NULL)
2728 free(conn->cookieFile);
2730 conn->cookieFile = strdup(String_val(option));
2732 result = curl_easy_setopt(conn->connection,
2733 CURLOPT_COOKIEFILE,
2734 conn->cookieFile);
2736 if (result != CURLE_OK)
2737 raiseError(conn, result);
2739 CAMLreturn0;
2742 static void handle_SSLVERSION(Connection *conn, value option)
2744 CAMLparam1(option);
2745 CURLcode result = CURLE_OK;
2747 result = curl_easy_setopt(conn->connection,
2748 CURLOPT_SSLVERSION,
2749 Long_val(option));
2751 if (result != CURLE_OK)
2752 raiseError(conn, result);
2754 CAMLreturn0;
2757 static void handle_TIMECONDITION(Connection *conn, value option)
2759 CAMLparam1(option);
2760 CURLcode result = CURLE_OK;
2761 int timecond = CURL_TIMECOND_NONE;
2763 switch (Long_val(option))
2765 case 0: timecond = CURL_TIMECOND_NONE; break;
2766 case 1: timecond = CURL_TIMECOND_IFMODSINCE; break;
2767 case 2: timecond = CURL_TIMECOND_IFUNMODSINCE; break;
2768 case 3: timecond = CURL_TIMECOND_LASTMOD; break;
2769 default:
2770 failwith("Invalid TIMECOND Option");
2771 break;
2774 result = curl_easy_setopt(conn->connection, CURLOPT_TIMECONDITION, timecond);
2776 if (result != CURLE_OK)
2777 raiseError(conn, result);
2779 CAMLreturn0;
2782 static void handle_TIMEVALUE(Connection *conn, value option)
2784 CAMLparam1(option);
2785 CURLcode result = CURLE_OK;
2787 result = curl_easy_setopt(conn->connection,
2788 CURLOPT_TIMEVALUE,
2789 Int32_val(option));
2791 if (result != CURLE_OK)
2792 raiseError(conn, result);
2794 CAMLreturn0;
2797 static void handle_CUSTOMREQUEST(Connection *conn, value option)
2799 CAMLparam1(option);
2800 CURLcode result = CURLE_OK;
2802 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
2804 if (conn->customRequest != NULL)
2805 free(conn->customRequest);
2807 conn->customRequest = strdup(String_val(option));
2809 result = curl_easy_setopt(conn->connection,
2810 CURLOPT_CUSTOMREQUEST,
2811 conn->customRequest);
2813 if (result != CURLE_OK)
2814 raiseError(conn, result);
2816 CAMLreturn0;
2819 static void handle_INTERFACE(Connection *conn, value option)
2821 CAMLparam1(option);
2822 CURLcode result = CURLE_OK;
2824 Store_field(conn->ocamlValues, OcamlInterface, option);
2826 if (conn->interface_ != NULL)
2827 free(conn->interface_);
2829 conn->interface_ = strdup(String_val(option));
2831 result = curl_easy_setopt(conn->connection,
2832 CURLOPT_INTERFACE,
2833 conn->interface_);
2835 if (result != CURLE_OK)
2836 raiseError(conn, result);
2838 CAMLreturn0;
2841 static void handle_KRB4LEVEL(Connection *conn, value option)
2843 CAMLparam1(option);
2844 CURLcode result = CURLE_OK;
2846 switch (Long_val(option))
2848 case 0: /* KRB4_NONE */
2849 result = curl_easy_setopt(conn->connection,
2850 CURLOPT_KRB4LEVEL,
2851 NULL);
2852 break;
2854 case 1: /* KRB4_CLEAR */
2855 result = curl_easy_setopt(conn->connection,
2856 CURLOPT_KRB4LEVEL,
2857 "clear");
2858 break;
2860 case 2: /* KRB4_SAFE */
2861 result = curl_easy_setopt(conn->connection,
2862 CURLOPT_KRB4LEVEL,
2863 "safe");
2864 break;
2866 case 3: /* KRB4_CONFIDENTIAL */
2867 result = curl_easy_setopt(conn->connection,
2868 CURLOPT_KRB4LEVEL,
2869 "confidential");
2870 break;
2872 case 4: /* KRB4_PRIVATE */
2873 result = curl_easy_setopt(conn->connection,
2874 CURLOPT_KRB4LEVEL,
2875 "private");
2876 break;
2878 default:
2879 failwith("Invalid KRB4 Option");
2880 break;
2883 if (result != CURLE_OK)
2884 raiseError(conn, result);
2886 CAMLreturn0;
2889 static void handle_PROGRESSFUNCTION(Connection *conn, value option)
2891 CAMLparam1(option);
2892 CURLcode result = CURLE_OK;
2894 if (Tag_val(option) == Closure_tag)
2895 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
2896 else
2897 failwith("Not a proper closure");
2899 result = curl_easy_setopt(conn->connection,
2900 CURLOPT_PROGRESSFUNCTION,
2901 progressFunction);
2902 if (result != CURLE_OK)
2903 raiseError(conn, result);
2905 result = curl_easy_setopt(conn->connection,
2906 CURLOPT_PROGRESSDATA,
2907 conn);
2909 if (result != CURLE_OK)
2910 raiseError(conn, result);
2912 CAMLreturn0;
2915 static void handle_SSL_VERIFYPEER(Connection *conn, value option)
2917 CAMLparam1(option);
2918 CURLcode result = CURLE_OK;
2920 result = curl_easy_setopt(conn->connection,
2921 CURLOPT_SSL_VERIFYPEER,
2922 Bool_val(option));
2924 if (result != CURLE_OK)
2925 raiseError(conn, result);
2927 CAMLreturn0;
2930 static void handle_CAINFO(Connection *conn, value option)
2932 CAMLparam1(option);
2933 CURLcode result = CURLE_OK;
2935 Store_field(conn->ocamlValues, OcamlCAInfo, option);
2937 if (conn->caInfo != NULL)
2938 free(conn->caInfo);
2940 conn->caInfo = strdup(String_val(option));
2942 result = curl_easy_setopt(conn->connection,
2943 CURLOPT_CAINFO,
2944 conn->caInfo);
2946 if (result != CURLE_OK)
2947 raiseError(conn, result);
2949 CAMLreturn0;
2952 static void handle_CAPATH(Connection *conn, value option)
2954 CAMLparam1(option);
2955 CURLcode result = CURLE_OK;
2957 Store_field(conn->ocamlValues, OcamlCAPath, option);
2959 if (conn->caPath != NULL)
2960 free(conn->caPath);
2962 conn->caPath = strdup(String_val(option));
2964 result = curl_easy_setopt(conn->connection,
2965 CURLOPT_CAPATH,
2966 conn->caPath);
2968 if (result != CURLE_OK)
2969 raiseError(conn, result);
2971 CAMLreturn0;
2974 static void handle_FILETIME(Connection *conn, value option)
2976 CAMLparam1(option);
2977 CURLcode result = CURLE_OK;
2979 result = curl_easy_setopt(conn->connection,
2980 CURLOPT_FILETIME,
2981 Bool_val(option));
2983 if (result != CURLE_OK)
2984 raiseError(conn, result);
2986 CAMLreturn0;
2989 static void handle_MAXREDIRS(Connection *conn, value option)
2991 CAMLparam1(option);
2992 CURLcode result = CURLE_OK;
2994 result = curl_easy_setopt(conn->connection,
2995 CURLOPT_MAXREDIRS,
2996 Long_val(option));
2998 if (result != CURLE_OK)
2999 raiseError(conn, result);
3001 CAMLreturn0;
3004 static void handle_MAXCONNECTS(Connection *conn, value option)
3006 CAMLparam1(option);
3007 CURLcode result = CURLE_OK;
3009 result = curl_easy_setopt(conn->connection,
3010 CURLOPT_MAXCONNECTS,
3011 Long_val(option));
3013 if (result != CURLE_OK)
3014 raiseError(conn, result);
3016 CAMLreturn0;
3019 static void handle_CLOSEPOLICY(Connection *conn, value option)
3021 CAMLparam1(option);
3022 CURLcode result = CURLE_OK;
3024 switch (Long_val(option))
3026 case 0: /* CLOSEPOLICY_OLDEST */
3027 result = curl_easy_setopt(conn->connection,
3028 CURLOPT_CLOSEPOLICY,
3029 CURLCLOSEPOLICY_OLDEST);
3030 break;
3032 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3033 result = curl_easy_setopt(conn->connection,
3034 CURLOPT_CLOSEPOLICY,
3035 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3036 break;
3038 default:
3039 failwith("Invalid CLOSEPOLICY Option");
3040 break;
3043 if (result != CURLE_OK)
3044 raiseError(conn, result);
3046 CAMLreturn0;
3049 static void handle_FRESH_CONNECT(Connection *conn, value option)
3051 CAMLparam1(option);
3052 CURLcode result = CURLE_OK;
3054 result = curl_easy_setopt(conn->connection,
3055 CURLOPT_FRESH_CONNECT,
3056 Bool_val(option));
3058 if (result != CURLE_OK)
3059 raiseError(conn, result);
3061 CAMLreturn0;
3064 static void handle_FORBID_REUSE(Connection *conn, value option)
3066 CAMLparam1(option);
3067 CURLcode result = CURLE_OK;
3069 result = curl_easy_setopt(conn->connection,
3070 CURLOPT_FORBID_REUSE,
3071 Bool_val(option));
3073 if (result != CURLE_OK)
3074 raiseError(conn, result);
3076 CAMLreturn0;
3079 static void handle_RANDOM_FILE(Connection *conn, value option)
3081 CAMLparam1(option);
3082 CURLcode result = CURLE_OK;
3084 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3086 if (conn->randomFile != NULL)
3087 free(conn->randomFile);
3089 conn->randomFile = strdup(String_val(option));
3091 result = curl_easy_setopt(conn->connection,
3092 CURLOPT_RANDOM_FILE,
3093 conn->randomFile);
3095 if (result != CURLE_OK)
3096 raiseError(conn, result);
3098 CAMLreturn0;
3101 static void handle_EGDSOCKET(Connection *conn, value option)
3103 CAMLparam1(option);
3104 CURLcode result = CURLE_OK;
3106 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3108 if (conn->egdSocket != NULL)
3109 free(conn->egdSocket);
3111 conn->egdSocket = strdup(String_val(option));
3113 result = curl_easy_setopt(conn->connection,
3114 CURLOPT_EGDSOCKET,
3115 conn->egdSocket);
3117 if (result != CURLE_OK)
3118 raiseError(conn, result);
3120 CAMLreturn0;
3123 static void handle_CONNECTTIMEOUT(Connection *conn, value option)
3125 CAMLparam1(option);
3126 CURLcode result = CURLE_OK;
3128 result = curl_easy_setopt(conn->connection,
3129 CURLOPT_CONNECTTIMEOUT,
3130 Long_val(option));
3132 if (result != CURLE_OK)
3133 raiseError(conn, result);
3135 CAMLreturn0;
3138 static void handle_HTTPGET(Connection *conn, value option)
3140 CAMLparam1(option);
3141 CURLcode result = CURLE_OK;
3143 result = curl_easy_setopt(conn->connection,
3144 CURLOPT_HTTPGET,
3145 Bool_val(option));
3147 if (result != CURLE_OK)
3148 raiseError(conn, result);
3150 CAMLreturn0;
3153 static void handle_SSL_VERIFYHOST(Connection *conn, value option)
3155 CAMLparam1(option);
3156 CURLcode result = CURLE_OK;
3158 switch (Long_val(option))
3160 case 0: /* SSLVERIFYHOST_NONE */
3161 case 1: /* SSLVERIFYHOST_EXISTENCE */
3162 case 2: /* SSLVERIFYHOST_HOSTNAME */
3163 result = curl_easy_setopt(conn->connection,
3164 CURLOPT_SSL_VERIFYHOST,
3165 /* map EXISTENCE to HOSTNAME */
3166 Long_val(option) == 0 ? 0 : 2);
3167 break;
3169 default:
3170 failwith("Invalid SSLVERIFYHOST Option");
3171 break;
3174 if (result != CURLE_OK)
3175 raiseError(conn, result);
3177 CAMLreturn0;
3180 static void handle_COOKIEJAR(Connection *conn, value option)
3182 CAMLparam1(option);
3183 CURLcode result = CURLE_OK;
3185 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3187 if (conn->cookieJar != NULL)
3188 free(conn->cookieJar);
3190 conn->cookieJar = strdup(String_val(option));
3192 result = curl_easy_setopt(conn->connection,
3193 CURLOPT_COOKIEJAR,
3194 conn->cookieJar);
3196 if (result != CURLE_OK)
3197 raiseError(conn, result);
3199 CAMLreturn0;
3202 static void handle_SSL_CIPHER_LIST(Connection *conn, value option)
3204 CAMLparam1(option);
3205 CURLcode result = CURLE_OK;
3207 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3209 if (conn->sslCipherList != NULL)
3210 free(conn->sslCipherList);
3212 conn->sslCipherList = strdup(String_val(option));
3214 result = curl_easy_setopt(conn->connection,
3215 CURLOPT_SSL_CIPHER_LIST,
3216 conn->sslCipherList);
3218 if (result != CURLE_OK)
3219 raiseError(conn, result);
3221 CAMLreturn0;
3224 static void handle_HTTP_VERSION(Connection *conn, value option)
3226 CAMLparam1(option);
3227 CURLcode result = CURLE_OK;
3229 switch (Long_val(option))
3231 case 0: /* HTTP_VERSION_NONE */
3232 result = curl_easy_setopt(conn->connection,
3233 CURLOPT_HTTP_VERSION,
3234 CURL_HTTP_VERSION_NONE);
3235 break;
3237 case 1: /* HTTP_VERSION_1_0 */
3238 result = curl_easy_setopt(conn->connection,
3239 CURLOPT_HTTP_VERSION,
3240 CURL_HTTP_VERSION_1_0);
3241 break;
3243 case 2: /* HTTP_VERSION_1_1 */
3244 result = curl_easy_setopt(conn->connection,
3245 CURLOPT_HTTP_VERSION,
3246 CURL_HTTP_VERSION_1_1);
3247 break;
3249 default:
3250 failwith("Invalid HTTP_VERSION Option");
3251 break;
3254 if (result != CURLE_OK)
3255 raiseError(conn, result);
3257 CAMLreturn0;
3260 static void handle_FTP_USE_EPSV(Connection *conn, value option)
3262 CAMLparam1(option);
3263 CURLcode result = CURLE_OK;
3265 result = curl_easy_setopt(conn->connection,
3266 CURLOPT_FTP_USE_EPSV,
3267 Bool_val(option));
3269 if (result != CURLE_OK)
3270 raiseError(conn, result);
3272 CAMLreturn0;
3275 static void handle_DNS_CACHE_TIMEOUT(Connection *conn, value option)
3277 CAMLparam1(option);
3278 CURLcode result = CURLE_OK;
3280 result = curl_easy_setopt(conn->connection,
3281 CURLOPT_DNS_CACHE_TIMEOUT,
3282 Long_val(option));
3284 if (result != CURLE_OK)
3285 raiseError(conn, result);
3287 CAMLreturn0;
3290 static void handle_DNS_USE_GLOBAL_CACHE(Connection *conn, value option)
3292 CAMLparam1(option);
3293 CURLcode result = CURLE_OK;
3295 result = curl_easy_setopt(conn->connection,
3296 CURLOPT_DNS_USE_GLOBAL_CACHE,
3297 Bool_val(option));
3299 if (result != CURLE_OK)
3300 raiseError(conn, result);
3302 CAMLreturn0;
3305 static void handle_DEBUGFUNCTION(Connection *conn, value option)
3307 CAMLparam1(option);
3308 CURLcode result = CURLE_OK;
3310 if (Tag_val(option) == Closure_tag)
3311 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3312 else
3313 failwith("Not a proper closure");
3315 result = curl_easy_setopt(conn->connection,
3316 CURLOPT_DEBUGFUNCTION,
3317 debugFunction);
3318 if (result != CURLE_OK)
3319 raiseError(conn, result);
3321 result = curl_easy_setopt(conn->connection,
3322 CURLOPT_DEBUGDATA,
3323 conn);
3325 if (result != CURLE_OK)
3326 raiseError(conn, result);
3328 CAMLreturn0;
3331 #if HAVE_DECL_CURLOPT_PRIVATE
3332 static void handle_PRIVATE(Connection *conn, value option)
3334 CAMLparam1(option);
3335 CURLcode result = CURLE_OK;
3337 Store_field(conn->ocamlValues, OcamlPrivate, option);
3339 if (conn->private != NULL)
3340 free(conn->private);
3342 conn->private = strdup(String_val(option));
3344 result = curl_easy_setopt(conn->connection,
3345 CURLOPT_PRIVATE,
3346 conn->private);
3348 if (result != CURLE_OK)
3349 raiseError(conn, result);
3351 CAMLreturn0;
3353 #endif
3355 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3356 static void handle_HTTP200ALIASES(Connection *conn, value option)
3358 CAMLparam1(option);
3359 CAMLlocal1(listIter);
3360 CURLcode result = CURLE_OK;
3362 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3364 free_curl_slist(conn->http200Aliases);
3365 conn->http200Aliases = NULL;
3367 listIter = option;
3369 while (!Is_long(listIter))
3371 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
3373 listIter = Field(listIter, 1);
3376 result = curl_easy_setopt(conn->connection,
3377 CURLOPT_HTTP200ALIASES,
3378 conn->http200Aliases);
3380 if (result != CURLE_OK)
3381 raiseError(conn, result);
3383 CAMLreturn0;
3385 #endif
3387 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
3388 static void handle_UNRESTRICTED_AUTH(Connection *conn, value option)
3390 CAMLparam1(option);
3391 CURLcode result = CURLE_OK;
3393 result = curl_easy_setopt(conn->connection,
3394 CURLOPT_UNRESTRICTED_AUTH,
3395 Bool_val(option));
3397 if (result != CURLE_OK)
3398 raiseError(conn, result);
3400 CAMLreturn0;
3402 #endif
3404 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
3405 static void handle_FTP_USE_EPRT(Connection *conn, value option)
3407 CAMLparam1(option);
3408 CURLcode result = CURLE_OK;
3410 result = curl_easy_setopt(conn->connection,
3411 CURLOPT_FTP_USE_EPRT,
3412 Bool_val(option));
3414 if (result != CURLE_OK)
3415 raiseError(conn, result);
3417 CAMLreturn0;
3419 #endif
3421 #if HAVE_DECL_CURLOPT_HTTPAUTH
3422 static void handle_HTTPAUTH(Connection *conn, value option)
3424 CAMLparam1(option);
3425 CAMLlocal1(listIter);
3426 CURLcode result = CURLE_OK;
3427 long auth = CURLAUTH_NONE;
3429 listIter = option;
3431 while (!Is_long(listIter))
3433 switch (Long_val(Field(listIter, 0)))
3435 case 0: /* CURLAUTH_BASIC */
3436 auth |= CURLAUTH_BASIC;
3437 break;
3439 case 1: /* CURLAUTH_DIGEST */
3440 auth |= CURLAUTH_DIGEST;
3441 break;
3443 case 2: /* CURLAUTH_GSSNEGOTIATE */
3444 auth |= CURLAUTH_GSSNEGOTIATE;
3445 break;
3447 case 3: /* CURLAUTH_NTLM */
3448 auth |= CURLAUTH_NTLM;
3449 break;
3451 case 4: /* CURLAUTH_ANY */
3452 auth |= CURLAUTH_ANY;
3453 break;
3455 case 5: /* CURLAUTH_ANYSAFE */
3456 auth |= CURLAUTH_ANYSAFE;
3457 break;
3459 default:
3460 failwith("Invalid HTTPAUTH Value");
3461 break;
3464 listIter = Field(listIter, 1);
3467 result = curl_easy_setopt(conn->connection,
3468 CURLOPT_HTTPAUTH,
3469 auth);
3471 if (result != CURLE_OK)
3472 raiseError(conn, result);
3474 CAMLreturn0;
3476 #endif
3478 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
3479 static void handle_FTP_CREATE_MISSING_DIRS(Connection *conn, value option)
3481 CAMLparam1(option);
3482 CURLcode result = CURLE_OK;
3484 result = curl_easy_setopt(conn->connection,
3485 CURLOPT_FTP_CREATE_MISSING_DIRS,
3486 Bool_val(option));
3488 if (result != CURLE_OK)
3489 raiseError(conn, result);
3491 CAMLreturn0;
3493 #endif
3495 #if HAVE_DECL_CURLOPT_PROXYAUTH
3496 static void handle_PROXYAUTH(Connection *conn, value option)
3498 CAMLparam1(option);
3499 CAMLlocal1(listIter);
3500 CURLcode result = CURLE_OK;
3501 long auth = CURLAUTH_NONE;
3503 listIter = option;
3505 while (!Is_long(listIter))
3507 switch (Long_val(Field(listIter, 0)))
3509 case 0: /* CURLAUTH_BASIC */
3510 auth |= CURLAUTH_BASIC;
3511 break;
3513 case 1: /* CURLAUTH_DIGEST */
3514 auth |= CURLAUTH_DIGEST;
3515 break;
3517 case 2: /* CURLAUTH_GSSNEGOTIATE */
3518 auth |= CURLAUTH_GSSNEGOTIATE;
3519 break;
3521 case 3: /* CURLAUTH_NTLM */
3522 auth |= CURLAUTH_NTLM;
3523 break;
3525 case 4: /* CURLAUTH_ANY */
3526 auth |= CURLAUTH_ANY;
3527 break;
3529 case 5: /* CURLAUTH_ANYSAFE */
3530 auth |= CURLAUTH_ANYSAFE;
3531 break;
3533 default:
3534 failwith("Invalid HTTPAUTH Value");
3535 break;
3538 listIter = Field(listIter, 1);
3541 result = curl_easy_setopt(conn->connection,
3542 CURLOPT_PROXYAUTH,
3543 auth);
3545 if (result != CURLE_OK)
3546 raiseError(conn, result);
3548 CAMLreturn0;
3550 #endif
3552 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
3553 static void handle_FTP_RESPONSE_TIMEOUT(Connection *conn, value option)
3555 CAMLparam1(option);
3556 CURLcode result = CURLE_OK;
3558 result = curl_easy_setopt(conn->connection,
3559 CURLOPT_FTP_RESPONSE_TIMEOUT,
3560 Long_val(option));
3562 if (result != CURLE_OK)
3563 raiseError(conn, result);
3565 CAMLreturn0;
3567 #endif
3569 #if HAVE_DECL_CURLOPT_IPRESOLVE
3570 static void handle_IPRESOLVE(Connection *conn, value option)
3572 CAMLparam1(option);
3573 CURLcode result = CURLE_OK;
3575 switch (Long_val(option))
3577 case 0: /* CURL_IPRESOLVE_WHATEVER */
3578 result = curl_easy_setopt(conn->connection,
3579 CURLOPT_IPRESOLVE,
3580 CURL_IPRESOLVE_WHATEVER);
3581 break;
3583 case 1: /* CURL_IPRESOLVE_V4 */
3584 result = curl_easy_setopt(conn->connection,
3585 CURLOPT_IPRESOLVE,
3586 CURL_IPRESOLVE_V4);
3587 break;
3589 case 2: /* CURL_IPRESOLVE_V6 */
3590 result = curl_easy_setopt(conn->connection,
3591 CURLOPT_IPRESOLVE,
3592 CURL_IPRESOLVE_V6);
3593 break;
3595 default:
3596 failwith("Invalid IPRESOLVE Value");
3597 break;
3600 if (result != CURLE_OK)
3601 raiseError(conn, result);
3603 CAMLreturn0;
3605 #endif
3607 #if HAVE_DECL_CURLOPT_MAXFILESIZE
3608 static void handle_MAXFILESIZE(Connection *conn, value option)
3610 CAMLparam1(option);
3611 CURLcode result = CURLE_OK;
3613 result = curl_easy_setopt(conn->connection,
3614 CURLOPT_MAXFILESIZE,
3615 Int32_val(option));
3617 if (result != CURLE_OK)
3618 raiseError(conn, result);
3620 CAMLreturn0;
3622 #endif
3624 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
3625 static void handle_INFILESIZE_LARGE(Connection *conn, value option)
3627 CAMLparam1(option);
3628 CURLcode result = CURLE_OK;
3630 result = curl_easy_setopt(conn->connection,
3631 CURLOPT_INFILESIZE_LARGE,
3632 Int64_val(option));
3634 if (result != CURLE_OK)
3635 raiseError(conn, result);
3637 CAMLreturn0;
3639 #endif
3641 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
3642 static void handle_RESUME_FROM_LARGE(Connection *conn, value option)
3644 CAMLparam1(option);
3645 CURLcode result = CURLE_OK;
3647 result = curl_easy_setopt(conn->connection,
3648 CURLOPT_RESUME_FROM_LARGE,
3649 Int64_val(option));
3651 if (result != CURLE_OK)
3652 raiseError(conn, result);
3654 CAMLreturn0;
3656 #endif
3658 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
3659 static void handle_MAXFILESIZE_LARGE(Connection *conn, value option)
3661 CAMLparam1(option);
3662 CURLcode result = CURLE_OK;
3664 result = curl_easy_setopt(conn->connection,
3665 CURLOPT_MAXFILESIZE_LARGE,
3666 Int64_val(option));
3668 if (result != CURLE_OK)
3669 raiseError(conn, result);
3671 CAMLreturn0;
3673 #endif
3675 #if HAVE_DECL_CURLOPT_NETRC_FILE
3676 static void handle_NETRC_FILE(Connection *conn, value option)
3678 CAMLparam1(option);
3679 CURLcode result = CURLE_OK;
3681 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
3683 if (conn->netrcFile != NULL)
3684 free(conn->netrcFile);
3686 conn->netrcFile = strdup(String_val(option));
3688 result = curl_easy_setopt(conn->connection,
3689 CURLOPT_NETRC_FILE,
3690 conn->netrcFile);
3692 if (result != CURLE_OK)
3693 raiseError(conn, result);
3695 CAMLreturn0;
3697 #endif
3699 #if HAVE_DECL_CURLOPT_FTP_SSL
3700 static void handle_FTP_SSL(Connection *conn, value option)
3702 CAMLparam1(option);
3703 CURLcode result = CURLE_OK;
3705 switch (Long_val(option))
3707 case 0: /* CURLFTPSSL_NONE */
3708 result = curl_easy_setopt(conn->connection,
3709 CURLOPT_FTP_SSL,
3710 CURLFTPSSL_NONE);
3711 break;
3713 case 1: /* CURLFTPSSL_TRY */
3714 result = curl_easy_setopt(conn->connection,
3715 CURLOPT_FTP_SSL,
3716 CURLFTPSSL_TRY);
3717 break;
3719 case 2: /* CURLFTPSSL_CONTROL */
3720 result = curl_easy_setopt(conn->connection,
3721 CURLOPT_FTP_SSL,
3722 CURLFTPSSL_CONTROL);
3723 break;
3725 case 3: /* CURLFTPSSL_ALL */
3726 result = curl_easy_setopt(conn->connection,
3727 CURLOPT_FTP_SSL,
3728 CURLFTPSSL_ALL);
3729 break;
3731 default:
3732 failwith("Invalid FTP_SSL Value");
3733 break;
3736 if (result != CURLE_OK)
3737 raiseError(conn, result);
3739 CAMLreturn0;
3741 #endif
3743 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
3744 static void handle_POSTFIELDSIZE_LARGE(Connection *conn, value option)
3746 CAMLparam1(option);
3747 CURLcode result = CURLE_OK;
3749 result = curl_easy_setopt(conn->connection,
3750 CURLOPT_POSTFIELDSIZE_LARGE,
3751 Int64_val(option));
3753 if (result != CURLE_OK)
3754 raiseError(conn, result);
3756 CAMLreturn0;
3758 #endif
3760 #if HAVE_DECL_CURLOPT_TCP_NODELAY
3761 static void handle_TCP_NODELAY(Connection *conn, value option)
3763 CAMLparam1(option);
3764 CURLcode result = CURLE_OK;
3766 result = curl_easy_setopt(conn->connection,
3767 CURLOPT_TCP_NODELAY,
3768 Bool_val(option));
3770 if (result != CURLE_OK)
3771 raiseError(conn, result);
3773 CAMLreturn0;
3775 #endif
3777 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
3778 static void handle_FTPSSLAUTH(Connection *conn, value option)
3780 CAMLparam1(option);
3781 CURLcode result = CURLE_OK;
3783 switch (Long_val(option))
3785 case 0: /* CURLFTPAUTH_DEFAULT */
3786 result = curl_easy_setopt(conn->connection,
3787 CURLOPT_FTPSSLAUTH,
3788 CURLFTPAUTH_DEFAULT);
3789 break;
3791 case 1: /* CURLFTPAUTH_SSL */
3792 result = curl_easy_setopt(conn->connection,
3793 CURLOPT_FTPSSLAUTH,
3794 CURLFTPAUTH_SSL);
3795 break;
3797 case 2: /* CURLFTPAUTH_TLS */
3798 result = curl_easy_setopt(conn->connection,
3799 CURLOPT_FTPSSLAUTH,
3800 CURLFTPAUTH_TLS);
3801 break;
3803 default:
3804 failwith("Invalid FTPSSLAUTH value");
3805 break;
3808 if (result != CURLE_OK)
3809 raiseError(conn, result);
3811 CAMLreturn0;
3813 #endif
3815 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
3816 static void handle_IOCTLFUNCTION(Connection *conn, value option)
3818 CAMLparam1(option);
3819 CURLcode result = CURLE_OK;
3821 if (Tag_val(option) == Closure_tag)
3822 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
3823 else
3824 failwith("Not a proper closure");
3826 result = curl_easy_setopt(conn->connection,
3827 CURLOPT_IOCTLFUNCTION,
3828 ioctlFunction);
3829 if (result != CURLE_OK)
3830 raiseError(conn, result);
3832 result = curl_easy_setopt(conn->connection,
3833 CURLOPT_DEBUGDATA,
3834 conn);
3836 if (result != CURLE_OK)
3837 raiseError(conn, result);
3839 CAMLreturn0;
3841 #endif
3843 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
3844 static void handle_FTP_ACCOUNT(Connection *conn, value option)
3846 CAMLparam1(option);
3847 CURLcode result = CURLE_OK;
3849 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
3851 if (conn->ftpaccount != NULL)
3852 free(conn->ftpaccount);
3854 conn->ftpaccount = strdup(String_val(option));
3856 result = curl_easy_setopt(conn->connection,
3857 CURLOPT_FTP_ACCOUNT,
3858 conn->ftpaccount);
3860 if (result != CURLE_OK)
3861 raiseError(conn, result);
3863 CAMLreturn0;
3865 #endif
3867 #if HAVE_DECL_CURLOPT_COOKIELIST
3868 static void handle_COOKIELIST(Connection *conn, value option)
3870 CAMLparam1(option);
3871 CURLcode result = CURLE_OK;
3873 Store_field(conn->ocamlValues, OcamlCookieList, option);
3875 if (conn->cookielist != NULL)
3876 free(conn->cookielist);
3878 conn->cookielist = strdup(String_val(option));
3880 result = curl_easy_setopt(conn->connection,
3881 CURLOPT_COOKIELIST,
3882 conn->cookielist);
3884 if (result != CURLE_OK)
3885 raiseError(conn, result);
3887 CAMLreturn0;
3889 #endif
3891 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
3892 static void handle_IGNORE_CONTENT_LENGTH(Connection *conn, value option)
3894 CAMLparam1(option);
3895 CURLcode result = CURLE_OK;
3897 result = curl_easy_setopt(conn->connection,
3898 CURLOPT_IGNORE_CONTENT_LENGTH,
3899 Bool_val(option));
3901 if (result != CURLE_OK)
3902 raiseError(conn, result);
3904 CAMLreturn0;
3906 #endif
3908 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
3909 static void handle_FTP_SKIP_PASV_IP(Connection *conn, value option)
3911 CAMLparam1(option);
3912 CURLcode result = CURLE_OK;
3914 result = curl_easy_setopt(conn->connection,
3915 CURLOPT_FTP_SKIP_PASV_IP,
3916 Bool_val(option));
3918 if (result != CURLE_OK)
3919 raiseError(conn, result);
3921 CAMLreturn0;
3923 #endif
3925 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
3926 static void handle_FTP_FILEMETHOD(Connection *conn, value option)
3928 CAMLparam1(option);
3929 CURLcode result = CURLE_OK;
3931 switch (Long_val(option))
3933 case 0: /* CURLFTPMETHOD_DEFAULT */
3934 result = curl_easy_setopt(conn->connection,
3935 CURLOPT_FTP_FILEMETHOD,
3936 CURLFTPMETHOD_DEFAULT);
3937 break;
3939 case 1: /* CURLFTMETHOD_MULTICWD */
3940 result = curl_easy_setopt(conn->connection,
3941 CURLOPT_FTP_FILEMETHOD,
3942 CURLFTPMETHOD_MULTICWD);
3943 break;
3945 case 2: /* CURLFTPMETHOD_NOCWD */
3946 result = curl_easy_setopt(conn->connection,
3947 CURLOPT_FTP_FILEMETHOD,
3948 CURLFTPMETHOD_NOCWD);
3949 break;
3951 case 3: /* CURLFTPMETHOD_SINGLECWD */
3952 result = curl_easy_setopt(conn->connection,
3953 CURLOPT_FTP_FILEMETHOD,
3954 CURLFTPMETHOD_SINGLECWD);
3956 default:
3957 failwith("Invalid FTP_FILEMETHOD value");
3958 break;
3961 if (result != CURLE_OK)
3962 raiseError(conn, result);
3964 CAMLreturn0;
3966 #endif
3968 #if HAVE_DECL_CURLOPT_LOCALPORT
3969 static void handle_LOCALPORT(Connection *conn, value option)
3971 CAMLparam1(option);
3972 CURLcode result = CURLE_OK;
3974 result = curl_easy_setopt(conn->connection,
3975 CURLOPT_LOCALPORT,
3976 Long_val(option));
3978 if (result != CURLE_OK)
3979 raiseError(conn, result);
3981 CAMLreturn0;
3983 #endif
3985 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
3986 static void handle_LOCALPORTRANGE(Connection *conn, value option)
3988 CAMLparam1(option);
3989 CURLcode result = CURLE_OK;
3991 result = curl_easy_setopt(conn->connection,
3992 CURLOPT_LOCALPORTRANGE,
3993 Long_val(option));
3995 if (result != CURLE_OK)
3996 raiseError(conn, result);
3998 CAMLreturn0;
4000 #endif
4002 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4003 static void handle_CONNECT_ONLY(Connection *conn, value option)
4005 CAMLparam1(option);
4006 CURLcode result = CURLE_OK;
4008 result = curl_easy_setopt(conn->connection,
4009 CURLOPT_CONNECT_ONLY,
4010 Bool_val(option));
4012 if (result != CURLE_OK)
4013 raiseError(conn, result);
4015 CAMLreturn0;
4017 #endif
4019 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4020 static void handle_MAX_SEND_SPEED_LARGE(Connection *conn, value option)
4022 CAMLparam1(option);
4023 CURLcode result = CURLE_OK;
4025 result = curl_easy_setopt(conn->connection,
4026 CURLOPT_MAX_SEND_SPEED_LARGE,
4027 Int64_val(option));
4029 if (result != CURLE_OK)
4030 raiseError(conn, result);
4032 CAMLreturn0;
4034 #endif
4036 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4037 static void handle_MAX_RECV_SPEED_LARGE(Connection *conn, value option)
4039 CAMLparam1(option);
4040 CURLcode result = CURLE_OK;
4042 result = curl_easy_setopt(conn->connection,
4043 CURLOPT_MAX_RECV_SPEED_LARGE,
4044 Int64_val(option));
4046 if (result != CURLE_OK)
4047 raiseError(conn, result);
4049 CAMLreturn0;
4051 #endif
4053 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4054 static void handle_FTP_ALTERNATIVE_TO_USER(Connection *conn, value option)
4056 CAMLparam1(option);
4057 CURLcode result = CURLE_OK;
4059 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4061 if (conn->ftpAlternativeToUser != NULL)
4062 free(conn->ftpAlternativeToUser);
4064 conn->ftpAlternativeToUser = strdup(String_val(option));
4066 result = curl_easy_setopt(conn->connection,
4067 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4068 conn->ftpAlternativeToUser);
4070 if (result != CURLE_OK)
4071 raiseError(conn, result);
4073 CAMLreturn0;
4075 #endif
4077 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4078 static void handle_SSL_SESSIONID_CACHE(Connection *conn, value option)
4080 CAMLparam1(option);
4081 CURLcode result = CURLE_OK;
4083 result = curl_easy_setopt(conn->connection,
4084 CURLOPT_SSL_SESSIONID_CACHE,
4085 Bool_val(option));
4087 if (result != CURLE_OK)
4088 raiseError(conn, result);
4090 CAMLreturn0;
4092 #endif
4094 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4095 static void handle_SSH_AUTH_TYPES(Connection *conn, value option)
4097 CAMLparam1(option);
4098 CAMLlocal1(listIter);
4099 CURLcode result = CURLE_OK;
4100 long authTypes = CURLSSH_AUTH_NONE;
4102 listIter = option;
4104 while (!Is_long(listIter))
4106 switch (Long_val(Field(listIter, 0)))
4108 case 0: /* CURLSSH_AUTH_ANY */
4109 authTypes |= CURLSSH_AUTH_ANY;
4110 break;
4112 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4113 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4114 break;
4116 case 2: /* CURLSSH_AUTH_PASSWORD */
4117 authTypes |= CURLSSH_AUTH_PASSWORD;
4118 break;
4120 case 3: /* CURLSSH_AUTH_HOST */
4121 authTypes |= CURLSSH_AUTH_HOST;
4122 break;
4124 case 4: /* CURLSSH_AUTH_KEYBOARD */
4125 authTypes |= CURLSSH_AUTH_KEYBOARD;
4126 break;
4128 default:
4129 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4130 break;
4133 listIter = Field(listIter, 1);
4136 result = curl_easy_setopt(conn->connection,
4137 CURLOPT_SSH_AUTH_TYPES,
4138 authTypes);
4140 if (result != CURLE_OK)
4141 raiseError(conn, result);
4143 CAMLreturn0;
4145 #endif
4147 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4148 static void handle_SSH_PUBLIC_KEYFILE(Connection *conn, value option)
4150 CAMLparam1(option);
4151 CURLcode result = CURLE_OK;
4153 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4155 if (conn->sshPublicKeyFile != NULL)
4156 free(conn->sshPublicKeyFile);
4158 conn->sshPublicKeyFile = strdup(String_val(option));
4160 result = curl_easy_setopt(conn->connection,
4161 CURLOPT_SSH_PUBLIC_KEYFILE,
4162 conn->sshPublicKeyFile);
4164 if (result != CURLE_OK)
4165 raiseError(conn, result);
4167 CAMLreturn0;
4169 #endif
4171 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4172 static void handle_SSH_PRIVATE_KEYFILE(Connection *conn, value option)
4174 CAMLparam1(option);
4175 CURLcode result = CURLE_OK;
4177 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4179 if (conn->sshPrivateKeyFile != NULL)
4180 free(conn->sshPrivateKeyFile);
4182 conn->sshPrivateKeyFile = strdup(String_val(option));
4184 result = curl_easy_setopt(conn->connection,
4185 CURLOPT_SSH_PRIVATE_KEYFILE,
4186 conn->sshPrivateKeyFile);
4188 if (result != CURLE_OK)
4189 raiseError(conn, result);
4191 CAMLreturn0;
4193 #endif
4195 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4196 static void handle_FTP_SSL_CCC(Connection *conn, value option)
4198 CAMLparam1(option);
4199 CURLcode result = CURLE_OK;
4201 switch (Long_val(option))
4203 case 0: /* CURLFTPSSL_CCC_NONE */
4204 result = curl_easy_setopt(conn->connection,
4205 CURLOPT_FTP_SSL_CCC,
4206 CURLFTPSSL_CCC_NONE);
4207 break;
4209 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4210 result = curl_easy_setopt(conn->connection,
4211 CURLOPT_FTP_SSL_CCC,
4212 CURLFTPSSL_CCC_PASSIVE);
4213 break;
4215 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4216 result = curl_easy_setopt(conn->connection,
4217 CURLOPT_FTP_SSL_CCC,
4218 CURLFTPSSL_CCC_ACTIVE);
4219 break;
4221 default:
4222 failwith("Invalid FTPSSL_CCC value");
4223 break;
4226 if (result != CURLE_OK)
4227 raiseError(conn, result);
4229 CAMLreturn0;
4231 #endif
4233 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4234 static void handle_TIMEOUT_MS(Connection *conn, value option)
4236 CAMLparam1(option);
4237 CURLcode result = CURLE_OK;
4239 result = curl_easy_setopt(conn->connection,
4240 CURLOPT_TIMEOUT_MS,
4241 Long_val(option));
4243 if (result != CURLE_OK)
4244 raiseError(conn, result);
4246 CAMLreturn0;
4248 #endif
4250 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4251 static void handle_CONNECTTIMEOUT_MS(Connection *conn, value option)
4253 CAMLparam1(option);
4254 CURLcode result = CURLE_OK;
4256 result = curl_easy_setopt(conn->connection,
4257 CURLOPT_CONNECTTIMEOUT_MS,
4258 Long_val(option));
4260 if (result != CURLE_OK)
4261 raiseError(conn, result);
4263 CAMLreturn0;
4265 #endif
4267 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4268 static void handle_HTTP_TRANSFER_DECODING(Connection *conn, value option)
4270 CAMLparam1(option);
4271 CURLcode result = CURLE_OK;
4273 result = curl_easy_setopt(conn->connection,
4274 CURLOPT_HTTP_TRANSFER_DECODING,
4275 Bool_val(option));
4277 if (result != CURLE_OK)
4278 raiseError(conn, result);
4280 CAMLreturn0;
4282 #endif
4284 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4285 static void handle_HTTP_CONTENT_DECODING(Connection *conn, value option)
4287 CAMLparam1(option);
4288 CURLcode result = CURLE_OK;
4290 result = curl_easy_setopt(conn->connection,
4291 CURLOPT_HTTP_CONTENT_DECODING,
4292 Bool_val(option));
4294 if (result != CURLE_OK)
4295 raiseError(conn, result);
4297 CAMLreturn0;
4299 #endif
4301 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
4302 static void handle_NEW_FILE_PERMS(Connection *conn, value option)
4304 CAMLparam1(option);
4305 CURLcode result = CURLE_OK;
4307 result = curl_easy_setopt(conn->connection,
4308 CURLOPT_NEW_FILE_PERMS,
4309 Long_val(option));
4311 if (result != CURLE_OK)
4312 raiseError(conn, result);
4314 CAMLreturn0;
4316 #endif
4318 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
4319 static void handle_NEW_DIRECTORY_PERMS(Connection *conn, value option)
4321 CAMLparam1(option);
4322 CURLcode result = CURLE_OK;
4324 result = curl_easy_setopt(conn->connection,
4325 CURLOPT_NEW_DIRECTORY_PERMS,
4326 Long_val(option));
4328 if (result != CURLE_OK)
4329 raiseError(conn, result);
4331 CAMLreturn0;
4333 #endif
4335 #if HAVE_DECL_CURLOPT_POST301
4336 static void handle_POST301(Connection *conn, value option)
4338 CAMLparam1(option);
4339 CURLcode result = CURLE_OK;
4341 result = curl_easy_setopt(conn->connection,
4342 CURLOPT_POST301,
4343 Bool_val(option));
4345 if (result != CURLE_OK)
4346 raiseError(conn, result);
4348 CAMLreturn0;
4350 #endif
4352 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
4353 static void handle_SSH_HOST_PUBLIC_KEY_MD5(Connection *conn, value option)
4355 CAMLparam1(option);
4356 CURLcode result = CURLE_OK;
4358 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
4360 if (conn->sshHostPublicKeyMD5 != NULL)
4361 free(conn->sshHostPublicKeyMD5);
4363 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
4365 result = curl_easy_setopt(conn->connection,
4366 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
4367 conn->sshHostPublicKeyMD5);
4369 if (result != CURLE_OK)
4370 raiseError(conn, result);
4372 CAMLreturn0;
4374 #endif
4376 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
4377 static void handle_COPYPOSTFIELDS(Connection *conn, value option)
4379 CAMLparam1(option);
4380 CURLcode result = CURLE_OK;
4382 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
4384 if (conn->copyPostFields != NULL)
4385 free(conn->copyPostFields);
4387 conn->copyPostFields = strdup(String_val(option));
4389 result = curl_easy_setopt(conn->connection,
4390 CURLOPT_COPYPOSTFIELDS,
4391 conn->copyPostFields);
4393 if (result != CURLE_OK)
4394 raiseError(conn, result);
4396 CAMLreturn0;
4398 #endif
4400 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
4401 static void handle_PROXY_TRANSFER_MODE(Connection *conn, value option)
4403 CAMLparam1(option);
4404 CURLcode result = CURLE_OK;
4406 result = curl_easy_setopt(conn->connection,
4407 CURLOPT_PROXY_TRANSFER_MODE,
4408 Bool_val(option));
4410 if (result != CURLE_OK)
4411 raiseError(conn, result);
4413 CAMLreturn0;
4415 #endif
4417 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
4418 static void handle_SEEKFUNCTION(Connection *conn, value option)
4420 CAMLparam1(option);
4421 CURLcode result = CURLE_OK;
4423 if (Tag_val(option) == Closure_tag)
4424 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
4425 else
4426 failwith("Not a proper closure");
4428 result = curl_easy_setopt(conn->connection,
4429 CURLOPT_SEEKFUNCTION,
4430 seekFunction);
4432 if (result != CURLE_OK)
4433 raiseError(conn, result);
4435 result = curl_easy_setopt(conn->connection,
4436 CURLOPT_SEEKDATA,
4437 conn);
4439 if (result != CURLE_OK)
4440 raiseError(conn, result);
4442 CAMLreturn0;
4444 #endif
4446 #if HAVE_DECL_CURLOPT_AUTOREFERER
4447 static void handle_AUTOREFERER(Connection *conn, value option)
4449 CAMLparam1(option);
4450 CURLcode result = curl_easy_setopt(conn->connection,
4451 CURLOPT_AUTOREFERER,
4452 Bool_val(option));
4454 if (result != CURLE_OK)
4455 raiseError(conn, result);
4457 CAMLreturn0;
4459 #endif
4461 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
4462 static void handle_OPENSOCKETFUNCTION(Connection *conn, value option)
4464 CAMLparam1(option);
4465 CURLcode result = CURLE_OK;
4467 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
4469 result = curl_easy_setopt(conn->connection,
4470 CURLOPT_OPENSOCKETDATA,
4471 conn);
4473 if (result != CURLE_OK)
4474 raiseError(conn, result);
4476 result = curl_easy_setopt(conn->connection,
4477 CURLOPT_OPENSOCKETFUNCTION,
4478 openSocketFunction);
4480 if (result != CURLE_OK)
4481 raiseError(conn, result);
4483 CAMLreturn0;
4485 #endif
4487 #if HAVE_DECL_CURLOPT_PROXYTYPE
4488 static void handle_PROXYTYPE(Connection *conn, value option)
4490 CAMLparam1(option);
4491 CURLcode result = CURLE_OK;
4492 long proxy_type;
4494 switch (Long_val(option))
4496 case 0: proxy_type = CURLPROXY_HTTP; break;
4497 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
4498 case 2: proxy_type = CURLPROXY_SOCKS4; break;
4499 case 3: proxy_type = CURLPROXY_SOCKS5; break;
4500 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
4501 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
4502 default:
4503 failwith("Invalid curl proxy type");
4506 result = curl_easy_setopt(conn->connection,
4507 CURLOPT_PROXYTYPE,
4508 proxy_type);
4510 if (result != CURLE_OK)
4511 raiseError(conn, result);
4513 CAMLreturn0;
4515 #endif
4517 #if HAVE_DECL_CURLOPT_PROTOCOLS || HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
4519 long protoMap[] =
4521 CURLPROTO_ALL,
4522 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
4523 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
4524 /* factor out with autoconf? */
4525 #if defined(CURLPROTO_IMAP)
4526 CURLPROTO_IMAP,
4527 #else
4529 #endif
4530 #if defined(CURLPROTO_IMAPS)
4531 CURLPROTO_IMAPS,
4532 #else
4534 #endif
4535 #if defined(CURLPROTO_POP3)
4536 CURLPROTO_POP3,
4537 #else
4539 #endif
4540 #if defined(CURLPROTO_POP3S)
4541 CURLPROTO_POP3S,
4542 #else
4544 #endif
4545 #if defined(CURLPROTO_SMTP)
4546 CURLPROTO_SMTP,
4547 #else
4549 #endif
4550 #if defined(CURLPROTO_SMTPS)
4551 CURLPROTO_SMTPS,
4552 #else
4554 #endif
4555 #if defined(CURLPROTO_RTSP)
4556 CURLPROTO_RTSP,
4557 #else
4559 #endif
4560 #if defined(CURLPROTO_RTMP)
4561 CURLPROTO_RTMP,
4562 #else
4564 #endif
4565 #if defined(CURLPROTO_RTMPT)
4566 CURLPROTO_RTMPT,
4567 #else
4569 #endif
4570 #if defined(CURLPROTO_RTMPE)
4571 CURLPROTO_RTMPE,
4572 #else
4574 #endif
4575 #if defined(CURLPROTO_RTMPTE)
4576 CURLPROTO_RTMPTE,
4577 #else
4579 #endif
4580 #if defined(CURLPROTO_RTMPS)
4581 CURLPROTO_RTMPS,
4582 #else
4584 #endif
4585 #if defined(CURLPROTO_RTMPTS)
4586 CURLPROTO_RTMPTS,
4587 #else
4589 #endif
4590 #if defined(CURLPROTO_GOPHER)
4591 CURLPROTO_GOPHER,
4592 #else
4594 #endif
4597 static void handle_PROTOCOLSOPTION(CURLoption curlopt, Connection *conn, value option)
4599 CAMLparam1(option);
4600 CURLcode result = CURLE_OK;
4601 long protocols = 0;
4602 int index;
4604 while (Val_emptylist != option)
4606 index = Int_val(Field(option, 0));
4607 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
4608 failwith("Invalid curl protocol");
4610 protocols = protocols | protoMap[index];
4612 option = Field(option, 1);
4615 result = curl_easy_setopt(conn->connection,
4616 curlopt,
4617 protocols);
4619 if (result != CURLE_OK)
4620 raiseError(conn, result);
4622 CAMLreturn0;
4624 #endif
4626 #if HAVE_DECL_CURLOPT_PROTOCOLS
4627 static void handle_PROTOCOLS(Connection *conn, value option)
4629 handle_PROTOCOLSOPTION(CURLOPT_PROTOCOLS, conn, option);
4631 #endif
4633 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
4634 static void handle_REDIR_PROTOCOLS(Connection *conn, value option)
4636 handle_PROTOCOLSOPTION(CURLOPT_REDIR_PROTOCOLS, conn, option);
4638 #endif
4640 #if HAVE_DECL_CURLOPT_RESOLVE
4641 static void handle_RESOLVE(Connection *conn, value option)
4643 CAMLparam1(option);
4644 CAMLlocal1(head);
4646 CURLcode result = CURLE_OK;
4648 free_curl_slist(conn->resolve);
4649 conn->resolve = NULL;
4651 head = option;
4653 while (head != Val_emptylist)
4655 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
4656 head = Field(head, 1);
4659 result = curl_easy_setopt(conn->connection,
4660 CURLOPT_RESOLVE,
4661 conn->resolve);
4663 if (result != CURLE_OK)
4664 raiseError(conn, result);
4666 CAMLreturn0;
4668 #endif
4670 #if HAVE_DECL_CURLOPT_DNS_SERVERS
4671 static void handle_DNS_SERVERS(Connection *conn, value option)
4673 CAMLparam1(option);
4675 Store_field(conn->ocamlValues, OcamlDNSServers, option);
4677 CURLcode result = CURLE_OK;
4678 free_if(conn->dns_servers);
4680 conn->dns_servers = strdup(String_val(option));
4682 result = curl_easy_setopt(conn->connection,
4683 CURLOPT_DNS_SERVERS,
4684 conn->dns_servers);
4686 if (result != CURLE_OK)
4687 raiseError(conn, result);
4689 CAMLreturn0;
4691 #endif
4693 #if HAVE_DECL_CURLOPT_MAIL_FROM
4694 static void handle_MAIL_FROM(Connection *conn, value option)
4696 CAMLparam1(option);
4697 CURLcode result = CURLE_OK;
4699 Store_field(conn->ocamlValues, OcamlMailFrom, option);
4701 if (conn->mailFrom != NULL)
4702 free(conn->mailFrom);
4704 conn->mailFrom = strdup(String_val(option));
4706 result = curl_easy_setopt(conn->connection,
4707 CURLOPT_MAIL_FROM,
4708 conn->mailFrom);
4710 if (result != CURLE_OK)
4711 raiseError(conn, result);
4713 CAMLreturn0;
4715 #endif
4717 #if HAVE_DECL_CURLOPT_MAIL_RCPT
4718 static void handle_MAIL_RCPT(Connection *conn, value option)
4720 CAMLparam1(option);
4721 CAMLlocal1(listIter);
4722 CURLcode result = CURLE_OK;
4724 Store_field(conn->ocamlValues, OcamlMailRcpt, option);
4726 free_curl_slist(conn->mailRcpt);
4727 conn->mailRcpt = NULL;
4729 listIter = option;
4731 while (Val_emptylist != listIter)
4733 conn->mailRcpt = curl_slist_append(conn->mailRcpt, String_val(Field(listIter, 0)));
4735 listIter = Field(listIter, 1);
4738 result = curl_easy_setopt(conn->connection,
4739 CURLOPT_MAIL_RCPT,
4740 conn->mailRcpt);
4742 if (result != CURLE_OK)
4743 raiseError(conn, result);
4745 CAMLreturn0;
4747 #endif
4749 static Connection *duplicateConnection(Connection *original)
4751 Connection *connection;
4752 CURL* h;
4754 caml_enter_blocking_section();
4755 h = curl_easy_duphandle(original->connection);
4756 caml_leave_blocking_section();
4758 connection = allocConnection(h);
4760 Store_field(connection->ocamlValues, OcamlWriteCallback,
4761 Field(original->ocamlValues, OcamlWriteCallback));
4762 Store_field(connection->ocamlValues, OcamlReadCallback,
4763 Field(original->ocamlValues, OcamlReadCallback));
4764 Store_field(connection->ocamlValues, OcamlErrorBuffer,
4765 Field(original->ocamlValues, OcamlErrorBuffer));
4766 Store_field(connection->ocamlValues, OcamlPostFields,
4767 Field(original->ocamlValues, OcamlPostFields));
4768 Store_field(connection->ocamlValues, OcamlHTTPHeader,
4769 Field(original->ocamlValues, OcamlHTTPHeader));
4770 Store_field(connection->ocamlValues, OcamlQuote,
4771 Field(original->ocamlValues, OcamlQuote));
4772 Store_field(connection->ocamlValues, OcamlPostQuote,
4773 Field(original->ocamlValues, OcamlPostQuote));
4774 Store_field(connection->ocamlValues, OcamlHeaderCallback,
4775 Field(original->ocamlValues, OcamlHeaderCallback));
4776 Store_field(connection->ocamlValues, OcamlProgressCallback,
4777 Field(original->ocamlValues, OcamlProgressCallback));
4778 Store_field(connection->ocamlValues, OcamlDebugCallback,
4779 Field(original->ocamlValues, OcamlDebugCallback));
4780 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
4781 Field(original->ocamlValues, OcamlHTTP200Aliases));
4782 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
4783 Field(original->ocamlValues, OcamlIOCTLCallback));
4784 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
4785 Field(original->ocamlValues, OcamlSeekFunctionCallback));
4787 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
4788 handle_URL(connection, Field(original->ocamlValues,
4789 OcamlURL));
4790 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
4791 handle_PROXY(connection, Field(original->ocamlValues,
4792 OcamlProxy));
4793 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
4794 handle_USERPWD(connection, Field(original->ocamlValues,
4795 OcamlUserPWD));
4796 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
4797 handle_PROXYUSERPWD(connection, Field(original->ocamlValues,
4798 OcamlProxyUserPWD));
4799 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
4800 handle_RANGE(connection, Field(original->ocamlValues,
4801 OcamlRange));
4802 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
4803 handle_ERRORBUFFER(connection, Field(original->ocamlValues,
4804 OcamlErrorBuffer));
4805 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
4806 handle_POSTFIELDS(connection, Field(original->ocamlValues,
4807 OcamlPostFields));
4808 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
4809 handle_REFERER(connection, Field(original->ocamlValues,
4810 OcamlReferer));
4811 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
4812 handle_USERAGENT(connection, Field(original->ocamlValues,
4813 OcamlUserAgent));
4814 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
4815 handle_FTPPORT(connection, Field(original->ocamlValues,
4816 OcamlFTPPort));
4817 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
4818 handle_COOKIE(connection, Field(original->ocamlValues,
4819 OcamlCookie));
4820 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
4821 handle_HTTPHEADER(connection, Field(original->ocamlValues,
4822 OcamlHTTPHeader));
4823 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
4824 handle_HTTPPOST(connection, Field(original->ocamlValues,
4825 OcamlHTTPPost));
4826 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
4827 handle_SSLCERT(connection, Field(original->ocamlValues,
4828 OcamlSSLCert));
4829 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
4830 handle_SSLCERTTYPE(connection, Field(original->ocamlValues,
4831 OcamlSSLCertType));
4832 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
4833 handle_SSLCERTPASSWD(connection, Field(original->ocamlValues,
4834 OcamlSSLCertPasswd));
4835 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
4836 handle_SSLKEY(connection, Field(original->ocamlValues,
4837 OcamlSSLKey));
4838 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
4839 handle_SSLKEYTYPE(connection, Field(original->ocamlValues,
4840 OcamlSSLKeyType));
4841 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
4842 handle_SSLKEYPASSWD(connection, Field(original->ocamlValues,
4843 OcamlSSLKeyPasswd));
4844 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
4845 handle_SSLENGINE(connection, Field(original->ocamlValues,
4846 OcamlSSLEngine));
4847 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
4848 handle_QUOTE(connection, Field(original->ocamlValues,
4849 OcamlQuote));
4850 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
4851 handle_POSTQUOTE(connection, Field(original->ocamlValues,
4852 OcamlPostQuote));
4853 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
4854 handle_COOKIEFILE(connection, Field(original->ocamlValues,
4855 OcamlCookieFile));
4856 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
4857 handle_CUSTOMREQUEST(connection, Field(original->ocamlValues,
4858 OcamlCustomRequest));
4859 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
4860 handle_INTERFACE(connection, Field(original->ocamlValues,
4861 OcamlInterface));
4862 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
4863 handle_CAINFO(connection, Field(original->ocamlValues,
4864 OcamlCAInfo));
4865 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
4866 handle_CAPATH(connection, Field(original->ocamlValues,
4867 OcamlCAPath));
4868 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
4869 handle_RANDOM_FILE(connection, Field(original->ocamlValues,
4870 OcamlRandomFile));
4871 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
4872 handle_EGDSOCKET(connection, Field(original->ocamlValues,
4873 OcamlEGDSocket));
4874 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
4875 handle_COOKIEJAR(connection, Field(original->ocamlValues,
4876 OcamlCookieJar));
4877 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
4878 handle_SSL_CIPHER_LIST(connection, Field(original->ocamlValues,
4879 OcamlSSLCipherList));
4880 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
4881 handle_PRIVATE(connection, Field(original->ocamlValues,
4882 OcamlPrivate));
4883 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
4884 handle_HTTP200ALIASES(connection, Field(original->ocamlValues,
4885 OcamlHTTP200Aliases));
4886 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
4887 handle_NETRC_FILE(connection, Field(original->ocamlValues,
4888 OcamlNETRCFile));
4889 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
4890 handle_FTP_ACCOUNT(connection, Field(original->ocamlValues,
4891 OcamlFTPAccount));
4892 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
4893 handle_COOKIELIST(connection, Field(original->ocamlValues,
4894 OcamlCookieList));
4895 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
4896 handle_FTP_ALTERNATIVE_TO_USER(connection,
4897 Field(original->ocamlValues,
4898 OcamlFTPAlternativeToUser));
4899 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
4900 handle_SSH_PUBLIC_KEYFILE(connection,
4901 Field(original->ocamlValues,
4902 OcamlSSHPublicKeyFile));
4903 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
4904 handle_SSH_PRIVATE_KEYFILE(connection,
4905 Field(original->ocamlValues,
4906 OcamlSSHPrivateKeyFile));
4907 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
4908 handle_COPYPOSTFIELDS(connection,
4909 Field(original->ocamlValues,
4910 OcamlCopyPostFields));
4911 if (Field(original->ocamlValues, OcamlDNSServers) != Val_unit)
4912 handle_DNS_SERVERS(connection,
4913 Field(original->ocamlValues,
4914 OcamlDNSServers));
4915 if (Field(original->ocamlValues, OcamlMailFrom) != Val_unit)
4916 handle_MAIL_FROM(connection,
4917 Field(original->ocamlValues,
4918 OcamlMailFrom));
4919 if (Field(original->ocamlValues, OcamlMailRcpt) != Val_unit)
4920 handle_MAIL_RCPT(connection,
4921 Field(original->ocamlValues,
4922 OcamlMailRcpt));
4924 return connection;
4928 ** curl_easy_setopt helper function
4931 #define MAP(name) { handle_ ## name, "CURLOPT_"#name /*, CURLOPT_##name */ }
4932 #define MAP_NO(name) { NULL, "CURLOPT_"#name /*, CURLOPT_##name */ }
4934 CURLOptionMapping implementedOptionMap[] =
4936 MAP(WRITEFUNCTION),
4937 MAP(READFUNCTION),
4938 MAP(INFILESIZE),
4939 MAP(URL),
4940 MAP(PROXY),
4941 MAP(PROXYPORT),
4942 MAP(HTTPPROXYTUNNEL),
4943 MAP(VERBOSE),
4944 MAP(HEADER),
4945 MAP(NOPROGRESS),
4946 #if HAVE_DECL_CURLOPT_NOSIGNAL
4947 MAP(NOSIGNAL),
4948 #else
4949 MAP_NO(NOSIGNAL),
4950 #endif
4951 MAP(NOBODY),
4952 MAP(FAILONERROR),
4953 MAP(UPLOAD),
4954 MAP(POST),
4955 MAP(FTPLISTONLY),
4956 MAP(FTPAPPEND),
4957 MAP(NETRC),
4958 #if HAVE_DECL_CURLOPT_ENCODING
4959 MAP(ENCODING),
4960 #else
4961 MAP_NO(ENCODING),
4962 #endif
4963 MAP(FOLLOWLOCATION),
4964 MAP(TRANSFERTEXT),
4965 MAP(PUT),
4966 MAP(USERPWD),
4967 MAP(PROXYUSERPWD),
4968 MAP(RANGE),
4969 MAP(ERRORBUFFER),
4970 MAP(TIMEOUT),
4971 MAP(POSTFIELDS),
4972 MAP(POSTFIELDSIZE),
4973 MAP(REFERER),
4974 MAP(USERAGENT),
4975 MAP(FTPPORT),
4976 MAP(LOW_SPEED_LIMIT),
4977 MAP(LOW_SPEED_TIME),
4978 MAP(RESUME_FROM),
4979 MAP(COOKIE),
4980 MAP(HTTPHEADER),
4981 MAP(HTTPPOST),
4982 MAP(SSLCERT),
4983 MAP(SSLCERTTYPE),
4984 MAP(SSLCERTPASSWD),
4985 MAP(SSLKEY),
4986 MAP(SSLKEYTYPE),
4987 MAP(SSLKEYPASSWD),
4988 MAP(SSLENGINE),
4989 MAP(SSLENGINE_DEFAULT),
4990 MAP(CRLF),
4991 MAP(QUOTE),
4992 MAP(POSTQUOTE),
4993 MAP(HEADERFUNCTION),
4994 MAP(COOKIEFILE),
4995 MAP(SSLVERSION),
4996 MAP(TIMECONDITION),
4997 MAP(TIMEVALUE),
4998 MAP(CUSTOMREQUEST),
4999 MAP(INTERFACE),
5000 MAP(KRB4LEVEL),
5001 MAP(PROGRESSFUNCTION),
5002 MAP(SSL_VERIFYPEER),
5003 MAP(CAINFO),
5004 MAP(CAPATH),
5005 MAP(FILETIME),
5006 MAP(MAXREDIRS),
5007 MAP(MAXCONNECTS),
5008 MAP(CLOSEPOLICY),
5009 MAP(FRESH_CONNECT),
5010 MAP(FORBID_REUSE),
5011 MAP(RANDOM_FILE),
5012 MAP(EGDSOCKET),
5013 MAP(CONNECTTIMEOUT),
5014 MAP(HTTPGET),
5015 MAP(SSL_VERIFYHOST),
5016 MAP(COOKIEJAR),
5017 MAP(SSL_CIPHER_LIST),
5018 MAP(HTTP_VERSION),
5019 MAP(FTP_USE_EPSV),
5020 MAP(DNS_CACHE_TIMEOUT),
5021 MAP(DNS_USE_GLOBAL_CACHE),
5022 MAP(DEBUGFUNCTION),
5023 #if HAVE_DECL_CURLOPT_PRIVATE
5024 MAP(PRIVATE),
5025 #else
5026 MAP_NO(PRIVATE),
5027 #endif
5028 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
5029 MAP(HTTP200ALIASES),
5030 #else
5031 MAP_NO(HTTP200ALIASES),
5032 #endif
5033 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
5034 MAP(UNRESTRICTED_AUTH),
5035 #else
5036 MAP_NO(UNRESTRICTED_AUTH),
5037 #endif
5038 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
5039 MAP(FTP_USE_EPRT),
5040 #else
5041 MAP_NO(FTP_USE_EPRT),
5042 #endif
5043 #if HAVE_DECL_CURLOPT_HTTPAUTH
5044 MAP(HTTPAUTH),
5045 #else
5046 MAP_NO(HTTPAUTH),
5047 #endif
5048 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
5049 MAP(FTP_CREATE_MISSING_DIRS),
5050 #else
5051 MAP_NO(FTP_CREATE_MISSING_DIRS),
5052 #endif
5053 #if HAVE_DECL_CURLOPT_PROXYAUTH
5054 MAP(PROXYAUTH),
5055 #else
5056 MAP_NO(PROXYAUTH),
5057 #endif
5058 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
5059 MAP(FTP_RESPONSE_TIMEOUT),
5060 #else
5061 MAP_NO(FTP_RESPONSE_TIMEOUT),
5062 #endif
5063 #if HAVE_DECL_CURLOPT_IPRESOLVE
5064 MAP(IPRESOLVE),
5065 #else
5066 MAP_NO(IPRESOLVE),
5067 #endif
5068 #if HAVE_DECL_CURLOPT_MAXFILESIZE
5069 MAP(MAXFILESIZE),
5070 #else
5071 MAP_NO(MAXFILESIZE),
5072 #endif
5073 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
5074 MAP(INFILESIZE_LARGE),
5075 #else
5076 MAP_NO(INFILESIZE_LARGE),
5077 #endif
5078 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
5079 MAP(RESUME_FROM_LARGE),
5080 #else
5081 MAP_NO(RESUME_FROM_LARGE),
5082 #endif
5083 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
5084 MAP(MAXFILESIZE_LARGE),
5085 #else
5086 MAP_NO(MAXFILESIZE_LARGE),
5087 #endif
5088 #if HAVE_DECL_CURLOPT_NETRC_FILE
5089 MAP(NETRC_FILE),
5090 #else
5091 MAP_NO(NETRC_FILE),
5092 #endif
5093 #if HAVE_DECL_CURLOPT_FTP_SSL
5094 MAP(FTP_SSL),
5095 #else
5096 MAP_NO(FTP_SSL),
5097 #endif
5098 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
5099 MAP(POSTFIELDSIZE_LARGE),
5100 #else
5101 MAP_NO(POSTFIELDSIZE_LARGE),
5102 #endif
5103 #if HAVE_DECL_CURLOPT_TCP_NODELAY
5104 MAP(TCP_NODELAY),
5105 #else
5106 MAP_NO(TCP_NODELAY),
5107 #endif
5108 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
5109 MAP(FTPSSLAUTH),
5110 #else
5111 MAP_NO(FTPSSLAUTH),
5112 #endif
5113 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
5114 MAP(IOCTLFUNCTION),
5115 #else
5116 MAP_NO(IOCTLFUNCTION),
5117 #endif
5118 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
5119 MAP(FTP_ACCOUNT),
5120 #else
5121 MAP_NO(FTP_ACCOUNT),
5122 #endif
5123 #if HAVE_DECL_CURLOPT_COOKIELIST
5124 MAP(COOKIELIST),
5125 #else
5126 MAP_NO(COOKIELIST),
5127 #endif
5128 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
5129 MAP(IGNORE_CONTENT_LENGTH),
5130 #else
5131 MAP_NO(IGNORE_CONTENT_LENGTH),
5132 #endif
5133 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
5134 MAP(FTP_SKIP_PASV_IP),
5135 #else
5136 MAP_NO(FTP_SKIP_PASV_IP),
5137 #endif
5138 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
5139 MAP(FTP_FILEMETHOD),
5140 #else
5141 MAP_NO(FTP_FILEMETHOD),
5142 #endif
5143 #if HAVE_DECL_CURLOPT_LOCALPORT
5144 MAP(LOCALPORT),
5145 #else
5146 MAP_NO(LOCALPORT),
5147 #endif
5148 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
5149 MAP(LOCALPORTRANGE),
5150 #else
5151 MAP_NO(LOCALPORTRANGE),
5152 #endif
5153 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
5154 MAP(CONNECT_ONLY),
5155 #else
5156 MAP_NO(CONNECT_ONLY),
5157 #endif
5158 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
5159 MAP(MAX_SEND_SPEED_LARGE),
5160 #else
5161 MAP_NO(MAX_SEND_SPEED_LARGE),
5162 #endif
5163 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
5164 MAP(MAX_RECV_SPEED_LARGE),
5165 #else
5166 MAP_NO(MAX_RECV_SPEED_LARGE),
5167 #endif
5168 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
5169 MAP(FTP_ALTERNATIVE_TO_USER),
5170 #else
5171 MAP_NO(FTP_ALTERNATIVE_TO_USER),
5172 #endif
5173 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
5174 MAP(SSL_SESSIONID_CACHE),
5175 #else
5176 MAP_NO(SSL_SESSIONID_CACHE),
5177 #endif
5178 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
5179 MAP(SSH_AUTH_TYPES),
5180 #else
5181 MAP_NO(SSH_AUTH_TYPES),
5182 #endif
5183 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
5184 MAP(SSH_PUBLIC_KEYFILE),
5185 #else
5186 MAP_NO(SSH_PUBLIC_KEYFILE),
5187 #endif
5188 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
5189 MAP(SSH_PRIVATE_KEYFILE),
5190 #else
5191 MAP_NO(SSH_PRIVATE_KEYFILE),
5192 #endif
5193 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
5194 MAP(FTP_SSL_CCC),
5195 #else
5196 MAP_NO(FTP_SSL_CCC),
5197 #endif
5198 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
5199 MAP(TIMEOUT_MS),
5200 #else
5201 MAP_NO(TIMEOUT_MS),
5202 #endif
5203 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
5204 MAP(CONNECTTIMEOUT_MS),
5205 #else
5206 MAP_NO(CONNECTTIMEOUT_MS),
5207 #endif
5208 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5209 MAP(HTTP_TRANSFER_DECODING),
5210 #else
5211 MAP_NO(HTTP_TRANSFER_DECODING),
5212 #endif
5213 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5214 MAP(HTTP_CONTENT_DECODING),
5215 #else
5216 MAP_NO(HTTP_CONTENT_DECODING),
5217 #endif
5218 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5219 MAP(NEW_FILE_PERMS),
5220 #else
5221 MAP_NO(NEW_FILE_PERMS),
5222 #endif
5223 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5224 MAP(NEW_DIRECTORY_PERMS),
5225 #else
5226 MAP_NO(NEW_DIRECTORY_PERMS),
5227 #endif
5228 #if HAVE_DECL_CURLOPT_POST301
5229 MAP(POST301),
5230 #else
5231 MAP_NO(POST301),
5232 #endif
5233 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5234 MAP(SSH_HOST_PUBLIC_KEY_MD5),
5235 #else
5236 MAP_NO(SSH_HOST_PUBLIC_KEY_MD5),
5237 #endif
5238 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5239 MAP(COPYPOSTFIELDS),
5240 #else
5241 MAP_NO(COPYPOSTFIELDS),
5242 #endif
5243 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5244 MAP(PROXY_TRANSFER_MODE),
5245 #else
5246 MAP_NO(PROXY_TRANSFER_MODE),
5247 #endif
5248 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5249 MAP(SEEKFUNCTION),
5250 #else
5251 MAP_NO(SEEKFUNCTION),
5252 #endif
5253 #if HAVE_DECL_CURLOPT_AUTOREFERER
5254 MAP(AUTOREFERER),
5255 #else
5256 MAP_NO(AUTOREFERER),
5257 #endif
5258 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5259 MAP(OPENSOCKETFUNCTION),
5260 #else
5261 MAP_NO(OPENSOCKETFUNCTION),
5262 #endif
5263 #if HAVE_DECL_CURLOPT_PROXYTYPE
5264 MAP(PROXYTYPE),
5265 #else
5266 MAP_NO(PROXYTYPE),
5267 #endif
5268 #if HAVE_DECL_CURLOPT_PROTOCOLS
5269 MAP(PROTOCOLS),
5270 #else
5271 MAP_NO(PROTOCOLS),
5272 #endif
5273 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5274 MAP(REDIR_PROTOCOLS),
5275 #else
5276 MAP_NO(REDIR_PROTOCOLS),
5277 #endif
5278 #if HAVE_DECL_CURLOPT_RESOLVE
5279 MAP(RESOLVE),
5280 #else
5281 MAP_NO(RESOLVE),
5282 #endif
5283 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5284 MAP(DNS_SERVERS),
5285 #else
5286 MAP_NO(DNS_SERVERS),
5287 #endif
5288 #if HAVE_DECL_CURLOPT_MAIL_FROM
5289 MAP(MAIL_FROM),
5290 #else
5291 MAP_NO(MAIL_FROM),
5292 #endif
5293 #if HAVE_DECL_CURLOPT_MAIL_RCPT
5294 MAP(MAIL_RCPT),
5295 #else
5296 MAP_NO(MAIL_RCPT),
5297 #endif
5300 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5302 CAMLparam2(conn, option);
5303 CAMLlocal1(data);
5304 Connection *connection = Connection_val(conn);
5305 CURLOptionMapping* thisOption = NULL;
5306 static value* exception = NULL;
5308 checkConnection(connection);
5310 if (!Is_block(option))
5311 failwith("Not a block");
5313 if (Wosize_val(option) < 1)
5314 failwith("Insufficient data in block");
5316 data = Field(option, 0);
5318 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5320 thisOption = &implementedOptionMap[Tag_val(option)];
5321 if (thisOption->optionHandler)
5322 thisOption->optionHandler(connection, data);
5323 else
5325 if (NULL == exception)
5327 exception = caml_named_value("Curl.NotImplemented");
5328 if (NULL == exception) caml_invalid_argument("Curl.NotImplemented");
5331 caml_raise_with_string(*exception, thisOption->name);
5334 else
5335 failwith("Invalid CURLOPT Option");
5337 CAMLreturn(Val_unit);
5341 ** curl_easy_perform helper function
5344 CAMLprim value helper_curl_easy_perform(value conn)
5346 CAMLparam1(conn);
5347 CURLcode result = CURLE_OK;
5348 Connection *connection = Connection_val(conn);
5350 checkConnection(connection);
5352 enter_blocking_section();
5353 result = curl_easy_perform(connection->connection);
5354 leave_blocking_section();
5356 if (result != CURLE_OK)
5357 raiseError(connection, result);
5359 CAMLreturn(Val_unit);
5363 ** curl_easy_cleanup helper function
5366 CAMLprim value helper_curl_easy_cleanup(value conn)
5368 CAMLparam1(conn);
5369 Connection *connection = Connection_val(conn);
5371 checkConnection(connection);
5373 removeConnection(connection, 0);
5375 CAMLreturn(Val_unit);
5379 ** curl_easy_duphandle helper function
5382 CAMLprim value helper_curl_easy_duphandle(value conn)
5384 CAMLparam1(conn);
5385 CAMLlocal1(result);
5386 Connection *connection = Connection_val(conn);
5388 checkConnection(connection);
5390 result = caml_curl_alloc(duplicateConnection(connection));
5392 CAMLreturn(result);
5396 ** curl_easy_getinfo helper function
5399 enum GetInfoResultType {
5400 StringValue, LongValue, DoubleValue, StringListValue
5403 value convertStringList(struct curl_slist *slist)
5405 CAMLparam0();
5406 CAMLlocal3(result, current, next);
5407 struct curl_slist *p = slist;
5409 result = Val_int(0);
5410 current = Val_int(0);
5411 next = Val_int(0);
5413 while (p != NULL)
5415 next = alloc_tuple(2);
5416 Store_field(next, 0, copy_string(p->data));
5417 Store_field(next, 1, Val_int(0));
5419 if (result == Val_int(0))
5420 result = next;
5422 if (current != Val_int(0))
5423 Store_field(current, 1, next);
5425 current = next;
5427 p = p->next;
5430 curl_slist_free_all(slist);
5432 CAMLreturn(result);
5435 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5437 CAMLparam2(conn, option);
5438 CAMLlocal1(result);
5439 CURLcode curlResult;
5440 Connection *connection = Connection_val(conn);
5441 enum GetInfoResultType resultType;
5442 char *strValue = NULL;
5443 double doubleValue;
5444 long longValue;
5445 struct curl_slist *stringListValue = NULL;
5447 checkConnection(connection);
5449 switch(Long_val(option))
5451 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5452 case 0: /* CURLINFO_EFFECTIVE_URL */
5453 resultType = StringValue;
5455 curlResult = curl_easy_getinfo(connection->connection,
5456 CURLINFO_EFFECTIVE_URL,
5457 &strValue);
5458 break;
5459 #else
5460 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5461 #endif
5463 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5464 case 1: /* CURLINFO_HTTP_CODE */
5465 case 2: /* CURLINFO_RESPONSE_CODE */
5466 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5467 resultType = LongValue;
5469 curlResult = curl_easy_getinfo(connection->connection,
5470 CURLINFO_RESPONSE_CODE,
5471 &longValue);
5472 #else
5473 resultType = LongValue;
5475 curlResult = curl_easy_getinfo(connection->connection,
5476 CURLINFO_HTTP_CODE,
5477 &longValue);
5478 #endif
5479 break;
5480 #endif
5482 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5483 case 3: /* CURLINFO_TOTAL_TIME */
5484 resultType = DoubleValue;
5486 curlResult = curl_easy_getinfo(connection->connection,
5487 CURLINFO_TOTAL_TIME,
5488 &doubleValue);
5489 break;
5490 #endif
5492 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5493 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5494 resultType = DoubleValue;
5496 curlResult = curl_easy_getinfo(connection->connection,
5497 CURLINFO_NAMELOOKUP_TIME,
5498 &doubleValue);
5499 break;
5500 #endif
5502 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5503 case 5: /* CURLINFO_CONNECT_TIME */
5504 resultType = DoubleValue;
5506 curlResult = curl_easy_getinfo(connection->connection,
5507 CURLINFO_CONNECT_TIME,
5508 &doubleValue);
5509 break;
5510 #endif
5512 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5513 case 6: /* CURLINFO_PRETRANSFER_TIME */
5514 resultType = DoubleValue;
5516 curlResult = curl_easy_getinfo(connection->connection,
5517 CURLINFO_PRETRANSFER_TIME,
5518 &doubleValue);
5519 break;
5520 #endif
5522 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5523 case 7: /* CURLINFO_SIZE_UPLOAD */
5524 resultType = DoubleValue;
5526 curlResult = curl_easy_getinfo(connection->connection,
5527 CURLINFO_SIZE_UPLOAD,
5528 &doubleValue);
5529 break;
5530 #endif
5532 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5533 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5534 resultType = DoubleValue;
5536 curlResult = curl_easy_getinfo(connection->connection,
5537 CURLINFO_SIZE_DOWNLOAD,
5538 &doubleValue);
5539 break;
5540 #endif
5542 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5543 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5544 resultType = DoubleValue;
5546 curlResult = curl_easy_getinfo(connection->connection,
5547 CURLINFO_SPEED_DOWNLOAD,
5548 &doubleValue);
5549 break;
5550 #endif
5552 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5553 case 10: /* CURLINFO_SPEED_UPLOAD */
5554 resultType = DoubleValue;
5556 curlResult = curl_easy_getinfo(connection->connection,
5557 CURLINFO_SPEED_UPLOAD,
5558 &doubleValue);
5559 break;
5561 #endif
5563 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5564 case 11: /* CURLINFO_HEADER_SIZE */
5565 resultType = LongValue;
5567 curlResult = curl_easy_getinfo(connection->connection,
5568 CURLINFO_HEADER_SIZE,
5569 &longValue);
5570 break;
5571 #endif
5573 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5574 case 12: /* CURLINFO_REQUEST_SIZE */
5575 resultType = LongValue;
5577 curlResult = curl_easy_getinfo(connection->connection,
5578 CURLINFO_REQUEST_SIZE,
5579 &longValue);
5580 break;
5581 #endif
5583 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5584 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5585 resultType = LongValue;
5587 curlResult = curl_easy_getinfo(connection->connection,
5588 CURLINFO_SSL_VERIFYRESULT,
5589 &longValue);
5590 break;
5591 #endif
5593 #if HAVE_DECL_CURLINFO_FILETIME
5594 case 14: /* CURLINFO_FILETIME */
5595 resultType = DoubleValue;
5597 curlResult = curl_easy_getinfo(connection->connection,
5598 CURLINFO_FILETIME,
5599 &longValue);
5601 doubleValue = longValue;
5602 break;
5603 #endif
5605 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5606 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5607 resultType = DoubleValue;
5609 curlResult = curl_easy_getinfo(connection->connection,
5610 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5611 &doubleValue);
5612 break;
5613 #endif
5615 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5616 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5617 resultType = DoubleValue;
5619 curlResult = curl_easy_getinfo(connection->connection,
5620 CURLINFO_CONTENT_LENGTH_UPLOAD,
5621 &doubleValue);
5622 break;
5623 #endif
5625 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5626 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5627 resultType = DoubleValue;
5629 curlResult = curl_easy_getinfo(connection->connection,
5630 CURLINFO_STARTTRANSFER_TIME,
5631 &doubleValue);
5632 break;
5633 #endif
5635 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5636 case 18: /* CURLINFO_CONTENT_TYPE */
5637 resultType = StringValue;
5639 curlResult = curl_easy_getinfo(connection->connection,
5640 CURLINFO_CONTENT_TYPE,
5641 &strValue);
5642 break;
5643 #endif
5645 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5646 case 19: /* CURLINFO_REDIRECT_TIME */
5647 resultType = DoubleValue;
5649 curlResult = curl_easy_getinfo(connection->connection,
5650 CURLINFO_REDIRECT_TIME,
5651 &doubleValue);
5652 break;
5653 #endif
5655 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5656 case 20: /* CURLINFO_REDIRECT_COUNT */
5657 resultType = LongValue;
5659 curlResult = curl_easy_getinfo(connection->connection,
5660 CURLINFO_REDIRECT_COUNT,
5661 &longValue);
5662 break;
5663 #endif
5665 #if HAVE_DECL_CURLINFO_PRIVATE
5666 case 21: /* CURLINFO_PRIVATE */
5667 resultType = StringValue;
5669 curlResult = curl_easy_getinfo(connection->connection,
5670 CURLINFO_PRIVATE,
5671 &strValue);
5672 break;
5673 #endif
5675 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5676 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5677 resultType = LongValue;
5679 curlResult = curl_easy_getinfo(connection->connection,
5680 CURLINFO_HTTP_CONNECTCODE,
5681 &longValue);
5682 break;
5683 #endif
5685 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5686 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5687 resultType = LongValue;
5689 curlResult = curl_easy_getinfo(connection->connection,
5690 CURLINFO_HTTPAUTH_AVAIL,
5691 &longValue);
5692 break;
5693 #endif
5695 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5696 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5697 resultType = LongValue;
5699 curlResult = curl_easy_getinfo(connection->connection,
5700 CURLINFO_PROXYAUTH_AVAIL,
5701 &longValue);
5702 break;
5703 #endif
5705 #if HAVE_DECL_CURLINFO_OS_ERRNO
5706 case 25: /* CURLINFO_OS_ERRNO */
5707 resultType = LongValue;
5709 curlResult = curl_easy_getinfo(connection->connection,
5710 CURLINFO_OS_ERRNO,
5711 &longValue);
5712 break;
5713 #endif
5715 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5716 case 26: /* CURLINFO_NUM_CONNECTS */
5717 resultType = LongValue;
5719 curlResult = curl_easy_getinfo(connection->connection,
5720 CURLINFO_NUM_CONNECTS,
5721 &longValue);
5722 break;
5723 #endif
5725 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5726 case 27: /* CURLINFO_SSL_ENGINES */
5727 resultType = StringListValue;
5729 curlResult = curl_easy_getinfo(connection->connection,
5730 CURLINFO_SSL_ENGINES,
5731 &stringListValue);
5732 break;
5733 #endif
5735 #if HAVE_DECL_CURLINFO_COOKIELIST
5736 case 28: /* CURLINFO_COOKIELIST */
5737 resultType = StringListValue;
5739 curlResult = curl_easy_getinfo(connection->connection,
5740 CURLINFO_COOKIELIST,
5741 &stringListValue);
5742 break;
5743 #endif
5745 #if HAVE_DECL_CURLINFO_LASTSOCKET
5746 case 29: /* CURLINFO_LASTSOCKET */
5747 resultType = LongValue;
5749 curlResult = curl_easy_getinfo(connection->connection,
5750 CURLINFO_LASTSOCKET,
5751 &longValue);
5752 break;
5753 #endif
5755 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5756 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5757 resultType = StringValue;
5759 curlResult = curl_easy_getinfo(connection->connection,
5760 CURLINFO_FTP_ENTRY_PATH,
5761 &strValue);
5762 break;
5763 #endif
5765 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5766 case 31: /* CURLINFO_REDIRECT_URL */
5767 resultType = StringValue;
5769 curlResult = curl_easy_getinfo(connection->connection,
5770 CURLINFO_REDIRECT_URL,
5771 &strValue);
5772 break;
5773 #else
5774 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5775 #endif
5777 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5778 case 32: /* CURLINFO_PRIMARY_IP */
5779 resultType = StringValue;
5781 curlResult = curl_easy_getinfo(connection->connection,
5782 CURLINFO_PRIMARY_IP,
5783 &strValue);
5784 break;
5785 #else
5786 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5787 #endif
5789 #if HAVE_DECL_CURLINFO_LOCAL_IP
5790 case 33: /* CURLINFO_LOCAL_IP */
5791 resultType = StringValue;
5793 curlResult = curl_easy_getinfo(connection->connection,
5794 CURLINFO_LOCAL_IP,
5795 &strValue);
5796 break;
5797 #else
5798 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
5799 #endif
5801 #if HAVE_DECL_CURLINFO_LOCAL_PORT
5802 case 34: /* CURLINFO_LOCAL_PORT */
5803 resultType = LongValue;
5805 curlResult = curl_easy_getinfo(connection->connection,
5806 CURLINFO_LOCAL_PORT,
5807 &longValue);
5808 break;
5809 #else
5810 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
5811 #endif
5813 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
5814 case 35: /* CURLINFO_CONDITION_UNMET */
5815 resultType = LongValue;
5817 curlResult = curl_easy_getinfo(connection->connection,
5818 CURLINFO_CONDITION_UNMET,
5819 &longValue);
5820 break;
5821 #else
5822 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
5823 #endif
5825 default:
5826 failwith("Invalid CURLINFO Option");
5827 break;
5830 if (curlResult != CURLE_OK)
5831 raiseError(connection, curlResult);
5833 switch (resultType)
5835 case StringValue:
5836 result = alloc(1, StringValue);
5837 Store_field(result, 0, copy_string(strValue?strValue:""));
5838 break;
5840 case LongValue:
5841 result = alloc(1, LongValue);
5842 Store_field(result, 0, Val_long(longValue));
5843 break;
5845 case DoubleValue:
5846 result = alloc(1, DoubleValue);
5847 Store_field(result, 0, copy_double(doubleValue));
5848 break;
5850 case StringListValue:
5851 result = alloc(1, StringListValue);
5852 Store_field(result, 0, convertStringList(stringListValue));
5853 break;
5856 CAMLreturn(result);
5860 ** curl_escape helper function
5863 CAMLprim value helper_curl_escape(value str)
5865 CAMLparam1(str);
5866 CAMLlocal1(result);
5867 char *curlResult;
5869 curlResult = curl_escape(String_val(str), string_length(str));
5870 result = copy_string(curlResult);
5871 free(curlResult);
5873 CAMLreturn(result);
5877 ** curl_unescape helper function
5880 CAMLprim value helper_curl_unescape(value str)
5882 CAMLparam1(str);
5883 CAMLlocal1(result);
5884 char *curlResult;
5886 curlResult = curl_unescape(String_val(str), string_length(str));
5887 result = copy_string(curlResult);
5888 free(curlResult);
5890 CAMLreturn(result);
5894 ** curl_getdate helper function
5897 CAMLprim value helper_curl_getdate(value str, value now)
5899 CAMLparam2(str, now);
5900 CAMLlocal1(result);
5901 time_t curlResult;
5902 time_t curlNow;
5904 curlNow = (time_t)Double_val(now);
5905 curlResult = curl_getdate(String_val(str), &curlNow);
5906 result = copy_double((double)curlResult);
5908 CAMLreturn(result);
5912 ** curl_version helper function
5915 CAMLprim value helper_curl_version(void)
5917 CAMLparam0();
5918 CAMLlocal1(result);
5919 char *str;
5921 str = curl_version();
5922 result = copy_string(str);
5924 CAMLreturn(result);
5927 struct CURLVersionBitsMapping
5929 int code;
5930 char *name;
5933 struct CURLVersionBitsMapping versionBitsMap[] =
5935 {CURL_VERSION_IPV6, "ipv6"},
5936 {CURL_VERSION_KERBEROS4, "kerberos4"},
5937 {CURL_VERSION_SSL, "ssl"},
5938 {CURL_VERSION_LIBZ, "libz"},
5939 {CURL_VERSION_NTLM, "ntlm"},
5940 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
5941 {CURL_VERSION_DEBUG, "debug"},
5942 {CURL_VERSION_CURLDEBUG, "curldebug"},
5943 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
5944 {CURL_VERSION_SPNEGO, "spnego"},
5945 {CURL_VERSION_LARGEFILE, "largefile"},
5946 {CURL_VERSION_IDN, "idn"},
5947 {CURL_VERSION_SSPI, "sspi"},
5948 {CURL_VERSION_CONV, "conv"},
5949 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
5950 {CURL_VERSION_TLSAUTH_SRP, "srp"},
5951 #endif
5952 #if HAVE_DECL_CURL_VERSION_NTLM_WB
5953 {CURL_VERSION_NTLM_WB, "wb"},
5954 #endif
5957 CAMLprim value caml_curl_version_info(value unit)
5959 CAMLparam1(unit);
5960 CAMLlocal4(v, vlist, vnum, vfeatures);
5961 const char* const* p = NULL;
5962 size_t i = 0;
5964 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
5965 if (NULL == data) caml_failwith("curl_version_info");
5967 vlist = Val_emptylist;
5968 for (p = data->protocols; NULL != *p; p++)
5970 vlist = Val_cons(vlist, caml_copy_string(*p));
5973 vfeatures = Val_emptylist;
5974 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
5976 if (0 != (versionBitsMap[i].code & data->features))
5977 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
5980 vnum = caml_alloc_tuple(3);
5981 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
5982 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
5983 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
5985 v = caml_alloc_tuple(12);
5986 Store_field(v,0,caml_copy_string(data->version));
5987 Store_field(v,1,vnum);
5988 Store_field(v,2,caml_copy_string(data->host));
5989 Store_field(v,3,vfeatures);
5990 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
5991 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
5992 Store_field(v,6,vlist);
5993 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
5994 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
5995 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
5996 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
5997 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
5999 CAMLreturn(v);
6002 CAMLprim value caml_curl_pause(value conn, value opts)
6004 CAMLparam2(conn, opts);
6005 CAMLlocal4(v, vlist, vnum, vfeatures);
6006 Connection *connection = Connection_val(conn);
6007 int bitmask = 0;
6008 CURLcode result;
6010 while (Val_emptylist != opts)
6012 switch (Int_val(Field(opts,0)))
6014 case 0: bitmask |= CURLPAUSE_SEND; break;
6015 case 1: bitmask |= CURLPAUSE_RECV; break;
6016 case 2: bitmask |= CURLPAUSE_ALL; break;
6017 default: caml_failwith("wrong pauseOption");
6019 opts = Field(opts,1);
6022 result = curl_easy_pause(connection->connection,bitmask);
6023 if (result != CURLE_OK)
6024 raiseError(connection, result);
6026 CAMLreturn(Val_unit);
6030 * Curl multi stack support
6032 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6033 * Other exported functions are prefixed with caml_curlm_, some of them
6034 * can/should be decomposed into smaller parts.
6037 struct ml_multi_handle
6039 CURLM* handle;
6040 value values; /* callbacks */
6043 enum
6045 curlmopt_socket_function,
6046 curlmopt_timer_function,
6048 /* last, not used */
6049 multi_values_total
6052 typedef struct ml_multi_handle ml_multi_handle;
6054 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6055 #define CURLM_val(v) (Multi_val(v)->handle)
6057 static struct custom_operations curl_multi_ops = {
6058 "ygrek.curl_multi",
6059 custom_finalize_default,
6060 custom_compare_default,
6061 custom_hash_default,
6062 custom_serialize_default,
6063 custom_deserialize_default,
6064 #if defined(custom_compare_ext_default)
6065 custom_compare_ext_default,
6066 #endif
6069 CAMLprim value caml_curl_multi_init(value unit)
6071 CAMLparam1(unit);
6072 CAMLlocal1(v);
6073 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6074 CURLM* h = curl_multi_init();
6076 if (!h)
6078 caml_stat_free(multi);
6079 failwith("caml_curl_multi_init");
6082 multi->handle = h;
6083 multi->values = caml_alloc(multi_values_total, 0);
6084 caml_register_generational_global_root(&multi->values);
6086 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6087 Multi_val(v) = multi;
6089 CAMLreturn(v);
6092 CAMLprim value caml_curl_multi_cleanup(value handle)
6094 CAMLparam1(handle);
6095 ml_multi_handle* h = Multi_val(handle);
6097 if (NULL == h)
6098 CAMLreturn(Val_unit);
6100 caml_remove_generational_global_root(&h->values);
6102 if (CURLM_OK != curl_multi_cleanup(h->handle))
6103 failwith("caml_curl_multi_cleanup");
6105 Multi_val(handle) = (ml_multi_handle*)NULL;
6107 CAMLreturn(Val_unit);
6110 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6112 int msgs_in_queue = 0;
6114 while (1)
6116 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6117 if (NULL == msg) return NULL;
6118 if (CURLMSG_DONE == msg->msg)
6120 CURL* easy_handle = msg->easy_handle;
6121 if (result) *result = msg->data.result;
6122 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6124 /*failwith("curlm_remove_finished");*/
6126 return easy_handle;
6131 CAMLprim value caml_curlm_remove_finished(value v_multi)
6133 CAMLparam1(v_multi);
6134 CAMLlocal2(v_easy, v_tuple);
6135 CURL* handle;
6136 CURLM* multi_handle;
6137 CURLcode result;
6138 Connection* conn = NULL;
6140 multi_handle = CURLM_val(v_multi);
6142 caml_enter_blocking_section();
6143 handle = curlm_remove_finished(multi_handle,&result);
6144 caml_leave_blocking_section();
6146 if (NULL == handle)
6148 CAMLreturn(Val_none);
6150 else
6152 conn = findConnection(handle);
6153 if (conn->errorBuffer != NULL)
6155 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0, caml_copy_string(conn->errorBuffer));
6157 conn->refcount--;
6158 /* NB: same handle, but different block */
6159 v_easy = caml_curl_alloc(conn);
6160 v_tuple = caml_alloc(2, 0);
6161 Store_field(v_tuple,0,v_easy);
6162 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6163 CAMLreturn(Val_some(v_tuple));
6167 static int curlm_wait_data(CURLM* multi_handle)
6169 struct timeval timeout;
6170 CURLMcode ret;
6172 fd_set fdread;
6173 fd_set fdwrite;
6174 fd_set fdexcep;
6175 int maxfd = -1;
6177 FD_ZERO(&fdread);
6178 FD_ZERO(&fdwrite);
6179 FD_ZERO(&fdexcep);
6181 /* set a suitable timeout */
6182 timeout.tv_sec = 1;
6183 timeout.tv_usec = 0;
6185 /* get file descriptors from the transfers */
6186 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6188 if (ret == CURLM_OK && maxfd >= 0)
6190 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6191 if (-1 != rc) return 0;
6193 return 1;
6196 CAMLprim value caml_curlm_wait_data(value v_multi)
6198 CAMLparam1(v_multi);
6199 int ret;
6200 CURLM* h = CURLM_val(v_multi);
6202 caml_enter_blocking_section();
6203 ret = curlm_wait_data(h);
6204 caml_leave_blocking_section();
6206 CAMLreturn(Val_bool(0 == ret));
6209 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6211 CAMLparam2(v_multi,v_easy);
6212 CURLM* multi = CURLM_val(v_multi);
6213 Connection* conn = Connection_val(v_easy);
6215 /* prevent collection of OCaml value while the easy handle is used
6216 and may invoke callbacks registered on OCaml side */
6217 conn->refcount++;
6219 /* may invoke callbacks so need to be consistent with locks */
6220 caml_enter_blocking_section();
6221 if (CURLM_OK != curl_multi_add_handle(multi, conn->connection))
6223 conn->refcount--; /* not added, revert */
6224 caml_leave_blocking_section();
6225 failwith("caml_curl_multi_add_handle");
6227 caml_leave_blocking_section();
6229 CAMLreturn(Val_unit);
6232 CAMLprim value caml_curl_multi_remove_handle(value v_multi, value v_easy)
6234 CAMLparam2(v_multi,v_easy);
6235 CURLM* multi = CURLM_val(v_multi);
6236 Connection* conn = Connection_val(v_easy);
6238 /* may invoke callbacks so need to be consistent with locks */
6239 caml_enter_blocking_section();
6240 if (CURLM_OK != curl_multi_remove_handle(multi, conn->connection))
6242 caml_leave_blocking_section();
6243 failwith("caml_curl_multi_remove_handle");
6245 conn->refcount--;
6246 caml_leave_blocking_section();
6248 CAMLreturn(Val_unit);
6251 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6253 CAMLparam1(v_multi);
6254 int still_running = 0;
6255 CURLM* h = CURLM_val(v_multi);
6257 caml_enter_blocking_section();
6258 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6259 caml_leave_blocking_section();
6261 CAMLreturn(Val_int(still_running));
6264 CAMLprim value helper_curl_easy_strerror(value v_code)
6266 CAMLparam1(v_code);
6267 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6271 * Wrappers for the curl_multi_socket_action infrastructure
6272 * Based on curl hiperfifo.c example
6275 #ifdef _WIN32
6276 #ifndef Val_socket
6277 #define Val_socket(v) win_alloc_socket(v)
6278 #endif
6279 #ifndef Socket_val
6280 #error Socket_val not defined in unixsupport.h
6281 #endif
6282 #else /* _WIN32 */
6283 #ifndef Socket_val
6284 #define Socket_val(v) Long_val(v)
6285 #endif
6286 #ifndef Val_socket
6287 #define Val_socket(v) Val_int(v)
6288 #endif
6289 #endif /* _WIN32 */
6291 static void raise_multi_error(char const* msg)
6293 static value* exception = NULL;
6295 if (NULL == exception)
6297 exception = caml_named_value("Curl.Multi.Error");
6298 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6301 caml_raise_with_string(*exception, msg);
6304 static void check_mcode(CURLMcode code)
6306 char const *s = NULL;
6307 switch (code)
6309 case CURLM_OK : return;
6310 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6311 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6312 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6313 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6314 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6315 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6316 case CURLM_LAST : s="CURLM_LAST"; break;
6317 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6318 default : s="CURLM_unknown"; break;
6320 raise_multi_error(s);
6323 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6325 CAMLparam3(v_multi, v_fd, v_kind);
6326 CURLM* h = CURLM_val(v_multi);
6327 int still_running = 0;
6328 CURLMcode rc = CURLM_OK;
6329 curl_socket_t socket;
6330 int kind = 0;
6332 if (Val_none == v_fd)
6334 socket = CURL_SOCKET_TIMEOUT;
6336 else
6338 socket = Socket_val(Field(v_fd, 0));
6341 switch (Int_val(v_kind))
6343 case 0 : break;
6344 case 1 : kind |= CURL_CSELECT_IN; break;
6345 case 2 : kind |= CURL_CSELECT_OUT; break;
6346 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6347 default:
6348 raise_multi_error("caml_curl_multi_socket_action");
6351 /* fprintf(stdout,"fd %u kind %u\n",socket, kind); fflush(stdout); */
6353 caml_enter_blocking_section();
6354 do {
6355 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6356 } while (rc == CURLM_CALL_MULTI_PERFORM);
6357 caml_leave_blocking_section();
6359 check_mcode(rc);
6361 CAMLreturn(Val_int(still_running));
6364 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6366 CAMLparam1(v_multi);
6367 int still_running = 0;
6368 CURLMcode rc = CURLM_OK;
6369 CURLM* h = CURLM_val(v_multi);
6371 caml_enter_blocking_section();
6372 do {
6373 rc = curl_multi_socket_all(h, &still_running);
6374 } while (rc == CURLM_CALL_MULTI_PERFORM);
6375 caml_leave_blocking_section();
6377 check_mcode(rc);
6379 CAMLreturn(Val_int(still_running));
6382 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6384 CAMLparam0();
6385 CAMLlocal2(v_what,csock);
6386 (void)e;
6387 (void)sockp; /* not used */
6389 /* v_what = Val_int(what); */
6390 switch (what)
6392 case CURL_POLL_NONE : v_what = Val_int(0); break;
6393 case CURL_POLL_IN : v_what = Val_int(1); break;
6394 case CURL_POLL_OUT : v_what = Val_int(2); break;
6395 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6396 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6397 default:
6398 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6399 fflush(stderr);
6400 raise_multi_error("curlm_sock_cb"); /* FIXME exception from callback */
6402 csock=Val_socket(sock);
6403 caml_callback2(Field(multi->values,curlmopt_socket_function),
6404 csock, v_what);
6406 CAMLreturn(0);
6409 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6411 int ret;
6412 caml_leave_blocking_section();
6413 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6414 caml_enter_blocking_section();
6415 return ret;
6418 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6420 CAMLparam2(v_multi, v_cb);
6421 ml_multi_handle* multi = Multi_val(v_multi);
6423 Store_field(multi->values, curlmopt_socket_function, v_cb);
6425 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6426 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6428 CAMLreturn(Val_unit);
6431 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6433 CAMLparam0();
6434 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6435 CAMLreturn0;
6438 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6440 (void)multi;
6442 caml_leave_blocking_section();
6443 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6444 caml_enter_blocking_section();
6445 return 0;
6448 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6450 CAMLparam2(v_multi, v_cb);
6451 ml_multi_handle* multi = Multi_val(v_multi);
6453 Store_field(multi->values, curlmopt_timer_function, v_cb);
6455 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6456 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6458 CAMLreturn(Val_unit);
6461 CAMLprim value caml_curl_multi_timeout(value v_multi)
6463 CAMLparam1(v_multi);
6464 long ms = 0;
6465 CURLMcode rc = CURLM_OK;
6466 ml_multi_handle* multi = Multi_val(v_multi);
6468 rc = curl_multi_timeout(multi->handle, &ms);
6470 check_mcode(rc);
6472 CAMLreturn(Val_long(ms));