fix build on windows (interface keyword)
[ocurl.git] / curl-helper.c
blob43b57bfdc467c0059fe3afbde7134c10b69aee5e
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 void leave_blocking_section(void);
28 void enter_blocking_section(void);
30 #define Val_none Val_int(0)
32 static __inline value
33 Val_some( value v )
35 CAMLparam1( v );
36 CAMLlocal1( some );
37 some = caml_alloc(1, 0);
38 Store_field( some, 0, v );
39 CAMLreturn( some );
42 static value Val_pair(value v1, value v2)
44 CAMLparam2(v1,v2);
45 CAMLlocal1(pair);
46 pair = caml_alloc_small(2,0);
47 Field(pair,0) = v1;
48 Field(pair,1) = v2;
49 CAMLreturn(pair);
52 static value Val_cons(value list, value v) { return Val_pair(v,list); }
54 typedef struct Connection Connection;
55 typedef struct ConnectionList ConnectionList;
57 #define Connection_val(v) ((Connection *)Field(v, 0))
59 enum OcamlValues
61 OcamlWriteCallback,
62 OcamlReadCallback,
63 OcamlErrorBuffer,
64 OcamlPostFields,
65 OcamlHTTPHeader,
66 OcamlHTTPPost,
67 OcamlQuote,
68 OcamlPostQuote,
69 OcamlHeaderCallback,
70 OcamlProgressCallback,
71 OcamlDebugCallback,
72 OcamlHTTP200Aliases,
73 OcamlIOCTLCallback,
74 OcamlSeekFunctionCallback,
75 OcamlOpenSocketFunctionCallback,
77 OcamlURL,
78 OcamlProxy,
79 OcamlUserPWD,
80 OcamlProxyUserPWD,
81 OcamlRange,
82 OcamlReferer,
83 OcamlUserAgent,
84 OcamlFTPPort,
85 OcamlCookie,
86 OcamlHTTPPostStrings,
87 OcamlSSLCert,
88 OcamlSSLCertType,
89 OcamlSSLCertPasswd,
90 OcamlSSLKey,
91 OcamlSSLKeyType,
92 OcamlSSLKeyPasswd,
93 OcamlSSLEngine,
94 OcamlCookieFile,
95 OcamlCustomRequest,
96 OcamlInterface,
97 OcamlCAInfo,
98 OcamlCAPath,
99 OcamlRandomFile,
100 OcamlEGDSocket,
101 OcamlCookieJar,
102 OcamlSSLCipherList,
103 OcamlPrivate,
104 OcamlNETRCFile,
105 OcamlFTPAccount,
106 OcamlCookieList,
107 OcamlFTPAlternativeToUser,
108 OcamlSSHPublicKeyFile,
109 OcamlSSHPrivateKeyFile,
110 OcamlSSHHostPublicKeyMD5,
111 OcamlCopyPostFields,
113 /* Not used, last for size */
114 OcamlValuesSize
117 struct Connection
119 CURL *connection;
120 Connection *next;
121 Connection *prev;
123 value ocamlValues;
125 char *url;
126 char *proxy;
127 char *userPwd;
128 char *proxyUserPwd;
129 char *range;
130 char *errorBuffer;
131 char *postFields;
132 int postFieldSize;
133 char *referer;
134 char *userAgent;
135 char *ftpPort;
136 char *cookie;
137 struct curl_slist *httpHeader;
138 struct curl_httppost *httpPostFirst;
139 struct curl_httppost *httpPostLast;
140 struct curl_slist *httpPostStrings;
141 struct curl_slist *resolve;
142 char *sslCert;
143 char *sslCertType;
144 char *sslCertPasswd;
145 char *sslKey;
146 char *sslKeyType;
147 char *sslKeyPasswd;
148 char *sslEngine;
149 struct curl_slist *quote;
150 struct curl_slist *postQuote;
151 char *cookieFile;
152 char *customRequest;
153 char *interface_; /* `interface` gives problems on windows */
154 char *caInfo;
155 char *caPath;
156 char *randomFile;
157 char *egdSocket;
158 char *cookieJar;
159 char *sslCipherList;
160 char *private;
161 struct curl_slist *http200Aliases;
162 char *netrcFile;
163 char *ftpaccount;
164 char *cookielist;
165 char *ftpAlternativeToUser;
166 char *sshPublicKeyFile;
167 char *sshPrivateKeyFile;
168 char *sshHostPublicKeyMD5;
169 char *copyPostFields;
170 char *dns_servers;
173 struct ConnectionList
175 Connection *head;
176 Connection *tail;
179 static ConnectionList connectionList = {NULL, NULL};
181 typedef struct CURLErrorMapping CURLErrorMapping;
183 struct CURLErrorMapping
185 char *name;
186 CURLcode error;
189 CURLErrorMapping errorMap[] =
191 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
192 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
193 #else
194 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
195 #endif
196 #if HAVE_DECL_CURLE_FAILED_INIT
197 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
198 #else
199 {"CURLE_FAILED_INIT", -1},
200 #endif
201 #if HAVE_DECL_CURLE_URL_MALFORMAT
202 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
203 #else
204 {"CURLE_URL_MALFORMAT", -1},
205 #endif
206 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
207 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
208 #else
209 {"CURLE_URL_MALFORMAT_USER", -1},
210 #endif
211 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
212 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
213 #else
214 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
215 #endif
216 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
217 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
218 #else
219 {"CURLE_COULDNT_RESOLVE_HOST", -1},
220 #endif
221 #if HAVE_DECL_CURLE_COULDNT_CONNECT
222 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
223 #else
224 {"CURLE_COULDNT_CONNECT", -1},
225 #endif
226 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
227 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
228 #else
229 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
230 #endif
231 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
232 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
233 #else
234 {"CURLE_FTP_ACCESS_DENIED", -1},
235 #endif
236 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
237 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
238 #else
239 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
240 #endif
241 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
242 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
243 #else
244 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
245 #endif
246 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
247 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
248 #else
249 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
250 #endif
251 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
252 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
253 #else
254 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
255 #endif
256 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
257 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
258 #else
259 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
260 #endif
261 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
262 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
263 #else
264 {"CURLE_FTP_CANT_GET_HOST", -1},
265 #endif
266 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
267 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
268 #else
269 {"CURLE_FTP_CANT_RECONNECT", -1},
270 #endif
271 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
272 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
273 #else
274 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
275 #endif
276 #if HAVE_DECL_CURLE_PARTIAL_FILE
277 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
278 #else
279 {"CURLE_PARTIAL_FILE", -1},
280 #endif
281 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
282 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
283 #else
284 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
285 #endif
286 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
287 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
288 #else
289 {"CURLE_FTP_WRITE_ERROR", -1},
290 #endif
291 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
292 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
293 #else
294 {"CURLE_FTP_QUOTE_ERROR", -1},
295 #endif
296 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
297 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
298 #else
299 {"CURLE_HTTP_NOT_FOUND", -1},
300 #endif
301 #if HAVE_DECL_CURLE_WRITE_ERROR
302 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
303 #else
304 {"CURLE_WRITE_ERROR", -1},
305 #endif
306 #if HAVE_DECL_CURLE_MALFORMAT_USER
307 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
308 #else
309 {"CURLE_MALFORMAT_USER", -1},
310 #endif
311 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
312 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
313 #else
314 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
315 #endif
316 #if HAVE_DECL_CURLE_READ_ERROR
317 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
318 #else
319 {"CURLE_READ_ERROR", -1},
320 #endif
321 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
322 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
323 #else
324 {"CURLE_OUT_OF_MEMORY", -1},
325 #endif
326 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
327 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
328 #else
329 {"CURLE_OPERATION_TIMEOUTED", -1},
330 #endif
331 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
332 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
333 #else
334 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
335 #endif
336 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
337 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
338 #else
339 {"CURLE_FTP_PORT_FAILED", -1},
340 #endif
341 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
342 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
343 #else
344 {"CURLE_FTP_COULDNT_USE_REST", -1},
345 #endif
346 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
347 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
348 #else
349 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
350 #endif
351 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
352 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
353 #else
354 {"CURLE_HTTP_RANGE_ERROR", -1},
355 #endif
356 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
357 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
358 #else
359 {"CURLE_HTTP_POST_ERROR", -1},
360 #endif
361 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
362 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
363 #else
364 {"CURLE_SSL_CONNECT_ERROR", -1},
365 #endif
366 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
367 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
368 #else
369 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
370 #endif
371 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
372 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
373 #else
374 {"CURLE_FILE_COULDNT_READ_FILE", -1},
375 #endif
376 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
377 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
378 #else
379 {"CURLE_LDAP_CANNOT_BIND", -1},
380 #endif
381 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
382 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
383 #else
384 {"CURLE_LDAP_SEARCH_FAILED", -1},
385 #endif
386 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
387 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
388 #else
389 {"CURLE_LIBRARY_NOT_FOUND", -1},
390 #endif
391 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
392 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
393 #else
394 {"CURLE_FUNCTION_NOT_FOUND", -1},
395 #endif
396 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
397 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
398 #else
399 {"CURLE_ABORTED_BY_CALLBACK", -1},
400 #endif
401 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
402 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
403 #else
404 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
405 #endif
406 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
407 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
408 #else
409 {"CURLE_BAD_CALLING_ORDER", -1},
410 #endif
411 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
412 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
413 #else
414 {"CURLE_HTTP_PORT_FAILED", -1},
415 #endif
416 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
417 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
418 #else
419 {"CURLE_BAD_PASSWORD_ENTERED", -1},
420 #endif
421 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
422 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
423 #else
424 {"CURLE_TOO_MANY_REDIRECTS", -1},
425 #endif
426 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
427 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
428 #else
429 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
430 #endif
431 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
432 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
433 #else
434 {"CURLE_TELNET_OPTION_SYNTAX", -1},
435 #endif
436 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
437 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
438 #else
439 {"CURLE_SSL_PEER_CERTIFICATE", -1},
440 #endif
441 #if HAVE_DECL_CURLE_GOT_NOTHING
442 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
443 #else
444 {"CURLE_GOT_NOTHING", -1},
445 #endif
446 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
447 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
448 #else
449 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
450 #endif
451 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
452 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
453 #else
454 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
455 #endif
456 #if HAVE_DECL_CURLE_SEND_ERROR
457 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
458 #else
459 {"CURLE_SEND_ERROR", -1},
460 #endif
461 #if HAVE_DECL_CURLE_RECV_ERROR
462 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
463 #else
464 {"CURLE_RECV_ERROR", -1},
465 #endif
466 #if HAVE_DECL_CURLE_SHARE_IN_USE
467 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
468 #else
469 {"CURLE_SHARE_IN_USE", -1},
470 #endif
471 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
472 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
473 #else
474 {"CURLE_SSL_CERTPROBLEN", -1},
475 #endif
476 #if HAVE_DECL_CURLE_SSL_CIPHER
477 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
478 #else
479 {"CURLE_SSL_CIPHER", -1},
480 #endif
481 #if HAVE_DECL_CURLE_SSL_CACERT
482 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
483 #else
484 {"CURLE_SSL_CACERT", -1},
485 #endif
486 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
487 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
488 #else
489 {"CURLE_BAD_CONTENT_ENCODING", -1},
490 #endif
491 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
492 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
493 #else
494 {"CURLE_LDAP_INVALID_URL", -1},
495 #endif
496 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
497 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
498 #else
499 {"CURLE_FILESIZE_EXCEEDED", -1},
500 #endif
501 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
502 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
503 #else
504 {"CURLE_FTP_SSL_FAILED", -1},
505 #endif
506 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
507 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
508 #else
509 {"CURLE_SEND_FAIL_REWIND", -1},
510 #endif
511 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
512 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
513 #else
514 {"CURLE_SSL_ENGINE_INITFAILED", -1},
515 #endif
516 #if HAVE_DECL_CURLE_LOGIN_DENIED
517 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
518 #else
519 {"CURLE_LOGIN_DENIED", -1},
520 #endif
521 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
522 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
523 #else
524 {"CURLE_TFTP_NOTFOUND", -1},
525 #endif
526 #if HAVE_DECL_CURLE_TFTP_PERM
527 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
528 #else
529 {"CURLE_TFTP_PERM", -1},
530 #endif
531 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
532 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
533 #else
534 {"CURLE_REMOTE_DISK_FULL", -1},
535 #endif
536 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
537 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
538 #else
539 {"CURLE_TFTP_ILLEGAL", -1},
540 #endif
541 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
542 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
543 #else
544 {"CURLE_TFTP_UNKNOWNID", -1},
545 #endif
546 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
547 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
548 #else
549 {"CURLE_REMOTE_FILE_EXISTS", -1},
550 #endif
551 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
552 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
553 #else
554 {"CURLE_TFTP_NOSUCHUSER", -1},
555 #endif
556 #if HAVE_DECL_CURLE_CONV_FAILED
557 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
558 #else
559 {"CURLE_CONV_FAILED", -1},
560 #endif
561 #if HAVE_DECL_CURLE_CONV_REQUIRED
562 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
563 #else
564 {"CURLE_CONV_REQUIRED", -1},
565 #endif
566 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
567 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
568 #else
569 {"CURLE_SSL_CACERT_BADFILE", -1},
570 #endif
571 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
572 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
573 #else
574 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
575 #endif
576 #if HAVE_DECL_CURLE_SSH
577 {"CURLE_SSH", CURLE_SSH},
578 #else
579 {"CURLE_SSH", -1},
580 #endif
581 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
582 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
583 #else
584 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
585 #endif
586 #if HAVE_DECL_CURLE_AGAIN
587 {"CURLE_AGAIN", CURLE_AGAIN},
588 #else
589 {"CURLE_AGAIN", -1},
590 #endif
591 {"CURLE_OK", CURLE_OK},
592 {NULL, 0}
595 typedef struct CURLOptionMapping CURLOptionMapping;
597 struct CURLOptionMapping
599 void (*optionHandler)(Connection *, value);
600 char *name;
601 CURLoption option;
604 CURLOptionMapping unimplementedOptionMap[] =
606 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
607 {NULL, NULL, 0}
610 static void handleWriteFunction(Connection *, value);
611 static void handleReadFunction(Connection *, value);
612 static void handleInFileSize(Connection *, value);
613 static void handleURL(Connection *, value);
614 static void handleProxy(Connection *, value);
615 static void handleProxyPort(Connection *, value);
616 static void handleHTTPProxyTunnel(Connection *, value);
617 static void handleVerbose(Connection *, value);
618 static void handleHeader(Connection *, value);
619 static void handleNoProgress(Connection *, value);
620 static void handleNoSignal(Connection *, value);
621 static void handleNoBody(Connection *, value);
622 static void handleFailOnError(Connection *, value);
623 static void handleUpload(Connection *, value);
624 static void handlePost(Connection *, value);
625 static void handleFTPListOnly(Connection *, value);
626 static void handleFTPAppend(Connection *, value);
627 static void handleNETRC(Connection *, value);
628 static void handleEncoding(Connection *, value);
629 static void handleFollowLocation(Connection *, value);
630 static void handleTransferText(Connection *, value);
631 static void handlePut(Connection *, value);
632 static void handleUserPwd(Connection *, value);
633 static void handleProxyUserPwd(Connection *, value);
634 static void handleRange(Connection *, value);
635 static void handleErrorBuffer(Connection *, value);
636 static void handleTimeout(Connection *, value);
637 static void handlePostFields(Connection *, value);
638 static void handlePostFieldSize(Connection *, value);
639 static void handleReferer(Connection *, value);
640 static void handleUserAgent(Connection *, value);
641 static void handleFTPPort(Connection *, value);
642 static void handleLowSpeedLimit(Connection *, value);
643 static void handleLowSpeedTime(Connection *, value);
644 static void handleResumeFrom(Connection *, value);
645 static void handleCookie(Connection *, value);
646 static void handleHTTPHeader(Connection *, value);
647 static void handleHTTPPost(Connection *, value);
648 static void handleSSLCert(Connection *, value);
649 static void handleSSLCertType(Connection *, value);
650 static void handleSSLCertPasswd(Connection *, value);
651 static void handleSSLKey(Connection *, value);
652 static void handleSSLKeyType(Connection *, value);
653 static void handleSSLKeyPasswd(Connection *, value);
654 static void handleSSLEngine(Connection *, value);
655 static void handleSSLEngineDefault(Connection *, value);
656 static void handleCRLF(Connection *, value);
657 static void handleQuote(Connection *, value);
658 static void handlePostQuote(Connection *, value);
659 static void handleHeaderFunction(Connection *, value);
660 static void handleCookieFile(Connection *, value);
661 static void handleSSLVersion(Connection *, value);
662 static void handleTimeCondition(Connection *, value);
663 static void handleTimeValue(Connection *, value);
664 static void handleCustomRequest(Connection *, value);
665 static void handleInterface(Connection *, value);
666 static void handleKRB4Level(Connection *, value);
667 static void handleProgressFunction(Connection *, value);
668 static void handleSSLVerifyPeer(Connection *, value);
669 static void handleCAInfo(Connection *, value);
670 static void handleCAPath(Connection *, value);
671 static void handleFileTime(Connection *, value);
672 static void handleMaxRedirs(Connection *, value);
673 static void handleMaxConnects(Connection *, value);
674 static void handleClosePolicy(Connection *, value);
675 static void handleFreshConnect(Connection *, value);
676 static void handleForbidReuse(Connection *, value);
677 static void handleRandomFile(Connection *, value);
678 static void handleEGDSocket(Connection *, value);
679 static void handleConnectTimeout(Connection *, value);
680 static void handleHTTPGet(Connection *, value);
681 static void handleSSLVerifyHost(Connection *, value);
682 static void handleCookieJar(Connection *, value);
683 static void handleSSLCipherList(Connection *, value);
684 static void handleHTTPVersion(Connection *, value);
685 static void handleFTPUseEPSV(Connection *, value);
686 static void handleDNSCacheTimeout(Connection *, value);
687 static void handleDNSUseGlobalCache(Connection *, value);
688 static void handleDebugFunction(Connection *, value);
689 static void handlePrivate(Connection *, value);
690 static void handleHTTP200Aliases(Connection *, value);
691 static void handleUnrestrictedAuth(Connection *, value);
692 static void handleFTPUseEPRT(Connection *, value);
693 static void handleHTTPAuth(Connection *, value);
694 static void handleFTPCreateMissingDirs(Connection *, value);
695 static void handleProxyAuth(Connection *, value);
696 static void handleFTPResponseTimeout(Connection *, value);
697 static void handleIPResolve(Connection *, value);
698 static void handleMaxFileSize(Connection *, value);
699 static void handleInFileSizeLarge(Connection *, value);
700 static void handleResumeFromLarge(Connection *, value);
701 static void handleMaxFileSizeLarge(Connection *, value);
702 static void handleNETRCFile(Connection *, value);
703 static void handleFTPSSL(Connection *, value);
704 static void handlePostFieldSizeLarge(Connection *, value);
705 static void handleTCPNoDelay(Connection *, value);
706 static void handleFTPSSLAuth(Connection *, value);
707 static void handleIOCTLFunction(Connection *, value);
708 static void handleFTPAccount(Connection *, value);
709 static void handleCookieList(Connection *, value);
710 static void handleIgnoreContentLength(Connection *, value);
711 static void handleFTPSkipPASVIP(Connection *, value);
712 static void handleFTPFileMethod(Connection *, value);
713 static void handleLocalPort(Connection *, value);
714 static void handleLocalPortRange(Connection *, value);
715 static void handleConnectOnly(Connection *, value);
716 static void handleMaxSendSpeedLarge(Connection *, value);
717 static void handleMaxRecvSpeedLarge(Connection *, value);
718 static void handleFTPAlternativeToUser(Connection *, value);
719 static void handleSSLSessionIdCache(Connection *, value);
720 static void handleSSHAuthTypes(Connection *, value);
721 static void handleSSHPublicKeyFile(Connection *, value);
722 static void handleSSHPrivateKeyFile(Connection *, value);
723 static void handleFTPSSLCCC(Connection *, value);
724 static void handleTimeoutMS(Connection *, value);
725 static void handleConnectTimeoutMS(Connection *, value);
726 static void handleHTTPTransferDecoding(Connection *, value);
727 static void handleHTTPContentDecoding(Connection *, value);
728 static void handleNewFilePerms(Connection *, value);
729 static void handleNewDirectoryPerms(Connection *, value);
730 static void handlePost301(Connection *, value);
731 static void handleSSHHostPublicKeyMD5(Connection *, value);
732 static void handleCopyPostFields(Connection *, value);
733 static void handleProxyTransferMode(Connection *, value);
734 static void handleSeekFunction(Connection *, value);
735 static void handleAutoReferer(Connection *, value);
736 static void handleOpenSocketFunction(Connection *, value);
737 static void handleProxyType(Connection *, value);
738 static void handleProtocols(Connection *, value);
739 static void handleRedirProtocols(Connection *, value);
740 static void handleResolve(Connection *, value);
741 static void handleDnsServers(Connection *, value);
743 CURLOptionMapping implementedOptionMap[] =
745 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
746 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
747 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
748 {handleURL, "CURLOPT_URL", CURLOPT_URL},
749 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
750 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
751 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
752 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
753 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
754 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
755 #if HAVE_DECL_CURLOPT_NOSIGNAL
756 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
757 #else
758 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
759 #endif
760 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
761 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
762 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
763 {handlePost, "CURLOPT_POST", CURLOPT_POST},
764 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
765 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
766 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
767 #if HAVE_DECL_CURLOPT_ENCODING
768 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
769 #else
770 {handleEncoding, "CURLOPT_ENCODING", 0},
771 #endif
772 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
773 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
774 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
775 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
776 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
777 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
778 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
779 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
780 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
781 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
782 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
783 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
784 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
785 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
786 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
787 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
788 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
789 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
790 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
791 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
792 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
793 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
794 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
795 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
796 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
797 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
798 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
799 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
800 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
801 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
802 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
803 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
804 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
805 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
806 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
807 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
808 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
809 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
810 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
811 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
812 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
813 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
814 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
815 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
816 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
817 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
818 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
819 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
820 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
821 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
822 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
823 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
824 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
825 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
826 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
827 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
828 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
829 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
830 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
831 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
832 #if HAVE_DECL_CURLOPT_PRIVATE
833 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
834 #else
835 {handlePrivate, "CURLOPT_PRIVATE", 0},
836 #endif
837 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
838 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
839 #else
840 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
841 #endif
842 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
843 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
844 #else
845 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
846 #endif
847 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
848 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
849 #else
850 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
851 #endif
852 #if HAVE_DECL_CURLOPT_HTTPAUTH
853 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
854 #else
855 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
856 #endif
857 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
858 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
859 #else
860 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
861 #endif
862 #if HAVE_DECL_CURLOPT_PROXYAUTH
863 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
864 #else
865 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
866 #endif
867 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
868 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
869 #else
870 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
871 #endif
872 #if HAVE_DECL_CURLOPT_IPRESOLVE
873 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
874 #else
875 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
876 #endif
877 #if HAVE_DECL_CURLOPT_MAXFILESIZE
878 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
879 #else
880 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
881 #endif
882 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
883 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
884 #else
885 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
886 #endif
887 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
888 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
889 #else
890 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
891 #endif
892 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
893 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
894 #else
895 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
896 #endif
897 #if HAVE_DECL_CURLOPT_NETRC_FILE
898 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
899 #else
900 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
901 #endif
902 #if HAVE_DECL_CURLOPT_FTP_SSL
903 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
904 #else
905 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
906 #endif
907 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
908 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
909 #else
910 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
911 #endif
912 #if HAVE_DECL_CURLOPT_TCP_NODELAY
913 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
914 #else
915 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
916 #endif
917 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
918 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
919 #else
920 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
921 #endif
922 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
923 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
924 #else
925 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
926 #endif
927 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
928 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
929 #else
930 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
931 #endif
932 #if HAVE_DECL_CURLOPT_COOKIELIST
933 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
934 #else
935 {handleCookieList, "CURLOPT_COOKIELIST", 0},
936 #endif
937 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
938 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
939 #else
940 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
941 #endif
942 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
943 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
944 #else
945 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
946 #endif
947 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
948 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
949 #else
950 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
951 #endif
952 #if HAVE_DECL_CURLOPT_LOCALPORT
953 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
954 #else
955 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
956 #endif
957 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
958 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
959 #else
960 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
961 #endif
962 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
963 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
964 #else
965 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
966 #endif
967 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
968 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
969 #else
970 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
971 #endif
972 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
973 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
974 #else
975 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
976 #endif
977 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
978 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
979 #else
980 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
981 #endif
982 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
983 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
984 #else
985 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
986 #endif
987 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
988 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
989 #else
990 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
991 #endif
992 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
993 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
994 #else
995 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
996 #endif
997 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
998 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
999 #else
1000 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
1001 #endif
1002 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
1003 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
1004 #else
1005 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
1006 #endif
1007 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
1008 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
1009 #else
1010 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
1011 #endif
1012 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
1013 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
1014 #else
1015 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
1016 #endif
1017 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1018 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1019 #else
1020 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1021 #endif
1022 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1023 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1024 #else
1025 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1026 #endif
1027 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1028 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1029 #else
1030 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1031 #endif
1032 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1033 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1034 #else
1035 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1036 #endif
1037 #if HAVE_DECL_CURLOPT_POST301
1038 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1039 #else
1040 {handlePost301, "CURLOPT_POST301", 0},
1041 #endif
1042 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1043 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1044 #else
1045 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1046 #endif
1047 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1048 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1049 #else
1050 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1051 #endif
1052 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1053 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1054 #else
1055 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1056 #endif
1057 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1058 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1059 #else
1060 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1061 #endif
1062 #if HAVE_DECL_CURLOPT_AUTOREFERER
1063 {handleAutoReferer, "CURLOPT_AUTOREFERER", CURLOPT_AUTOREFERER},
1064 #else
1065 {handleAutoReferer, "CURLOPT_AUTOREFERER", 0},
1066 #endif
1067 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1068 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION},
1069 #else
1070 {handleOpenSocketFunction, "CURLOPT_OPENSOCKETFUNCTION", 0},
1071 #endif
1072 #if HAVE_DECL_CURLOPT_PROXYTYPE
1073 {handleProxyType, "CURLOPT_PROXYTYPE", CURLOPT_PROXYTYPE},
1074 #else
1075 {handleProxyType, "CURLOPT_PROXYTYPE", 0},
1076 #endif
1077 #if HAVE_DECL_CURLOPT_PROTOCOLS
1078 {handleProtocols, "CURLOPT_PROTOCOLS", CURLOPT_PROTOCOLS},
1079 #else
1080 {handleProtocols, "CURLOPT_PROTOCOLS", 0},
1081 #endif
1082 #if HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
1083 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS},
1084 #else
1085 {handleRedirProtocols, "CURLOPT_REDIR_PROTOCOLS", 0},
1086 #endif
1087 #if HAVE_DECL_CURLOPT_RESOLVE
1088 {handleResolve, "CURLOPT_RESOLVE", CURLOPT_RESOLVE},
1089 #else
1090 {handleResolve, "CURLOPT_RESOLVE", 0},
1091 #endif
1092 #if HAVE_DECL_CURLOPT_DNS_SERVERS
1093 {handleDnsServers, "CURLOPT_DNS_SERVERS", CURLOPT_DNS_SERVERS},
1094 #else
1095 {handleDnsServers, "CURLOPT_DNS_SERVERS", 0},
1096 #endif
1099 static char *findOption(CURLOptionMapping optionMap[],
1100 CURLoption option)
1102 return optionMap[option].name;
1105 static void free_curl_slist(struct curl_slist *slist)
1107 if (NULL == slist)
1108 return;
1110 curl_slist_free_all(slist);
1113 static void raiseError(Connection *conn, CURLcode code)
1115 CAMLparam0();
1116 CAMLlocal1(exceptionData);
1117 value *exception;
1118 char *errorString = "Unknown Error";
1119 int i;
1121 for (i = 0; errorMap[i].name != NULL; i++)
1123 if (errorMap[i].error == code)
1125 errorString = errorMap[i].name;
1126 break;
1130 exceptionData = caml_alloc(3, 0);
1132 Store_field(exceptionData, 0, Val_int(code));
1133 Store_field(exceptionData, 1, Val_int(code));
1134 Store_field(exceptionData, 2, copy_string(errorString));
1136 if (conn != NULL && conn->errorBuffer != NULL)
1138 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1139 copy_string(conn->errorBuffer));
1142 exception = caml_named_value("CurlException");
1144 if (exception == NULL)
1145 caml_failwith("CurlException not registered");
1147 raise_with_arg(*exception, exceptionData);
1149 CAMLreturn0;
1152 static void resetOcamlValues(Connection* connection)
1154 int i;
1156 for (i = 0; i < OcamlValuesSize; i++)
1157 Store_field(connection->ocamlValues, i, Val_unit);
1160 static Connection *newConnection(void)
1162 Connection *connection;
1164 connection = (Connection *)malloc(sizeof(Connection));
1166 enter_blocking_section();
1167 connection->connection = curl_easy_init();
1168 leave_blocking_section();
1170 connection->next = NULL;
1171 connection->prev = NULL;
1173 if (connectionList.tail == NULL)
1175 connectionList.tail = connection;
1176 connectionList.head = connection;
1178 else
1180 connection->prev = connectionList.head;
1181 connectionList.head->next = connection;
1182 connectionList.head = connection;
1185 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1186 resetOcamlValues(connection);
1187 register_global_root(&connection->ocamlValues);
1189 connection->url = NULL;
1190 connection->proxy = NULL;
1191 connection->userPwd = NULL;
1192 connection->proxyUserPwd = NULL;
1193 connection->range = NULL;
1194 connection->errorBuffer = NULL;
1195 connection->postFields = NULL;
1196 connection->postFieldSize = -1;
1197 connection->referer = NULL;
1198 connection->userAgent = NULL;
1199 connection->ftpPort = NULL;
1200 connection->cookie = NULL;
1201 connection->httpHeader = NULL;
1202 connection->httpPostFirst = NULL;
1203 connection->httpPostLast = NULL;
1204 connection->httpPostStrings = NULL;
1205 connection->sslCert = NULL;
1206 connection->sslCertType = NULL;
1207 connection->sslCertPasswd = NULL;
1208 connection->sslKey = NULL;
1209 connection->sslKeyType = NULL;
1210 connection->sslKeyPasswd = NULL;
1211 connection->sslEngine = NULL;
1212 connection->quote = NULL;
1213 connection->postQuote = NULL;
1214 connection->cookieFile = NULL;
1215 connection->customRequest = NULL;
1216 connection->interface_ = NULL;
1217 connection->caInfo = NULL;
1218 connection->caPath = NULL;
1219 connection->randomFile = NULL;
1220 connection->egdSocket = NULL;
1221 connection->cookieJar = NULL;
1222 connection->sslCipherList = NULL;
1223 connection->private = NULL;
1224 connection->http200Aliases = NULL;
1225 connection->netrcFile = NULL;
1226 connection->ftpaccount = NULL;
1227 connection->cookielist = NULL;
1228 connection->ftpAlternativeToUser = NULL;
1229 connection->sshPublicKeyFile = NULL;
1230 connection->sshPrivateKeyFile = NULL;
1231 connection->copyPostFields = NULL;
1232 connection->resolve = NULL;
1233 connection->dns_servers = NULL;
1235 return connection;
1238 static Connection *duplicateConnection(Connection *original)
1240 Connection *connection;
1242 connection = (Connection *)malloc(sizeof(Connection));
1244 enter_blocking_section();
1245 connection->connection = curl_easy_duphandle(original->connection);
1246 leave_blocking_section();
1248 connection->next = NULL;
1249 connection->prev = NULL;
1251 if (connectionList.tail == NULL)
1253 connectionList.tail = connection;
1254 connectionList.head = connection;
1256 else
1258 connection->prev = connectionList.head;
1259 connectionList.head->next = connection;
1260 connectionList.head = connection;
1263 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1264 resetOcamlValues(connection);
1265 register_global_root(&connection->ocamlValues);
1267 Store_field(connection->ocamlValues, OcamlWriteCallback,
1268 Field(original->ocamlValues, OcamlWriteCallback));
1269 Store_field(connection->ocamlValues, OcamlReadCallback,
1270 Field(original->ocamlValues, OcamlReadCallback));
1271 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1272 Field(original->ocamlValues, OcamlErrorBuffer));
1273 Store_field(connection->ocamlValues, OcamlPostFields,
1274 Field(original->ocamlValues, OcamlPostFields));
1275 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1276 Field(original->ocamlValues, OcamlHTTPHeader));
1277 Store_field(connection->ocamlValues, OcamlQuote,
1278 Field(original->ocamlValues, OcamlQuote));
1279 Store_field(connection->ocamlValues, OcamlPostQuote,
1280 Field(original->ocamlValues, OcamlPostQuote));
1281 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1282 Field(original->ocamlValues, OcamlHeaderCallback));
1283 Store_field(connection->ocamlValues, OcamlProgressCallback,
1284 Field(original->ocamlValues, OcamlProgressCallback));
1285 Store_field(connection->ocamlValues, OcamlDebugCallback,
1286 Field(original->ocamlValues, OcamlDebugCallback));
1287 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1288 Field(original->ocamlValues, OcamlHTTP200Aliases));
1289 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1290 Field(original->ocamlValues, OcamlIOCTLCallback));
1291 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1292 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1294 connection->url = NULL;
1295 connection->proxy = NULL;
1296 connection->userPwd = NULL;
1297 connection->proxyUserPwd = NULL;
1298 connection->range = NULL;
1299 connection->errorBuffer = NULL;
1300 connection->postFields = NULL;
1301 connection->postFieldSize = -1;
1302 connection->referer = NULL;
1303 connection->userAgent = NULL;
1304 connection->ftpPort = NULL;
1305 connection->cookie = NULL;
1306 connection->httpHeader = NULL;
1307 connection->httpPostFirst = NULL;
1308 connection->httpPostLast = NULL;
1309 connection->httpPostStrings = NULL;
1310 connection->sslCert = NULL;
1311 connection->sslCertType = NULL;
1312 connection->sslCertPasswd = NULL;
1313 connection->sslKey = NULL;
1314 connection->sslKeyType = NULL;
1315 connection->sslKeyPasswd = NULL;
1316 connection->sslEngine = NULL;
1317 connection->quote = NULL;
1318 connection->postQuote = NULL;
1319 connection->cookieFile = NULL;
1320 connection->customRequest = NULL;
1321 connection->interface_ = NULL;
1322 connection->caInfo = NULL;
1323 connection->caPath = NULL;
1324 connection->randomFile = NULL;
1325 connection->egdSocket = NULL;
1326 connection->cookieJar = NULL;
1327 connection->sslCipherList = NULL;
1328 connection->private = NULL;
1329 connection->http200Aliases = NULL;
1330 connection->netrcFile = NULL;
1331 connection->ftpaccount = NULL;
1332 connection->cookielist = NULL;
1333 connection->sshPublicKeyFile = NULL;
1334 connection->sshPrivateKeyFile = NULL;
1335 connection->copyPostFields = NULL;
1336 connection->resolve = NULL;
1337 connection->dns_servers = NULL;
1339 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1340 handleURL(connection, Field(original->ocamlValues,
1341 OcamlURL));
1342 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1343 handleProxy(connection, Field(original->ocamlValues,
1344 OcamlProxy));
1345 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1346 handleUserPwd(connection, Field(original->ocamlValues,
1347 OcamlUserPWD));
1348 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1349 handleProxyUserPwd(connection, Field(original->ocamlValues,
1350 OcamlProxyUserPWD));
1351 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1352 handleRange(connection, Field(original->ocamlValues,
1353 OcamlRange));
1354 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1355 handleErrorBuffer(connection, Field(original->ocamlValues,
1356 OcamlErrorBuffer));
1357 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1358 handlePostFields(connection, Field(original->ocamlValues,
1359 OcamlPostFields));
1360 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1361 handleReferer(connection, Field(original->ocamlValues,
1362 OcamlReferer));
1363 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1364 handleUserAgent(connection, Field(original->ocamlValues,
1365 OcamlUserAgent));
1366 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1367 handleFTPPort(connection, Field(original->ocamlValues,
1368 OcamlFTPPort));
1369 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1370 handleCookie(connection, Field(original->ocamlValues,
1371 OcamlCookie));
1372 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1373 handleHTTPHeader(connection, Field(original->ocamlValues,
1374 OcamlHTTPHeader));
1375 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1376 handleHTTPPost(connection, Field(original->ocamlValues,
1377 OcamlHTTPPost));
1378 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1379 handleSSLCert(connection, Field(original->ocamlValues,
1380 OcamlSSLCert));
1381 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1382 handleSSLCertType(connection, Field(original->ocamlValues,
1383 OcamlSSLCertType));
1384 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1385 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1386 OcamlSSLCertPasswd));
1387 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1388 handleSSLKey(connection, Field(original->ocamlValues,
1389 OcamlSSLKey));
1390 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1391 handleSSLKeyType(connection, Field(original->ocamlValues,
1392 OcamlSSLKeyType));
1393 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1394 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1395 OcamlSSLKeyPasswd));
1396 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1397 handleSSLEngine(connection, Field(original->ocamlValues,
1398 OcamlSSLEngine));
1399 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1400 handleQuote(connection, Field(original->ocamlValues,
1401 OcamlQuote));
1402 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1403 handlePostQuote(connection, Field(original->ocamlValues,
1404 OcamlPostQuote));
1405 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1406 handleCookieFile(connection, Field(original->ocamlValues,
1407 OcamlCookieFile));
1408 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1409 handleCustomRequest(connection, Field(original->ocamlValues,
1410 OcamlCustomRequest));
1411 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1412 handleInterface(connection, Field(original->ocamlValues,
1413 OcamlInterface));
1414 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1415 handleCAInfo(connection, Field(original->ocamlValues,
1416 OcamlCAInfo));
1417 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1418 handleCAPath(connection, Field(original->ocamlValues,
1419 OcamlCAPath));
1420 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1421 handleRandomFile(connection, Field(original->ocamlValues,
1422 OcamlRandomFile));
1423 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1424 handleEGDSocket(connection, Field(original->ocamlValues,
1425 OcamlEGDSocket));
1426 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1427 handleCookieJar(connection, Field(original->ocamlValues,
1428 OcamlCookieJar));
1429 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1430 handleSSLCipherList(connection, Field(original->ocamlValues,
1431 OcamlSSLCipherList));
1432 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1433 handlePrivate(connection, Field(original->ocamlValues,
1434 OcamlPrivate));
1435 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1436 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1437 OcamlHTTP200Aliases));
1438 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1439 handleNETRCFile(connection, Field(original->ocamlValues,
1440 OcamlNETRCFile));
1441 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1442 handleFTPAccount(connection, Field(original->ocamlValues,
1443 OcamlFTPAccount));
1444 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1445 handleCookieList(connection, Field(original->ocamlValues,
1446 OcamlCookieList));
1447 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1448 handleFTPAlternativeToUser(connection,
1449 Field(original->ocamlValues,
1450 OcamlFTPAlternativeToUser));
1451 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1452 handleSSHPublicKeyFile(connection,
1453 Field(original->ocamlValues,
1454 OcamlSSHPublicKeyFile));
1455 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1456 handleSSHPrivateKeyFile(connection,
1457 Field(original->ocamlValues,
1458 OcamlSSHPrivateKeyFile));
1459 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1460 handleCopyPostFields(connection,
1461 Field(original->ocamlValues,
1462 OcamlCopyPostFields));
1464 return connection;
1467 static void free_if(void* p) { if (NULL != p) free(p); }
1469 static void removeConnection(Connection *connection)
1471 enter_blocking_section();
1472 curl_easy_cleanup(connection->connection);
1473 leave_blocking_section();
1475 if (connectionList.tail == connection)
1476 connectionList.tail = connectionList.tail->next;
1477 if (connectionList.head == connection)
1478 connectionList.head = connectionList.head->prev;
1480 if (connection->next != NULL)
1481 connection->next->prev = connection->prev;
1482 if (connection->prev != NULL)
1483 connection->prev->next = connection->next;
1485 remove_global_root(&connection->ocamlValues);
1487 free_if(connection->url);
1488 free_if(connection->proxy);
1489 free_if(connection->userPwd);
1490 free_if(connection->proxyUserPwd);
1491 free_if(connection->range);
1492 free_if(connection->errorBuffer);
1493 free_if(connection->postFields);
1494 free_if(connection->referer);
1495 free_if(connection->userAgent);
1496 free_if(connection->ftpPort);
1497 free_if(connection->cookie);
1498 free_curl_slist(connection->httpHeader);
1499 if (connection->httpPostFirst != NULL)
1500 curl_formfree(connection->httpPostFirst);
1501 free_curl_slist(connection->httpPostStrings);
1502 free_curl_slist(connection->resolve);
1503 free_if(connection->sslCert);
1504 free_if(connection->sslCertType);
1505 free_if(connection->sslCertPasswd);
1506 free_if(connection->sslKey);
1507 free_if(connection->sslKeyType);
1508 free_if(connection->sslKeyPasswd);
1509 free_if(connection->sslEngine);
1510 free_curl_slist(connection->quote);
1511 free_curl_slist(connection->postQuote);
1512 free_if(connection->cookieFile);
1513 free_if(connection->customRequest);
1514 free_if(connection->interface_);
1515 free_if(connection->caInfo);
1516 free_if(connection->caPath);
1517 free_if(connection->randomFile);
1518 free_if(connection->egdSocket);
1519 free_if(connection->cookieJar);
1520 free_if(connection->sslCipherList);
1521 free_if(connection->private);
1522 free_curl_slist(connection->http200Aliases);
1523 free_if(connection->netrcFile);
1524 free_if(connection->ftpaccount);
1525 free_if(connection->cookielist);
1526 free_if(connection->ftpAlternativeToUser);
1527 free_if(connection->sshPublicKeyFile);
1528 free_if(connection->sshPrivateKeyFile);
1529 free_if(connection->copyPostFields);
1530 free_if(connection->dns_servers);
1532 free(connection);
1535 #if 1
1536 static void checkConnection(Connection * connection)
1538 (void)connection;
1540 #else
1541 static void checkConnection(Connection *connection)
1543 Connection *listIter;
1545 listIter = connectionList.tail;
1547 while (listIter != NULL)
1549 if (listIter == connection)
1550 return;
1552 listIter = listIter->next;
1555 failwith("Invalid Connection");
1557 #endif
1559 static Connection* findConnection(CURL* h)
1561 Connection *listIter;
1563 listIter = connectionList.tail;
1565 while (listIter != NULL)
1567 if (listIter->connection == h)
1568 return listIter;
1570 listIter = listIter->next;
1573 failwith("Unknown handle");
1576 #define WRAP_DATA_CALLBACK(f) \
1577 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1579 size_t result;\
1580 leave_blocking_section();\
1581 result = f##_nolock(ptr,size,nmemb,data);\
1582 enter_blocking_section();\
1583 return result;\
1586 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1588 CAMLparam0();
1589 CAMLlocal2(result, str);
1590 Connection *conn = (Connection *)data;
1591 size_t i;
1593 checkConnection(conn);
1595 str = alloc_string(size*nmemb);
1597 for (i = 0; i < size*nmemb; i++)
1598 Byte(str, i) = ptr[i];
1600 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1602 CAMLreturnT(size_t, Int_val(result));
1605 WRAP_DATA_CALLBACK(writeFunction)
1607 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1609 CAMLparam0();
1610 CAMLlocal1(result);
1611 Connection *conn = (Connection *)data;
1612 size_t length;
1614 checkConnection(conn);
1616 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1617 Val_int(size*nmemb));
1619 length = string_length(result);
1621 if (length >= size*nmemb)
1622 length = size*nmemb;
1624 memcpy(ptr, String_val(result), length);
1626 CAMLreturnT(size_t,length);
1629 WRAP_DATA_CALLBACK(readFunction)
1631 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1633 CAMLparam0();
1634 CAMLlocal2(result,str);
1635 Connection *conn = (Connection *)data;
1636 size_t i;
1638 checkConnection(conn);
1640 str = alloc_string(size*nmemb);
1642 for (i = 0; i < size*nmemb; i++)
1643 Byte(str, i) = ptr[i];
1645 result = callback(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1647 CAMLreturnT(size_t, Int_val(result));
1650 WRAP_DATA_CALLBACK(headerFunction)
1652 static int progressFunction_nolock(void *data,
1653 double dlTotal,
1654 double dlNow,
1655 double ulTotal,
1656 double ulNow)
1658 CAMLparam0();
1659 CAMLlocal1(result);
1660 CAMLlocalN(callbackData, 4);
1661 Connection *conn = (Connection *)data;
1663 checkConnection(conn);
1665 callbackData[0] = copy_double(dlTotal);
1666 callbackData[1] = copy_double(dlNow);
1667 callbackData[2] = copy_double(ulTotal);
1668 callbackData[3] = copy_double(ulNow);
1670 result = callbackN(Field(conn->ocamlValues, OcamlProgressCallback),
1671 4, callbackData);
1673 CAMLreturnT(int, Bool_val(result));
1676 static int progressFunction(void *data,
1677 double dlTotal,
1678 double dlNow,
1679 double ulTotal,
1680 double ulNow)
1682 int r;
1683 leave_blocking_section();
1684 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1685 enter_blocking_section();
1686 return r;
1689 static int debugFunction_nolock(CURL *debugConnection,
1690 curl_infotype infoType,
1691 char *buffer,
1692 size_t bufferLength,
1693 void *data)
1695 CAMLparam0();
1696 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1697 size_t i;
1698 Connection *conn = (Connection *)data;
1699 (void)debugConnection; /* not used */
1701 checkConnection(conn);
1703 camlDebugConnection = (value)conn;
1704 camlInfoType = Val_long(infoType);
1705 camlMessage = alloc_string(bufferLength);
1707 for (i = 0; i < bufferLength; i++)
1708 Byte(camlMessage, i) = buffer[i];
1710 callback3(Field(conn->ocamlValues, OcamlDebugCallback),
1711 camlDebugConnection,
1712 camlInfoType,
1713 camlMessage);
1715 CAMLreturnT(int, 0);
1718 static int debugFunction(CURL *debugConnection,
1719 curl_infotype infoType,
1720 char *buffer,
1721 size_t bufferLength,
1722 void *data)
1724 int r;
1725 leave_blocking_section();
1726 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1727 enter_blocking_section();
1728 return r;
1731 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1732 int cmd,
1733 void *data)
1735 CAMLparam0();
1736 CAMLlocal3(camlResult, camlConnection, camlCmd);
1737 Connection *conn = (Connection *)data;
1738 curlioerr result = CURLIOE_OK;
1739 (void)ioctl; /* not used */
1741 checkConnection(conn);
1743 if (cmd == CURLIOCMD_NOP)
1744 camlCmd = Val_long(0);
1745 else if (cmd == CURLIOCMD_RESTARTREAD)
1746 camlCmd = Val_long(1);
1747 else
1748 failwith("Invalid IOCTL Cmd!");
1750 camlConnection = caml_alloc(1, Abstract_tag);
1751 Field(camlConnection, 0) = (value)conn;
1753 camlResult = callback2(Field(conn->ocamlValues, OcamlIOCTLCallback),
1754 camlConnection,
1755 camlCmd);
1757 switch (Long_val(camlResult))
1759 case 0: /* CURLIOE_OK */
1760 result = CURLIOE_OK;
1761 break;
1763 case 1: /* CURLIOE_UNKNOWNCMD */
1764 result = CURLIOE_UNKNOWNCMD;
1765 break;
1767 case 2: /* CURLIOE_FAILRESTART */
1768 result = CURLIOE_FAILRESTART;
1769 break;
1771 default: /* Incorrect return value, but let's handle it */
1772 result = CURLIOE_FAILRESTART;
1773 break;
1776 CAMLreturnT(curlioerr, result);
1779 static curlioerr ioctlFunction(CURL *ioctl,
1780 int cmd,
1781 void *data)
1783 curlioerr r;
1784 leave_blocking_section();
1785 r = ioctlFunction_nolock(ioctl, cmd, data);
1786 enter_blocking_section();
1787 return r;
1790 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1791 static int seekFunction_nolock(void *data,
1792 curl_off_t offset,
1793 int origin)
1795 CAMLparam0();
1796 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1797 Connection *conn = (Connection *)data;
1798 int result = 0;
1800 camlOffset = copy_int64(offset);
1802 if (origin == SEEK_SET)
1803 camlOrigin = Val_long(0);
1804 else if (origin == SEEK_CUR)
1805 camlOrigin = Val_long(1);
1806 else if (origin == SEEK_END)
1807 camlOrigin = Val_long(2);
1808 else
1809 camlOrigin = Val_long(0);
1811 camlResult = callback2(Field(conn->ocamlValues,
1812 OcamlSeekFunctionCallback),
1813 camlOffset,
1814 camlOrigin);
1816 result = Int_val(camlResult);
1818 CAMLreturnT(int, result);
1821 static int seekFunction(void *data,
1822 curl_off_t offset,
1823 int origin)
1825 int r;
1826 leave_blocking_section();
1827 r = seekFunction_nolock(data,offset,origin);
1828 enter_blocking_section();
1829 return r;
1832 #endif
1834 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1835 static int openSocketFunction_nolock(void *data,
1836 curlsocktype purpose,
1837 struct curl_sockaddr *addr)
1839 CAMLparam0();
1840 Connection *conn = (Connection *)data;
1841 int sock = -1;
1842 (void)purpose; /* not used */
1844 sock = socket(addr->family, addr->socktype, addr->protocol);
1846 if (-1 != sock)
1848 /* FIXME windows */
1849 callback(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1852 CAMLreturnT(int, sock);
1855 static int openSocketFunction(void *data,
1856 curlsocktype purpose,
1857 struct curl_sockaddr *address)
1859 int r;
1860 leave_blocking_section();
1861 r = openSocketFunction_nolock(data,purpose,address);
1862 enter_blocking_section();
1863 return r;
1866 #endif
1869 ** curl_global_init helper function
1872 CAMLprim value helper_curl_global_init(value initOption)
1874 CAMLparam1(initOption);
1876 switch (Long_val(initOption))
1878 case 0: /* CURLINIT_GLOBALALL */
1879 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1880 break;
1882 case 1: /* CURLINIT_GLOBALSSL */
1883 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1884 break;
1886 case 2: /* CURLINIT_GLOBALWIN32 */
1887 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1888 break;
1890 case 3: /* CURLINIT_GLOBALNOTHING */
1891 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1892 break;
1894 default:
1895 failwith("Invalid Initialization Option");
1896 break;
1899 /* Keep compiler happy, we should never get here due to failwith() */
1900 CAMLreturn(Val_unit);
1904 ** curl_global_cleanup helper function
1907 CAMLprim value helper_curl_global_cleanup(void)
1909 CAMLparam0();
1911 curl_global_cleanup();
1913 CAMLreturn(Val_unit);
1917 ** curl_easy_init helper function
1920 CAMLprim value helper_curl_easy_init(void)
1922 CAMLparam0();
1923 CAMLlocal1(result);
1925 Connection *conn = newConnection();
1927 result = caml_alloc(1, Abstract_tag);
1928 Field(result, 0) = (value)conn;
1930 CAMLreturn(result);
1933 CAMLprim value helper_curl_easy_reset(value conn)
1935 CAMLparam1(conn);
1936 Connection *connection = Connection_val(conn);
1938 checkConnection(connection);
1939 curl_easy_reset(connection->connection);
1940 resetOcamlValues(connection);
1942 CAMLreturn(Val_unit);
1946 ** curl_easy_setopt helper utility functions
1949 static void handleWriteFunction(Connection *conn, value option)
1951 CAMLparam1(option);
1952 CURLcode result = CURLE_OK;
1954 if (Tag_val(option) == Closure_tag)
1955 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1956 else
1957 failwith("Not a proper closure");
1959 result = curl_easy_setopt(conn->connection,
1960 CURLOPT_WRITEFUNCTION,
1961 writeFunction);
1963 if (result != CURLE_OK)
1964 raiseError(conn, result);
1966 result = curl_easy_setopt(conn->connection,
1967 CURLOPT_WRITEDATA,
1968 conn);
1970 if (result != CURLE_OK)
1971 raiseError(conn, result);
1973 CAMLreturn0;
1976 static void handleReadFunction(Connection *conn, value option)
1978 CAMLparam1(option);
1979 CURLcode result = CURLE_OK;
1981 if (Tag_val(option) == Closure_tag)
1982 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1983 else
1984 failwith("Not a proper closure");
1986 result = curl_easy_setopt(conn->connection,
1987 CURLOPT_READFUNCTION,
1988 readFunction);
1990 if (result != CURLE_OK)
1991 raiseError(conn, result);
1993 result = curl_easy_setopt(conn->connection,
1994 CURLOPT_READDATA,
1995 conn);
1997 if (result != CURLE_OK)
1998 raiseError(conn, result);
2000 CAMLreturn0;
2003 static void handleURL(Connection *conn, value option)
2005 CAMLparam1(option);
2006 CURLcode result = CURLE_OK;
2008 Store_field(conn->ocamlValues, OcamlURL, option);
2010 if (conn->url != NULL)
2011 free(conn->url);
2013 conn->url = strdup(String_val(option));
2015 result = curl_easy_setopt(conn->connection,
2016 CURLOPT_URL,
2017 conn->url);
2019 if (result != CURLE_OK)
2020 raiseError(conn, result);
2022 CAMLreturn0;
2025 static void handleInFileSize(Connection *conn, value option)
2027 CAMLparam1(option);
2028 CURLcode result = CURLE_OK;
2030 result = curl_easy_setopt(conn->connection,
2031 CURLOPT_INFILESIZE,
2032 Long_val(option));
2034 if (result != CURLE_OK)
2035 raiseError(conn, result);
2037 CAMLreturn0;
2040 static void handleProxy(Connection *conn, value option)
2042 CAMLparam1(option);
2043 CURLcode result = CURLE_OK;
2045 Store_field(conn->ocamlValues, OcamlProxy, option);
2047 if (conn->proxy != NULL)
2048 free(conn->proxy);
2050 conn->proxy = strdup(String_val(option));
2052 result = curl_easy_setopt(conn->connection,
2053 CURLOPT_PROXY,
2054 conn->proxy);
2056 if (result != CURLE_OK)
2057 raiseError(conn, result);
2059 CAMLreturn0;
2062 static void handleProxyPort(Connection *conn, value option)
2064 CAMLparam1(option);
2065 CURLcode result = CURLE_OK;
2067 result = curl_easy_setopt(conn->connection,
2068 CURLOPT_PROXYPORT,
2069 Long_val(option));
2071 if (result != CURLE_OK)
2072 raiseError(conn, result);
2074 CAMLreturn0;
2077 static void handleHTTPProxyTunnel(Connection *conn, value option)
2079 CAMLparam1(option);
2080 CURLcode result = CURLE_OK;
2082 result = curl_easy_setopt(conn->connection,
2083 CURLOPT_HTTPPROXYTUNNEL,
2084 Bool_val(option));
2086 if (result != CURLE_OK)
2087 raiseError(conn, result);
2089 CAMLreturn0;
2092 static void handleVerbose(Connection *conn, value option)
2094 CAMLparam1(option);
2095 CURLcode result = CURLE_OK;
2097 result = curl_easy_setopt(conn->connection,
2098 CURLOPT_VERBOSE,
2099 Bool_val(option));
2101 if (result != CURLE_OK)
2102 raiseError(conn, result);
2104 CAMLreturn0;
2107 static void handleHeader(Connection *conn, value option)
2109 CAMLparam1(option);
2110 CURLcode result = CURLE_OK;
2112 result = curl_easy_setopt(conn->connection,
2113 CURLOPT_HEADER,
2114 Bool_val(option));
2116 if (result != CURLE_OK)
2117 raiseError(conn, result);
2119 CAMLreturn0;
2122 static void handleNoProgress(Connection *conn, value option)
2124 CAMLparam1(option);
2125 CURLcode result = CURLE_OK;
2127 result = curl_easy_setopt(conn->connection,
2128 CURLOPT_NOPROGRESS,
2129 Bool_val(option));
2131 if (result != CURLE_OK)
2132 raiseError(conn, result);
2134 CAMLreturn0;
2137 static void handleNoSignal(Connection *conn, value option)
2139 #if HAVE_DECL_CURLOPT_NOSIGNAL
2140 CAMLparam1(option);
2141 CURLcode result = CURLE_OK;
2143 result = curl_easy_setopt(conn->connection,
2144 CURLOPT_NOSIGNAL,
2145 Bool_val(option));
2147 if (result != CURLE_OK)
2148 raiseError(conn, result);
2150 CAMLreturn0;
2151 #else
2152 #pragma message("libcurl does not implement CURLOPT_NOSIGNAL")
2153 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2154 #endif
2157 static void handleNoBody(Connection *conn, value option)
2159 CAMLparam1(option);
2160 CURLcode result = CURLE_OK;
2162 result = curl_easy_setopt(conn->connection,
2163 CURLOPT_NOBODY,
2164 Bool_val(option));
2166 if (result != CURLE_OK)
2167 raiseError(conn, result);
2169 CAMLreturn0;
2172 static void handleFailOnError(Connection *conn, value option)
2174 CAMLparam1(option);
2175 CURLcode result = CURLE_OK;
2177 result = curl_easy_setopt(conn->connection,
2178 CURLOPT_FAILONERROR,
2179 Bool_val(option));
2181 if (result != CURLE_OK)
2182 raiseError(conn, result);
2184 CAMLreturn0;
2187 static void handleUpload(Connection *conn, value option)
2189 CAMLparam1(option);
2190 CURLcode result = CURLE_OK;
2192 result = curl_easy_setopt(conn->connection,
2193 CURLOPT_UPLOAD,
2194 Bool_val(option));
2196 if (result != CURLE_OK)
2197 raiseError(conn, result);
2199 CAMLreturn0;
2202 static void handlePost(Connection *conn, value option)
2204 CAMLparam1(option);
2205 CURLcode result = CURLE_OK;
2207 result = curl_easy_setopt(conn->connection,
2208 CURLOPT_POST,
2209 Bool_val(option));
2211 if (result != CURLE_OK)
2212 raiseError(conn, result);
2214 CAMLreturn0;
2217 static void handleFTPListOnly(Connection *conn, value option)
2219 CAMLparam1(option);
2220 CURLcode result = CURLE_OK;
2222 result = curl_easy_setopt(conn->connection,
2223 CURLOPT_FTPLISTONLY,
2224 Bool_val(option));
2226 if (result != CURLE_OK)
2227 raiseError(conn, result);
2229 CAMLreturn0;
2232 static void handleFTPAppend(Connection *conn, value option)
2234 CAMLparam1(option);
2235 CURLcode result = CURLE_OK;
2237 result = curl_easy_setopt(conn->connection,
2238 CURLOPT_FTPAPPEND,
2239 Bool_val(option));
2241 if (result != CURLE_OK)
2242 raiseError(conn, result);
2244 CAMLreturn0;
2247 static void handleNETRC(Connection *conn, value option)
2249 CAMLparam1(option);
2250 CURLcode result = CURLE_OK;
2251 long netrc;
2253 switch (Long_val(option))
2255 case 0: /* CURL_NETRC_OPTIONAL */
2256 netrc = CURL_NETRC_OPTIONAL;
2257 break;
2259 case 1:/* CURL_NETRC_IGNORED */
2260 netrc = CURL_NETRC_IGNORED;
2261 break;
2263 case 2: /* CURL_NETRC_REQUIRED */
2264 netrc = CURL_NETRC_REQUIRED;
2265 break;
2267 default:
2268 failwith("Invalid NETRC Option");
2269 break;
2272 result = curl_easy_setopt(conn->connection,
2273 CURLOPT_NETRC,
2274 netrc);
2276 if (result != CURLE_OK)
2277 raiseError(conn, result);
2279 CAMLreturn0;
2282 static void handleEncoding(Connection *conn, value option)
2284 #if HAVE_DECL_CURLOPT_ENCODING
2285 CAMLparam1(option);
2286 CURLcode result = CURLE_OK;
2288 switch (Long_val(option))
2290 case 0: /* CURL_ENCODING_NONE */
2291 result = curl_easy_setopt(conn->connection,
2292 CURLOPT_ENCODING,
2293 "identity");
2294 break;
2296 case 1: /* CURL_ENCODING_DEFLATE */
2297 result = curl_easy_setopt(conn->connection,
2298 CURLOPT_ENCODING,
2299 "deflate");
2300 break;
2302 case 2: /* CURL_ENCODING_GZIP */
2303 result = curl_easy_setopt(conn->connection,
2304 CURLOPT_ENCODING,
2305 "gzip");
2306 break;
2308 case 3: /* CURL_ENCODING_ANY */
2309 result = curl_easy_setopt(conn->connection,
2310 CURLOPT_ENCODING,
2311 "");
2312 break;
2314 default:
2315 failwith("Invalid Encoding Option");
2316 break;
2319 if (result != CURLE_OK)
2320 raiseError(conn, result);
2322 CAMLreturn0;
2323 #else
2324 #pragma message("libcurl does not implement CURLOPT_ENCODING")
2325 failwith("libcurl does not implement CURLOPT_ENCODING");
2326 #endif
2329 static void handleFollowLocation(Connection *conn, value option)
2331 CAMLparam1(option);
2332 CURLcode result = CURLE_OK;
2334 result = curl_easy_setopt(conn->connection,
2335 CURLOPT_FOLLOWLOCATION,
2336 Bool_val(option));
2338 if (result != CURLE_OK)
2339 raiseError(conn, result);
2341 CAMLreturn0;
2344 static void handleTransferText(Connection *conn, value option)
2346 CAMLparam1(option);
2347 CURLcode result = CURLE_OK;
2349 result = curl_easy_setopt(conn->connection,
2350 CURLOPT_TRANSFERTEXT,
2351 Bool_val(option));
2353 if (result != CURLE_OK)
2354 raiseError(conn, result);
2356 CAMLreturn0;
2359 static void handlePut(Connection *conn, value option)
2361 CAMLparam1(option);
2362 CURLcode result = CURLE_OK;
2364 result = curl_easy_setopt(conn->connection,
2365 CURLOPT_PUT,
2366 Bool_val(option));
2368 if (result != CURLE_OK)
2369 raiseError(conn, result);
2371 CAMLreturn0;
2374 static void handleUserPwd(Connection *conn, value option)
2376 CAMLparam1(option);
2377 CURLcode result = CURLE_OK;
2379 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2381 if (conn->userPwd != NULL)
2382 free(conn->userPwd);
2384 conn->userPwd = strdup(String_val(option));
2386 result = curl_easy_setopt(conn->connection,
2387 CURLOPT_USERPWD,
2388 conn->userPwd);
2390 if (result != CURLE_OK)
2391 raiseError(conn, result);
2393 CAMLreturn0;
2396 static void handleProxyUserPwd(Connection *conn, value option)
2398 CAMLparam1(option);
2399 CURLcode result = CURLE_OK;
2401 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2403 if (conn->proxyUserPwd != NULL)
2404 free(conn->proxyUserPwd);
2406 conn->proxyUserPwd = strdup(String_val(option));
2408 result = curl_easy_setopt(conn->connection,
2409 CURLOPT_PROXYUSERPWD,
2410 conn->proxyUserPwd);
2412 if (result != CURLE_OK)
2413 raiseError(conn, result);
2415 CAMLreturn0;
2418 static void handleRange(Connection *conn, value option)
2420 CAMLparam1(option);
2421 CURLcode result = CURLE_OK;
2423 Store_field(conn->ocamlValues, OcamlRange, option);
2425 if (conn->range != NULL)
2426 free(conn->range);
2428 conn->range = strdup(String_val(option));
2430 result = curl_easy_setopt(conn->connection,
2431 CURLOPT_RANGE,
2432 conn->range);
2434 if (result != CURLE_OK)
2435 raiseError(conn, result);
2437 CAMLreturn0;
2440 static void handleErrorBuffer(Connection *conn, value option)
2442 CAMLparam1(option);
2443 CURLcode result = CURLE_OK;
2445 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2447 if (conn->errorBuffer != NULL)
2448 free(conn->errorBuffer);
2450 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2452 result = curl_easy_setopt(conn->connection,
2453 CURLOPT_ERRORBUFFER,
2454 conn->errorBuffer);
2456 if (result != CURLE_OK)
2457 raiseError(conn, result);
2459 CAMLreturn0;
2462 static void handleTimeout(Connection *conn, value option)
2464 CAMLparam1(option);
2465 CURLcode result = CURLE_OK;
2467 result = curl_easy_setopt(conn->connection,
2468 CURLOPT_TIMEOUT,
2469 Long_val(option));
2471 if (result != CURLE_OK)
2472 raiseError(conn, result);
2474 CAMLreturn0;
2477 static void handlePostFields(Connection *conn, value option)
2479 CAMLparam1(option);
2480 CURLcode result = CURLE_OK;
2482 Store_field(conn->ocamlValues, OcamlPostFields, option);
2484 if (conn->postFields != NULL)
2485 free(conn->postFields);
2487 conn->postFields = malloc(string_length(option)+1);
2488 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2490 result = curl_easy_setopt(conn->connection,
2491 CURLOPT_POSTFIELDS,
2492 conn->postFields);
2494 if (result != CURLE_OK)
2495 raiseError(conn, result);
2497 CAMLreturn0;
2500 static void handlePostFieldSize(Connection *conn, value option)
2502 CAMLparam1(option);
2503 CURLcode result = CURLE_OK;
2505 result = curl_easy_setopt(conn->connection,
2506 CURLOPT_POSTFIELDSIZE,
2507 Long_val(option));
2509 if (result != CURLE_OK)
2510 raiseError(conn, result);
2512 CAMLreturn0;
2515 static void handleReferer(Connection *conn, value option)
2517 CAMLparam1(option);
2518 CURLcode result = CURLE_OK;
2520 Store_field(conn->ocamlValues, OcamlReferer, option);
2522 if (conn->referer != NULL)
2523 free(conn->referer);
2525 conn->referer = strdup(String_val(option));
2527 result = curl_easy_setopt(conn->connection,
2528 CURLOPT_REFERER,
2529 conn->referer);
2531 if (result != CURLE_OK)
2532 raiseError(conn, result);
2534 CAMLreturn0;
2537 static void handleUserAgent(Connection *conn, value option)
2539 CAMLparam1(option);
2540 CURLcode result = CURLE_OK;
2542 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2544 if (conn->userAgent != NULL)
2545 free(conn->userAgent);
2547 conn->userAgent = strdup(String_val(option));
2549 result = curl_easy_setopt(conn->connection,
2550 CURLOPT_USERAGENT,
2551 conn->userAgent);
2553 if (result != CURLE_OK)
2554 raiseError(conn, result);
2556 CAMLreturn0;
2559 static void handleFTPPort(Connection *conn, value option)
2561 CAMLparam1(option);
2562 CURLcode result = CURLE_OK;
2564 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2566 if (conn->ftpPort != NULL)
2567 free(conn->ftpPort);
2569 conn->ftpPort = strdup(String_val(option));
2571 result = curl_easy_setopt(conn->connection,
2572 CURLOPT_FTPPORT,
2573 conn->ftpPort);
2575 if (result != CURLE_OK)
2576 raiseError(conn, result);
2578 CAMLreturn0;
2581 static void handleLowSpeedLimit(Connection *conn, value option)
2583 CAMLparam1(option);
2584 CURLcode result = CURLE_OK;
2586 result = curl_easy_setopt(conn->connection,
2587 CURLOPT_LOW_SPEED_LIMIT,
2588 Long_val(option));
2590 if (result != CURLE_OK)
2591 raiseError(conn, result);
2593 CAMLreturn0;
2596 static void handleLowSpeedTime(Connection *conn, value option)
2598 CAMLparam1(option);
2599 CURLcode result = CURLE_OK;
2601 result = curl_easy_setopt(conn->connection,
2602 CURLOPT_LOW_SPEED_TIME,
2603 Long_val(option));
2605 if (result != CURLE_OK)
2606 raiseError(conn, result);
2608 CAMLreturn0;
2611 static void handleResumeFrom(Connection *conn, value option)
2613 CAMLparam1(option);
2614 CURLcode result = CURLE_OK;
2616 result = curl_easy_setopt(conn->connection,
2617 CURLOPT_RESUME_FROM,
2618 Long_val(option));
2620 if (result != CURLE_OK)
2621 raiseError(conn, result);
2623 CAMLreturn0;
2626 static void handleCookie(Connection *conn, value option)
2628 CAMLparam1(option);
2629 CURLcode result = CURLE_OK;
2631 Store_field(conn->ocamlValues, OcamlCookie, option);
2633 if (conn->cookie != NULL)
2634 free(conn->cookie);
2636 conn->cookie = strdup(String_val(option));
2638 result = curl_easy_setopt(conn->connection,
2639 CURLOPT_COOKIE,
2640 conn->cookie);
2642 if (result != CURLE_OK)
2643 raiseError(conn, result);
2645 CAMLreturn0;
2648 static void handleHTTPHeader(Connection *conn, value option)
2650 CAMLparam1(option);
2651 CAMLlocal1(listIter);
2652 CURLcode result = CURLE_OK;
2654 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2656 free_curl_slist(conn->httpHeader);
2657 conn->httpHeader = NULL;
2659 listIter = option;
2661 while (!Is_long(listIter))
2663 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2665 listIter = Field(listIter, 1);
2668 result = curl_easy_setopt(conn->connection,
2669 CURLOPT_HTTPHEADER,
2670 conn->httpHeader);
2672 if (result != CURLE_OK)
2673 raiseError(conn, result);
2675 CAMLreturn0;
2678 static void handleHTTPPost(Connection *conn, value option)
2680 CAMLparam1(option);
2681 CAMLlocal3(listIter, formItem, contentType);
2682 CURLcode result = CURLE_OK;
2683 char *str1, *str2, *str3, *str4;
2685 listIter = option;
2687 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2689 if (conn->httpPostFirst != NULL)
2690 curl_formfree(conn->httpPostFirst);
2692 conn->httpPostFirst = NULL;
2693 conn->httpPostLast = NULL;
2695 free_curl_slist(conn->httpPostStrings);
2696 conn->httpPostStrings = NULL;
2698 while (!Is_long(listIter))
2700 formItem = Field(listIter, 0);
2702 switch (Tag_val(formItem))
2704 case 0: /* CURLFORM_CONTENT */
2705 if (Wosize_val(formItem) < 3)
2707 failwith("Incorrect CURLFORM_CONTENT parameters");
2710 if (Is_long(Field(formItem, 2)) &&
2711 Long_val(Field(formItem, 2)) == 0)
2713 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2714 memcpy(str1,
2715 String_val(Field(formItem, 0)),
2716 string_length(Field(formItem, 0)));
2717 str1[string_length(Field(formItem, 0))] = 0;
2718 conn->httpPostStrings =
2719 curl_slist_append(conn->httpPostStrings, str1);
2721 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2722 memcpy(str2,
2723 String_val(Field(formItem, 1)),
2724 string_length(Field(formItem, 1)));
2725 str2[string_length(Field(formItem, 1))] = 0;
2726 conn->httpPostStrings =
2727 curl_slist_append(conn->httpPostStrings, str2);
2729 curl_formadd(&conn->httpPostFirst,
2730 &conn->httpPostLast,
2731 CURLFORM_PTRNAME,
2732 str1,
2733 CURLFORM_NAMELENGTH,
2734 string_length(Field(formItem, 0)),
2735 CURLFORM_PTRCONTENTS,
2736 str2,
2737 CURLFORM_CONTENTSLENGTH,
2738 string_length(Field(formItem, 1)),
2739 CURLFORM_END);
2741 else if (Is_block(Field(formItem, 2)))
2743 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2744 memcpy(str1,
2745 String_val(Field(formItem, 0)),
2746 string_length(Field(formItem, 0)));
2747 str1[string_length(Field(formItem, 0))] = 0;
2748 conn->httpPostStrings =
2749 curl_slist_append(conn->httpPostStrings, str1);
2751 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2752 memcpy(str2,
2753 String_val(Field(formItem, 1)),
2754 string_length(Field(formItem, 1)));
2755 str2[string_length(Field(formItem, 1))] = 0;
2756 conn->httpPostStrings =
2757 curl_slist_append(conn->httpPostStrings, str2);
2759 contentType = Field(formItem, 2);
2761 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2762 memcpy(str3,
2763 String_val(Field(contentType, 0)),
2764 string_length(Field(contentType, 0)));
2765 str3[string_length(Field(contentType, 0))] = 0;
2766 conn->httpPostStrings =
2767 curl_slist_append(conn->httpPostStrings, str3);
2769 curl_formadd(&conn->httpPostFirst,
2770 &conn->httpPostLast,
2771 CURLFORM_PTRNAME,
2772 str1,
2773 CURLFORM_NAMELENGTH,
2774 string_length(Field(formItem, 0)),
2775 CURLFORM_PTRCONTENTS,
2776 str2,
2777 CURLFORM_CONTENTSLENGTH,
2778 string_length(Field(formItem, 1)),
2779 CURLFORM_CONTENTTYPE,
2780 str3,
2781 CURLFORM_END);
2783 else
2785 failwith("Incorrect CURLFORM_CONTENT parameters");
2787 break;
2789 case 1: /* CURLFORM_FILECONTENT */
2790 if (Wosize_val(formItem) < 3)
2792 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2795 if (Is_long(Field(formItem, 2)) &&
2796 Long_val(Field(formItem, 2)) == 0)
2798 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2799 memcpy(str1,
2800 String_val(Field(formItem, 0)),
2801 string_length(Field(formItem, 0)));
2802 str1[string_length(Field(formItem, 0))] = 0;
2803 conn->httpPostStrings =
2804 curl_slist_append(conn->httpPostStrings, str1);
2806 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2807 memcpy(str2,
2808 String_val(Field(formItem, 1)),
2809 string_length(Field(formItem, 1)));
2810 str2[string_length(Field(formItem, 1))] = 0;
2811 conn->httpPostStrings =
2812 curl_slist_append(conn->httpPostStrings, str2);
2814 curl_formadd(&conn->httpPostFirst,
2815 &conn->httpPostLast,
2816 CURLFORM_PTRNAME,
2817 str1,
2818 CURLFORM_NAMELENGTH,
2819 string_length(Field(formItem, 0)),
2820 CURLFORM_FILECONTENT,
2821 str2,
2822 CURLFORM_END);
2824 else if (Is_block(Field(formItem, 2)))
2826 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2827 memcpy(str1,
2828 String_val(Field(formItem, 0)),
2829 string_length(Field(formItem, 0)));
2830 str1[string_length(Field(formItem, 0))] = 0;
2831 conn->httpPostStrings =
2832 curl_slist_append(conn->httpPostStrings, str1);
2834 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2835 memcpy(str2,
2836 String_val(Field(formItem, 1)),
2837 string_length(Field(formItem, 1)));
2838 str2[string_length(Field(formItem, 1))] = 0;
2839 conn->httpPostStrings =
2840 curl_slist_append(conn->httpPostStrings, str2);
2842 contentType = Field(formItem, 2);
2844 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2845 memcpy(str3,
2846 String_val(Field(contentType, 0)),
2847 string_length(Field(contentType, 0)));
2848 str3[string_length(Field(contentType, 0))] = 0;
2849 conn->httpPostStrings =
2850 curl_slist_append(conn->httpPostStrings, str3);
2852 curl_formadd(&conn->httpPostFirst,
2853 &conn->httpPostLast,
2854 CURLFORM_PTRNAME,
2855 str1,
2856 CURLFORM_NAMELENGTH,
2857 string_length(Field(formItem, 0)),
2858 CURLFORM_FILECONTENT,
2859 str2,
2860 CURLFORM_CONTENTTYPE,
2861 str3,
2862 CURLFORM_END);
2864 else
2866 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2868 break;
2870 case 2: /* CURLFORM_FILE */
2871 if (Wosize_val(formItem) < 3)
2873 failwith("Incorrect CURLFORM_FILE parameters");
2876 if (Is_long(Field(formItem, 2)) &&
2877 Long_val(Field(formItem, 2)) == 0)
2879 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2880 memcpy(str1,
2881 String_val(Field(formItem, 0)),
2882 string_length(Field(formItem, 0)));
2883 str1[string_length(Field(formItem, 0))] = 0;
2884 conn->httpPostStrings =
2885 curl_slist_append(conn->httpPostStrings, str1);
2887 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2888 memcpy(str2,
2889 String_val(Field(formItem, 1)),
2890 string_length(Field(formItem, 1)));
2891 str2[string_length(Field(formItem, 1))] = 0;
2892 conn->httpPostStrings =
2893 curl_slist_append(conn->httpPostStrings, str2);
2895 curl_formadd(&conn->httpPostFirst,
2896 &conn->httpPostLast,
2897 CURLFORM_PTRNAME,
2898 str1,
2899 CURLFORM_NAMELENGTH,
2900 string_length(Field(formItem, 0)),
2901 CURLFORM_FILE,
2902 str2,
2903 CURLFORM_END);
2905 else if (Is_block(Field(formItem, 2)))
2907 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2908 memcpy(str1,
2909 String_val(Field(formItem, 0)),
2910 string_length(Field(formItem, 0)));
2911 str1[string_length(Field(formItem, 0))] = 0;
2912 conn->httpPostStrings =
2913 curl_slist_append(conn->httpPostStrings, str1);
2915 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2916 memcpy(str2,
2917 String_val(Field(formItem, 1)),
2918 string_length(Field(formItem, 1)));
2919 str2[string_length(Field(formItem, 1))] = 0;
2920 conn->httpPostStrings =
2921 curl_slist_append(conn->httpPostStrings, str2);
2923 contentType = Field(formItem, 2);
2925 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2926 memcpy(str3,
2927 String_val(Field(contentType, 0)),
2928 string_length(Field(contentType, 0)));
2929 str3[string_length(Field(contentType, 0))] = 0;
2930 conn->httpPostStrings =
2931 curl_slist_append(conn->httpPostStrings, str3);
2933 curl_formadd(&conn->httpPostFirst,
2934 &conn->httpPostLast,
2935 CURLFORM_PTRNAME,
2936 str1,
2937 CURLFORM_NAMELENGTH,
2938 string_length(Field(formItem, 0)),
2939 CURLFORM_FILE,
2940 str2,
2941 CURLFORM_CONTENTTYPE,
2942 str3,
2943 CURLFORM_END);
2945 else
2947 failwith("Incorrect CURLFORM_FILE parameters");
2949 break;
2951 case 3: /* CURLFORM_BUFFER */
2952 if (Wosize_val(formItem) < 4)
2954 failwith("Incorrect CURLFORM_BUFFER parameters");
2957 if (Is_long(Field(formItem, 3)) &&
2958 Long_val(Field(formItem, 3)) == 0)
2960 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2961 memcpy(str1,
2962 String_val(Field(formItem, 0)),
2963 string_length(Field(formItem, 0)));
2964 str1[string_length(Field(formItem, 0))] = 0;
2965 conn->httpPostStrings =
2966 curl_slist_append(conn->httpPostStrings, str1);
2968 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2969 memcpy(str2,
2970 String_val(Field(formItem, 1)),
2971 string_length(Field(formItem, 1)));
2972 str2[string_length(Field(formItem, 1))] = 0;
2973 conn->httpPostStrings =
2974 curl_slist_append(conn->httpPostStrings, str2);
2976 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2977 memcpy(str3,
2978 String_val(Field(formItem, 2)),
2979 string_length(Field(formItem, 2)));
2980 str3[string_length(Field(formItem, 2))] = 0;
2981 conn->httpPostStrings =
2982 curl_slist_append(conn->httpPostStrings, str3);
2984 curl_formadd(&conn->httpPostFirst,
2985 &conn->httpPostLast,
2986 CURLFORM_PTRNAME,
2987 str1,
2988 CURLFORM_NAMELENGTH,
2989 string_length(Field(formItem, 0)),
2990 CURLFORM_BUFFER,
2991 str2,
2992 CURLFORM_BUFFERPTR,
2993 str3,
2994 CURLFORM_BUFFERLENGTH,
2995 string_length(Field(formItem, 2)),
2996 CURLFORM_END);
2998 else if (Is_block(Field(formItem, 3)))
3000 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
3001 memcpy(str1,
3002 String_val(Field(formItem, 0)),
3003 string_length(Field(formItem, 0)));
3004 str1[string_length(Field(formItem, 0))] = 0;
3005 conn->httpPostStrings =
3006 curl_slist_append(conn->httpPostStrings, str1);
3008 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
3009 memcpy(str2,
3010 String_val(Field(formItem, 1)),
3011 string_length(Field(formItem, 1)));
3012 str2[string_length(Field(formItem, 1))] = 0;
3013 conn->httpPostStrings =
3014 curl_slist_append(conn->httpPostStrings, str2);
3016 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
3017 memcpy(str3,
3018 String_val(Field(formItem, 2)),
3019 string_length(Field(formItem, 2)));
3020 str3[string_length(Field(formItem, 2))] = 0;
3021 conn->httpPostStrings =
3022 curl_slist_append(conn->httpPostStrings, str3);
3024 contentType = Field(formItem, 3);
3026 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
3027 memcpy(str4,
3028 String_val(Field(contentType, 0)),
3029 string_length(Field(contentType, 0)));
3030 str4[string_length(Field(contentType, 0))] = 0;
3031 conn->httpPostStrings =
3032 curl_slist_append(conn->httpPostStrings, str4);
3034 curl_formadd(&conn->httpPostFirst,
3035 &conn->httpPostLast,
3036 CURLFORM_PTRNAME,
3037 str1,
3038 CURLFORM_NAMELENGTH,
3039 string_length(Field(formItem, 0)),
3040 CURLFORM_BUFFER,
3041 str2,
3042 CURLFORM_BUFFERPTR,
3043 str3,
3044 CURLFORM_BUFFERLENGTH,
3045 string_length(Field(formItem, 2)),
3046 CURLFORM_CONTENTTYPE,
3047 str4,
3048 CURLFORM_END);
3050 else
3052 failwith("Incorrect CURLFORM_BUFFER parameters");
3054 break;
3057 listIter = Field(listIter, 1);
3060 result = curl_easy_setopt(conn->connection,
3061 CURLOPT_HTTPPOST,
3062 conn->httpPostFirst);
3064 if (result != CURLE_OK)
3065 raiseError(conn, result);
3067 CAMLreturn0;
3070 static void handleSSLCert(Connection *conn, value option)
3072 CAMLparam1(option);
3073 CURLcode result = CURLE_OK;
3075 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3077 if (conn->sslCert != NULL)
3078 free(conn->sslCert);
3080 conn->sslCert = strdup(String_val(option));
3082 result = curl_easy_setopt(conn->connection,
3083 CURLOPT_SSLCERT,
3084 conn->sslCert);
3086 if (result != CURLE_OK)
3087 raiseError(conn, result);
3089 CAMLreturn0;
3092 static void handleSSLCertType(Connection *conn, value option)
3094 CAMLparam1(option);
3095 CURLcode result = CURLE_OK;
3097 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3099 if (conn->sslCertType != NULL)
3100 free(conn->sslCertType);
3102 conn->sslCertType = strdup(String_val(option));
3104 result = curl_easy_setopt(conn->connection,
3105 CURLOPT_SSLCERTTYPE,
3106 conn->sslCertType);
3108 if (result != CURLE_OK)
3109 raiseError(conn, result);
3111 CAMLreturn0;
3114 static void handleSSLCertPasswd(Connection *conn, value option)
3116 CAMLparam1(option);
3117 CURLcode result = CURLE_OK;
3119 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3121 if (conn->sslCertPasswd != NULL)
3122 free(conn->sslCertPasswd);
3124 conn->sslCertPasswd = strdup(String_val(option));
3126 result = curl_easy_setopt(conn->connection,
3127 CURLOPT_SSLCERTPASSWD,
3128 conn->sslCertPasswd);
3130 if (result != CURLE_OK)
3131 raiseError(conn, result);
3133 CAMLreturn0;
3136 static void handleSSLKey(Connection *conn, value option)
3138 CAMLparam1(option);
3139 CURLcode result = CURLE_OK;
3141 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3143 if (conn->sslKey != NULL)
3144 free(conn->sslKey);
3146 conn->sslKey = strdup(String_val(option));
3148 result = curl_easy_setopt(conn->connection,
3149 CURLOPT_SSLKEY,
3150 conn->sslKey);
3152 if (result != CURLE_OK)
3153 raiseError(conn, result);
3155 CAMLreturn0;
3158 static void handleSSLKeyType(Connection *conn, value option)
3160 CAMLparam1(option);
3161 CURLcode result = CURLE_OK;
3163 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3165 if (conn->sslKeyType != NULL)
3166 free(conn->sslKeyType);
3168 conn->sslKeyType = strdup(String_val(option));
3170 result = curl_easy_setopt(conn->connection,
3171 CURLOPT_SSLKEYTYPE,
3172 conn->sslKeyType);
3174 if (result != CURLE_OK)
3175 raiseError(conn, result);
3177 CAMLreturn0;
3180 static void handleSSLKeyPasswd(Connection *conn, value option)
3182 CAMLparam1(option);
3183 CURLcode result = CURLE_OK;
3185 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3187 if (conn->sslKeyPasswd != NULL)
3188 free(conn->sslKeyPasswd);
3190 conn->sslKeyPasswd = strdup(String_val(option));
3192 result = curl_easy_setopt(conn->connection,
3193 CURLOPT_SSLKEYPASSWD,
3194 conn->sslKeyPasswd);
3196 if (result != CURLE_OK)
3197 raiseError(conn, result);
3199 CAMLreturn0;
3202 static void handleSSLEngine(Connection *conn, value option)
3204 CAMLparam1(option);
3205 CURLcode result = CURLE_OK;
3207 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3209 if (conn->sslEngine != NULL)
3210 free(conn->sslEngine);
3212 conn->sslEngine = strdup(String_val(option));
3214 result = curl_easy_setopt(conn->connection,
3215 CURLOPT_SSLENGINE,
3216 conn->sslEngine);
3218 if (result != CURLE_OK)
3219 raiseError(conn, result);
3221 CAMLreturn0;
3224 static void handleSSLEngineDefault(Connection *conn, value option)
3226 CAMLparam1(option);
3227 CURLcode result = CURLE_OK;
3229 result = curl_easy_setopt(conn->connection,
3230 CURLOPT_SSLENGINE_DEFAULT,
3231 Bool_val(option));
3233 if (result != CURLE_OK)
3234 raiseError(conn, result);
3236 CAMLreturn0;
3239 static void handleCRLF(Connection *conn, value option)
3241 CAMLparam1(option);
3242 CURLcode result = CURLE_OK;
3244 result = curl_easy_setopt(conn->connection,
3245 CURLOPT_CRLF,
3246 Bool_val(option));
3248 if (result != CURLE_OK)
3249 raiseError(conn, result);
3251 CAMLreturn0;
3254 static void handleQuote(Connection *conn, value option)
3256 CAMLparam1(option);
3257 CAMLlocal1(listIter);
3258 CURLcode result = CURLE_OK;
3260 Store_field(conn->ocamlValues, OcamlQuote, option);
3262 free_curl_slist(conn->quote);
3263 conn->quote = NULL;
3265 listIter = option;
3267 while (!Is_long(listIter))
3269 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3271 listIter = Field(listIter, 1);
3274 result = curl_easy_setopt(conn->connection,
3275 CURLOPT_QUOTE,
3276 conn->quote);
3278 if (result != CURLE_OK)
3279 raiseError(conn, result);
3281 CAMLreturn0;
3284 static void handlePostQuote(Connection *conn, value option)
3286 CAMLparam1(option);
3287 CAMLlocal1(listIter);
3288 CURLcode result = CURLE_OK;
3290 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3292 free_curl_slist(conn->postQuote);
3293 conn->postQuote = NULL;
3295 listIter = option;
3297 while (!Is_long(listIter))
3299 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3301 listIter = Field(listIter, 1);
3304 result = curl_easy_setopt(conn->connection,
3305 CURLOPT_POSTQUOTE,
3306 conn->postQuote);
3308 if (result != CURLE_OK)
3309 raiseError(conn, result);
3311 CAMLreturn0;
3314 static void handleHeaderFunction(Connection *conn, value option)
3316 CAMLparam1(option);
3317 CURLcode result = CURLE_OK;
3319 if (Tag_val(option) == Closure_tag)
3320 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3321 else
3322 failwith("Not a proper closure");
3324 result = curl_easy_setopt(conn->connection,
3325 CURLOPT_HEADERFUNCTION,
3326 headerFunction);
3328 if (result != CURLE_OK)
3329 raiseError(conn, result);
3331 result = curl_easy_setopt(conn->connection,
3332 CURLOPT_WRITEHEADER,
3333 conn);
3335 if (result != CURLE_OK)
3336 raiseError(conn, result);
3338 CAMLreturn0;
3341 static void handleCookieFile(Connection *conn, value option)
3343 CAMLparam1(option);
3344 CURLcode result = CURLE_OK;
3346 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3348 if (conn->cookieFile != NULL)
3349 free(conn->cookieFile);
3351 conn->cookieFile = strdup(String_val(option));
3353 result = curl_easy_setopt(conn->connection,
3354 CURLOPT_COOKIEFILE,
3355 conn->cookieFile);
3357 if (result != CURLE_OK)
3358 raiseError(conn, result);
3360 CAMLreturn0;
3363 static void handleSSLVersion(Connection *conn, value option)
3365 CAMLparam1(option);
3366 CURLcode result = CURLE_OK;
3368 result = curl_easy_setopt(conn->connection,
3369 CURLOPT_SSLVERSION,
3370 Long_val(option));
3372 if (result != CURLE_OK)
3373 raiseError(conn, result);
3375 CAMLreturn0;
3378 static void handleTimeCondition(Connection *conn, value option)
3380 CAMLparam1(option);
3381 CURLcode result = CURLE_OK;
3383 switch (Long_val(option))
3385 case 0: /* TIMECOND_IFMODSINCE */
3386 result = curl_easy_setopt(conn->connection,
3387 CURLOPT_TIMECONDITION,
3388 CURL_TIMECOND_IFMODSINCE);
3389 break;
3391 case 1: /* TIMECOND_IFUNMODSINCE */
3392 result = curl_easy_setopt(conn->connection,
3393 CURLOPT_TIMECONDITION,
3394 CURL_TIMECOND_IFUNMODSINCE);
3395 break;
3397 default:
3398 failwith("Invalid TIMECOND Option");
3399 break;
3402 if (result != CURLE_OK)
3403 raiseError(conn, result);
3405 CAMLreturn0;
3408 static void handleTimeValue(Connection *conn, value option)
3410 CAMLparam1(option);
3411 CURLcode result = CURLE_OK;
3413 result = curl_easy_setopt(conn->connection,
3414 CURLOPT_TIMEVALUE,
3415 Int32_val(option));
3417 if (result != CURLE_OK)
3418 raiseError(conn, result);
3420 CAMLreturn0;
3423 static void handleCustomRequest(Connection *conn, value option)
3425 CAMLparam1(option);
3426 CURLcode result = CURLE_OK;
3428 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3430 if (conn->customRequest != NULL)
3431 free(conn->customRequest);
3433 conn->customRequest = strdup(String_val(option));
3435 result = curl_easy_setopt(conn->connection,
3436 CURLOPT_CUSTOMREQUEST,
3437 conn->customRequest);
3439 if (result != CURLE_OK)
3440 raiseError(conn, result);
3442 CAMLreturn0;
3445 static void handleInterface(Connection *conn, value option)
3447 CAMLparam1(option);
3448 CURLcode result = CURLE_OK;
3450 Store_field(conn->ocamlValues, OcamlInterface, option);
3452 if (conn->interface_ != NULL)
3453 free(conn->interface_);
3455 conn->interface_ = strdup(String_val(option));
3457 result = curl_easy_setopt(conn->connection,
3458 CURLOPT_INTERFACE,
3459 conn->interface_);
3461 if (result != CURLE_OK)
3462 raiseError(conn, result);
3464 CAMLreturn0;
3467 static void handleKRB4Level(Connection *conn, value option)
3469 CAMLparam1(option);
3470 CURLcode result = CURLE_OK;
3472 switch (Long_val(option))
3474 case 0: /* KRB4_NONE */
3475 result = curl_easy_setopt(conn->connection,
3476 CURLOPT_KRB4LEVEL,
3477 NULL);
3478 break;
3480 case 1: /* KRB4_CLEAR */
3481 result = curl_easy_setopt(conn->connection,
3482 CURLOPT_KRB4LEVEL,
3483 "clear");
3484 break;
3486 case 2: /* KRB4_SAFE */
3487 result = curl_easy_setopt(conn->connection,
3488 CURLOPT_KRB4LEVEL,
3489 "safe");
3490 break;
3492 case 3: /* KRB4_CONFIDENTIAL */
3493 result = curl_easy_setopt(conn->connection,
3494 CURLOPT_KRB4LEVEL,
3495 "confidential");
3496 break;
3498 case 4: /* KRB4_PRIVATE */
3499 result = curl_easy_setopt(conn->connection,
3500 CURLOPT_KRB4LEVEL,
3501 "private");
3502 break;
3504 default:
3505 failwith("Invalid KRB4 Option");
3506 break;
3509 if (result != CURLE_OK)
3510 raiseError(conn, result);
3512 CAMLreturn0;
3515 static void handleProgressFunction(Connection *conn, value option)
3517 CAMLparam1(option);
3518 CURLcode result = CURLE_OK;
3520 if (Tag_val(option) == Closure_tag)
3521 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3522 else
3523 failwith("Not a proper closure");
3525 result = curl_easy_setopt(conn->connection,
3526 CURLOPT_PROGRESSFUNCTION,
3527 progressFunction);
3528 if (result != CURLE_OK)
3529 raiseError(conn, result);
3531 result = curl_easy_setopt(conn->connection,
3532 CURLOPT_PROGRESSDATA,
3533 conn);
3535 if (result != CURLE_OK)
3536 raiseError(conn, result);
3538 CAMLreturn0;
3541 static void handleSSLVerifyPeer(Connection *conn, value option)
3543 CAMLparam1(option);
3544 CURLcode result = CURLE_OK;
3546 result = curl_easy_setopt(conn->connection,
3547 CURLOPT_SSL_VERIFYPEER,
3548 Bool_val(option));
3550 if (result != CURLE_OK)
3551 raiseError(conn, result);
3553 CAMLreturn0;
3556 static void handleCAInfo(Connection *conn, value option)
3558 CAMLparam1(option);
3559 CURLcode result = CURLE_OK;
3561 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3563 if (conn->caInfo != NULL)
3564 free(conn->caInfo);
3566 conn->caInfo = strdup(String_val(option));
3568 result = curl_easy_setopt(conn->connection,
3569 CURLOPT_CAINFO,
3570 conn->caInfo);
3572 if (result != CURLE_OK)
3573 raiseError(conn, result);
3575 CAMLreturn0;
3578 static void handleCAPath(Connection *conn, value option)
3580 CAMLparam1(option);
3581 CURLcode result = CURLE_OK;
3583 Store_field(conn->ocamlValues, OcamlCAPath, option);
3585 if (conn->caPath != NULL)
3586 free(conn->caPath);
3588 conn->caPath = strdup(String_val(option));
3590 result = curl_easy_setopt(conn->connection,
3591 CURLOPT_CAPATH,
3592 conn->caPath);
3594 if (result != CURLE_OK)
3595 raiseError(conn, result);
3597 CAMLreturn0;
3600 static void handleFileTime(Connection *conn, value option)
3602 CAMLparam1(option);
3603 CURLcode result = CURLE_OK;
3605 result = curl_easy_setopt(conn->connection,
3606 CURLOPT_FILETIME,
3607 Bool_val(option));
3609 if (result != CURLE_OK)
3610 raiseError(conn, result);
3612 CAMLreturn0;
3615 static void handleMaxRedirs(Connection *conn, value option)
3617 CAMLparam1(option);
3618 CURLcode result = CURLE_OK;
3620 result = curl_easy_setopt(conn->connection,
3621 CURLOPT_MAXREDIRS,
3622 Long_val(option));
3624 if (result != CURLE_OK)
3625 raiseError(conn, result);
3627 CAMLreturn0;
3630 static void handleMaxConnects(Connection *conn, value option)
3632 CAMLparam1(option);
3633 CURLcode result = CURLE_OK;
3635 result = curl_easy_setopt(conn->connection,
3636 CURLOPT_MAXCONNECTS,
3637 Long_val(option));
3639 if (result != CURLE_OK)
3640 raiseError(conn, result);
3642 CAMLreturn0;
3645 static void handleClosePolicy(Connection *conn, value option)
3647 CAMLparam1(option);
3648 CURLcode result = CURLE_OK;
3650 switch (Long_val(option))
3652 case 0: /* CLOSEPOLICY_OLDEST */
3653 result = curl_easy_setopt(conn->connection,
3654 CURLOPT_CLOSEPOLICY,
3655 CURLCLOSEPOLICY_OLDEST);
3656 break;
3658 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3659 result = curl_easy_setopt(conn->connection,
3660 CURLOPT_CLOSEPOLICY,
3661 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3662 break;
3664 default:
3665 failwith("Invalid CLOSEPOLICY Option");
3666 break;
3669 if (result != CURLE_OK)
3670 raiseError(conn, result);
3672 CAMLreturn0;
3675 static void handleFreshConnect(Connection *conn, value option)
3677 CAMLparam1(option);
3678 CURLcode result = CURLE_OK;
3680 result = curl_easy_setopt(conn->connection,
3681 CURLOPT_FRESH_CONNECT,
3682 Bool_val(option));
3684 if (result != CURLE_OK)
3685 raiseError(conn, result);
3687 CAMLreturn0;
3690 static void handleForbidReuse(Connection *conn, value option)
3692 CAMLparam1(option);
3693 CURLcode result = CURLE_OK;
3695 result = curl_easy_setopt(conn->connection,
3696 CURLOPT_FORBID_REUSE,
3697 Bool_val(option));
3699 if (result != CURLE_OK)
3700 raiseError(conn, result);
3702 CAMLreturn0;
3705 static void handleRandomFile(Connection *conn, value option)
3707 CAMLparam1(option);
3708 CURLcode result = CURLE_OK;
3710 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3712 if (conn->randomFile != NULL)
3713 free(conn->randomFile);
3715 conn->randomFile = strdup(String_val(option));
3717 result = curl_easy_setopt(conn->connection,
3718 CURLOPT_RANDOM_FILE,
3719 conn->randomFile);
3721 if (result != CURLE_OK)
3722 raiseError(conn, result);
3724 CAMLreturn0;
3727 static void handleEGDSocket(Connection *conn, value option)
3729 CAMLparam1(option);
3730 CURLcode result = CURLE_OK;
3732 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3734 if (conn->egdSocket != NULL)
3735 free(conn->egdSocket);
3737 conn->egdSocket = strdup(String_val(option));
3739 result = curl_easy_setopt(conn->connection,
3740 CURLOPT_EGDSOCKET,
3741 conn->egdSocket);
3743 if (result != CURLE_OK)
3744 raiseError(conn, result);
3746 CAMLreturn0;
3749 static void handleConnectTimeout(Connection *conn, value option)
3751 CAMLparam1(option);
3752 CURLcode result = CURLE_OK;
3754 result = curl_easy_setopt(conn->connection,
3755 CURLOPT_CONNECTTIMEOUT,
3756 Long_val(option));
3758 if (result != CURLE_OK)
3759 raiseError(conn, result);
3761 CAMLreturn0;
3764 static void handleHTTPGet(Connection *conn, value option)
3766 CAMLparam1(option);
3767 CURLcode result = CURLE_OK;
3769 result = curl_easy_setopt(conn->connection,
3770 CURLOPT_HTTPGET,
3771 Bool_val(option));
3773 if (result != CURLE_OK)
3774 raiseError(conn, result);
3776 CAMLreturn0;
3779 static void handleSSLVerifyHost(Connection *conn, value option)
3781 CAMLparam1(option);
3782 CURLcode result = CURLE_OK;
3784 switch (Long_val(option))
3786 case 0: /* SSLVERIFYHOST_NONE */
3787 case 1: /* SSLVERIFYHOST_EXISTENCE */
3788 case 2: /* SSLVERIFYHOST_HOSTNAME */
3789 result = curl_easy_setopt(conn->connection,
3790 CURLOPT_SSL_VERIFYHOST,
3791 /* map EXISTENCE to HOSTNAME */
3792 Long_val(option) == 0 ? 0 : 2);
3793 break;
3795 default:
3796 failwith("Invalid SSLVERIFYHOST Option");
3797 break;
3800 if (result != CURLE_OK)
3801 raiseError(conn, result);
3803 CAMLreturn0;
3806 static void handleCookieJar(Connection *conn, value option)
3808 CAMLparam1(option);
3809 CURLcode result = CURLE_OK;
3811 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3813 if (conn->cookieJar != NULL)
3814 free(conn->cookieJar);
3816 conn->cookieJar = strdup(String_val(option));
3818 result = curl_easy_setopt(conn->connection,
3819 CURLOPT_COOKIEJAR,
3820 conn->cookieJar);
3822 if (result != CURLE_OK)
3823 raiseError(conn, result);
3825 CAMLreturn0;
3828 static void handleSSLCipherList(Connection *conn, value option)
3830 CAMLparam1(option);
3831 CURLcode result = CURLE_OK;
3833 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3835 if (conn->sslCipherList != NULL)
3836 free(conn->sslCipherList);
3838 conn->sslCipherList = strdup(String_val(option));
3840 result = curl_easy_setopt(conn->connection,
3841 CURLOPT_SSL_CIPHER_LIST,
3842 conn->sslCipherList);
3844 if (result != CURLE_OK)
3845 raiseError(conn, result);
3847 CAMLreturn0;
3850 static void handleHTTPVersion(Connection *conn, value option)
3852 CAMLparam1(option);
3853 CURLcode result = CURLE_OK;
3855 switch (Long_val(option))
3857 case 0: /* HTTP_VERSION_NONE */
3858 result = curl_easy_setopt(conn->connection,
3859 CURLOPT_HTTP_VERSION,
3860 CURL_HTTP_VERSION_NONE);
3861 break;
3863 case 1: /* HTTP_VERSION_1_0 */
3864 result = curl_easy_setopt(conn->connection,
3865 CURLOPT_HTTP_VERSION,
3866 CURL_HTTP_VERSION_1_0);
3867 break;
3869 case 2: /* HTTP_VERSION_1_1 */
3870 result = curl_easy_setopt(conn->connection,
3871 CURLOPT_HTTP_VERSION,
3872 CURL_HTTP_VERSION_1_1);
3873 break;
3875 default:
3876 failwith("Invalid HTTP_VERSION Option");
3877 break;
3880 if (result != CURLE_OK)
3881 raiseError(conn, result);
3883 CAMLreturn0;
3886 static void handleFTPUseEPSV(Connection *conn, value option)
3888 CAMLparam1(option);
3889 CURLcode result = CURLE_OK;
3891 result = curl_easy_setopt(conn->connection,
3892 CURLOPT_FTP_USE_EPSV,
3893 Bool_val(option));
3895 if (result != CURLE_OK)
3896 raiseError(conn, result);
3898 CAMLreturn0;
3901 static void handleDNSCacheTimeout(Connection *conn, value option)
3903 CAMLparam1(option);
3904 CURLcode result = CURLE_OK;
3906 result = curl_easy_setopt(conn->connection,
3907 CURLOPT_DNS_CACHE_TIMEOUT,
3908 Long_val(option));
3910 if (result != CURLE_OK)
3911 raiseError(conn, result);
3913 CAMLreturn0;
3916 static void handleDNSUseGlobalCache(Connection *conn, value option)
3918 CAMLparam1(option);
3919 CURLcode result = CURLE_OK;
3921 result = curl_easy_setopt(conn->connection,
3922 CURLOPT_DNS_USE_GLOBAL_CACHE,
3923 Bool_val(option));
3925 if (result != CURLE_OK)
3926 raiseError(conn, result);
3928 CAMLreturn0;
3931 static void handleDebugFunction(Connection *conn, value option)
3933 CAMLparam1(option);
3934 CURLcode result = CURLE_OK;
3936 if (Tag_val(option) == Closure_tag)
3937 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3938 else
3939 failwith("Not a proper closure");
3941 result = curl_easy_setopt(conn->connection,
3942 CURLOPT_DEBUGFUNCTION,
3943 debugFunction);
3944 if (result != CURLE_OK)
3945 raiseError(conn, result);
3947 result = curl_easy_setopt(conn->connection,
3948 CURLOPT_DEBUGDATA,
3949 conn);
3951 if (result != CURLE_OK)
3952 raiseError(conn, result);
3954 CAMLreturn0;
3957 static void handlePrivate(Connection *conn, value option)
3959 #if HAVE_DECL_CURLOPT_PRIVATE
3960 CAMLparam1(option);
3961 CURLcode result = CURLE_OK;
3963 Store_field(conn->ocamlValues, OcamlPrivate, option);
3965 if (conn->private != NULL)
3966 free(conn->private);
3968 conn->private = strdup(String_val(option));
3970 result = curl_easy_setopt(conn->connection,
3971 CURLOPT_PRIVATE,
3972 conn->private);
3974 if (result != CURLE_OK)
3975 raiseError(conn, result);
3977 CAMLreturn0;
3978 #else
3979 #pragma message("libcurl does not implement CURLOPT_PRIVATE")
3980 failwith("libcurl does not implement CURLOPT_PRIVATE");
3981 #endif
3984 static void handleHTTP200Aliases(Connection *conn, value option)
3986 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3987 CAMLparam1(option);
3988 CAMLlocal1(listIter);
3989 CURLcode result = CURLE_OK;
3991 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3993 free_curl_slist(conn->http200Aliases);
3994 conn->http200Aliases = NULL;
3996 listIter = option;
3998 while (!Is_long(listIter))
4000 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
4002 listIter = Field(listIter, 1);
4005 result = curl_easy_setopt(conn->connection,
4006 CURLOPT_HTTP200ALIASES,
4007 conn->http200Aliases);
4009 if (result != CURLE_OK)
4010 raiseError(conn, result);
4012 CAMLreturn0;
4013 #else
4014 #pragma message("libcurl does not implement CURLOPT_HTTP200ALIASES")
4015 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
4016 #endif
4019 static void handleUnrestrictedAuth(Connection *conn, value option)
4021 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4022 CAMLparam1(option);
4023 CURLcode result = CURLE_OK;
4025 result = curl_easy_setopt(conn->connection,
4026 CURLOPT_UNRESTRICTED_AUTH,
4027 Bool_val(option));
4029 if (result != CURLE_OK)
4030 raiseError(conn, result);
4032 CAMLreturn0;
4033 #else
4034 #pragma message("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH")
4035 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4036 #endif
4039 static void handleFTPUseEPRT(Connection *conn, value option)
4041 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4042 CAMLparam1(option);
4043 CURLcode result = CURLE_OK;
4045 result = curl_easy_setopt(conn->connection,
4046 CURLOPT_FTP_USE_EPRT,
4047 Bool_val(option));
4049 if (result != CURLE_OK)
4050 raiseError(conn, result);
4052 CAMLreturn0;
4053 #else
4054 #pragma message("libcurl does not implement CURLOPT_FTP_USE_EPRT")
4055 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4056 #endif
4059 static void handleHTTPAuth(Connection *conn, value option)
4061 #if HAVE_DECL_CURLOPT_HTTPAUTH
4062 CAMLparam1(option);
4063 CAMLlocal1(listIter);
4064 CURLcode result = CURLE_OK;
4065 long auth = CURLAUTH_NONE;
4067 listIter = option;
4069 while (!Is_long(listIter))
4071 switch (Long_val(Field(listIter, 0)))
4073 case 0: /* CURLAUTH_BASIC */
4074 auth |= CURLAUTH_BASIC;
4075 break;
4077 case 1: /* CURLAUTH_DIGEST */
4078 auth |= CURLAUTH_DIGEST;
4079 break;
4081 case 2: /* CURLAUTH_GSSNEGOTIATE */
4082 auth |= CURLAUTH_GSSNEGOTIATE;
4083 break;
4085 case 3: /* CURLAUTH_NTLM */
4086 auth |= CURLAUTH_NTLM;
4087 break;
4089 case 4: /* CURLAUTH_ANY */
4090 auth |= CURLAUTH_ANY;
4091 break;
4093 case 5: /* CURLAUTH_ANYSAFE */
4094 auth |= CURLAUTH_ANYSAFE;
4095 break;
4097 default:
4098 failwith("Invalid HTTPAUTH Value");
4099 break;
4102 listIter = Field(listIter, 1);
4105 result = curl_easy_setopt(conn->connection,
4106 CURLOPT_HTTPAUTH,
4107 auth);
4109 if (result != CURLE_OK)
4110 raiseError(conn, result);
4112 CAMLreturn0;
4113 #else
4114 #pragma message("libcurl does not implement CURLOPT_HTTPAUTH")
4115 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4116 #endif
4119 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4121 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4122 CAMLparam1(option);
4123 CURLcode result = CURLE_OK;
4125 result = curl_easy_setopt(conn->connection,
4126 CURLOPT_FTP_CREATE_MISSING_DIRS,
4127 Bool_val(option));
4129 if (result != CURLE_OK)
4130 raiseError(conn, result);
4132 CAMLreturn0;
4133 #else
4134 #pragma message("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS")
4135 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4136 #endif
4139 static void handleProxyAuth(Connection *conn, value option)
4141 #if HAVE_DECL_CURLOPT_PROXYAUTH
4142 CAMLparam1(option);
4143 CAMLlocal1(listIter);
4144 CURLcode result = CURLE_OK;
4145 long auth = CURLAUTH_NONE;
4147 listIter = option;
4149 while (!Is_long(listIter))
4151 switch (Long_val(Field(listIter, 0)))
4153 case 0: /* CURLAUTH_BASIC */
4154 auth |= CURLAUTH_BASIC;
4155 break;
4157 case 1: /* CURLAUTH_DIGEST */
4158 auth |= CURLAUTH_DIGEST;
4159 break;
4161 case 2: /* CURLAUTH_GSSNEGOTIATE */
4162 auth |= CURLAUTH_GSSNEGOTIATE;
4163 break;
4165 case 3: /* CURLAUTH_NTLM */
4166 auth |= CURLAUTH_NTLM;
4167 break;
4169 case 4: /* CURLAUTH_ANY */
4170 auth |= CURLAUTH_ANY;
4171 break;
4173 case 5: /* CURLAUTH_ANYSAFE */
4174 auth |= CURLAUTH_ANYSAFE;
4175 break;
4177 default:
4178 failwith("Invalid HTTPAUTH Value");
4179 break;
4182 listIter = Field(listIter, 1);
4185 result = curl_easy_setopt(conn->connection,
4186 CURLOPT_PROXYAUTH,
4187 auth);
4189 if (result != CURLE_OK)
4190 raiseError(conn, result);
4192 CAMLreturn0;
4193 #else
4194 #pragma message("libcurl does not implement CURLOPT_PROXYAUTH")
4195 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4196 #endif
4199 static void handleFTPResponseTimeout(Connection *conn, value option)
4201 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4202 CAMLparam1(option);
4203 CURLcode result = CURLE_OK;
4205 result = curl_easy_setopt(conn->connection,
4206 CURLOPT_FTP_RESPONSE_TIMEOUT,
4207 Long_val(option));
4209 if (result != CURLE_OK)
4210 raiseError(conn, result);
4212 CAMLreturn0;
4213 #else
4214 #pragma message("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT")
4215 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4216 #endif
4219 static void handleIPResolve(Connection *conn, value option)
4221 #if HAVE_DECL_CURLOPT_IPRESOLVE
4222 CAMLparam1(option);
4223 CURLcode result = CURLE_OK;
4225 switch (Long_val(option))
4227 case 0: /* CURL_IPRESOLVE_WHATEVER */
4228 result = curl_easy_setopt(conn->connection,
4229 CURLOPT_IPRESOLVE,
4230 CURL_IPRESOLVE_WHATEVER);
4231 break;
4233 case 1: /* CURL_IPRESOLVE_V4 */
4234 result = curl_easy_setopt(conn->connection,
4235 CURLOPT_IPRESOLVE,
4236 CURL_IPRESOLVE_V4);
4237 break;
4239 case 2: /* CURL_IPRESOLVE_V6 */
4240 result = curl_easy_setopt(conn->connection,
4241 CURLOPT_IPRESOLVE,
4242 CURL_IPRESOLVE_V6);
4243 break;
4245 default:
4246 failwith("Invalid IPRESOLVE Value");
4247 break;
4250 if (result != CURLE_OK)
4251 raiseError(conn, result);
4253 CAMLreturn0;
4254 #else
4255 #pragma message("libcurl does not implement CURLOPT_IPRESOLVE")
4256 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4257 #endif
4260 static void handleMaxFileSize(Connection *conn, value option)
4262 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4263 CAMLparam1(option);
4264 CURLcode result = CURLE_OK;
4266 result = curl_easy_setopt(conn->connection,
4267 CURLOPT_MAXFILESIZE,
4268 Int32_val(option));
4270 if (result != CURLE_OK)
4271 raiseError(conn, result);
4273 CAMLreturn0;
4274 #else
4275 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE")
4276 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4277 #endif
4280 static void handleInFileSizeLarge(Connection *conn, value option)
4282 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4283 CAMLparam1(option);
4284 CURLcode result = CURLE_OK;
4286 result = curl_easy_setopt(conn->connection,
4287 CURLOPT_INFILESIZE_LARGE,
4288 Int64_val(option));
4290 if (result != CURLE_OK)
4291 raiseError(conn, result);
4293 CAMLreturn0;
4294 #else
4295 #pragma message("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4296 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4297 #endif
4300 static void handleResumeFromLarge(Connection *conn, value option)
4302 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4303 CAMLparam1(option);
4304 CURLcode result = CURLE_OK;
4306 result = curl_easy_setopt(conn->connection,
4307 CURLOPT_RESUME_FROM_LARGE,
4308 Int64_val(option));
4310 if (result != CURLE_OK)
4311 raiseError(conn, result);
4313 CAMLreturn0;
4314 #else
4315 #pragma message("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4316 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4317 #endif
4320 static void handleMaxFileSizeLarge(Connection *conn, value option)
4322 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4323 CAMLparam1(option);
4324 CURLcode result = CURLE_OK;
4326 result = curl_easy_setopt(conn->connection,
4327 CURLOPT_MAXFILESIZE_LARGE,
4328 Int64_val(option));
4330 if (result != CURLE_OK)
4331 raiseError(conn, result);
4333 CAMLreturn0;
4334 #else
4335 #pragma message("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE")
4336 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4337 #endif
4340 static void handleNETRCFile(Connection *conn, value option)
4342 #if HAVE_DECL_CURLOPT_NETRC_FILE
4343 CAMLparam1(option);
4344 CURLcode result = CURLE_OK;
4346 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4348 if (conn->netrcFile != NULL)
4349 free(conn->netrcFile);
4351 conn->netrcFile = strdup(String_val(option));
4353 result = curl_easy_setopt(conn->connection,
4354 CURLOPT_NETRC_FILE,
4355 conn->netrcFile);
4357 if (result != CURLE_OK)
4358 raiseError(conn, result);
4360 CAMLreturn0;
4361 #else
4362 #pragma message("libcurl does not implement CURLOPT_NETRC_FILE")
4363 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4364 #endif
4367 static void handleFTPSSL(Connection *conn, value option)
4369 #if HAVE_DECL_CURLOPT_FTP_SSL
4370 CAMLparam1(option);
4371 CURLcode result = CURLE_OK;
4373 switch (Long_val(option))
4375 case 0: /* CURLFTPSSL_NONE */
4376 result = curl_easy_setopt(conn->connection,
4377 CURLOPT_FTP_SSL,
4378 CURLFTPSSL_NONE);
4379 break;
4381 case 1: /* CURLFTPSSL_TRY */
4382 result = curl_easy_setopt(conn->connection,
4383 CURLOPT_FTP_SSL,
4384 CURLFTPSSL_TRY);
4385 break;
4387 case 2: /* CURLFTPSSL_CONTROL */
4388 result = curl_easy_setopt(conn->connection,
4389 CURLOPT_FTP_SSL,
4390 CURLFTPSSL_CONTROL);
4391 break;
4393 case 3: /* CURLFTPSSL_ALL */
4394 result = curl_easy_setopt(conn->connection,
4395 CURLOPT_FTP_SSL,
4396 CURLFTPSSL_ALL);
4397 break;
4399 default:
4400 failwith("Invalid FTP_SSL Value");
4401 break;
4404 if (result != CURLE_OK)
4405 raiseError(conn, result);
4407 CAMLreturn0;
4408 #else
4409 #pragma message("libcurl does not implement CURLOPT_FTP_SSL")
4410 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4411 #endif
4414 static void handlePostFieldSizeLarge(Connection *conn, value option)
4416 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4417 CAMLparam1(option);
4418 CURLcode result = CURLE_OK;
4420 result = curl_easy_setopt(conn->connection,
4421 CURLOPT_POSTFIELDSIZE_LARGE,
4422 Int64_val(option));
4424 if (result != CURLE_OK)
4425 raiseError(conn, result);
4427 CAMLreturn0;
4428 #else
4429 #pragma message("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE")
4430 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4431 #endif
4434 static void handleTCPNoDelay(Connection *conn, value option)
4436 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4437 CAMLparam1(option);
4438 CURLcode result = CURLE_OK;
4440 result = curl_easy_setopt(conn->connection,
4441 CURLOPT_TCP_NODELAY,
4442 Bool_val(option));
4444 if (result != CURLE_OK)
4445 raiseError(conn, result);
4447 CAMLreturn0;
4448 #else
4449 #pragma message("libcurl does not implement CURLOPT_TCP_NODELAY")
4450 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4451 #endif
4454 static void handleFTPSSLAuth(Connection *conn, value option)
4456 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4457 CAMLparam1(option);
4458 CURLcode result = CURLE_OK;
4460 switch (Long_val(option))
4462 case 0: /* CURLFTPAUTH_DEFAULT */
4463 result = curl_easy_setopt(conn->connection,
4464 CURLOPT_FTPSSLAUTH,
4465 CURLFTPAUTH_DEFAULT);
4466 break;
4468 case 1: /* CURLFTPAUTH_SSL */
4469 result = curl_easy_setopt(conn->connection,
4470 CURLOPT_FTPSSLAUTH,
4471 CURLFTPAUTH_SSL);
4472 break;
4474 case 2: /* CURLFTPAUTH_TLS */
4475 result = curl_easy_setopt(conn->connection,
4476 CURLOPT_FTPSSLAUTH,
4477 CURLFTPAUTH_TLS);
4478 break;
4480 default:
4481 failwith("Invalid FTPSSLAUTH value");
4482 break;
4485 if (result != CURLE_OK)
4486 raiseError(conn, result);
4488 CAMLreturn0;
4489 #else
4490 #pragma message("libcurl does not implement CURLOPT_FTPSSLAUTH")
4491 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4492 #endif
4495 static void handleIOCTLFunction(Connection *conn, value option)
4497 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4498 CAMLparam1(option);
4499 CURLcode result = CURLE_OK;
4501 if (Tag_val(option) == Closure_tag)
4502 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4503 else
4504 failwith("Not a proper closure");
4506 result = curl_easy_setopt(conn->connection,
4507 CURLOPT_IOCTLFUNCTION,
4508 ioctlFunction);
4509 if (result != CURLE_OK)
4510 raiseError(conn, result);
4512 result = curl_easy_setopt(conn->connection,
4513 CURLOPT_DEBUGDATA,
4514 conn);
4516 if (result != CURLE_OK)
4517 raiseError(conn, result);
4519 CAMLreturn0;
4520 #else
4521 #pragma message("libcurl does not implement CURLOPT_IOCTLFUNCTION")
4522 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4523 #endif
4526 static void handleFTPAccount(Connection *conn, value option)
4528 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4529 CAMLparam1(option);
4530 CURLcode result = CURLE_OK;
4532 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4534 if (conn->ftpaccount != NULL)
4535 free(conn->ftpaccount);
4537 conn->ftpaccount = strdup(String_val(option));
4539 result = curl_easy_setopt(conn->connection,
4540 CURLOPT_FTP_ACCOUNT,
4541 conn->ftpaccount);
4543 if (result != CURLE_OK)
4544 raiseError(conn, result);
4546 CAMLreturn0;
4547 #else
4548 #pragma message("libcurl does not implement CURLOPT_FTP_ACCOUNT")
4549 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4550 #endif
4553 static void handleCookieList(Connection *conn, value option)
4555 #if HAVE_DECL_CURLOPT_COOKIELIST
4556 CAMLparam1(option);
4557 CURLcode result = CURLE_OK;
4559 Store_field(conn->ocamlValues, OcamlCookieList, option);
4561 if (conn->cookielist != NULL)
4562 free(conn->cookielist);
4564 conn->cookielist = strdup(String_val(option));
4566 result = curl_easy_setopt(conn->connection,
4567 CURLOPT_COOKIELIST,
4568 conn->cookielist);
4570 if (result != CURLE_OK)
4571 raiseError(conn, result);
4573 CAMLreturn0;
4574 #else
4575 #pragma message("libcurl does not implement CURLOPT_COOKIELIST")
4576 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4577 #endif
4580 static void handleIgnoreContentLength(Connection *conn, value option)
4582 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4583 CAMLparam1(option);
4584 CURLcode result = CURLE_OK;
4586 result = curl_easy_setopt(conn->connection,
4587 CURLOPT_IGNORE_CONTENT_LENGTH,
4588 Bool_val(option));
4590 if (result != CURLE_OK)
4591 raiseError(conn, result);
4593 CAMLreturn0;
4594 #else
4595 #pragma message("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH")
4596 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4597 #endif
4600 static void handleFTPSkipPASVIP(Connection *conn, value option)
4602 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4603 CAMLparam1(option);
4604 CURLcode result = CURLE_OK;
4606 result = curl_easy_setopt(conn->connection,
4607 CURLOPT_FTP_SKIP_PASV_IP,
4608 Bool_val(option));
4610 if (result != CURLE_OK)
4611 raiseError(conn, result);
4613 CAMLreturn0;
4614 #else
4615 #pragma message("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP")
4616 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4617 #endif
4620 static void handleFTPFileMethod(Connection *conn, value option)
4622 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4623 CAMLparam1(option);
4624 CURLcode result = CURLE_OK;
4626 switch (Long_val(option))
4628 case 0: /* CURLFTPMETHOD_DEFAULT */
4629 result = curl_easy_setopt(conn->connection,
4630 CURLOPT_FTP_FILEMETHOD,
4631 CURLFTPMETHOD_DEFAULT);
4632 break;
4634 case 1: /* CURLFTMETHOD_MULTICWD */
4635 result = curl_easy_setopt(conn->connection,
4636 CURLOPT_FTP_FILEMETHOD,
4637 CURLFTPMETHOD_MULTICWD);
4638 break;
4640 case 2: /* CURLFTPMETHOD_NOCWD */
4641 result = curl_easy_setopt(conn->connection,
4642 CURLOPT_FTP_FILEMETHOD,
4643 CURLFTPMETHOD_NOCWD);
4644 break;
4646 case 3: /* CURLFTPMETHOD_SINGLECWD */
4647 result = curl_easy_setopt(conn->connection,
4648 CURLOPT_FTP_FILEMETHOD,
4649 CURLFTPMETHOD_SINGLECWD);
4651 default:
4652 failwith("Invalid FTP_FILEMETHOD value");
4653 break;
4656 if (result != CURLE_OK)
4657 raiseError(conn, result);
4659 CAMLreturn0;
4660 #else
4661 #pragma message("libcurl does not implement CURLOPT_FTP_FILEMETHOD")
4662 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4663 #endif
4666 static void handleLocalPort(Connection *conn, value option)
4668 #if HAVE_DECL_CURLOPT_LOCALPORT
4669 CAMLparam1(option);
4670 CURLcode result = CURLE_OK;
4672 result = curl_easy_setopt(conn->connection,
4673 CURLOPT_LOCALPORT,
4674 Long_val(option));
4676 if (result != CURLE_OK)
4677 raiseError(conn, result);
4679 CAMLreturn0;
4680 #else
4681 #pragma message("libcurl does not implement CURLOPT_LOCALPORT")
4682 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4683 #endif
4686 static void handleLocalPortRange(Connection *conn, value option)
4688 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4689 CAMLparam1(option);
4690 CURLcode result = CURLE_OK;
4692 result = curl_easy_setopt(conn->connection,
4693 CURLOPT_LOCALPORTRANGE,
4694 Long_val(option));
4696 if (result != CURLE_OK)
4697 raiseError(conn, result);
4699 CAMLreturn0;
4700 #else
4701 #pragma message("libcurl does not implement CURLOPT_LOCALPORTRANGE")
4702 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4703 #endif
4706 static void handleConnectOnly(Connection *conn, value option)
4708 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4709 CAMLparam1(option);
4710 CURLcode result = CURLE_OK;
4712 result = curl_easy_setopt(conn->connection,
4713 CURLOPT_CONNECT_ONLY,
4714 Bool_val(option));
4716 if (result != CURLE_OK)
4717 raiseError(conn, result);
4719 CAMLreturn0;
4720 #else
4721 #pragma message("libcurl does not implement CURLOPT_CONNECT_ONLY")
4722 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4723 #endif
4726 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4728 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4729 CAMLparam1(option);
4730 CURLcode result = CURLE_OK;
4732 result = curl_easy_setopt(conn->connection,
4733 CURLOPT_MAX_SEND_SPEED_LARGE,
4734 Int64_val(option));
4736 if (result != CURLE_OK)
4737 raiseError(conn, result);
4739 CAMLreturn0;
4740 #else
4741 #pragma message("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE")
4742 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4743 #endif
4746 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4748 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4749 CAMLparam1(option);
4750 CURLcode result = CURLE_OK;
4752 result = curl_easy_setopt(conn->connection,
4753 CURLOPT_MAX_RECV_SPEED_LARGE,
4754 Int64_val(option));
4756 if (result != CURLE_OK)
4757 raiseError(conn, result);
4759 CAMLreturn0;
4760 #else
4761 #pragma message("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE")
4762 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4763 #endif
4766 static void handleFTPAlternativeToUser(Connection *conn, value option)
4768 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4769 CAMLparam1(option);
4770 CURLcode result = CURLE_OK;
4772 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4774 if (conn->ftpAlternativeToUser != NULL)
4775 free(conn->ftpAlternativeToUser);
4777 conn->ftpAlternativeToUser = strdup(String_val(option));
4779 result = curl_easy_setopt(conn->connection,
4780 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4781 conn->ftpAlternativeToUser);
4783 if (result != CURLE_OK)
4784 raiseError(conn, result);
4786 CAMLreturn0;
4787 #else
4788 #pragma message("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER")
4789 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4790 #endif
4793 static void handleSSLSessionIdCache(Connection *conn, value option)
4795 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4796 CAMLparam1(option);
4797 CURLcode result = CURLE_OK;
4799 result = curl_easy_setopt(conn->connection,
4800 CURLOPT_SSL_SESSIONID_CACHE,
4801 Bool_val(option));
4803 if (result != CURLE_OK)
4804 raiseError(conn, result);
4806 CAMLreturn0;
4807 #else
4808 #pragma message("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE")
4809 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4810 #endif
4813 static void handleSSHAuthTypes(Connection *conn, value option)
4815 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4816 CAMLparam1(option);
4817 CAMLlocal1(listIter);
4818 CURLcode result = CURLE_OK;
4819 long authTypes = CURLSSH_AUTH_NONE;
4821 listIter = option;
4823 while (!Is_long(listIter))
4825 switch (Long_val(Field(listIter, 0)))
4827 case 0: /* CURLSSH_AUTH_ANY */
4828 authTypes |= CURLSSH_AUTH_ANY;
4829 break;
4831 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4832 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4833 break;
4835 case 2: /* CURLSSH_AUTH_PASSWORD */
4836 authTypes |= CURLSSH_AUTH_PASSWORD;
4837 break;
4839 case 3: /* CURLSSH_AUTH_HOST */
4840 authTypes |= CURLSSH_AUTH_HOST;
4841 break;
4843 case 4: /* CURLSSH_AUTH_KEYBOARD */
4844 authTypes |= CURLSSH_AUTH_KEYBOARD;
4845 break;
4847 default:
4848 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4849 break;
4852 listIter = Field(listIter, 1);
4855 result = curl_easy_setopt(conn->connection,
4856 CURLOPT_SSH_AUTH_TYPES,
4857 authTypes);
4859 if (result != CURLE_OK)
4860 raiseError(conn, result);
4862 CAMLreturn0;
4863 #else
4864 #pragma message("libcurl does not implement CURLOPT_SSH_AUTH_TYPES")
4865 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4866 #endif
4869 static void handleSSHPublicKeyFile(Connection *conn, value option)
4871 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4872 CAMLparam1(option);
4873 CURLcode result = CURLE_OK;
4875 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4877 if (conn->sshPublicKeyFile != NULL)
4878 free(conn->sshPublicKeyFile);
4880 conn->sshPublicKeyFile = strdup(String_val(option));
4882 result = curl_easy_setopt(conn->connection,
4883 CURLOPT_SSH_PUBLIC_KEYFILE,
4884 conn->sshPublicKeyFile);
4886 if (result != CURLE_OK)
4887 raiseError(conn, result);
4889 CAMLreturn0;
4890 #else
4891 #pragma message("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE")
4892 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4893 #endif
4896 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4898 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4899 CAMLparam1(option);
4900 CURLcode result = CURLE_OK;
4902 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4904 if (conn->sshPrivateKeyFile != NULL)
4905 free(conn->sshPrivateKeyFile);
4907 conn->sshPrivateKeyFile = strdup(String_val(option));
4909 result = curl_easy_setopt(conn->connection,
4910 CURLOPT_SSH_PRIVATE_KEYFILE,
4911 conn->sshPrivateKeyFile);
4913 if (result != CURLE_OK)
4914 raiseError(conn, result);
4916 CAMLreturn0;
4917 #else
4918 #pragma message("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE")
4919 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4920 #endif
4923 static void handleFTPSSLCCC(Connection *conn, value option)
4925 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4926 CAMLparam1(option);
4927 CURLcode result = CURLE_OK;
4929 switch (Long_val(option))
4931 case 0: /* CURLFTPSSL_CCC_NONE */
4932 result = curl_easy_setopt(conn->connection,
4933 CURLOPT_FTP_SSL_CCC,
4934 CURLFTPSSL_CCC_NONE);
4935 break;
4937 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4938 result = curl_easy_setopt(conn->connection,
4939 CURLOPT_FTP_SSL_CCC,
4940 CURLFTPSSL_CCC_PASSIVE);
4941 break;
4943 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4944 result = curl_easy_setopt(conn->connection,
4945 CURLOPT_FTP_SSL_CCC,
4946 CURLFTPSSL_CCC_ACTIVE);
4947 break;
4949 default:
4950 failwith("Invalid FTPSSL_CCC value");
4951 break;
4954 if (result != CURLE_OK)
4955 raiseError(conn, result);
4957 CAMLreturn0;
4958 #else
4959 #pragma message("libcurl does not implement CURLOPT_FTP_SSL_CCC")
4960 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4961 #endif
4964 static void handleTimeoutMS(Connection *conn, value option)
4966 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4967 CAMLparam1(option);
4968 CURLcode result = CURLE_OK;
4970 result = curl_easy_setopt(conn->connection,
4971 CURLOPT_TIMEOUT_MS,
4972 Long_val(option));
4974 if (result != CURLE_OK)
4975 raiseError(conn, result);
4977 CAMLreturn0;
4978 #else
4979 #pragma message("libcurl does not implement CURLOPT_TIMEOUT_MS")
4980 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4981 #endif
4984 static void handleConnectTimeoutMS(Connection *conn, value option)
4986 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4987 CAMLparam1(option);
4988 CURLcode result = CURLE_OK;
4990 result = curl_easy_setopt(conn->connection,
4991 CURLOPT_CONNECTTIMEOUT_MS,
4992 Long_val(option));
4994 if (result != CURLE_OK)
4995 raiseError(conn, result);
4997 CAMLreturn0;
4998 #else
4999 #pragma message("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS")
5000 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
5001 #endif
5004 static void handleHTTPTransferDecoding(Connection *conn, value option)
5006 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
5007 CAMLparam1(option);
5008 CURLcode result = CURLE_OK;
5010 result = curl_easy_setopt(conn->connection,
5011 CURLOPT_HTTP_TRANSFER_DECODING,
5012 Bool_val(option));
5014 if (result != CURLE_OK)
5015 raiseError(conn, result);
5017 CAMLreturn0;
5018 #else
5019 #pragma message("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING")
5020 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
5021 #endif
5024 static void handleHTTPContentDecoding(Connection *conn, value option)
5026 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5027 CAMLparam1(option);
5028 CURLcode result = CURLE_OK;
5030 result = curl_easy_setopt(conn->connection,
5031 CURLOPT_HTTP_CONTENT_DECODING,
5032 Bool_val(option));
5034 if (result != CURLE_OK)
5035 raiseError(conn, result);
5037 CAMLreturn0;
5038 #else
5039 #pragma message("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING")
5040 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5041 #endif
5044 static void handleNewFilePerms(Connection *conn, value option)
5046 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5047 CAMLparam1(option);
5048 CURLcode result = CURLE_OK;
5050 result = curl_easy_setopt(conn->connection,
5051 CURLOPT_NEW_FILE_PERMS,
5052 Long_val(option));
5054 if (result != CURLE_OK)
5055 raiseError(conn, result);
5057 CAMLreturn0;
5058 #else
5059 #pragma message("libcurl does not implement CURLOPT_NEW_FILE_PERMS")
5060 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5061 #endif
5064 static void handleNewDirectoryPerms(Connection *conn, value option)
5066 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5067 CAMLparam1(option);
5068 CURLcode result = CURLE_OK;
5070 result = curl_easy_setopt(conn->connection,
5071 CURLOPT_NEW_DIRECTORY_PERMS,
5072 Long_val(option));
5074 if (result != CURLE_OK)
5075 raiseError(conn, result);
5077 CAMLreturn0;
5078 #else
5079 #pragma message("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS")
5080 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5081 #endif
5084 static void handlePost301(Connection *conn, value option)
5086 #if HAVE_DECL_CURLOPT_POST301
5087 CAMLparam1(option);
5088 CURLcode result = CURLE_OK;
5090 result = curl_easy_setopt(conn->connection,
5091 CURLOPT_POST301,
5092 Bool_val(option));
5094 if (result != CURLE_OK)
5095 raiseError(conn, result);
5097 CAMLreturn0;
5098 #else
5099 #pragma message("libcurl does not implement CURLOPT_POST301")
5100 failwith("libcurl does not implement CURLOPT_POST301");
5101 #endif
5104 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5106 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5107 CAMLparam1(option);
5108 CURLcode result = CURLE_OK;
5110 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5112 if (conn->sshHostPublicKeyMD5 != NULL)
5113 free(conn->sshHostPublicKeyMD5);
5115 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5117 result = curl_easy_setopt(conn->connection,
5118 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5119 conn->sshHostPublicKeyMD5);
5121 if (result != CURLE_OK)
5122 raiseError(conn, result);
5124 CAMLreturn0;
5125 #else
5126 #pragma message("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5")
5127 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5128 #endif
5131 static void handleCopyPostFields(Connection *conn, value option)
5133 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5134 CAMLparam1(option);
5135 CURLcode result = CURLE_OK;
5137 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5139 if (conn->copyPostFields != NULL)
5140 free(conn->copyPostFields);
5142 conn->copyPostFields = strdup(String_val(option));
5144 result = curl_easy_setopt(conn->connection,
5145 CURLOPT_COPYPOSTFIELDS,
5146 conn->copyPostFields);
5148 if (result != CURLE_OK)
5149 raiseError(conn, result);
5151 CAMLreturn0;
5152 #else
5153 #pragma message("libcurl does not implement CURLOPT_COPYPOSTFIELDS")
5154 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5155 #endif
5158 static void handleProxyTransferMode(Connection *conn, value option)
5160 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5161 CAMLparam1(option);
5162 CURLcode result = CURLE_OK;
5164 result = curl_easy_setopt(conn->connection,
5165 CURLOPT_PROXY_TRANSFER_MODE,
5166 Bool_val(option));
5168 if (result != CURLE_OK)
5169 raiseError(conn, result);
5171 CAMLreturn0;
5172 #else
5173 #pragma message("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE")
5174 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5175 #endif
5178 static void handleSeekFunction(Connection *conn, value option)
5180 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5181 CAMLparam1(option);
5182 CURLcode result = CURLE_OK;
5184 if (Tag_val(option) == Closure_tag)
5185 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5186 else
5187 failwith("Not a proper closure");
5189 result = curl_easy_setopt(conn->connection,
5190 CURLOPT_SEEKFUNCTION,
5191 seekFunction);
5193 if (result != CURLE_OK)
5194 raiseError(conn, result);
5196 result = curl_easy_setopt(conn->connection,
5197 CURLOPT_SEEKDATA,
5198 conn);
5200 if (result != CURLE_OK)
5201 raiseError(conn, result);
5203 CAMLreturn0;
5204 #else
5205 #pragma message("libcurl does not implement CURLOPT_SEEKFUNCTION")
5206 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5207 #endif
5210 static void handleAutoReferer(Connection *conn, value option)
5212 #if HAVE_DECL_CURLOPT_AUTOREFERER
5213 CAMLparam1(option);
5214 CURLcode result = curl_easy_setopt(conn->connection,
5215 CURLOPT_AUTOREFERER,
5216 Bool_val(option));
5218 if (result != CURLE_OK)
5219 raiseError(conn, result);
5221 CAMLreturn0;
5222 #else
5223 #pragma message("libcurl does not implement CURLOPT_AUTOREFERER")
5224 failwith("libcurl does not implement CURLOPT_AUTOREFERER");
5225 #endif
5228 static void handleOpenSocketFunction(Connection *conn, value option)
5230 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5231 CAMLparam1(option);
5232 CURLcode result = CURLE_OK;
5234 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5236 result = curl_easy_setopt(conn->connection,
5237 CURLOPT_OPENSOCKETDATA,
5238 conn);
5240 if (result != CURLE_OK)
5241 raiseError(conn, result);
5243 result = curl_easy_setopt(conn->connection,
5244 CURLOPT_OPENSOCKETFUNCTION,
5245 openSocketFunction);
5247 if (result != CURLE_OK)
5248 raiseError(conn, result);
5250 CAMLreturn0;
5251 #else
5252 #pragma message("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION")
5253 failwith("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION");
5254 #endif
5257 static void handleProxyType(Connection *conn, value option)
5259 #if HAVE_DECL_CURLOPT_PROXYTYPE
5260 CAMLparam1(option);
5261 CURLcode result = CURLE_OK;
5262 long proxy_type;
5264 switch (Long_val(option))
5266 case 0: proxy_type = CURLPROXY_HTTP; break;
5267 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5268 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5269 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5270 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5271 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5272 default:
5273 failwith("Invalid curl proxy type");
5276 result = curl_easy_setopt(conn->connection,
5277 CURLOPT_PROXYTYPE,
5278 proxy_type);
5280 if (result != CURLE_OK)
5281 raiseError(conn, result);
5283 CAMLreturn0;
5284 #else
5285 #pragma message("libcurl does not implement CURLOPT_PROXYTYPE")
5286 failwith("libcurl does not implement CURLOPT_PROXYTYPE");
5287 #endif
5290 #if HAVE_DECL_CURLOPT_PROTOCOLS && HAVE_DECL_CURLOPT_REDIR_PROTOCOLS
5292 long protoMap[] =
5294 CURLPROTO_ALL,
5295 CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP,
5296 CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP,
5297 /* factor out with autoconf? */
5298 #if defined(CURLPROTO_IMAP)
5299 CURLPROTO_IMAP,
5300 #else
5302 #endif
5303 #if defined(CURLPROTO_IMAPS)
5304 CURLPROTO_IMAPS,
5305 #else
5307 #endif
5308 #if defined(CURLPROTO_POP3)
5309 CURLPROTO_POP3,
5310 #else
5312 #endif
5313 #if defined(CURLPROTO_POP3S)
5314 CURLPROTO_POP3S,
5315 #else
5317 #endif
5318 #if defined(CURLPROTO_SMTP)
5319 CURLPROTO_SMTP,
5320 #else
5322 #endif
5323 #if defined(CURLPROTO_SMTPS)
5324 CURLPROTO_SMTPS,
5325 #else
5327 #endif
5328 #if defined(CURLPROTO_RTSP)
5329 CURLPROTO_RTSP,
5330 #else
5332 #endif
5333 #if defined(CURLPROTO_RTMP)
5334 CURLPROTO_RTMP,
5335 #else
5337 #endif
5338 #if defined(CURLPROTO_RTMPT)
5339 CURLPROTO_RTMPT,
5340 #else
5342 #endif
5343 #if defined(CURLPROTO_RTMPE)
5344 CURLPROTO_RTMPE,
5345 #else
5347 #endif
5348 #if defined(CURLPROTO_RTMPTE)
5349 CURLPROTO_RTMPTE,
5350 #else
5352 #endif
5353 #if defined(CURLPROTO_RTMPS)
5354 CURLPROTO_RTMPS,
5355 #else
5357 #endif
5358 #if defined(CURLPROTO_RTMPTS)
5359 CURLPROTO_RTMPTS,
5360 #else
5362 #endif
5363 #if defined(CURLPROTO_GOPHER)
5364 CURLPROTO_GOPHER,
5365 #else
5367 #endif
5370 static void handleProtocolsOption(CURLoption curlopt, Connection *conn, value option)
5372 CAMLparam1(option);
5373 CURLcode result = CURLE_OK;
5374 long protocols = 0;
5375 int index;
5377 while (Val_emptylist != option)
5379 index = Int_val(Field(option, 0));
5380 if ((index < 0) || ((size_t)index >= sizeof(protoMap) / sizeof(protoMap[0])))
5381 failwith("Invalid curl protocol");
5383 protocols = protocols | protoMap[index];
5385 option = Field(option, 1);
5388 result = curl_easy_setopt(conn->connection,
5389 curlopt,
5390 protocols);
5392 if (result != CURLE_OK)
5393 raiseError(conn, result);
5395 CAMLreturn0;
5398 static void handleProtocols(Connection *conn, value option)
5400 handleProtocolsOption(CURLOPT_PROTOCOLS, conn, option);
5403 static void handleRedirProtocols(Connection *conn, value option)
5405 handleProtocolsOption(CURLOPT_REDIR_PROTOCOLS, conn, option);
5408 #else
5409 #pragma message("libcurl does not implement CURLOPT_PROTOCOLS or CURLOPT_REDIR_PROTOCOLS")
5410 static void handleProtocols(Connection *conn, value option)
5412 failwith("libcurl does not implement CURLOPT_PROTOCOLS");
5414 static void handleRedirProtocols(Connection *conn, value option)
5416 failwith("libcurl does not implement CURLOPT_REDIR_PROTOCOLS");
5418 #endif
5420 #if HAVE_DECL_CURLOPT_RESOLVE
5421 static void handleResolve(Connection *conn, value option)
5423 CAMLparam1(option);
5424 CAMLlocal1(head);
5426 CURLcode result = CURLE_OK;
5428 free_curl_slist(conn->resolve);
5429 conn->resolve = NULL;
5431 head = option;
5433 while (head != Val_emptylist)
5435 conn->resolve = curl_slist_append(conn->resolve, String_val(Field(head,0)));
5436 head = Field(head, 1);
5439 result = curl_easy_setopt(conn->connection,
5440 CURLOPT_RESOLVE,
5441 conn->resolve);
5443 if (result != CURLE_OK)
5444 raiseError(conn, result);
5446 CAMLreturn0;
5449 #else
5450 #pragma message("libcurl does not implement CURLOPT_RESOLVE")
5451 static void handleResolve(Connection *conn, value option)
5453 failwith("libcurl does not implement CURLOPT_RESOLVE");
5455 #endif
5457 #if HAVE_DECL_CURLOPT_DNS_SERVERS
5458 static void handleDnsServers(Connection *conn, value option)
5460 CAMLparam1(option);
5462 CURLcode result = CURLE_OK;
5463 free_if(conn->dns_servers);
5465 conn->dns_servers = strdup(String_val(option));
5467 result = curl_easy_setopt(conn->connection,
5468 CURLOPT_DNS_SERVERS,
5469 conn->dns_servers);
5471 if (result != CURLE_OK)
5472 raiseError(conn, result);
5474 CAMLreturn0;
5476 #else
5477 #pragma message("libcurl does not implement CURLOPT_DNS_SERVERS")
5478 static void handleDnsServers(Connection *conn, value option)
5480 failwith("libcurl does not implement CURLOPT_DNS_SERVERS");
5482 #endif
5485 ** curl_easy_setopt helper function
5488 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5490 CAMLparam2(conn, option);
5491 CAMLlocal1(data);
5492 Connection *connection = Connection_val(conn);
5494 checkConnection(connection);
5496 if (Is_long(option))
5498 char error[128];
5500 sprintf(error, "Unimplemented Option: %s",
5501 findOption(unimplementedOptionMap,
5502 (CURLoption)(Long_val(option))));
5504 failwith(error);
5507 if (!Is_block(option))
5508 failwith("Not a block");
5510 if (Wosize_val(option) < 1)
5511 failwith("Insufficient data in block");
5513 data = Field(option, 0);
5515 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5516 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5517 data);
5518 else
5519 failwith("Invalid CURLOPT Option");
5521 CAMLreturn(Val_unit);
5525 ** curl_easy_perform helper function
5528 CAMLprim value helper_curl_easy_perform(value conn)
5530 CAMLparam1(conn);
5531 CURLcode result = CURLE_OK;
5532 Connection *connection = Connection_val(conn);
5534 checkConnection(connection);
5536 enter_blocking_section();
5537 result = curl_easy_perform(connection->connection);
5538 leave_blocking_section();
5540 if (result != CURLE_OK)
5541 raiseError(connection, result);
5543 CAMLreturn(Val_unit);
5547 ** curl_easy_cleanup helper function
5550 CAMLprim value helper_curl_easy_cleanup(value conn)
5552 CAMLparam1(conn);
5553 Connection *connection = Connection_val(conn);
5555 checkConnection(connection);
5557 removeConnection(connection);
5559 CAMLreturn(Val_unit);
5563 ** curl_easy_duphandle helper function
5566 CAMLprim value helper_curl_easy_duphandle(value conn)
5568 CAMLparam1(conn);
5569 CAMLlocal1(result);
5570 Connection *connection = Connection_val(conn);
5572 checkConnection(connection);
5574 result = caml_alloc(1, Abstract_tag);
5575 Field(result, 0) = (value)duplicateConnection(connection);
5577 CAMLreturn(result);
5581 ** curl_easy_getinfo helper function
5584 enum GetInfoResultType {
5585 StringValue, LongValue, DoubleValue, StringListValue
5588 value convertStringList(struct curl_slist *slist)
5590 CAMLparam0();
5591 CAMLlocal3(result, current, next);
5592 struct curl_slist *p = slist;
5594 result = Val_int(0);
5595 current = Val_int(0);
5596 next = Val_int(0);
5598 while (p != NULL)
5600 next = alloc_tuple(2);
5601 Store_field(next, 0, copy_string(p->data));
5602 Store_field(next, 1, Val_int(0));
5604 if (result == Val_int(0))
5605 result = next;
5607 if (current != Val_int(0))
5608 Store_field(current, 1, next);
5610 current = next;
5612 p = p->next;
5615 curl_slist_free_all(slist);
5617 CAMLreturn(result);
5620 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5622 CAMLparam2(conn, option);
5623 CAMLlocal1(result);
5624 CURLcode curlResult;
5625 Connection *connection = Connection_val(conn);
5626 enum GetInfoResultType resultType;
5627 char *strValue = NULL;
5628 double doubleValue;
5629 long longValue;
5630 struct curl_slist *stringListValue = NULL;
5632 checkConnection(connection);
5634 switch(Long_val(option))
5636 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5637 case 0: /* CURLINFO_EFFECTIVE_URL */
5638 resultType = StringValue;
5640 curlResult = curl_easy_getinfo(connection->connection,
5641 CURLINFO_EFFECTIVE_URL,
5642 &strValue);
5643 break;
5644 #else
5645 #pragma message("libcurl does not provide CURLINFO_EFFECTIVE_URL")
5646 #endif
5648 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5649 case 1: /* CURLINFO_HTTP_CODE */
5650 case 2: /* CURLINFO_RESPONSE_CODE */
5651 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5652 resultType = LongValue;
5654 curlResult = curl_easy_getinfo(connection->connection,
5655 CURLINFO_RESPONSE_CODE,
5656 &longValue);
5657 #else
5658 resultType = LongValue;
5660 curlResult = curl_easy_getinfo(connection->connection,
5661 CURLINFO_HTTP_CODE,
5662 &longValue);
5663 #endif
5664 break;
5665 #endif
5667 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5668 case 3: /* CURLINFO_TOTAL_TIME */
5669 resultType = DoubleValue;
5671 curlResult = curl_easy_getinfo(connection->connection,
5672 CURLINFO_TOTAL_TIME,
5673 &doubleValue);
5674 break;
5675 #endif
5677 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5678 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5679 resultType = DoubleValue;
5681 curlResult = curl_easy_getinfo(connection->connection,
5682 CURLINFO_NAMELOOKUP_TIME,
5683 &doubleValue);
5684 break;
5685 #endif
5687 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5688 case 5: /* CURLINFO_CONNECT_TIME */
5689 resultType = DoubleValue;
5691 curlResult = curl_easy_getinfo(connection->connection,
5692 CURLINFO_CONNECT_TIME,
5693 &doubleValue);
5694 break;
5695 #endif
5697 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5698 case 6: /* CURLINFO_PRETRANSFER_TIME */
5699 resultType = DoubleValue;
5701 curlResult = curl_easy_getinfo(connection->connection,
5702 CURLINFO_PRETRANSFER_TIME,
5703 &doubleValue);
5704 break;
5705 #endif
5707 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5708 case 7: /* CURLINFO_SIZE_UPLOAD */
5709 resultType = DoubleValue;
5711 curlResult = curl_easy_getinfo(connection->connection,
5712 CURLINFO_SIZE_UPLOAD,
5713 &doubleValue);
5714 break;
5715 #endif
5717 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5718 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5719 resultType = DoubleValue;
5721 curlResult = curl_easy_getinfo(connection->connection,
5722 CURLINFO_SIZE_DOWNLOAD,
5723 &doubleValue);
5724 break;
5725 #endif
5727 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5728 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5729 resultType = DoubleValue;
5731 curlResult = curl_easy_getinfo(connection->connection,
5732 CURLINFO_SPEED_DOWNLOAD,
5733 &doubleValue);
5734 break;
5735 #endif
5737 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5738 case 10: /* CURLINFO_SPEED_UPLOAD */
5739 resultType = DoubleValue;
5741 curlResult = curl_easy_getinfo(connection->connection,
5742 CURLINFO_SPEED_UPLOAD,
5743 &doubleValue);
5744 break;
5746 #endif
5748 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5749 case 11: /* CURLINFO_HEADER_SIZE */
5750 resultType = LongValue;
5752 curlResult = curl_easy_getinfo(connection->connection,
5753 CURLINFO_HEADER_SIZE,
5754 &longValue);
5755 break;
5756 #endif
5758 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5759 case 12: /* CURLINFO_REQUEST_SIZE */
5760 resultType = LongValue;
5762 curlResult = curl_easy_getinfo(connection->connection,
5763 CURLINFO_REQUEST_SIZE,
5764 &longValue);
5765 break;
5766 #endif
5768 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5769 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5770 resultType = LongValue;
5772 curlResult = curl_easy_getinfo(connection->connection,
5773 CURLINFO_SSL_VERIFYRESULT,
5774 &longValue);
5775 break;
5776 #endif
5778 #if HAVE_DECL_CURLINFO_FILETIME
5779 case 14: /* CURLINFO_FILETIME */
5780 resultType = DoubleValue;
5782 curlResult = curl_easy_getinfo(connection->connection,
5783 CURLINFO_FILETIME,
5784 &longValue);
5786 doubleValue = longValue;
5787 break;
5788 #endif
5790 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5791 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5792 resultType = DoubleValue;
5794 curlResult = curl_easy_getinfo(connection->connection,
5795 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5796 &doubleValue);
5797 break;
5798 #endif
5800 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5801 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5802 resultType = DoubleValue;
5804 curlResult = curl_easy_getinfo(connection->connection,
5805 CURLINFO_CONTENT_LENGTH_UPLOAD,
5806 &doubleValue);
5807 break;
5808 #endif
5810 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5811 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5812 resultType = DoubleValue;
5814 curlResult = curl_easy_getinfo(connection->connection,
5815 CURLINFO_STARTTRANSFER_TIME,
5816 &doubleValue);
5817 break;
5818 #endif
5820 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5821 case 18: /* CURLINFO_CONTENT_TYPE */
5822 resultType = StringValue;
5824 curlResult = curl_easy_getinfo(connection->connection,
5825 CURLINFO_CONTENT_TYPE,
5826 &strValue);
5827 break;
5828 #endif
5830 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5831 case 19: /* CURLINFO_REDIRECT_TIME */
5832 resultType = DoubleValue;
5834 curlResult = curl_easy_getinfo(connection->connection,
5835 CURLINFO_REDIRECT_TIME,
5836 &doubleValue);
5837 break;
5838 #endif
5840 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5841 case 20: /* CURLINFO_REDIRECT_COUNT */
5842 resultType = LongValue;
5844 curlResult = curl_easy_getinfo(connection->connection,
5845 CURLINFO_REDIRECT_COUNT,
5846 &longValue);
5847 break;
5848 #endif
5850 #if HAVE_DECL_CURLINFO_PRIVATE
5851 case 21: /* CURLINFO_PRIVATE */
5852 resultType = StringValue;
5854 curlResult = curl_easy_getinfo(connection->connection,
5855 CURLINFO_PRIVATE,
5856 &strValue);
5857 break;
5858 #endif
5860 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5861 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5862 resultType = LongValue;
5864 curlResult = curl_easy_getinfo(connection->connection,
5865 CURLINFO_HTTP_CONNECTCODE,
5866 &longValue);
5867 break;
5868 #endif
5870 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5871 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5872 resultType = LongValue;
5874 curlResult = curl_easy_getinfo(connection->connection,
5875 CURLINFO_HTTPAUTH_AVAIL,
5876 &longValue);
5877 break;
5878 #endif
5880 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5881 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5882 resultType = LongValue;
5884 curlResult = curl_easy_getinfo(connection->connection,
5885 CURLINFO_PROXYAUTH_AVAIL,
5886 &longValue);
5887 break;
5888 #endif
5890 #if HAVE_DECL_CURLINFO_OS_ERRNO
5891 case 25: /* CURLINFO_OS_ERRNO */
5892 resultType = LongValue;
5894 curlResult = curl_easy_getinfo(connection->connection,
5895 CURLINFO_OS_ERRNO,
5896 &longValue);
5897 break;
5898 #endif
5900 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5901 case 26: /* CURLINFO_NUM_CONNECTS */
5902 resultType = LongValue;
5904 curlResult = curl_easy_getinfo(connection->connection,
5905 CURLINFO_NUM_CONNECTS,
5906 &longValue);
5907 break;
5908 #endif
5910 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5911 case 27: /* CURLINFO_SSL_ENGINES */
5912 resultType = StringListValue;
5914 curlResult = curl_easy_getinfo(connection->connection,
5915 CURLINFO_SSL_ENGINES,
5916 &stringListValue);
5917 break;
5918 #endif
5920 #if HAVE_DECL_CURLINFO_COOKIELIST
5921 case 28: /* CURLINFO_COOKIELIST */
5922 resultType = StringListValue;
5924 curlResult = curl_easy_getinfo(connection->connection,
5925 CURLINFO_COOKIELIST,
5926 &stringListValue);
5927 break;
5928 #endif
5930 #if HAVE_DECL_CURLINFO_LASTSOCKET
5931 case 29: /* CURLINFO_LASTSOCKET */
5932 resultType = LongValue;
5934 curlResult = curl_easy_getinfo(connection->connection,
5935 CURLINFO_LASTSOCKET,
5936 &longValue);
5937 break;
5938 #endif
5940 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5941 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5942 resultType = StringValue;
5944 curlResult = curl_easy_getinfo(connection->connection,
5945 CURLINFO_FTP_ENTRY_PATH,
5946 &strValue);
5947 break;
5948 #endif
5950 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5951 case 31: /* CURLINFO_REDIRECT_URL */
5952 resultType = StringValue;
5954 curlResult = curl_easy_getinfo(connection->connection,
5955 CURLINFO_REDIRECT_URL,
5956 &strValue);
5957 break;
5958 #else
5959 #pragma message("libcurl does not provide CURLINFO_REDIRECT_URL")
5960 #endif
5962 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5963 case 32: /* CURLINFO_PRIMARY_IP */
5964 resultType = StringValue;
5966 curlResult = curl_easy_getinfo(connection->connection,
5967 CURLINFO_PRIMARY_IP,
5968 &strValue);
5969 break;
5970 #else
5971 #pragma message("libcurl does not provide CURLINFO_PRIMARY_IP")
5972 #endif
5974 #if HAVE_DECL_CURLINFO_LOCAL_IP
5975 case 33: /* CURLINFO_LOCAL_IP */
5976 resultType = StringValue;
5978 curlResult = curl_easy_getinfo(connection->connection,
5979 CURLINFO_LOCAL_IP,
5980 &strValue);
5981 break;
5982 #else
5983 #pragma message("libcurl does not provide CURLINFO_LOCAL_IP")
5984 #endif
5986 #if HAVE_DECL_CURLINFO_LOCAL_PORT
5987 case 34: /* CURLINFO_LOCAL_PORT */
5988 resultType = LongValue;
5990 curlResult = curl_easy_getinfo(connection->connection,
5991 CURLINFO_LOCAL_PORT,
5992 &longValue);
5993 break;
5994 #else
5995 #pragma message("libcurl does not provide CURLINFO_LOCAL_PORT")
5996 #endif
5998 #if HAVE_DECL_CURLINFO_CONDITION_UNMET
5999 case 35: /* CURLINFO_CONDITION_UNMET */
6000 resultType = LongValue;
6002 curlResult = curl_easy_getinfo(connection->connection,
6003 CURLINFO_CONDITION_UNMET,
6004 &longValue);
6005 break;
6006 #else
6007 #pragma message("libcurl does not provide CURLINFO_CONDITION_UNMET")
6008 #endif
6010 default:
6011 failwith("Invalid CURLINFO Option");
6012 break;
6015 if (curlResult != CURLE_OK)
6016 raiseError(connection, curlResult);
6018 switch (resultType)
6020 case StringValue:
6021 result = alloc(1, StringValue);
6022 Store_field(result, 0, copy_string(strValue?strValue:""));
6023 break;
6025 case LongValue:
6026 result = alloc(1, LongValue);
6027 Store_field(result, 0, Val_long(longValue));
6028 break;
6030 case DoubleValue:
6031 result = alloc(1, DoubleValue);
6032 Store_field(result, 0, copy_double(doubleValue));
6033 break;
6035 case StringListValue:
6036 result = alloc(1, StringListValue);
6037 Store_field(result, 0, convertStringList(stringListValue));
6038 break;
6041 CAMLreturn(result);
6045 ** curl_escape helper function
6048 CAMLprim value helper_curl_escape(value str)
6050 CAMLparam1(str);
6051 CAMLlocal1(result);
6052 char *curlResult;
6054 curlResult = curl_escape(String_val(str), string_length(str));
6055 result = copy_string(curlResult);
6056 free(curlResult);
6058 CAMLreturn(result);
6062 ** curl_unescape helper function
6065 CAMLprim value helper_curl_unescape(value str)
6067 CAMLparam1(str);
6068 CAMLlocal1(result);
6069 char *curlResult;
6071 curlResult = curl_unescape(String_val(str), string_length(str));
6072 result = copy_string(curlResult);
6073 free(curlResult);
6075 CAMLreturn(result);
6079 ** curl_getdate helper function
6082 CAMLprim value helper_curl_getdate(value str, value now)
6084 CAMLparam2(str, now);
6085 CAMLlocal1(result);
6086 time_t curlResult;
6087 time_t curlNow;
6089 curlNow = (time_t)Double_val(now);
6090 curlResult = curl_getdate(String_val(str), &curlNow);
6091 result = copy_double((double)curlResult);
6093 CAMLreturn(result);
6097 ** curl_version helper function
6100 CAMLprim value helper_curl_version(void)
6102 CAMLparam0();
6103 CAMLlocal1(result);
6104 char *str;
6106 str = curl_version();
6107 result = copy_string(str);
6109 CAMLreturn(result);
6112 struct CURLVersionBitsMapping
6114 int code;
6115 char *name;
6118 struct CURLVersionBitsMapping versionBitsMap[] =
6120 {CURL_VERSION_IPV6, "ipv6"},
6121 {CURL_VERSION_KERBEROS4, "kerberos4"},
6122 {CURL_VERSION_SSL, "ssl"},
6123 {CURL_VERSION_LIBZ, "libz"},
6124 {CURL_VERSION_NTLM, "ntlm"},
6125 {CURL_VERSION_GSSNEGOTIATE, "gssnegotiate"},
6126 {CURL_VERSION_DEBUG, "debug"},
6127 {CURL_VERSION_CURLDEBUG, "curldebug"},
6128 {CURL_VERSION_ASYNCHDNS, "asynchdns"},
6129 {CURL_VERSION_SPNEGO, "spnego"},
6130 {CURL_VERSION_LARGEFILE, "largefile"},
6131 {CURL_VERSION_IDN, "idn"},
6132 {CURL_VERSION_SSPI, "sspi"},
6133 {CURL_VERSION_CONV, "conv"},
6134 #if HAVE_DECL_CURL_VERSION_TLSAUTH_SRP
6135 {CURL_VERSION_TLSAUTH_SRP, "srp"},
6136 #endif
6137 #if HAVE_DECL_CURL_VERSION_NTLM_WB
6138 {CURL_VERSION_NTLM_WB, "wb"},
6139 #endif
6142 CAMLprim value caml_curl_version_info(value unit)
6144 CAMLparam1(unit);
6145 CAMLlocal4(v, vlist, vnum, vfeatures);
6146 const char* const* p = NULL;
6147 size_t i = 0;
6149 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
6150 if (NULL == data) caml_failwith("curl_version_info");
6152 vlist = Val_emptylist;
6153 for (p = data->protocols; NULL != *p; p++)
6155 vlist = Val_cons(vlist, caml_copy_string(*p));
6158 vfeatures = Val_emptylist;
6159 for (i = 0; i < sizeof(versionBitsMap)/sizeof(versionBitsMap[0]); i++)
6161 if (0 != (versionBitsMap[i].code & data->features))
6162 vfeatures = Val_cons(vfeatures, caml_copy_string(versionBitsMap[i].name));
6165 vnum = caml_alloc_tuple(3);
6166 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
6167 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
6168 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
6170 v = caml_alloc_tuple(12);
6171 Store_field(v,0,caml_copy_string(data->version));
6172 Store_field(v,1,vnum);
6173 Store_field(v,2,caml_copy_string(data->host));
6174 Store_field(v,3,vfeatures);
6175 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
6176 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
6177 Store_field(v,6,vlist);
6178 Store_field(v,7,caml_copy_string((data->age >= 1 && data->ares) ? data->ares : ""));
6179 Store_field(v,8,Val_int((data->age >= 1) ? data->ares_num : 0));
6180 Store_field(v,9,caml_copy_string((data->age >= 2 && data->libidn) ? data->libidn : ""));
6181 Store_field(v,10,Val_int((data->age >= 3) ? data->iconv_ver_num : 0));
6182 Store_field(v,11,caml_copy_string((data->age >= 3 && data->libssh_version) ? data->libssh_version : ""));
6184 CAMLreturn(v);
6187 CAMLprim value caml_curl_pause(value conn, value opts)
6189 CAMLparam2(conn, opts);
6190 CAMLlocal4(v, vlist, vnum, vfeatures);
6191 Connection *connection = Connection_val(conn);
6192 int bitmask = 0;
6193 CURLcode result;
6195 while (Val_emptylist != opts)
6197 switch (Int_val(Field(opts,0)))
6199 case 0: bitmask |= CURLPAUSE_SEND; break;
6200 case 1: bitmask |= CURLPAUSE_RECV; break;
6201 case 2: bitmask |= CURLPAUSE_ALL; break;
6202 default: caml_failwith("wrong pauseOption");
6204 opts = Field(opts,1);
6207 result = curl_easy_pause(connection->connection,bitmask);
6208 if (result != CURLE_OK)
6209 raiseError(connection, result);
6211 CAMLreturn(Val_unit);
6215 * Curl multi stack support
6217 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
6218 * Other exported functions are prefixed with caml_curlm_, some of them
6219 * can/should be decomposed into smaller parts.
6222 struct ml_multi_handle
6224 CURLM* handle;
6225 value values; /* callbacks */
6228 enum
6230 curlmopt_socket_function,
6231 curlmopt_timer_function,
6233 /* last, not used */
6234 multi_values_total
6237 typedef struct ml_multi_handle ml_multi_handle;
6239 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
6240 #define CURLM_val(v) (Multi_val(v)->handle)
6242 static struct custom_operations curl_multi_ops = {
6243 "ygrek.curl_multi",
6244 custom_finalize_default,
6245 custom_compare_default,
6246 custom_hash_default,
6247 custom_serialize_default,
6248 custom_deserialize_default,
6249 #if defined(custom_compare_ext_default)
6250 custom_compare_ext_default,
6251 #endif
6254 CAMLprim value caml_curl_multi_init(value unit)
6256 CAMLparam1(unit);
6257 CAMLlocal1(v);
6258 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
6259 CURLM* h = curl_multi_init();
6261 if (!h)
6263 caml_stat_free(multi);
6264 failwith("caml_curl_multi_init");
6267 multi->handle = h;
6268 multi->values = caml_alloc(multi_values_total, 0);
6269 caml_register_generational_global_root(&multi->values);
6271 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
6272 Multi_val(v) = multi;
6274 CAMLreturn(v);
6277 CAMLprim value caml_curl_multi_cleanup(value handle)
6279 CAMLparam1(handle);
6280 ml_multi_handle* h = Multi_val(handle);
6282 if (NULL == h)
6283 CAMLreturn(Val_unit);
6285 caml_remove_generational_global_root(&h->values);
6287 if (CURLM_OK != curl_multi_cleanup(h->handle))
6288 failwith("caml_curl_multi_cleanup");
6290 Multi_val(handle) = (ml_multi_handle*)NULL;
6292 CAMLreturn(Val_unit);
6295 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
6297 int msgs_in_queue = 0;
6299 while (1)
6301 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
6302 if (NULL == msg) return NULL;
6303 if (CURLMSG_DONE == msg->msg)
6305 CURL* easy_handle = msg->easy_handle;
6306 if (result) *result = msg->data.result;
6307 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
6309 /*failwith("curlm_remove_finished");*/
6311 return easy_handle;
6316 CAMLprim value caml_curlm_remove_finished(value v_multi)
6318 CAMLparam1(v_multi);
6319 CAMLlocal2(v_easy, v_tuple);
6320 CURL* handle;
6321 CURLM* multi_handle;
6322 CURLcode result;
6324 multi_handle = CURLM_val(v_multi);
6326 caml_enter_blocking_section();
6327 handle = curlm_remove_finished(multi_handle,&result);
6328 caml_leave_blocking_section();
6330 if (NULL == handle)
6332 CAMLreturn(Val_none);
6334 else
6336 /* not good: same handle, but different block */
6337 v_easy = caml_alloc(1, Abstract_tag);
6338 Field(v_easy, 0) = (value)findConnection(handle);
6339 v_tuple = caml_alloc(2, 0);
6340 Store_field(v_tuple,0,v_easy);
6341 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6342 CAMLreturn(Val_some(v_tuple));
6346 static int curlm_wait_data(CURLM* multi_handle)
6348 struct timeval timeout;
6349 CURLMcode ret;
6351 fd_set fdread;
6352 fd_set fdwrite;
6353 fd_set fdexcep;
6354 int maxfd = -1;
6356 FD_ZERO(&fdread);
6357 FD_ZERO(&fdwrite);
6358 FD_ZERO(&fdexcep);
6360 /* set a suitable timeout */
6361 timeout.tv_sec = 1;
6362 timeout.tv_usec = 0;
6364 /* get file descriptors from the transfers */
6365 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6367 if (ret == CURLM_OK && maxfd >= 0)
6369 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6370 if (-1 != rc) return 0;
6372 return 1;
6375 CAMLprim value caml_curlm_wait_data(value v_multi)
6377 CAMLparam1(v_multi);
6378 int ret;
6379 CURLM* h = CURLM_val(v_multi);
6381 caml_enter_blocking_section();
6382 ret = curlm_wait_data(h);
6383 caml_leave_blocking_section();
6385 CAMLreturn(Val_bool(0 == ret));
6388 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6390 CAMLparam2(v_multi,v_easy);
6391 CURLM* multi = CURLM_val(v_multi);
6392 CURL* easy = Connection_val(v_easy)->connection;
6394 /* may invoke callbacks so need to be consistent with locks */
6395 caml_enter_blocking_section();
6396 if (CURLM_OK != curl_multi_add_handle(multi, easy))
6398 caml_leave_blocking_section();
6399 failwith("caml_curl_multi_add_handle");
6401 caml_leave_blocking_section();
6403 CAMLreturn(Val_unit);
6406 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6408 CAMLparam1(v_multi);
6409 int still_running = 0;
6410 CURLM* h = CURLM_val(v_multi);
6412 caml_enter_blocking_section();
6413 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6414 caml_leave_blocking_section();
6416 CAMLreturn(Val_int(still_running));
6419 CAMLprim value helper_curl_easy_strerror(value v_code)
6421 CAMLparam1(v_code);
6422 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));
6426 * Wrappers for the curl_multi_socket_action infrastructure
6427 * Based on curl hiperfifo.c example
6430 /* FIXME win32unix */
6431 #define Socket_val(v) Int_val(v)
6432 #define Val_socket(v) Val_int(v)
6434 static void raise_error(char const* msg)
6436 static value* exception = NULL;
6438 if (NULL == exception)
6440 exception = caml_named_value("Curl.Multi.Error");
6441 if (NULL == exception) caml_invalid_argument("Curl.Multi.Error");
6444 caml_raise_with_string(*exception, msg);
6447 static void check_mcode(CURLMcode code)
6449 char const *s = NULL;
6450 switch (code)
6452 case CURLM_OK : return;
6453 case CURLM_CALL_MULTI_PERFORM : s="CURLM_CALL_MULTI_PERFORM"; break;
6454 case CURLM_BAD_HANDLE : s="CURLM_BAD_HANDLE"; break;
6455 case CURLM_BAD_EASY_HANDLE : s="CURLM_BAD_EASY_HANDLE"; break;
6456 case CURLM_OUT_OF_MEMORY : s="CURLM_OUT_OF_MEMORY"; break;
6457 case CURLM_INTERNAL_ERROR : s="CURLM_INTERNAL_ERROR"; break;
6458 case CURLM_UNKNOWN_OPTION : s="CURLM_UNKNOWN_OPTION"; break;
6459 case CURLM_LAST : s="CURLM_LAST"; break;
6460 case CURLM_BAD_SOCKET : s="CURLM_BAD_SOCKET"; break;
6461 default : s="CURLM_unknown"; break;
6463 raise_error(s);
6466 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
6468 CAMLparam3(v_multi, v_fd, v_kind);
6469 CURLM* h = CURLM_val(v_multi);
6470 int still_running = 0;
6471 CURLMcode rc = CURLM_OK;
6472 int socket = Socket_val(v_fd);
6473 int kind = 0;
6475 switch (Int_val(v_kind))
6477 case 0 : break;
6478 case 1 : kind |= CURL_CSELECT_IN; break;
6479 case 2 : kind |= CURL_CSELECT_OUT; break;
6480 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
6481 default:
6482 raise_error("caml_curl_multi_socket_action");
6485 /* fprintf(stdout,"fd %u kind %u\n",Socket_val(v_fd), kind); fflush(stdout); */
6487 caml_enter_blocking_section();
6488 do {
6489 rc = curl_multi_socket_action(h, socket, kind, &still_running);
6490 } while (rc == CURLM_CALL_MULTI_PERFORM);
6491 caml_leave_blocking_section();
6493 check_mcode(rc);
6495 CAMLreturn(Val_int(still_running));
6498 CAMLprim value caml_curl_multi_socket_all(value v_multi)
6500 CAMLparam1(v_multi);
6501 int still_running = 0;
6502 CURLMcode rc = CURLM_OK;
6503 CURLM* h = CURLM_val(v_multi);
6505 caml_enter_blocking_section();
6506 do {
6507 rc = curl_multi_socket_all(h, &still_running);
6508 } while (rc == CURLM_CALL_MULTI_PERFORM);
6509 caml_leave_blocking_section();
6511 check_mcode(rc);
6513 CAMLreturn(Val_int(still_running));
6516 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
6518 CAMLparam0();
6519 CAMLlocal1(v_what);
6520 (void)e;
6521 (void)sockp; /* not used */
6523 /* v_what = Val_int(what); */
6524 switch (what)
6526 case CURL_POLL_NONE : v_what = Val_int(0); break;
6527 case CURL_POLL_IN : v_what = Val_int(1); break;
6528 case CURL_POLL_OUT : v_what = Val_int(2); break;
6529 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6530 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6531 default:
6532 fprintf(stderr, "curlm_sock_cb sock=%d what=%d\n", sock, what);
6533 fflush(stderr);
6534 raise_error("curlm_sock_cb"); /* FIXME exception from callback */
6537 caml_callback2(Field(multi->values,curlmopt_socket_function),
6538 Val_socket(sock), v_what);
6540 CAMLreturn(0);
6543 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6545 int ret;
6546 caml_leave_blocking_section();
6547 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6548 caml_enter_blocking_section();
6549 return ret;
6552 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6554 CAMLparam2(v_multi, v_cb);
6555 ml_multi_handle* multi = Multi_val(v_multi);
6557 Store_field(multi->values, curlmopt_socket_function, v_cb);
6559 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6560 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6562 CAMLreturn(Val_unit);
6565 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6567 CAMLparam0();
6568 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6569 CAMLreturn0;
6572 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6574 (void)multi;
6576 caml_leave_blocking_section();
6577 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6578 caml_enter_blocking_section();
6579 return 0;
6582 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6584 CAMLparam2(v_multi, v_cb);
6585 ml_multi_handle* multi = Multi_val(v_multi);
6587 Store_field(multi->values, curlmopt_timer_function, v_cb);
6589 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6590 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6592 CAMLreturn(Val_unit);
6595 CAMLprim value caml_curl_multi_timeout(value v_multi)
6597 CAMLparam1(v_multi);
6598 long ms = 0;
6599 CURLMcode rc = CURLM_OK;
6600 ml_multi_handle* multi = Multi_val(v_multi);
6602 rc = curl_multi_timeout(multi->handle, &ms);
6604 check_mcode(rc);
6606 CAMLreturn(Val_long(ms));