release 0.6.1
[ocurl.git] / curl-helper.c
blob6e8a39f8dec6c8647316a4347cdf40ccb5ac808f
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 #include <curl/curl.h>
15 #include <caml/alloc.h>
16 #include <caml/memory.h>
17 #include <caml/mlvalues.h>
18 #include <caml/callback.h>
19 #include <caml/fail.h>
20 #include <caml/custom.h>
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #else
25 #pragma message("No config file given.")
26 #endif
28 void leave_blocking_section(void);
29 void enter_blocking_section(void);
31 #define Val_none Val_int(0)
33 static __inline value
34 Val_some( value v )
36 CAMLparam1( v );
37 CAMLlocal1( some );
38 some = caml_alloc(1, 0);
39 Store_field( some, 0, v );
40 CAMLreturn( some );
43 static value Val_pair(value v1, value v2)
45 CAMLparam2(v1,v2);
46 CAMLlocal1(pair);
47 pair = caml_alloc_small(2,0);
48 Field(pair,0) = v1;
49 Field(pair,1) = v2;
50 CAMLreturn(pair);
53 static value Val_cons(value list, value v) { return Val_pair(v,list); }
55 typedef struct Connection Connection;
56 typedef struct ConnectionList ConnectionList;
58 #define Connection_val(v) ((Connection *)Field(v, 0))
60 enum OcamlValues
62 OcamlWriteCallback,
63 OcamlReadCallback,
64 OcamlErrorBuffer,
65 OcamlPostFields,
66 OcamlHTTPHeader,
67 OcamlHTTPPost,
68 OcamlQuote,
69 OcamlPostQuote,
70 OcamlHeaderCallback,
71 OcamlProgressCallback,
72 OcamlDebugCallback,
73 OcamlHTTP200Aliases,
74 OcamlIOCTLCallback,
75 OcamlSeekFunctionCallback,
76 OcamlOpenSocketFunctionCallback,
78 OcamlURL,
79 OcamlProxy,
80 OcamlUserPWD,
81 OcamlProxyUserPWD,
82 OcamlRange,
83 OcamlReferer,
84 OcamlUserAgent,
85 OcamlFTPPort,
86 OcamlCookie,
87 OcamlHTTPPostStrings,
88 OcamlSSLCert,
89 OcamlSSLCertType,
90 OcamlSSLCertPasswd,
91 OcamlSSLKey,
92 OcamlSSLKeyType,
93 OcamlSSLKeyPasswd,
94 OcamlSSLEngine,
95 OcamlCookieFile,
96 OcamlCustomRequest,
97 OcamlInterface,
98 OcamlCAInfo,
99 OcamlCAPath,
100 OcamlRandomFile,
101 OcamlEGDSocket,
102 OcamlCookieJar,
103 OcamlSSLCipherList,
104 OcamlPrivate,
105 OcamlNETRCFile,
106 OcamlFTPAccount,
107 OcamlCookieList,
108 OcamlFTPAlternativeToUser,
109 OcamlSSHPublicKeyFile,
110 OcamlSSHPrivateKeyFile,
111 OcamlSSHHostPublicKeyMD5,
112 OcamlCopyPostFields,
114 /* Not used, last for size */
115 OcamlValuesSize
118 struct Connection
120 CURL *connection;
121 Connection *next;
122 Connection *prev;
124 value ocamlValues;
126 char *url;
127 char *proxy;
128 char *userPwd;
129 char *proxyUserPwd;
130 char *range;
131 char *errorBuffer;
132 char *postFields;
133 int postFieldSize;
134 char *referer;
135 char *userAgent;
136 char *ftpPort;
137 char *cookie;
138 struct curl_slist *httpHeader;
139 struct curl_httppost *httpPostFirst;
140 struct curl_httppost *httpPostLast;
141 struct curl_slist *httpPostStrings;
142 struct curl_slist *resolve;
143 char *sslCert;
144 char *sslCertType;
145 char *sslCertPasswd;
146 char *sslKey;
147 char *sslKeyType;
148 char *sslKeyPasswd;
149 char *sslEngine;
150 struct curl_slist *quote;
151 struct curl_slist *postQuote;
152 char *cookieFile;
153 char *customRequest;
154 char *interface_; /* `interface` gives problems on windows */
155 char *caInfo;
156 char *caPath;
157 char *randomFile;
158 char *egdSocket;
159 char *cookieJar;
160 char *sslCipherList;
161 char *private;
162 struct curl_slist *http200Aliases;
163 char *netrcFile;
164 char *ftpaccount;
165 char *cookielist;
166 char *ftpAlternativeToUser;
167 char *sshPublicKeyFile;
168 char *sshPrivateKeyFile;
169 char *sshHostPublicKeyMD5;
170 char *copyPostFields;
171 char *dns_servers;
174 struct ConnectionList
176 Connection *head;
177 Connection *tail;
180 static ConnectionList connectionList = {NULL, NULL};
182 typedef struct CURLErrorMapping CURLErrorMapping;
184 struct CURLErrorMapping
186 char *name;
187 CURLcode error;
190 CURLErrorMapping errorMap[] =
192 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
193 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
194 #else
195 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
196 #endif
197 #if HAVE_DECL_CURLE_FAILED_INIT
198 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
199 #else
200 {"CURLE_FAILED_INIT", -1},
201 #endif
202 #if HAVE_DECL_CURLE_URL_MALFORMAT
203 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
204 #else
205 {"CURLE_URL_MALFORMAT", -1},
206 #endif
207 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
208 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
209 #else
210 {"CURLE_URL_MALFORMAT_USER", -1},
211 #endif
212 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
213 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
214 #else
215 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
216 #endif
217 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
218 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
219 #else
220 {"CURLE_COULDNT_RESOLVE_HOST", -1},
221 #endif
222 #if HAVE_DECL_CURLE_COULDNT_CONNECT
223 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
224 #else
225 {"CURLE_COULDNT_CONNECT", -1},
226 #endif
227 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
228 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
229 #else
230 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
231 #endif
232 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
233 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
234 #else
235 {"CURLE_FTP_ACCESS_DENIED", -1},
236 #endif
237 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
238 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
239 #else
240 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
241 #endif
242 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
243 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
244 #else
245 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
246 #endif
247 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
248 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
249 #else
250 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
251 #endif
252 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
253 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
254 #else
255 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
256 #endif
257 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
258 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
259 #else
260 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
261 #endif
262 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
263 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
264 #else
265 {"CURLE_FTP_CANT_GET_HOST", -1},
266 #endif
267 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
268 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
269 #else
270 {"CURLE_FTP_CANT_RECONNECT", -1},
271 #endif
272 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
273 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
274 #else
275 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
276 #endif
277 #if HAVE_DECL_CURLE_PARTIAL_FILE
278 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
279 #else
280 {"CURLE_PARTIAL_FILE", -1},
281 #endif
282 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
283 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
284 #else
285 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
286 #endif
287 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
288 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
289 #else
290 {"CURLE_FTP_WRITE_ERROR", -1},
291 #endif
292 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
293 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
294 #else
295 {"CURLE_FTP_QUOTE_ERROR", -1},
296 #endif
297 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
298 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
299 #else
300 {"CURLE_HTTP_NOT_FOUND", -1},
301 #endif
302 #if HAVE_DECL_CURLE_WRITE_ERROR
303 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
304 #else
305 {"CURLE_WRITE_ERROR", -1},
306 #endif
307 #if HAVE_DECL_CURLE_MALFORMAT_USER
308 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
309 #else
310 {"CURLE_MALFORMAT_USER", -1},
311 #endif
312 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
313 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
314 #else
315 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
316 #endif
317 #if HAVE_DECL_CURLE_READ_ERROR
318 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
319 #else
320 {"CURLE_READ_ERROR", -1},
321 #endif
322 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
323 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
324 #else
325 {"CURLE_OUT_OF_MEMORY", -1},
326 #endif
327 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
328 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
329 #else
330 {"CURLE_OPERATION_TIMEOUTED", -1},
331 #endif
332 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
333 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
334 #else
335 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
336 #endif
337 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
338 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
339 #else
340 {"CURLE_FTP_PORT_FAILED", -1},
341 #endif
342 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
343 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
344 #else
345 {"CURLE_FTP_COULDNT_USE_REST", -1},
346 #endif
347 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
348 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
349 #else
350 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
351 #endif
352 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
353 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
354 #else
355 {"CURLE_HTTP_RANGE_ERROR", -1},
356 #endif
357 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
358 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
359 #else
360 {"CURLE_HTTP_POST_ERROR", -1},
361 #endif
362 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
363 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
364 #else
365 {"CURLE_SSL_CONNECT_ERROR", -1},
366 #endif
367 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
368 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
369 #else
370 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
371 #endif
372 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
373 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
374 #else
375 {"CURLE_FILE_COULDNT_READ_FILE", -1},
376 #endif
377 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
378 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
379 #else
380 {"CURLE_LDAP_CANNOT_BIND", -1},
381 #endif
382 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
383 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
384 #else
385 {"CURLE_LDAP_SEARCH_FAILED", -1},
386 #endif
387 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
388 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
389 #else
390 {"CURLE_LIBRARY_NOT_FOUND", -1},
391 #endif
392 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
393 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
394 #else
395 {"CURLE_FUNCTION_NOT_FOUND", -1},
396 #endif
397 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
398 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
399 #else
400 {"CURLE_ABORTED_BY_CALLBACK", -1},
401 #endif
402 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
403 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
404 #else
405 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
406 #endif
407 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
408 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
409 #else
410 {"CURLE_BAD_CALLING_ORDER", -1},
411 #endif
412 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
413 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
414 #else
415 {"CURLE_HTTP_PORT_FAILED", -1},
416 #endif
417 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
418 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
419 #else
420 {"CURLE_BAD_PASSWORD_ENTERED", -1},
421 #endif
422 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
423 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
424 #else
425 {"CURLE_TOO_MANY_REDIRECTS", -1},
426 #endif
427 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
428 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
429 #else
430 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
431 #endif
432 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
433 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
434 #else
435 {"CURLE_TELNET_OPTION_SYNTAX", -1},
436 #endif
437 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
438 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
439 #else
440 {"CURLE_SSL_PEER_CERTIFICATE", -1},
441 #endif
442 #if HAVE_DECL_CURLE_GOT_NOTHING
443 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
444 #else
445 {"CURLE_GOT_NOTHING", -1},
446 #endif
447 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
448 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
449 #else
450 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
451 #endif
452 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
453 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
454 #else
455 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
456 #endif
457 #if HAVE_DECL_CURLE_SEND_ERROR
458 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
459 #else
460 {"CURLE_SEND_ERROR", -1},
461 #endif
462 #if HAVE_DECL_CURLE_RECV_ERROR
463 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
464 #else
465 {"CURLE_RECV_ERROR", -1},
466 #endif
467 #if HAVE_DECL_CURLE_SHARE_IN_USE
468 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
469 #else
470 {"CURLE_SHARE_IN_USE", -1},
471 #endif
472 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
473 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
474 #else
475 {"CURLE_SSL_CERTPROBLEN", -1},
476 #endif
477 #if HAVE_DECL_CURLE_SSL_CIPHER
478 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
479 #else
480 {"CURLE_SSL_CIPHER", -1},
481 #endif
482 #if HAVE_DECL_CURLE_SSL_CACERT
483 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
484 #else
485 {"CURLE_SSL_CACERT", -1},
486 #endif
487 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
488 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
489 #else
490 {"CURLE_BAD_CONTENT_ENCODING", -1},
491 #endif
492 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
493 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
494 #else
495 {"CURLE_LDAP_INVALID_URL", -1},
496 #endif
497 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
498 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
499 #else
500 {"CURLE_FILESIZE_EXCEEDED", -1},
501 #endif
502 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
503 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
504 #else
505 {"CURLE_FTP_SSL_FAILED", -1},
506 #endif
507 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
508 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
509 #else
510 {"CURLE_SEND_FAIL_REWIND", -1},
511 #endif
512 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
513 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
514 #else
515 {"CURLE_SSL_ENGINE_INITFAILED", -1},
516 #endif
517 #if HAVE_DECL_CURLE_LOGIN_DENIED
518 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
519 #else
520 {"CURLE_LOGIN_DENIED", -1},
521 #endif
522 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
523 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
524 #else
525 {"CURLE_TFTP_NOTFOUND", -1},
526 #endif
527 #if HAVE_DECL_CURLE_TFTP_PERM
528 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
529 #else
530 {"CURLE_TFTP_PERM", -1},
531 #endif
532 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
533 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
534 #else
535 {"CURLE_REMOTE_DISK_FULL", -1},
536 #endif
537 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
538 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
539 #else
540 {"CURLE_TFTP_ILLEGAL", -1},
541 #endif
542 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
543 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
544 #else
545 {"CURLE_TFTP_UNKNOWNID", -1},
546 #endif
547 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
548 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
549 #else
550 {"CURLE_REMOTE_FILE_EXISTS", -1},
551 #endif
552 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
553 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
554 #else
555 {"CURLE_TFTP_NOSUCHUSER", -1},
556 #endif
557 #if HAVE_DECL_CURLE_CONV_FAILED
558 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
559 #else
560 {"CURLE_CONV_FAILED", -1},
561 #endif
562 #if HAVE_DECL_CURLE_CONV_REQUIRED
563 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
564 #else
565 {"CURLE_CONV_REQUIRED", -1},
566 #endif
567 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
568 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
569 #else
570 {"CURLE_SSL_CACERT_BADFILE", -1},
571 #endif
572 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
573 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
574 #else
575 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
576 #endif
577 #if HAVE_DECL_CURLE_SSH
578 {"CURLE_SSH", CURLE_SSH},
579 #else
580 {"CURLE_SSH", -1},
581 #endif
582 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
583 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
584 #else
585 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
586 #endif
587 #if HAVE_DECL_CURLE_AGAIN
588 {"CURLE_AGAIN", CURLE_AGAIN},
589 #else
590 {"CURLE_AGAIN", -1},
591 #endif
592 {"CURLE_OK", CURLE_OK},
593 {NULL, 0}
596 typedef struct CURLOptionMapping CURLOptionMapping;
598 struct CURLOptionMapping
600 void (*optionHandler)(Connection *, value);
601 char *name;
602 CURLoption option;
605 CURLOptionMapping unimplementedOptionMap[] =
607 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
608 {NULL, NULL, 0}
611 static void handleWriteFunction(Connection *, value);
612 static void handleReadFunction(Connection *, value);
613 static void handleInFileSize(Connection *, value);
614 static void handleURL(Connection *, value);
615 static void handleProxy(Connection *, value);
616 static void handleProxyPort(Connection *, value);
617 static void handleHTTPProxyTunnel(Connection *, value);
618 static void handleVerbose(Connection *, value);
619 static void handleHeader(Connection *, value);
620 static void handleNoProgress(Connection *, value);
621 static void handleNoSignal(Connection *, value);
622 static void handleNoBody(Connection *, value);
623 static void handleFailOnError(Connection *, value);
624 static void handleUpload(Connection *, value);
625 static void handlePost(Connection *, value);
626 static void handleFTPListOnly(Connection *, value);
627 static void handleFTPAppend(Connection *, value);
628 static void handleNETRC(Connection *, value);
629 static void handleEncoding(Connection *, value);
630 static void handleFollowLocation(Connection *, value);
631 static void handleTransferText(Connection *, value);
632 static void handlePut(Connection *, value);
633 static void handleUserPwd(Connection *, value);
634 static void handleProxyUserPwd(Connection *, value);
635 static void handleRange(Connection *, value);
636 static void handleErrorBuffer(Connection *, value);
637 static void handleTimeout(Connection *, value);
638 static void handlePostFields(Connection *, value);
639 static void handlePostFieldSize(Connection *, value);
640 static void handleReferer(Connection *, value);
641 static void handleUserAgent(Connection *, value);
642 static void handleFTPPort(Connection *, value);
643 static void handleLowSpeedLimit(Connection *, value);
644 static void handleLowSpeedTime(Connection *, value);
645 static void handleResumeFrom(Connection *, value);
646 static void handleCookie(Connection *, value);
647 static void handleHTTPHeader(Connection *, value);
648 static void handleHTTPPost(Connection *, value);
649 static void handleSSLCert(Connection *, value);
650 static void handleSSLCertType(Connection *, value);
651 static void handleSSLCertPasswd(Connection *, value);
652 static void handleSSLKey(Connection *, value);
653 static void handleSSLKeyType(Connection *, value);
654 static void handleSSLKeyPasswd(Connection *, value);
655 static void handleSSLEngine(Connection *, value);
656 static void handleSSLEngineDefault(Connection *, value);
657 static void handleCRLF(Connection *, value);
658 static void handleQuote(Connection *, value);
659 static void handlePostQuote(Connection *, value);
660 static void handleHeaderFunction(Connection *, value);
661 static void handleCookieFile(Connection *, value);
662 static void handleSSLVersion(Connection *, value);
663 static void handleTimeCondition(Connection *, value);
664 static void handleTimeValue(Connection *, value);
665 static void handleCustomRequest(Connection *, value);
666 static void handleInterface(Connection *, value);
667 static void handleKRB4Level(Connection *, value);
668 static void handleProgressFunction(Connection *, value);
669 static void handleSSLVerifyPeer(Connection *, value);
670 static void handleCAInfo(Connection *, value);
671 static void handleCAPath(Connection *, value);
672 static void handleFileTime(Connection *, value);
673 static void handleMaxRedirs(Connection *, value);
674 static void handleMaxConnects(Connection *, value);
675 static void handleClosePolicy(Connection *, value);
676 static void handleFreshConnect(Connection *, value);
677 static void handleForbidReuse(Connection *, value);
678 static void handleRandomFile(Connection *, value);
679 static void handleEGDSocket(Connection *, value);
680 static void handleConnectTimeout(Connection *, value);
681 static void handleHTTPGet(Connection *, value);
682 static void handleSSLVerifyHost(Connection *, value);
683 static void handleCookieJar(Connection *, value);
684 static void handleSSLCipherList(Connection *, value);
685 static void handleHTTPVersion(Connection *, value);
686 static void handleFTPUseEPSV(Connection *, value);
687 static void handleDNSCacheTimeout(Connection *, value);
688 static void handleDNSUseGlobalCache(Connection *, value);
689 static void handleDebugFunction(Connection *, value);
690 static void handlePrivate(Connection *, value);
691 static void handleHTTP200Aliases(Connection *, value);
692 static void handleUnrestrictedAuth(Connection *, value);
693 static void handleFTPUseEPRT(Connection *, value);
694 static void handleHTTPAuth(Connection *, value);
695 static void handleFTPCreateMissingDirs(Connection *, value);
696 static void handleProxyAuth(Connection *, value);
697 static void handleFTPResponseTimeout(Connection *, value);
698 static void handleIPResolve(Connection *, value);
699 static void handleMaxFileSize(Connection *, value);
700 static void handleInFileSizeLarge(Connection *, value);
701 static void handleResumeFromLarge(Connection *, value);
702 static void handleMaxFileSizeLarge(Connection *, value);
703 static void handleNETRCFile(Connection *, value);
704 static void handleFTPSSL(Connection *, value);
705 static void handlePostFieldSizeLarge(Connection *, value);
706 static void handleTCPNoDelay(Connection *, value);
707 static void handleFTPSSLAuth(Connection *, value);
708 static void handleIOCTLFunction(Connection *, value);
709 static void handleFTPAccount(Connection *, value);
710 static void handleCookieList(Connection *, value);
711 static void handleIgnoreContentLength(Connection *, value);
712 static void handleFTPSkipPASVIP(Connection *, value);
713 static void handleFTPFileMethod(Connection *, value);
714 static void handleLocalPort(Connection *, value);
715 static void handleLocalPortRange(Connection *, value);
716 static void handleConnectOnly(Connection *, value);
717 static void handleMaxSendSpeedLarge(Connection *, value);
718 static void handleMaxRecvSpeedLarge(Connection *, value);
719 static void handleFTPAlternativeToUser(Connection *, value);
720 static void handleSSLSessionIdCache(Connection *, value);
721 static void handleSSHAuthTypes(Connection *, value);
722 static void handleSSHPublicKeyFile(Connection *, value);
723 static void handleSSHPrivateKeyFile(Connection *, value);
724 static void handleFTPSSLCCC(Connection *, value);
725 static void handleTimeoutMS(Connection *, value);
726 static void handleConnectTimeoutMS(Connection *, value);
727 static void handleHTTPTransferDecoding(Connection *, value);
728 static void handleHTTPContentDecoding(Connection *, value);
729 static void handleNewFilePerms(Connection *, value);
730 static void handleNewDirectoryPerms(Connection *, value);
731 static void handlePost301(Connection *, value);
732 static void handleSSHHostPublicKeyMD5(Connection *, value);
733 static void handleCopyPostFields(Connection *, value);
734 static void handleProxyTransferMode(Connection *, value);
735 static void handleSeekFunction(Connection *, value);
736 static void handleAutoReferer(Connection *, value);
737 static void handleOpenSocketFunction(Connection *, value);
738 static void handleProxyType(Connection *, value);
739 static void handleProtocols(Connection *, value);
740 static void handleRedirProtocols(Connection *, value);
741 static void handleResolve(Connection *, value);
742 static void handleDnsServers(Connection *, value);
744 CURLOptionMapping implementedOptionMap[] =
746 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
747 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
748 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
749 {handleURL, "CURLOPT_URL", CURLOPT_URL},
750 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
751 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
752 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
753 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
754 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
755 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
756 #if HAVE_DECL_CURLOPT_NOSIGNAL
757 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
758 #else
759 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
760 #endif
761 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
762 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
763 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
764 {handlePost, "CURLOPT_POST", CURLOPT_POST},
765 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
766 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
767 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
768 #if HAVE_DECL_CURLOPT_ENCODING
769 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
770 #else
771 {handleEncoding, "CURLOPT_ENCODING", 0},
772 #endif
773 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
774 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
775 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
776 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
777 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
778 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
779 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
780 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
781 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
782 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
783 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
784 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
785 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
786 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
787 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
788 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
789 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
790 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
791 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
792 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
793 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
794 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
795 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
796 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
797 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
798 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
799 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
800 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
801 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
802 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
803 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
804 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
805 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
806 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
807 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
808 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
809 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
810 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
811 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
812 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
813 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
814 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
815 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
816 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
817 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
818 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
819 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
820 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
821 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
822 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
823 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
824 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
825 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
826 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
827 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
828 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
829 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
830 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
831 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
832 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
833 #if HAVE_DECL_CURLOPT_PRIVATE
834 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
835 #else
836 {handlePrivate, "CURLOPT_PRIVATE", 0},
837 #endif
838 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
839 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
840 #else
841 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
842 #endif
843 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
844 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
845 #else
846 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
847 #endif
848 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
849 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
850 #else
851 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
852 #endif
853 #if HAVE_DECL_CURLOPT_HTTPAUTH
854 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
855 #else
856 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
857 #endif
858 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
859 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
860 #else
861 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
862 #endif
863 #if HAVE_DECL_CURLOPT_PROXYAUTH
864 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
865 #else
866 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
867 #endif
868 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
869 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
870 #else
871 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
872 #endif
873 #if HAVE_DECL_CURLOPT_IPRESOLVE
874 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
875 #else
876 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
877 #endif
878 #if HAVE_DECL_CURLOPT_MAXFILESIZE
879 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
880 #else
881 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
882 #endif
883 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
884 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
885 #else
886 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
887 #endif
888 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
889 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
890 #else
891 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
892 #endif
893 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
894 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
895 #else
896 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
897 #endif
898 #if HAVE_DECL_CURLOPT_NETRC_FILE
899 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
900 #else
901 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
902 #endif
903 #if HAVE_DECL_CURLOPT_FTP_SSL
904 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
905 #else
906 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
907 #endif
908 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
909 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
910 #else
911 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
912 #endif
913 #if HAVE_DECL_CURLOPT_TCP_NODELAY
914 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
915 #else
916 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
917 #endif
918 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
919 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
920 #else
921 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
922 #endif
923 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
924 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
925 #else
926 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
927 #endif
928 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
929 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
930 #else
931 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
932 #endif
933 #if HAVE_DECL_CURLOPT_COOKIELIST
934 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
935 #else
936 {handleCookieList, "CURLOPT_COOKIELIST", 0},
937 #endif
938 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
939 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
940 #else
941 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
942 #endif
943 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
944 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
945 #else
946 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
947 #endif
948 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
949 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
950 #else
951 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
952 #endif
953 #if HAVE_DECL_CURLOPT_LOCALPORT
954 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
955 #else
956 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
957 #endif
958 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
959 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
960 #else
961 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
962 #endif
963 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
964 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
965 #else
966 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
967 #endif
968 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
969 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
970 #else
971 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
972 #endif
973 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
974 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
975 #else
976 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
977 #endif
978 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
979 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
980 #else
981 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
982 #endif
983 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
984 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
985 #else
986 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
987 #endif
988 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
989 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
990 #else
991 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
992 #endif
993 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
994 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
995 #else
996 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
997 #endif
998 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
999 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
1000 #else
1001 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
1002 #endif
1003 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
1004 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
1005 #else
1006 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
1007 #endif
1008 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
1009 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
1010 #else
1011 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
1012 #endif
1013 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
1014 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
1015 #else
1016 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
1017 #endif
1018 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1019 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1020 #else
1021 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1022 #endif
1023 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1024 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1025 #else
1026 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1027 #endif
1028 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1029 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1030 #else
1031 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1032 #endif
1033 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1034 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1035 #else
1036 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1037 #endif
1038 #if HAVE_DECL_CURLOPT_POST301
1039 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1040 #else
1041 {handlePost301, "CURLOPT_POST301", 0},
1042 #endif
1043 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1044 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1045 #else
1046 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1047 #endif
1048 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1049 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1050 #else
1051 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1052 #endif
1053 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1054 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1055 #else
1056 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1057 #endif
1058 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1059 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1060 #else
1061 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1062 #endif
1063 #if HAVE_DECL_CURLOPT_AUTOREFERER
1064 {handleAutoReferer, "CURLOPT_AUTOREFERER", CURLOPT_AUTOREFERER},
1065 #else
1066 {handleAutoReferer, "CURLOPT_AUTOREFERER", 0},
1067 #endif
1068 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1069 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION},
1070 #else
1071 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", 0},
1072 #endif
1073 #if HAVE_DECL_CURLOPT_PROXYTYPE
1074 {handleProxyType, "CURLOPT_PROXYTYPE", CURLOPT_PROXYTYPE},
1075 #else
1076 {handleProxyType, "CURLOPT_PROXYTYPE", 0},
1077 #endif
1078 #if HAVE_DECL_CURLOPT_PROTOCOLS
1079 {handleProtocols, "CURLOPT_PROTOCOLS", CURLOPT_PROTOCOLS},
1080 #else
1081 {handleProtocols, "CURLOPT_PROTOCOLS", 0},
1082 #endif
1083 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
1084 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS},
1085 #else
1086 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", 0},
1087 #endif
1088 #if HAVE_DECL_CURLOPT_RESOLVE
1089 {handleResolve, "CURLOPT_RESOLVE", CURLOPT_RESOLVE},
1090 #else
1091 {handleResolve, "CURLOPT_RESOLVE", 0},
1092 #endif
1093 #if HAVE_DECL_CURLOPT_DNS_SERVERS
1094 {handleDnsServers, "CURLOPT_DNS_SERVERS", CURLOPT_DNS_SERVERS},
1095 #else
1096 {handleDnsServers, "CURLOPT_DNS_SERVERS", 0},
1097 #endif
1100 static char *findOption(CURLOptionMapping optionMap[],
1101 CURLoption option)
1103 return optionMap[option].name;
1106 static void free_curl_slist(struct curl_slist *slist)
1108 if (NULL == slist)
1109 return;
1111 curl_slist_free_all(slist);
1114 static void raiseError(Connection *conn, CURLcode code)
1116 CAMLparam0();
1117 CAMLlocal1(exceptionData);
1118 value *exception;
1119 char *errorString = "Unknown Error";
1120 int i;
1122 for (i = 0; errorMap[i].name != NULL; i++)
1124 if (errorMap[i].error == code)
1126 errorString = errorMap[i].name;
1127 break;
1131 exceptionData = caml_alloc(3, 0);
1133 Store_field(exceptionData, 0, Val_int(code));
1134 Store_field(exceptionData, 1, Val_int(code));
1135 Store_field(exceptionData, 2, copy_string(errorString));
1137 if (conn != NULL && conn->errorBuffer != NULL)
1139 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1140 copy_string(conn->errorBuffer));
1143 exception = caml_named_value("CurlException");
1145 if (exception == NULL)
1146 caml_failwith("CurlException not registered");
1148 raise_with_arg(*exception, exceptionData);
1150 CAMLreturn0;
1153 static void resetOcamlValues(Connection* connection)
1155 int i;
1157 for (i = 0; i < OcamlValuesSize; i++)
1158 Store_field(connection->ocamlValues, i, Val_unit);
1161 static Connection *newConnection(void)
1163 Connection *connection;
1165 connection = (Connection *)malloc(sizeof(Connection));
1167 enter_blocking_section();
1168 connection->connection = curl_easy_init();
1169 leave_blocking_section();
1171 connection->next = NULL;
1172 connection->prev = NULL;
1174 if (connectionList.tail == NULL)
1176 connectionList.tail = connection;
1177 connectionList.head = connection;
1179 else
1181 connection->prev = connectionList.head;
1182 connectionList.head->next = connection;
1183 connectionList.head = connection;
1186 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1187 resetOcamlValues(connection);
1188 register_global_root(&connection->ocamlValues);
1190 connection->url = NULL;
1191 connection->proxy = NULL;
1192 connection->userPwd = NULL;
1193 connection->proxyUserPwd = NULL;
1194 connection->range = NULL;
1195 connection->errorBuffer = NULL;
1196 connection->postFields = NULL;
1197 connection->postFieldSize = -1;
1198 connection->referer = NULL;
1199 connection->userAgent = NULL;
1200 connection->ftpPort = NULL;
1201 connection->cookie = NULL;
1202 connection->httpHeader = NULL;
1203 connection->httpPostFirst = NULL;
1204 connection->httpPostLast = NULL;
1205 connection->httpPostStrings = NULL;
1206 connection->sslCert = NULL;
1207 connection->sslCertType = NULL;
1208 connection->sslCertPasswd = NULL;
1209 connection->sslKey = NULL;
1210 connection->sslKeyType = NULL;
1211 connection->sslKeyPasswd = NULL;
1212 connection->sslEngine = NULL;
1213 connection->quote = NULL;
1214 connection->postQuote = NULL;
1215 connection->cookieFile = NULL;
1216 connection->customRequest = NULL;
1217 connection->interface_ = NULL;
1218 connection->caInfo = NULL;
1219 connection->caPath = NULL;
1220 connection->randomFile = NULL;
1221 connection->egdSocket = NULL;
1222 connection->cookieJar = NULL;
1223 connection->sslCipherList = NULL;
1224 connection->private = NULL;
1225 connection->http200Aliases = NULL;
1226 connection->netrcFile = NULL;
1227 connection->ftpaccount = NULL;
1228 connection->cookielist = NULL;
1229 connection->ftpAlternativeToUser = NULL;
1230 connection->sshPublicKeyFile = NULL;
1231 connection->sshPrivateKeyFile = NULL;
1232 connection->copyPostFields = NULL;
1233 connection->resolve = NULL;
1234 connection->dns_servers = NULL;
1236 return connection;
1239 static Connection *duplicateConnection(Connection *original)
1241 Connection *connection;
1243 connection = (Connection *)malloc(sizeof(Connection));
1245 enter_blocking_section();
1246 connection->connection = curl_easy_duphandle(original->connection);
1247 leave_blocking_section();
1249 connection->next = NULL;
1250 connection->prev = NULL;
1252 if (connectionList.tail == NULL)
1254 connectionList.tail = connection;
1255 connectionList.head = connection;
1257 else
1259 connection->prev = connectionList.head;
1260 connectionList.head->next = connection;
1261 connectionList.head = connection;
1264 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1265 resetOcamlValues(connection);
1266 register_global_root(&connection->ocamlValues);
1268 Store_field(connection->ocamlValues, OcamlWriteCallback,
1269 Field(original->ocamlValues, OcamlWriteCallback));
1270 Store_field(connection->ocamlValues, OcamlReadCallback,
1271 Field(original->ocamlValues, OcamlReadCallback));
1272 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1273 Field(original->ocamlValues, OcamlErrorBuffer));
1274 Store_field(connection->ocamlValues, OcamlPostFields,
1275 Field(original->ocamlValues, OcamlPostFields));
1276 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1277 Field(original->ocamlValues, OcamlHTTPHeader));
1278 Store_field(connection->ocamlValues, OcamlQuote,
1279 Field(original->ocamlValues, OcamlQuote));
1280 Store_field(connection->ocamlValues, OcamlPostQuote,
1281 Field(original->ocamlValues, OcamlPostQuote));
1282 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1283 Field(original->ocamlValues, OcamlHeaderCallback));
1284 Store_field(connection->ocamlValues, OcamlProgressCallback,
1285 Field(original->ocamlValues, OcamlProgressCallback));
1286 Store_field(connection->ocamlValues, OcamlDebugCallback,
1287 Field(original->ocamlValues, OcamlDebugCallback));
1288 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1289 Field(original->ocamlValues, OcamlHTTP200Aliases));
1290 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1291 Field(original->ocamlValues, OcamlIOCTLCallback));
1292 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1293 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1295 connection->url = NULL;
1296 connection->proxy = NULL;
1297 connection->userPwd = NULL;
1298 connection->proxyUserPwd = NULL;
1299 connection->range = NULL;
1300 connection->errorBuffer = NULL;
1301 connection->postFields = NULL;
1302 connection->postFieldSize = -1;
1303 connection->referer = NULL;
1304 connection->userAgent = NULL;
1305 connection->ftpPort = NULL;
1306 connection->cookie = NULL;
1307 connection->httpHeader = NULL;
1308 connection->httpPostFirst = NULL;
1309 connection->httpPostLast = NULL;
1310 connection->httpPostStrings = NULL;
1311 connection->sslCert = NULL;
1312 connection->sslCertType = NULL;
1313 connection->sslCertPasswd = NULL;
1314 connection->sslKey = NULL;
1315 connection->sslKeyType = NULL;
1316 connection->sslKeyPasswd = NULL;
1317 connection->sslEngine = NULL;
1318 connection->quote = NULL;
1319 connection->postQuote = NULL;
1320 connection->cookieFile = NULL;
1321 connection->customRequest = NULL;
1322 connection->interface_ = NULL;
1323 connection->caInfo = NULL;
1324 connection->caPath = NULL;
1325 connection->randomFile = NULL;
1326 connection->egdSocket = NULL;
1327 connection->cookieJar = NULL;
1328 connection->sslCipherList = NULL;
1329 connection->private = NULL;
1330 connection->http200Aliases = NULL;
1331 connection->netrcFile = NULL;
1332 connection->ftpaccount = NULL;
1333 connection->cookielist = NULL;
1334 connection->sshPublicKeyFile = NULL;
1335 connection->sshPrivateKeyFile = NULL;
1336 connection->copyPostFields = NULL;
1337 connection->resolve = NULL;
1338 connection->dns_servers = NULL;
1340 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1341 handleURL(connection, Field(original->ocamlValues,
1342 OcamlURL));
1343 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1344 handleProxy(connection, Field(original->ocamlValues,
1345 OcamlProxy));
1346 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1347 handleUserPwd(connection, Field(original->ocamlValues,
1348 OcamlUserPWD));
1349 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1350 handleProxyUserPwd(connection, Field(original->ocamlValues,
1351 OcamlProxyUserPWD));
1352 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1353 handleRange(connection, Field(original->ocamlValues,
1354 OcamlRange));
1355 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1356 handleErrorBuffer(connection, Field(original->ocamlValues,
1357 OcamlErrorBuffer));
1358 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1359 handlePostFields(connection, Field(original->ocamlValues,
1360 OcamlPostFields));
1361 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1362 handleReferer(connection, Field(original->ocamlValues,
1363 OcamlReferer));
1364 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1365 handleUserAgent(connection, Field(original->ocamlValues,
1366 OcamlUserAgent));
1367 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1368 handleFTPPort(connection, Field(original->ocamlValues,
1369 OcamlFTPPort));
1370 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1371 handleCookie(connection, Field(original->ocamlValues,
1372 OcamlCookie));
1373 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1374 handleHTTPHeader(connection, Field(original->ocamlValues,
1375 OcamlHTTPHeader));
1376 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1377 handleHTTPPost(connection, Field(original->ocamlValues,
1378 OcamlHTTPPost));
1379 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1380 handleSSLCert(connection, Field(original->ocamlValues,
1381 OcamlSSLCert));
1382 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1383 handleSSLCertType(connection, Field(original->ocamlValues,
1384 OcamlSSLCertType));
1385 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1386 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1387 OcamlSSLCertPasswd));
1388 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1389 handleSSLKey(connection, Field(original->ocamlValues,
1390 OcamlSSLKey));
1391 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1392 handleSSLKeyType(connection, Field(original->ocamlValues,
1393 OcamlSSLKeyType));
1394 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1395 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1396 OcamlSSLKeyPasswd));
1397 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1398 handleSSLEngine(connection, Field(original->ocamlValues,
1399 OcamlSSLEngine));
1400 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1401 handleQuote(connection, Field(original->ocamlValues,
1402 OcamlQuote));
1403 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1404 handlePostQuote(connection, Field(original->ocamlValues,
1405 OcamlPostQuote));
1406 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1407 handleCookieFile(connection, Field(original->ocamlValues,
1408 OcamlCookieFile));
1409 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1410 handleCustomRequest(connection, Field(original->ocamlValues,
1411 OcamlCustomRequest));
1412 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1413 handleInterface(connection, Field(original->ocamlValues,
1414 OcamlInterface));
1415 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1416 handleCAInfo(connection, Field(original->ocamlValues,
1417 OcamlCAInfo));
1418 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1419 handleCAPath(connection, Field(original->ocamlValues,
1420 OcamlCAPath));
1421 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1422 handleRandomFile(connection, Field(original->ocamlValues,
1423 OcamlRandomFile));
1424 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1425 handleEGDSocket(connection, Field(original->ocamlValues,
1426 OcamlEGDSocket));
1427 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1428 handleCookieJar(connection, Field(original->ocamlValues,
1429 OcamlCookieJar));
1430 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1431 handleSSLCipherList(connection, Field(original->ocamlValues,
1432 OcamlSSLCipherList));
1433 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1434 handlePrivate(connection, Field(original->ocamlValues,
1435 OcamlPrivate));
1436 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1437 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1438 OcamlHTTP200Aliases));
1439 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1440 handleNETRCFile(connection, Field(original->ocamlValues,
1441 OcamlNETRCFile));
1442 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1443 handleFTPAccount(connection, Field(original->ocamlValues,
1444 OcamlFTPAccount));
1445 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1446 handleCookieList(connection, Field(original->ocamlValues,
1447 OcamlCookieList));
1448 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1449 handleFTPAlternativeToUser(connection,
1450 Field(original->ocamlValues,
1451 OcamlFTPAlternativeToUser));
1452 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1453 handleSSHPublicKeyFile(connection,
1454 Field(original->ocamlValues,
1455 OcamlSSHPublicKeyFile));
1456 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1457 handleSSHPrivateKeyFile(connection,
1458 Field(original->ocamlValues,
1459 OcamlSSHPrivateKeyFile));
1460 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1461 handleCopyPostFields(connection,
1462 Field(original->ocamlValues,
1463 OcamlCopyPostFields));
1465 return connection;
1468 static void free_if(void* p) { if (NULL != p) free(p); }
1470 static void removeConnection(Connection *connection)
1472 enter_blocking_section();
1473 curl_easy_cleanup(connection->connection);
1474 leave_blocking_section();
1476 if (connectionList.tail == connection)
1477 connectionList.tail = connectionList.tail->next;
1478 if (connectionList.head == connection)
1479 connectionList.head = connectionList.head->prev;
1481 if (connection->next != NULL)
1482 connection->next->prev = connection->prev;
1483 if (connection->prev != NULL)
1484 connection->prev->next = connection->next;
1486 remove_global_root(&connection->ocamlValues);
1488 free_if(connection->url);
1489 free_if(connection->proxy);
1490 free_if(connection->userPwd);
1491 free_if(connection->proxyUserPwd);
1492 free_if(connection->range);
1493 free_if(connection->errorBuffer);
1494 free_if(connection->postFields);
1495 free_if(connection->referer);
1496 free_if(connection->userAgent);
1497 free_if(connection->ftpPort);
1498 free_if(connection->cookie);
1499 free_curl_slist(connection->httpHeader);
1500 if (connection->httpPostFirst != NULL)
1501 curl_formfree(connection->httpPostFirst);
1502 free_curl_slist(connection->httpPostStrings);
1503 free_curl_slist(connection->resolve);
1504 free_if(connection->sslCert);
1505 free_if(connection->sslCertType);
1506 free_if(connection->sslCertPasswd);
1507 free_if(connection->sslKey);
1508 free_if(connection->sslKeyType);
1509 free_if(connection->sslKeyPasswd);
1510 free_if(connection->sslEngine);
1511 free_curl_slist(connection->quote);
1512 free_curl_slist(connection->postQuote);
1513 free_if(connection->cookieFile);
1514 free_if(connection->customRequest);
1515 free_if(connection->interface_);
1516 free_if(connection->caInfo);
1517 free_if(connection->caPath);
1518 free_if(connection->randomFile);
1519 free_if(connection->egdSocket);
1520 free_if(connection->cookieJar);
1521 free_if(connection->sslCipherList);
1522 free_if(connection->private);
1523 free_curl_slist(connection->http200Aliases);
1524 free_if(connection->netrcFile);
1525 free_if(connection->ftpaccount);
1526 free_if(connection->cookielist);
1527 free_if(connection->ftpAlternativeToUser);
1528 free_if(connection->sshPublicKeyFile);
1529 free_if(connection->sshPrivateKeyFile);
1530 free_if(connection->copyPostFields);
1531 free_if(connection->dns_servers);
1533 free(connection);
1536 #if 1
1537 static void checkConnection(Connection * connection)
1539 (void)connection;
1541 #else
1542 static void checkConnection(Connection *connection)
1544 Connection *listIter;
1546 listIter = connectionList.tail;
1548 while (listIter != NULL)
1550 if (listIter == connection)
1551 return;
1553 listIter = listIter->next;
1556 failwith("Invalid Connection");
1558 #endif
1560 static Connection* findConnection(CURL* h)
1562 Connection *listIter;
1564 listIter = connectionList.tail;
1566 while (listIter != NULL)
1568 if (listIter->connection == h)
1569 return listIter;
1571 listIter = listIter->next;
1574 failwith("Unknown handle");
1577 #define WRAP_DATA_CALLBACK(f) \
1578 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1580 size_t result;\
1581 leave_blocking_section();\
1582 result = f##_nolock(ptr,size,nmemb,data);\
1583 enter_blocking_section();\
1584 return result;\
1587 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1589 CAMLparam0();
1590 CAMLlocal2(result, str);
1591 Connection *conn = (Connection *)data;
1592 size_t i;
1594 checkConnection(conn);
1596 str = alloc_string(size*nmemb);
1598 for (i = 0; i < size*nmemb; i++)
1599 Byte(str, i) = ptr[i];
1601 result = callback_exn(Field(conn->ocamlValues, OcamlWriteCallback), str);
1603 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1606 WRAP_DATA_CALLBACK(writeFunction)
1608 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1610 CAMLparam0();
1611 CAMLlocal1(result);
1612 Connection *conn = (Connection *)data;
1613 size_t length;
1615 checkConnection(conn);
1617 result = callback_exn(Field(conn->ocamlValues, OcamlReadCallback),
1618 Val_int(size*nmemb));
1620 if (Is_exception_result(result))
1622 CAMLreturnT(size_t,CURL_READFUNC_ABORT);
1625 length = string_length(result);
1627 if (length >= size*nmemb)
1628 length = size*nmemb;
1630 memcpy(ptr, String_val(result), length);
1632 CAMLreturnT(size_t,length);
1635 WRAP_DATA_CALLBACK(readFunction)
1637 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1639 CAMLparam0();
1640 CAMLlocal2(result,str);
1641 Connection *conn = (Connection *)data;
1642 size_t i;
1644 checkConnection(conn);
1646 str = alloc_string(size*nmemb);
1648 for (i = 0; i < size*nmemb; i++)
1649 Byte(str, i) = ptr[i];
1651 result = callback_exn(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1653 CAMLreturnT(size_t, Is_exception_result(result) ? 0 : Int_val(result));
1656 WRAP_DATA_CALLBACK(headerFunction)
1658 static int progressFunction_nolock(void *data,
1659 double dlTotal,
1660 double dlNow,
1661 double ulTotal,
1662 double ulNow)
1664 CAMLparam0();
1665 CAMLlocal1(result);
1666 CAMLlocalN(callbackData, 4);
1667 Connection *conn = (Connection *)data;
1669 checkConnection(conn);
1671 callbackData[0] = copy_double(dlTotal);
1672 callbackData[1] = copy_double(dlNow);
1673 callbackData[2] = copy_double(ulTotal);
1674 callbackData[3] = copy_double(ulNow);
1676 result = callbackN_exn(Field(conn->ocamlValues, OcamlProgressCallback),
1677 4, callbackData);
1679 CAMLreturnT(int, Is_exception_result(result) ? 1 : Bool_val(result));
1682 static int progressFunction(void *data,
1683 double dlTotal,
1684 double dlNow,
1685 double ulTotal,
1686 double ulNow)
1688 int r;
1689 leave_blocking_section();
1690 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1691 enter_blocking_section();
1692 return r;
1695 static int debugFunction_nolock(CURL *debugConnection,
1696 curl_infotype infoType,
1697 char *buffer,
1698 size_t bufferLength,
1699 void *data)
1701 CAMLparam0();
1702 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1703 size_t i;
1704 Connection *conn = (Connection *)data;
1705 (void)debugConnection; /* not used */
1707 checkConnection(conn);
1709 camlDebugConnection = (value)conn;
1710 camlInfoType = Val_long(infoType);
1711 camlMessage = alloc_string(bufferLength);
1713 for (i = 0; i < bufferLength; i++)
1714 Byte(camlMessage, i) = buffer[i];
1716 callback3_exn(Field(conn->ocamlValues, OcamlDebugCallback),
1717 camlDebugConnection,
1718 camlInfoType,
1719 camlMessage);
1721 CAMLreturnT(int, 0);
1724 static int debugFunction(CURL *debugConnection,
1725 curl_infotype infoType,
1726 char *buffer,
1727 size_t bufferLength,
1728 void *data)
1730 int r;
1731 leave_blocking_section();
1732 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1733 enter_blocking_section();
1734 return r;
1737 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1738 int cmd,
1739 void *data)
1741 CAMLparam0();
1742 CAMLlocal3(camlResult, camlConnection, camlCmd);
1743 Connection *conn = (Connection *)data;
1744 curlioerr result = CURLIOE_OK;
1745 (void)ioctl; /* not used */
1747 checkConnection(conn);
1749 if (cmd == CURLIOCMD_NOP)
1750 camlCmd = Val_long(0);
1751 else if (cmd == CURLIOCMD_RESTARTREAD)
1752 camlCmd = Val_long(1);
1753 else
1754 failwith("Invalid IOCTL Cmd!");
1756 camlConnection = caml_alloc(1, Abstract_tag);
1757 Field(camlConnection, 0) = (value)conn;
1759 camlResult = callback2_exn(Field(conn->ocamlValues, OcamlIOCTLCallback),
1760 camlConnection,
1761 camlCmd);
1763 if (Is_exception_result(camlResult))
1765 result = CURLIOE_FAILRESTART;
1767 else
1768 switch (Long_val(camlResult))
1770 case 0: /* CURLIOE_OK */
1771 result = CURLIOE_OK;
1772 break;
1774 case 1: /* CURLIOE_UNKNOWNCMD */
1775 result = CURLIOE_UNKNOWNCMD;
1776 break;
1778 case 2: /* CURLIOE_FAILRESTART */
1779 result = CURLIOE_FAILRESTART;
1780 break;
1782 default: /* Incorrect return value, but let's handle it */
1783 result = CURLIOE_FAILRESTART;
1784 break;
1787 CAMLreturnT(curlioerr, result);
1790 static curlioerr ioctlFunction(CURL *ioctl,
1791 int cmd,
1792 void *data)
1794 curlioerr r;
1795 leave_blocking_section();
1796 r = ioctlFunction_nolock(ioctl, cmd, data);
1797 enter_blocking_section();
1798 return r;
1801 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1802 static int seekFunction_nolock(void *data,
1803 curl_off_t offset,
1804 int origin)
1806 CAMLparam0();
1807 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1808 Connection *conn = (Connection *)data;
1810 camlOffset = copy_int64(offset);
1812 if (origin == SEEK_SET)
1813 camlOrigin = Val_long(0);
1814 else if (origin == SEEK_CUR)
1815 camlOrigin = Val_long(1);
1816 else if (origin == SEEK_END)
1817 camlOrigin = Val_long(2);
1818 else
1819 failwith("Invalid seek code");
1821 camlResult = callback2_exn(Field(conn->ocamlValues,
1822 OcamlSeekFunctionCallback),
1823 camlOffset,
1824 camlOrigin);
1826 int result;
1827 if (Is_exception_result(camlResult))
1828 result = CURL_SEEKFUNC_FAIL;
1829 else
1830 switch (Int_val(camlResult))
1832 case 0: result = CURL_SEEKFUNC_OK; break;
1833 case 1: result = CURL_SEEKFUNC_FAIL; break;
1834 case 2: result = CURL_SEEKFUNC_CANTSEEK; break;
1835 default: failwith("Invalid seek result");
1838 CAMLreturnT(int, result);
1841 static int seekFunction(void *data,
1842 curl_off_t offset,
1843 int origin)
1845 int r;
1846 leave_blocking_section();
1847 r = seekFunction_nolock(data,offset,origin);
1848 enter_blocking_section();
1849 return r;
1852 #endif
1854 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1855 static int openSocketFunction_nolock(void *data,
1856 curlsocktype purpose,
1857 struct curl_sockaddr *addr)
1859 CAMLparam0();
1860 CAMLlocal1(result);
1861 Connection *conn = (Connection *)data;
1862 int sock = -1;
1863 (void)purpose; /* not used */
1865 sock = socket(addr->family, addr->socktype, addr->protocol);
1867 if (-1 != sock)
1869 /* FIXME windows */
1870 result = callback_exn(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1871 if (Is_exception_result(result))
1873 close(sock);
1874 sock = -1;
1878 CAMLreturnT(int, (sock == -1) ? CURL_SOCKET_BAD : sock);
1881 static int openSocketFunction(void *data,
1882 curlsocktype purpose,
1883 struct curl_sockaddr *address)
1885 int r;
1886 leave_blocking_section();
1887 r = openSocketFunction_nolock(data,purpose,address);
1888 enter_blocking_section();
1889 return r;
1892 #endif
1895 ** curl_global_init helper function
1898 CAMLprim value helper_curl_global_init(value initOption)
1900 CAMLparam1(initOption);
1902 switch (Long_val(initOption))
1904 case 0: /* CURLINIT_GLOBALALL */
1905 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1906 break;
1908 case 1: /* CURLINIT_GLOBALSSL */
1909 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1910 break;
1912 case 2: /* CURLINIT_GLOBALWIN32 */
1913 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1914 break;
1916 case 3: /* CURLINIT_GLOBALNOTHING */
1917 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1918 break;
1920 default:
1921 failwith("Invalid Initialization Option");
1922 break;
1925 /* Keep compiler happy, we should never get here due to failwith() */
1926 CAMLreturn(Val_unit);
1930 ** curl_global_cleanup helper function
1933 CAMLprim value helper_curl_global_cleanup(void)
1935 CAMLparam0();
1937 curl_global_cleanup();
1939 CAMLreturn(Val_unit);
1943 ** curl_easy_init helper function
1946 CAMLprim value helper_curl_easy_init(void)
1948 CAMLparam0();
1949 CAMLlocal1(result);
1951 Connection *conn = newConnection();
1953 result = caml_alloc(1, Abstract_tag);
1954 Field(result, 0) = (value)conn;
1956 CAMLreturn(result);
1959 CAMLprim value helper_curl_easy_reset(value conn)
1961 CAMLparam1(conn);
1962 Connection *connection = Connection_val(conn);
1964 checkConnection(connection);
1965 curl_easy_reset(connection->connection);
1966 resetOcamlValues(connection);
1968 CAMLreturn(Val_unit);
1972 ** curl_easy_setopt helper utility functions
1975 static void handleWriteFunction(Connection *conn, value option)
1977 CAMLparam1(option);
1978 CURLcode result = CURLE_OK;
1980 if (Tag_val(option) == Closure_tag)
1981 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1982 else
1983 failwith("Not a proper closure");
1985 result = curl_easy_setopt(conn->connection,
1986 CURLOPT_WRITEFUNCTION,
1987 writeFunction);
1989 if (result != CURLE_OK)
1990 raiseError(conn, result);
1992 result = curl_easy_setopt(conn->connection,
1993 CURLOPT_WRITEDATA,
1994 conn);
1996 if (result != CURLE_OK)
1997 raiseError(conn, result);
1999 CAMLreturn0;
2002 static void handleReadFunction(Connection *conn, value option)
2004 CAMLparam1(option);
2005 CURLcode result = CURLE_OK;
2007 if (Tag_val(option) == Closure_tag)
2008 Store_field(conn->ocamlValues, OcamlReadCallback, option);
2009 else
2010 failwith("Not a proper closure");
2012 result = curl_easy_setopt(conn->connection,
2013 CURLOPT_READFUNCTION,
2014 readFunction);
2016 if (result != CURLE_OK)
2017 raiseError(conn, result);
2019 result = curl_easy_setopt(conn->connection,
2020 CURLOPT_READDATA,
2021 conn);
2023 if (result != CURLE_OK)
2024 raiseError(conn, result);
2026 CAMLreturn0;
2029 static void handleURL(Connection *conn, value option)
2031 CAMLparam1(option);
2032 CURLcode result = CURLE_OK;
2034 Store_field(conn->ocamlValues, OcamlURL, option);
2036 if (conn->url != NULL)
2037 free(conn->url);
2039 conn->url = strdup(String_val(option));
2041 result = curl_easy_setopt(conn->connection,
2042 CURLOPT_URL,
2043 conn->url);
2045 if (result != CURLE_OK)
2046 raiseError(conn, result);
2048 CAMLreturn0;
2051 static void handleInFileSize(Connection *conn, value option)
2053 CAMLparam1(option);
2054 CURLcode result = CURLE_OK;
2056 result = curl_easy_setopt(conn->connection,
2057 CURLOPT_INFILESIZE,
2058 Long_val(option));
2060 if (result != CURLE_OK)
2061 raiseError(conn, result);
2063 CAMLreturn0;
2066 static void handleProxy(Connection *conn, value option)
2068 CAMLparam1(option);
2069 CURLcode result = CURLE_OK;
2071 Store_field(conn->ocamlValues, OcamlProxy, option);
2073 if (conn->proxy != NULL)
2074 free(conn->proxy);
2076 conn->proxy = strdup(String_val(option));
2078 result = curl_easy_setopt(conn->connection,
2079 CURLOPT_PROXY,
2080 conn->proxy);
2082 if (result != CURLE_OK)
2083 raiseError(conn, result);
2085 CAMLreturn0;
2088 static void handleProxyPort(Connection *conn, value option)
2090 CAMLparam1(option);
2091 CURLcode result = CURLE_OK;
2093 result = curl_easy_setopt(conn->connection,
2094 CURLOPT_PROXYPORT,
2095 Long_val(option));
2097 if (result != CURLE_OK)
2098 raiseError(conn, result);
2100 CAMLreturn0;
2103 static void handleHTTPProxyTunnel(Connection *conn, value option)
2105 CAMLparam1(option);
2106 CURLcode result = CURLE_OK;
2108 result = curl_easy_setopt(conn->connection,
2109 CURLOPT_HTTPPROXYTUNNEL,
2110 Bool_val(option));
2112 if (result != CURLE_OK)
2113 raiseError(conn, result);
2115 CAMLreturn0;
2118 static void handleVerbose(Connection *conn, value option)
2120 CAMLparam1(option);
2121 CURLcode result = CURLE_OK;
2123 result = curl_easy_setopt(conn->connection,
2124 CURLOPT_VERBOSE,
2125 Bool_val(option));
2127 if (result != CURLE_OK)
2128 raiseError(conn, result);
2130 CAMLreturn0;
2133 static void handleHeader(Connection *conn, value option)
2135 CAMLparam1(option);
2136 CURLcode result = CURLE_OK;
2138 result = curl_easy_setopt(conn->connection,
2139 CURLOPT_HEADER,
2140 Bool_val(option));
2142 if (result != CURLE_OK)
2143 raiseError(conn, result);
2145 CAMLreturn0;
2148 static void handleNoProgress(Connection *conn, value option)
2150 CAMLparam1(option);
2151 CURLcode result = CURLE_OK;
2153 result = curl_easy_setopt(conn->connection,
2154 CURLOPT_NOPROGRESS,
2155 Bool_val(option));
2157 if (result != CURLE_OK)
2158 raiseError(conn, result);
2160 CAMLreturn0;
2163 static void handleNoSignal(Connection *conn, value option)
2165 #if HAVE_DECL_CURLOPT_NOSIGNAL
2166 CAMLparam1(option);
2167 CURLcode result = CURLE_OK;
2169 result = curl_easy_setopt(conn->connection,
2170 CURLOPT_NOSIGNAL,
2171 Bool_val(option));
2173 if (result != CURLE_OK)
2174 raiseError(conn, result);
2176 CAMLreturn0;
2177 #else
2178 #pragma message("libcurl does not implement CURLOPT_NOSIGNAL")
2179 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2180 #endif
2183 static void handleNoBody(Connection *conn, value option)
2185 CAMLparam1(option);
2186 CURLcode result = CURLE_OK;
2188 result = curl_easy_setopt(conn->connection,
2189 CURLOPT_NOBODY,
2190 Bool_val(option));
2192 if (result != CURLE_OK)
2193 raiseError(conn, result);
2195 CAMLreturn0;
2198 static void handleFailOnError(Connection *conn, value option)
2200 CAMLparam1(option);
2201 CURLcode result = CURLE_OK;
2203 result = curl_easy_setopt(conn->connection,
2204 CURLOPT_FAILONERROR,
2205 Bool_val(option));
2207 if (result != CURLE_OK)
2208 raiseError(conn, result);
2210 CAMLreturn0;
2213 static void handleUpload(Connection *conn, value option)
2215 CAMLparam1(option);
2216 CURLcode result = CURLE_OK;
2218 result = curl_easy_setopt(conn->connection,
2219 CURLOPT_UPLOAD,
2220 Bool_val(option));
2222 if (result != CURLE_OK)
2223 raiseError(conn, result);
2225 CAMLreturn0;
2228 static void handlePost(Connection *conn, value option)
2230 CAMLparam1(option);
2231 CURLcode result = CURLE_OK;
2233 result = curl_easy_setopt(conn->connection,
2234 CURLOPT_POST,
2235 Bool_val(option));
2237 if (result != CURLE_OK)
2238 raiseError(conn, result);
2240 CAMLreturn0;
2243 static void handleFTPListOnly(Connection *conn, value option)
2245 CAMLparam1(option);
2246 CURLcode result = CURLE_OK;
2248 result = curl_easy_setopt(conn->connection,
2249 CURLOPT_FTPLISTONLY,
2250 Bool_val(option));
2252 if (result != CURLE_OK)
2253 raiseError(conn, result);
2255 CAMLreturn0;
2258 static void handleFTPAppend(Connection *conn, value option)
2260 CAMLparam1(option);
2261 CURLcode result = CURLE_OK;
2263 result = curl_easy_setopt(conn->connection,
2264 CURLOPT_FTPAPPEND,
2265 Bool_val(option));
2267 if (result != CURLE_OK)
2268 raiseError(conn, result);
2270 CAMLreturn0;
2273 static void handleNETRC(Connection *conn, value option)
2275 CAMLparam1(option);
2276 CURLcode result = CURLE_OK;
2277 long netrc;
2279 switch (Long_val(option))
2281 case 0: /* CURL_NETRC_OPTIONAL */
2282 netrc = CURL_NETRC_OPTIONAL;
2283 break;
2285 case 1:/* CURL_NETRC_IGNORED */
2286 netrc = CURL_NETRC_IGNORED;
2287 break;
2289 case 2: /* CURL_NETRC_REQUIRED */
2290 netrc = CURL_NETRC_REQUIRED;
2291 break;
2293 default:
2294 failwith("Invalid NETRC Option");
2295 break;
2298 result = curl_easy_setopt(conn->connection,
2299 CURLOPT_NETRC,
2300 netrc);
2302 if (result != CURLE_OK)
2303 raiseError(conn, result);
2305 CAMLreturn0;
2308 static void handleEncoding(Connection *conn, value option)
2310 #if HAVE_DECL_CURLOPT_ENCODING
2311 CAMLparam1(option);
2312 CURLcode result = CURLE_OK;
2314 switch (Long_val(option))
2316 case 0: /* CURL_ENCODING_NONE */
2317 result = curl_easy_setopt(conn->connection,
2318 CURLOPT_ENCODING,
2319 "identity");
2320 break;
2322 case 1: /* CURL_ENCODING_DEFLATE */
2323 result = curl_easy_setopt(conn->connection,
2324 CURLOPT_ENCODING,
2325 "deflate");
2326 break;
2328 case 2: /* CURL_ENCODING_GZIP */
2329 result = curl_easy_setopt(conn->connection,
2330 CURLOPT_ENCODING,
2331 "gzip");
2332 break;
2334 case 3: /* CURL_ENCODING_ANY */
2335 result = curl_easy_setopt(conn->connection,
2336 CURLOPT_ENCODING,
2337 "");
2338 break;
2340 default:
2341 failwith("Invalid Encoding Option");
2342 break;
2345 if (result != CURLE_OK)
2346 raiseError(conn, result);
2348 CAMLreturn0;
2349 #else
2350 #pragma message("libcurl does not implement CURLOPT_ENCODING")
2351 failwith("libcurl does not implement CURLOPT_ENCODING");
2352 #endif
2355 static void handleFollowLocation(Connection *conn, value option)
2357 CAMLparam1(option);
2358 CURLcode result = CURLE_OK;
2360 result = curl_easy_setopt(conn->connection,
2361 CURLOPT_FOLLOWLOCATION,
2362 Bool_val(option));
2364 if (result != CURLE_OK)
2365 raiseError(conn, result);
2367 CAMLreturn0;
2370 static void handleTransferText(Connection *conn, value option)
2372 CAMLparam1(option);
2373 CURLcode result = CURLE_OK;
2375 result = curl_easy_setopt(conn->connection,
2376 CURLOPT_TRANSFERTEXT,
2377 Bool_val(option));
2379 if (result != CURLE_OK)
2380 raiseError(conn, result);
2382 CAMLreturn0;
2385 static void handlePut(Connection *conn, value option)
2387 CAMLparam1(option);
2388 CURLcode result = CURLE_OK;
2390 result = curl_easy_setopt(conn->connection,
2391 CURLOPT_PUT,
2392 Bool_val(option));
2394 if (result != CURLE_OK)
2395 raiseError(conn, result);
2397 CAMLreturn0;
2400 static void handleUserPwd(Connection *conn, value option)
2402 CAMLparam1(option);
2403 CURLcode result = CURLE_OK;
2405 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2407 if (conn->userPwd != NULL)
2408 free(conn->userPwd);
2410 conn->userPwd = strdup(String_val(option));
2412 result = curl_easy_setopt(conn->connection,
2413 CURLOPT_USERPWD,
2414 conn->userPwd);
2416 if (result != CURLE_OK)
2417 raiseError(conn, result);
2419 CAMLreturn0;
2422 static void handleProxyUserPwd(Connection *conn, value option)
2424 CAMLparam1(option);
2425 CURLcode result = CURLE_OK;
2427 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2429 if (conn->proxyUserPwd != NULL)
2430 free(conn->proxyUserPwd);
2432 conn->proxyUserPwd = strdup(String_val(option));
2434 result = curl_easy_setopt(conn->connection,
2435 CURLOPT_PROXYUSERPWD,
2436 conn->proxyUserPwd);
2438 if (result != CURLE_OK)
2439 raiseError(conn, result);
2441 CAMLreturn0;
2444 static void handleRange(Connection *conn, value option)
2446 CAMLparam1(option);
2447 CURLcode result = CURLE_OK;
2449 Store_field(conn->ocamlValues, OcamlRange, option);
2451 if (conn->range != NULL)
2452 free(conn->range);
2454 conn->range = strdup(String_val(option));
2456 result = curl_easy_setopt(conn->connection,
2457 CURLOPT_RANGE,
2458 conn->range);
2460 if (result != CURLE_OK)
2461 raiseError(conn, result);
2463 CAMLreturn0;
2466 static void handleErrorBuffer(Connection *conn, value option)
2468 CAMLparam1(option);
2469 CURLcode result = CURLE_OK;
2471 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2473 if (conn->errorBuffer != NULL)
2474 free(conn->errorBuffer);
2476 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2478 result = curl_easy_setopt(conn->connection,
2479 CURLOPT_ERRORBUFFER,
2480 conn->errorBuffer);
2482 if (result != CURLE_OK)
2483 raiseError(conn, result);
2485 CAMLreturn0;
2488 static void handleTimeout(Connection *conn, value option)
2490 CAMLparam1(option);
2491 CURLcode result = CURLE_OK;
2493 result = curl_easy_setopt(conn->connection,
2494 CURLOPT_TIMEOUT,
2495 Long_val(option));
2497 if (result != CURLE_OK)
2498 raiseError(conn, result);
2500 CAMLreturn0;
2503 static void handlePostFields(Connection *conn, value option)
2505 CAMLparam1(option);
2506 CURLcode result = CURLE_OK;
2508 Store_field(conn->ocamlValues, OcamlPostFields, option);
2510 if (conn->postFields != NULL)
2511 free(conn->postFields);
2513 conn->postFields = malloc(string_length(option)+1);
2514 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2516 result = curl_easy_setopt(conn->connection,
2517 CURLOPT_POSTFIELDS,
2518 conn->postFields);
2520 if (result != CURLE_OK)
2521 raiseError(conn, result);
2523 CAMLreturn0;
2526 static void handlePostFieldSize(Connection *conn, value option)
2528 CAMLparam1(option);
2529 CURLcode result = CURLE_OK;
2531 result = curl_easy_setopt(conn->connection,
2532 CURLOPT_POSTFIELDSIZE,
2533 Long_val(option));
2535 if (result != CURLE_OK)
2536 raiseError(conn, result);
2538 CAMLreturn0;
2541 static void handleReferer(Connection *conn, value option)
2543 CAMLparam1(option);
2544 CURLcode result = CURLE_OK;
2546 Store_field(conn->ocamlValues, OcamlReferer, option);
2548 if (conn->referer != NULL)
2549 free(conn->referer);
2551 conn->referer = strdup(String_val(option));
2553 result = curl_easy_setopt(conn->connection,
2554 CURLOPT_REFERER,
2555 conn->referer);
2557 if (result != CURLE_OK)
2558 raiseError(conn, result);
2560 CAMLreturn0;
2563 static void handleUserAgent(Connection *conn, value option)
2565 CAMLparam1(option);
2566 CURLcode result = CURLE_OK;
2568 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2570 if (conn->userAgent != NULL)
2571 free(conn->userAgent);
2573 conn->userAgent = strdup(String_val(option));
2575 result = curl_easy_setopt(conn->connection,
2576 CURLOPT_USERAGENT,
2577 conn->userAgent);
2579 if (result != CURLE_OK)
2580 raiseError(conn, result);
2582 CAMLreturn0;
2585 static void handleFTPPort(Connection *conn, value option)
2587 CAMLparam1(option);
2588 CURLcode result = CURLE_OK;
2590 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2592 if (conn->ftpPort != NULL)
2593 free(conn->ftpPort);
2595 conn->ftpPort = strdup(String_val(option));
2597 result = curl_easy_setopt(conn->connection,
2598 CURLOPT_FTPPORT,
2599 conn->ftpPort);
2601 if (result != CURLE_OK)
2602 raiseError(conn, result);
2604 CAMLreturn0;
2607 static void handleLowSpeedLimit(Connection *conn, value option)
2609 CAMLparam1(option);
2610 CURLcode result = CURLE_OK;
2612 result = curl_easy_setopt(conn->connection,
2613 CURLOPT_LOW_SPEED_LIMIT,
2614 Long_val(option));
2616 if (result != CURLE_OK)
2617 raiseError(conn, result);
2619 CAMLreturn0;
2622 static void handleLowSpeedTime(Connection *conn, value option)
2624 CAMLparam1(option);
2625 CURLcode result = CURLE_OK;
2627 result = curl_easy_setopt(conn->connection,
2628 CURLOPT_LOW_SPEED_TIME,
2629 Long_val(option));
2631 if (result != CURLE_OK)
2632 raiseError(conn, result);
2634 CAMLreturn0;
2637 static void handleResumeFrom(Connection *conn, value option)
2639 CAMLparam1(option);
2640 CURLcode result = CURLE_OK;
2642 result = curl_easy_setopt(conn->connection,
2643 CURLOPT_RESUME_FROM,
2644 Long_val(option));
2646 if (result != CURLE_OK)
2647 raiseError(conn, result);
2649 CAMLreturn0;
2652 static void handleCookie(Connection *conn, value option)
2654 CAMLparam1(option);
2655 CURLcode result = CURLE_OK;
2657 Store_field(conn->ocamlValues, OcamlCookie, option);
2659 if (conn->cookie != NULL)
2660 free(conn->cookie);
2662 conn->cookie = strdup(String_val(option));
2664 result = curl_easy_setopt(conn->connection,
2665 CURLOPT_COOKIE,
2666 conn->cookie);
2668 if (result != CURLE_OK)
2669 raiseError(conn, result);
2671 CAMLreturn0;
2674 static void handleHTTPHeader(Connection *conn, value option)
2676 CAMLparam1(option);
2677 CAMLlocal1(listIter);
2678 CURLcode result = CURLE_OK;
2680 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2682 free_curl_slist(conn->httpHeader);
2683 conn->httpHeader = NULL;
2685 listIter = option;
2687 while (!Is_long(listIter))
2689 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2691 listIter = Field(listIter, 1);
2694 result = curl_easy_setopt(conn->connection,
2695 CURLOPT_HTTPHEADER,
2696 conn->httpHeader);
2698 if (result != CURLE_OK)
2699 raiseError(conn, result);
2701 CAMLreturn0;
2704 static void handleHTTPPost(Connection *conn, value option)
2706 CAMLparam1(option);
2707 CAMLlocal3(listIter, formItem, contentType);
2708 CURLcode result = CURLE_OK;
2709 char *str1, *str2, *str3, *str4;
2711 listIter = option;
2713 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2715 if (conn->httpPostFirst != NULL)
2716 curl_formfree(conn->httpPostFirst);
2718 conn->httpPostFirst = NULL;
2719 conn->httpPostLast = NULL;
2721 free_curl_slist(conn->httpPostStrings);
2722 conn->httpPostStrings = NULL;
2724 while (!Is_long(listIter))
2726 formItem = Field(listIter, 0);
2728 switch (Tag_val(formItem))
2730 case 0: /* CURLFORM_CONTENT */
2731 if (Wosize_val(formItem) < 3)
2733 failwith("Incorrect CURLFORM_CONTENT parameters");
2736 if (Is_long(Field(formItem, 2)) &&
2737 Long_val(Field(formItem, 2)) == 0)
2739 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2740 memcpy(str1,
2741 String_val(Field(formItem, 0)),
2742 string_length(Field(formItem, 0)));
2743 str1[string_length(Field(formItem, 0))] = 0;
2744 conn->httpPostStrings =
2745 curl_slist_append(conn->httpPostStrings, str1);
2747 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2748 memcpy(str2,
2749 String_val(Field(formItem, 1)),
2750 string_length(Field(formItem, 1)));
2751 str2[string_length(Field(formItem, 1))] = 0;
2752 conn->httpPostStrings =
2753 curl_slist_append(conn->httpPostStrings, str2);
2755 curl_formadd(&conn->httpPostFirst,
2756 &conn->httpPostLast,
2757 CURLFORM_PTRNAME,
2758 str1,
2759 CURLFORM_NAMELENGTH,
2760 string_length(Field(formItem, 0)),
2761 CURLFORM_PTRCONTENTS,
2762 str2,
2763 CURLFORM_CONTENTSLENGTH,
2764 string_length(Field(formItem, 1)),
2765 CURLFORM_END);
2767 else if (Is_block(Field(formItem, 2)))
2769 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2770 memcpy(str1,
2771 String_val(Field(formItem, 0)),
2772 string_length(Field(formItem, 0)));
2773 str1[string_length(Field(formItem, 0))] = 0;
2774 conn->httpPostStrings =
2775 curl_slist_append(conn->httpPostStrings, str1);
2777 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2778 memcpy(str2,
2779 String_val(Field(formItem, 1)),
2780 string_length(Field(formItem, 1)));
2781 str2[string_length(Field(formItem, 1))] = 0;
2782 conn->httpPostStrings =
2783 curl_slist_append(conn->httpPostStrings, str2);
2785 contentType = Field(formItem, 2);
2787 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2788 memcpy(str3,
2789 String_val(Field(contentType, 0)),
2790 string_length(Field(contentType, 0)));
2791 str3[string_length(Field(contentType, 0))] = 0;
2792 conn->httpPostStrings =
2793 curl_slist_append(conn->httpPostStrings, str3);
2795 curl_formadd(&conn->httpPostFirst,
2796 &conn->httpPostLast,
2797 CURLFORM_PTRNAME,
2798 str1,
2799 CURLFORM_NAMELENGTH,
2800 string_length(Field(formItem, 0)),
2801 CURLFORM_PTRCONTENTS,
2802 str2,
2803 CURLFORM_CONTENTSLENGTH,
2804 string_length(Field(formItem, 1)),
2805 CURLFORM_CONTENTTYPE,
2806 str3,
2807 CURLFORM_END);
2809 else
2811 failwith("Incorrect CURLFORM_CONTENT parameters");
2813 break;
2815 case 1: /* CURLFORM_FILECONTENT */
2816 if (Wosize_val(formItem) < 3)
2818 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2821 if (Is_long(Field(formItem, 2)) &&
2822 Long_val(Field(formItem, 2)) == 0)
2824 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2825 memcpy(str1,
2826 String_val(Field(formItem, 0)),
2827 string_length(Field(formItem, 0)));
2828 str1[string_length(Field(formItem, 0))] = 0;
2829 conn->httpPostStrings =
2830 curl_slist_append(conn->httpPostStrings, str1);
2832 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2833 memcpy(str2,
2834 String_val(Field(formItem, 1)),
2835 string_length(Field(formItem, 1)));
2836 str2[string_length(Field(formItem, 1))] = 0;
2837 conn->httpPostStrings =
2838 curl_slist_append(conn->httpPostStrings, str2);
2840 curl_formadd(&conn->httpPostFirst,
2841 &conn->httpPostLast,
2842 CURLFORM_PTRNAME,
2843 str1,
2844 CURLFORM_NAMELENGTH,
2845 string_length(Field(formItem, 0)),
2846 CURLFORM_FILECONTENT,
2847 str2,
2848 CURLFORM_END);
2850 else if (Is_block(Field(formItem, 2)))
2852 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2853 memcpy(str1,
2854 String_val(Field(formItem, 0)),
2855 string_length(Field(formItem, 0)));
2856 str1[string_length(Field(formItem, 0))] = 0;
2857 conn->httpPostStrings =
2858 curl_slist_append(conn->httpPostStrings, str1);
2860 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2861 memcpy(str2,
2862 String_val(Field(formItem, 1)),
2863 string_length(Field(formItem, 1)));
2864 str2[string_length(Field(formItem, 1))] = 0;
2865 conn->httpPostStrings =
2866 curl_slist_append(conn->httpPostStrings, str2);
2868 contentType = Field(formItem, 2);
2870 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2871 memcpy(str3,
2872 String_val(Field(contentType, 0)),
2873 string_length(Field(contentType, 0)));
2874 str3[string_length(Field(contentType, 0))] = 0;
2875 conn->httpPostStrings =
2876 curl_slist_append(conn->httpPostStrings, str3);
2878 curl_formadd(&conn->httpPostFirst,
2879 &conn->httpPostLast,
2880 CURLFORM_PTRNAME,
2881 str1,
2882 CURLFORM_NAMELENGTH,
2883 string_length(Field(formItem, 0)),
2884 CURLFORM_FILECONTENT,
2885 str2,
2886 CURLFORM_CONTENTTYPE,
2887 str3,
2888 CURLFORM_END);
2890 else
2892 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2894 break;
2896 case 2: /* CURLFORM_FILE */
2897 if (Wosize_val(formItem) < 3)
2899 failwith("Incorrect CURLFORM_FILE parameters");
2902 if (Is_long(Field(formItem, 2)) &&
2903 Long_val(Field(formItem, 2)) == 0)
2905 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2906 memcpy(str1,
2907 String_val(Field(formItem, 0)),
2908 string_length(Field(formItem, 0)));
2909 str1[string_length(Field(formItem, 0))] = 0;
2910 conn->httpPostStrings =
2911 curl_slist_append(conn->httpPostStrings, str1);
2913 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2914 memcpy(str2,
2915 String_val(Field(formItem, 1)),
2916 string_length(Field(formItem, 1)));
2917 str2[string_length(Field(formItem, 1))] = 0;
2918 conn->httpPostStrings =
2919 curl_slist_append(conn->httpPostStrings, str2);
2921 curl_formadd(&conn->httpPostFirst,
2922 &conn->httpPostLast,
2923 CURLFORM_PTRNAME,
2924 str1,
2925 CURLFORM_NAMELENGTH,
2926 string_length(Field(formItem, 0)),
2927 CURLFORM_FILE,
2928 str2,
2929 CURLFORM_END);
2931 else if (Is_block(Field(formItem, 2)))
2933 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2934 memcpy(str1,
2935 String_val(Field(formItem, 0)),
2936 string_length(Field(formItem, 0)));
2937 str1[string_length(Field(formItem, 0))] = 0;
2938 conn->httpPostStrings =
2939 curl_slist_append(conn->httpPostStrings, str1);
2941 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2942 memcpy(str2,
2943 String_val(Field(formItem, 1)),
2944 string_length(Field(formItem, 1)));
2945 str2[string_length(Field(formItem, 1))] = 0;
2946 conn->httpPostStrings =
2947 curl_slist_append(conn->httpPostStrings, str2);
2949 contentType = Field(formItem, 2);
2951 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2952 memcpy(str3,
2953 String_val(Field(contentType, 0)),
2954 string_length(Field(contentType, 0)));
2955 str3[string_length(Field(contentType, 0))] = 0;
2956 conn->httpPostStrings =
2957 curl_slist_append(conn->httpPostStrings, str3);
2959 curl_formadd(&conn->httpPostFirst,
2960 &conn->httpPostLast,
2961 CURLFORM_PTRNAME,
2962 str1,
2963 CURLFORM_NAMELENGTH,
2964 string_length(Field(formItem, 0)),
2965 CURLFORM_FILE,
2966 str2,
2967 CURLFORM_CONTENTTYPE,
2968 str3,
2969 CURLFORM_END);
2971 else
2973 failwith("Incorrect CURLFORM_FILE parameters");
2975 break;
2977 case 3: /* CURLFORM_BUFFER */
2978 if (Wosize_val(formItem) < 4)
2980 failwith("Incorrect CURLFORM_BUFFER parameters");
2983 if (Is_long(Field(formItem, 3)) &&
2984 Long_val(Field(formItem, 3)) == 0)
2986 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2987 memcpy(str1,
2988 String_val(Field(formItem, 0)),
2989 string_length(Field(formItem, 0)));
2990 str1[string_length(Field(formItem, 0))] = 0;
2991 conn->httpPostStrings =
2992 curl_slist_append(conn->httpPostStrings, str1);
2994 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2995 memcpy(str2,
2996 String_val(Field(formItem, 1)),
2997 string_length(Field(formItem, 1)));
2998 str2[string_length(Field(formItem, 1))] = 0;
2999 conn->httpPostStrings =
3000 curl_slist_append(conn->httpPostStrings, str2);
3002 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3003 memcpy(str3,
3004 String_val(Field(formItem, 2)),
3005 string_length(Field(formItem, 2)));
3006 str3[string_length(Field(formItem, 2))] = 0;
3007 conn->httpPostStrings =
3008 curl_slist_append(conn->httpPostStrings, str3);
3010 curl_formadd(&conn->httpPostFirst,
3011 &conn->httpPostLast,
3012 CURLFORM_PTRNAME,
3013 str1,
3014 CURLFORM_NAMELENGTH,
3015 string_length(Field(formItem, 0)),
3016 CURLFORM_BUFFER,
3017 str2,
3018 CURLFORM_BUFFERPTR,
3019 str3,
3020 CURLFORM_BUFFERLENGTH,
3021 string_length(Field(formItem, 2)),
3022 CURLFORM_END);
3024 else if (Is_block(Field(formItem, 3)))
3026 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3027 memcpy(str1,
3028 String_val(Field(formItem, 0)),
3029 string_length(Field(formItem, 0)));
3030 str1[string_length(Field(formItem, 0))] = 0;
3031 conn->httpPostStrings =
3032 curl_slist_append(conn->httpPostStrings, str1);
3034 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3035 memcpy(str2,
3036 String_val(Field(formItem, 1)),
3037 string_length(Field(formItem, 1)));
3038 str2[string_length(Field(formItem, 1))] = 0;
3039 conn->httpPostStrings =
3040 curl_slist_append(conn->httpPostStrings, str2);
3042 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3043 memcpy(str3,
3044 String_val(Field(formItem, 2)),
3045 string_length(Field(formItem, 2)));
3046 str3[string_length(Field(formItem, 2))] = 0;
3047 conn->httpPostStrings =
3048 curl_slist_append(conn->httpPostStrings, str3);
3050 contentType = Field(formItem, 3);
3052 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
3053 memcpy(str4,
3054 String_val(Field(contentType, 0)),
3055 string_length(Field(contentType, 0)));
3056 str4[string_length(Field(contentType, 0))] = 0;
3057 conn->httpPostStrings =
3058 curl_slist_append(conn->httpPostStrings, str4);
3060 curl_formadd(&conn->httpPostFirst,
3061 &conn->httpPostLast,
3062 CURLFORM_PTRNAME,
3063 str1,
3064 CURLFORM_NAMELENGTH,
3065 string_length(Field(formItem, 0)),
3066 CURLFORM_BUFFER,
3067 str2,
3068 CURLFORM_BUFFERPTR,
3069 str3,
3070 CURLFORM_BUFFERLENGTH,
3071 string_length(Field(formItem, 2)),
3072 CURLFORM_CONTENTTYPE,
3073 str4,
3074 CURLFORM_END);
3076 else
3078 failwith("Incorrect CURLFORM_BUFFER parameters");
3080 break;
3083 listIter = Field(listIter, 1);
3086 result = curl_easy_setopt(conn->connection,
3087 CURLOPT_HTTPPOST,
3088 conn->httpPostFirst);
3090 if (result != CURLE_OK)
3091 raiseError(conn, result);
3093 CAMLreturn0;
3096 static void handleSSLCert(Connection *conn, value option)
3098 CAMLparam1(option);
3099 CURLcode result = CURLE_OK;
3101 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3103 if (conn->sslCert != NULL)
3104 free(conn->sslCert);
3106 conn->sslCert = strdup(String_val(option));
3108 result = curl_easy_setopt(conn->connection,
3109 CURLOPT_SSLCERT,
3110 conn->sslCert);
3112 if (result != CURLE_OK)
3113 raiseError(conn, result);
3115 CAMLreturn0;
3118 static void handleSSLCertType(Connection *conn, value option)
3120 CAMLparam1(option);
3121 CURLcode result = CURLE_OK;
3123 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3125 if (conn->sslCertType != NULL)
3126 free(conn->sslCertType);
3128 conn->sslCertType = strdup(String_val(option));
3130 result = curl_easy_setopt(conn->connection,
3131 CURLOPT_SSLCERTTYPE,
3132 conn->sslCertType);
3134 if (result != CURLE_OK)
3135 raiseError(conn, result);
3137 CAMLreturn0;
3140 static void handleSSLCertPasswd(Connection *conn, value option)
3142 CAMLparam1(option);
3143 CURLcode result = CURLE_OK;
3145 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3147 if (conn->sslCertPasswd != NULL)
3148 free(conn->sslCertPasswd);
3150 conn->sslCertPasswd = strdup(String_val(option));
3152 result = curl_easy_setopt(conn->connection,
3153 CURLOPT_SSLCERTPASSWD,
3154 conn->sslCertPasswd);
3156 if (result != CURLE_OK)
3157 raiseError(conn, result);
3159 CAMLreturn0;
3162 static void handleSSLKey(Connection *conn, value option)
3164 CAMLparam1(option);
3165 CURLcode result = CURLE_OK;
3167 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3169 if (conn->sslKey != NULL)
3170 free(conn->sslKey);
3172 conn->sslKey = strdup(String_val(option));
3174 result = curl_easy_setopt(conn->connection,
3175 CURLOPT_SSLKEY,
3176 conn->sslKey);
3178 if (result != CURLE_OK)
3179 raiseError(conn, result);
3181 CAMLreturn0;
3184 static void handleSSLKeyType(Connection *conn, value option)
3186 CAMLparam1(option);
3187 CURLcode result = CURLE_OK;
3189 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3191 if (conn->sslKeyType != NULL)
3192 free(conn->sslKeyType);
3194 conn->sslKeyType = strdup(String_val(option));
3196 result = curl_easy_setopt(conn->connection,
3197 CURLOPT_SSLKEYTYPE,
3198 conn->sslKeyType);
3200 if (result != CURLE_OK)
3201 raiseError(conn, result);
3203 CAMLreturn0;
3206 static void handleSSLKeyPasswd(Connection *conn, value option)
3208 CAMLparam1(option);
3209 CURLcode result = CURLE_OK;
3211 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3213 if (conn->sslKeyPasswd != NULL)
3214 free(conn->sslKeyPasswd);
3216 conn->sslKeyPasswd = strdup(String_val(option));
3218 result = curl_easy_setopt(conn->connection,
3219 CURLOPT_SSLKEYPASSWD,
3220 conn->sslKeyPasswd);
3222 if (result != CURLE_OK)
3223 raiseError(conn, result);
3225 CAMLreturn0;
3228 static void handleSSLEngine(Connection *conn, value option)
3230 CAMLparam1(option);
3231 CURLcode result = CURLE_OK;
3233 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3235 if (conn->sslEngine != NULL)
3236 free(conn->sslEngine);
3238 conn->sslEngine = strdup(String_val(option));
3240 result = curl_easy_setopt(conn->connection,
3241 CURLOPT_SSLENGINE,
3242 conn->sslEngine);
3244 if (result != CURLE_OK)
3245 raiseError(conn, result);
3247 CAMLreturn0;
3250 static void handleSSLEngineDefault(Connection *conn, value option)
3252 CAMLparam1(option);
3253 CURLcode result = CURLE_OK;
3255 result = curl_easy_setopt(conn->connection,
3256 CURLOPT_SSLENGINE_DEFAULT,
3257 Bool_val(option));
3259 if (result != CURLE_OK)
3260 raiseError(conn, result);
3262 CAMLreturn0;
3265 static void handleCRLF(Connection *conn, value option)
3267 CAMLparam1(option);
3268 CURLcode result = CURLE_OK;
3270 result = curl_easy_setopt(conn->connection,
3271 CURLOPT_CRLF,
3272 Bool_val(option));
3274 if (result != CURLE_OK)
3275 raiseError(conn, result);
3277 CAMLreturn0;
3280 static void handleQuote(Connection *conn, value option)
3282 CAMLparam1(option);
3283 CAMLlocal1(listIter);
3284 CURLcode result = CURLE_OK;
3286 Store_field(conn->ocamlValues, OcamlQuote, option);
3288 free_curl_slist(conn->quote);
3289 conn->quote = NULL;
3291 listIter = option;
3293 while (!Is_long(listIter))
3295 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3297 listIter = Field(listIter, 1);
3300 result = curl_easy_setopt(conn->connection,
3301 CURLOPT_QUOTE,
3302 conn->quote);
3304 if (result != CURLE_OK)
3305 raiseError(conn, result);
3307 CAMLreturn0;
3310 static void handlePostQuote(Connection *conn, value option)
3312 CAMLparam1(option);
3313 CAMLlocal1(listIter);
3314 CURLcode result = CURLE_OK;
3316 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3318 free_curl_slist(conn->postQuote);
3319 conn->postQuote = NULL;
3321 listIter = option;
3323 while (!Is_long(listIter))
3325 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3327 listIter = Field(listIter, 1);
3330 result = curl_easy_setopt(conn->connection,
3331 CURLOPT_POSTQUOTE,
3332 conn->postQuote);
3334 if (result != CURLE_OK)
3335 raiseError(conn, result);
3337 CAMLreturn0;
3340 static void handleHeaderFunction(Connection *conn, value option)
3342 CAMLparam1(option);
3343 CURLcode result = CURLE_OK;
3345 if (Tag_val(option) == Closure_tag)
3346 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3347 else
3348 failwith("Not a proper closure");
3350 result = curl_easy_setopt(conn->connection,
3351 CURLOPT_HEADERFUNCTION,
3352 headerFunction);
3354 if (result != CURLE_OK)
3355 raiseError(conn, result);
3357 result = curl_easy_setopt(conn->connection,
3358 CURLOPT_WRITEHEADER,
3359 conn);
3361 if (result != CURLE_OK)
3362 raiseError(conn, result);
3364 CAMLreturn0;
3367 static void handleCookieFile(Connection *conn, value option)
3369 CAMLparam1(option);
3370 CURLcode result = CURLE_OK;
3372 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3374 if (conn->cookieFile != NULL)
3375 free(conn->cookieFile);
3377 conn->cookieFile = strdup(String_val(option));
3379 result = curl_easy_setopt(conn->connection,
3380 CURLOPT_COOKIEFILE,
3381 conn->cookieFile);
3383 if (result != CURLE_OK)
3384 raiseError(conn, result);
3386 CAMLreturn0;
3389 static void handleSSLVersion(Connection *conn, value option)
3391 CAMLparam1(option);
3392 CURLcode result = CURLE_OK;
3394 result = curl_easy_setopt(conn->connection,
3395 CURLOPT_SSLVERSION,
3396 Long_val(option));
3398 if (result != CURLE_OK)
3399 raiseError(conn, result);
3401 CAMLreturn0;
3404 static void handleTimeCondition(Connection *conn, value option)
3406 CAMLparam1(option);
3407 CURLcode result = CURLE_OK;
3408 int timecond = CURL_TIMECOND_NONE;
3410 switch (Long_val(option))
3412 case 0: timecond = CURL_TIMECOND_NONE; break;
3413 case 1: timecond = CURL_TIMECOND_IFMODSINCE; break;
3414 case 2: timecond = CURL_TIMECOND_IFUNMODSINCE; break;
3415 case 3: timecond = CURL_TIMECOND_LASTMOD; break;
3416 default:
3417 failwith("Invalid TIMECOND Option");
3418 break;
3421 result = curl_easy_setopt(conn->connection, CURLOPT_TIMECONDITION, timecond);
3423 if (result != CURLE_OK)
3424 raiseError(conn, result);
3426 CAMLreturn0;
3429 static void handleTimeValue(Connection *conn, value option)
3431 CAMLparam1(option);
3432 CURLcode result = CURLE_OK;
3434 result = curl_easy_setopt(conn->connection,
3435 CURLOPT_TIMEVALUE,
3436 Int32_val(option));
3438 if (result != CURLE_OK)
3439 raiseError(conn, result);
3441 CAMLreturn0;
3444 static void handleCustomRequest(Connection *conn, value option)
3446 CAMLparam1(option);
3447 CURLcode result = CURLE_OK;
3449 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3451 if (conn->customRequest != NULL)
3452 free(conn->customRequest);
3454 conn->customRequest = strdup(String_val(option));
3456 result = curl_easy_setopt(conn->connection,
3457 CURLOPT_CUSTOMREQUEST,
3458 conn->customRequest);
3460 if (result != CURLE_OK)
3461 raiseError(conn, result);
3463 CAMLreturn0;
3466 static void handleInterface(Connection *conn, value option)
3468 CAMLparam1(option);
3469 CURLcode result = CURLE_OK;
3471 Store_field(conn->ocamlValues, OcamlInterface, option);
3473 if (conn->interface_ != NULL)
3474 free(conn->interface_);
3476 conn->interface_ = strdup(String_val(option));
3478 result = curl_easy_setopt(conn->connection,
3479 CURLOPT_INTERFACE,
3480 conn->interface_);
3482 if (result != CURLE_OK)
3483 raiseError(conn, result);
3485 CAMLreturn0;
3488 static void handleKRB4Level(Connection *conn, value option)
3490 CAMLparam1(option);
3491 CURLcode result = CURLE_OK;
3493 switch (Long_val(option))
3495 case 0: /* KRB4_NONE */
3496 result = curl_easy_setopt(conn->connection,
3497 CURLOPT_KRB4LEVEL,
3498 NULL);
3499 break;
3501 case 1: /* KRB4_CLEAR */
3502 result = curl_easy_setopt(conn->connection,
3503 CURLOPT_KRB4LEVEL,
3504 "clear");
3505 break;
3507 case 2: /* KRB4_SAFE */
3508 result = curl_easy_setopt(conn->connection,
3509 CURLOPT_KRB4LEVEL,
3510 "safe");
3511 break;
3513 case 3: /* KRB4_CONFIDENTIAL */
3514 result = curl_easy_setopt(conn->connection,
3515 CURLOPT_KRB4LEVEL,
3516 "confidential");
3517 break;
3519 case 4: /* KRB4_PRIVATE */
3520 result = curl_easy_setopt(conn->connection,
3521 CURLOPT_KRB4LEVEL,
3522 "private");
3523 break;
3525 default:
3526 failwith("Invalid KRB4 Option");
3527 break;
3530 if (result != CURLE_OK)
3531 raiseError(conn, result);
3533 CAMLreturn0;
3536 static void handleProgressFunction(Connection *conn, value option)
3538 CAMLparam1(option);
3539 CURLcode result = CURLE_OK;
3541 if (Tag_val(option) == Closure_tag)
3542 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3543 else
3544 failwith("Not a proper closure");
3546 result = curl_easy_setopt(conn->connection,
3547 CURLOPT_PROGRESSFUNCTION,
3548 progressFunction);
3549 if (result != CURLE_OK)
3550 raiseError(conn, result);
3552 result = curl_easy_setopt(conn->connection,
3553 CURLOPT_PROGRESSDATA,
3554 conn);
3556 if (result != CURLE_OK)
3557 raiseError(conn, result);
3559 CAMLreturn0;
3562 static void handleSSLVerifyPeer(Connection *conn, value option)
3564 CAMLparam1(option);
3565 CURLcode result = CURLE_OK;
3567 result = curl_easy_setopt(conn->connection,
3568 CURLOPT_SSL_VERIFYPEER,
3569 Bool_val(option));
3571 if (result != CURLE_OK)
3572 raiseError(conn, result);
3574 CAMLreturn0;
3577 static void handleCAInfo(Connection *conn, value option)
3579 CAMLparam1(option);
3580 CURLcode result = CURLE_OK;
3582 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3584 if (conn->caInfo != NULL)
3585 free(conn->caInfo);
3587 conn->caInfo = strdup(String_val(option));
3589 result = curl_easy_setopt(conn->connection,
3590 CURLOPT_CAINFO,
3591 conn->caInfo);
3593 if (result != CURLE_OK)
3594 raiseError(conn, result);
3596 CAMLreturn0;
3599 static void handleCAPath(Connection *conn, value option)
3601 CAMLparam1(option);
3602 CURLcode result = CURLE_OK;
3604 Store_field(conn->ocamlValues, OcamlCAPath, option);
3606 if (conn->caPath != NULL)
3607 free(conn->caPath);
3609 conn->caPath = strdup(String_val(option));
3611 result = curl_easy_setopt(conn->connection,
3612 CURLOPT_CAPATH,
3613 conn->caPath);
3615 if (result != CURLE_OK)
3616 raiseError(conn, result);
3618 CAMLreturn0;
3621 static void handleFileTime(Connection *conn, value option)
3623 CAMLparam1(option);
3624 CURLcode result = CURLE_OK;
3626 result = curl_easy_setopt(conn->connection,
3627 CURLOPT_FILETIME,
3628 Bool_val(option));
3630 if (result != CURLE_OK)
3631 raiseError(conn, result);
3633 CAMLreturn0;
3636 static void handleMaxRedirs(Connection *conn, value option)
3638 CAMLparam1(option);
3639 CURLcode result = CURLE_OK;
3641 result = curl_easy_setopt(conn->connection,
3642 CURLOPT_MAXREDIRS,
3643 Long_val(option));
3645 if (result != CURLE_OK)
3646 raiseError(conn, result);
3648 CAMLreturn0;
3651 static void handleMaxConnects(Connection *conn, value option)
3653 CAMLparam1(option);
3654 CURLcode result = CURLE_OK;
3656 result = curl_easy_setopt(conn->connection,
3657 CURLOPT_MAXCONNECTS,
3658 Long_val(option));
3660 if (result != CURLE_OK)
3661 raiseError(conn, result);
3663 CAMLreturn0;
3666 static void handleClosePolicy(Connection *conn, value option)
3668 CAMLparam1(option);
3669 CURLcode result = CURLE_OK;
3671 switch (Long_val(option))
3673 case 0: /* CLOSEPOLICY_OLDEST */
3674 result = curl_easy_setopt(conn->connection,
3675 CURLOPT_CLOSEPOLICY,
3676 CURLCLOSEPOLICY_OLDEST);
3677 break;
3679 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3680 result = curl_easy_setopt(conn->connection,
3681 CURLOPT_CLOSEPOLICY,
3682 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3683 break;
3685 default:
3686 failwith("Invalid CLOSEPOLICY Option");
3687 break;
3690 if (result != CURLE_OK)
3691 raiseError(conn, result);
3693 CAMLreturn0;
3696 static void handleFreshConnect(Connection *conn, value option)
3698 CAMLparam1(option);
3699 CURLcode result = CURLE_OK;
3701 result = curl_easy_setopt(conn->connection,
3702 CURLOPT_FRESH_CONNECT,
3703 Bool_val(option));
3705 if (result != CURLE_OK)
3706 raiseError(conn, result);
3708 CAMLreturn0;
3711 static void handleForbidReuse(Connection *conn, value option)
3713 CAMLparam1(option);
3714 CURLcode result = CURLE_OK;
3716 result = curl_easy_setopt(conn->connection,
3717 CURLOPT_FORBID_REUSE,
3718 Bool_val(option));
3720 if (result != CURLE_OK)
3721 raiseError(conn, result);
3723 CAMLreturn0;
3726 static void handleRandomFile(Connection *conn, value option)
3728 CAMLparam1(option);
3729 CURLcode result = CURLE_OK;
3731 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3733 if (conn->randomFile != NULL)
3734 free(conn->randomFile);
3736 conn->randomFile = strdup(String_val(option));
3738 result = curl_easy_setopt(conn->connection,
3739 CURLOPT_RANDOM_FILE,
3740 conn->randomFile);
3742 if (result != CURLE_OK)
3743 raiseError(conn, result);
3745 CAMLreturn0;
3748 static void handleEGDSocket(Connection *conn, value option)
3750 CAMLparam1(option);
3751 CURLcode result = CURLE_OK;
3753 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3755 if (conn->egdSocket != NULL)
3756 free(conn->egdSocket);
3758 conn->egdSocket = strdup(String_val(option));
3760 result = curl_easy_setopt(conn->connection,
3761 CURLOPT_EGDSOCKET,
3762 conn->egdSocket);
3764 if (result != CURLE_OK)
3765 raiseError(conn, result);
3767 CAMLreturn0;
3770 static void handleConnectTimeout(Connection *conn, value option)
3772 CAMLparam1(option);
3773 CURLcode result = CURLE_OK;
3775 result = curl_easy_setopt(conn->connection,
3776 CURLOPT_CONNECTTIMEOUT,
3777 Long_val(option));
3779 if (result != CURLE_OK)
3780 raiseError(conn, result);
3782 CAMLreturn0;
3785 static void handleHTTPGet(Connection *conn, value option)
3787 CAMLparam1(option);
3788 CURLcode result = CURLE_OK;
3790 result = curl_easy_setopt(conn->connection,
3791 CURLOPT_HTTPGET,
3792 Bool_val(option));
3794 if (result != CURLE_OK)
3795 raiseError(conn, result);
3797 CAMLreturn0;
3800 static void handleSSLVerifyHost(Connection *conn, value option)
3802 CAMLparam1(option);
3803 CURLcode result = CURLE_OK;
3805 switch (Long_val(option))
3807 case 0: /* SSLVERIFYHOST_NONE */
3808 case 1: /* SSLVERIFYHOST_EXISTENCE */
3809 case 2: /* SSLVERIFYHOST_HOSTNAME */
3810 result = curl_easy_setopt(conn->connection,
3811 CURLOPT_SSL_VERIFYHOST,
3812 /* map EXISTENCE to HOSTNAME */
3813 Long_val(option) == 0 ? 0 : 2);
3814 break;
3816 default:
3817 failwith("Invalid SSLVERIFYHOST Option");
3818 break;
3821 if (result != CURLE_OK)
3822 raiseError(conn, result);
3824 CAMLreturn0;
3827 static void handleCookieJar(Connection *conn, value option)
3829 CAMLparam1(option);
3830 CURLcode result = CURLE_OK;
3832 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3834 if (conn->cookieJar != NULL)
3835 free(conn->cookieJar);
3837 conn->cookieJar = strdup(String_val(option));
3839 result = curl_easy_setopt(conn->connection,
3840 CURLOPT_COOKIEJAR,
3841 conn->cookieJar);
3843 if (result != CURLE_OK)
3844 raiseError(conn, result);
3846 CAMLreturn0;
3849 static void handleSSLCipherList(Connection *conn, value option)
3851 CAMLparam1(option);
3852 CURLcode result = CURLE_OK;
3854 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3856 if (conn->sslCipherList != NULL)
3857 free(conn->sslCipherList);
3859 conn->sslCipherList = strdup(String_val(option));
3861 result = curl_easy_setopt(conn->connection,
3862 CURLOPT_SSL_CIPHER_LIST,
3863 conn->sslCipherList);
3865 if (result != CURLE_OK)
3866 raiseError(conn, result);
3868 CAMLreturn0;
3871 static void handleHTTPVersion(Connection *conn, value option)
3873 CAMLparam1(option);
3874 CURLcode result = CURLE_OK;
3876 switch (Long_val(option))
3878 case 0: /* HTTP_VERSION_NONE */
3879 result = curl_easy_setopt(conn->connection,
3880 CURLOPT_HTTP_VERSION,
3881 CURL_HTTP_VERSION_NONE);
3882 break;
3884 case 1: /* HTTP_VERSION_1_0 */
3885 result = curl_easy_setopt(conn->connection,
3886 CURLOPT_HTTP_VERSION,
3887 CURL_HTTP_VERSION_1_0);
3888 break;
3890 case 2: /* HTTP_VERSION_1_1 */
3891 result = curl_easy_setopt(conn->connection,
3892 CURLOPT_HTTP_VERSION,
3893 CURL_HTTP_VERSION_1_1);
3894 break;
3896 default:
3897 failwith("Invalid HTTP_VERSION Option");
3898 break;
3901 if (result != CURLE_OK)
3902 raiseError(conn, result);
3904 CAMLreturn0;
3907 static void handleFTPUseEPSV(Connection *conn, value option)
3909 CAMLparam1(option);
3910 CURLcode result = CURLE_OK;
3912 result = curl_easy_setopt(conn->connection,
3913 CURLOPT_FTP_USE_EPSV,
3914 Bool_val(option));
3916 if (result != CURLE_OK)
3917 raiseError(conn, result);
3919 CAMLreturn0;
3922 static void handleDNSCacheTimeout(Connection *conn, value option)
3924 CAMLparam1(option);
3925 CURLcode result = CURLE_OK;
3927 result = curl_easy_setopt(conn->connection,
3928 CURLOPT_DNS_CACHE_TIMEOUT,
3929 Long_val(option));
3931 if (result != CURLE_OK)
3932 raiseError(conn, result);
3934 CAMLreturn0;
3937 static void handleDNSUseGlobalCache(Connection *conn, value option)
3939 CAMLparam1(option);
3940 CURLcode result = CURLE_OK;
3942 result = curl_easy_setopt(conn->connection,
3943 CURLOPT_DNS_USE_GLOBAL_CACHE,
3944 Bool_val(option));
3946 if (result != CURLE_OK)
3947 raiseError(conn, result);
3949 CAMLreturn0;
3952 static void handleDebugFunction(Connection *conn, value option)
3954 CAMLparam1(option);
3955 CURLcode result = CURLE_OK;
3957 if (Tag_val(option) == Closure_tag)
3958 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3959 else
3960 failwith("Not a proper closure");
3962 result = curl_easy_setopt(conn->connection,
3963 CURLOPT_DEBUGFUNCTION,
3964 debugFunction);
3965 if (result != CURLE_OK)
3966 raiseError(conn, result);
3968 result = curl_easy_setopt(conn->connection,
3969 CURLOPT_DEBUGDATA,
3970 conn);
3972 if (result != CURLE_OK)
3973 raiseError(conn, result);
3975 CAMLreturn0;
3978 static void handlePrivate(Connection *conn, value option)
3980 #if HAVE_DECL_CURLOPT_PRIVATE
3981 CAMLparam1(option);
3982 CURLcode result = CURLE_OK;
3984 Store_field(conn->ocamlValues, OcamlPrivate, option);
3986 if (conn->private != NULL)
3987 free(conn->private);
3989 conn->private = strdup(String_val(option));
3991 result = curl_easy_setopt(conn->connection,
3992 CURLOPT_PRIVATE,
3993 conn->private);
3995 if (result != CURLE_OK)
3996 raiseError(conn, result);
3998 CAMLreturn0;
3999 #else
4000 #pragma message("libcurl does not implement CURLOPT_PRIVATE")
4001 failwith("libcurl does not implement CURLOPT_PRIVATE");
4002 #endif
4005 static void handleHTTP200Aliases(Connection *conn, value option)
4007 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
4008 CAMLparam1(option);
4009 CAMLlocal1(listIter);
4010 CURLcode result = CURLE_OK;
4012 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
4014 free_curl_slist(conn->http200Aliases);
4015 conn->http200Aliases = NULL;
4017 listIter = option;
4019 while (!Is_long(listIter))
4021 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
4023 listIter = Field(listIter, 1);
4026 result = curl_easy_setopt(conn->connection,
4027 CURLOPT_HTTP200ALIASES,
4028 conn->http200Aliases);
4030 if (result != CURLE_OK)
4031 raiseError(conn, result);
4033 CAMLreturn0;
4034 #else
4035 #pragma message("libcurl does not implement CURLOPT_HTTP200ALIASES")
4036 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
4037 #endif
4040 static void handleUnrestrictedAuth(Connection *conn, value option)
4042 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4043 CAMLparam1(option);
4044 CURLcode result = CURLE_OK;
4046 result = curl_easy_setopt(conn->connection,
4047 CURLOPT_UNRESTRICTED_AUTH,
4048 Bool_val(option));
4050 if (result != CURLE_OK)
4051 raiseError(conn, result);
4053 CAMLreturn0;
4054 #else
4055 #pragma message("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH")
4056 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4057 #endif
4060 static void handleFTPUseEPRT(Connection *conn, value option)
4062 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4063 CAMLparam1(option);
4064 CURLcode result = CURLE_OK;
4066 result = curl_easy_setopt(conn->connection,
4067 CURLOPT_FTP_USE_EPRT,
4068 Bool_val(option));
4070 if (result != CURLE_OK)
4071 raiseError(conn, result);
4073 CAMLreturn0;
4074 #else
4075 #pragma message("libcurl does not implement CURLOPT_FTP_USE_EPRT")
4076 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4077 #endif
4080 static void handleHTTPAuth(Connection *conn, value option)
4082 #if HAVE_DECL_CURLOPT_HTTPAUTH
4083 CAMLparam1(option);
4084 CAMLlocal1(listIter);
4085 CURLcode result = CURLE_OK;
4086 long auth = CURLAUTH_NONE;
4088 listIter = option;
4090 while (!Is_long(listIter))
4092 switch (Long_val(Field(listIter, 0)))
4094 case 0: /* CURLAUTH_BASIC */
4095 auth |= CURLAUTH_BASIC;
4096 break;
4098 case 1: /* CURLAUTH_DIGEST */
4099 auth |= CURLAUTH_DIGEST;
4100 break;
4102 case 2: /* CURLAUTH_GSSNEGOTIATE */
4103 auth |= CURLAUTH_GSSNEGOTIATE;
4104 break;
4106 case 3: /* CURLAUTH_NTLM */
4107 auth |= CURLAUTH_NTLM;
4108 break;
4110 case 4: /* CURLAUTH_ANY */
4111 auth |= CURLAUTH_ANY;
4112 break;
4114 case 5: /* CURLAUTH_ANYSAFE */
4115 auth |= CURLAUTH_ANYSAFE;
4116 break;
4118 default:
4119 failwith("Invalid HTTPAUTH Value");
4120 break;
4123 listIter = Field(listIter, 1);
4126 result = curl_easy_setopt(conn->connection,
4127 CURLOPT_HTTPAUTH,
4128 auth);
4130 if (result != CURLE_OK)
4131 raiseError(conn, result);
4133 CAMLreturn0;
4134 #else
4135 #pragma message("libcurl does not implement CURLOPT_HTTPAUTH")
4136 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4137 #endif
4140 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4142 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4143 CAMLparam1(option);
4144 CURLcode result = CURLE_OK;
4146 result = curl_easy_setopt(conn->connection,
4147 CURLOPT_FTP_CREATE_MISSING_DIRS,
4148 Bool_val(option));
4150 if (result != CURLE_OK)
4151 raiseError(conn, result);
4153 CAMLreturn0;
4154 #else
4155 #pragma message("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS")
4156 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4157 #endif
4160 static void handleProxyAuth(Connection *conn, value option)
4162 #if HAVE_DECL_CURLOPT_PROXYAUTH
4163 CAMLparam1(option);
4164 CAMLlocal1(listIter);
4165 CURLcode result = CURLE_OK;
4166 long auth = CURLAUTH_NONE;
4168 listIter = option;
4170 while (!Is_long(listIter))
4172 switch (Long_val(Field(listIter, 0)))
4174 case 0: /* CURLAUTH_BASIC */
4175 auth |= CURLAUTH_BASIC;
4176 break;
4178 case 1: /* CURLAUTH_DIGEST */
4179 auth |= CURLAUTH_DIGEST;
4180 break;
4182 case 2: /* CURLAUTH_GSSNEGOTIATE */
4183 auth |= CURLAUTH_GSSNEGOTIATE;
4184 break;
4186 case 3: /* CURLAUTH_NTLM */
4187 auth |= CURLAUTH_NTLM;
4188 break;
4190 case 4: /* CURLAUTH_ANY */
4191 auth |= CURLAUTH_ANY;
4192 break;
4194 case 5: /* CURLAUTH_ANYSAFE */
4195 auth |= CURLAUTH_ANYSAFE;
4196 break;
4198 default:
4199 failwith("Invalid HTTPAUTH Value");
4200 break;
4203 listIter = Field(listIter, 1);
4206 result = curl_easy_setopt(conn->connection,
4207 CURLOPT_PROXYAUTH,
4208 auth);
4210 if (result != CURLE_OK)
4211 raiseError(conn, result);
4213 CAMLreturn0;
4214 #else
4215 #pragma message("libcurl does not implement CURLOPT_PROXYAUTH")
4216 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4217 #endif
4220 static void handleFTPResponseTimeout(Connection *conn, value option)
4222 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4223 CAMLparam1(option);
4224 CURLcode result = CURLE_OK;
4226 result = curl_easy_setopt(conn->connection,
4227 CURLOPT_FTP_RESPONSE_TIMEOUT,
4228 Long_val(option));
4230 if (result != CURLE_OK)
4231 raiseError(conn, result);
4233 CAMLreturn0;
4234 #else
4235 #pragma message("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT")
4236 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4237 #endif
4240 static void handleIPResolve(Connection *conn, value option)
4242 #if HAVE_DECL_CURLOPT_IPRESOLVE
4243 CAMLparam1(option);
4244 CURLcode result = CURLE_OK;
4246 switch (Long_val(option))
4248 case 0: /* CURL_IPRESOLVE_WHATEVER */
4249 result = curl_easy_setopt(conn->connection,
4250 CURLOPT_IPRESOLVE,
4251 CURL_IPRESOLVE_WHATEVER);
4252 break;
4254 case 1: /* CURL_IPRESOLVE_V4 */
4255 result = curl_easy_setopt(conn->connection,
4256 CURLOPT_IPRESOLVE,
4257 CURL_IPRESOLVE_V4);
4258 break;
4260 case 2: /* CURL_IPRESOLVE_V6 */
4261 result = curl_easy_setopt(conn->connection,
4262 CURLOPT_IPRESOLVE,
4263 CURL_IPRESOLVE_V6);
4264 break;
4266 default:
4267 failwith("Invalid IPRESOLVE Value");
4268 break;
4271 if (result != CURLE_OK)
4272 raiseError(conn, result);
4274 CAMLreturn0;
4275 #else
4276 #pragma message("libcurl does not implement CURLOPT_IPRESOLVE")
4277 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4278 #endif
4281 static void handleMaxFileSize(Connection *conn, value option)
4283 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4284 CAMLparam1(option);
4285 CURLcode result = CURLE_OK;
4287 result = curl_easy_setopt(conn->connection,
4288 CURLOPT_MAXFILESIZE,
4289 Int32_val(option));
4291 if (result != CURLE_OK)
4292 raiseError(conn, result);
4294 CAMLreturn0;
4295 #else
4296 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE")
4297 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4298 #endif
4301 static void handleInFileSizeLarge(Connection *conn, value option)
4303 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4304 CAMLparam1(option);
4305 CURLcode result = CURLE_OK;
4307 result = curl_easy_setopt(conn->connection,
4308 CURLOPT_INFILESIZE_LARGE,
4309 Int64_val(option));
4311 if (result != CURLE_OK)
4312 raiseError(conn, result);
4314 CAMLreturn0;
4315 #else
4316 #pragma message("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4317 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4318 #endif
4321 static void handleResumeFromLarge(Connection *conn, value option)
4323 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4324 CAMLparam1(option);
4325 CURLcode result = CURLE_OK;
4327 result = curl_easy_setopt(conn->connection,
4328 CURLOPT_RESUME_FROM_LARGE,
4329 Int64_val(option));
4331 if (result != CURLE_OK)
4332 raiseError(conn, result);
4334 CAMLreturn0;
4335 #else
4336 #pragma message("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4337 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4338 #endif
4341 static void handleMaxFileSizeLarge(Connection *conn, value option)
4343 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4344 CAMLparam1(option);
4345 CURLcode result = CURLE_OK;
4347 result = curl_easy_setopt(conn->connection,
4348 CURLOPT_MAXFILESIZE_LARGE,
4349 Int64_val(option));
4351 if (result != CURLE_OK)
4352 raiseError(conn, result);
4354 CAMLreturn0;
4355 #else
4356 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE")
4357 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4358 #endif
4361 static void handleNETRCFile(Connection *conn, value option)
4363 #if HAVE_DECL_CURLOPT_NETRC_FILE
4364 CAMLparam1(option);
4365 CURLcode result = CURLE_OK;
4367 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4369 if (conn->netrcFile != NULL)
4370 free(conn->netrcFile);
4372 conn->netrcFile = strdup(String_val(option));
4374 result = curl_easy_setopt(conn->connection,
4375 CURLOPT_NETRC_FILE,
4376 conn->netrcFile);
4378 if (result != CURLE_OK)
4379 raiseError(conn, result);
4381 CAMLreturn0;
4382 #else
4383 #pragma message("libcurl does not implement CURLOPT_NETRC_FILE")
4384 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4385 #endif
4388 static void handleFTPSSL(Connection *conn, value option)
4390 #if HAVE_DECL_CURLOPT_FTP_SSL
4391 CAMLparam1(option);
4392 CURLcode result = CURLE_OK;
4394 switch (Long_val(option))
4396 case 0: /* CURLFTPSSL_NONE */
4397 result = curl_easy_setopt(conn->connection,
4398 CURLOPT_FTP_SSL,
4399 CURLFTPSSL_NONE);
4400 break;
4402 case 1: /* CURLFTPSSL_TRY */
4403 result = curl_easy_setopt(conn->connection,
4404 CURLOPT_FTP_SSL,
4405 CURLFTPSSL_TRY);
4406 break;
4408 case 2: /* CURLFTPSSL_CONTROL */
4409 result = curl_easy_setopt(conn->connection,
4410 CURLOPT_FTP_SSL,
4411 CURLFTPSSL_CONTROL);
4412 break;
4414 case 3: /* CURLFTPSSL_ALL */
4415 result = curl_easy_setopt(conn->connection,
4416 CURLOPT_FTP_SSL,
4417 CURLFTPSSL_ALL);
4418 break;
4420 default:
4421 failwith("Invalid FTP_SSL Value");
4422 break;
4425 if (result != CURLE_OK)
4426 raiseError(conn, result);
4428 CAMLreturn0;
4429 #else
4430 #pragma message("libcurl does not implement CURLOPT_FTP_SSL")
4431 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4432 #endif
4435 static void handlePostFieldSizeLarge(Connection *conn, value option)
4437 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4438 CAMLparam1(option);
4439 CURLcode result = CURLE_OK;
4441 result = curl_easy_setopt(conn->connection,
4442 CURLOPT_POSTFIELDSIZE_LARGE,
4443 Int64_val(option));
4445 if (result != CURLE_OK)
4446 raiseError(conn, result);
4448 CAMLreturn0;
4449 #else
4450 #pragma message("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE")
4451 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4452 #endif
4455 static void handleTCPNoDelay(Connection *conn, value option)
4457 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4458 CAMLparam1(option);
4459 CURLcode result = CURLE_OK;
4461 result = curl_easy_setopt(conn->connection,
4462 CURLOPT_TCP_NODELAY,
4463 Bool_val(option));
4465 if (result != CURLE_OK)
4466 raiseError(conn, result);
4468 CAMLreturn0;
4469 #else
4470 #pragma message("libcurl does not implement CURLOPT_TCP_NODELAY")
4471 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4472 #endif
4475 static void handleFTPSSLAuth(Connection *conn, value option)
4477 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4478 CAMLparam1(option);
4479 CURLcode result = CURLE_OK;
4481 switch (Long_val(option))
4483 case 0: /* CURLFTPAUTH_DEFAULT */
4484 result = curl_easy_setopt(conn->connection,
4485 CURLOPT_FTPSSLAUTH,
4486 CURLFTPAUTH_DEFAULT);
4487 break;
4489 case 1: /* CURLFTPAUTH_SSL */
4490 result = curl_easy_setopt(conn->connection,
4491 CURLOPT_FTPSSLAUTH,
4492 CURLFTPAUTH_SSL);
4493 break;
4495 case 2: /* CURLFTPAUTH_TLS */
4496 result = curl_easy_setopt(conn->connection,
4497 CURLOPT_FTPSSLAUTH,
4498 CURLFTPAUTH_TLS);
4499 break;
4501 default:
4502 failwith("Invalid FTPSSLAUTH value");
4503 break;
4506 if (result != CURLE_OK)
4507 raiseError(conn, result);
4509 CAMLreturn0;
4510 #else
4511 #pragma message("libcurl does not implement CURLOPT_FTPSSLAUTH")
4512 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4513 #endif
4516 static void handleIOCTLFunction(Connection *conn, value option)
4518 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4519 CAMLparam1(option);
4520 CURLcode result = CURLE_OK;
4522 if (Tag_val(option) == Closure_tag)
4523 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4524 else
4525 failwith("Not a proper closure");
4527 result = curl_easy_setopt(conn->connection,
4528 CURLOPT_IOCTLFUNCTION,
4529 ioctlFunction);
4530 if (result != CURLE_OK)
4531 raiseError(conn, result);
4533 result = curl_easy_setopt(conn->connection,
4534 CURLOPT_DEBUGDATA,
4535 conn);
4537 if (result != CURLE_OK)
4538 raiseError(conn, result);
4540 CAMLreturn0;
4541 #else
4542 #pragma message("libcurl does not implement CURLOPT_IOCTLFUNCTION")
4543 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4544 #endif
4547 static void handleFTPAccount(Connection *conn, value option)
4549 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4550 CAMLparam1(option);
4551 CURLcode result = CURLE_OK;
4553 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4555 if (conn->ftpaccount != NULL)
4556 free(conn->ftpaccount);
4558 conn->ftpaccount = strdup(String_val(option));
4560 result = curl_easy_setopt(conn->connection,
4561 CURLOPT_FTP_ACCOUNT,
4562 conn->ftpaccount);
4564 if (result != CURLE_OK)
4565 raiseError(conn, result);
4567 CAMLreturn0;
4568 #else
4569 #pragma message("libcurl does not implement CURLOPT_FTP_ACCOUNT")
4570 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4571 #endif
4574 static void handleCookieList(Connection *conn, value option)
4576 #if HAVE_DECL_CURLOPT_COOKIELIST
4577 CAMLparam1(option);
4578 CURLcode result = CURLE_OK;
4580 Store_field(conn->ocamlValues, OcamlCookieList, option);
4582 if (conn->cookielist != NULL)
4583 free(conn->cookielist);
4585 conn->cookielist = strdup(String_val(option));
4587 result = curl_easy_setopt(conn->connection,
4588 CURLOPT_COOKIELIST,
4589 conn->cookielist);
4591 if (result != CURLE_OK)
4592 raiseError(conn, result);
4594 CAMLreturn0;
4595 #else
4596 #pragma message("libcurl does not implement CURLOPT_COOKIELIST")
4597 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4598 #endif
4601 static void handleIgnoreContentLength(Connection *conn, value option)
4603 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4604 CAMLparam1(option);
4605 CURLcode result = CURLE_OK;
4607 result = curl_easy_setopt(conn->connection,
4608 CURLOPT_IGNORE_CONTENT_LENGTH,
4609 Bool_val(option));
4611 if (result != CURLE_OK)
4612 raiseError(conn, result);
4614 CAMLreturn0;
4615 #else
4616 #pragma message("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH")
4617 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4618 #endif
4621 static void handleFTPSkipPASVIP(Connection *conn, value option)
4623 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4624 CAMLparam1(option);
4625 CURLcode result = CURLE_OK;
4627 result = curl_easy_setopt(conn->connection,
4628 CURLOPT_FTP_SKIP_PASV_IP,
4629 Bool_val(option));
4631 if (result != CURLE_OK)
4632 raiseError(conn, result);
4634 CAMLreturn0;
4635 #else
4636 #pragma message("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP")
4637 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4638 #endif
4641 static void handleFTPFileMethod(Connection *conn, value option)
4643 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4644 CAMLparam1(option);
4645 CURLcode result = CURLE_OK;
4647 switch (Long_val(option))
4649 case 0: /* CURLFTPMETHOD_DEFAULT */
4650 result = curl_easy_setopt(conn->connection,
4651 CURLOPT_FTP_FILEMETHOD,
4652 CURLFTPMETHOD_DEFAULT);
4653 break;
4655 case 1: /* CURLFTMETHOD_MULTICWD */
4656 result = curl_easy_setopt(conn->connection,
4657 CURLOPT_FTP_FILEMETHOD,
4658 CURLFTPMETHOD_MULTICWD);
4659 break;
4661 case 2: /* CURLFTPMETHOD_NOCWD */
4662 result = curl_easy_setopt(conn->connection,
4663 CURLOPT_FTP_FILEMETHOD,
4664 CURLFTPMETHOD_NOCWD);
4665 break;
4667 case 3: /* CURLFTPMETHOD_SINGLECWD */
4668 result = curl_easy_setopt(conn->connection,
4669 CURLOPT_FTP_FILEMETHOD,
4670 CURLFTPMETHOD_SINGLECWD);
4672 default:
4673 failwith("Invalid FTP_FILEMETHOD value");
4674 break;
4677 if (result != CURLE_OK)
4678 raiseError(conn, result);
4680 CAMLreturn0;
4681 #else
4682 #pragma message("libcurl does not implement CURLOPT_FTP_FILEMETHOD")
4683 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4684 #endif
4687 static void handleLocalPort(Connection *conn, value option)
4689 #if HAVE_DECL_CURLOPT_LOCALPORT
4690 CAMLparam1(option);
4691 CURLcode result = CURLE_OK;
4693 result = curl_easy_setopt(conn->connection,
4694 CURLOPT_LOCALPORT,
4695 Long_val(option));
4697 if (result != CURLE_OK)
4698 raiseError(conn, result);
4700 CAMLreturn0;
4701 #else
4702 #pragma message("libcurl does not implement CURLOPT_LOCALPORT")
4703 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4704 #endif
4707 static void handleLocalPortRange(Connection *conn, value option)
4709 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4710 CAMLparam1(option);
4711 CURLcode result = CURLE_OK;
4713 result = curl_easy_setopt(conn->connection,
4714 CURLOPT_LOCALPORTRANGE,
4715 Long_val(option));
4717 if (result != CURLE_OK)
4718 raiseError(conn, result);
4720 CAMLreturn0;
4721 #else
4722 #pragma message("libcurl does not implement CURLOPT_LOCALPORTRANGE")
4723 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4724 #endif
4727 static void handleConnectOnly(Connection *conn, value option)
4729 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4730 CAMLparam1(option);
4731 CURLcode result = CURLE_OK;
4733 result = curl_easy_setopt(conn->connection,
4734 CURLOPT_CONNECT_ONLY,
4735 Bool_val(option));
4737 if (result != CURLE_OK)
4738 raiseError(conn, result);
4740 CAMLreturn0;
4741 #else
4742 #pragma message("libcurl does not implement CURLOPT_CONNECT_ONLY")
4743 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4744 #endif
4747 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4749 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4750 CAMLparam1(option);
4751 CURLcode result = CURLE_OK;
4753 result = curl_easy_setopt(conn->connection,
4754 CURLOPT_MAX_SEND_SPEED_LARGE,
4755 Int64_val(option));
4757 if (result != CURLE_OK)
4758 raiseError(conn, result);
4760 CAMLreturn0;
4761 #else
4762 #pragma message("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE")
4763 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4764 #endif
4767 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4769 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4770 CAMLparam1(option);
4771 CURLcode result = CURLE_OK;
4773 result = curl_easy_setopt(conn->connection,
4774 CURLOPT_MAX_RECV_SPEED_LARGE,
4775 Int64_val(option));
4777 if (result != CURLE_OK)
4778 raiseError(conn, result);
4780 CAMLreturn0;
4781 #else
4782 #pragma message("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE")
4783 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4784 #endif
4787 static void handleFTPAlternativeToUser(Connection *conn, value option)
4789 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4790 CAMLparam1(option);
4791 CURLcode result = CURLE_OK;
4793 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4795 if (conn->ftpAlternativeToUser != NULL)
4796 free(conn->ftpAlternativeToUser);
4798 conn->ftpAlternativeToUser = strdup(String_val(option));
4800 result = curl_easy_setopt(conn->connection,
4801 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4802 conn->ftpAlternativeToUser);
4804 if (result != CURLE_OK)
4805 raiseError(conn, result);
4807 CAMLreturn0;
4808 #else
4809 #pragma message("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER")
4810 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4811 #endif
4814 static void handleSSLSessionIdCache(Connection *conn, value option)
4816 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4817 CAMLparam1(option);
4818 CURLcode result = CURLE_OK;
4820 result = curl_easy_setopt(conn->connection,
4821 CURLOPT_SSL_SESSIONID_CACHE,
4822 Bool_val(option));
4824 if (result != CURLE_OK)
4825 raiseError(conn, result);
4827 CAMLreturn0;
4828 #else
4829 #pragma message("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE")
4830 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4831 #endif
4834 static void handleSSHAuthTypes(Connection *conn, value option)
4836 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4837 CAMLparam1(option);
4838 CAMLlocal1(listIter);
4839 CURLcode result = CURLE_OK;
4840 long authTypes = CURLSSH_AUTH_NONE;
4842 listIter = option;
4844 while (!Is_long(listIter))
4846 switch (Long_val(Field(listIter, 0)))
4848 case 0: /* CURLSSH_AUTH_ANY */
4849 authTypes |= CURLSSH_AUTH_ANY;
4850 break;
4852 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4853 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4854 break;
4856 case 2: /* CURLSSH_AUTH_PASSWORD */
4857 authTypes |= CURLSSH_AUTH_PASSWORD;
4858 break;
4860 case 3: /* CURLSSH_AUTH_HOST */
4861 authTypes |= CURLSSH_AUTH_HOST;
4862 break;
4864 case 4: /* CURLSSH_AUTH_KEYBOARD */
4865 authTypes |= CURLSSH_AUTH_KEYBOARD;
4866 break;
4868 default:
4869 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4870 break;
4873 listIter = Field(listIter, 1);
4876 result = curl_easy_setopt(conn->connection,
4877 CURLOPT_SSH_AUTH_TYPES,
4878 authTypes);
4880 if (result != CURLE_OK)
4881 raiseError(conn, result);
4883 CAMLreturn0;
4884 #else
4885 #pragma message("libcurl does not implement CURLOPT_SSH_AUTH_TYPES")
4886 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4887 #endif
4890 static void handleSSHPublicKeyFile(Connection *conn, value option)
4892 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4893 CAMLparam1(option);
4894 CURLcode result = CURLE_OK;
4896 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4898 if (conn->sshPublicKeyFile != NULL)
4899 free(conn->sshPublicKeyFile);
4901 conn->sshPublicKeyFile = strdup(String_val(option));
4903 result = curl_easy_setopt(conn->connection,
4904 CURLOPT_SSH_PUBLIC_KEYFILE,
4905 conn->sshPublicKeyFile);
4907 if (result != CURLE_OK)
4908 raiseError(conn, result);
4910 CAMLreturn0;
4911 #else
4912 #pragma message("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE")
4913 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4914 #endif
4917 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4919 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4920 CAMLparam1(option);
4921 CURLcode result = CURLE_OK;
4923 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4925 if (conn->sshPrivateKeyFile != NULL)
4926 free(conn->sshPrivateKeyFile);
4928 conn->sshPrivateKeyFile = strdup(String_val(option));
4930 result = curl_easy_setopt(conn->connection,
4931 CURLOPT_SSH_PRIVATE_KEYFILE,
4932 conn->sshPrivateKeyFile);
4934 if (result != CURLE_OK)
4935 raiseError(conn, result);
4937 CAMLreturn0;
4938 #else
4939 #pragma message("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE")
4940 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4941 #endif
4944 static void handleFTPSSLCCC(Connection *conn, value option)
4946 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4947 CAMLparam1(option);
4948 CURLcode result = CURLE_OK;
4950 switch (Long_val(option))
4952 case 0: /* CURLFTPSSL_CCC_NONE */
4953 result = curl_easy_setopt(conn->connection,
4954 CURLOPT_FTP_SSL_CCC,
4955 CURLFTPSSL_CCC_NONE);
4956 break;
4958 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4959 result = curl_easy_setopt(conn->connection,
4960 CURLOPT_FTP_SSL_CCC,
4961 CURLFTPSSL_CCC_PASSIVE);
4962 break;
4964 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4965 result = curl_easy_setopt(conn->connection,
4966 CURLOPT_FTP_SSL_CCC,
4967 CURLFTPSSL_CCC_ACTIVE);
4968 break;
4970 default:
4971 failwith("Invalid FTPSSL_CCC value");
4972 break;
4975 if (result != CURLE_OK)
4976 raiseError(conn, result);
4978 CAMLreturn0;
4979 #else
4980 #pragma message("libcurl does not implement CURLOPT_FTP_SSL_CCC")
4981 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4982 #endif
4985 static void handleTimeoutMS(Connection *conn, value option)
4987 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4988 CAMLparam1(option);
4989 CURLcode result = CURLE_OK;
4991 result = curl_easy_setopt(conn->connection,
4992 CURLOPT_TIMEOUT_MS,
4993 Long_val(option));
4995 if (result != CURLE_OK)
4996 raiseError(conn, result);
4998 CAMLreturn0;
4999 #else
5000 #pragma message("libcurl does not implement CURLOPT_TIMEOUT_MS")
5001 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
5002 #endif
5005 static void handleConnectTimeoutMS(Connection *conn, value option)
5007 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
5008 CAMLparam1(option);
5009 CURLcode result = CURLE_OK;
5011 result = curl_easy_setopt(conn->connection,
5012 CURLOPT_CONNECTTIMEOUT_MS,
5013 Long_val(option));
5015 if (result != CURLE_OK)
5016 raiseError(conn, result);
5018 CAMLreturn0;
5019 #else
5020 #pragma message("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS")
5021 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
5022 #endif
5025 static void handleHTTPTransferDecoding(Connection *conn, value option)
5027 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5028 CAMLparam1(option);
5029 CURLcode result = CURLE_OK;
5031 result = curl_easy_setopt(conn->connection,
5032 CURLOPT_HTTP_TRANSFER_DECODING,
5033 Bool_val(option));
5035 if (result != CURLE_OK)
5036 raiseError(conn, result);
5038 CAMLreturn0;
5039 #else
5040 #pragma message("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING")
5041 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
5042 #endif
5045 static void handleHTTPContentDecoding(Connection *conn, value option)
5047 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5048 CAMLparam1(option);
5049 CURLcode result = CURLE_OK;
5051 result = curl_easy_setopt(conn->connection,
5052 CURLOPT_HTTP_CONTENT_DECODING,
5053 Bool_val(option));
5055 if (result != CURLE_OK)
5056 raiseError(conn, result);
5058 CAMLreturn0;
5059 #else
5060 #pragma message("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING")
5061 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5062 #endif
5065 static void handleNewFilePerms(Connection *conn, value option)
5067 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5068 CAMLparam1(option);
5069 CURLcode result = CURLE_OK;
5071 result = curl_easy_setopt(conn->connection,
5072 CURLOPT_NEW_FILE_PERMS,
5073 Long_val(option));
5075 if (result != CURLE_OK)
5076 raiseError(conn, result);
5078 CAMLreturn0;
5079 #else
5080 #pragma message("libcurl does not implement CURLOPT_NEW_FILE_PERMS")
5081 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5082 #endif
5085 static void handleNewDirectoryPerms(Connection *conn, value option)
5087 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5088 CAMLparam1(option);
5089 CURLcode result = CURLE_OK;
5091 result = curl_easy_setopt(conn->connection,
5092 CURLOPT_NEW_DIRECTORY_PERMS,
5093 Long_val(option));
5095 if (result != CURLE_OK)
5096 raiseError(conn, result);
5098 CAMLreturn0;
5099 #else
5100 #pragma message("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS")
5101 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5102 #endif
5105 static void handlePost301(Connection *conn, value option)
5107 #if HAVE_DECL_CURLOPT_POST301
5108 CAMLparam1(option);
5109 CURLcode result = CURLE_OK;
5111 result = curl_easy_setopt(conn->connection,
5112 CURLOPT_POST301,
5113 Bool_val(option));
5115 if (result != CURLE_OK)
5116 raiseError(conn, result);
5118 CAMLreturn0;
5119 #else
5120 #pragma message("libcurl does not implement CURLOPT_POST301")
5121 failwith("libcurl does not implement CURLOPT_POST301");
5122 #endif
5125 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5127 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5128 CAMLparam1(option);
5129 CURLcode result = CURLE_OK;
5131 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5133 if (conn->sshHostPublicKeyMD5 != NULL)
5134 free(conn->sshHostPublicKeyMD5);
5136 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5138 result = curl_easy_setopt(conn->connection,
5139 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5140 conn->sshHostPublicKeyMD5);
5142 if (result != CURLE_OK)
5143 raiseError(conn, result);
5145 CAMLreturn0;
5146 #else
5147 #pragma message("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5")
5148 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5149 #endif
5152 static void handleCopyPostFields(Connection *conn, value option)
5154 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5155 CAMLparam1(option);
5156 CURLcode result = CURLE_OK;
5158 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5160 if (conn->copyPostFields != NULL)
5161 free(conn->copyPostFields);
5163 conn->copyPostFields = strdup(String_val(option));
5165 result = curl_easy_setopt(conn->connection,
5166 CURLOPT_COPYPOSTFIELDS,
5167 conn->copyPostFields);
5169 if (result != CURLE_OK)
5170 raiseError(conn, result);
5172 CAMLreturn0;
5173 #else
5174 #pragma message("libcurl does not implement CURLOPT_COPYPOSTFIELDS")
5175 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5176 #endif
5179 static void handleProxyTransferMode(Connection *conn, value option)
5181 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5182 CAMLparam1(option);
5183 CURLcode result = CURLE_OK;
5185 result = curl_easy_setopt(conn->connection,
5186 CURLOPT_PROXY_TRANSFER_MODE,
5187 Bool_val(option));
5189 if (result != CURLE_OK)
5190 raiseError(conn, result);
5192 CAMLreturn0;
5193 #else
5194 #pragma message("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE")
5195 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5196 #endif
5199 static void handleSeekFunction(Connection *conn, value option)
5201 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5202 CAMLparam1(option);
5203 CURLcode result = CURLE_OK;
5205 if (Tag_val(option) == Closure_tag)
5206 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5207 else
5208 failwith("Not a proper closure");
5210 result = curl_easy_setopt(conn->connection,
5211 CURLOPT_SEEKFUNCTION,
5212 seekFunction);
5214 if (result != CURLE_OK)
5215 raiseError(conn, result);
5217 result = curl_easy_setopt(conn->connection,
5218 CURLOPT_SEEKDATA,
5219 conn);
5221 if (result != CURLE_OK)
5222 raiseError(conn, result);
5224 CAMLreturn0;
5225 #else
5226 #pragma message("libcurl does not implement CURLOPT_SEEKFUNCTION")
5227 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5228 #endif
5231 static void handleAutoReferer(Connection *conn, value option)
5233 #if HAVE_DECL_CURLOPT_AUTOREFERER
5234 CAMLparam1(option);
5235 CURLcode result = curl_easy_setopt(conn->connection,
5236 CURLOPT_AUTOREFERER,
5237 Bool_val(option));
5239 if (result != CURLE_OK)
5240 raiseError(conn, result);
5242 CAMLreturn0;
5243 #else
5244 #pragma message("libcurl does not implement CURLOPT_AUTOREFERER")
5245 failwith("libcurl does not implement CURLOPT_AUTOREFERER");
5246 #endif
5249 static void handleOpenSocketFunction(Connection *conn, value option)
5251 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5252 CAMLparam1(option);
5253 CURLcode result = CURLE_OK;
5255 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5257 result = curl_easy_setopt(conn->connection,
5258 CURLOPT_OPENSOCKETDATA,
5259 conn);
5261 if (result != CURLE_OK)
5262 raiseError(conn, result);
5264 result = curl_easy_setopt(conn->connection,
5265 CURLOPT_OPENSOCKETFUNCTION,
5266 openSocketFunction);
5268 if (result != CURLE_OK)
5269 raiseError(conn, result);
5271 CAMLreturn0;
5272 #else
5273 #pragma message("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION")
5274 failwith("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION");
5275 #endif
5278 static void handleProxyType(Connection *conn, value option)
5280 #if HAVE_DECL_CURLOPT_PROXYTYPE
5281 CAMLparam1(option);
5282 CURLcode result = CURLE_OK;
5283 long proxy_type;
5285 switch (Long_val(option))
5287 case 0: proxy_type = CURLPROXY_HTTP; break;
5288 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5289 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5290 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5291 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5292 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5293 default:
5294 failwith("Invalid curl proxy type");
5297 result = curl_easy_setopt(conn->connection,
5298 CURLOPT_PROXYTYPE,
5299 proxy_type);
5301 if (result != CURLE_OK)
5302 raiseError(conn, result);
5304 CAMLreturn0;
5305 #else
5306 #pragma message("libcurl does not implement CURLOPT_PROXYTYPE")
5307 failwith("libcurl does not implement CURLOPT_PROXYTYPE");
5308 #endif
5311 #if HAVE_DECL_CURLOPT_PROTOCOLS && HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5313 long protoMap[] =
5315 CURLPROTO_ALL,
5316 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
5317 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
5318 /* factor out with autoconf? */
5319 #if defined(CURLPROTO_IMAP)
5320 CURLPROTO_IMAP,
5321 #else
5323 #endif
5324 #if defined(CURLPROTO_IMAPS)
5325 CURLPROTO_IMAPS,
5326 #else
5328 #endif
5329 #if defined(CURLPROTO_POP3)
5330 CURLPROTO_POP3,
5331 #else
5333 #endif
5334 #if defined(CURLPROTO_POP3S)
5335 CURLPROTO_POP3S,
5336 #else
5338 #endif
5339 #if defined(CURLPROTO_SMTP)
5340 CURLPROTO_SMTP,
5341 #else
5343 #endif
5344 #if defined(CURLPROTO_SMTPS)
5345 CURLPROTO_SMTPS,
5346 #else
5348 #endif
5349 #if defined(CURLPROTO_RTSP)
5350 CURLPROTO_RTSP,
5351 #else
5353 #endif
5354 #if defined(CURLPROTO_RTMP)
5355 CURLPROTO_RTMP,
5356 #else
5358 #endif
5359 #if defined(CURLPROTO_RTMPT)
5360 CURLPROTO_RTMPT,
5361 #else
5363 #endif
5364 #if defined(CURLPROTO_RTMPE)
5365 CURLPROTO_RTMPE,
5366 #else
5368 #endif
5369 #if defined(CURLPROTO_RTMPTE)
5370 CURLPROTO_RTMPTE,
5371 #else
5373 #endif
5374 #if defined(CURLPROTO_RTMPS)
5375 CURLPROTO_RTMPS,
5376 #else
5378 #endif
5379 #if defined(CURLPROTO_RTMPTS)
5380 CURLPROTO_RTMPTS,
5381 #else
5383 #endif
5384 #if defined(CURLPROTO_GOPHER)
5385 CURLPROTO_GOPHER,
5386 #else
5388 #endif
5391 static void handleProtocolsOption(CURLoption curlopt, Connection *conn, value option)
5393 CAMLparam1(option);
5394 CURLcode result = CURLE_OK;
5395 long protocols = 0;
5396 int index;
5398 while (Val_emptylist != option)
5400 index = Int_val(Field(option, 0));
5401 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
5402 failwith("Invalid curl protocol");
5404 protocols = protocols | protoMap[index];
5406 option = Field(option, 1);
5409 result = curl_easy_setopt(conn->connection,
5410 curlopt,
5411 protocols);
5413 if (result != CURLE_OK)
5414 raiseError(conn, result);
5416 CAMLreturn0;
5419 static void handleProtocols(Connection *conn, value option)
5421 handleProtocolsOption(CURLOPT_PROTOCOLS, conn, option);
5424 static void handleRedirProtocols(Connection *conn, value option)
5426 handleProtocolsOption(CURLOPT_REDIR_PROTOCOLS, conn, option);
5429 #else
5430 #pragma message("libcurl does not implement CURLOPT_PROTOCOLS or CURLOPT_REDIR_PROTOCOLS")
5431 static void handleProtocols(Connection *conn, value option)
5433 failwith("libcurl does not implement CURLOPT_PROTOCOLS");
5435 static void handleRedirProtocols(Connection *conn, value option)
5437 failwith("libcurl does not implement CURLOPT_REDIR_PROTOCOLS");
5439 #endif
5441 #if HAVE_DECL_CURLOPT_RESOLVE
5442 static void handleResolve(Connection *conn, value option)
5444 CAMLparam1(option);
5445 CAMLlocal1(head);
5447 CURLcode result = CURLE_OK;
5449 free_curl_slist(conn->resolve);
5450 conn->resolve = NULL;
5452 head = option;
5454 while (head != Val_emptylist)
5456 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
5457 head = Field(head, 1);
5460 result = curl_easy_setopt(conn->connection,
5461 CURLOPT_RESOLVE,
5462 conn->resolve);
5464 if (result != CURLE_OK)
5465 raiseError(conn, result);
5467 CAMLreturn0;
5470 #else
5471 #pragma message("libcurl does not implement CURLOPT_RESOLVE")
5472 static void handleResolve(Connection *conn, value option)
5474 failwith("libcurl does not implement CURLOPT_RESOLVE");
5476 #endif
5478 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5479 static void handleDnsServers(Connection *conn, value option)
5481 CAMLparam1(option);
5483 CURLcode result = CURLE_OK;
5484 free_if(conn->dns_servers);
5486 conn->dns_servers = strdup(String_val(option));
5488 result = curl_easy_setopt(conn->connection,
5489 CURLOPT_DNS_SERVERS,
5490 conn->dns_servers);
5492 if (result != CURLE_OK)
5493 raiseError(conn, result);
5495 CAMLreturn0;
5497 #else
5498 #pragma message("libcurl does not implement CURLOPT_DNS_SERVERS")
5499 static void handleDnsServers(Connection *conn, value option)
5501 failwith("libcurl does not implement CURLOPT_DNS_SERVERS");
5503 #endif
5506 ** curl_easy_setopt helper function
5509 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5511 CAMLparam2(conn, option);
5512 CAMLlocal1(data);
5513 Connection *connection = Connection_val(conn);
5515 checkConnection(connection);
5517 if (Is_long(option))
5519 char error[128];
5521 sprintf(error, "Unimplemented Option: %s",
5522 findOption(unimplementedOptionMap,
5523 (CURLoption)(Long_val(option))));
5525 failwith(error);
5528 if (!Is_block(option))
5529 failwith("Not a block");
5531 if (Wosize_val(option) < 1)
5532 failwith("Insufficient data in block");
5534 data = Field(option, 0);
5536 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5537 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5538 data);
5539 else
5540 failwith("Invalid CURLOPT Option");
5542 CAMLreturn(Val_unit);
5546 ** curl_easy_perform helper function
5549 CAMLprim value helper_curl_easy_perform(value conn)
5551 CAMLparam1(conn);
5552 CURLcode result = CURLE_OK;
5553 Connection *connection = Connection_val(conn);
5555 checkConnection(connection);
5557 enter_blocking_section();
5558 result = curl_easy_perform(connection->connection);
5559 leave_blocking_section();
5561 if (result != CURLE_OK)
5562 raiseError(connection, result);
5564 CAMLreturn(Val_unit);
5568 ** curl_easy_cleanup helper function
5571 CAMLprim value helper_curl_easy_cleanup(value conn)
5573 CAMLparam1(conn);
5574 Connection *connection = Connection_val(conn);
5576 checkConnection(connection);
5578 removeConnection(connection);
5580 CAMLreturn(Val_unit);
5584 ** curl_easy_duphandle helper function
5587 CAMLprim value helper_curl_easy_duphandle(value conn)
5589 CAMLparam1(conn);
5590 CAMLlocal1(result);
5591 Connection *connection = Connection_val(conn);
5593 checkConnection(connection);
5595 result = caml_alloc(1, Abstract_tag);
5596 Field(result, 0) = (value)duplicateConnection(connection);
5598 CAMLreturn(result);
5602 ** curl_easy_getinfo helper function
5605 enum GetInfoResultType {
5606 StringValue, LongValue, DoubleValue, StringListValue
5609 value convertStringList(struct curl_slist *slist)
5611 CAMLparam0();
5612 CAMLlocal3(result, current, next);
5613 struct curl_slist *p = slist;
5615 result = Val_int(0);
5616 current = Val_int(0);
5617 next = Val_int(0);
5619 while (p != NULL)
5621 next = alloc_tuple(2);
5622 Store_field(next, 0, copy_string(p->data));
5623 Store_field(next, 1, Val_int(0));
5625 if (result == Val_int(0))
5626 result = next;
5628 if (current != Val_int(0))
5629 Store_field(current, 1, next);
5631 current = next;
5633 p = p->next;
5636 curl_slist_free_all(slist);
5638 CAMLreturn(result);
5641 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5643 CAMLparam2(conn, option);
5644 CAMLlocal1(result);
5645 CURLcode curlResult;
5646 Connection *connection = Connection_val(conn);
5647 enum GetInfoResultType resultType;
5648 char *strValue = NULL;
5649 double doubleValue;
5650 long longValue;
5651 struct curl_slist *stringListValue = NULL;
5653 checkConnection(connection);
5655 switch(Long_val(option))
5657 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5658 case 0: /* CURLINFO_EFFECTIVE_URL */
5659 resultType = StringValue;
5661 curlResult = curl_easy_getinfo(connection->connection,
5662 CURLINFO_EFFECTIVE_URL,
5663 &strValue);
5664 break;
5665 #else
5666 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5667 #endif
5669 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5670 case 1: /* CURLINFO_HTTP_CODE */
5671 case 2: /* CURLINFO_RESPONSE_CODE */
5672 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5673 resultType = LongValue;
5675 curlResult = curl_easy_getinfo(connection->connection,
5676 CURLINFO_RESPONSE_CODE,
5677 &longValue);
5678 #else
5679 resultType = LongValue;
5681 curlResult = curl_easy_getinfo(connection->connection,
5682 CURLINFO_HTTP_CODE,
5683 &longValue);
5684 #endif
5685 break;
5686 #endif
5688 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5689 case 3: /* CURLINFO_TOTAL_TIME */
5690 resultType = DoubleValue;
5692 curlResult = curl_easy_getinfo(connection->connection,
5693 CURLINFO_TOTAL_TIME,
5694 &doubleValue);
5695 break;
5696 #endif
5698 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5699 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5700 resultType = DoubleValue;
5702 curlResult = curl_easy_getinfo(connection->connection,
5703 CURLINFO_NAMELOOKUP_TIME,
5704 &doubleValue);
5705 break;
5706 #endif
5708 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5709 case 5: /* CURLINFO_CONNECT_TIME */
5710 resultType = DoubleValue;
5712 curlResult = curl_easy_getinfo(connection->connection,
5713 CURLINFO_CONNECT_TIME,
5714 &doubleValue);
5715 break;
5716 #endif
5718 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5719 case 6: /* CURLINFO_PRETRANSFER_TIME */
5720 resultType = DoubleValue;
5722 curlResult = curl_easy_getinfo(connection->connection,
5723 CURLINFO_PRETRANSFER_TIME,
5724 &doubleValue);
5725 break;
5726 #endif
5728 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5729 case 7: /* CURLINFO_SIZE_UPLOAD */
5730 resultType = DoubleValue;
5732 curlResult = curl_easy_getinfo(connection->connection,
5733 CURLINFO_SIZE_UPLOAD,
5734 &doubleValue);
5735 break;
5736 #endif
5738 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5739 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5740 resultType = DoubleValue;
5742 curlResult = curl_easy_getinfo(connection->connection,
5743 CURLINFO_SIZE_DOWNLOAD,
5744 &doubleValue);
5745 break;
5746 #endif
5748 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5749 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5750 resultType = DoubleValue;
5752 curlResult = curl_easy_getinfo(connection->connection,
5753 CURLINFO_SPEED_DOWNLOAD,
5754 &doubleValue);
5755 break;
5756 #endif
5758 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5759 case 10: /* CURLINFO_SPEED_UPLOAD */
5760 resultType = DoubleValue;
5762 curlResult = curl_easy_getinfo(connection->connection,
5763 CURLINFO_SPEED_UPLOAD,
5764 &doubleValue);
5765 break;
5767 #endif
5769 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5770 case 11: /* CURLINFO_HEADER_SIZE */
5771 resultType = LongValue;
5773 curlResult = curl_easy_getinfo(connection->connection,
5774 CURLINFO_HEADER_SIZE,
5775 &longValue);
5776 break;
5777 #endif
5779 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5780 case 12: /* CURLINFO_REQUEST_SIZE */
5781 resultType = LongValue;
5783 curlResult = curl_easy_getinfo(connection->connection,
5784 CURLINFO_REQUEST_SIZE,
5785 &longValue);
5786 break;
5787 #endif
5789 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5790 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5791 resultType = LongValue;
5793 curlResult = curl_easy_getinfo(connection->connection,
5794 CURLINFO_SSL_VERIFYRESULT,
5795 &longValue);
5796 break;
5797 #endif
5799 #if HAVE_DECL_CURLINFO_FILETIME
5800 case 14: /* CURLINFO_FILETIME */
5801 resultType = DoubleValue;
5803 curlResult = curl_easy_getinfo(connection->connection,
5804 CURLINFO_FILETIME,
5805 &longValue);
5807 doubleValue = longValue;
5808 break;
5809 #endif
5811 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5812 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5813 resultType = DoubleValue;
5815 curlResult = curl_easy_getinfo(connection->connection,
5816 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5817 &doubleValue);
5818 break;
5819 #endif
5821 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5822 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5823 resultType = DoubleValue;
5825 curlResult = curl_easy_getinfo(connection->connection,
5826 CURLINFO_CONTENT_LENGTH_UPLOAD,
5827 &doubleValue);
5828 break;
5829 #endif
5831 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5832 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5833 resultType = DoubleValue;
5835 curlResult = curl_easy_getinfo(connection->connection,
5836 CURLINFO_STARTTRANSFER_TIME,
5837 &doubleValue);
5838 break;
5839 #endif
5841 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5842 case 18: /* CURLINFO_CONTENT_TYPE */
5843 resultType = StringValue;
5845 curlResult = curl_easy_getinfo(connection->connection,
5846 CURLINFO_CONTENT_TYPE,
5847 &strValue);
5848 break;
5849 #endif
5851 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5852 case 19: /* CURLINFO_REDIRECT_TIME */
5853 resultType = DoubleValue;
5855 curlResult = curl_easy_getinfo(connection->connection,
5856 CURLINFO_REDIRECT_TIME,
5857 &doubleValue);
5858 break;
5859 #endif
5861 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5862 case 20: /* CURLINFO_REDIRECT_COUNT */
5863 resultType = LongValue;
5865 curlResult = curl_easy_getinfo(connection->connection,
5866 CURLINFO_REDIRECT_COUNT,
5867 &longValue);
5868 break;
5869 #endif
5871 #if HAVE_DECL_CURLINFO_PRIVATE
5872 case 21: /* CURLINFO_PRIVATE */
5873 resultType = StringValue;
5875 curlResult = curl_easy_getinfo(connection->connection,
5876 CURLINFO_PRIVATE,
5877 &strValue);
5878 break;
5879 #endif
5881 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5882 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5883 resultType = LongValue;
5885 curlResult = curl_easy_getinfo(connection->connection,
5886 CURLINFO_HTTP_CONNECTCODE,
5887 &longValue);
5888 break;
5889 #endif
5891 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5892 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5893 resultType = LongValue;
5895 curlResult = curl_easy_getinfo(connection->connection,
5896 CURLINFO_HTTPAUTH_AVAIL,
5897 &longValue);
5898 break;
5899 #endif
5901 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5902 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5903 resultType = LongValue;
5905 curlResult = curl_easy_getinfo(connection->connection,
5906 CURLINFO_PROXYAUTH_AVAIL,
5907 &longValue);
5908 break;
5909 #endif
5911 #if HAVE_DECL_CURLINFO_OS_ERRNO
5912 case 25: /* CURLINFO_OS_ERRNO */
5913 resultType = LongValue;
5915 curlResult = curl_easy_getinfo(connection->connection,
5916 CURLINFO_OS_ERRNO,
5917 &longValue);
5918 break;
5919 #endif
5921 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5922 case 26: /* CURLINFO_NUM_CONNECTS */
5923 resultType = LongValue;
5925 curlResult = curl_easy_getinfo(connection->connection,
5926 CURLINFO_NUM_CONNECTS,
5927 &longValue);
5928 break;
5929 #endif
5931 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5932 case 27: /* CURLINFO_SSL_ENGINES */
5933 resultType = StringListValue;
5935 curlResult = curl_easy_getinfo(connection->connection,
5936 CURLINFO_SSL_ENGINES,
5937 &stringListValue);
5938 break;
5939 #endif
5941 #if HAVE_DECL_CURLINFO_COOKIELIST
5942 case 28: /* CURLINFO_COOKIELIST */
5943 resultType = StringListValue;
5945 curlResult = curl_easy_getinfo(connection->connection,
5946 CURLINFO_COOKIELIST,
5947 &stringListValue);
5948 break;
5949 #endif
5951 #if HAVE_DECL_CURLINFO_LASTSOCKET
5952 case 29: /* CURLINFO_LASTSOCKET */
5953 resultType = LongValue;
5955 curlResult = curl_easy_getinfo(connection->connection,
5956 CURLINFO_LASTSOCKET,
5957 &longValue);
5958 break;
5959 #endif
5961 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5962 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5963 resultType = StringValue;
5965 curlResult = curl_easy_getinfo(connection->connection,
5966 CURLINFO_FTP_ENTRY_PATH,
5967 &strValue);
5968 break;
5969 #endif
5971 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5972 case 31: /* CURLINFO_REDIRECT_URL */
5973 resultType = StringValue;
5975 curlResult = curl_easy_getinfo(connection->connection,
5976 CURLINFO_REDIRECT_URL,
5977 &strValue);
5978 break;
5979 #else
5980 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5981 #endif
5983 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5984 case 32: /* CURLINFO_PRIMARY_IP */
5985 resultType = StringValue;
5987 curlResult = curl_easy_getinfo(connection->connection,
5988 CURLINFO_PRIMARY_IP,
5989 &strValue);
5990 break;
5991 #else
5992 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5993 #endif
5995 #if HAVE_DECL_CURLINFO_LOCAL_IP
5996 case 33: /* CURLINFO_LOCAL_IP */
5997 resultType = StringValue;
5999 curlResult = curl_easy_getinfo(connection->connection,
6000 CURLINFO_LOCAL_IP,
6001 &strValue);
6002 break;
6003 #else
6004 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
6005 #endif
6007 #if HAVE_DECL_CURLINFO_LOCAL_PORT
6008 case 34: /* CURLINFO_LOCAL_PORT */
6009 resultType = LongValue;
6011 curlResult = curl_easy_getinfo(connection->connection,
6012 CURLINFO_LOCAL_PORT,
6013 &longValue);
6014 break;
6015 #else
6016 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
6017 #endif
6019 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
6020 case 35: /* CURLINFO_CONDITION_UNMET */
6021 resultType = LongValue;
6023 curlResult = curl_easy_getinfo(connection->connection,
6024 CURLINFO_CONDITION_UNMET,
6025 &longValue);
6026 break;
6027 #else
6028 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
6029 #endif
6031 default:
6032 failwith("Invalid CURLINFO Option");
6033 break;
6036 if (curlResult != CURLE_OK)
6037 raiseError(connection, curlResult);
6039 switch (resultType)
6041 case StringValue:
6042 result = alloc(1, StringValue);
6043 Store_field(result, 0, copy_string(strValue?strValue:""));
6044 break;
6046 case LongValue:
6047 result = alloc(1, LongValue);
6048 Store_field(result, 0, Val_long(longValue));
6049 break;
6051 case DoubleValue:
6052 result = alloc(1, DoubleValue);
6053 Store_field(result, 0, copy_double(doubleValue));
6054 break;
6056 case StringListValue:
6057 result = alloc(1, StringListValue);
6058 Store_field(result, 0, convertStringList(stringListValue));
6059 break;
6062 CAMLreturn(result);
6066 ** curl_escape helper function
6069 CAMLprim value helper_curl_escape(value str)
6071 CAMLparam1(str);
6072 CAMLlocal1(result);
6073 char *curlResult;
6075 curlResult = curl_escape(String_val(str), string_length(str));
6076 result = copy_string(curlResult);
6077 free(curlResult);
6079 CAMLreturn(result);
6083 ** curl_unescape helper function
6086 CAMLprim value helper_curl_unescape(value str)
6088 CAMLparam1(str);
6089 CAMLlocal1(result);
6090 char *curlResult;
6092 curlResult = curl_unescape(String_val(str), string_length(str));
6093 result = copy_string(curlResult);
6094 free(curlResult);
6096 CAMLreturn(result);
6100 ** curl_getdate helper function
6103 CAMLprim value helper_curl_getdate(value str, value now)
6105 CAMLparam2(str, now);
6106 CAMLlocal1(result);
6107 time_t curlResult;
6108 time_t curlNow;
6110 curlNow = (time_t)Double_val(now);
6111 curlResult = curl_getdate(String_val(str), &curlNow);
6112 result = copy_double((double)curlResult);
6114 CAMLreturn(result);
6118 ** curl_version helper function
6121 CAMLprim value helper_curl_version(void)
6123 CAMLparam0();
6124 CAMLlocal1(result);
6125 char *str;
6127 str = curl_version();
6128 result = copy_string(str);
6130 CAMLreturn(result);
6133 struct CURLVersionBitsMapping
6135 int code;
6136 char *name;
6139 struct CURLVersionBitsMapping versionBitsMap[] =
6141 {CURL_VERSION_IPV6, "ipv6"},
6142 {CURL_VERSION_KERBEROS4, "kerberos4"},
6143 {CURL_VERSION_SSL, "ssl"},
6144 {CURL_VERSION_LIBZ, "libz"},
6145 {CURL_VERSION_NTLM, "ntlm"},
6146 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
6147 {CURL_VERSION_DEBUG, "debug"},
6148 {CURL_VERSION_CURLDEBUG, "curldebug"},
6149 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
6150 {CURL_VERSION_SPNEGO, "spnego"},
6151 {CURL_VERSION_LARGEFILE, "largefile"},
6152 {CURL_VERSION_IDN, "idn"},
6153 {CURL_VERSION_SSPI, "sspi"},
6154 {CURL_VERSION_CONV, "conv"},
6155 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
6156 {CURL_VERSION_TLSAUTH_SRP, "srp"},
6157 #endif
6158 #if HAVE_DECL_CURL_VERSION_NTLM_WB
6159 {CURL_VERSION_NTLM_WB, "wb"},
6160 #endif
6163 CAMLprim value caml_curl_version_info(value unit)
6165 CAMLparam1(unit);
6166 CAMLlocal4(v, vlist, vnum, vfeatures);
6167 const char* const* p = NULL;
6168 size_t i = 0;
6170 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
6171 if (NULL == data) caml_failwith("curl_version_info");
6173 vlist = Val_emptylist;
6174 for (p = data->protocols; NULL != *p; p++)
6176 vlist = Val_cons(vlist, caml_copy_string(*p));
6179 vfeatures = Val_emptylist;
6180 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
6182 if (0 != (versionBitsMap[i].code & data->features))
6183 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
6186 vnum = caml_alloc_tuple(3);
6187 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
6188 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
6189 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
6191 v = caml_alloc_tuple(12);
6192 Store_field(v,0,caml_copy_string(data->version));
6193 Store_field(v,1,vnum);
6194 Store_field(v,2,caml_copy_string(data->host));
6195 Store_field(v,3,vfeatures);
6196 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
6197 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
6198 Store_field(v,6,vlist);
6199 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
6200 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
6201 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
6202 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
6203 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
6205 CAMLreturn(v);
6208 CAMLprim value caml_curl_pause(value conn, value opts)
6210 CAMLparam2(conn, opts);
6211 CAMLlocal4(v, vlist, vnum, vfeatures);
6212 Connection *connection = Connection_val(conn);
6213 int bitmask = 0;
6214 CURLcode result;
6216 while (Val_emptylist != opts)
6218 switch (Int_val(Field(opts,0)))
6220 case 0: bitmask |= CURLPAUSE_SEND; break;
6221 case 1: bitmask |= CURLPAUSE_RECV; break;
6222 case 2: bitmask |= CURLPAUSE_ALL; break;
6223 default: caml_failwith("wrong pauseOption");
6225 opts = Field(opts,1);
6228 result = curl_easy_pause(connection->connection,bitmask);
6229 if (result != CURLE_OK)
6230 raiseError(connection, result);
6232 CAMLreturn(Val_unit);
6236 * Curl multi stack support
6238 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6239 * Other exported functions are prefixed with caml_curlm_, some of them
6240 * can/should be decomposed into smaller parts.
6243 struct ml_multi_handle
6245 CURLM* handle;
6246 value values; /* callbacks */
6249 enum
6251 curlmopt_socket_function,
6252 curlmopt_timer_function,
6254 /* last, not used */
6255 multi_values_total
6258 typedef struct ml_multi_handle ml_multi_handle;
6260 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6261 #define CURLM_val(v) (Multi_val(v)->handle)
6263 static struct custom_operations curl_multi_ops = {
6264 "ygrek.curl_multi",
6265 custom_finalize_default,
6266 custom_compare_default,
6267 custom_hash_default,
6268 custom_serialize_default,
6269 custom_deserialize_default,
6270 #if defined(custom_compare_ext_default)
6271 custom_compare_ext_default,
6272 #endif
6275 CAMLprim value caml_curl_multi_init(value unit)
6277 CAMLparam1(unit);
6278 CAMLlocal1(v);
6279 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6280 CURLM* h = curl_multi_init();
6282 if (!h)
6284 caml_stat_free(multi);
6285 failwith("caml_curl_multi_init");
6288 multi->handle = h;
6289 multi->values = caml_alloc(multi_values_total, 0);
6290 caml_register_generational_global_root(&multi->values);
6292 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6293 Multi_val(v) = multi;
6295 CAMLreturn(v);
6298 CAMLprim value caml_curl_multi_cleanup(value handle)
6300 CAMLparam1(handle);
6301 ml_multi_handle* h = Multi_val(handle);
6303 if (NULL == h)
6304 CAMLreturn(Val_unit);
6306 caml_remove_generational_global_root(&h->values);
6308 if (CURLM_OK != curl_multi_cleanup(h->handle))
6309 failwith("caml_curl_multi_cleanup");
6311 Multi_val(handle) = (ml_multi_handle*)NULL;
6313 CAMLreturn(Val_unit);
6316 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6318 int msgs_in_queue = 0;
6320 while (1)
6322 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6323 if (NULL == msg) return NULL;
6324 if (CURLMSG_DONE == msg->msg)
6326 CURL* easy_handle = msg->easy_handle;
6327 if (result) *result = msg->data.result;
6328 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6330 /*failwith("curlm_remove_finished");*/
6332 return easy_handle;
6337 CAMLprim value caml_curlm_remove_finished(value v_multi)
6339 CAMLparam1(v_multi);
6340 CAMLlocal2(v_easy, v_tuple);
6341 CURL* handle;
6342 CURLM* multi_handle;
6343 CURLcode result;
6345 multi_handle = CURLM_val(v_multi);
6347 caml_enter_blocking_section();
6348 handle = curlm_remove_finished(multi_handle,&result);
6349 caml_leave_blocking_section();
6351 if (NULL == handle)
6353 CAMLreturn(Val_none);
6355 else
6357 /* not good: same handle, but different block */
6358 v_easy = caml_alloc(1, Abstract_tag);
6359 Field(v_easy, 0) = (value)findConnection(handle);
6360 v_tuple = caml_alloc(2, 0);
6361 Store_field(v_tuple,0,v_easy);
6362 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6363 CAMLreturn(Val_some(v_tuple));
6367 static int curlm_wait_data(CURLM* multi_handle)
6369 struct timeval timeout;
6370 CURLMcode ret;
6372 fd_set fdread;
6373 fd_set fdwrite;
6374 fd_set fdexcep;
6375 int maxfd = -1;
6377 FD_ZERO(&fdread);
6378 FD_ZERO(&fdwrite);
6379 FD_ZERO(&fdexcep);
6381 /* set a suitable timeout */
6382 timeout.tv_sec = 1;
6383 timeout.tv_usec = 0;
6385 /* get file descriptors from the transfers */
6386 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6388 if (ret == CURLM_OK && maxfd >= 0)
6390 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6391 if (-1 != rc) return 0;
6393 return 1;
6396 CAMLprim value caml_curlm_wait_data(value v_multi)
6398 CAMLparam1(v_multi);
6399 int ret;
6400 CURLM* h = CURLM_val(v_multi);
6402 caml_enter_blocking_section();
6403 ret = curlm_wait_data(h);
6404 caml_leave_blocking_section();
6406 CAMLreturn(Val_bool(0 == ret));
6409 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6411 CAMLparam2(v_multi,v_easy);
6412 CURLM* multi = CURLM_val(v_multi);
6413 CURL* easy = Connection_val(v_easy)->connection;
6415 /* may invoke callbacks so need to be consistent with locks */
6416 caml_enter_blocking_section();
6417 if (CURLM_OK != curl_multi_add_handle(multi, easy))
6419 caml_leave_blocking_section();
6420 failwith("caml_curl_multi_add_handle");
6422 caml_leave_blocking_section();
6424 CAMLreturn(Val_unit);
6427 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6429 CAMLparam1(v_multi);
6430 int still_running = 0;
6431 CURLM* h = CURLM_val(v_multi);
6433 caml_enter_blocking_section();
6434 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6435 caml_leave_blocking_section();
6437 CAMLreturn(Val_int(still_running));
6440 CAMLprim value helper_curl_easy_strerror(value v_code)
6442 CAMLparam1(v_code);
6443 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6447 * Wrappers for the curl_multi_socket_action infrastructure
6448 * Based on curl hiperfifo.c example
6451 /* FIXME win32unix */
6452 #define Socket_val(v) Int_val(v)
6453 #define Val_socket(v) Val_int(v)
6455 static void raise_error(char const* msg)
6457 static value* exception = NULL;
6459 if (NULL == exception)
6461 exception = caml_named_value("Curl.Multi.Error");
6462 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6465 caml_raise_with_string(*exception, msg);
6468 static void check_mcode(CURLMcode code)
6470 char const *s = NULL;
6471 switch (code)
6473 case CURLM_OK : return;
6474 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6475 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6476 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6477 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6478 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6479 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6480 case CURLM_LAST : s="CURLM_LAST"; break;
6481 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6482 default : s="CURLM_unknown"; break;
6484 raise_error(s);
6487 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6489 CAMLparam3(v_multi, v_fd, v_kind);
6490 CURLM* h = CURLM_val(v_multi);
6491 int still_running = 0;
6492 CURLMcode rc = CURLM_OK;
6493 int socket = Socket_val(v_fd);
6494 int kind = 0;
6496 switch (Int_val(v_kind))
6498 case 0 : break;
6499 case 1 : kind |= CURL_CSELECT_IN; break;
6500 case 2 : kind |= CURL_CSELECT_OUT; break;
6501 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6502 default:
6503 raise_error("caml_curl_multi_socket_action");
6506 /* fprintf(stdout,"fd %u kind %u\n",Socket_val(v_fd), kind); fflush(stdout); */
6508 caml_enter_blocking_section();
6509 do {
6510 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6511 } while (rc == CURLM_CALL_MULTI_PERFORM);
6512 caml_leave_blocking_section();
6514 check_mcode(rc);
6516 CAMLreturn(Val_int(still_running));
6519 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6521 CAMLparam1(v_multi);
6522 int still_running = 0;
6523 CURLMcode rc = CURLM_OK;
6524 CURLM* h = CURLM_val(v_multi);
6526 caml_enter_blocking_section();
6527 do {
6528 rc = curl_multi_socket_all(h, &still_running);
6529 } while (rc == CURLM_CALL_MULTI_PERFORM);
6530 caml_leave_blocking_section();
6532 check_mcode(rc);
6534 CAMLreturn(Val_int(still_running));
6537 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6539 CAMLparam0();
6540 CAMLlocal1(v_what);
6541 (void)e;
6542 (void)sockp; /* not used */
6544 /* v_what = Val_int(what); */
6545 switch (what)
6547 case CURL_POLL_NONE : v_what = Val_int(0); break;
6548 case CURL_POLL_IN : v_what = Val_int(1); break;
6549 case CURL_POLL_OUT : v_what = Val_int(2); break;
6550 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6551 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6552 default:
6553 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6554 fflush(stderr);
6555 raise_error("curlm_sock_cb"); /* FIXME exception from callback */
6558 caml_callback2(Field(multi->values,curlmopt_socket_function),
6559 Val_socket(sock), v_what);
6561 CAMLreturn(0);
6564 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6566 int ret;
6567 caml_leave_blocking_section();
6568 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6569 caml_enter_blocking_section();
6570 return ret;
6573 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6575 CAMLparam2(v_multi, v_cb);
6576 ml_multi_handle* multi = Multi_val(v_multi);
6578 Store_field(multi->values, curlmopt_socket_function, v_cb);
6580 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6581 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6583 CAMLreturn(Val_unit);
6586 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6588 CAMLparam0();
6589 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6590 CAMLreturn0;
6593 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6595 (void)multi;
6597 caml_leave_blocking_section();
6598 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6599 caml_enter_blocking_section();
6600 return 0;
6603 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6605 CAMLparam2(v_multi, v_cb);
6606 ml_multi_handle* multi = Multi_val(v_multi);
6608 Store_field(multi->values, curlmopt_timer_function, v_cb);
6610 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6611 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6613 CAMLreturn(Val_unit);
6616 CAMLprim value caml_curl_multi_timeout(value v_multi)
6618 CAMLparam1(v_multi);
6619 long ms = 0;
6620 CURLMcode rc = CURLM_OK;
6621 ml_multi_handle* multi = Multi_val(v_multi);
6623 rc = curl_multi_timeout(multi->handle, &ms);
6625 check_mcode(rc);
6627 CAMLreturn(Val_long(ms));