release 0.6.0
[ocurl.git] / curl-helper.c
blob78e84947ffd84f535588d01dedfb0bdafa96efbf
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 <curl/curl.h>
14 #include <caml/alloc.h>
15 #include <caml/memory.h>
16 #include <caml/mlvalues.h>
17 #include <caml/callback.h>
18 #include <caml/fail.h>
19 #include <caml/custom.h>
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #else
24 #pragma message("No config file given.")
25 #endif
27 #if defined(_MSC_VER)
28 #ifdef interface
29 #undef interface
30 #endif
31 #endif
33 void leave_blocking_section(void);
34 void enter_blocking_section(void);
36 #define Val_none Val_int(0)
38 static __inline value
39 Val_some( value v )
41 CAMLparam1( v );
42 CAMLlocal1( some );
43 some = caml_alloc(1, 0);
44 Store_field( some, 0, v );
45 CAMLreturn( some );
48 static value Val_pair(value v1, value v2)
50 CAMLparam2(v1,v2);
51 CAMLlocal1(pair);
52 pair = caml_alloc_small(2,0);
53 Field(pair,0) = v1;
54 Field(pair,1) = v2;
55 CAMLreturn(pair);
58 static value Val_cons(value list, value v) { return Val_pair(v,list); }
60 typedef struct Connection Connection;
61 typedef struct ConnectionList ConnectionList;
63 #define Connection_val(v) ((Connection *)Field(v, 0))
65 enum OcamlValues
67 OcamlWriteCallback,
68 OcamlReadCallback,
69 OcamlErrorBuffer,
70 OcamlPostFields,
71 OcamlHTTPHeader,
72 OcamlHTTPPost,
73 OcamlQuote,
74 OcamlPostQuote,
75 OcamlHeaderCallback,
76 OcamlProgressCallback,
77 OcamlDebugCallback,
78 OcamlHTTP200Aliases,
79 OcamlIOCTLCallback,
80 OcamlSeekFunctionCallback,
81 OcamlOpenSocketFunctionCallback,
83 OcamlURL,
84 OcamlProxy,
85 OcamlUserPWD,
86 OcamlProxyUserPWD,
87 OcamlRange,
88 OcamlReferer,
89 OcamlUserAgent,
90 OcamlFTPPort,
91 OcamlCookie,
92 OcamlHTTPPostStrings,
93 OcamlSSLCert,
94 OcamlSSLCertType,
95 OcamlSSLCertPasswd,
96 OcamlSSLKey,
97 OcamlSSLKeyType,
98 OcamlSSLKeyPasswd,
99 OcamlSSLEngine,
100 OcamlCookieFile,
101 OcamlCustomRequest,
102 OcamlInterface,
103 OcamlCAInfo,
104 OcamlCAPath,
105 OcamlRandomFile,
106 OcamlEGDSocket,
107 OcamlCookieJar,
108 OcamlSSLCipherList,
109 OcamlPrivate,
110 OcamlNETRCFile,
111 OcamlFTPAccount,
112 OcamlCookieList,
113 OcamlFTPAlternativeToUser,
114 OcamlSSHPublicKeyFile,
115 OcamlSSHPrivateKeyFile,
116 OcamlSSHHostPublicKeyMD5,
117 OcamlCopyPostFields,
119 /* Not used, last for size */
120 OcamlValuesSize
123 struct Connection
125 CURL *connection;
126 Connection *next;
127 Connection *prev;
129 value ocamlValues;
131 char *url;
132 char *proxy;
133 char *userPwd;
134 char *proxyUserPwd;
135 char *range;
136 char *errorBuffer;
137 char *postFields;
138 int postFieldSize;
139 char *referer;
140 char *userAgent;
141 char *ftpPort;
142 char *cookie;
143 struct curl_slist *httpHeader;
144 struct curl_httppost *httpPostFirst;
145 struct curl_httppost *httpPostLast;
146 struct curl_slist *httpPostStrings;
147 struct curl_slist *resolve;
148 char *sslCert;
149 char *sslCertType;
150 char *sslCertPasswd;
151 char *sslKey;
152 char *sslKeyType;
153 char *sslKeyPasswd;
154 char *sslEngine;
155 struct curl_slist *quote;
156 struct curl_slist *postQuote;
157 char *cookieFile;
158 char *customRequest;
159 char *interface;
160 char *caInfo;
161 char *caPath;
162 char *randomFile;
163 char *egdSocket;
164 char *cookieJar;
165 char *sslCipherList;
166 char *private;
167 struct curl_slist *http200Aliases;
168 char *netrcFile;
169 char *ftpaccount;
170 char *cookielist;
171 char *ftpAlternativeToUser;
172 char *sshPublicKeyFile;
173 char *sshPrivateKeyFile;
174 char *sshHostPublicKeyMD5;
175 char *copyPostFields;
176 char *dns_servers;
179 struct ConnectionList
181 Connection *head;
182 Connection *tail;
185 static ConnectionList connectionList = {NULL, NULL};
187 typedef struct CURLErrorMapping CURLErrorMapping;
189 struct CURLErrorMapping
191 char *name;
192 CURLcode error;
195 CURLErrorMapping errorMap[] =
197 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
198 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
199 #else
200 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
201 #endif
202 #if HAVE_DECL_CURLE_FAILED_INIT
203 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
204 #else
205 {"CURLE_FAILED_INIT", -1},
206 #endif
207 #if HAVE_DECL_CURLE_URL_MALFORMAT
208 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
209 #else
210 {"CURLE_URL_MALFORMAT", -1},
211 #endif
212 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
213 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
214 #else
215 {"CURLE_URL_MALFORMAT_USER", -1},
216 #endif
217 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
218 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
219 #else
220 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
221 #endif
222 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
223 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
224 #else
225 {"CURLE_COULDNT_RESOLVE_HOST", -1},
226 #endif
227 #if HAVE_DECL_CURLE_COULDNT_CONNECT
228 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
229 #else
230 {"CURLE_COULDNT_CONNECT", -1},
231 #endif
232 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
233 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
234 #else
235 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
236 #endif
237 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
238 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
239 #else
240 {"CURLE_FTP_ACCESS_DENIED", -1},
241 #endif
242 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
243 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
244 #else
245 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
246 #endif
247 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
248 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
249 #else
250 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
251 #endif
252 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
253 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
254 #else
255 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
256 #endif
257 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
258 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
259 #else
260 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
261 #endif
262 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
263 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
264 #else
265 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
266 #endif
267 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
268 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
269 #else
270 {"CURLE_FTP_CANT_GET_HOST", -1},
271 #endif
272 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
273 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
274 #else
275 {"CURLE_FTP_CANT_RECONNECT", -1},
276 #endif
277 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
278 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
279 #else
280 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
281 #endif
282 #if HAVE_DECL_CURLE_PARTIAL_FILE
283 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
284 #else
285 {"CURLE_PARTIAL_FILE", -1},
286 #endif
287 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
288 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
289 #else
290 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
291 #endif
292 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
293 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
294 #else
295 {"CURLE_FTP_WRITE_ERROR", -1},
296 #endif
297 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
298 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
299 #else
300 {"CURLE_FTP_QUOTE_ERROR", -1},
301 #endif
302 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
303 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
304 #else
305 {"CURLE_HTTP_NOT_FOUND", -1},
306 #endif
307 #if HAVE_DECL_CURLE_WRITE_ERROR
308 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
309 #else
310 {"CURLE_WRITE_ERROR", -1},
311 #endif
312 #if HAVE_DECL_CURLE_MALFORMAT_USER
313 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
314 #else
315 {"CURLE_MALFORMAT_USER", -1},
316 #endif
317 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
318 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
319 #else
320 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
321 #endif
322 #if HAVE_DECL_CURLE_READ_ERROR
323 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
324 #else
325 {"CURLE_READ_ERROR", -1},
326 #endif
327 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
328 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
329 #else
330 {"CURLE_OUT_OF_MEMORY", -1},
331 #endif
332 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
333 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
334 #else
335 {"CURLE_OPERATION_TIMEOUTED", -1},
336 #endif
337 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
338 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
339 #else
340 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
341 #endif
342 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
343 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
344 #else
345 {"CURLE_FTP_PORT_FAILED", -1},
346 #endif
347 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
348 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
349 #else
350 {"CURLE_FTP_COULDNT_USE_REST", -1},
351 #endif
352 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
353 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
354 #else
355 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
356 #endif
357 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
358 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
359 #else
360 {"CURLE_HTTP_RANGE_ERROR", -1},
361 #endif
362 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
363 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
364 #else
365 {"CURLE_HTTP_POST_ERROR", -1},
366 #endif
367 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
368 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
369 #else
370 {"CURLE_SSL_CONNECT_ERROR", -1},
371 #endif
372 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
373 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
374 #else
375 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
376 #endif
377 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
378 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
379 #else
380 {"CURLE_FILE_COULDNT_READ_FILE", -1},
381 #endif
382 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
383 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
384 #else
385 {"CURLE_LDAP_CANNOT_BIND", -1},
386 #endif
387 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
388 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
389 #else
390 {"CURLE_LDAP_SEARCH_FAILED", -1},
391 #endif
392 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
393 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
394 #else
395 {"CURLE_LIBRARY_NOT_FOUND", -1},
396 #endif
397 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
398 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
399 #else
400 {"CURLE_FUNCTION_NOT_FOUND", -1},
401 #endif
402 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
403 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
404 #else
405 {"CURLE_ABORTED_BY_CALLBACK", -1},
406 #endif
407 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
408 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
409 #else
410 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
411 #endif
412 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
413 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
414 #else
415 {"CURLE_BAD_CALLING_ORDER", -1},
416 #endif
417 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
418 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
419 #else
420 {"CURLE_HTTP_PORT_FAILED", -1},
421 #endif
422 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
423 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
424 #else
425 {"CURLE_BAD_PASSWORD_ENTERED", -1},
426 #endif
427 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
428 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
429 #else
430 {"CURLE_TOO_MANY_REDIRECTS", -1},
431 #endif
432 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
433 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
434 #else
435 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
436 #endif
437 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
438 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
439 #else
440 {"CURLE_TELNET_OPTION_SYNTAX", -1},
441 #endif
442 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
443 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
444 #else
445 {"CURLE_SSL_PEER_CERTIFICATE", -1},
446 #endif
447 #if HAVE_DECL_CURLE_GOT_NOTHING
448 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
449 #else
450 {"CURLE_GOT_NOTHING", -1},
451 #endif
452 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
453 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
454 #else
455 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
456 #endif
457 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
458 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
459 #else
460 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
461 #endif
462 #if HAVE_DECL_CURLE_SEND_ERROR
463 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
464 #else
465 {"CURLE_SEND_ERROR", -1},
466 #endif
467 #if HAVE_DECL_CURLE_RECV_ERROR
468 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
469 #else
470 {"CURLE_RECV_ERROR", -1},
471 #endif
472 #if HAVE_DECL_CURLE_SHARE_IN_USE
473 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
474 #else
475 {"CURLE_SHARE_IN_USE", -1},
476 #endif
477 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
478 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
479 #else
480 {"CURLE_SSL_CERTPROBLEN", -1},
481 #endif
482 #if HAVE_DECL_CURLE_SSL_CIPHER
483 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
484 #else
485 {"CURLE_SSL_CIPHER", -1},
486 #endif
487 #if HAVE_DECL_CURLE_SSL_CACERT
488 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
489 #else
490 {"CURLE_SSL_CACERT", -1},
491 #endif
492 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
493 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
494 #else
495 {"CURLE_BAD_CONTENT_ENCODING", -1},
496 #endif
497 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
498 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
499 #else
500 {"CURLE_LDAP_INVALID_URL", -1},
501 #endif
502 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
503 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
504 #else
505 {"CURLE_FILESIZE_EXCEEDED", -1},
506 #endif
507 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
508 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
509 #else
510 {"CURLE_FTP_SSL_FAILED", -1},
511 #endif
512 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
513 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
514 #else
515 {"CURLE_SEND_FAIL_REWIND", -1},
516 #endif
517 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
518 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
519 #else
520 {"CURLE_SSL_ENGINE_INITFAILED", -1},
521 #endif
522 #if HAVE_DECL_CURLE_LOGIN_DENIED
523 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
524 #else
525 {"CURLE_LOGIN_DENIED", -1},
526 #endif
527 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
528 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
529 #else
530 {"CURLE_TFTP_NOTFOUND", -1},
531 #endif
532 #if HAVE_DECL_CURLE_TFTP_PERM
533 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
534 #else
535 {"CURLE_TFTP_PERM", -1},
536 #endif
537 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
538 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
539 #else
540 {"CURLE_REMOTE_DISK_FULL", -1},
541 #endif
542 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
543 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
544 #else
545 {"CURLE_TFTP_ILLEGAL", -1},
546 #endif
547 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
548 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
549 #else
550 {"CURLE_TFTP_UNKNOWNID", -1},
551 #endif
552 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
553 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
554 #else
555 {"CURLE_REMOTE_FILE_EXISTS", -1},
556 #endif
557 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
558 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
559 #else
560 {"CURLE_TFTP_NOSUCHUSER", -1},
561 #endif
562 #if HAVE_DECL_CURLE_CONV_FAILED
563 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
564 #else
565 {"CURLE_CONV_FAILED", -1},
566 #endif
567 #if HAVE_DECL_CURLE_CONV_REQUIRED
568 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
569 #else
570 {"CURLE_CONV_REQUIRED", -1},
571 #endif
572 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
573 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
574 #else
575 {"CURLE_SSL_CACERT_BADFILE", -1},
576 #endif
577 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
578 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
579 #else
580 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
581 #endif
582 #if HAVE_DECL_CURLE_SSH
583 {"CURLE_SSH", CURLE_SSH},
584 #else
585 {"CURLE_SSH", -1},
586 #endif
587 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
588 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
589 #else
590 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
591 #endif
592 #if HAVE_DECL_CURLE_AGAIN
593 {"CURLE_AGAIN", CURLE_AGAIN},
594 #else
595 {"CURLE_AGAIN", -1},
596 #endif
597 {"CURLE_OK", CURLE_OK},
598 {NULL, 0}
601 typedef struct CURLOptionMapping CURLOptionMapping;
603 struct CURLOptionMapping
605 void (*optionHandler)(Connection *, value);
606 char *name;
607 CURLoption option;
610 CURLOptionMapping unimplementedOptionMap[] =
612 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
613 {NULL, NULL, 0}
616 static void handleWriteFunction(Connection *, value);
617 static void handleReadFunction(Connection *, value);
618 static void handleInFileSize(Connection *, value);
619 static void handleURL(Connection *, value);
620 static void handleProxy(Connection *, value);
621 static void handleProxyPort(Connection *, value);
622 static void handleHTTPProxyTunnel(Connection *, value);
623 static void handleVerbose(Connection *, value);
624 static void handleHeader(Connection *, value);
625 static void handleNoProgress(Connection *, value);
626 static void handleNoSignal(Connection *, value);
627 static void handleNoBody(Connection *, value);
628 static void handleFailOnError(Connection *, value);
629 static void handleUpload(Connection *, value);
630 static void handlePost(Connection *, value);
631 static void handleFTPListOnly(Connection *, value);
632 static void handleFTPAppend(Connection *, value);
633 static void handleNETRC(Connection *, value);
634 static void handleEncoding(Connection *, value);
635 static void handleFollowLocation(Connection *, value);
636 static void handleTransferText(Connection *, value);
637 static void handlePut(Connection *, value);
638 static void handleUserPwd(Connection *, value);
639 static void handleProxyUserPwd(Connection *, value);
640 static void handleRange(Connection *, value);
641 static void handleErrorBuffer(Connection *, value);
642 static void handleTimeout(Connection *, value);
643 static void handlePostFields(Connection *, value);
644 static void handlePostFieldSize(Connection *, value);
645 static void handleReferer(Connection *, value);
646 static void handleUserAgent(Connection *, value);
647 static void handleFTPPort(Connection *, value);
648 static void handleLowSpeedLimit(Connection *, value);
649 static void handleLowSpeedTime(Connection *, value);
650 static void handleResumeFrom(Connection *, value);
651 static void handleCookie(Connection *, value);
652 static void handleHTTPHeader(Connection *, value);
653 static void handleHTTPPost(Connection *, value);
654 static void handleSSLCert(Connection *, value);
655 static void handleSSLCertType(Connection *, value);
656 static void handleSSLCertPasswd(Connection *, value);
657 static void handleSSLKey(Connection *, value);
658 static void handleSSLKeyType(Connection *, value);
659 static void handleSSLKeyPasswd(Connection *, value);
660 static void handleSSLEngine(Connection *, value);
661 static void handleSSLEngineDefault(Connection *, value);
662 static void handleCRLF(Connection *, value);
663 static void handleQuote(Connection *, value);
664 static void handlePostQuote(Connection *, value);
665 static void handleHeaderFunction(Connection *, value);
666 static void handleCookieFile(Connection *, value);
667 static void handleSSLVersion(Connection *, value);
668 static void handleTimeCondition(Connection *, value);
669 static void handleTimeValue(Connection *, value);
670 static void handleCustomRequest(Connection *, value);
671 static void handleInterface(Connection *, value);
672 static void handleKRB4Level(Connection *, value);
673 static void handleProgressFunction(Connection *, value);
674 static void handleSSLVerifyPeer(Connection *, value);
675 static void handleCAInfo(Connection *, value);
676 static void handleCAPath(Connection *, value);
677 static void handleFileTime(Connection *, value);
678 static void handleMaxRedirs(Connection *, value);
679 static void handleMaxConnects(Connection *, value);
680 static void handleClosePolicy(Connection *, value);
681 static void handleFreshConnect(Connection *, value);
682 static void handleForbidReuse(Connection *, value);
683 static void handleRandomFile(Connection *, value);
684 static void handleEGDSocket(Connection *, value);
685 static void handleConnectTimeout(Connection *, value);
686 static void handleHTTPGet(Connection *, value);
687 static void handleSSLVerifyHost(Connection *, value);
688 static void handleCookieJar(Connection *, value);
689 static void handleSSLCipherList(Connection *, value);
690 static void handleHTTPVersion(Connection *, value);
691 static void handleFTPUseEPSV(Connection *, value);
692 static void handleDNSCacheTimeout(Connection *, value);
693 static void handleDNSUseGlobalCache(Connection *, value);
694 static void handleDebugFunction(Connection *, value);
695 static void handlePrivate(Connection *, value);
696 static void handleHTTP200Aliases(Connection *, value);
697 static void handleUnrestrictedAuth(Connection *, value);
698 static void handleFTPUseEPRT(Connection *, value);
699 static void handleHTTPAuth(Connection *, value);
700 static void handleFTPCreateMissingDirs(Connection *, value);
701 static void handleProxyAuth(Connection *, value);
702 static void handleFTPResponseTimeout(Connection *, value);
703 static void handleIPResolve(Connection *, value);
704 static void handleMaxFileSize(Connection *, value);
705 static void handleInFileSizeLarge(Connection *, value);
706 static void handleResumeFromLarge(Connection *, value);
707 static void handleMaxFileSizeLarge(Connection *, value);
708 static void handleNETRCFile(Connection *, value);
709 static void handleFTPSSL(Connection *, value);
710 static void handlePostFieldSizeLarge(Connection *, value);
711 static void handleTCPNoDelay(Connection *, value);
712 static void handleFTPSSLAuth(Connection *, value);
713 static void handleIOCTLFunction(Connection *, value);
714 static void handleFTPAccount(Connection *, value);
715 static void handleCookieList(Connection *, value);
716 static void handleIgnoreContentLength(Connection *, value);
717 static void handleFTPSkipPASVIP(Connection *, value);
718 static void handleFTPFileMethod(Connection *, value);
719 static void handleLocalPort(Connection *, value);
720 static void handleLocalPortRange(Connection *, value);
721 static void handleConnectOnly(Connection *, value);
722 static void handleMaxSendSpeedLarge(Connection *, value);
723 static void handleMaxRecvSpeedLarge(Connection *, value);
724 static void handleFTPAlternativeToUser(Connection *, value);
725 static void handleSSLSessionIdCache(Connection *, value);
726 static void handleSSHAuthTypes(Connection *, value);
727 static void handleSSHPublicKeyFile(Connection *, value);
728 static void handleSSHPrivateKeyFile(Connection *, value);
729 static void handleFTPSSLCCC(Connection *, value);
730 static void handleTimeoutMS(Connection *, value);
731 static void handleConnectTimeoutMS(Connection *, value);
732 static void handleHTTPTransferDecoding(Connection *, value);
733 static void handleHTTPContentDecoding(Connection *, value);
734 static void handleNewFilePerms(Connection *, value);
735 static void handleNewDirectoryPerms(Connection *, value);
736 static void handlePost301(Connection *, value);
737 static void handleSSHHostPublicKeyMD5(Connection *, value);
738 static void handleCopyPostFields(Connection *, value);
739 static void handleProxyTransferMode(Connection *, value);
740 static void handleSeekFunction(Connection *, value);
741 static void handleAutoReferer(Connection *, value);
742 static void handleOpenSocketFunction(Connection *, value);
743 static void handleProxyType(Connection *, value);
744 static void handleProtocols(Connection *, value);
745 static void handleRedirProtocols(Connection *, value);
746 static void handleResolve(Connection *, value);
747 static void handleDnsServers(Connection *, value);
749 CURLOptionMapping implementedOptionMap[] =
751 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
752 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
753 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
754 {handleURL, "CURLOPT_URL", CURLOPT_URL},
755 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
756 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
757 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
758 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
759 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
760 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
761 #if HAVE_DECL_CURLOPT_NOSIGNAL
762 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
763 #else
764 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
765 #endif
766 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
767 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
768 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
769 {handlePost, "CURLOPT_POST", CURLOPT_POST},
770 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
771 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
772 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
773 #if HAVE_DECL_CURLOPT_ENCODING
774 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
775 #else
776 {handleEncoding, "CURLOPT_ENCODING", 0},
777 #endif
778 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
779 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
780 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
781 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
782 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
783 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
784 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
785 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
786 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
787 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
788 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
789 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
790 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
791 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
792 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
793 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
794 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
795 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
796 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
797 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
798 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
799 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
800 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
801 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
802 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
803 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
804 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
805 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
806 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
807 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
808 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
809 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
810 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
811 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
812 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
813 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
814 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
815 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
816 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
817 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
818 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
819 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
820 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
821 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
822 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
823 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
824 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
825 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
826 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
827 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
828 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
829 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
830 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
831 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
832 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
833 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
834 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
835 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
836 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
837 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
838 #if HAVE_DECL_CURLOPT_PRIVATE
839 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
840 #else
841 {handlePrivate, "CURLOPT_PRIVATE", 0},
842 #endif
843 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
844 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
845 #else
846 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
847 #endif
848 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
849 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
850 #else
851 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
852 #endif
853 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
854 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
855 #else
856 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
857 #endif
858 #if HAVE_DECL_CURLOPT_HTTPAUTH
859 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
860 #else
861 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
862 #endif
863 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
864 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
865 #else
866 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
867 #endif
868 #if HAVE_DECL_CURLOPT_PROXYAUTH
869 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
870 #else
871 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
872 #endif
873 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
874 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
875 #else
876 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
877 #endif
878 #if HAVE_DECL_CURLOPT_IPRESOLVE
879 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
880 #else
881 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
882 #endif
883 #if HAVE_DECL_CURLOPT_MAXFILESIZE
884 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
885 #else
886 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
887 #endif
888 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
889 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
890 #else
891 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
892 #endif
893 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
894 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
895 #else
896 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
897 #endif
898 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
899 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
900 #else
901 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
902 #endif
903 #if HAVE_DECL_CURLOPT_NETRC_FILE
904 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
905 #else
906 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
907 #endif
908 #if HAVE_DECL_CURLOPT_FTP_SSL
909 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
910 #else
911 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
912 #endif
913 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
914 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
915 #else
916 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
917 #endif
918 #if HAVE_DECL_CURLOPT_TCP_NODELAY
919 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
920 #else
921 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
922 #endif
923 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
924 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
925 #else
926 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
927 #endif
928 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
929 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
930 #else
931 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
932 #endif
933 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
934 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
935 #else
936 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
937 #endif
938 #if HAVE_DECL_CURLOPT_COOKIELIST
939 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
940 #else
941 {handleCookieList, "CURLOPT_COOKIELIST", 0},
942 #endif
943 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
944 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
945 #else
946 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
947 #endif
948 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
949 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
950 #else
951 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
952 #endif
953 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
954 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
955 #else
956 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
957 #endif
958 #if HAVE_DECL_CURLOPT_LOCALPORT
959 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
960 #else
961 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
962 #endif
963 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
964 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
965 #else
966 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
967 #endif
968 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
969 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
970 #else
971 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
972 #endif
973 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
974 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
975 #else
976 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
977 #endif
978 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
979 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
980 #else
981 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
982 #endif
983 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
984 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
985 #else
986 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
987 #endif
988 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
989 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
990 #else
991 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
992 #endif
993 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
994 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
995 #else
996 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
997 #endif
998 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
999 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
1000 #else
1001 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
1002 #endif
1003 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
1004 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
1005 #else
1006 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
1007 #endif
1008 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
1009 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
1010 #else
1011 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
1012 #endif
1013 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
1014 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
1015 #else
1016 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
1017 #endif
1018 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
1019 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
1020 #else
1021 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
1022 #endif
1023 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1024 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1025 #else
1026 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1027 #endif
1028 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1029 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1030 #else
1031 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1032 #endif
1033 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1034 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1035 #else
1036 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1037 #endif
1038 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1039 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1040 #else
1041 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1042 #endif
1043 #if HAVE_DECL_CURLOPT_POST301
1044 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1045 #else
1046 {handlePost301, "CURLOPT_POST301", 0},
1047 #endif
1048 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1049 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1050 #else
1051 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1052 #endif
1053 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1054 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1055 #else
1056 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1057 #endif
1058 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1059 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1060 #else
1061 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1062 #endif
1063 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1064 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1065 #else
1066 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1067 #endif
1068 #if HAVE_DECL_CURLOPT_AUTOREFERER
1069 {handleAutoReferer, "CURLOPT_AUTOREFERER", CURLOPT_AUTOREFERER},
1070 #else
1071 {handleAutoReferer, "CURLOPT_AUTOREFERER", 0},
1072 #endif
1073 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1074 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION},
1075 #else
1076 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", 0},
1077 #endif
1078 #if HAVE_DECL_CURLOPT_PROXYTYPE
1079 {handleProxyType, "CURLOPT_PROXYTYPE", CURLOPT_PROXYTYPE},
1080 #else
1081 {handleProxyType, "CURLOPT_PROXYTYPE", 0},
1082 #endif
1083 #if HAVE_DECL_CURLOPT_PROTOCOLS
1084 {handleProtocols, "CURLOPT_PROTOCOLS", CURLOPT_PROTOCOLS},
1085 #else
1086 {handleProtocols, "CURLOPT_PROTOCOLS", 0},
1087 #endif
1088 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
1089 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS},
1090 #else
1091 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", 0},
1092 #endif
1093 #if HAVE_DECL_CURLOPT_RESOLVE
1094 {handleResolve, "CURLOPT_RESOLVE", CURLOPT_RESOLVE},
1095 #else
1096 {handleResolve, "CURLOPT_RESOLVE", 0},
1097 #endif
1098 #if HAVE_DECL_CURLOPT_DNS_SERVERS
1099 {handleDnsServers, "CURLOPT_DNS_SERVERS", CURLOPT_DNS_SERVERS},
1100 #else
1101 {handleDnsServers, "CURLOPT_DNS_SERVERS", 0},
1102 #endif
1105 static char *findOption(CURLOptionMapping optionMap[],
1106 CURLoption option)
1108 return optionMap[option].name;
1111 static void free_curl_slist(struct curl_slist *slist)
1113 if (NULL == slist)
1114 return;
1116 curl_slist_free_all(slist);
1119 static void raiseError(Connection *conn, CURLcode code)
1121 CAMLparam0();
1122 CAMLlocal1(exceptionData);
1123 value *exception;
1124 char *errorString = "Unknown Error";
1125 int i;
1127 for (i = 0; errorMap[i].name != NULL; i++)
1129 if (errorMap[i].error == code)
1131 errorString = errorMap[i].name;
1132 break;
1136 exceptionData = caml_alloc(3, 0);
1138 Store_field(exceptionData, 0, Val_int(code));
1139 Store_field(exceptionData, 1, Val_int(code));
1140 Store_field(exceptionData, 2, copy_string(errorString));
1142 if (conn != NULL && conn->errorBuffer != NULL)
1144 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1145 copy_string(conn->errorBuffer));
1148 exception = caml_named_value("CurlException");
1150 if (exception == NULL)
1151 caml_failwith("CurlException not registered");
1153 raise_with_arg(*exception, exceptionData);
1155 CAMLreturn0;
1158 static void resetOcamlValues(Connection* connection)
1160 int i;
1162 for (i = 0; i < OcamlValuesSize; i++)
1163 Store_field(connection->ocamlValues, i, Val_unit);
1166 static Connection *newConnection(void)
1168 Connection *connection;
1170 connection = (Connection *)malloc(sizeof(Connection));
1172 enter_blocking_section();
1173 connection->connection = curl_easy_init();
1174 leave_blocking_section();
1176 connection->next = NULL;
1177 connection->prev = NULL;
1179 if (connectionList.tail == NULL)
1181 connectionList.tail = connection;
1182 connectionList.head = connection;
1184 else
1186 connection->prev = connectionList.head;
1187 connectionList.head->next = connection;
1188 connectionList.head = connection;
1191 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1192 resetOcamlValues(connection);
1193 register_global_root(&connection->ocamlValues);
1195 connection->url = NULL;
1196 connection->proxy = NULL;
1197 connection->userPwd = NULL;
1198 connection->proxyUserPwd = NULL;
1199 connection->range = NULL;
1200 connection->errorBuffer = NULL;
1201 connection->postFields = NULL;
1202 connection->postFieldSize = -1;
1203 connection->referer = NULL;
1204 connection->userAgent = NULL;
1205 connection->ftpPort = NULL;
1206 connection->cookie = NULL;
1207 connection->httpHeader = NULL;
1208 connection->httpPostFirst = NULL;
1209 connection->httpPostLast = NULL;
1210 connection->httpPostStrings = NULL;
1211 connection->sslCert = NULL;
1212 connection->sslCertType = NULL;
1213 connection->sslCertPasswd = NULL;
1214 connection->sslKey = NULL;
1215 connection->sslKeyType = NULL;
1216 connection->sslKeyPasswd = NULL;
1217 connection->sslEngine = NULL;
1218 connection->quote = NULL;
1219 connection->postQuote = NULL;
1220 connection->cookieFile = NULL;
1221 connection->customRequest = NULL;
1222 connection->interface = NULL;
1223 connection->caInfo = NULL;
1224 connection->caPath = NULL;
1225 connection->randomFile = NULL;
1226 connection->egdSocket = NULL;
1227 connection->cookieJar = NULL;
1228 connection->sslCipherList = NULL;
1229 connection->private = NULL;
1230 connection->http200Aliases = NULL;
1231 connection->netrcFile = NULL;
1232 connection->ftpaccount = NULL;
1233 connection->cookielist = NULL;
1234 connection->ftpAlternativeToUser = NULL;
1235 connection->sshPublicKeyFile = NULL;
1236 connection->sshPrivateKeyFile = NULL;
1237 connection->copyPostFields = NULL;
1238 connection->resolve = NULL;
1239 connection->dns_servers = NULL;
1241 return connection;
1244 static Connection *duplicateConnection(Connection *original)
1246 Connection *connection;
1248 connection = (Connection *)malloc(sizeof(Connection));
1250 enter_blocking_section();
1251 connection->connection = curl_easy_duphandle(original->connection);
1252 leave_blocking_section();
1254 connection->next = NULL;
1255 connection->prev = NULL;
1257 if (connectionList.tail == NULL)
1259 connectionList.tail = connection;
1260 connectionList.head = connection;
1262 else
1264 connection->prev = connectionList.head;
1265 connectionList.head->next = connection;
1266 connectionList.head = connection;
1269 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1270 resetOcamlValues(connection);
1271 register_global_root(&connection->ocamlValues);
1273 Store_field(connection->ocamlValues, OcamlWriteCallback,
1274 Field(original->ocamlValues, OcamlWriteCallback));
1275 Store_field(connection->ocamlValues, OcamlReadCallback,
1276 Field(original->ocamlValues, OcamlReadCallback));
1277 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1278 Field(original->ocamlValues, OcamlErrorBuffer));
1279 Store_field(connection->ocamlValues, OcamlPostFields,
1280 Field(original->ocamlValues, OcamlPostFields));
1281 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1282 Field(original->ocamlValues, OcamlHTTPHeader));
1283 Store_field(connection->ocamlValues, OcamlQuote,
1284 Field(original->ocamlValues, OcamlQuote));
1285 Store_field(connection->ocamlValues, OcamlPostQuote,
1286 Field(original->ocamlValues, OcamlPostQuote));
1287 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1288 Field(original->ocamlValues, OcamlHeaderCallback));
1289 Store_field(connection->ocamlValues, OcamlProgressCallback,
1290 Field(original->ocamlValues, OcamlProgressCallback));
1291 Store_field(connection->ocamlValues, OcamlDebugCallback,
1292 Field(original->ocamlValues, OcamlDebugCallback));
1293 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1294 Field(original->ocamlValues, OcamlHTTP200Aliases));
1295 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1296 Field(original->ocamlValues, OcamlIOCTLCallback));
1297 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1298 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1300 connection->url = NULL;
1301 connection->proxy = NULL;
1302 connection->userPwd = NULL;
1303 connection->proxyUserPwd = NULL;
1304 connection->range = NULL;
1305 connection->errorBuffer = NULL;
1306 connection->postFields = NULL;
1307 connection->postFieldSize = -1;
1308 connection->referer = NULL;
1309 connection->userAgent = NULL;
1310 connection->ftpPort = NULL;
1311 connection->cookie = NULL;
1312 connection->httpHeader = NULL;
1313 connection->httpPostFirst = NULL;
1314 connection->httpPostLast = NULL;
1315 connection->httpPostStrings = NULL;
1316 connection->sslCert = NULL;
1317 connection->sslCertType = NULL;
1318 connection->sslCertPasswd = NULL;
1319 connection->sslKey = NULL;
1320 connection->sslKeyType = NULL;
1321 connection->sslKeyPasswd = NULL;
1322 connection->sslEngine = NULL;
1323 connection->quote = NULL;
1324 connection->postQuote = NULL;
1325 connection->cookieFile = NULL;
1326 connection->customRequest = NULL;
1327 connection->interface = NULL;
1328 connection->caInfo = NULL;
1329 connection->caPath = NULL;
1330 connection->randomFile = NULL;
1331 connection->egdSocket = NULL;
1332 connection->cookieJar = NULL;
1333 connection->sslCipherList = NULL;
1334 connection->private = NULL;
1335 connection->http200Aliases = NULL;
1336 connection->netrcFile = NULL;
1337 connection->ftpaccount = NULL;
1338 connection->cookielist = NULL;
1339 connection->sshPublicKeyFile = NULL;
1340 connection->sshPrivateKeyFile = NULL;
1341 connection->copyPostFields = NULL;
1342 connection->resolve = NULL;
1343 connection->dns_servers = NULL;
1345 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1346 handleURL(connection, Field(original->ocamlValues,
1347 OcamlURL));
1348 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1349 handleProxy(connection, Field(original->ocamlValues,
1350 OcamlProxy));
1351 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1352 handleUserPwd(connection, Field(original->ocamlValues,
1353 OcamlUserPWD));
1354 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1355 handleProxyUserPwd(connection, Field(original->ocamlValues,
1356 OcamlProxyUserPWD));
1357 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1358 handleRange(connection, Field(original->ocamlValues,
1359 OcamlRange));
1360 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1361 handleErrorBuffer(connection, Field(original->ocamlValues,
1362 OcamlErrorBuffer));
1363 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1364 handlePostFields(connection, Field(original->ocamlValues,
1365 OcamlPostFields));
1366 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1367 handleReferer(connection, Field(original->ocamlValues,
1368 OcamlReferer));
1369 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1370 handleUserAgent(connection, Field(original->ocamlValues,
1371 OcamlUserAgent));
1372 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1373 handleFTPPort(connection, Field(original->ocamlValues,
1374 OcamlFTPPort));
1375 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1376 handleCookie(connection, Field(original->ocamlValues,
1377 OcamlCookie));
1378 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1379 handleHTTPHeader(connection, Field(original->ocamlValues,
1380 OcamlHTTPHeader));
1381 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1382 handleHTTPPost(connection, Field(original->ocamlValues,
1383 OcamlHTTPPost));
1384 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1385 handleSSLCert(connection, Field(original->ocamlValues,
1386 OcamlSSLCert));
1387 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1388 handleSSLCertType(connection, Field(original->ocamlValues,
1389 OcamlSSLCertType));
1390 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1391 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1392 OcamlSSLCertPasswd));
1393 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1394 handleSSLKey(connection, Field(original->ocamlValues,
1395 OcamlSSLKey));
1396 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1397 handleSSLKeyType(connection, Field(original->ocamlValues,
1398 OcamlSSLKeyType));
1399 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1400 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1401 OcamlSSLKeyPasswd));
1402 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1403 handleSSLEngine(connection, Field(original->ocamlValues,
1404 OcamlSSLEngine));
1405 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1406 handleQuote(connection, Field(original->ocamlValues,
1407 OcamlQuote));
1408 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1409 handlePostQuote(connection, Field(original->ocamlValues,
1410 OcamlPostQuote));
1411 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1412 handleCookieFile(connection, Field(original->ocamlValues,
1413 OcamlCookieFile));
1414 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1415 handleCustomRequest(connection, Field(original->ocamlValues,
1416 OcamlCustomRequest));
1417 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1418 handleInterface(connection, Field(original->ocamlValues,
1419 OcamlInterface));
1420 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1421 handleCAInfo(connection, Field(original->ocamlValues,
1422 OcamlCAInfo));
1423 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1424 handleCAPath(connection, Field(original->ocamlValues,
1425 OcamlCAPath));
1426 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1427 handleRandomFile(connection, Field(original->ocamlValues,
1428 OcamlRandomFile));
1429 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1430 handleEGDSocket(connection, Field(original->ocamlValues,
1431 OcamlEGDSocket));
1432 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1433 handleCookieJar(connection, Field(original->ocamlValues,
1434 OcamlCookieJar));
1435 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1436 handleSSLCipherList(connection, Field(original->ocamlValues,
1437 OcamlSSLCipherList));
1438 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1439 handlePrivate(connection, Field(original->ocamlValues,
1440 OcamlPrivate));
1441 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1442 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1443 OcamlHTTP200Aliases));
1444 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1445 handleNETRCFile(connection, Field(original->ocamlValues,
1446 OcamlNETRCFile));
1447 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1448 handleFTPAccount(connection, Field(original->ocamlValues,
1449 OcamlFTPAccount));
1450 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1451 handleCookieList(connection, Field(original->ocamlValues,
1452 OcamlCookieList));
1453 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1454 handleFTPAlternativeToUser(connection,
1455 Field(original->ocamlValues,
1456 OcamlFTPAlternativeToUser));
1457 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1458 handleSSHPublicKeyFile(connection,
1459 Field(original->ocamlValues,
1460 OcamlSSHPublicKeyFile));
1461 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1462 handleSSHPrivateKeyFile(connection,
1463 Field(original->ocamlValues,
1464 OcamlSSHPrivateKeyFile));
1465 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1466 handleCopyPostFields(connection,
1467 Field(original->ocamlValues,
1468 OcamlCopyPostFields));
1470 return connection;
1473 static void free_if(void* p) { if (NULL != p) free(p); }
1475 static void removeConnection(Connection *connection)
1477 enter_blocking_section();
1478 curl_easy_cleanup(connection->connection);
1479 leave_blocking_section();
1481 if (connectionList.tail == connection)
1482 connectionList.tail = connectionList.tail->next;
1483 if (connectionList.head == connection)
1484 connectionList.head = connectionList.head->prev;
1486 if (connection->next != NULL)
1487 connection->next->prev = connection->prev;
1488 if (connection->prev != NULL)
1489 connection->prev->next = connection->next;
1491 remove_global_root(&connection->ocamlValues);
1493 free_if(connection->url);
1494 free_if(connection->proxy);
1495 free_if(connection->userPwd);
1496 free_if(connection->proxyUserPwd);
1497 free_if(connection->range);
1498 free_if(connection->errorBuffer);
1499 free_if(connection->postFields);
1500 free_if(connection->referer);
1501 free_if(connection->userAgent);
1502 free_if(connection->ftpPort);
1503 free_if(connection->cookie);
1504 free_curl_slist(connection->httpHeader);
1505 if (connection->httpPostFirst != NULL)
1506 curl_formfree(connection->httpPostFirst);
1507 free_curl_slist(connection->httpPostStrings);
1508 free_curl_slist(connection->resolve);
1509 free_if(connection->sslCert);
1510 free_if(connection->sslCertType);
1511 free_if(connection->sslCertPasswd);
1512 free_if(connection->sslKey);
1513 free_if(connection->sslKeyType);
1514 free_if(connection->sslKeyPasswd);
1515 free_if(connection->sslEngine);
1516 free_curl_slist(connection->quote);
1517 free_curl_slist(connection->postQuote);
1518 free_if(connection->cookieFile);
1519 free_if(connection->customRequest);
1520 free_if(connection->interface);
1521 free_if(connection->caInfo);
1522 free_if(connection->caPath);
1523 free_if(connection->randomFile);
1524 free_if(connection->egdSocket);
1525 free_if(connection->cookieJar);
1526 free_if(connection->sslCipherList);
1527 free_if(connection->private);
1528 free_curl_slist(connection->http200Aliases);
1529 free_if(connection->netrcFile);
1530 free_if(connection->ftpaccount);
1531 free_if(connection->cookielist);
1532 free_if(connection->ftpAlternativeToUser);
1533 free_if(connection->sshPublicKeyFile);
1534 free_if(connection->sshPrivateKeyFile);
1535 free_if(connection->copyPostFields);
1536 free_if(connection->dns_servers);
1538 free(connection);
1541 #if 1
1542 static void checkConnection(Connection * connection)
1544 (void)connection;
1546 #else
1547 static void checkConnection(Connection *connection)
1549 Connection *listIter;
1551 listIter = connectionList.tail;
1553 while (listIter != NULL)
1555 if (listIter == connection)
1556 return;
1558 listIter = listIter->next;
1561 failwith("Invalid Connection");
1563 #endif
1565 static Connection* findConnection(CURL* h)
1567 Connection *listIter;
1569 listIter = connectionList.tail;
1571 while (listIter != NULL)
1573 if (listIter->connection == h)
1574 return listIter;
1576 listIter = listIter->next;
1579 failwith("Unknown handle");
1582 #define WRAP_DATA_CALLBACK(f) \
1583 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1585 size_t result;\
1586 leave_blocking_section();\
1587 result = f##_nolock(ptr,size,nmemb,data);\
1588 enter_blocking_section();\
1589 return result;\
1592 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1594 CAMLparam0();
1595 CAMLlocal2(result, str);
1596 Connection *conn = (Connection *)data;
1597 size_t i;
1599 checkConnection(conn);
1601 str = alloc_string(size*nmemb);
1603 for (i = 0; i < size*nmemb; i++)
1604 Byte(str, i) = ptr[i];
1606 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1608 CAMLreturnT(size_t, Int_val(result));
1611 WRAP_DATA_CALLBACK(writeFunction)
1613 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1615 CAMLparam0();
1616 CAMLlocal1(result);
1617 Connection *conn = (Connection *)data;
1618 size_t length;
1620 checkConnection(conn);
1622 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1623 Val_int(size*nmemb));
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(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1653 CAMLreturnT(size_t, 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(Field(conn->ocamlValues, OcamlProgressCallback),
1677 4, callbackData);
1679 CAMLreturnT(int, 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(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(Field(conn->ocamlValues, OcamlIOCTLCallback),
1760 camlConnection,
1761 camlCmd);
1763 switch (Long_val(camlResult))
1765 case 0: /* CURLIOE_OK */
1766 result = CURLIOE_OK;
1767 break;
1769 case 1: /* CURLIOE_UNKNOWNCMD */
1770 result = CURLIOE_UNKNOWNCMD;
1771 break;
1773 case 2: /* CURLIOE_FAILRESTART */
1774 result = CURLIOE_FAILRESTART;
1775 break;
1777 default: /* Incorrect return value, but let's handle it */
1778 result = CURLIOE_FAILRESTART;
1779 break;
1782 CAMLreturnT(curlioerr, result);
1785 static curlioerr ioctlFunction(CURL *ioctl,
1786 int cmd,
1787 void *data)
1789 curlioerr r;
1790 leave_blocking_section();
1791 r = ioctlFunction_nolock(ioctl, cmd, data);
1792 enter_blocking_section();
1793 return r;
1796 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1797 static int seekFunction_nolock(void *data,
1798 curl_off_t offset,
1799 int origin)
1801 CAMLparam0();
1802 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1803 Connection *conn = (Connection *)data;
1804 int result = 0;
1806 camlOffset = copy_int64(offset);
1808 if (origin == SEEK_SET)
1809 camlOrigin = Val_long(0);
1810 else if (origin == SEEK_CUR)
1811 camlOrigin = Val_long(1);
1812 else if (origin == SEEK_END)
1813 camlOrigin = Val_long(2);
1814 else
1815 camlOrigin = Val_long(0);
1817 camlResult = callback2(Field(conn->ocamlValues,
1818 OcamlSeekFunctionCallback),
1819 camlOffset,
1820 camlOrigin);
1822 result = Int_val(camlResult);
1824 CAMLreturnT(int, result);
1827 static int seekFunction(void *data,
1828 curl_off_t offset,
1829 int origin)
1831 int r;
1832 leave_blocking_section();
1833 r = seekFunction_nolock(data,offset,origin);
1834 enter_blocking_section();
1835 return r;
1838 #endif
1840 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1841 static int openSocketFunction_nolock(void *data,
1842 curlsocktype purpose,
1843 struct curl_sockaddr *addr)
1845 CAMLparam0();
1846 Connection *conn = (Connection *)data;
1847 int sock = -1;
1848 (void)purpose; /* not used */
1850 sock = socket(addr->family, addr->socktype, addr->protocol);
1852 if (-1 != sock)
1854 /* FIXME windows */
1855 callback(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1858 CAMLreturnT(int, sock);
1861 static int openSocketFunction(void *data,
1862 curlsocktype purpose,
1863 struct curl_sockaddr *address)
1865 int r;
1866 leave_blocking_section();
1867 r = openSocketFunction_nolock(data,purpose,address);
1868 enter_blocking_section();
1869 return r;
1872 #endif
1875 ** curl_global_init helper function
1878 CAMLprim value helper_curl_global_init(value initOption)
1880 CAMLparam1(initOption);
1882 switch (Long_val(initOption))
1884 case 0: /* CURLINIT_GLOBALALL */
1885 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1886 break;
1888 case 1: /* CURLINIT_GLOBALSSL */
1889 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1890 break;
1892 case 2: /* CURLINIT_GLOBALWIN32 */
1893 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1894 break;
1896 case 3: /* CURLINIT_GLOBALNOTHING */
1897 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1898 break;
1900 default:
1901 failwith("Invalid Initialization Option");
1902 break;
1905 /* Keep compiler happy, we should never get here due to failwith() */
1906 CAMLreturn(Val_unit);
1910 ** curl_global_cleanup helper function
1913 CAMLprim value helper_curl_global_cleanup(void)
1915 CAMLparam0();
1917 curl_global_cleanup();
1919 CAMLreturn(Val_unit);
1923 ** curl_easy_init helper function
1926 CAMLprim value helper_curl_easy_init(void)
1928 CAMLparam0();
1929 CAMLlocal1(result);
1931 Connection *conn = newConnection();
1933 result = caml_alloc(1, Abstract_tag);
1934 Field(result, 0) = (value)conn;
1936 CAMLreturn(result);
1939 CAMLprim value helper_curl_easy_reset(value conn)
1941 CAMLparam1(conn);
1942 Connection *connection = Connection_val(conn);
1944 checkConnection(connection);
1945 curl_easy_reset(connection->connection);
1946 resetOcamlValues(connection);
1948 CAMLreturn(Val_unit);
1952 ** curl_easy_setopt helper utility functions
1955 static void handleWriteFunction(Connection *conn, value option)
1957 CAMLparam1(option);
1958 CURLcode result = CURLE_OK;
1960 if (Tag_val(option) == Closure_tag)
1961 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1962 else
1963 failwith("Not a proper closure");
1965 result = curl_easy_setopt(conn->connection,
1966 CURLOPT_WRITEFUNCTION,
1967 writeFunction);
1969 if (result != CURLE_OK)
1970 raiseError(conn, result);
1972 result = curl_easy_setopt(conn->connection,
1973 CURLOPT_WRITEDATA,
1974 conn);
1976 if (result != CURLE_OK)
1977 raiseError(conn, result);
1979 CAMLreturn0;
1982 static void handleReadFunction(Connection *conn, value option)
1984 CAMLparam1(option);
1985 CURLcode result = CURLE_OK;
1987 if (Tag_val(option) == Closure_tag)
1988 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1989 else
1990 failwith("Not a proper closure");
1992 result = curl_easy_setopt(conn->connection,
1993 CURLOPT_READFUNCTION,
1994 readFunction);
1996 if (result != CURLE_OK)
1997 raiseError(conn, result);
1999 result = curl_easy_setopt(conn->connection,
2000 CURLOPT_READDATA,
2001 conn);
2003 if (result != CURLE_OK)
2004 raiseError(conn, result);
2006 CAMLreturn0;
2009 static void handleURL(Connection *conn, value option)
2011 CAMLparam1(option);
2012 CURLcode result = CURLE_OK;
2014 Store_field(conn->ocamlValues, OcamlURL, option);
2016 if (conn->url != NULL)
2017 free(conn->url);
2019 conn->url = strdup(String_val(option));
2021 result = curl_easy_setopt(conn->connection,
2022 CURLOPT_URL,
2023 conn->url);
2025 if (result != CURLE_OK)
2026 raiseError(conn, result);
2028 CAMLreturn0;
2031 static void handleInFileSize(Connection *conn, value option)
2033 CAMLparam1(option);
2034 CURLcode result = CURLE_OK;
2036 result = curl_easy_setopt(conn->connection,
2037 CURLOPT_INFILESIZE,
2038 Long_val(option));
2040 if (result != CURLE_OK)
2041 raiseError(conn, result);
2043 CAMLreturn0;
2046 static void handleProxy(Connection *conn, value option)
2048 CAMLparam1(option);
2049 CURLcode result = CURLE_OK;
2051 Store_field(conn->ocamlValues, OcamlProxy, option);
2053 if (conn->proxy != NULL)
2054 free(conn->proxy);
2056 conn->proxy = strdup(String_val(option));
2058 result = curl_easy_setopt(conn->connection,
2059 CURLOPT_PROXY,
2060 conn->proxy);
2062 if (result != CURLE_OK)
2063 raiseError(conn, result);
2065 CAMLreturn0;
2068 static void handleProxyPort(Connection *conn, value option)
2070 CAMLparam1(option);
2071 CURLcode result = CURLE_OK;
2073 result = curl_easy_setopt(conn->connection,
2074 CURLOPT_PROXYPORT,
2075 Long_val(option));
2077 if (result != CURLE_OK)
2078 raiseError(conn, result);
2080 CAMLreturn0;
2083 static void handleHTTPProxyTunnel(Connection *conn, value option)
2085 CAMLparam1(option);
2086 CURLcode result = CURLE_OK;
2088 result = curl_easy_setopt(conn->connection,
2089 CURLOPT_HTTPPROXYTUNNEL,
2090 Bool_val(option));
2092 if (result != CURLE_OK)
2093 raiseError(conn, result);
2095 CAMLreturn0;
2098 static void handleVerbose(Connection *conn, value option)
2100 CAMLparam1(option);
2101 CURLcode result = CURLE_OK;
2103 result = curl_easy_setopt(conn->connection,
2104 CURLOPT_VERBOSE,
2105 Bool_val(option));
2107 if (result != CURLE_OK)
2108 raiseError(conn, result);
2110 CAMLreturn0;
2113 static void handleHeader(Connection *conn, value option)
2115 CAMLparam1(option);
2116 CURLcode result = CURLE_OK;
2118 result = curl_easy_setopt(conn->connection,
2119 CURLOPT_HEADER,
2120 Bool_val(option));
2122 if (result != CURLE_OK)
2123 raiseError(conn, result);
2125 CAMLreturn0;
2128 static void handleNoProgress(Connection *conn, value option)
2130 CAMLparam1(option);
2131 CURLcode result = CURLE_OK;
2133 result = curl_easy_setopt(conn->connection,
2134 CURLOPT_NOPROGRESS,
2135 Bool_val(option));
2137 if (result != CURLE_OK)
2138 raiseError(conn, result);
2140 CAMLreturn0;
2143 static void handleNoSignal(Connection *conn, value option)
2145 #if HAVE_DECL_CURLOPT_NOSIGNAL
2146 CAMLparam1(option);
2147 CURLcode result = CURLE_OK;
2149 result = curl_easy_setopt(conn->connection,
2150 CURLOPT_NOSIGNAL,
2151 Bool_val(option));
2153 if (result != CURLE_OK)
2154 raiseError(conn, result);
2156 CAMLreturn0;
2157 #else
2158 #pragma message("libcurl does not implement CURLOPT_NOSIGNAL")
2159 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2160 #endif
2163 static void handleNoBody(Connection *conn, value option)
2165 CAMLparam1(option);
2166 CURLcode result = CURLE_OK;
2168 result = curl_easy_setopt(conn->connection,
2169 CURLOPT_NOBODY,
2170 Bool_val(option));
2172 if (result != CURLE_OK)
2173 raiseError(conn, result);
2175 CAMLreturn0;
2178 static void handleFailOnError(Connection *conn, value option)
2180 CAMLparam1(option);
2181 CURLcode result = CURLE_OK;
2183 result = curl_easy_setopt(conn->connection,
2184 CURLOPT_FAILONERROR,
2185 Bool_val(option));
2187 if (result != CURLE_OK)
2188 raiseError(conn, result);
2190 CAMLreturn0;
2193 static void handleUpload(Connection *conn, value option)
2195 CAMLparam1(option);
2196 CURLcode result = CURLE_OK;
2198 result = curl_easy_setopt(conn->connection,
2199 CURLOPT_UPLOAD,
2200 Bool_val(option));
2202 if (result != CURLE_OK)
2203 raiseError(conn, result);
2205 CAMLreturn0;
2208 static void handlePost(Connection *conn, value option)
2210 CAMLparam1(option);
2211 CURLcode result = CURLE_OK;
2213 result = curl_easy_setopt(conn->connection,
2214 CURLOPT_POST,
2215 Bool_val(option));
2217 if (result != CURLE_OK)
2218 raiseError(conn, result);
2220 CAMLreturn0;
2223 static void handleFTPListOnly(Connection *conn, value option)
2225 CAMLparam1(option);
2226 CURLcode result = CURLE_OK;
2228 result = curl_easy_setopt(conn->connection,
2229 CURLOPT_FTPLISTONLY,
2230 Bool_val(option));
2232 if (result != CURLE_OK)
2233 raiseError(conn, result);
2235 CAMLreturn0;
2238 static void handleFTPAppend(Connection *conn, value option)
2240 CAMLparam1(option);
2241 CURLcode result = CURLE_OK;
2243 result = curl_easy_setopt(conn->connection,
2244 CURLOPT_FTPAPPEND,
2245 Bool_val(option));
2247 if (result != CURLE_OK)
2248 raiseError(conn, result);
2250 CAMLreturn0;
2253 static void handleNETRC(Connection *conn, value option)
2255 CAMLparam1(option);
2256 CURLcode result = CURLE_OK;
2257 long netrc;
2259 switch (Long_val(option))
2261 case 0: /* CURL_NETRC_OPTIONAL */
2262 netrc = CURL_NETRC_OPTIONAL;
2263 break;
2265 case 1:/* CURL_NETRC_IGNORED */
2266 netrc = CURL_NETRC_IGNORED;
2267 break;
2269 case 2: /* CURL_NETRC_REQUIRED */
2270 netrc = CURL_NETRC_REQUIRED;
2271 break;
2273 default:
2274 failwith("Invalid NETRC Option");
2275 break;
2278 result = curl_easy_setopt(conn->connection,
2279 CURLOPT_NETRC,
2280 netrc);
2282 if (result != CURLE_OK)
2283 raiseError(conn, result);
2285 CAMLreturn0;
2288 static void handleEncoding(Connection *conn, value option)
2290 #if HAVE_DECL_CURLOPT_ENCODING
2291 CAMLparam1(option);
2292 CURLcode result = CURLE_OK;
2294 switch (Long_val(option))
2296 case 0: /* CURL_ENCODING_NONE */
2297 result = curl_easy_setopt(conn->connection,
2298 CURLOPT_ENCODING,
2299 "identity");
2300 break;
2302 case 1: /* CURL_ENCODING_DEFLATE */
2303 result = curl_easy_setopt(conn->connection,
2304 CURLOPT_ENCODING,
2305 "deflate");
2306 break;
2308 case 2: /* CURL_ENCODING_GZIP */
2309 result = curl_easy_setopt(conn->connection,
2310 CURLOPT_ENCODING,
2311 "gzip");
2312 break;
2314 case 3: /* CURL_ENCODING_ANY */
2315 result = curl_easy_setopt(conn->connection,
2316 CURLOPT_ENCODING,
2317 "");
2318 break;
2320 default:
2321 failwith("Invalid Encoding Option");
2322 break;
2325 if (result != CURLE_OK)
2326 raiseError(conn, result);
2328 CAMLreturn0;
2329 #else
2330 #pragma message("libcurl does not implement CURLOPT_ENCODING")
2331 failwith("libcurl does not implement CURLOPT_ENCODING");
2332 #endif
2335 static void handleFollowLocation(Connection *conn, value option)
2337 CAMLparam1(option);
2338 CURLcode result = CURLE_OK;
2340 result = curl_easy_setopt(conn->connection,
2341 CURLOPT_FOLLOWLOCATION,
2342 Bool_val(option));
2344 if (result != CURLE_OK)
2345 raiseError(conn, result);
2347 CAMLreturn0;
2350 static void handleTransferText(Connection *conn, value option)
2352 CAMLparam1(option);
2353 CURLcode result = CURLE_OK;
2355 result = curl_easy_setopt(conn->connection,
2356 CURLOPT_TRANSFERTEXT,
2357 Bool_val(option));
2359 if (result != CURLE_OK)
2360 raiseError(conn, result);
2362 CAMLreturn0;
2365 static void handlePut(Connection *conn, value option)
2367 CAMLparam1(option);
2368 CURLcode result = CURLE_OK;
2370 result = curl_easy_setopt(conn->connection,
2371 CURLOPT_PUT,
2372 Bool_val(option));
2374 if (result != CURLE_OK)
2375 raiseError(conn, result);
2377 CAMLreturn0;
2380 static void handleUserPwd(Connection *conn, value option)
2382 CAMLparam1(option);
2383 CURLcode result = CURLE_OK;
2385 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2387 if (conn->userPwd != NULL)
2388 free(conn->userPwd);
2390 conn->userPwd = strdup(String_val(option));
2392 result = curl_easy_setopt(conn->connection,
2393 CURLOPT_USERPWD,
2394 conn->userPwd);
2396 if (result != CURLE_OK)
2397 raiseError(conn, result);
2399 CAMLreturn0;
2402 static void handleProxyUserPwd(Connection *conn, value option)
2404 CAMLparam1(option);
2405 CURLcode result = CURLE_OK;
2407 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2409 if (conn->proxyUserPwd != NULL)
2410 free(conn->proxyUserPwd);
2412 conn->proxyUserPwd = strdup(String_val(option));
2414 result = curl_easy_setopt(conn->connection,
2415 CURLOPT_PROXYUSERPWD,
2416 conn->proxyUserPwd);
2418 if (result != CURLE_OK)
2419 raiseError(conn, result);
2421 CAMLreturn0;
2424 static void handleRange(Connection *conn, value option)
2426 CAMLparam1(option);
2427 CURLcode result = CURLE_OK;
2429 Store_field(conn->ocamlValues, OcamlRange, option);
2431 if (conn->range != NULL)
2432 free(conn->range);
2434 conn->range = strdup(String_val(option));
2436 result = curl_easy_setopt(conn->connection,
2437 CURLOPT_RANGE,
2438 conn->range);
2440 if (result != CURLE_OK)
2441 raiseError(conn, result);
2443 CAMLreturn0;
2446 static void handleErrorBuffer(Connection *conn, value option)
2448 CAMLparam1(option);
2449 CURLcode result = CURLE_OK;
2451 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2453 if (conn->errorBuffer != NULL)
2454 free(conn->errorBuffer);
2456 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2458 result = curl_easy_setopt(conn->connection,
2459 CURLOPT_ERRORBUFFER,
2460 conn->errorBuffer);
2462 if (result != CURLE_OK)
2463 raiseError(conn, result);
2465 CAMLreturn0;
2468 static void handleTimeout(Connection *conn, value option)
2470 CAMLparam1(option);
2471 CURLcode result = CURLE_OK;
2473 result = curl_easy_setopt(conn->connection,
2474 CURLOPT_TIMEOUT,
2475 Long_val(option));
2477 if (result != CURLE_OK)
2478 raiseError(conn, result);
2480 CAMLreturn0;
2483 static void handlePostFields(Connection *conn, value option)
2485 CAMLparam1(option);
2486 CURLcode result = CURLE_OK;
2488 Store_field(conn->ocamlValues, OcamlPostFields, option);
2490 if (conn->postFields != NULL)
2491 free(conn->postFields);
2493 conn->postFields = malloc(string_length(option)+1);
2494 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2496 result = curl_easy_setopt(conn->connection,
2497 CURLOPT_POSTFIELDS,
2498 conn->postFields);
2500 if (result != CURLE_OK)
2501 raiseError(conn, result);
2503 CAMLreturn0;
2506 static void handlePostFieldSize(Connection *conn, value option)
2508 CAMLparam1(option);
2509 CURLcode result = CURLE_OK;
2511 result = curl_easy_setopt(conn->connection,
2512 CURLOPT_POSTFIELDSIZE,
2513 Long_val(option));
2515 if (result != CURLE_OK)
2516 raiseError(conn, result);
2518 CAMLreturn0;
2521 static void handleReferer(Connection *conn, value option)
2523 CAMLparam1(option);
2524 CURLcode result = CURLE_OK;
2526 Store_field(conn->ocamlValues, OcamlReferer, option);
2528 if (conn->referer != NULL)
2529 free(conn->referer);
2531 conn->referer = strdup(String_val(option));
2533 result = curl_easy_setopt(conn->connection,
2534 CURLOPT_REFERER,
2535 conn->referer);
2537 if (result != CURLE_OK)
2538 raiseError(conn, result);
2540 CAMLreturn0;
2543 static void handleUserAgent(Connection *conn, value option)
2545 CAMLparam1(option);
2546 CURLcode result = CURLE_OK;
2548 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2550 if (conn->userAgent != NULL)
2551 free(conn->userAgent);
2553 conn->userAgent = strdup(String_val(option));
2555 result = curl_easy_setopt(conn->connection,
2556 CURLOPT_USERAGENT,
2557 conn->userAgent);
2559 if (result != CURLE_OK)
2560 raiseError(conn, result);
2562 CAMLreturn0;
2565 static void handleFTPPort(Connection *conn, value option)
2567 CAMLparam1(option);
2568 CURLcode result = CURLE_OK;
2570 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2572 if (conn->ftpPort != NULL)
2573 free(conn->ftpPort);
2575 conn->ftpPort = strdup(String_val(option));
2577 result = curl_easy_setopt(conn->connection,
2578 CURLOPT_FTPPORT,
2579 conn->ftpPort);
2581 if (result != CURLE_OK)
2582 raiseError(conn, result);
2584 CAMLreturn0;
2587 static void handleLowSpeedLimit(Connection *conn, value option)
2589 CAMLparam1(option);
2590 CURLcode result = CURLE_OK;
2592 result = curl_easy_setopt(conn->connection,
2593 CURLOPT_LOW_SPEED_LIMIT,
2594 Long_val(option));
2596 if (result != CURLE_OK)
2597 raiseError(conn, result);
2599 CAMLreturn0;
2602 static void handleLowSpeedTime(Connection *conn, value option)
2604 CAMLparam1(option);
2605 CURLcode result = CURLE_OK;
2607 result = curl_easy_setopt(conn->connection,
2608 CURLOPT_LOW_SPEED_TIME,
2609 Long_val(option));
2611 if (result != CURLE_OK)
2612 raiseError(conn, result);
2614 CAMLreturn0;
2617 static void handleResumeFrom(Connection *conn, value option)
2619 CAMLparam1(option);
2620 CURLcode result = CURLE_OK;
2622 result = curl_easy_setopt(conn->connection,
2623 CURLOPT_RESUME_FROM,
2624 Long_val(option));
2626 if (result != CURLE_OK)
2627 raiseError(conn, result);
2629 CAMLreturn0;
2632 static void handleCookie(Connection *conn, value option)
2634 CAMLparam1(option);
2635 CURLcode result = CURLE_OK;
2637 Store_field(conn->ocamlValues, OcamlCookie, option);
2639 if (conn->cookie != NULL)
2640 free(conn->cookie);
2642 conn->cookie = strdup(String_val(option));
2644 result = curl_easy_setopt(conn->connection,
2645 CURLOPT_COOKIE,
2646 conn->cookie);
2648 if (result != CURLE_OK)
2649 raiseError(conn, result);
2651 CAMLreturn0;
2654 static void handleHTTPHeader(Connection *conn, value option)
2656 CAMLparam1(option);
2657 CAMLlocal1(listIter);
2658 CURLcode result = CURLE_OK;
2660 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2662 free_curl_slist(conn->httpHeader);
2663 conn->httpHeader = NULL;
2665 listIter = option;
2667 while (!Is_long(listIter))
2669 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2671 listIter = Field(listIter, 1);
2674 result = curl_easy_setopt(conn->connection,
2675 CURLOPT_HTTPHEADER,
2676 conn->httpHeader);
2678 if (result != CURLE_OK)
2679 raiseError(conn, result);
2681 CAMLreturn0;
2684 static void handleHTTPPost(Connection *conn, value option)
2686 CAMLparam1(option);
2687 CAMLlocal3(listIter, formItem, contentType);
2688 CURLcode result = CURLE_OK;
2689 char *str1, *str2, *str3, *str4;
2691 listIter = option;
2693 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2695 if (conn->httpPostFirst != NULL)
2696 curl_formfree(conn->httpPostFirst);
2698 conn->httpPostFirst = NULL;
2699 conn->httpPostLast = NULL;
2701 free_curl_slist(conn->httpPostStrings);
2702 conn->httpPostStrings = NULL;
2704 while (!Is_long(listIter))
2706 formItem = Field(listIter, 0);
2708 switch (Tag_val(formItem))
2710 case 0: /* CURLFORM_CONTENT */
2711 if (Wosize_val(formItem) < 3)
2713 failwith("Incorrect CURLFORM_CONTENT parameters");
2716 if (Is_long(Field(formItem, 2)) &&
2717 Long_val(Field(formItem, 2)) == 0)
2719 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2720 memcpy(str1,
2721 String_val(Field(formItem, 0)),
2722 string_length(Field(formItem, 0)));
2723 str1[string_length(Field(formItem, 0))] = 0;
2724 conn->httpPostStrings =
2725 curl_slist_append(conn->httpPostStrings, str1);
2727 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2728 memcpy(str2,
2729 String_val(Field(formItem, 1)),
2730 string_length(Field(formItem, 1)));
2731 str2[string_length(Field(formItem, 1))] = 0;
2732 conn->httpPostStrings =
2733 curl_slist_append(conn->httpPostStrings, str2);
2735 curl_formadd(&conn->httpPostFirst,
2736 &conn->httpPostLast,
2737 CURLFORM_PTRNAME,
2738 str1,
2739 CURLFORM_NAMELENGTH,
2740 string_length(Field(formItem, 0)),
2741 CURLFORM_PTRCONTENTS,
2742 str2,
2743 CURLFORM_CONTENTSLENGTH,
2744 string_length(Field(formItem, 1)),
2745 CURLFORM_END);
2747 else if (Is_block(Field(formItem, 2)))
2749 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2750 memcpy(str1,
2751 String_val(Field(formItem, 0)),
2752 string_length(Field(formItem, 0)));
2753 str1[string_length(Field(formItem, 0))] = 0;
2754 conn->httpPostStrings =
2755 curl_slist_append(conn->httpPostStrings, str1);
2757 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2758 memcpy(str2,
2759 String_val(Field(formItem, 1)),
2760 string_length(Field(formItem, 1)));
2761 str2[string_length(Field(formItem, 1))] = 0;
2762 conn->httpPostStrings =
2763 curl_slist_append(conn->httpPostStrings, str2);
2765 contentType = Field(formItem, 2);
2767 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2768 memcpy(str3,
2769 String_val(Field(contentType, 0)),
2770 string_length(Field(contentType, 0)));
2771 str3[string_length(Field(contentType, 0))] = 0;
2772 conn->httpPostStrings =
2773 curl_slist_append(conn->httpPostStrings, str3);
2775 curl_formadd(&conn->httpPostFirst,
2776 &conn->httpPostLast,
2777 CURLFORM_PTRNAME,
2778 str1,
2779 CURLFORM_NAMELENGTH,
2780 string_length(Field(formItem, 0)),
2781 CURLFORM_PTRCONTENTS,
2782 str2,
2783 CURLFORM_CONTENTSLENGTH,
2784 string_length(Field(formItem, 1)),
2785 CURLFORM_CONTENTTYPE,
2786 str3,
2787 CURLFORM_END);
2789 else
2791 failwith("Incorrect CURLFORM_CONTENT parameters");
2793 break;
2795 case 1: /* CURLFORM_FILECONTENT */
2796 if (Wosize_val(formItem) < 3)
2798 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2801 if (Is_long(Field(formItem, 2)) &&
2802 Long_val(Field(formItem, 2)) == 0)
2804 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2805 memcpy(str1,
2806 String_val(Field(formItem, 0)),
2807 string_length(Field(formItem, 0)));
2808 str1[string_length(Field(formItem, 0))] = 0;
2809 conn->httpPostStrings =
2810 curl_slist_append(conn->httpPostStrings, str1);
2812 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2813 memcpy(str2,
2814 String_val(Field(formItem, 1)),
2815 string_length(Field(formItem, 1)));
2816 str2[string_length(Field(formItem, 1))] = 0;
2817 conn->httpPostStrings =
2818 curl_slist_append(conn->httpPostStrings, str2);
2820 curl_formadd(&conn->httpPostFirst,
2821 &conn->httpPostLast,
2822 CURLFORM_PTRNAME,
2823 str1,
2824 CURLFORM_NAMELENGTH,
2825 string_length(Field(formItem, 0)),
2826 CURLFORM_FILECONTENT,
2827 str2,
2828 CURLFORM_END);
2830 else if (Is_block(Field(formItem, 2)))
2832 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2833 memcpy(str1,
2834 String_val(Field(formItem, 0)),
2835 string_length(Field(formItem, 0)));
2836 str1[string_length(Field(formItem, 0))] = 0;
2837 conn->httpPostStrings =
2838 curl_slist_append(conn->httpPostStrings, str1);
2840 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2841 memcpy(str2,
2842 String_val(Field(formItem, 1)),
2843 string_length(Field(formItem, 1)));
2844 str2[string_length(Field(formItem, 1))] = 0;
2845 conn->httpPostStrings =
2846 curl_slist_append(conn->httpPostStrings, str2);
2848 contentType = Field(formItem, 2);
2850 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2851 memcpy(str3,
2852 String_val(Field(contentType, 0)),
2853 string_length(Field(contentType, 0)));
2854 str3[string_length(Field(contentType, 0))] = 0;
2855 conn->httpPostStrings =
2856 curl_slist_append(conn->httpPostStrings, str3);
2858 curl_formadd(&conn->httpPostFirst,
2859 &conn->httpPostLast,
2860 CURLFORM_PTRNAME,
2861 str1,
2862 CURLFORM_NAMELENGTH,
2863 string_length(Field(formItem, 0)),
2864 CURLFORM_FILECONTENT,
2865 str2,
2866 CURLFORM_CONTENTTYPE,
2867 str3,
2868 CURLFORM_END);
2870 else
2872 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2874 break;
2876 case 2: /* CURLFORM_FILE */
2877 if (Wosize_val(formItem) < 3)
2879 failwith("Incorrect CURLFORM_FILE parameters");
2882 if (Is_long(Field(formItem, 2)) &&
2883 Long_val(Field(formItem, 2)) == 0)
2885 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2886 memcpy(str1,
2887 String_val(Field(formItem, 0)),
2888 string_length(Field(formItem, 0)));
2889 str1[string_length(Field(formItem, 0))] = 0;
2890 conn->httpPostStrings =
2891 curl_slist_append(conn->httpPostStrings, str1);
2893 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2894 memcpy(str2,
2895 String_val(Field(formItem, 1)),
2896 string_length(Field(formItem, 1)));
2897 str2[string_length(Field(formItem, 1))] = 0;
2898 conn->httpPostStrings =
2899 curl_slist_append(conn->httpPostStrings, str2);
2901 curl_formadd(&conn->httpPostFirst,
2902 &conn->httpPostLast,
2903 CURLFORM_PTRNAME,
2904 str1,
2905 CURLFORM_NAMELENGTH,
2906 string_length(Field(formItem, 0)),
2907 CURLFORM_FILE,
2908 str2,
2909 CURLFORM_END);
2911 else if (Is_block(Field(formItem, 2)))
2913 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2914 memcpy(str1,
2915 String_val(Field(formItem, 0)),
2916 string_length(Field(formItem, 0)));
2917 str1[string_length(Field(formItem, 0))] = 0;
2918 conn->httpPostStrings =
2919 curl_slist_append(conn->httpPostStrings, str1);
2921 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2922 memcpy(str2,
2923 String_val(Field(formItem, 1)),
2924 string_length(Field(formItem, 1)));
2925 str2[string_length(Field(formItem, 1))] = 0;
2926 conn->httpPostStrings =
2927 curl_slist_append(conn->httpPostStrings, str2);
2929 contentType = Field(formItem, 2);
2931 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2932 memcpy(str3,
2933 String_val(Field(contentType, 0)),
2934 string_length(Field(contentType, 0)));
2935 str3[string_length(Field(contentType, 0))] = 0;
2936 conn->httpPostStrings =
2937 curl_slist_append(conn->httpPostStrings, str3);
2939 curl_formadd(&conn->httpPostFirst,
2940 &conn->httpPostLast,
2941 CURLFORM_PTRNAME,
2942 str1,
2943 CURLFORM_NAMELENGTH,
2944 string_length(Field(formItem, 0)),
2945 CURLFORM_FILE,
2946 str2,
2947 CURLFORM_CONTENTTYPE,
2948 str3,
2949 CURLFORM_END);
2951 else
2953 failwith("Incorrect CURLFORM_FILE parameters");
2955 break;
2957 case 3: /* CURLFORM_BUFFER */
2958 if (Wosize_val(formItem) < 4)
2960 failwith("Incorrect CURLFORM_BUFFER parameters");
2963 if (Is_long(Field(formItem, 3)) &&
2964 Long_val(Field(formItem, 3)) == 0)
2966 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2967 memcpy(str1,
2968 String_val(Field(formItem, 0)),
2969 string_length(Field(formItem, 0)));
2970 str1[string_length(Field(formItem, 0))] = 0;
2971 conn->httpPostStrings =
2972 curl_slist_append(conn->httpPostStrings, str1);
2974 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2975 memcpy(str2,
2976 String_val(Field(formItem, 1)),
2977 string_length(Field(formItem, 1)));
2978 str2[string_length(Field(formItem, 1))] = 0;
2979 conn->httpPostStrings =
2980 curl_slist_append(conn->httpPostStrings, str2);
2982 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2983 memcpy(str3,
2984 String_val(Field(formItem, 2)),
2985 string_length(Field(formItem, 2)));
2986 str3[string_length(Field(formItem, 2))] = 0;
2987 conn->httpPostStrings =
2988 curl_slist_append(conn->httpPostStrings, str3);
2990 curl_formadd(&conn->httpPostFirst,
2991 &conn->httpPostLast,
2992 CURLFORM_PTRNAME,
2993 str1,
2994 CURLFORM_NAMELENGTH,
2995 string_length(Field(formItem, 0)),
2996 CURLFORM_BUFFER,
2997 str2,
2998 CURLFORM_BUFFERPTR,
2999 str3,
3000 CURLFORM_BUFFERLENGTH,
3001 string_length(Field(formItem, 2)),
3002 CURLFORM_END);
3004 else if (Is_block(Field(formItem, 3)))
3006 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3007 memcpy(str1,
3008 String_val(Field(formItem, 0)),
3009 string_length(Field(formItem, 0)));
3010 str1[string_length(Field(formItem, 0))] = 0;
3011 conn->httpPostStrings =
3012 curl_slist_append(conn->httpPostStrings, str1);
3014 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3015 memcpy(str2,
3016 String_val(Field(formItem, 1)),
3017 string_length(Field(formItem, 1)));
3018 str2[string_length(Field(formItem, 1))] = 0;
3019 conn->httpPostStrings =
3020 curl_slist_append(conn->httpPostStrings, str2);
3022 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3023 memcpy(str3,
3024 String_val(Field(formItem, 2)),
3025 string_length(Field(formItem, 2)));
3026 str3[string_length(Field(formItem, 2))] = 0;
3027 conn->httpPostStrings =
3028 curl_slist_append(conn->httpPostStrings, str3);
3030 contentType = Field(formItem, 3);
3032 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
3033 memcpy(str4,
3034 String_val(Field(contentType, 0)),
3035 string_length(Field(contentType, 0)));
3036 str4[string_length(Field(contentType, 0))] = 0;
3037 conn->httpPostStrings =
3038 curl_slist_append(conn->httpPostStrings, str4);
3040 curl_formadd(&conn->httpPostFirst,
3041 &conn->httpPostLast,
3042 CURLFORM_PTRNAME,
3043 str1,
3044 CURLFORM_NAMELENGTH,
3045 string_length(Field(formItem, 0)),
3046 CURLFORM_BUFFER,
3047 str2,
3048 CURLFORM_BUFFERPTR,
3049 str3,
3050 CURLFORM_BUFFERLENGTH,
3051 string_length(Field(formItem, 2)),
3052 CURLFORM_CONTENTTYPE,
3053 str4,
3054 CURLFORM_END);
3056 else
3058 failwith("Incorrect CURLFORM_BUFFER parameters");
3060 break;
3063 listIter = Field(listIter, 1);
3066 result = curl_easy_setopt(conn->connection,
3067 CURLOPT_HTTPPOST,
3068 conn->httpPostFirst);
3070 if (result != CURLE_OK)
3071 raiseError(conn, result);
3073 CAMLreturn0;
3076 static void handleSSLCert(Connection *conn, value option)
3078 CAMLparam1(option);
3079 CURLcode result = CURLE_OK;
3081 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3083 if (conn->sslCert != NULL)
3084 free(conn->sslCert);
3086 conn->sslCert = strdup(String_val(option));
3088 result = curl_easy_setopt(conn->connection,
3089 CURLOPT_SSLCERT,
3090 conn->sslCert);
3092 if (result != CURLE_OK)
3093 raiseError(conn, result);
3095 CAMLreturn0;
3098 static void handleSSLCertType(Connection *conn, value option)
3100 CAMLparam1(option);
3101 CURLcode result = CURLE_OK;
3103 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3105 if (conn->sslCertType != NULL)
3106 free(conn->sslCertType);
3108 conn->sslCertType = strdup(String_val(option));
3110 result = curl_easy_setopt(conn->connection,
3111 CURLOPT_SSLCERTTYPE,
3112 conn->sslCertType);
3114 if (result != CURLE_OK)
3115 raiseError(conn, result);
3117 CAMLreturn0;
3120 static void handleSSLCertPasswd(Connection *conn, value option)
3122 CAMLparam1(option);
3123 CURLcode result = CURLE_OK;
3125 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3127 if (conn->sslCertPasswd != NULL)
3128 free(conn->sslCertPasswd);
3130 conn->sslCertPasswd = strdup(String_val(option));
3132 result = curl_easy_setopt(conn->connection,
3133 CURLOPT_SSLCERTPASSWD,
3134 conn->sslCertPasswd);
3136 if (result != CURLE_OK)
3137 raiseError(conn, result);
3139 CAMLreturn0;
3142 static void handleSSLKey(Connection *conn, value option)
3144 CAMLparam1(option);
3145 CURLcode result = CURLE_OK;
3147 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3149 if (conn->sslKey != NULL)
3150 free(conn->sslKey);
3152 conn->sslKey = strdup(String_val(option));
3154 result = curl_easy_setopt(conn->connection,
3155 CURLOPT_SSLKEY,
3156 conn->sslKey);
3158 if (result != CURLE_OK)
3159 raiseError(conn, result);
3161 CAMLreturn0;
3164 static void handleSSLKeyType(Connection *conn, value option)
3166 CAMLparam1(option);
3167 CURLcode result = CURLE_OK;
3169 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3171 if (conn->sslKeyType != NULL)
3172 free(conn->sslKeyType);
3174 conn->sslKeyType = strdup(String_val(option));
3176 result = curl_easy_setopt(conn->connection,
3177 CURLOPT_SSLKEYTYPE,
3178 conn->sslKeyType);
3180 if (result != CURLE_OK)
3181 raiseError(conn, result);
3183 CAMLreturn0;
3186 static void handleSSLKeyPasswd(Connection *conn, value option)
3188 CAMLparam1(option);
3189 CURLcode result = CURLE_OK;
3191 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3193 if (conn->sslKeyPasswd != NULL)
3194 free(conn->sslKeyPasswd);
3196 conn->sslKeyPasswd = strdup(String_val(option));
3198 result = curl_easy_setopt(conn->connection,
3199 CURLOPT_SSLKEYPASSWD,
3200 conn->sslKeyPasswd);
3202 if (result != CURLE_OK)
3203 raiseError(conn, result);
3205 CAMLreturn0;
3208 static void handleSSLEngine(Connection *conn, value option)
3210 CAMLparam1(option);
3211 CURLcode result = CURLE_OK;
3213 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3215 if (conn->sslEngine != NULL)
3216 free(conn->sslEngine);
3218 conn->sslEngine = strdup(String_val(option));
3220 result = curl_easy_setopt(conn->connection,
3221 CURLOPT_SSLENGINE,
3222 conn->sslEngine);
3224 if (result != CURLE_OK)
3225 raiseError(conn, result);
3227 CAMLreturn0;
3230 static void handleSSLEngineDefault(Connection *conn, value option)
3232 CAMLparam1(option);
3233 CURLcode result = CURLE_OK;
3235 result = curl_easy_setopt(conn->connection,
3236 CURLOPT_SSLENGINE_DEFAULT,
3237 Bool_val(option));
3239 if (result != CURLE_OK)
3240 raiseError(conn, result);
3242 CAMLreturn0;
3245 static void handleCRLF(Connection *conn, value option)
3247 CAMLparam1(option);
3248 CURLcode result = CURLE_OK;
3250 result = curl_easy_setopt(conn->connection,
3251 CURLOPT_CRLF,
3252 Bool_val(option));
3254 if (result != CURLE_OK)
3255 raiseError(conn, result);
3257 CAMLreturn0;
3260 static void handleQuote(Connection *conn, value option)
3262 CAMLparam1(option);
3263 CAMLlocal1(listIter);
3264 CURLcode result = CURLE_OK;
3266 Store_field(conn->ocamlValues, OcamlQuote, option);
3268 free_curl_slist(conn->quote);
3269 conn->quote = NULL;
3271 listIter = option;
3273 while (!Is_long(listIter))
3275 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3277 listIter = Field(listIter, 1);
3280 result = curl_easy_setopt(conn->connection,
3281 CURLOPT_QUOTE,
3282 conn->quote);
3284 if (result != CURLE_OK)
3285 raiseError(conn, result);
3287 CAMLreturn0;
3290 static void handlePostQuote(Connection *conn, value option)
3292 CAMLparam1(option);
3293 CAMLlocal1(listIter);
3294 CURLcode result = CURLE_OK;
3296 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3298 free_curl_slist(conn->postQuote);
3299 conn->postQuote = NULL;
3301 listIter = option;
3303 while (!Is_long(listIter))
3305 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3307 listIter = Field(listIter, 1);
3310 result = curl_easy_setopt(conn->connection,
3311 CURLOPT_POSTQUOTE,
3312 conn->postQuote);
3314 if (result != CURLE_OK)
3315 raiseError(conn, result);
3317 CAMLreturn0;
3320 static void handleHeaderFunction(Connection *conn, value option)
3322 CAMLparam1(option);
3323 CURLcode result = CURLE_OK;
3325 if (Tag_val(option) == Closure_tag)
3326 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3327 else
3328 failwith("Not a proper closure");
3330 result = curl_easy_setopt(conn->connection,
3331 CURLOPT_HEADERFUNCTION,
3332 headerFunction);
3334 if (result != CURLE_OK)
3335 raiseError(conn, result);
3337 result = curl_easy_setopt(conn->connection,
3338 CURLOPT_WRITEHEADER,
3339 conn);
3341 if (result != CURLE_OK)
3342 raiseError(conn, result);
3344 CAMLreturn0;
3347 static void handleCookieFile(Connection *conn, value option)
3349 CAMLparam1(option);
3350 CURLcode result = CURLE_OK;
3352 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3354 if (conn->cookieFile != NULL)
3355 free(conn->cookieFile);
3357 conn->cookieFile = strdup(String_val(option));
3359 result = curl_easy_setopt(conn->connection,
3360 CURLOPT_COOKIEFILE,
3361 conn->cookieFile);
3363 if (result != CURLE_OK)
3364 raiseError(conn, result);
3366 CAMLreturn0;
3369 static void handleSSLVersion(Connection *conn, value option)
3371 CAMLparam1(option);
3372 CURLcode result = CURLE_OK;
3374 result = curl_easy_setopt(conn->connection,
3375 CURLOPT_SSLVERSION,
3376 Long_val(option));
3378 if (result != CURLE_OK)
3379 raiseError(conn, result);
3381 CAMLreturn0;
3384 static void handleTimeCondition(Connection *conn, value option)
3386 CAMLparam1(option);
3387 CURLcode result = CURLE_OK;
3389 switch (Long_val(option))
3391 case 0: /* TIMECOND_IFMODSINCE */
3392 result = curl_easy_setopt(conn->connection,
3393 CURLOPT_TIMECONDITION,
3394 CURL_TIMECOND_IFMODSINCE);
3395 break;
3397 case 1: /* TIMECOND_IFUNMODSINCE */
3398 result = curl_easy_setopt(conn->connection,
3399 CURLOPT_TIMECONDITION,
3400 CURL_TIMECOND_IFUNMODSINCE);
3401 break;
3403 default:
3404 failwith("Invalid TIMECOND Option");
3405 break;
3408 if (result != CURLE_OK)
3409 raiseError(conn, result);
3411 CAMLreturn0;
3414 static void handleTimeValue(Connection *conn, value option)
3416 CAMLparam1(option);
3417 CURLcode result = CURLE_OK;
3419 result = curl_easy_setopt(conn->connection,
3420 CURLOPT_TIMEVALUE,
3421 Int32_val(option));
3423 if (result != CURLE_OK)
3424 raiseError(conn, result);
3426 CAMLreturn0;
3429 static void handleCustomRequest(Connection *conn, value option)
3431 CAMLparam1(option);
3432 CURLcode result = CURLE_OK;
3434 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3436 if (conn->customRequest != NULL)
3437 free(conn->customRequest);
3439 conn->customRequest = strdup(String_val(option));
3441 result = curl_easy_setopt(conn->connection,
3442 CURLOPT_CUSTOMREQUEST,
3443 conn->customRequest);
3445 if (result != CURLE_OK)
3446 raiseError(conn, result);
3448 CAMLreturn0;
3451 static void handleInterface(Connection *conn, value option)
3453 CAMLparam1(option);
3454 CURLcode result = CURLE_OK;
3456 Store_field(conn->ocamlValues, OcamlInterface, option);
3458 if (conn->interface != NULL)
3459 free(conn->interface);
3461 conn->interface = strdup(String_val(option));
3463 result = curl_easy_setopt(conn->connection,
3464 CURLOPT_INTERFACE,
3465 conn->interface);
3467 if (result != CURLE_OK)
3468 raiseError(conn, result);
3470 CAMLreturn0;
3473 static void handleKRB4Level(Connection *conn, value option)
3475 CAMLparam1(option);
3476 CURLcode result = CURLE_OK;
3478 switch (Long_val(option))
3480 case 0: /* KRB4_NONE */
3481 result = curl_easy_setopt(conn->connection,
3482 CURLOPT_KRB4LEVEL,
3483 NULL);
3484 break;
3486 case 1: /* KRB4_CLEAR */
3487 result = curl_easy_setopt(conn->connection,
3488 CURLOPT_KRB4LEVEL,
3489 "clear");
3490 break;
3492 case 2: /* KRB4_SAFE */
3493 result = curl_easy_setopt(conn->connection,
3494 CURLOPT_KRB4LEVEL,
3495 "safe");
3496 break;
3498 case 3: /* KRB4_CONFIDENTIAL */
3499 result = curl_easy_setopt(conn->connection,
3500 CURLOPT_KRB4LEVEL,
3501 "confidential");
3502 break;
3504 case 4: /* KRB4_PRIVATE */
3505 result = curl_easy_setopt(conn->connection,
3506 CURLOPT_KRB4LEVEL,
3507 "private");
3508 break;
3510 default:
3511 failwith("Invalid KRB4 Option");
3512 break;
3515 if (result != CURLE_OK)
3516 raiseError(conn, result);
3518 CAMLreturn0;
3521 static void handleProgressFunction(Connection *conn, value option)
3523 CAMLparam1(option);
3524 CURLcode result = CURLE_OK;
3526 if (Tag_val(option) == Closure_tag)
3527 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3528 else
3529 failwith("Not a proper closure");
3531 result = curl_easy_setopt(conn->connection,
3532 CURLOPT_PROGRESSFUNCTION,
3533 progressFunction);
3534 if (result != CURLE_OK)
3535 raiseError(conn, result);
3537 result = curl_easy_setopt(conn->connection,
3538 CURLOPT_PROGRESSDATA,
3539 conn);
3541 if (result != CURLE_OK)
3542 raiseError(conn, result);
3544 CAMLreturn0;
3547 static void handleSSLVerifyPeer(Connection *conn, value option)
3549 CAMLparam1(option);
3550 CURLcode result = CURLE_OK;
3552 result = curl_easy_setopt(conn->connection,
3553 CURLOPT_SSL_VERIFYPEER,
3554 Bool_val(option));
3556 if (result != CURLE_OK)
3557 raiseError(conn, result);
3559 CAMLreturn0;
3562 static void handleCAInfo(Connection *conn, value option)
3564 CAMLparam1(option);
3565 CURLcode result = CURLE_OK;
3567 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3569 if (conn->caInfo != NULL)
3570 free(conn->caInfo);
3572 conn->caInfo = strdup(String_val(option));
3574 result = curl_easy_setopt(conn->connection,
3575 CURLOPT_CAINFO,
3576 conn->caInfo);
3578 if (result != CURLE_OK)
3579 raiseError(conn, result);
3581 CAMLreturn0;
3584 static void handleCAPath(Connection *conn, value option)
3586 CAMLparam1(option);
3587 CURLcode result = CURLE_OK;
3589 Store_field(conn->ocamlValues, OcamlCAPath, option);
3591 if (conn->caPath != NULL)
3592 free(conn->caPath);
3594 conn->caPath = strdup(String_val(option));
3596 result = curl_easy_setopt(conn->connection,
3597 CURLOPT_CAPATH,
3598 conn->caPath);
3600 if (result != CURLE_OK)
3601 raiseError(conn, result);
3603 CAMLreturn0;
3606 static void handleFileTime(Connection *conn, value option)
3608 CAMLparam1(option);
3609 CURLcode result = CURLE_OK;
3611 result = curl_easy_setopt(conn->connection,
3612 CURLOPT_FILETIME,
3613 Bool_val(option));
3615 if (result != CURLE_OK)
3616 raiseError(conn, result);
3618 CAMLreturn0;
3621 static void handleMaxRedirs(Connection *conn, value option)
3623 CAMLparam1(option);
3624 CURLcode result = CURLE_OK;
3626 result = curl_easy_setopt(conn->connection,
3627 CURLOPT_MAXREDIRS,
3628 Long_val(option));
3630 if (result != CURLE_OK)
3631 raiseError(conn, result);
3633 CAMLreturn0;
3636 static void handleMaxConnects(Connection *conn, value option)
3638 CAMLparam1(option);
3639 CURLcode result = CURLE_OK;
3641 result = curl_easy_setopt(conn->connection,
3642 CURLOPT_MAXCONNECTS,
3643 Long_val(option));
3645 if (result != CURLE_OK)
3646 raiseError(conn, result);
3648 CAMLreturn0;
3651 static void handleClosePolicy(Connection *conn, value option)
3653 CAMLparam1(option);
3654 CURLcode result = CURLE_OK;
3656 switch (Long_val(option))
3658 case 0: /* CLOSEPOLICY_OLDEST */
3659 result = curl_easy_setopt(conn->connection,
3660 CURLOPT_CLOSEPOLICY,
3661 CURLCLOSEPOLICY_OLDEST);
3662 break;
3664 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3665 result = curl_easy_setopt(conn->connection,
3666 CURLOPT_CLOSEPOLICY,
3667 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3668 break;
3670 default:
3671 failwith("Invalid CLOSEPOLICY Option");
3672 break;
3675 if (result != CURLE_OK)
3676 raiseError(conn, result);
3678 CAMLreturn0;
3681 static void handleFreshConnect(Connection *conn, value option)
3683 CAMLparam1(option);
3684 CURLcode result = CURLE_OK;
3686 result = curl_easy_setopt(conn->connection,
3687 CURLOPT_FRESH_CONNECT,
3688 Bool_val(option));
3690 if (result != CURLE_OK)
3691 raiseError(conn, result);
3693 CAMLreturn0;
3696 static void handleForbidReuse(Connection *conn, value option)
3698 CAMLparam1(option);
3699 CURLcode result = CURLE_OK;
3701 result = curl_easy_setopt(conn->connection,
3702 CURLOPT_FORBID_REUSE,
3703 Bool_val(option));
3705 if (result != CURLE_OK)
3706 raiseError(conn, result);
3708 CAMLreturn0;
3711 static void handleRandomFile(Connection *conn, value option)
3713 CAMLparam1(option);
3714 CURLcode result = CURLE_OK;
3716 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3718 if (conn->randomFile != NULL)
3719 free(conn->randomFile);
3721 conn->randomFile = strdup(String_val(option));
3723 result = curl_easy_setopt(conn->connection,
3724 CURLOPT_RANDOM_FILE,
3725 conn->randomFile);
3727 if (result != CURLE_OK)
3728 raiseError(conn, result);
3730 CAMLreturn0;
3733 static void handleEGDSocket(Connection *conn, value option)
3735 CAMLparam1(option);
3736 CURLcode result = CURLE_OK;
3738 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3740 if (conn->egdSocket != NULL)
3741 free(conn->egdSocket);
3743 conn->egdSocket = strdup(String_val(option));
3745 result = curl_easy_setopt(conn->connection,
3746 CURLOPT_EGDSOCKET,
3747 conn->egdSocket);
3749 if (result != CURLE_OK)
3750 raiseError(conn, result);
3752 CAMLreturn0;
3755 static void handleConnectTimeout(Connection *conn, value option)
3757 CAMLparam1(option);
3758 CURLcode result = CURLE_OK;
3760 result = curl_easy_setopt(conn->connection,
3761 CURLOPT_CONNECTTIMEOUT,
3762 Long_val(option));
3764 if (result != CURLE_OK)
3765 raiseError(conn, result);
3767 CAMLreturn0;
3770 static void handleHTTPGet(Connection *conn, value option)
3772 CAMLparam1(option);
3773 CURLcode result = CURLE_OK;
3775 result = curl_easy_setopt(conn->connection,
3776 CURLOPT_HTTPGET,
3777 Bool_val(option));
3779 if (result != CURLE_OK)
3780 raiseError(conn, result);
3782 CAMLreturn0;
3785 static void handleSSLVerifyHost(Connection *conn, value option)
3787 CAMLparam1(option);
3788 CURLcode result = CURLE_OK;
3790 switch (Long_val(option))
3792 case 0: /* SSLVERIFYHOST_NONE */
3793 case 1: /* SSLVERIFYHOST_EXISTENCE */
3794 case 2: /* SSLVERIFYHOST_HOSTNAME */
3795 result = curl_easy_setopt(conn->connection,
3796 CURLOPT_SSL_VERIFYHOST,
3797 /* map EXISTENCE to HOSTNAME */
3798 Long_val(option) == 0 ? 0 : 2);
3799 break;
3801 default:
3802 failwith("Invalid SSLVERIFYHOST Option");
3803 break;
3806 if (result != CURLE_OK)
3807 raiseError(conn, result);
3809 CAMLreturn0;
3812 static void handleCookieJar(Connection *conn, value option)
3814 CAMLparam1(option);
3815 CURLcode result = CURLE_OK;
3817 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3819 if (conn->cookieJar != NULL)
3820 free(conn->cookieJar);
3822 conn->cookieJar = strdup(String_val(option));
3824 result = curl_easy_setopt(conn->connection,
3825 CURLOPT_COOKIEJAR,
3826 conn->cookieJar);
3828 if (result != CURLE_OK)
3829 raiseError(conn, result);
3831 CAMLreturn0;
3834 static void handleSSLCipherList(Connection *conn, value option)
3836 CAMLparam1(option);
3837 CURLcode result = CURLE_OK;
3839 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3841 if (conn->sslCipherList != NULL)
3842 free(conn->sslCipherList);
3844 conn->sslCipherList = strdup(String_val(option));
3846 result = curl_easy_setopt(conn->connection,
3847 CURLOPT_SSL_CIPHER_LIST,
3848 conn->sslCipherList);
3850 if (result != CURLE_OK)
3851 raiseError(conn, result);
3853 CAMLreturn0;
3856 static void handleHTTPVersion(Connection *conn, value option)
3858 CAMLparam1(option);
3859 CURLcode result = CURLE_OK;
3861 switch (Long_val(option))
3863 case 0: /* HTTP_VERSION_NONE */
3864 result = curl_easy_setopt(conn->connection,
3865 CURLOPT_HTTP_VERSION,
3866 CURL_HTTP_VERSION_NONE);
3867 break;
3869 case 1: /* HTTP_VERSION_1_0 */
3870 result = curl_easy_setopt(conn->connection,
3871 CURLOPT_HTTP_VERSION,
3872 CURL_HTTP_VERSION_1_0);
3873 break;
3875 case 2: /* HTTP_VERSION_1_1 */
3876 result = curl_easy_setopt(conn->connection,
3877 CURLOPT_HTTP_VERSION,
3878 CURL_HTTP_VERSION_1_1);
3879 break;
3881 default:
3882 failwith("Invalid HTTP_VERSION Option");
3883 break;
3886 if (result != CURLE_OK)
3887 raiseError(conn, result);
3889 CAMLreturn0;
3892 static void handleFTPUseEPSV(Connection *conn, value option)
3894 CAMLparam1(option);
3895 CURLcode result = CURLE_OK;
3897 result = curl_easy_setopt(conn->connection,
3898 CURLOPT_FTP_USE_EPSV,
3899 Bool_val(option));
3901 if (result != CURLE_OK)
3902 raiseError(conn, result);
3904 CAMLreturn0;
3907 static void handleDNSCacheTimeout(Connection *conn, value option)
3909 CAMLparam1(option);
3910 CURLcode result = CURLE_OK;
3912 result = curl_easy_setopt(conn->connection,
3913 CURLOPT_DNS_CACHE_TIMEOUT,
3914 Long_val(option));
3916 if (result != CURLE_OK)
3917 raiseError(conn, result);
3919 CAMLreturn0;
3922 static void handleDNSUseGlobalCache(Connection *conn, value option)
3924 CAMLparam1(option);
3925 CURLcode result = CURLE_OK;
3927 result = curl_easy_setopt(conn->connection,
3928 CURLOPT_DNS_USE_GLOBAL_CACHE,
3929 Bool_val(option));
3931 if (result != CURLE_OK)
3932 raiseError(conn, result);
3934 CAMLreturn0;
3937 static void handleDebugFunction(Connection *conn, value option)
3939 CAMLparam1(option);
3940 CURLcode result = CURLE_OK;
3942 if (Tag_val(option) == Closure_tag)
3943 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3944 else
3945 failwith("Not a proper closure");
3947 result = curl_easy_setopt(conn->connection,
3948 CURLOPT_DEBUGFUNCTION,
3949 debugFunction);
3950 if (result != CURLE_OK)
3951 raiseError(conn, result);
3953 result = curl_easy_setopt(conn->connection,
3954 CURLOPT_DEBUGDATA,
3955 conn);
3957 if (result != CURLE_OK)
3958 raiseError(conn, result);
3960 CAMLreturn0;
3963 static void handlePrivate(Connection *conn, value option)
3965 #if HAVE_DECL_CURLOPT_PRIVATE
3966 CAMLparam1(option);
3967 CURLcode result = CURLE_OK;
3969 Store_field(conn->ocamlValues, OcamlPrivate, option);
3971 if (conn->private != NULL)
3972 free(conn->private);
3974 conn->private = strdup(String_val(option));
3976 result = curl_easy_setopt(conn->connection,
3977 CURLOPT_PRIVATE,
3978 conn->private);
3980 if (result != CURLE_OK)
3981 raiseError(conn, result);
3983 CAMLreturn0;
3984 #else
3985 #pragma message("libcurl does not implement CURLOPT_PRIVATE")
3986 failwith("libcurl does not implement CURLOPT_PRIVATE");
3987 #endif
3990 static void handleHTTP200Aliases(Connection *conn, value option)
3992 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3993 CAMLparam1(option);
3994 CAMLlocal1(listIter);
3995 CURLcode result = CURLE_OK;
3997 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3999 free_curl_slist(conn->http200Aliases);
4000 conn->http200Aliases = NULL;
4002 listIter = option;
4004 while (!Is_long(listIter))
4006 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
4008 listIter = Field(listIter, 1);
4011 result = curl_easy_setopt(conn->connection,
4012 CURLOPT_HTTP200ALIASES,
4013 conn->http200Aliases);
4015 if (result != CURLE_OK)
4016 raiseError(conn, result);
4018 CAMLreturn0;
4019 #else
4020 #pragma message("libcurl does not implement CURLOPT_HTTP200ALIASES")
4021 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
4022 #endif
4025 static void handleUnrestrictedAuth(Connection *conn, value option)
4027 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4028 CAMLparam1(option);
4029 CURLcode result = CURLE_OK;
4031 result = curl_easy_setopt(conn->connection,
4032 CURLOPT_UNRESTRICTED_AUTH,
4033 Bool_val(option));
4035 if (result != CURLE_OK)
4036 raiseError(conn, result);
4038 CAMLreturn0;
4039 #else
4040 #pragma message("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH")
4041 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4042 #endif
4045 static void handleFTPUseEPRT(Connection *conn, value option)
4047 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4048 CAMLparam1(option);
4049 CURLcode result = CURLE_OK;
4051 result = curl_easy_setopt(conn->connection,
4052 CURLOPT_FTP_USE_EPRT,
4053 Bool_val(option));
4055 if (result != CURLE_OK)
4056 raiseError(conn, result);
4058 CAMLreturn0;
4059 #else
4060 #pragma message("libcurl does not implement CURLOPT_FTP_USE_EPRT")
4061 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4062 #endif
4065 static void handleHTTPAuth(Connection *conn, value option)
4067 #if HAVE_DECL_CURLOPT_HTTPAUTH
4068 CAMLparam1(option);
4069 CAMLlocal1(listIter);
4070 CURLcode result = CURLE_OK;
4071 long auth = CURLAUTH_NONE;
4073 listIter = option;
4075 while (!Is_long(listIter))
4077 switch (Long_val(Field(listIter, 0)))
4079 case 0: /* CURLAUTH_BASIC */
4080 auth |= CURLAUTH_BASIC;
4081 break;
4083 case 1: /* CURLAUTH_DIGEST */
4084 auth |= CURLAUTH_DIGEST;
4085 break;
4087 case 2: /* CURLAUTH_GSSNEGOTIATE */
4088 auth |= CURLAUTH_GSSNEGOTIATE;
4089 break;
4091 case 3: /* CURLAUTH_NTLM */
4092 auth |= CURLAUTH_NTLM;
4093 break;
4095 case 4: /* CURLAUTH_ANY */
4096 auth |= CURLAUTH_ANY;
4097 break;
4099 case 5: /* CURLAUTH_ANYSAFE */
4100 auth |= CURLAUTH_ANYSAFE;
4101 break;
4103 default:
4104 failwith("Invalid HTTPAUTH Value");
4105 break;
4108 listIter = Field(listIter, 1);
4111 result = curl_easy_setopt(conn->connection,
4112 CURLOPT_HTTPAUTH,
4113 auth);
4115 if (result != CURLE_OK)
4116 raiseError(conn, result);
4118 CAMLreturn0;
4119 #else
4120 #pragma message("libcurl does not implement CURLOPT_HTTPAUTH")
4121 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4122 #endif
4125 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4127 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4128 CAMLparam1(option);
4129 CURLcode result = CURLE_OK;
4131 result = curl_easy_setopt(conn->connection,
4132 CURLOPT_FTP_CREATE_MISSING_DIRS,
4133 Bool_val(option));
4135 if (result != CURLE_OK)
4136 raiseError(conn, result);
4138 CAMLreturn0;
4139 #else
4140 #pragma message("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS")
4141 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4142 #endif
4145 static void handleProxyAuth(Connection *conn, value option)
4147 #if HAVE_DECL_CURLOPT_PROXYAUTH
4148 CAMLparam1(option);
4149 CAMLlocal1(listIter);
4150 CURLcode result = CURLE_OK;
4151 long auth = CURLAUTH_NONE;
4153 listIter = option;
4155 while (!Is_long(listIter))
4157 switch (Long_val(Field(listIter, 0)))
4159 case 0: /* CURLAUTH_BASIC */
4160 auth |= CURLAUTH_BASIC;
4161 break;
4163 case 1: /* CURLAUTH_DIGEST */
4164 auth |= CURLAUTH_DIGEST;
4165 break;
4167 case 2: /* CURLAUTH_GSSNEGOTIATE */
4168 auth |= CURLAUTH_GSSNEGOTIATE;
4169 break;
4171 case 3: /* CURLAUTH_NTLM */
4172 auth |= CURLAUTH_NTLM;
4173 break;
4175 case 4: /* CURLAUTH_ANY */
4176 auth |= CURLAUTH_ANY;
4177 break;
4179 case 5: /* CURLAUTH_ANYSAFE */
4180 auth |= CURLAUTH_ANYSAFE;
4181 break;
4183 default:
4184 failwith("Invalid HTTPAUTH Value");
4185 break;
4188 listIter = Field(listIter, 1);
4191 result = curl_easy_setopt(conn->connection,
4192 CURLOPT_PROXYAUTH,
4193 auth);
4195 if (result != CURLE_OK)
4196 raiseError(conn, result);
4198 CAMLreturn0;
4199 #else
4200 #pragma message("libcurl does not implement CURLOPT_PROXYAUTH")
4201 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4202 #endif
4205 static void handleFTPResponseTimeout(Connection *conn, value option)
4207 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4208 CAMLparam1(option);
4209 CURLcode result = CURLE_OK;
4211 result = curl_easy_setopt(conn->connection,
4212 CURLOPT_FTP_RESPONSE_TIMEOUT,
4213 Long_val(option));
4215 if (result != CURLE_OK)
4216 raiseError(conn, result);
4218 CAMLreturn0;
4219 #else
4220 #pragma message("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT")
4221 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4222 #endif
4225 static void handleIPResolve(Connection *conn, value option)
4227 #if HAVE_DECL_CURLOPT_IPRESOLVE
4228 CAMLparam1(option);
4229 CURLcode result = CURLE_OK;
4231 switch (Long_val(option))
4233 case 0: /* CURL_IPRESOLVE_WHATEVER */
4234 result = curl_easy_setopt(conn->connection,
4235 CURLOPT_IPRESOLVE,
4236 CURL_IPRESOLVE_WHATEVER);
4237 break;
4239 case 1: /* CURL_IPRESOLVE_V4 */
4240 result = curl_easy_setopt(conn->connection,
4241 CURLOPT_IPRESOLVE,
4242 CURL_IPRESOLVE_V4);
4243 break;
4245 case 2: /* CURL_IPRESOLVE_V6 */
4246 result = curl_easy_setopt(conn->connection,
4247 CURLOPT_IPRESOLVE,
4248 CURL_IPRESOLVE_V6);
4249 break;
4251 default:
4252 failwith("Invalid IPRESOLVE Value");
4253 break;
4256 if (result != CURLE_OK)
4257 raiseError(conn, result);
4259 CAMLreturn0;
4260 #else
4261 #pragma message("libcurl does not implement CURLOPT_IPRESOLVE")
4262 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4263 #endif
4266 static void handleMaxFileSize(Connection *conn, value option)
4268 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4269 CAMLparam1(option);
4270 CURLcode result = CURLE_OK;
4272 result = curl_easy_setopt(conn->connection,
4273 CURLOPT_MAXFILESIZE,
4274 Int32_val(option));
4276 if (result != CURLE_OK)
4277 raiseError(conn, result);
4279 CAMLreturn0;
4280 #else
4281 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE")
4282 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4283 #endif
4286 static void handleInFileSizeLarge(Connection *conn, value option)
4288 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4289 CAMLparam1(option);
4290 CURLcode result = CURLE_OK;
4292 result = curl_easy_setopt(conn->connection,
4293 CURLOPT_INFILESIZE_LARGE,
4294 Int64_val(option));
4296 if (result != CURLE_OK)
4297 raiseError(conn, result);
4299 CAMLreturn0;
4300 #else
4301 #pragma message("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4302 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4303 #endif
4306 static void handleResumeFromLarge(Connection *conn, value option)
4308 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4309 CAMLparam1(option);
4310 CURLcode result = CURLE_OK;
4312 result = curl_easy_setopt(conn->connection,
4313 CURLOPT_RESUME_FROM_LARGE,
4314 Int64_val(option));
4316 if (result != CURLE_OK)
4317 raiseError(conn, result);
4319 CAMLreturn0;
4320 #else
4321 #pragma message("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4322 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4323 #endif
4326 static void handleMaxFileSizeLarge(Connection *conn, value option)
4328 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4329 CAMLparam1(option);
4330 CURLcode result = CURLE_OK;
4332 result = curl_easy_setopt(conn->connection,
4333 CURLOPT_MAXFILESIZE_LARGE,
4334 Int64_val(option));
4336 if (result != CURLE_OK)
4337 raiseError(conn, result);
4339 CAMLreturn0;
4340 #else
4341 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE")
4342 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4343 #endif
4346 static void handleNETRCFile(Connection *conn, value option)
4348 #if HAVE_DECL_CURLOPT_NETRC_FILE
4349 CAMLparam1(option);
4350 CURLcode result = CURLE_OK;
4352 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4354 if (conn->netrcFile != NULL)
4355 free(conn->netrcFile);
4357 conn->netrcFile = strdup(String_val(option));
4359 result = curl_easy_setopt(conn->connection,
4360 CURLOPT_NETRC_FILE,
4361 conn->netrcFile);
4363 if (result != CURLE_OK)
4364 raiseError(conn, result);
4366 CAMLreturn0;
4367 #else
4368 #pragma message("libcurl does not implement CURLOPT_NETRC_FILE")
4369 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4370 #endif
4373 static void handleFTPSSL(Connection *conn, value option)
4375 #if HAVE_DECL_CURLOPT_FTP_SSL
4376 CAMLparam1(option);
4377 CURLcode result = CURLE_OK;
4379 switch (Long_val(option))
4381 case 0: /* CURLFTPSSL_NONE */
4382 result = curl_easy_setopt(conn->connection,
4383 CURLOPT_FTP_SSL,
4384 CURLFTPSSL_NONE);
4385 break;
4387 case 1: /* CURLFTPSSL_TRY */
4388 result = curl_easy_setopt(conn->connection,
4389 CURLOPT_FTP_SSL,
4390 CURLFTPSSL_TRY);
4391 break;
4393 case 2: /* CURLFTPSSL_CONTROL */
4394 result = curl_easy_setopt(conn->connection,
4395 CURLOPT_FTP_SSL,
4396 CURLFTPSSL_CONTROL);
4397 break;
4399 case 3: /* CURLFTPSSL_ALL */
4400 result = curl_easy_setopt(conn->connection,
4401 CURLOPT_FTP_SSL,
4402 CURLFTPSSL_ALL);
4403 break;
4405 default:
4406 failwith("Invalid FTP_SSL Value");
4407 break;
4410 if (result != CURLE_OK)
4411 raiseError(conn, result);
4413 CAMLreturn0;
4414 #else
4415 #pragma message("libcurl does not implement CURLOPT_FTP_SSL")
4416 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4417 #endif
4420 static void handlePostFieldSizeLarge(Connection *conn, value option)
4422 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4423 CAMLparam1(option);
4424 CURLcode result = CURLE_OK;
4426 result = curl_easy_setopt(conn->connection,
4427 CURLOPT_POSTFIELDSIZE_LARGE,
4428 Int64_val(option));
4430 if (result != CURLE_OK)
4431 raiseError(conn, result);
4433 CAMLreturn0;
4434 #else
4435 #pragma message("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE")
4436 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4437 #endif
4440 static void handleTCPNoDelay(Connection *conn, value option)
4442 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4443 CAMLparam1(option);
4444 CURLcode result = CURLE_OK;
4446 result = curl_easy_setopt(conn->connection,
4447 CURLOPT_TCP_NODELAY,
4448 Bool_val(option));
4450 if (result != CURLE_OK)
4451 raiseError(conn, result);
4453 CAMLreturn0;
4454 #else
4455 #pragma message("libcurl does not implement CURLOPT_TCP_NODELAY")
4456 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4457 #endif
4460 static void handleFTPSSLAuth(Connection *conn, value option)
4462 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4463 CAMLparam1(option);
4464 CURLcode result = CURLE_OK;
4466 switch (Long_val(option))
4468 case 0: /* CURLFTPAUTH_DEFAULT */
4469 result = curl_easy_setopt(conn->connection,
4470 CURLOPT_FTPSSLAUTH,
4471 CURLFTPAUTH_DEFAULT);
4472 break;
4474 case 1: /* CURLFTPAUTH_SSL */
4475 result = curl_easy_setopt(conn->connection,
4476 CURLOPT_FTPSSLAUTH,
4477 CURLFTPAUTH_SSL);
4478 break;
4480 case 2: /* CURLFTPAUTH_TLS */
4481 result = curl_easy_setopt(conn->connection,
4482 CURLOPT_FTPSSLAUTH,
4483 CURLFTPAUTH_TLS);
4484 break;
4486 default:
4487 failwith("Invalid FTPSSLAUTH value");
4488 break;
4491 if (result != CURLE_OK)
4492 raiseError(conn, result);
4494 CAMLreturn0;
4495 #else
4496 #pragma message("libcurl does not implement CURLOPT_FTPSSLAUTH")
4497 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4498 #endif
4501 static void handleIOCTLFunction(Connection *conn, value option)
4503 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4504 CAMLparam1(option);
4505 CURLcode result = CURLE_OK;
4507 if (Tag_val(option) == Closure_tag)
4508 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4509 else
4510 failwith("Not a proper closure");
4512 result = curl_easy_setopt(conn->connection,
4513 CURLOPT_IOCTLFUNCTION,
4514 ioctlFunction);
4515 if (result != CURLE_OK)
4516 raiseError(conn, result);
4518 result = curl_easy_setopt(conn->connection,
4519 CURLOPT_DEBUGDATA,
4520 conn);
4522 if (result != CURLE_OK)
4523 raiseError(conn, result);
4525 CAMLreturn0;
4526 #else
4527 #pragma message("libcurl does not implement CURLOPT_IOCTLFUNCTION")
4528 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4529 #endif
4532 static void handleFTPAccount(Connection *conn, value option)
4534 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4535 CAMLparam1(option);
4536 CURLcode result = CURLE_OK;
4538 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4540 if (conn->ftpaccount != NULL)
4541 free(conn->ftpaccount);
4543 conn->ftpaccount = strdup(String_val(option));
4545 result = curl_easy_setopt(conn->connection,
4546 CURLOPT_FTP_ACCOUNT,
4547 conn->ftpaccount);
4549 if (result != CURLE_OK)
4550 raiseError(conn, result);
4552 CAMLreturn0;
4553 #else
4554 #pragma message("libcurl does not implement CURLOPT_FTP_ACCOUNT")
4555 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4556 #endif
4559 static void handleCookieList(Connection *conn, value option)
4561 #if HAVE_DECL_CURLOPT_COOKIELIST
4562 CAMLparam1(option);
4563 CURLcode result = CURLE_OK;
4565 Store_field(conn->ocamlValues, OcamlCookieList, option);
4567 if (conn->cookielist != NULL)
4568 free(conn->cookielist);
4570 conn->cookielist = strdup(String_val(option));
4572 result = curl_easy_setopt(conn->connection,
4573 CURLOPT_COOKIELIST,
4574 conn->cookielist);
4576 if (result != CURLE_OK)
4577 raiseError(conn, result);
4579 CAMLreturn0;
4580 #else
4581 #pragma message("libcurl does not implement CURLOPT_COOKIELIST")
4582 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4583 #endif
4586 static void handleIgnoreContentLength(Connection *conn, value option)
4588 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4589 CAMLparam1(option);
4590 CURLcode result = CURLE_OK;
4592 result = curl_easy_setopt(conn->connection,
4593 CURLOPT_IGNORE_CONTENT_LENGTH,
4594 Bool_val(option));
4596 if (result != CURLE_OK)
4597 raiseError(conn, result);
4599 CAMLreturn0;
4600 #else
4601 #pragma message("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH")
4602 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4603 #endif
4606 static void handleFTPSkipPASVIP(Connection *conn, value option)
4608 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4609 CAMLparam1(option);
4610 CURLcode result = CURLE_OK;
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_SKIP_PASV_IP,
4614 Bool_val(option));
4616 if (result != CURLE_OK)
4617 raiseError(conn, result);
4619 CAMLreturn0;
4620 #else
4621 #pragma message("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP")
4622 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4623 #endif
4626 static void handleFTPFileMethod(Connection *conn, value option)
4628 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4629 CAMLparam1(option);
4630 CURLcode result = CURLE_OK;
4632 switch (Long_val(option))
4634 case 0: /* CURLFTPMETHOD_DEFAULT */
4635 result = curl_easy_setopt(conn->connection,
4636 CURLOPT_FTP_FILEMETHOD,
4637 CURLFTPMETHOD_DEFAULT);
4638 break;
4640 case 1: /* CURLFTMETHOD_MULTICWD */
4641 result = curl_easy_setopt(conn->connection,
4642 CURLOPT_FTP_FILEMETHOD,
4643 CURLFTPMETHOD_MULTICWD);
4644 break;
4646 case 2: /* CURLFTPMETHOD_NOCWD */
4647 result = curl_easy_setopt(conn->connection,
4648 CURLOPT_FTP_FILEMETHOD,
4649 CURLFTPMETHOD_NOCWD);
4650 break;
4652 case 3: /* CURLFTPMETHOD_SINGLECWD */
4653 result = curl_easy_setopt(conn->connection,
4654 CURLOPT_FTP_FILEMETHOD,
4655 CURLFTPMETHOD_SINGLECWD);
4657 default:
4658 failwith("Invalid FTP_FILEMETHOD value");
4659 break;
4662 if (result != CURLE_OK)
4663 raiseError(conn, result);
4665 CAMLreturn0;
4666 #else
4667 #pragma message("libcurl does not implement CURLOPT_FTP_FILEMETHOD")
4668 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4669 #endif
4672 static void handleLocalPort(Connection *conn, value option)
4674 #if HAVE_DECL_CURLOPT_LOCALPORT
4675 CAMLparam1(option);
4676 CURLcode result = CURLE_OK;
4678 result = curl_easy_setopt(conn->connection,
4679 CURLOPT_LOCALPORT,
4680 Long_val(option));
4682 if (result != CURLE_OK)
4683 raiseError(conn, result);
4685 CAMLreturn0;
4686 #else
4687 #pragma message("libcurl does not implement CURLOPT_LOCALPORT")
4688 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4689 #endif
4692 static void handleLocalPortRange(Connection *conn, value option)
4694 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4695 CAMLparam1(option);
4696 CURLcode result = CURLE_OK;
4698 result = curl_easy_setopt(conn->connection,
4699 CURLOPT_LOCALPORTRANGE,
4700 Long_val(option));
4702 if (result != CURLE_OK)
4703 raiseError(conn, result);
4705 CAMLreturn0;
4706 #else
4707 #pragma message("libcurl does not implement CURLOPT_LOCALPORTRANGE")
4708 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4709 #endif
4712 static void handleConnectOnly(Connection *conn, value option)
4714 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4715 CAMLparam1(option);
4716 CURLcode result = CURLE_OK;
4718 result = curl_easy_setopt(conn->connection,
4719 CURLOPT_CONNECT_ONLY,
4720 Bool_val(option));
4722 if (result != CURLE_OK)
4723 raiseError(conn, result);
4725 CAMLreturn0;
4726 #else
4727 #pragma message("libcurl does not implement CURLOPT_CONNECT_ONLY")
4728 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4729 #endif
4732 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4734 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4735 CAMLparam1(option);
4736 CURLcode result = CURLE_OK;
4738 result = curl_easy_setopt(conn->connection,
4739 CURLOPT_MAX_SEND_SPEED_LARGE,
4740 Int64_val(option));
4742 if (result != CURLE_OK)
4743 raiseError(conn, result);
4745 CAMLreturn0;
4746 #else
4747 #pragma message("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE")
4748 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4749 #endif
4752 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4754 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4755 CAMLparam1(option);
4756 CURLcode result = CURLE_OK;
4758 result = curl_easy_setopt(conn->connection,
4759 CURLOPT_MAX_RECV_SPEED_LARGE,
4760 Int64_val(option));
4762 if (result != CURLE_OK)
4763 raiseError(conn, result);
4765 CAMLreturn0;
4766 #else
4767 #pragma message("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE")
4768 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4769 #endif
4772 static void handleFTPAlternativeToUser(Connection *conn, value option)
4774 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4775 CAMLparam1(option);
4776 CURLcode result = CURLE_OK;
4778 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4780 if (conn->ftpAlternativeToUser != NULL)
4781 free(conn->ftpAlternativeToUser);
4783 conn->ftpAlternativeToUser = strdup(String_val(option));
4785 result = curl_easy_setopt(conn->connection,
4786 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4787 conn->ftpAlternativeToUser);
4789 if (result != CURLE_OK)
4790 raiseError(conn, result);
4792 CAMLreturn0;
4793 #else
4794 #pragma message("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER")
4795 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4796 #endif
4799 static void handleSSLSessionIdCache(Connection *conn, value option)
4801 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4802 CAMLparam1(option);
4803 CURLcode result = CURLE_OK;
4805 result = curl_easy_setopt(conn->connection,
4806 CURLOPT_SSL_SESSIONID_CACHE,
4807 Bool_val(option));
4809 if (result != CURLE_OK)
4810 raiseError(conn, result);
4812 CAMLreturn0;
4813 #else
4814 #pragma message("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE")
4815 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4816 #endif
4819 static void handleSSHAuthTypes(Connection *conn, value option)
4821 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4822 CAMLparam1(option);
4823 CAMLlocal1(listIter);
4824 CURLcode result = CURLE_OK;
4825 long authTypes = CURLSSH_AUTH_NONE;
4827 listIter = option;
4829 while (!Is_long(listIter))
4831 switch (Long_val(Field(listIter, 0)))
4833 case 0: /* CURLSSH_AUTH_ANY */
4834 authTypes |= CURLSSH_AUTH_ANY;
4835 break;
4837 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4838 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4839 break;
4841 case 2: /* CURLSSH_AUTH_PASSWORD */
4842 authTypes |= CURLSSH_AUTH_PASSWORD;
4843 break;
4845 case 3: /* CURLSSH_AUTH_HOST */
4846 authTypes |= CURLSSH_AUTH_HOST;
4847 break;
4849 case 4: /* CURLSSH_AUTH_KEYBOARD */
4850 authTypes |= CURLSSH_AUTH_KEYBOARD;
4851 break;
4853 default:
4854 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4855 break;
4858 listIter = Field(listIter, 1);
4861 result = curl_easy_setopt(conn->connection,
4862 CURLOPT_SSH_AUTH_TYPES,
4863 authTypes);
4865 if (result != CURLE_OK)
4866 raiseError(conn, result);
4868 CAMLreturn0;
4869 #else
4870 #pragma message("libcurl does not implement CURLOPT_SSH_AUTH_TYPES")
4871 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4872 #endif
4875 static void handleSSHPublicKeyFile(Connection *conn, value option)
4877 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4878 CAMLparam1(option);
4879 CURLcode result = CURLE_OK;
4881 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4883 if (conn->sshPublicKeyFile != NULL)
4884 free(conn->sshPublicKeyFile);
4886 conn->sshPublicKeyFile = strdup(String_val(option));
4888 result = curl_easy_setopt(conn->connection,
4889 CURLOPT_SSH_PUBLIC_KEYFILE,
4890 conn->sshPublicKeyFile);
4892 if (result != CURLE_OK)
4893 raiseError(conn, result);
4895 CAMLreturn0;
4896 #else
4897 #pragma message("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE")
4898 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4899 #endif
4902 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4904 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4905 CAMLparam1(option);
4906 CURLcode result = CURLE_OK;
4908 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4910 if (conn->sshPrivateKeyFile != NULL)
4911 free(conn->sshPrivateKeyFile);
4913 conn->sshPrivateKeyFile = strdup(String_val(option));
4915 result = curl_easy_setopt(conn->connection,
4916 CURLOPT_SSH_PRIVATE_KEYFILE,
4917 conn->sshPrivateKeyFile);
4919 if (result != CURLE_OK)
4920 raiseError(conn, result);
4922 CAMLreturn0;
4923 #else
4924 #pragma message("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE")
4925 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4926 #endif
4929 static void handleFTPSSLCCC(Connection *conn, value option)
4931 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4932 CAMLparam1(option);
4933 CURLcode result = CURLE_OK;
4935 switch (Long_val(option))
4937 case 0: /* CURLFTPSSL_CCC_NONE */
4938 result = curl_easy_setopt(conn->connection,
4939 CURLOPT_FTP_SSL_CCC,
4940 CURLFTPSSL_CCC_NONE);
4941 break;
4943 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4944 result = curl_easy_setopt(conn->connection,
4945 CURLOPT_FTP_SSL_CCC,
4946 CURLFTPSSL_CCC_PASSIVE);
4947 break;
4949 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4950 result = curl_easy_setopt(conn->connection,
4951 CURLOPT_FTP_SSL_CCC,
4952 CURLFTPSSL_CCC_ACTIVE);
4953 break;
4955 default:
4956 failwith("Invalid FTPSSL_CCC value");
4957 break;
4960 if (result != CURLE_OK)
4961 raiseError(conn, result);
4963 CAMLreturn0;
4964 #else
4965 #pragma message("libcurl does not implement CURLOPT_FTP_SSL_CCC")
4966 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4967 #endif
4970 static void handleTimeoutMS(Connection *conn, value option)
4972 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4973 CAMLparam1(option);
4974 CURLcode result = CURLE_OK;
4976 result = curl_easy_setopt(conn->connection,
4977 CURLOPT_TIMEOUT_MS,
4978 Long_val(option));
4980 if (result != CURLE_OK)
4981 raiseError(conn, result);
4983 CAMLreturn0;
4984 #else
4985 #pragma message("libcurl does not implement CURLOPT_TIMEOUT_MS")
4986 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4987 #endif
4990 static void handleConnectTimeoutMS(Connection *conn, value option)
4992 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4993 CAMLparam1(option);
4994 CURLcode result = CURLE_OK;
4996 result = curl_easy_setopt(conn->connection,
4997 CURLOPT_CONNECTTIMEOUT_MS,
4998 Long_val(option));
5000 if (result != CURLE_OK)
5001 raiseError(conn, result);
5003 CAMLreturn0;
5004 #else
5005 #pragma message("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS")
5006 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
5007 #endif
5010 static void handleHTTPTransferDecoding(Connection *conn, value option)
5012 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5013 CAMLparam1(option);
5014 CURLcode result = CURLE_OK;
5016 result = curl_easy_setopt(conn->connection,
5017 CURLOPT_HTTP_TRANSFER_DECODING,
5018 Bool_val(option));
5020 if (result != CURLE_OK)
5021 raiseError(conn, result);
5023 CAMLreturn0;
5024 #else
5025 #pragma message("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING")
5026 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
5027 #endif
5030 static void handleHTTPContentDecoding(Connection *conn, value option)
5032 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5033 CAMLparam1(option);
5034 CURLcode result = CURLE_OK;
5036 result = curl_easy_setopt(conn->connection,
5037 CURLOPT_HTTP_CONTENT_DECODING,
5038 Bool_val(option));
5040 if (result != CURLE_OK)
5041 raiseError(conn, result);
5043 CAMLreturn0;
5044 #else
5045 #pragma message("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING")
5046 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5047 #endif
5050 static void handleNewFilePerms(Connection *conn, value option)
5052 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5053 CAMLparam1(option);
5054 CURLcode result = CURLE_OK;
5056 result = curl_easy_setopt(conn->connection,
5057 CURLOPT_NEW_FILE_PERMS,
5058 Long_val(option));
5060 if (result != CURLE_OK)
5061 raiseError(conn, result);
5063 CAMLreturn0;
5064 #else
5065 #pragma message("libcurl does not implement CURLOPT_NEW_FILE_PERMS")
5066 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5067 #endif
5070 static void handleNewDirectoryPerms(Connection *conn, value option)
5072 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5073 CAMLparam1(option);
5074 CURLcode result = CURLE_OK;
5076 result = curl_easy_setopt(conn->connection,
5077 CURLOPT_NEW_DIRECTORY_PERMS,
5078 Long_val(option));
5080 if (result != CURLE_OK)
5081 raiseError(conn, result);
5083 CAMLreturn0;
5084 #else
5085 #pragma message("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS")
5086 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5087 #endif
5090 static void handlePost301(Connection *conn, value option)
5092 #if HAVE_DECL_CURLOPT_POST301
5093 CAMLparam1(option);
5094 CURLcode result = CURLE_OK;
5096 result = curl_easy_setopt(conn->connection,
5097 CURLOPT_POST301,
5098 Bool_val(option));
5100 if (result != CURLE_OK)
5101 raiseError(conn, result);
5103 CAMLreturn0;
5104 #else
5105 #pragma message("libcurl does not implement CURLOPT_POST301")
5106 failwith("libcurl does not implement CURLOPT_POST301");
5107 #endif
5110 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5112 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5113 CAMLparam1(option);
5114 CURLcode result = CURLE_OK;
5116 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5118 if (conn->sshHostPublicKeyMD5 != NULL)
5119 free(conn->sshHostPublicKeyMD5);
5121 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5123 result = curl_easy_setopt(conn->connection,
5124 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5125 conn->sshHostPublicKeyMD5);
5127 if (result != CURLE_OK)
5128 raiseError(conn, result);
5130 CAMLreturn0;
5131 #else
5132 #pragma message("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5")
5133 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5134 #endif
5137 static void handleCopyPostFields(Connection *conn, value option)
5139 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5140 CAMLparam1(option);
5141 CURLcode result = CURLE_OK;
5143 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5145 if (conn->copyPostFields != NULL)
5146 free(conn->copyPostFields);
5148 conn->copyPostFields = strdup(String_val(option));
5150 result = curl_easy_setopt(conn->connection,
5151 CURLOPT_COPYPOSTFIELDS,
5152 conn->copyPostFields);
5154 if (result != CURLE_OK)
5155 raiseError(conn, result);
5157 CAMLreturn0;
5158 #else
5159 #pragma message("libcurl does not implement CURLOPT_COPYPOSTFIELDS")
5160 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5161 #endif
5164 static void handleProxyTransferMode(Connection *conn, value option)
5166 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5167 CAMLparam1(option);
5168 CURLcode result = CURLE_OK;
5170 result = curl_easy_setopt(conn->connection,
5171 CURLOPT_PROXY_TRANSFER_MODE,
5172 Bool_val(option));
5174 if (result != CURLE_OK)
5175 raiseError(conn, result);
5177 CAMLreturn0;
5178 #else
5179 #pragma message("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE")
5180 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5181 #endif
5184 static void handleSeekFunction(Connection *conn, value option)
5186 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5187 CAMLparam1(option);
5188 CURLcode result = CURLE_OK;
5190 if (Tag_val(option) == Closure_tag)
5191 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5192 else
5193 failwith("Not a proper closure");
5195 result = curl_easy_setopt(conn->connection,
5196 CURLOPT_SEEKFUNCTION,
5197 seekFunction);
5199 if (result != CURLE_OK)
5200 raiseError(conn, result);
5202 result = curl_easy_setopt(conn->connection,
5203 CURLOPT_SEEKDATA,
5204 conn);
5206 if (result != CURLE_OK)
5207 raiseError(conn, result);
5209 CAMLreturn0;
5210 #else
5211 #pragma message("libcurl does not implement CURLOPT_SEEKFUNCTION")
5212 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5213 #endif
5216 static void handleAutoReferer(Connection *conn, value option)
5218 #if HAVE_DECL_CURLOPT_AUTOREFERER
5219 CAMLparam1(option);
5220 CURLcode result = curl_easy_setopt(conn->connection,
5221 CURLOPT_AUTOREFERER,
5222 Bool_val(option));
5224 if (result != CURLE_OK)
5225 raiseError(conn, result);
5227 CAMLreturn0;
5228 #else
5229 #pragma message("libcurl does not implement CURLOPT_AUTOREFERER")
5230 failwith("libcurl does not implement CURLOPT_AUTOREFERER");
5231 #endif
5234 static void handleOpenSocketFunction(Connection *conn, value option)
5236 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5237 CAMLparam1(option);
5238 CURLcode result = CURLE_OK;
5240 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5242 result = curl_easy_setopt(conn->connection,
5243 CURLOPT_OPENSOCKETDATA,
5244 conn);
5246 if (result != CURLE_OK)
5247 raiseError(conn, result);
5249 result = curl_easy_setopt(conn->connection,
5250 CURLOPT_OPENSOCKETFUNCTION,
5251 openSocketFunction);
5253 if (result != CURLE_OK)
5254 raiseError(conn, result);
5256 CAMLreturn0;
5257 #else
5258 #pragma message("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION")
5259 failwith("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION");
5260 #endif
5263 static void handleProxyType(Connection *conn, value option)
5265 #if HAVE_DECL_CURLOPT_PROXYTYPE
5266 CAMLparam1(option);
5267 CURLcode result = CURLE_OK;
5268 long proxy_type;
5270 switch (Long_val(option))
5272 case 0: proxy_type = CURLPROXY_HTTP; break;
5273 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5274 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5275 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5276 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5277 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5278 default:
5279 failwith("Invalid curl proxy type");
5282 result = curl_easy_setopt(conn->connection,
5283 CURLOPT_PROXYTYPE,
5284 proxy_type);
5286 if (result != CURLE_OK)
5287 raiseError(conn, result);
5289 CAMLreturn0;
5290 #else
5291 #pragma message("libcurl does not implement CURLOPT_PROXYTYPE")
5292 failwith("libcurl does not implement CURLOPT_PROXYTYPE");
5293 #endif
5296 #if HAVE_DECL_CURLOPT_PROTOCOLS && HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5298 long protoMap[] =
5300 CURLPROTO_ALL,
5301 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
5302 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
5303 /* factor out with autoconf? */
5304 #if defined(CURLPROTO_IMAP)
5305 CURLPROTO_IMAP,
5306 #else
5308 #endif
5309 #if defined(CURLPROTO_IMAPS)
5310 CURLPROTO_IMAPS,
5311 #else
5313 #endif
5314 #if defined(CURLPROTO_POP3)
5315 CURLPROTO_POP3,
5316 #else
5318 #endif
5319 #if defined(CURLPROTO_POP3S)
5320 CURLPROTO_POP3S,
5321 #else
5323 #endif
5324 #if defined(CURLPROTO_SMTP)
5325 CURLPROTO_SMTP,
5326 #else
5328 #endif
5329 #if defined(CURLPROTO_SMTPS)
5330 CURLPROTO_SMTPS,
5331 #else
5333 #endif
5334 #if defined(CURLPROTO_RTSP)
5335 CURLPROTO_RTSP,
5336 #else
5338 #endif
5339 #if defined(CURLPROTO_RTMP)
5340 CURLPROTO_RTMP,
5341 #else
5343 #endif
5344 #if defined(CURLPROTO_RTMPT)
5345 CURLPROTO_RTMPT,
5346 #else
5348 #endif
5349 #if defined(CURLPROTO_RTMPE)
5350 CURLPROTO_RTMPE,
5351 #else
5353 #endif
5354 #if defined(CURLPROTO_RTMPTE)
5355 CURLPROTO_RTMPTE,
5356 #else
5358 #endif
5359 #if defined(CURLPROTO_RTMPS)
5360 CURLPROTO_RTMPS,
5361 #else
5363 #endif
5364 #if defined(CURLPROTO_RTMPTS)
5365 CURLPROTO_RTMPTS,
5366 #else
5368 #endif
5369 #if defined(CURLPROTO_GOPHER)
5370 CURLPROTO_GOPHER,
5371 #else
5373 #endif
5376 static void handleProtocolsOption(CURLoption curlopt, Connection *conn, value option)
5378 CAMLparam1(option);
5379 CURLcode result = CURLE_OK;
5380 long protocols = 0;
5381 int index;
5383 while (Val_emptylist != option)
5385 index = Int_val(Field(option, 0));
5386 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
5387 failwith("Invalid curl protocol");
5389 protocols = protocols | protoMap[index];
5391 option = Field(option, 1);
5394 result = curl_easy_setopt(conn->connection,
5395 curlopt,
5396 protocols);
5398 if (result != CURLE_OK)
5399 raiseError(conn, result);
5401 CAMLreturn0;
5404 static void handleProtocols(Connection *conn, value option)
5406 handleProtocolsOption(CURLOPT_PROTOCOLS, conn, option);
5409 static void handleRedirProtocols(Connection *conn, value option)
5411 handleProtocolsOption(CURLOPT_REDIR_PROTOCOLS, conn, option);
5414 #else
5415 #pragma message("libcurl does not implement CURLOPT_PROTOCOLS or CURLOPT_REDIR_PROTOCOLS")
5416 static void handleProtocols(Connection *conn, value option)
5418 failwith("libcurl does not implement CURLOPT_PROTOCOLS");
5420 static void handleRedirProtocols(Connection *conn, value option)
5422 failwith("libcurl does not implement CURLOPT_REDIR_PROTOCOLS");
5424 #endif
5426 #if HAVE_DECL_CURLOPT_RESOLVE
5427 static void handleResolve(Connection *conn, value option)
5429 CAMLparam1(option);
5430 CAMLlocal1(head);
5432 CURLcode result = CURLE_OK;
5434 free_curl_slist(conn->resolve);
5435 conn->resolve = NULL;
5437 head = option;
5439 while (head != Val_emptylist)
5441 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
5442 head = Field(head, 1);
5445 result = curl_easy_setopt(conn->connection,
5446 CURLOPT_RESOLVE,
5447 conn->resolve);
5449 if (result != CURLE_OK)
5450 raiseError(conn, result);
5452 CAMLreturn0;
5455 #else
5456 #pragma message("libcurl does not implement CURLOPT_RESOLVE")
5457 static void handleResolve(Connection *conn, value option)
5459 failwith("libcurl does not implement CURLOPT_RESOLVE");
5461 #endif
5463 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5464 static void handleDnsServers(Connection *conn, value option)
5466 CAMLparam1(option);
5468 CURLcode result = CURLE_OK;
5469 free_if(conn->dns_servers);
5471 conn->dns_servers = strdup(String_val(option));
5473 result = curl_easy_setopt(conn->connection,
5474 CURLOPT_DNS_SERVERS,
5475 conn->dns_servers);
5477 if (result != CURLE_OK)
5478 raiseError(conn, result);
5480 CAMLreturn0;
5482 #else
5483 #pragma message("libcurl does not implement CURLOPT_DNS_SERVERS")
5484 static void handleDnsServers(Connection *conn, value option)
5486 failwith("libcurl does not implement CURLOPT_DNS_SERVERS");
5488 #endif
5491 ** curl_easy_setopt helper function
5494 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5496 CAMLparam2(conn, option);
5497 CAMLlocal1(data);
5498 Connection *connection = Connection_val(conn);
5500 checkConnection(connection);
5502 if (Is_long(option))
5504 char error[128];
5506 sprintf(error, "Unimplemented Option: %s",
5507 findOption(unimplementedOptionMap,
5508 (CURLoption)(Long_val(option))));
5510 failwith(error);
5513 if (!Is_block(option))
5514 failwith("Not a block");
5516 if (Wosize_val(option) < 1)
5517 failwith("Insufficient data in block");
5519 data = Field(option, 0);
5521 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5522 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5523 data);
5524 else
5525 failwith("Invalid CURLOPT Option");
5527 CAMLreturn(Val_unit);
5531 ** curl_easy_perform helper function
5534 CAMLprim value helper_curl_easy_perform(value conn)
5536 CAMLparam1(conn);
5537 CURLcode result = CURLE_OK;
5538 Connection *connection = Connection_val(conn);
5540 checkConnection(connection);
5542 enter_blocking_section();
5543 result = curl_easy_perform(connection->connection);
5544 leave_blocking_section();
5546 if (result != CURLE_OK)
5547 raiseError(connection, result);
5549 CAMLreturn(Val_unit);
5553 ** curl_easy_cleanup helper function
5556 CAMLprim value helper_curl_easy_cleanup(value conn)
5558 CAMLparam1(conn);
5559 Connection *connection = Connection_val(conn);
5561 checkConnection(connection);
5563 removeConnection(connection);
5565 CAMLreturn(Val_unit);
5569 ** curl_easy_duphandle helper function
5572 CAMLprim value helper_curl_easy_duphandle(value conn)
5574 CAMLparam1(conn);
5575 CAMLlocal1(result);
5576 Connection *connection = Connection_val(conn);
5578 checkConnection(connection);
5580 result = caml_alloc(1, Abstract_tag);
5581 Field(result, 0) = (value)duplicateConnection(connection);
5583 CAMLreturn(result);
5587 ** curl_easy_getinfo helper function
5590 enum GetInfoResultType {
5591 StringValue, LongValue, DoubleValue, StringListValue
5594 value convertStringList(struct curl_slist *slist)
5596 CAMLparam0();
5597 CAMLlocal3(result, current, next);
5598 struct curl_slist *p = slist;
5600 result = Val_int(0);
5601 current = Val_int(0);
5602 next = Val_int(0);
5604 while (p != NULL)
5606 next = alloc_tuple(2);
5607 Store_field(next, 0, copy_string(p->data));
5608 Store_field(next, 1, Val_int(0));
5610 if (result == Val_int(0))
5611 result = next;
5613 if (current != Val_int(0))
5614 Store_field(current, 1, next);
5616 current = next;
5618 p = p->next;
5621 curl_slist_free_all(slist);
5623 CAMLreturn(result);
5626 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5628 CAMLparam2(conn, option);
5629 CAMLlocal1(result);
5630 CURLcode curlResult;
5631 Connection *connection = Connection_val(conn);
5632 enum GetInfoResultType resultType;
5633 char *strValue = NULL;
5634 double doubleValue;
5635 long longValue;
5636 struct curl_slist *stringListValue = NULL;
5638 checkConnection(connection);
5640 switch(Long_val(option))
5642 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5643 case 0: /* CURLINFO_EFFECTIVE_URL */
5644 resultType = StringValue;
5646 curlResult = curl_easy_getinfo(connection->connection,
5647 CURLINFO_EFFECTIVE_URL,
5648 &strValue);
5649 break;
5650 #else
5651 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5652 #endif
5654 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5655 case 1: /* CURLINFO_HTTP_CODE */
5656 case 2: /* CURLINFO_RESPONSE_CODE */
5657 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5658 resultType = LongValue;
5660 curlResult = curl_easy_getinfo(connection->connection,
5661 CURLINFO_RESPONSE_CODE,
5662 &longValue);
5663 #else
5664 resultType = LongValue;
5666 curlResult = curl_easy_getinfo(connection->connection,
5667 CURLINFO_HTTP_CODE,
5668 &longValue);
5669 #endif
5670 break;
5671 #endif
5673 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5674 case 3: /* CURLINFO_TOTAL_TIME */
5675 resultType = DoubleValue;
5677 curlResult = curl_easy_getinfo(connection->connection,
5678 CURLINFO_TOTAL_TIME,
5679 &doubleValue);
5680 break;
5681 #endif
5683 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5684 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5685 resultType = DoubleValue;
5687 curlResult = curl_easy_getinfo(connection->connection,
5688 CURLINFO_NAMELOOKUP_TIME,
5689 &doubleValue);
5690 break;
5691 #endif
5693 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5694 case 5: /* CURLINFO_CONNECT_TIME */
5695 resultType = DoubleValue;
5697 curlResult = curl_easy_getinfo(connection->connection,
5698 CURLINFO_CONNECT_TIME,
5699 &doubleValue);
5700 break;
5701 #endif
5703 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5704 case 6: /* CURLINFO_PRETRANSFER_TIME */
5705 resultType = DoubleValue;
5707 curlResult = curl_easy_getinfo(connection->connection,
5708 CURLINFO_PRETRANSFER_TIME,
5709 &doubleValue);
5710 break;
5711 #endif
5713 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5714 case 7: /* CURLINFO_SIZE_UPLOAD */
5715 resultType = DoubleValue;
5717 curlResult = curl_easy_getinfo(connection->connection,
5718 CURLINFO_SIZE_UPLOAD,
5719 &doubleValue);
5720 break;
5721 #endif
5723 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5724 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5725 resultType = DoubleValue;
5727 curlResult = curl_easy_getinfo(connection->connection,
5728 CURLINFO_SIZE_DOWNLOAD,
5729 &doubleValue);
5730 break;
5731 #endif
5733 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5734 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5735 resultType = DoubleValue;
5737 curlResult = curl_easy_getinfo(connection->connection,
5738 CURLINFO_SPEED_DOWNLOAD,
5739 &doubleValue);
5740 break;
5741 #endif
5743 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5744 case 10: /* CURLINFO_SPEED_UPLOAD */
5745 resultType = DoubleValue;
5747 curlResult = curl_easy_getinfo(connection->connection,
5748 CURLINFO_SPEED_UPLOAD,
5749 &doubleValue);
5750 break;
5752 #endif
5754 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5755 case 11: /* CURLINFO_HEADER_SIZE */
5756 resultType = LongValue;
5758 curlResult = curl_easy_getinfo(connection->connection,
5759 CURLINFO_HEADER_SIZE,
5760 &longValue);
5761 break;
5762 #endif
5764 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5765 case 12: /* CURLINFO_REQUEST_SIZE */
5766 resultType = LongValue;
5768 curlResult = curl_easy_getinfo(connection->connection,
5769 CURLINFO_REQUEST_SIZE,
5770 &longValue);
5771 break;
5772 #endif
5774 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5775 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5776 resultType = LongValue;
5778 curlResult = curl_easy_getinfo(connection->connection,
5779 CURLINFO_SSL_VERIFYRESULT,
5780 &longValue);
5781 break;
5782 #endif
5784 #if HAVE_DECL_CURLINFO_FILETIME
5785 case 14: /* CURLINFO_FILETIME */
5786 resultType = DoubleValue;
5788 curlResult = curl_easy_getinfo(connection->connection,
5789 CURLINFO_FILETIME,
5790 &longValue);
5792 doubleValue = longValue;
5793 break;
5794 #endif
5796 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5797 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5798 resultType = DoubleValue;
5800 curlResult = curl_easy_getinfo(connection->connection,
5801 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5802 &doubleValue);
5803 break;
5804 #endif
5806 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5807 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5808 resultType = DoubleValue;
5810 curlResult = curl_easy_getinfo(connection->connection,
5811 CURLINFO_CONTENT_LENGTH_UPLOAD,
5812 &doubleValue);
5813 break;
5814 #endif
5816 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5817 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5818 resultType = DoubleValue;
5820 curlResult = curl_easy_getinfo(connection->connection,
5821 CURLINFO_STARTTRANSFER_TIME,
5822 &doubleValue);
5823 break;
5824 #endif
5826 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5827 case 18: /* CURLINFO_CONTENT_TYPE */
5828 resultType = StringValue;
5830 curlResult = curl_easy_getinfo(connection->connection,
5831 CURLINFO_CONTENT_TYPE,
5832 &strValue);
5833 break;
5834 #endif
5836 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5837 case 19: /* CURLINFO_REDIRECT_TIME */
5838 resultType = DoubleValue;
5840 curlResult = curl_easy_getinfo(connection->connection,
5841 CURLINFO_REDIRECT_TIME,
5842 &doubleValue);
5843 break;
5844 #endif
5846 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5847 case 20: /* CURLINFO_REDIRECT_COUNT */
5848 resultType = LongValue;
5850 curlResult = curl_easy_getinfo(connection->connection,
5851 CURLINFO_REDIRECT_COUNT,
5852 &longValue);
5853 break;
5854 #endif
5856 #if HAVE_DECL_CURLINFO_PRIVATE
5857 case 21: /* CURLINFO_PRIVATE */
5858 resultType = StringValue;
5860 curlResult = curl_easy_getinfo(connection->connection,
5861 CURLINFO_PRIVATE,
5862 &strValue);
5863 break;
5864 #endif
5866 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5867 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5868 resultType = LongValue;
5870 curlResult = curl_easy_getinfo(connection->connection,
5871 CURLINFO_HTTP_CONNECTCODE,
5872 &longValue);
5873 break;
5874 #endif
5876 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5877 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5878 resultType = LongValue;
5880 curlResult = curl_easy_getinfo(connection->connection,
5881 CURLINFO_HTTPAUTH_AVAIL,
5882 &longValue);
5883 break;
5884 #endif
5886 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5887 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5888 resultType = LongValue;
5890 curlResult = curl_easy_getinfo(connection->connection,
5891 CURLINFO_PROXYAUTH_AVAIL,
5892 &longValue);
5893 break;
5894 #endif
5896 #if HAVE_DECL_CURLINFO_OS_ERRNO
5897 case 25: /* CURLINFO_OS_ERRNO */
5898 resultType = LongValue;
5900 curlResult = curl_easy_getinfo(connection->connection,
5901 CURLINFO_OS_ERRNO,
5902 &longValue);
5903 break;
5904 #endif
5906 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5907 case 26: /* CURLINFO_NUM_CONNECTS */
5908 resultType = LongValue;
5910 curlResult = curl_easy_getinfo(connection->connection,
5911 CURLINFO_NUM_CONNECTS,
5912 &longValue);
5913 break;
5914 #endif
5916 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5917 case 27: /* CURLINFO_SSL_ENGINES */
5918 resultType = StringListValue;
5920 curlResult = curl_easy_getinfo(connection->connection,
5921 CURLINFO_SSL_ENGINES,
5922 &stringListValue);
5923 break;
5924 #endif
5926 #if HAVE_DECL_CURLINFO_COOKIELIST
5927 case 28: /* CURLINFO_COOKIELIST */
5928 resultType = StringListValue;
5930 curlResult = curl_easy_getinfo(connection->connection,
5931 CURLINFO_COOKIELIST,
5932 &stringListValue);
5933 break;
5934 #endif
5936 #if HAVE_DECL_CURLINFO_LASTSOCKET
5937 case 29: /* CURLINFO_LASTSOCKET */
5938 resultType = LongValue;
5940 curlResult = curl_easy_getinfo(connection->connection,
5941 CURLINFO_LASTSOCKET,
5942 &longValue);
5943 break;
5944 #endif
5946 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5947 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5948 resultType = StringValue;
5950 curlResult = curl_easy_getinfo(connection->connection,
5951 CURLINFO_FTP_ENTRY_PATH,
5952 &strValue);
5953 break;
5954 #endif
5956 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5957 case 31: /* CURLINFO_REDIRECT_URL */
5958 resultType = StringValue;
5960 curlResult = curl_easy_getinfo(connection->connection,
5961 CURLINFO_REDIRECT_URL,
5962 &strValue);
5963 break;
5964 #else
5965 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5966 #endif
5968 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5969 case 32: /* CURLINFO_PRIMARY_IP */
5970 resultType = StringValue;
5972 curlResult = curl_easy_getinfo(connection->connection,
5973 CURLINFO_PRIMARY_IP,
5974 &strValue);
5975 break;
5976 #else
5977 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5978 #endif
5980 #if HAVE_DECL_CURLINFO_LOCAL_IP
5981 case 33: /* CURLINFO_LOCAL_IP */
5982 resultType = StringValue;
5984 curlResult = curl_easy_getinfo(connection->connection,
5985 CURLINFO_LOCAL_IP,
5986 &strValue);
5987 break;
5988 #else
5989 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
5990 #endif
5992 #if HAVE_DECL_CURLINFO_LOCAL_PORT
5993 case 34: /* CURLINFO_LOCAL_PORT */
5994 resultType = LongValue;
5996 curlResult = curl_easy_getinfo(connection->connection,
5997 CURLINFO_LOCAL_PORT,
5998 &longValue);
5999 break;
6000 #else
6001 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
6002 #endif
6004 default:
6005 failwith("Invalid CURLINFO Option");
6006 break;
6009 if (curlResult != CURLE_OK)
6010 raiseError(connection, curlResult);
6012 switch (resultType)
6014 case StringValue:
6015 result = alloc(1, StringValue);
6016 Store_field(result, 0, copy_string(strValue?strValue:""));
6017 break;
6019 case LongValue:
6020 result = alloc(1, LongValue);
6021 Store_field(result, 0, Val_long(longValue));
6022 break;
6024 case DoubleValue:
6025 result = alloc(1, DoubleValue);
6026 Store_field(result, 0, copy_double(doubleValue));
6027 break;
6029 case StringListValue:
6030 result = alloc(1, StringListValue);
6031 Store_field(result, 0, convertStringList(stringListValue));
6032 break;
6035 CAMLreturn(result);
6039 ** curl_escape helper function
6042 CAMLprim value helper_curl_escape(value str)
6044 CAMLparam1(str);
6045 CAMLlocal1(result);
6046 char *curlResult;
6048 curlResult = curl_escape(String_val(str), string_length(str));
6049 result = copy_string(curlResult);
6050 free(curlResult);
6052 CAMLreturn(result);
6056 ** curl_unescape helper function
6059 CAMLprim value helper_curl_unescape(value str)
6061 CAMLparam1(str);
6062 CAMLlocal1(result);
6063 char *curlResult;
6065 curlResult = curl_unescape(String_val(str), string_length(str));
6066 result = copy_string(curlResult);
6067 free(curlResult);
6069 CAMLreturn(result);
6073 ** curl_getdate helper function
6076 CAMLprim value helper_curl_getdate(value str, value now)
6078 CAMLparam2(str, now);
6079 CAMLlocal1(result);
6080 time_t curlResult;
6081 time_t curlNow;
6083 curlNow = (time_t)Double_val(now);
6084 curlResult = curl_getdate(String_val(str), &curlNow);
6085 result = copy_double((double)curlResult);
6087 CAMLreturn(result);
6091 ** curl_version helper function
6094 CAMLprim value helper_curl_version(void)
6096 CAMLparam0();
6097 CAMLlocal1(result);
6098 char *str;
6100 str = curl_version();
6101 result = copy_string(str);
6103 CAMLreturn(result);
6106 struct CURLVersionBitsMapping
6108 int code;
6109 char *name;
6112 struct CURLVersionBitsMapping versionBitsMap[] =
6114 {CURL_VERSION_IPV6, "ipv6"},
6115 {CURL_VERSION_KERBEROS4, "kerberos4"},
6116 {CURL_VERSION_SSL, "ssl"},
6117 {CURL_VERSION_LIBZ, "libz"},
6118 {CURL_VERSION_NTLM, "ntlm"},
6119 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
6120 {CURL_VERSION_DEBUG, "debug"},
6121 {CURL_VERSION_CURLDEBUG, "curldebug"},
6122 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
6123 {CURL_VERSION_SPNEGO, "spnego"},
6124 {CURL_VERSION_LARGEFILE, "largefile"},
6125 {CURL_VERSION_IDN, "idn"},
6126 {CURL_VERSION_SSPI, "sspi"},
6127 {CURL_VERSION_CONV, "conv"},
6128 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
6129 {CURL_VERSION_TLSAUTH_SRP, "srp"},
6130 #endif
6131 #if HAVE_DECL_CURL_VERSION_NTLM_WB
6132 {CURL_VERSION_NTLM_WB, "wb"},
6133 #endif
6136 CAMLprim value caml_curl_version_info(value unit)
6138 CAMLparam1(unit);
6139 CAMLlocal4(v, vlist, vnum, vfeatures);
6140 const char* const* p = NULL;
6141 size_t i = 0;
6143 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
6144 if (NULL == data) caml_failwith("curl_version_info");
6146 vlist = Val_emptylist;
6147 for (p = data->protocols; NULL != *p; p++)
6149 vlist = Val_cons(vlist, caml_copy_string(*p));
6152 vfeatures = Val_emptylist;
6153 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
6155 if (0 != (versionBitsMap[i].code & data->features))
6156 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
6159 vnum = caml_alloc_tuple(3);
6160 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
6161 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
6162 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
6164 v = caml_alloc_tuple(12);
6165 Store_field(v,0,caml_copy_string(data->version));
6166 Store_field(v,1,vnum);
6167 Store_field(v,2,caml_copy_string(data->host));
6168 Store_field(v,3,vfeatures);
6169 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
6170 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
6171 Store_field(v,6,vlist);
6172 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
6173 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
6174 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
6175 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
6176 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
6178 CAMLreturn(v);
6181 CAMLprim value caml_curl_pause(value conn, value opts)
6183 CAMLparam2(conn, opts);
6184 CAMLlocal4(v, vlist, vnum, vfeatures);
6185 Connection *connection = Connection_val(conn);
6186 int bitmask = 0;
6187 CURLcode result;
6189 while (Val_emptylist != opts)
6191 switch (Int_val(Field(opts,0)))
6193 case 0: bitmask |= CURLPAUSE_SEND; break;
6194 case 1: bitmask |= CURLPAUSE_RECV; break;
6195 case 2: bitmask |= CURLPAUSE_ALL; break;
6196 default: caml_failwith("wrong pauseOption");
6198 opts = Field(opts,1);
6201 result = curl_easy_pause(connection->connection,bitmask);
6202 if (result != CURLE_OK)
6203 raiseError(connection, result);
6205 CAMLreturn(Val_unit);
6209 * Curl multi stack support
6211 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6212 * Other exported functions are prefixed with caml_curlm_, some of them
6213 * can/should be decomposed into smaller parts.
6216 struct ml_multi_handle
6218 CURLM* handle;
6219 value values; /* callbacks */
6222 enum
6224 curlmopt_socket_function,
6225 curlmopt_timer_function,
6227 /* last, not used */
6228 multi_values_total
6231 typedef struct ml_multi_handle ml_multi_handle;
6233 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6234 #define CURLM_val(v) (Multi_val(v)->handle)
6236 static struct custom_operations curl_multi_ops = {
6237 "ygrek.curl_multi",
6238 custom_finalize_default,
6239 custom_compare_default,
6240 custom_hash_default,
6241 custom_serialize_default,
6242 custom_deserialize_default,
6243 #if defined(custom_compare_ext_default)
6244 custom_compare_ext_default,
6245 #endif
6248 CAMLprim value caml_curl_multi_init(value unit)
6250 CAMLparam1(unit);
6251 CAMLlocal1(v);
6252 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6253 CURLM* h = curl_multi_init();
6255 if (!h)
6257 caml_stat_free(multi);
6258 failwith("caml_curl_multi_init");
6261 multi->handle = h;
6262 multi->values = caml_alloc(multi_values_total, 0);
6263 caml_register_generational_global_root(&multi->values);
6265 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6266 Multi_val(v) = multi;
6268 CAMLreturn(v);
6271 CAMLprim value caml_curl_multi_cleanup(value handle)
6273 CAMLparam1(handle);
6274 ml_multi_handle* h = Multi_val(handle);
6276 if (NULL == h)
6277 CAMLreturn(Val_unit);
6279 caml_remove_generational_global_root(&h->values);
6281 if (CURLM_OK != curl_multi_cleanup(h->handle))
6282 failwith("caml_curl_multi_cleanup");
6284 Multi_val(handle) = (ml_multi_handle*)NULL;
6286 CAMLreturn(Val_unit);
6289 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6291 int msgs_in_queue = 0;
6293 while (1)
6295 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6296 if (NULL == msg) return NULL;
6297 if (CURLMSG_DONE == msg->msg)
6299 CURL* easy_handle = msg->easy_handle;
6300 if (result) *result = msg->data.result;
6301 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6303 /*failwith("curlm_remove_finished");*/
6305 return easy_handle;
6310 CAMLprim value caml_curlm_remove_finished(value v_multi)
6312 CAMLparam1(v_multi);
6313 CAMLlocal2(v_easy, v_tuple);
6314 CURL* handle;
6315 CURLM* multi_handle;
6316 CURLcode result;
6318 multi_handle = CURLM_val(v_multi);
6320 caml_enter_blocking_section();
6321 handle = curlm_remove_finished(multi_handle,&result);
6322 caml_leave_blocking_section();
6324 if (NULL == handle)
6326 CAMLreturn(Val_none);
6328 else
6330 /* not good: same handle, but different block */
6331 v_easy = caml_alloc(1, Abstract_tag);
6332 Field(v_easy, 0) = (value)findConnection(handle);
6333 v_tuple = caml_alloc(2, 0);
6334 Store_field(v_tuple,0,v_easy);
6335 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6336 CAMLreturn(Val_some(v_tuple));
6340 static int curlm_wait_data(CURLM* multi_handle)
6342 struct timeval timeout;
6343 CURLMcode ret;
6345 fd_set fdread;
6346 fd_set fdwrite;
6347 fd_set fdexcep;
6348 int maxfd = -1;
6350 FD_ZERO(&fdread);
6351 FD_ZERO(&fdwrite);
6352 FD_ZERO(&fdexcep);
6354 /* set a suitable timeout */
6355 timeout.tv_sec = 1;
6356 timeout.tv_usec = 0;
6358 /* get file descriptors from the transfers */
6359 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6361 if (ret == CURLM_OK && maxfd >= 0)
6363 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6364 if (-1 != rc) return 0;
6366 return 1;
6369 CAMLprim value caml_curlm_wait_data(value v_multi)
6371 CAMLparam1(v_multi);
6372 int ret;
6373 CURLM* h = CURLM_val(v_multi);
6375 caml_enter_blocking_section();
6376 ret = curlm_wait_data(h);
6377 caml_leave_blocking_section();
6379 CAMLreturn(Val_bool(0 == ret));
6382 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6384 CAMLparam2(v_multi,v_easy);
6385 CURLM* multi = CURLM_val(v_multi);
6386 CURL* easy = Connection_val(v_easy)->connection;
6388 /* may invoke callbacks so need to be consistent with locks */
6389 caml_enter_blocking_section();
6390 if (CURLM_OK != curl_multi_add_handle(multi, easy))
6392 caml_leave_blocking_section();
6393 failwith("caml_curl_multi_add_handle");
6395 caml_leave_blocking_section();
6397 CAMLreturn(Val_unit);
6400 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6402 CAMLparam1(v_multi);
6403 int still_running = 0;
6404 CURLM* h = CURLM_val(v_multi);
6406 caml_enter_blocking_section();
6407 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6408 caml_leave_blocking_section();
6410 CAMLreturn(Val_int(still_running));
6413 CAMLprim value helper_curl_easy_strerror(value v_code)
6415 CAMLparam1(v_code);
6416 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6420 * Wrappers for the curl_multi_socket_action infrastructure
6421 * Based on curl hiperfifo.c example
6424 /* FIXME win32unix */
6425 #define Socket_val(v) Int_val(v)
6426 #define Val_socket(v) Val_int(v)
6428 static void raise_error(char const* msg)
6430 static value* exception = NULL;
6432 if (NULL == exception)
6434 exception = caml_named_value("Curl.Multi.Error");
6435 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6438 caml_raise_with_string(*exception, msg);
6441 static void check_mcode(CURLMcode code)
6443 char const *s = NULL;
6444 switch (code)
6446 case CURLM_OK : return;
6447 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6448 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6449 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6450 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6451 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6452 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6453 case CURLM_LAST : s="CURLM_LAST"; break;
6454 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6455 default : s="CURLM_unknown"; break;
6457 raise_error(s);
6460 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6462 CAMLparam3(v_multi, v_fd, v_kind);
6463 CURLM* h = CURLM_val(v_multi);
6464 int still_running = 0;
6465 CURLMcode rc = CURLM_OK;
6466 int socket = Socket_val(v_fd);
6467 int kind = 0;
6469 switch (Int_val(v_kind))
6471 case 0 : break;
6472 case 1 : kind |= CURL_CSELECT_IN; break;
6473 case 2 : kind |= CURL_CSELECT_OUT; break;
6474 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6475 default:
6476 raise_error("caml_curl_multi_socket_action");
6479 /* fprintf(stdout,"fd %u kind %u\n",Socket_val(v_fd), kind); fflush(stdout); */
6481 caml_enter_blocking_section();
6482 do {
6483 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6484 } while (rc == CURLM_CALL_MULTI_PERFORM);
6485 caml_leave_blocking_section();
6487 check_mcode(rc);
6489 CAMLreturn(Val_int(still_running));
6492 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6494 CAMLparam1(v_multi);
6495 int still_running = 0;
6496 CURLMcode rc = CURLM_OK;
6497 CURLM* h = CURLM_val(v_multi);
6499 caml_enter_blocking_section();
6500 do {
6501 rc = curl_multi_socket_all(h, &still_running);
6502 } while (rc == CURLM_CALL_MULTI_PERFORM);
6503 caml_leave_blocking_section();
6505 check_mcode(rc);
6507 CAMLreturn(Val_int(still_running));
6510 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6512 CAMLparam0();
6513 CAMLlocal1(v_what);
6514 (void)e;
6515 (void)sockp; /* not used */
6517 /* v_what = Val_int(what); */
6518 switch (what)
6520 case CURL_POLL_NONE : v_what = Val_int(0); break;
6521 case CURL_POLL_IN : v_what = Val_int(1); break;
6522 case CURL_POLL_OUT : v_what = Val_int(2); break;
6523 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6524 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6525 default:
6526 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6527 fflush(stderr);
6528 raise_error("curlm_sock_cb"); /* FIXME exception from callback */
6531 caml_callback2(Field(multi->values,curlmopt_socket_function),
6532 Val_socket(sock), v_what);
6534 CAMLreturn(0);
6537 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6539 int ret;
6540 caml_leave_blocking_section();
6541 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6542 caml_enter_blocking_section();
6543 return ret;
6546 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6548 CAMLparam2(v_multi, v_cb);
6549 ml_multi_handle* multi = Multi_val(v_multi);
6551 Store_field(multi->values, curlmopt_socket_function, v_cb);
6553 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6554 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6556 CAMLreturn(Val_unit);
6559 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6561 CAMLparam0();
6562 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6563 CAMLreturn0;
6566 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6568 (void)multi;
6570 caml_leave_blocking_section();
6571 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6572 caml_enter_blocking_section();
6573 return 0;
6576 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6578 CAMLparam2(v_multi, v_cb);
6579 ml_multi_handle* multi = Multi_val(v_multi);
6581 Store_field(multi->values, curlmopt_timer_function, v_cb);
6583 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6584 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6586 CAMLreturn(Val_unit);
6589 CAMLprim value caml_curl_multi_timeout(value v_multi)
6591 CAMLparam1(v_multi);
6592 long ms = 0;
6593 CURLMcode rc = CURLM_OK;
6594 ml_multi_handle* multi = Multi_val(v_multi);
6596 rc = curl_multi_timeout(multi->handle, &ms);
6598 check_mcode(rc);
6600 CAMLreturn(Val_long(ms));