update Copyright
[ocurl.git] / curl-helper.c
blobe30b4bb36a84a53d94119f525c9da43a99199ba7
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 #warning "No config file given."
25 #endif
27 #if defined(_MSC_VER)
28 #ifdef interface
29 #undef interface
30 #endif
31 #endif
33 void leave_blocking_section(void);
34 void enter_blocking_section(void);
36 #define Val_none Val_int(0)
38 static __inline value
39 Val_some( value v )
41 CAMLparam1( v );
42 CAMLlocal1( some );
43 some = caml_alloc(1, 0);
44 Store_field( some, 0, v );
45 CAMLreturn( some );
48 static value Val_pair(value v1, value v2)
50 CAMLparam2(v1,v2);
51 CAMLlocal1(pair);
52 pair = caml_alloc_small(2,0);
53 Field(pair,0) = v1;
54 Field(pair,1) = v2;
55 CAMLreturn(pair);
58 static value Val_cons(value list, value v) { return Val_pair(v,list); }
60 typedef struct Connection Connection;
61 typedef struct ConnectionList ConnectionList;
63 #define Connection_val(v) ((Connection *)Field(v, 0))
65 enum OcamlValues
67 OcamlWriteCallback,
68 OcamlReadCallback,
69 OcamlErrorBuffer,
70 OcamlPostFields,
71 OcamlHTTPHeader,
72 OcamlHTTPPost,
73 OcamlQuote,
74 OcamlPostQuote,
75 OcamlHeaderCallback,
76 OcamlProgressCallback,
77 OcamlDebugCallback,
78 OcamlHTTP200Aliases,
79 OcamlIOCTLCallback,
80 OcamlSeekFunctionCallback,
81 OcamlOpenSocketFunctionCallback,
83 OcamlURL,
84 OcamlProxy,
85 OcamlUserPWD,
86 OcamlProxyUserPWD,
87 OcamlRange,
88 OcamlReferer,
89 OcamlUserAgent,
90 OcamlFTPPort,
91 OcamlCookie,
92 OcamlHTTPPostStrings,
93 OcamlSSLCert,
94 OcamlSSLCertType,
95 OcamlSSLCertPasswd,
96 OcamlSSLKey,
97 OcamlSSLKeyType,
98 OcamlSSLKeyPasswd,
99 OcamlSSLEngine,
100 OcamlCookieFile,
101 OcamlCustomRequest,
102 OcamlInterface,
103 OcamlCAInfo,
104 OcamlCAPath,
105 OcamlRandomFile,
106 OcamlEGDSocket,
107 OcamlCookieJar,
108 OcamlSSLCipherList,
109 OcamlPrivate,
110 OcamlNETRCFile,
111 OcamlFTPAccount,
112 OcamlCookieList,
113 OcamlFTPAlternativeToUser,
114 OcamlSSHPublicKeyFile,
115 OcamlSSHPrivateKeyFile,
116 OcamlSSHHostPublicKeyMD5,
117 OcamlCopyPostFields,
119 /* Not used, last for size */
120 OcamlValuesSize
123 struct Connection
125 CURL *connection;
126 Connection *next;
127 Connection *prev;
129 value ocamlValues;
131 char *url;
132 char *proxy;
133 char *userPwd;
134 char *proxyUserPwd;
135 char *range;
136 char *errorBuffer;
137 char *postFields;
138 int postFieldSize;
139 char *referer;
140 char *userAgent;
141 char *ftpPort;
142 char *cookie;
143 struct curl_slist *httpHeader;
144 struct curl_httppost *httpPostFirst;
145 struct curl_httppost *httpPostLast;
146 struct curl_slist *httpPostStrings;
147 char *sslCert;
148 char *sslCertType;
149 char *sslCertPasswd;
150 char *sslKey;
151 char *sslKeyType;
152 char *sslKeyPasswd;
153 char *sslEngine;
154 struct curl_slist *quote;
155 struct curl_slist *postQuote;
156 char *cookieFile;
157 char *customRequest;
158 char *interface;
159 char *caInfo;
160 char *caPath;
161 char *randomFile;
162 char *egdSocket;
163 char *cookieJar;
164 char *sslCipherList;
165 char *private;
166 struct curl_slist *http200Aliases;
167 char *netrcFile;
168 char *ftpaccount;
169 char *cookielist;
170 char *ftpAlternativeToUser;
171 char *sshPublicKeyFile;
172 char *sshPrivateKeyFile;
173 char *sshHostPublicKeyMD5;
174 char *copyPostFields;
177 struct ConnectionList
179 Connection *head;
180 Connection *tail;
183 static ConnectionList connectionList = {NULL, NULL};
185 typedef struct CURLErrorMapping CURLErrorMapping;
187 struct CURLErrorMapping
189 char *name;
190 CURLcode error;
193 CURLErrorMapping errorMap[] =
195 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
196 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
197 #else
198 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
199 #endif
200 #if HAVE_DECL_CURLE_FAILED_INIT
201 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
202 #else
203 {"CURLE_FAILED_INIT", -1},
204 #endif
205 #if HAVE_DECL_CURLE_URL_MALFORMAT
206 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
207 #else
208 {"CURLE_URL_MALFORMAT", -1},
209 #endif
210 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
211 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
212 #else
213 {"CURLE_URL_MALFORMAT_USER", -1},
214 #endif
215 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
216 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
217 #else
218 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
219 #endif
220 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
221 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
222 #else
223 {"CURLE_COULDNT_RESOLVE_HOST", -1},
224 #endif
225 #if HAVE_DECL_CURLE_COULDNT_CONNECT
226 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
227 #else
228 {"CURLE_COULDNT_CONNECT", -1},
229 #endif
230 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
231 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
232 #else
233 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
234 #endif
235 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
236 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
237 #else
238 {"CURLE_FTP_ACCESS_DENIED", -1},
239 #endif
240 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
241 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
242 #else
243 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
244 #endif
245 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
246 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
247 #else
248 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
249 #endif
250 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
251 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
252 #else
253 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
254 #endif
255 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
256 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
257 #else
258 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
259 #endif
260 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
261 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
262 #else
263 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
264 #endif
265 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
266 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
267 #else
268 {"CURLE_FTP_CANT_GET_HOST", -1},
269 #endif
270 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
271 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
272 #else
273 {"CURLE_FTP_CANT_RECONNECT", -1},
274 #endif
275 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
276 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
277 #else
278 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
279 #endif
280 #if HAVE_DECL_CURLE_PARTIAL_FILE
281 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
282 #else
283 {"CURLE_PARTIAL_FILE", -1},
284 #endif
285 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
286 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
287 #else
288 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
289 #endif
290 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
291 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
292 #else
293 {"CURLE_FTP_WRITE_ERROR", -1},
294 #endif
295 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
296 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
297 #else
298 {"CURLE_FTP_QUOTE_ERROR", -1},
299 #endif
300 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
301 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
302 #else
303 {"CURLE_HTTP_NOT_FOUND", -1},
304 #endif
305 #if HAVE_DECL_CURLE_WRITE_ERROR
306 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
307 #else
308 {"CURLE_WRITE_ERROR", -1},
309 #endif
310 #if HAVE_DECL_CURLE_MALFORMAT_USER
311 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
312 #else
313 {"CURLE_MALFORMAT_USER", -1},
314 #endif
315 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
316 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
317 #else
318 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
319 #endif
320 #if HAVE_DECL_CURLE_READ_ERROR
321 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
322 #else
323 {"CURLE_READ_ERROR", -1},
324 #endif
325 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
326 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
327 #else
328 {"CURLE_OUT_OF_MEMORY", -1},
329 #endif
330 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
331 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
332 #else
333 {"CURLE_OPERATION_TIMEOUTED", -1},
334 #endif
335 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
336 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
337 #else
338 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
339 #endif
340 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
341 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
342 #else
343 {"CURLE_FTP_PORT_FAILED", -1},
344 #endif
345 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
346 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
347 #else
348 {"CURLE_FTP_COULDNT_USE_REST", -1},
349 #endif
350 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
351 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
352 #else
353 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
354 #endif
355 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
356 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
357 #else
358 {"CURLE_HTTP_RANGE_ERROR", -1},
359 #endif
360 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
361 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
362 #else
363 {"CURLE_HTTP_POST_ERROR", -1},
364 #endif
365 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
366 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
367 #else
368 {"CURLE_SSL_CONNECT_ERROR", -1},
369 #endif
370 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
371 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
372 #else
373 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
374 #endif
375 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
376 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
377 #else
378 {"CURLE_FILE_COULDNT_READ_FILE", -1},
379 #endif
380 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
381 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
382 #else
383 {"CURLE_LDAP_CANNOT_BIND", -1},
384 #endif
385 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
386 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
387 #else
388 {"CURLE_LDAP_SEARCH_FAILED", -1},
389 #endif
390 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
391 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
392 #else
393 {"CURLE_LIBRARY_NOT_FOUND", -1},
394 #endif
395 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
396 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
397 #else
398 {"CURLE_FUNCTION_NOT_FOUND", -1},
399 #endif
400 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
401 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
402 #else
403 {"CURLE_ABORTED_BY_CALLBACK", -1},
404 #endif
405 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
406 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
407 #else
408 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
409 #endif
410 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
411 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
412 #else
413 {"CURLE_BAD_CALLING_ORDER", -1},
414 #endif
415 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
416 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
417 #else
418 {"CURLE_HTTP_PORT_FAILED", -1},
419 #endif
420 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
421 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
422 #else
423 {"CURLE_BAD_PASSWORD_ENTERED", -1},
424 #endif
425 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
426 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
427 #else
428 {"CURLE_TOO_MANY_REDIRECTS", -1},
429 #endif
430 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
431 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
432 #else
433 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
434 #endif
435 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
436 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
437 #else
438 {"CURLE_TELNET_OPTION_SYNTAX", -1},
439 #endif
440 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
441 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
442 #else
443 {"CURLE_SSL_PEER_CERTIFICATE", -1},
444 #endif
445 #if HAVE_DECL_CURLE_GOT_NOTHING
446 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
447 #else
448 {"CURLE_GOT_NOTHING", -1},
449 #endif
450 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
451 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
452 #else
453 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
454 #endif
455 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
456 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
457 #else
458 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
459 #endif
460 #if HAVE_DECL_CURLE_SEND_ERROR
461 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
462 #else
463 {"CURLE_SEND_ERROR", -1},
464 #endif
465 #if HAVE_DECL_CURLE_RECV_ERROR
466 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
467 #else
468 {"CURLE_RECV_ERROR", -1},
469 #endif
470 #if HAVE_DECL_CURLE_SHARE_IN_USE
471 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
472 #else
473 {"CURLE_SHARE_IN_USE", -1},
474 #endif
475 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
476 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
477 #else
478 {"CURLE_SSL_CERTPROBLEN", -1},
479 #endif
480 #if HAVE_DECL_CURLE_SSL_CIPHER
481 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
482 #else
483 {"CURLE_SSL_CIPHER", -1},
484 #endif
485 #if HAVE_DECL_CURLE_SSL_CACERT
486 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
487 #else
488 {"CURLE_SSL_CACERT", -1},
489 #endif
490 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
491 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
492 #else
493 {"CURLE_BAD_CONTENT_ENCODING", -1},
494 #endif
495 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
496 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
497 #else
498 {"CURLE_LDAP_INVALID_URL", -1},
499 #endif
500 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
501 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
502 #else
503 {"CURLE_FILESIZE_EXCEEDED", -1},
504 #endif
505 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
506 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
507 #else
508 {"CURLE_FTP_SSL_FAILED", -1},
509 #endif
510 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
511 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
512 #else
513 {"CURLE_SEND_FAIL_REWIND", -1},
514 #endif
515 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
516 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
517 #else
518 {"CURLE_SSL_ENGINE_INITFAILED", -1},
519 #endif
520 #if HAVE_DECL_CURLE_LOGIN_DENIED
521 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
522 #else
523 {"CURLE_LOGIN_DENIED", -1},
524 #endif
525 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
526 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
527 #else
528 {"CURLE_TFTP_NOTFOUND", -1},
529 #endif
530 #if HAVE_DECL_CURLE_TFTP_PERM
531 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
532 #else
533 {"CURLE_TFTP_PERM", -1},
534 #endif
535 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
536 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
537 #else
538 {"CURLE_REMOTE_DISK_FULL", -1},
539 #endif
540 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
541 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
542 #else
543 {"CURLE_TFTP_ILLEGAL", -1},
544 #endif
545 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
546 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
547 #else
548 {"CURLE_TFTP_UNKNOWNID", -1},
549 #endif
550 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
551 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
552 #else
553 {"CURLE_REMOTE_FILE_EXISTS", -1},
554 #endif
555 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
556 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
557 #else
558 {"CURLE_TFTP_NOSUCHUSER", -1},
559 #endif
560 #if HAVE_DECL_CURLE_CONV_FAILED
561 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
562 #else
563 {"CURLE_CONV_FAILED", -1},
564 #endif
565 #if HAVE_DECL_CURLE_CONV_REQUIRED
566 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
567 #else
568 {"CURLE_CONV_REQUIRED", -1},
569 #endif
570 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
571 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
572 #else
573 {"CURLE_SSL_CACERT_BADFILE", -1},
574 #endif
575 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
576 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
577 #else
578 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
579 #endif
580 #if HAVE_DECL_CURLE_SSH
581 {"CURLE_SSH", CURLE_SSH},
582 #else
583 {"CURLE_SSH", -1},
584 #endif
585 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
586 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
587 #else
588 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
589 #endif
590 #if HAVE_DECL_CURLE_AGAIN
591 {"CURLE_AGAIN", CURLE_AGAIN},
592 #else
593 {"CURLE_AGAIN", -1},
594 #endif
595 {"CURLE_OK", CURLE_OK},
596 {NULL, 0}
599 typedef struct CURLOptionMapping CURLOptionMapping;
601 struct CURLOptionMapping
603 void (*optionHandler)(Connection *, value);
604 char *name;
605 CURLoption option;
608 CURLOptionMapping unimplementedOptionMap[] =
610 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
611 {NULL, NULL, 0}
614 static void handleWriteFunction(Connection *, value);
615 static void handleReadFunction(Connection *, value);
616 static void handleInFileSize(Connection *, value);
617 static void handleURL(Connection *, value);
618 static void handleProxy(Connection *, value);
619 static void handleProxyPort(Connection *, value);
620 static void handleHTTPProxyTunnel(Connection *, value);
621 static void handleVerbose(Connection *, value);
622 static void handleHeader(Connection *, value);
623 static void handleNoProgress(Connection *, value);
624 static void handleNoSignal(Connection *, value);
625 static void handleNoBody(Connection *, value);
626 static void handleFailOnError(Connection *, value);
627 static void handleUpload(Connection *, value);
628 static void handlePost(Connection *, value);
629 static void handleFTPListOnly(Connection *, value);
630 static void handleFTPAppend(Connection *, value);
631 static void handleNETRC(Connection *, value);
632 static void handleEncoding(Connection *, value);
633 static void handleFollowLocation(Connection *, value);
634 static void handleTransferText(Connection *, value);
635 static void handlePut(Connection *, value);
636 static void handleUserPwd(Connection *, value);
637 static void handleProxyUserPwd(Connection *, value);
638 static void handleRange(Connection *, value);
639 static void handleErrorBuffer(Connection *, value);
640 static void handleTimeout(Connection *, value);
641 static void handlePostFields(Connection *, value);
642 static void handlePostFieldSize(Connection *, value);
643 static void handleReferer(Connection *, value);
644 static void handleUserAgent(Connection *, value);
645 static void handleFTPPort(Connection *, value);
646 static void handleLowSpeedLimit(Connection *, value);
647 static void handleLowSpeedTime(Connection *, value);
648 static void handleResumeFrom(Connection *, value);
649 static void handleCookie(Connection *, value);
650 static void handleHTTPHeader(Connection *, value);
651 static void handleHTTPPost(Connection *, value);
652 static void handleSSLCert(Connection *, value);
653 static void handleSSLCertType(Connection *, value);
654 static void handleSSLCertPasswd(Connection *, value);
655 static void handleSSLKey(Connection *, value);
656 static void handleSSLKeyType(Connection *, value);
657 static void handleSSLKeyPasswd(Connection *, value);
658 static void handleSSLEngine(Connection *, value);
659 static void handleSSLEngineDefault(Connection *, value);
660 static void handleCRLF(Connection *, value);
661 static void handleQuote(Connection *, value);
662 static void handlePostQuote(Connection *, value);
663 static void handleHeaderFunction(Connection *, value);
664 static void handleCookieFile(Connection *, value);
665 static void handleSSLVersion(Connection *, value);
666 static void handleTimeCondition(Connection *, value);
667 static void handleTimeValue(Connection *, value);
668 static void handleCustomRequest(Connection *, value);
669 static void handleInterface(Connection *, value);
670 static void handleKRB4Level(Connection *, value);
671 static void handleProgressFunction(Connection *, value);
672 static void handleSSLVerifyPeer(Connection *, value);
673 static void handleCAInfo(Connection *, value);
674 static void handleCAPath(Connection *, value);
675 static void handleFileTime(Connection *, value);
676 static void handleMaxRedirs(Connection *, value);
677 static void handleMaxConnects(Connection *, value);
678 static void handleClosePolicy(Connection *, value);
679 static void handleFreshConnect(Connection *, value);
680 static void handleForbidReuse(Connection *, value);
681 static void handleRandomFile(Connection *, value);
682 static void handleEGDSocket(Connection *, value);
683 static void handleConnectTimeout(Connection *, value);
684 static void handleHTTPGet(Connection *, value);
685 static void handleSSLVerifyHost(Connection *, value);
686 static void handleCookieJar(Connection *, value);
687 static void handleSSLCipherList(Connection *, value);
688 static void handleHTTPVersion(Connection *, value);
689 static void handleFTPUseEPSV(Connection *, value);
690 static void handleDNSCacheTimeout(Connection *, value);
691 static void handleDNSUseGlobalCache(Connection *, value);
692 static void handleDebugFunction(Connection *, value);
693 static void handlePrivate(Connection *, value);
694 static void handleHTTP200Aliases(Connection *, value);
695 static void handleUnrestrictedAuth(Connection *, value);
696 static void handleFTPUseEPRT(Connection *, value);
697 static void handleHTTPAuth(Connection *, value);
698 static void handleFTPCreateMissingDirs(Connection *, value);
699 static void handleProxyAuth(Connection *, value);
700 static void handleFTPResponseTimeout(Connection *, value);
701 static void handleIPResolve(Connection *, value);
702 static void handleMaxFileSize(Connection *, value);
703 static void handleInFileSizeLarge(Connection *, value);
704 static void handleResumeFromLarge(Connection *, value);
705 static void handleMaxFileSizeLarge(Connection *, value);
706 static void handleNETRCFile(Connection *, value);
707 static void handleFTPSSL(Connection *, value);
708 static void handlePostFieldSizeLarge(Connection *, value);
709 static void handleTCPNoDelay(Connection *, value);
710 static void handleFTPSSLAuth(Connection *, value);
711 static void handleIOCTLFunction(Connection *, value);
712 static void handleFTPAccount(Connection *, value);
713 static void handleCookieList(Connection *, value);
714 static void handleIgnoreContentLength(Connection *, value);
715 static void handleFTPSkipPASVIP(Connection *, value);
716 static void handleFTPFileMethod(Connection *, value);
717 static void handleLocalPort(Connection *, value);
718 static void handleLocalPortRange(Connection *, value);
719 static void handleConnectOnly(Connection *, value);
720 static void handleMaxSendSpeedLarge(Connection *, value);
721 static void handleMaxRecvSpeedLarge(Connection *, value);
722 static void handleFTPAlternativeToUser(Connection *, value);
723 static void handleSSLSessionIdCache(Connection *, value);
724 static void handleSSHAuthTypes(Connection *, value);
725 static void handleSSHPublicKeyFile(Connection *, value);
726 static void handleSSHPrivateKeyFile(Connection *, value);
727 static void handleFTPSSLCCC(Connection *, value);
728 static void handleTimeoutMS(Connection *, value);
729 static void handleConnectTimeoutMS(Connection *, value);
730 static void handleHTTPTransferDecoding(Connection *, value);
731 static void handleHTTPContentDecoding(Connection *, value);
732 static void handleNewFilePerms(Connection *, value);
733 static void handleNewDirectoryPerms(Connection *, value);
734 static void handlePost301(Connection *, value);
735 static void handleSSHHostPublicKeyMD5(Connection *, value);
736 static void handleCopyPostFields(Connection *, value);
737 static void handleProxyTransferMode(Connection *, value);
738 static void handleSeekFunction(Connection *, value);
739 static void handleAutoReferer(Connection *, value);
740 static void handleOpenSocketFunction(Connection *, value);
741 static void handleProxyType(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
1079 static char *findOption(CURLOptionMapping optionMap[],
1080 CURLoption option)
1082 return optionMap[option].name;
1085 static void free_curl_slist(struct curl_slist *slist)
1087 if (NULL == slist)
1088 return;
1090 curl_slist_free_all(slist);
1093 static void raiseError(Connection *conn, CURLcode code)
1095 CAMLparam0();
1096 CAMLlocal1(exceptionData);
1097 value *exception;
1098 char *errorString = "Unknown Error";
1099 int i;
1101 for (i = 0; errorMap[i].name != NULL; i++)
1103 if (errorMap[i].error == code)
1105 errorString = errorMap[i].name;
1106 break;
1110 exceptionData = caml_alloc(3, 0);
1112 Store_field(exceptionData, 0, Val_int(code));
1113 Store_field(exceptionData, 1, Val_int(code));
1114 Store_field(exceptionData, 2, copy_string(errorString));
1116 if (conn != NULL && conn->errorBuffer != NULL)
1118 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1119 copy_string(conn->errorBuffer));
1122 exception = caml_named_value("CurlException");
1124 if (exception == NULL)
1125 caml_failwith("CurlException not registered");
1127 raise_with_arg(*exception, exceptionData);
1129 CAMLreturn0;
1132 static void resetOcamlValues(Connection* connection)
1134 int i;
1136 for (i = 0; i < OcamlValuesSize; i++)
1137 Store_field(connection->ocamlValues, i, Val_unit);
1140 static Connection *newConnection(void)
1142 Connection *connection;
1144 connection = (Connection *)malloc(sizeof(Connection));
1146 enter_blocking_section();
1147 connection->connection = curl_easy_init();
1148 leave_blocking_section();
1150 connection->next = NULL;
1151 connection->prev = NULL;
1153 if (connectionList.tail == NULL)
1155 connectionList.tail = connection;
1156 connectionList.head = connection;
1158 else
1160 connection->prev = connectionList.head;
1161 connectionList.head->next = connection;
1162 connectionList.head = connection;
1165 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1166 resetOcamlValues(connection);
1167 register_global_root(&connection->ocamlValues);
1169 connection->url = NULL;
1170 connection->proxy = NULL;
1171 connection->userPwd = NULL;
1172 connection->proxyUserPwd = NULL;
1173 connection->range = NULL;
1174 connection->errorBuffer = NULL;
1175 connection->postFields = NULL;
1176 connection->postFieldSize = -1;
1177 connection->referer = NULL;
1178 connection->userAgent = NULL;
1179 connection->ftpPort = NULL;
1180 connection->cookie = NULL;
1181 connection->httpHeader = NULL;
1182 connection->httpPostFirst = NULL;
1183 connection->httpPostLast = NULL;
1184 connection->httpPostStrings = NULL;
1185 connection->sslCert = NULL;
1186 connection->sslCertType = NULL;
1187 connection->sslCertPasswd = NULL;
1188 connection->sslKey = NULL;
1189 connection->sslKeyType = NULL;
1190 connection->sslKeyPasswd = NULL;
1191 connection->sslEngine = NULL;
1192 connection->quote = NULL;
1193 connection->postQuote = NULL;
1194 connection->cookieFile = NULL;
1195 connection->customRequest = NULL;
1196 connection->interface = NULL;
1197 connection->caInfo = NULL;
1198 connection->caPath = NULL;
1199 connection->randomFile = NULL;
1200 connection->egdSocket = NULL;
1201 connection->cookieJar = NULL;
1202 connection->sslCipherList = NULL;
1203 connection->private = NULL;
1204 connection->http200Aliases = NULL;
1205 connection->netrcFile = NULL;
1206 connection->ftpaccount = NULL;
1207 connection->cookielist = NULL;
1208 connection->ftpAlternativeToUser = NULL;
1209 connection->sshPublicKeyFile = NULL;
1210 connection->sshPrivateKeyFile = NULL;
1211 connection->copyPostFields = NULL;
1213 return connection;
1216 static Connection *duplicateConnection(Connection *original)
1218 Connection *connection;
1220 connection = (Connection *)malloc(sizeof(Connection));
1222 enter_blocking_section();
1223 connection->connection = curl_easy_duphandle(original->connection);
1224 leave_blocking_section();
1226 connection->next = NULL;
1227 connection->prev = NULL;
1229 if (connectionList.tail == NULL)
1231 connectionList.tail = connection;
1232 connectionList.head = connection;
1234 else
1236 connection->prev = connectionList.head;
1237 connectionList.head->next = connection;
1238 connectionList.head = connection;
1241 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1242 resetOcamlValues(connection);
1243 register_global_root(&connection->ocamlValues);
1245 Store_field(connection->ocamlValues, OcamlWriteCallback,
1246 Field(original->ocamlValues, OcamlWriteCallback));
1247 Store_field(connection->ocamlValues, OcamlReadCallback,
1248 Field(original->ocamlValues, OcamlReadCallback));
1249 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1250 Field(original->ocamlValues, OcamlErrorBuffer));
1251 Store_field(connection->ocamlValues, OcamlPostFields,
1252 Field(original->ocamlValues, OcamlPostFields));
1253 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1254 Field(original->ocamlValues, OcamlHTTPHeader));
1255 Store_field(connection->ocamlValues, OcamlQuote,
1256 Field(original->ocamlValues, OcamlQuote));
1257 Store_field(connection->ocamlValues, OcamlPostQuote,
1258 Field(original->ocamlValues, OcamlPostQuote));
1259 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1260 Field(original->ocamlValues, OcamlHeaderCallback));
1261 Store_field(connection->ocamlValues, OcamlProgressCallback,
1262 Field(original->ocamlValues, OcamlProgressCallback));
1263 Store_field(connection->ocamlValues, OcamlDebugCallback,
1264 Field(original->ocamlValues, OcamlDebugCallback));
1265 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1266 Field(original->ocamlValues, OcamlHTTP200Aliases));
1267 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1268 Field(original->ocamlValues, OcamlIOCTLCallback));
1269 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1270 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1272 connection->url = NULL;
1273 connection->proxy = NULL;
1274 connection->userPwd = NULL;
1275 connection->proxyUserPwd = NULL;
1276 connection->range = NULL;
1277 connection->errorBuffer = NULL;
1278 connection->postFields = NULL;
1279 connection->postFieldSize = -1;
1280 connection->referer = NULL;
1281 connection->userAgent = NULL;
1282 connection->ftpPort = NULL;
1283 connection->cookie = NULL;
1284 connection->httpHeader = NULL;
1285 connection->httpPostFirst = NULL;
1286 connection->httpPostLast = NULL;
1287 connection->httpPostStrings = NULL;
1288 connection->sslCert = NULL;
1289 connection->sslCertType = NULL;
1290 connection->sslCertPasswd = NULL;
1291 connection->sslKey = NULL;
1292 connection->sslKeyType = NULL;
1293 connection->sslKeyPasswd = NULL;
1294 connection->sslEngine = NULL;
1295 connection->quote = NULL;
1296 connection->postQuote = NULL;
1297 connection->cookieFile = NULL;
1298 connection->customRequest = NULL;
1299 connection->interface = NULL;
1300 connection->caInfo = NULL;
1301 connection->caPath = NULL;
1302 connection->randomFile = NULL;
1303 connection->egdSocket = NULL;
1304 connection->cookieJar = NULL;
1305 connection->sslCipherList = NULL;
1306 connection->private = NULL;
1307 connection->http200Aliases = NULL;
1308 connection->netrcFile = NULL;
1309 connection->ftpaccount = NULL;
1310 connection->cookielist = NULL;
1311 connection->sshPublicKeyFile = NULL;
1312 connection->sshPrivateKeyFile = NULL;
1313 connection->copyPostFields = NULL;
1315 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1316 handleURL(connection, Field(original->ocamlValues,
1317 OcamlURL));
1318 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1319 handleProxy(connection, Field(original->ocamlValues,
1320 OcamlProxy));
1321 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1322 handleUserPwd(connection, Field(original->ocamlValues,
1323 OcamlUserPWD));
1324 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1325 handleProxyUserPwd(connection, Field(original->ocamlValues,
1326 OcamlProxyUserPWD));
1327 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1328 handleRange(connection, Field(original->ocamlValues,
1329 OcamlRange));
1330 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1331 handleErrorBuffer(connection, Field(original->ocamlValues,
1332 OcamlErrorBuffer));
1333 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1334 handlePostFields(connection, Field(original->ocamlValues,
1335 OcamlPostFields));
1336 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1337 handleReferer(connection, Field(original->ocamlValues,
1338 OcamlReferer));
1339 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1340 handleUserAgent(connection, Field(original->ocamlValues,
1341 OcamlUserAgent));
1342 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1343 handleFTPPort(connection, Field(original->ocamlValues,
1344 OcamlFTPPort));
1345 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1346 handleCookie(connection, Field(original->ocamlValues,
1347 OcamlCookie));
1348 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1349 handleHTTPHeader(connection, Field(original->ocamlValues,
1350 OcamlHTTPHeader));
1351 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1352 handleHTTPPost(connection, Field(original->ocamlValues,
1353 OcamlHTTPPost));
1354 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1355 handleSSLCert(connection, Field(original->ocamlValues,
1356 OcamlSSLCert));
1357 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1358 handleSSLCertType(connection, Field(original->ocamlValues,
1359 OcamlSSLCertType));
1360 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1361 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1362 OcamlSSLCertPasswd));
1363 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1364 handleSSLKey(connection, Field(original->ocamlValues,
1365 OcamlSSLKey));
1366 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1367 handleSSLKeyType(connection, Field(original->ocamlValues,
1368 OcamlSSLKeyType));
1369 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1370 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1371 OcamlSSLKeyPasswd));
1372 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1373 handleSSLEngine(connection, Field(original->ocamlValues,
1374 OcamlSSLEngine));
1375 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1376 handleQuote(connection, Field(original->ocamlValues,
1377 OcamlQuote));
1378 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1379 handlePostQuote(connection, Field(original->ocamlValues,
1380 OcamlPostQuote));
1381 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1382 handleCookieFile(connection, Field(original->ocamlValues,
1383 OcamlCookieFile));
1384 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1385 handleCustomRequest(connection, Field(original->ocamlValues,
1386 OcamlCustomRequest));
1387 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1388 handleInterface(connection, Field(original->ocamlValues,
1389 OcamlInterface));
1390 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1391 handleCAInfo(connection, Field(original->ocamlValues,
1392 OcamlCAInfo));
1393 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1394 handleCAPath(connection, Field(original->ocamlValues,
1395 OcamlCAPath));
1396 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1397 handleRandomFile(connection, Field(original->ocamlValues,
1398 OcamlRandomFile));
1399 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1400 handleEGDSocket(connection, Field(original->ocamlValues,
1401 OcamlEGDSocket));
1402 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1403 handleCookieJar(connection, Field(original->ocamlValues,
1404 OcamlCookieJar));
1405 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1406 handleSSLCipherList(connection, Field(original->ocamlValues,
1407 OcamlSSLCipherList));
1408 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1409 handlePrivate(connection, Field(original->ocamlValues,
1410 OcamlPrivate));
1411 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1412 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1413 OcamlHTTP200Aliases));
1414 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1415 handleNETRCFile(connection, Field(original->ocamlValues,
1416 OcamlNETRCFile));
1417 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1418 handleFTPAccount(connection, Field(original->ocamlValues,
1419 OcamlFTPAccount));
1420 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1421 handleCookieList(connection, Field(original->ocamlValues,
1422 OcamlCookieList));
1423 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1424 handleFTPAlternativeToUser(connection,
1425 Field(original->ocamlValues,
1426 OcamlFTPAlternativeToUser));
1427 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1428 handleSSHPublicKeyFile(connection,
1429 Field(original->ocamlValues,
1430 OcamlSSHPublicKeyFile));
1431 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1432 handleSSHPrivateKeyFile(connection,
1433 Field(original->ocamlValues,
1434 OcamlSSHPrivateKeyFile));
1435 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1436 handleCopyPostFields(connection,
1437 Field(original->ocamlValues,
1438 OcamlCopyPostFields));
1440 return connection;
1443 static void free_if(void* p) { if (NULL != p) free(p); }
1445 static void removeConnection(Connection *connection)
1447 enter_blocking_section();
1448 curl_easy_cleanup(connection->connection);
1449 leave_blocking_section();
1451 if (connectionList.tail == connection)
1452 connectionList.tail = connectionList.tail->next;
1453 if (connectionList.head == connection)
1454 connectionList.head = connectionList.head->prev;
1456 if (connection->next != NULL)
1457 connection->next->prev = connection->prev;
1458 if (connection->prev != NULL)
1459 connection->prev->next = connection->next;
1461 remove_global_root(&connection->ocamlValues);
1463 free_if(connection->url);
1464 free_if(connection->proxy);
1465 free_if(connection->userPwd);
1466 free_if(connection->proxyUserPwd);
1467 free_if(connection->range);
1468 free_if(connection->errorBuffer);
1469 free_if(connection->postFields);
1470 free_if(connection->referer);
1471 free_if(connection->userAgent);
1472 free_if(connection->ftpPort);
1473 free_if(connection->cookie);
1474 free_curl_slist(connection->httpHeader);
1475 if (connection->httpPostFirst != NULL)
1476 curl_formfree(connection->httpPostFirst);
1477 free_curl_slist(connection->httpPostStrings);
1478 free_if(connection->sslCert);
1479 free_if(connection->sslCertType);
1480 free_if(connection->sslCertPasswd);
1481 free_if(connection->sslKey);
1482 free_if(connection->sslKeyType);
1483 free_if(connection->sslKeyPasswd);
1484 free_if(connection->sslEngine);
1485 free_curl_slist(connection->quote);
1486 free_curl_slist(connection->postQuote);
1487 free_if(connection->cookieFile);
1488 free_if(connection->customRequest);
1489 free_if(connection->interface);
1490 free_if(connection->caInfo);
1491 free_if(connection->caPath);
1492 free_if(connection->randomFile);
1493 free_if(connection->egdSocket);
1494 free_if(connection->cookieJar);
1495 free_if(connection->sslCipherList);
1496 free_if(connection->private);
1497 free_curl_slist(connection->http200Aliases);
1498 free_if(connection->netrcFile);
1499 free_if(connection->ftpaccount);
1500 free_if(connection->cookielist);
1501 free_if(connection->ftpAlternativeToUser);
1502 free_if(connection->sshPublicKeyFile);
1503 free_if(connection->sshPrivateKeyFile);
1504 free_if(connection->copyPostFields);
1506 free(connection);
1509 static void checkConnection(Connection *connection)
1511 return;
1513 Connection *listIter;
1515 listIter = connectionList.tail;
1517 while (listIter != NULL)
1519 if (listIter == connection)
1520 return;
1522 listIter = listIter->next;
1525 failwith("Invalid Connection");
1528 static Connection* findConnection(CURL* h)
1530 Connection *listIter;
1532 listIter = connectionList.tail;
1534 while (listIter != NULL)
1536 if (listIter->connection == h)
1537 return listIter;
1539 listIter = listIter->next;
1542 failwith("Unknown handle");
1545 #define WRAP_DATA_CALLBACK(f) \
1546 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1548 size_t result;\
1549 leave_blocking_section();\
1550 result = f##_nolock(ptr,size,nmemb,data);\
1551 enter_blocking_section();\
1552 return result;\
1555 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1557 CAMLparam0();
1558 CAMLlocal2(result, str);
1559 Connection *conn = (Connection *)data;
1560 int i;
1562 checkConnection(conn);
1564 str = alloc_string(size*nmemb);
1566 for (i = 0; i < size*nmemb; i++)
1567 Byte(str, i) = ptr[i];
1569 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1571 CAMLreturnT(size_t, Int_val(result));
1574 WRAP_DATA_CALLBACK(writeFunction)
1576 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1578 CAMLparam0();
1579 CAMLlocal1(result);
1580 Connection *conn = (Connection *)data;
1581 int length;
1583 checkConnection(conn);
1585 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1586 Val_int(size*nmemb));
1588 length = string_length(result);
1590 if (length >= size*nmemb)
1591 length = size*nmemb;
1593 memcpy(ptr, String_val(result), length);
1595 CAMLreturnT(size_t,length);
1598 WRAP_DATA_CALLBACK(readFunction)
1600 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1602 CAMLparam0();
1603 CAMLlocal2(result,str);
1604 Connection *conn = (Connection *)data;
1605 int i;
1607 checkConnection(conn);
1609 str = alloc_string(size*nmemb);
1611 for (i = 0; i < size*nmemb; i++)
1612 Byte(str, i) = ptr[i];
1614 result = callback(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1616 CAMLreturnT(size_t, Int_val(result));
1619 WRAP_DATA_CALLBACK(headerFunction)
1621 static int progressFunction_nolock(void *data,
1622 double dlTotal,
1623 double dlNow,
1624 double ulTotal,
1625 double ulNow)
1627 CAMLparam0();
1628 CAMLlocal1(result);
1629 CAMLlocalN(callbackData, 4);
1630 Connection *conn = (Connection *)data;
1632 checkConnection(conn);
1634 callbackData[0] = copy_double(dlTotal);
1635 callbackData[1] = copy_double(dlNow);
1636 callbackData[2] = copy_double(ulTotal);
1637 callbackData[3] = copy_double(ulNow);
1639 result = callbackN(Field(conn->ocamlValues, OcamlProgressCallback),
1640 4, callbackData);
1642 CAMLreturnT(int, Bool_val(result));
1645 static int progressFunction(void *data,
1646 double dlTotal,
1647 double dlNow,
1648 double ulTotal,
1649 double ulNow)
1651 int r;
1652 leave_blocking_section();
1653 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1654 enter_blocking_section();
1655 return r;
1658 static int debugFunction_nolock(CURL *debugConnection,
1659 curl_infotype infoType,
1660 char *buffer,
1661 size_t bufferLength,
1662 void *data)
1664 CAMLparam0();
1665 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1666 int i;
1667 Connection *conn = (Connection *)data;
1669 checkConnection(conn);
1671 camlDebugConnection = (value)conn;
1672 camlInfoType = Val_long(infoType);
1673 camlMessage = alloc_string(bufferLength);
1675 for (i = 0; i < bufferLength; i++)
1676 Byte(camlMessage, i) = buffer[i];
1678 callback3(Field(conn->ocamlValues, OcamlDebugCallback),
1679 camlDebugConnection,
1680 camlInfoType,
1681 camlMessage);
1683 CAMLreturnT(int, 0);
1686 static int debugFunction(CURL *debugConnection,
1687 curl_infotype infoType,
1688 char *buffer,
1689 size_t bufferLength,
1690 void *data)
1692 int r;
1693 leave_blocking_section();
1694 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1695 enter_blocking_section();
1696 return r;
1699 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1700 int cmd,
1701 void *data)
1703 CAMLparam0();
1704 CAMLlocal3(camlResult, camlConnection, camlCmd);
1705 Connection *conn = (Connection *)data;
1706 curlioerr result = CURLIOE_OK;
1708 checkConnection(conn);
1710 if (cmd == CURLIOCMD_NOP)
1711 camlCmd = Val_long(0);
1712 else if (cmd == CURLIOCMD_RESTARTREAD)
1713 camlCmd = Val_long(1);
1714 else
1715 failwith("Invalid IOCTL Cmd!");
1717 camlConnection = caml_alloc(1, Abstract_tag);
1718 Field(camlConnection, 0) = (value)conn;
1720 camlResult = callback2(Field(conn->ocamlValues, OcamlIOCTLCallback),
1721 camlConnection,
1722 camlCmd);
1724 switch (Long_val(camlResult))
1726 case 0: /* CURLIOE_OK */
1727 result = CURLIOE_OK;
1728 break;
1730 case 1: /* CURLIOE_UNKNOWNCMD */
1731 result = CURLIOE_UNKNOWNCMD;
1732 break;
1734 case 2: /* CURLIOE_FAILRESTART */
1735 result = CURLIOE_FAILRESTART;
1736 break;
1738 default: /* Incorrect return value, but let's handle it */
1739 result = CURLIOE_FAILRESTART;
1740 break;
1743 CAMLreturnT(curlioerr, result);
1746 static curlioerr ioctlFunction(CURL *ioctl,
1747 int cmd,
1748 void *data)
1750 curlioerr r;
1751 leave_blocking_section();
1752 r = ioctlFunction_nolock(ioctl, cmd, data);
1753 enter_blocking_section();
1754 return r;
1757 #ifdef HAVE_DECL_CURLOPT_SEEKFUNCTION
1758 static int seekFunction_nolock(void *data,
1759 curl_off_t offset,
1760 int origin)
1762 CAMLparam0();
1763 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1764 Connection *conn = (Connection *)data;
1765 int result = 0;
1767 camlOffset = copy_int64(offset);
1769 if (origin == SEEK_SET)
1770 camlOrigin = Val_long(0);
1771 else if (origin == SEEK_CUR)
1772 camlOrigin = Val_long(1);
1773 else if (origin == SEEK_END)
1774 camlOrigin = Val_long(2);
1775 else
1776 camlOrigin = Val_long(0);
1778 camlResult = callback2(Field(conn->ocamlValues,
1779 OcamlSeekFunctionCallback),
1780 camlOffset,
1781 camlOrigin);
1783 result = Int_val(camlResult);
1785 CAMLreturnT(int, result);
1788 static int seekFunction(void *data,
1789 curl_off_t offset,
1790 int origin)
1792 int r;
1793 leave_blocking_section();
1794 r = seekFunction_nolock(data,offset,origin);
1795 enter_blocking_section();
1796 return r;
1799 #endif
1801 #ifdef HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
1802 static int openSocketFunction_nolock(void *data,
1803 curlsocktype purpose,
1804 struct curl_sockaddr *addr)
1806 CAMLparam0();
1807 Connection *conn = (Connection *)data;
1808 int sock = -1;
1810 sock = socket(addr->family, addr->socktype, addr->protocol);
1812 if (-1 != sock)
1814 /* FIXME windows */
1815 callback(Field(conn->ocamlValues, OcamlOpenSocketFunctionCallback), Val_int(sock));
1818 CAMLreturnT(int, sock);
1821 static int openSocketFunction(void *data,
1822 curlsocktype purpose,
1823 struct curl_sockaddr *address)
1825 int r;
1826 leave_blocking_section();
1827 r = openSocketFunction_nolock(data,purpose,address);
1828 enter_blocking_section();
1829 return r;
1832 #endif
1835 ** curl_global_init helper function
1838 CAMLprim value helper_curl_global_init(value initOption)
1840 CAMLparam1(initOption);
1842 switch (Long_val(initOption))
1844 case 0: /* CURLINIT_GLOBALALL */
1845 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1846 break;
1848 case 1: /* CURLINIT_GLOBALSSL */
1849 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1850 break;
1852 case 2: /* CURLINIT_GLOBALWIN32 */
1853 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1854 break;
1856 case 3: /* CURLINIT_GLOBALNOTHING */
1857 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1858 break;
1860 default:
1861 failwith("Invalid Initialization Option");
1862 break;
1865 /* Keep compiler happy, we should never get here due to failwith() */
1866 CAMLreturn(Val_unit);
1870 ** curl_global_cleanup helper function
1873 CAMLprim value helper_curl_global_cleanup(void)
1875 CAMLparam0();
1877 curl_global_cleanup();
1879 CAMLreturn(Val_unit);
1883 ** curl_easy_init helper function
1886 CAMLprim value helper_curl_easy_init(void)
1888 CAMLparam0();
1889 CAMLlocal1(result);
1891 Connection *conn = newConnection();
1893 result = caml_alloc(1, Abstract_tag);
1894 Field(result, 0) = (value)conn;
1896 CAMLreturn(result);
1899 CAMLprim value helper_curl_easy_reset(value conn)
1901 CAMLparam1(conn);
1902 Connection *connection = Connection_val(conn);
1904 checkConnection(connection);
1905 curl_easy_reset(connection->connection);
1906 resetOcamlValues(connection);
1908 CAMLreturn(Val_unit);
1912 ** curl_easy_setopt helper utility functions
1915 static void handleWriteFunction(Connection *conn, value option)
1917 CAMLparam1(option);
1918 CURLcode result = CURLE_OK;
1920 if (Tag_val(option) == Closure_tag)
1921 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1922 else
1923 failwith("Not a proper closure");
1925 result = curl_easy_setopt(conn->connection,
1926 CURLOPT_WRITEFUNCTION,
1927 writeFunction);
1929 if (result != CURLE_OK)
1930 raiseError(conn, result);
1932 result = curl_easy_setopt(conn->connection,
1933 CURLOPT_WRITEDATA,
1934 conn);
1936 if (result != CURLE_OK)
1937 raiseError(conn, result);
1939 CAMLreturn0;
1942 static void handleReadFunction(Connection *conn, value option)
1944 CAMLparam1(option);
1945 CURLcode result = CURLE_OK;
1947 if (Tag_val(option) == Closure_tag)
1948 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1949 else
1950 failwith("Not a proper closure");
1952 result = curl_easy_setopt(conn->connection,
1953 CURLOPT_READFUNCTION,
1954 readFunction);
1956 if (result != CURLE_OK)
1957 raiseError(conn, result);
1959 result = curl_easy_setopt(conn->connection,
1960 CURLOPT_READDATA,
1961 conn);
1963 if (result != CURLE_OK)
1964 raiseError(conn, result);
1966 CAMLreturn0;
1969 static void handleURL(Connection *conn, value option)
1971 CAMLparam1(option);
1972 CURLcode result = CURLE_OK;
1974 Store_field(conn->ocamlValues, OcamlURL, option);
1976 if (conn->url != NULL)
1977 free(conn->url);
1979 conn->url = strdup(String_val(option));
1981 result = curl_easy_setopt(conn->connection,
1982 CURLOPT_URL,
1983 conn->url);
1985 if (result != CURLE_OK)
1986 raiseError(conn, result);
1988 CAMLreturn0;
1991 static void handleInFileSize(Connection *conn, value option)
1993 CAMLparam1(option);
1994 CURLcode result = CURLE_OK;
1996 result = curl_easy_setopt(conn->connection,
1997 CURLOPT_INFILESIZE,
1998 Long_val(option));
2000 if (result != CURLE_OK)
2001 raiseError(conn, result);
2003 CAMLreturn0;
2006 static void handleProxy(Connection *conn, value option)
2008 CAMLparam1(option);
2009 CURLcode result = CURLE_OK;
2011 Store_field(conn->ocamlValues, OcamlProxy, option);
2013 if (conn->proxy != NULL)
2014 free(conn->proxy);
2016 conn->proxy = strdup(String_val(option));
2018 result = curl_easy_setopt(conn->connection,
2019 CURLOPT_PROXY,
2020 conn->proxy);
2022 if (result != CURLE_OK)
2023 raiseError(conn, result);
2025 CAMLreturn0;
2028 static void handleProxyPort(Connection *conn, value option)
2030 CAMLparam1(option);
2031 CURLcode result = CURLE_OK;
2033 result = curl_easy_setopt(conn->connection,
2034 CURLOPT_PROXYPORT,
2035 Long_val(option));
2037 if (result != CURLE_OK)
2038 raiseError(conn, result);
2040 CAMLreturn0;
2043 static void handleHTTPProxyTunnel(Connection *conn, value option)
2045 CAMLparam1(option);
2046 CURLcode result = CURLE_OK;
2048 result = curl_easy_setopt(conn->connection,
2049 CURLOPT_HTTPPROXYTUNNEL,
2050 Bool_val(option));
2052 if (result != CURLE_OK)
2053 raiseError(conn, result);
2055 CAMLreturn0;
2058 static void handleVerbose(Connection *conn, value option)
2060 CAMLparam1(option);
2061 CURLcode result = CURLE_OK;
2063 result = curl_easy_setopt(conn->connection,
2064 CURLOPT_VERBOSE,
2065 Bool_val(option));
2067 if (result != CURLE_OK)
2068 raiseError(conn, result);
2070 CAMLreturn0;
2073 static void handleHeader(Connection *conn, value option)
2075 CAMLparam1(option);
2076 CURLcode result = CURLE_OK;
2078 result = curl_easy_setopt(conn->connection,
2079 CURLOPT_HEADER,
2080 Bool_val(option));
2082 if (result != CURLE_OK)
2083 raiseError(conn, result);
2085 CAMLreturn0;
2088 static void handleNoProgress(Connection *conn, value option)
2090 CAMLparam1(option);
2091 CURLcode result = CURLE_OK;
2093 result = curl_easy_setopt(conn->connection,
2094 CURLOPT_NOPROGRESS,
2095 Bool_val(option));
2097 if (result != CURLE_OK)
2098 raiseError(conn, result);
2100 CAMLreturn0;
2103 static void handleNoSignal(Connection *conn, value option)
2105 #if HAVE_DECL_CURLOPT_NOSIGNAL
2106 CAMLparam1(option);
2107 CURLcode result = CURLE_OK;
2109 result = curl_easy_setopt(conn->connection,
2110 CURLOPT_NOSIGNAL,
2111 Bool_val(option));
2113 if (result != CURLE_OK)
2114 raiseError(conn, result);
2116 CAMLreturn0;
2117 #else
2118 #warning "libcurl does not implement CURLOPT_NOSIGNAL"
2119 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2120 #endif
2123 static void handleNoBody(Connection *conn, value option)
2125 CAMLparam1(option);
2126 CURLcode result = CURLE_OK;
2128 result = curl_easy_setopt(conn->connection,
2129 CURLOPT_NOBODY,
2130 Bool_val(option));
2132 if (result != CURLE_OK)
2133 raiseError(conn, result);
2135 CAMLreturn0;
2138 static void handleFailOnError(Connection *conn, value option)
2140 CAMLparam1(option);
2141 CURLcode result = CURLE_OK;
2143 result = curl_easy_setopt(conn->connection,
2144 CURLOPT_FAILONERROR,
2145 Bool_val(option));
2147 if (result != CURLE_OK)
2148 raiseError(conn, result);
2150 CAMLreturn0;
2153 static void handleUpload(Connection *conn, value option)
2155 CAMLparam1(option);
2156 CURLcode result = CURLE_OK;
2158 result = curl_easy_setopt(conn->connection,
2159 CURLOPT_UPLOAD,
2160 Bool_val(option));
2162 if (result != CURLE_OK)
2163 raiseError(conn, result);
2165 CAMLreturn0;
2168 static void handlePost(Connection *conn, value option)
2170 CAMLparam1(option);
2171 CURLcode result = CURLE_OK;
2173 result = curl_easy_setopt(conn->connection,
2174 CURLOPT_POST,
2175 Bool_val(option));
2177 if (result != CURLE_OK)
2178 raiseError(conn, result);
2180 CAMLreturn0;
2183 static void handleFTPListOnly(Connection *conn, value option)
2185 CAMLparam1(option);
2186 CURLcode result = CURLE_OK;
2188 result = curl_easy_setopt(conn->connection,
2189 CURLOPT_FTPLISTONLY,
2190 Bool_val(option));
2192 if (result != CURLE_OK)
2193 raiseError(conn, result);
2195 CAMLreturn0;
2198 static void handleFTPAppend(Connection *conn, value option)
2200 CAMLparam1(option);
2201 CURLcode result = CURLE_OK;
2203 result = curl_easy_setopt(conn->connection,
2204 CURLOPT_FTPAPPEND,
2205 Bool_val(option));
2207 if (result != CURLE_OK)
2208 raiseError(conn, result);
2210 CAMLreturn0;
2213 static void handleNETRC(Connection *conn, value option)
2215 CAMLparam1(option);
2216 CURLcode result = CURLE_OK;
2217 long netrc;
2219 switch (Long_val(option))
2221 case 0: /* CURL_NETRC_OPTIONAL */
2222 netrc = CURL_NETRC_OPTIONAL;
2223 break;
2225 case 1:/* CURL_NETRC_IGNORED */
2226 netrc = CURL_NETRC_IGNORED;
2227 break;
2229 case 2: /* CURL_NETRC_REQUIRED */
2230 netrc = CURL_NETRC_REQUIRED;
2231 break;
2233 default:
2234 failwith("Invalid NETRC Option");
2235 break;
2238 result = curl_easy_setopt(conn->connection,
2239 CURLOPT_NETRC,
2240 netrc);
2242 if (result != CURLE_OK)
2243 raiseError(conn, result);
2245 CAMLreturn0;
2248 static void handleEncoding(Connection *conn, value option)
2250 #if HAVE_DECL_CURLOPT_ENCODING
2251 CAMLparam1(option);
2252 CURLcode result = CURLE_OK;
2254 switch (Long_val(option))
2256 case 0: /* CURL_ENCODING_NONE */
2257 result = curl_easy_setopt(conn->connection,
2258 CURLOPT_ENCODING,
2259 "identity");
2260 break;
2262 case 1: /* CURL_ENCODING_DEFLATE */
2263 result = curl_easy_setopt(conn->connection,
2264 CURLOPT_ENCODING,
2265 "deflate");
2266 break;
2268 case 2: /* CURL_ENCODING_GZIP */
2269 result = curl_easy_setopt(conn->connection,
2270 CURLOPT_ENCODING,
2271 "gzip");
2272 break;
2274 case 3: /* CURL_ENCODING_ANY */
2275 result = curl_easy_setopt(conn->connection,
2276 CURLOPT_ENCODING,
2277 "");
2278 break;
2280 default:
2281 failwith("Invalid Encoding Option");
2282 break;
2285 if (result != CURLE_OK)
2286 raiseError(conn, result);
2288 CAMLreturn0;
2289 #else
2290 #warning "libcurl does not implement CURLOPT_ENCODING"
2291 failwith("libcurl does not implement CURLOPT_ENCODING");
2292 #endif
2295 static void handleFollowLocation(Connection *conn, value option)
2297 CAMLparam1(option);
2298 CURLcode result = CURLE_OK;
2300 result = curl_easy_setopt(conn->connection,
2301 CURLOPT_FOLLOWLOCATION,
2302 Bool_val(option));
2304 if (result != CURLE_OK)
2305 raiseError(conn, result);
2307 CAMLreturn0;
2310 static void handleTransferText(Connection *conn, value option)
2312 CAMLparam1(option);
2313 CURLcode result = CURLE_OK;
2315 result = curl_easy_setopt(conn->connection,
2316 CURLOPT_TRANSFERTEXT,
2317 Bool_val(option));
2319 if (result != CURLE_OK)
2320 raiseError(conn, result);
2322 CAMLreturn0;
2325 static void handlePut(Connection *conn, value option)
2327 CAMLparam1(option);
2328 CURLcode result = CURLE_OK;
2330 result = curl_easy_setopt(conn->connection,
2331 CURLOPT_PUT,
2332 Bool_val(option));
2334 if (result != CURLE_OK)
2335 raiseError(conn, result);
2337 CAMLreturn0;
2340 static void handleUserPwd(Connection *conn, value option)
2342 CAMLparam1(option);
2343 CURLcode result = CURLE_OK;
2345 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2347 if (conn->userPwd != NULL)
2348 free(conn->userPwd);
2350 conn->userPwd = strdup(String_val(option));
2352 result = curl_easy_setopt(conn->connection,
2353 CURLOPT_USERPWD,
2354 conn->userPwd);
2356 if (result != CURLE_OK)
2357 raiseError(conn, result);
2359 CAMLreturn0;
2362 static void handleProxyUserPwd(Connection *conn, value option)
2364 CAMLparam1(option);
2365 CURLcode result = CURLE_OK;
2367 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2369 if (conn->proxyUserPwd != NULL)
2370 free(conn->proxyUserPwd);
2372 conn->proxyUserPwd = strdup(String_val(option));
2374 result = curl_easy_setopt(conn->connection,
2375 CURLOPT_PROXYUSERPWD,
2376 conn->proxyUserPwd);
2378 if (result != CURLE_OK)
2379 raiseError(conn, result);
2381 CAMLreturn0;
2384 static void handleRange(Connection *conn, value option)
2386 CAMLparam1(option);
2387 CURLcode result = CURLE_OK;
2389 Store_field(conn->ocamlValues, OcamlRange, option);
2391 if (conn->range != NULL)
2392 free(conn->range);
2394 conn->range = strdup(String_val(option));
2396 result = curl_easy_setopt(conn->connection,
2397 CURLOPT_RANGE,
2398 conn->range);
2400 if (result != CURLE_OK)
2401 raiseError(conn, result);
2403 CAMLreturn0;
2406 static void handleErrorBuffer(Connection *conn, value option)
2408 CAMLparam1(option);
2409 CURLcode result = CURLE_OK;
2411 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2413 if (conn->errorBuffer != NULL)
2414 free(conn->errorBuffer);
2416 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2418 result = curl_easy_setopt(conn->connection,
2419 CURLOPT_ERRORBUFFER,
2420 conn->errorBuffer);
2422 if (result != CURLE_OK)
2423 raiseError(conn, result);
2425 CAMLreturn0;
2428 static void handleTimeout(Connection *conn, value option)
2430 CAMLparam1(option);
2431 CURLcode result = CURLE_OK;
2433 result = curl_easy_setopt(conn->connection,
2434 CURLOPT_TIMEOUT,
2435 Long_val(option));
2437 if (result != CURLE_OK)
2438 raiseError(conn, result);
2440 CAMLreturn0;
2443 static void handlePostFields(Connection *conn, value option)
2445 CAMLparam1(option);
2446 CURLcode result = CURLE_OK;
2448 Store_field(conn->ocamlValues, OcamlPostFields, option);
2450 if (conn->postFields != NULL)
2451 free(conn->postFields);
2453 conn->postFields = malloc(string_length(option)+1);
2454 memcpy(conn->postFields, String_val(option), string_length(option)+1);
2456 result = curl_easy_setopt(conn->connection,
2457 CURLOPT_POSTFIELDS,
2458 conn->postFields);
2460 if (result != CURLE_OK)
2461 raiseError(conn, result);
2463 CAMLreturn0;
2466 static void handlePostFieldSize(Connection *conn, value option)
2468 CAMLparam1(option);
2469 CURLcode result = CURLE_OK;
2471 result = curl_easy_setopt(conn->connection,
2472 CURLOPT_POSTFIELDSIZE,
2473 Long_val(option));
2475 if (result != CURLE_OK)
2476 raiseError(conn, result);
2478 CAMLreturn0;
2481 static void handleReferer(Connection *conn, value option)
2483 CAMLparam1(option);
2484 CURLcode result = CURLE_OK;
2486 Store_field(conn->ocamlValues, OcamlReferer, option);
2488 if (conn->referer != NULL)
2489 free(conn->referer);
2491 conn->referer = strdup(String_val(option));
2493 result = curl_easy_setopt(conn->connection,
2494 CURLOPT_REFERER,
2495 conn->referer);
2497 if (result != CURLE_OK)
2498 raiseError(conn, result);
2500 CAMLreturn0;
2503 static void handleUserAgent(Connection *conn, value option)
2505 CAMLparam1(option);
2506 CURLcode result = CURLE_OK;
2508 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2510 if (conn->userAgent != NULL)
2511 free(conn->userAgent);
2513 conn->userAgent = strdup(String_val(option));
2515 result = curl_easy_setopt(conn->connection,
2516 CURLOPT_USERAGENT,
2517 conn->userAgent);
2519 if (result != CURLE_OK)
2520 raiseError(conn, result);
2522 CAMLreturn0;
2525 static void handleFTPPort(Connection *conn, value option)
2527 CAMLparam1(option);
2528 CURLcode result = CURLE_OK;
2530 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2532 if (conn->ftpPort != NULL)
2533 free(conn->ftpPort);
2535 conn->ftpPort = strdup(String_val(option));
2537 result = curl_easy_setopt(conn->connection,
2538 CURLOPT_FTPPORT,
2539 conn->ftpPort);
2541 if (result != CURLE_OK)
2542 raiseError(conn, result);
2544 CAMLreturn0;
2547 static void handleLowSpeedLimit(Connection *conn, value option)
2549 CAMLparam1(option);
2550 CURLcode result = CURLE_OK;
2552 result = curl_easy_setopt(conn->connection,
2553 CURLOPT_LOW_SPEED_LIMIT,
2554 Long_val(option));
2556 if (result != CURLE_OK)
2557 raiseError(conn, result);
2559 CAMLreturn0;
2562 static void handleLowSpeedTime(Connection *conn, value option)
2564 CAMLparam1(option);
2565 CURLcode result = CURLE_OK;
2567 result = curl_easy_setopt(conn->connection,
2568 CURLOPT_LOW_SPEED_TIME,
2569 Long_val(option));
2571 if (result != CURLE_OK)
2572 raiseError(conn, result);
2574 CAMLreturn0;
2577 static void handleResumeFrom(Connection *conn, value option)
2579 CAMLparam1(option);
2580 CURLcode result = CURLE_OK;
2582 result = curl_easy_setopt(conn->connection,
2583 CURLOPT_RESUME_FROM,
2584 Long_val(option));
2586 if (result != CURLE_OK)
2587 raiseError(conn, result);
2589 CAMLreturn0;
2592 static void handleCookie(Connection *conn, value option)
2594 CAMLparam1(option);
2595 CURLcode result = CURLE_OK;
2597 Store_field(conn->ocamlValues, OcamlCookie, option);
2599 if (conn->cookie != NULL)
2600 free(conn->cookie);
2602 conn->cookie = strdup(String_val(option));
2604 result = curl_easy_setopt(conn->connection,
2605 CURLOPT_COOKIE,
2606 conn->cookie);
2608 if (result != CURLE_OK)
2609 raiseError(conn, result);
2611 CAMLreturn0;
2614 static void handleHTTPHeader(Connection *conn, value option)
2616 CAMLparam1(option);
2617 CAMLlocal1(listIter);
2618 CURLcode result = CURLE_OK;
2620 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2622 free_curl_slist(conn->httpHeader);
2623 conn->httpHeader = NULL;
2625 listIter = option;
2627 while (!Is_long(listIter))
2629 conn->httpHeader = curl_slist_append(conn->httpHeader, String_val(Field(listIter, 0)));
2631 listIter = Field(listIter, 1);
2634 result = curl_easy_setopt(conn->connection,
2635 CURLOPT_HTTPHEADER,
2636 conn->httpHeader);
2638 if (result != CURLE_OK)
2639 raiseError(conn, result);
2641 CAMLreturn0;
2644 static void handleHTTPPost(Connection *conn, value option)
2646 CAMLparam1(option);
2647 CAMLlocal3(listIter, formItem, contentType);
2648 CURLcode result = CURLE_OK;
2649 char *str1, *str2, *str3, *str4;
2651 listIter = option;
2653 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2655 if (conn->httpPostFirst != NULL)
2656 curl_formfree(conn->httpPostFirst);
2658 conn->httpPostFirst = NULL;
2659 conn->httpPostLast = NULL;
2661 free_curl_slist(conn->httpPostStrings);
2662 conn->httpPostStrings = NULL;
2664 while (!Is_long(listIter))
2666 formItem = Field(listIter, 0);
2668 switch (Tag_val(formItem))
2670 case 0: /* CURLFORM_CONTENT */
2671 if (Wosize_val(formItem) < 3)
2673 failwith("Incorrect CURLFORM_CONTENT parameters");
2676 if (Is_long(Field(formItem, 2)) &&
2677 Long_val(Field(formItem, 2)) == 0)
2679 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2680 memcpy(str1,
2681 String_val(Field(formItem, 0)),
2682 string_length(Field(formItem, 0)));
2683 str1[string_length(Field(formItem, 0))] = 0;
2684 conn->httpPostStrings =
2685 curl_slist_append(conn->httpPostStrings, str1);
2687 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2688 memcpy(str2,
2689 String_val(Field(formItem, 1)),
2690 string_length(Field(formItem, 1)));
2691 str2[string_length(Field(formItem, 1))] = 0;
2692 conn->httpPostStrings =
2693 curl_slist_append(conn->httpPostStrings, str2);
2695 curl_formadd(&conn->httpPostFirst,
2696 &conn->httpPostLast,
2697 CURLFORM_PTRNAME,
2698 str1,
2699 CURLFORM_NAMELENGTH,
2700 string_length(Field(formItem, 0)),
2701 CURLFORM_PTRCONTENTS,
2702 str2,
2703 CURLFORM_CONTENTSLENGTH,
2704 string_length(Field(formItem, 1)),
2705 CURLFORM_END);
2707 else if (Is_block(Field(formItem, 2)))
2709 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2710 memcpy(str1,
2711 String_val(Field(formItem, 0)),
2712 string_length(Field(formItem, 0)));
2713 str1[string_length(Field(formItem, 0))] = 0;
2714 conn->httpPostStrings =
2715 curl_slist_append(conn->httpPostStrings, str1);
2717 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2718 memcpy(str2,
2719 String_val(Field(formItem, 1)),
2720 string_length(Field(formItem, 1)));
2721 str2[string_length(Field(formItem, 1))] = 0;
2722 conn->httpPostStrings =
2723 curl_slist_append(conn->httpPostStrings, str2);
2725 contentType = Field(formItem, 2);
2727 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2728 memcpy(str3,
2729 String_val(Field(contentType, 0)),
2730 string_length(Field(contentType, 0)));
2731 str3[string_length(Field(contentType, 0))] = 0;
2732 conn->httpPostStrings =
2733 curl_slist_append(conn->httpPostStrings, str3);
2735 curl_formadd(&conn->httpPostFirst,
2736 &conn->httpPostLast,
2737 CURLFORM_PTRNAME,
2738 str1,
2739 CURLFORM_NAMELENGTH,
2740 string_length(Field(formItem, 0)),
2741 CURLFORM_PTRCONTENTS,
2742 str2,
2743 CURLFORM_CONTENTSLENGTH,
2744 string_length(Field(formItem, 1)),
2745 CURLFORM_CONTENTTYPE,
2746 str3,
2747 CURLFORM_END);
2749 else
2751 failwith("Incorrect CURLFORM_CONTENT parameters");
2753 break;
2755 case 1: /* CURLFORM_FILECONTENT */
2756 if (Wosize_val(formItem) < 3)
2758 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2761 if (Is_long(Field(formItem, 2)) &&
2762 Long_val(Field(formItem, 2)) == 0)
2764 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2765 memcpy(str1,
2766 String_val(Field(formItem, 0)),
2767 string_length(Field(formItem, 0)));
2768 str1[string_length(Field(formItem, 0))] = 0;
2769 conn->httpPostStrings =
2770 curl_slist_append(conn->httpPostStrings, str1);
2772 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2773 memcpy(str2,
2774 String_val(Field(formItem, 1)),
2775 string_length(Field(formItem, 1)));
2776 str2[string_length(Field(formItem, 1))] = 0;
2777 conn->httpPostStrings =
2778 curl_slist_append(conn->httpPostStrings, str2);
2780 curl_formadd(&conn->httpPostFirst,
2781 &conn->httpPostLast,
2782 CURLFORM_PTRNAME,
2783 str1,
2784 CURLFORM_NAMELENGTH,
2785 string_length(Field(formItem, 0)),
2786 CURLFORM_FILECONTENT,
2787 str2,
2788 CURLFORM_END);
2790 else if (Is_block(Field(formItem, 2)))
2792 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2793 memcpy(str1,
2794 String_val(Field(formItem, 0)),
2795 string_length(Field(formItem, 0)));
2796 str1[string_length(Field(formItem, 0))] = 0;
2797 conn->httpPostStrings =
2798 curl_slist_append(conn->httpPostStrings, str1);
2800 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2801 memcpy(str2,
2802 String_val(Field(formItem, 1)),
2803 string_length(Field(formItem, 1)));
2804 str2[string_length(Field(formItem, 1))] = 0;
2805 conn->httpPostStrings =
2806 curl_slist_append(conn->httpPostStrings, str2);
2808 contentType = Field(formItem, 2);
2810 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2811 memcpy(str3,
2812 String_val(Field(contentType, 0)),
2813 string_length(Field(contentType, 0)));
2814 str3[string_length(Field(contentType, 0))] = 0;
2815 conn->httpPostStrings =
2816 curl_slist_append(conn->httpPostStrings, str3);
2818 curl_formadd(&conn->httpPostFirst,
2819 &conn->httpPostLast,
2820 CURLFORM_PTRNAME,
2821 str1,
2822 CURLFORM_NAMELENGTH,
2823 string_length(Field(formItem, 0)),
2824 CURLFORM_FILECONTENT,
2825 str2,
2826 CURLFORM_CONTENTTYPE,
2827 str3,
2828 CURLFORM_END);
2830 else
2832 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2834 break;
2836 case 2: /* CURLFORM_FILE */
2837 if (Wosize_val(formItem) < 3)
2839 failwith("Incorrect CURLFORM_FILE parameters");
2842 if (Is_long(Field(formItem, 2)) &&
2843 Long_val(Field(formItem, 2)) == 0)
2845 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2846 memcpy(str1,
2847 String_val(Field(formItem, 0)),
2848 string_length(Field(formItem, 0)));
2849 str1[string_length(Field(formItem, 0))] = 0;
2850 conn->httpPostStrings =
2851 curl_slist_append(conn->httpPostStrings, str1);
2853 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2854 memcpy(str2,
2855 String_val(Field(formItem, 1)),
2856 string_length(Field(formItem, 1)));
2857 str2[string_length(Field(formItem, 1))] = 0;
2858 conn->httpPostStrings =
2859 curl_slist_append(conn->httpPostStrings, str2);
2861 curl_formadd(&conn->httpPostFirst,
2862 &conn->httpPostLast,
2863 CURLFORM_PTRNAME,
2864 str1,
2865 CURLFORM_NAMELENGTH,
2866 string_length(Field(formItem, 0)),
2867 CURLFORM_FILE,
2868 str2,
2869 CURLFORM_END);
2871 else if (Is_block(Field(formItem, 2)))
2873 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2874 memcpy(str1,
2875 String_val(Field(formItem, 0)),
2876 string_length(Field(formItem, 0)));
2877 str1[string_length(Field(formItem, 0))] = 0;
2878 conn->httpPostStrings =
2879 curl_slist_append(conn->httpPostStrings, str1);
2881 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2882 memcpy(str2,
2883 String_val(Field(formItem, 1)),
2884 string_length(Field(formItem, 1)));
2885 str2[string_length(Field(formItem, 1))] = 0;
2886 conn->httpPostStrings =
2887 curl_slist_append(conn->httpPostStrings, str2);
2889 contentType = Field(formItem, 2);
2891 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2892 memcpy(str3,
2893 String_val(Field(contentType, 0)),
2894 string_length(Field(contentType, 0)));
2895 str3[string_length(Field(contentType, 0))] = 0;
2896 conn->httpPostStrings =
2897 curl_slist_append(conn->httpPostStrings, str3);
2899 curl_formadd(&conn->httpPostFirst,
2900 &conn->httpPostLast,
2901 CURLFORM_PTRNAME,
2902 str1,
2903 CURLFORM_NAMELENGTH,
2904 string_length(Field(formItem, 0)),
2905 CURLFORM_FILE,
2906 str2,
2907 CURLFORM_CONTENTTYPE,
2908 str3,
2909 CURLFORM_END);
2911 else
2913 failwith("Incorrect CURLFORM_FILE parameters");
2915 break;
2917 case 3: /* CURLFORM_BUFFER */
2918 if (Wosize_val(formItem) < 4)
2920 failwith("Incorrect CURLFORM_BUFFER parameters");
2923 if (Is_long(Field(formItem, 3)) &&
2924 Long_val(Field(formItem, 3)) == 0)
2926 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2927 memcpy(str1,
2928 String_val(Field(formItem, 0)),
2929 string_length(Field(formItem, 0)));
2930 str1[string_length(Field(formItem, 0))] = 0;
2931 conn->httpPostStrings =
2932 curl_slist_append(conn->httpPostStrings, str1);
2934 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2935 memcpy(str2,
2936 String_val(Field(formItem, 1)),
2937 string_length(Field(formItem, 1)));
2938 str2[string_length(Field(formItem, 1))] = 0;
2939 conn->httpPostStrings =
2940 curl_slist_append(conn->httpPostStrings, str2);
2942 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2943 memcpy(str3,
2944 String_val(Field(formItem, 2)),
2945 string_length(Field(formItem, 2)));
2946 str3[string_length(Field(formItem, 2))] = 0;
2947 conn->httpPostStrings =
2948 curl_slist_append(conn->httpPostStrings, str3);
2950 curl_formadd(&conn->httpPostFirst,
2951 &conn->httpPostLast,
2952 CURLFORM_PTRNAME,
2953 str1,
2954 CURLFORM_NAMELENGTH,
2955 string_length(Field(formItem, 0)),
2956 CURLFORM_BUFFER,
2957 str2,
2958 CURLFORM_BUFFERPTR,
2959 str3,
2960 CURLFORM_BUFFERLENGTH,
2961 string_length(Field(formItem, 2)),
2962 CURLFORM_END);
2964 else if (Is_block(Field(formItem, 3)))
2966 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2967 memcpy(str1,
2968 String_val(Field(formItem, 0)),
2969 string_length(Field(formItem, 0)));
2970 str1[string_length(Field(formItem, 0))] = 0;
2971 conn->httpPostStrings =
2972 curl_slist_append(conn->httpPostStrings, str1);
2974 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2975 memcpy(str2,
2976 String_val(Field(formItem, 1)),
2977 string_length(Field(formItem, 1)));
2978 str2[string_length(Field(formItem, 1))] = 0;
2979 conn->httpPostStrings =
2980 curl_slist_append(conn->httpPostStrings, str2);
2982 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2983 memcpy(str3,
2984 String_val(Field(formItem, 2)),
2985 string_length(Field(formItem, 2)));
2986 str3[string_length(Field(formItem, 2))] = 0;
2987 conn->httpPostStrings =
2988 curl_slist_append(conn->httpPostStrings, str3);
2990 contentType = Field(formItem, 3);
2992 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
2993 memcpy(str4,
2994 String_val(Field(contentType, 0)),
2995 string_length(Field(contentType, 0)));
2996 str4[string_length(Field(contentType, 0))] = 0;
2997 conn->httpPostStrings =
2998 curl_slist_append(conn->httpPostStrings, str4);
3000 curl_formadd(&conn->httpPostFirst,
3001 &conn->httpPostLast,
3002 CURLFORM_PTRNAME,
3003 str1,
3004 CURLFORM_NAMELENGTH,
3005 string_length(Field(formItem, 0)),
3006 CURLFORM_BUFFER,
3007 str2,
3008 CURLFORM_BUFFERPTR,
3009 str3,
3010 CURLFORM_BUFFERLENGTH,
3011 string_length(Field(formItem, 2)),
3012 CURLFORM_CONTENTTYPE,
3013 str4,
3014 CURLFORM_END);
3016 else
3018 failwith("Incorrect CURLFORM_BUFFER parameters");
3020 break;
3023 listIter = Field(listIter, 1);
3026 result = curl_easy_setopt(conn->connection,
3027 CURLOPT_HTTPPOST,
3028 conn->httpPostFirst);
3030 if (result != CURLE_OK)
3031 raiseError(conn, result);
3033 CAMLreturn0;
3036 static void handleSSLCert(Connection *conn, value option)
3038 CAMLparam1(option);
3039 CURLcode result = CURLE_OK;
3041 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3043 if (conn->sslCert != NULL)
3044 free(conn->sslCert);
3046 conn->sslCert = strdup(String_val(option));
3048 result = curl_easy_setopt(conn->connection,
3049 CURLOPT_SSLCERT,
3050 conn->sslCert);
3052 if (result != CURLE_OK)
3053 raiseError(conn, result);
3055 CAMLreturn0;
3058 static void handleSSLCertType(Connection *conn, value option)
3060 CAMLparam1(option);
3061 CURLcode result = CURLE_OK;
3063 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3065 if (conn->sslCertType != NULL)
3066 free(conn->sslCertType);
3068 conn->sslCertType = strdup(String_val(option));
3070 result = curl_easy_setopt(conn->connection,
3071 CURLOPT_SSLCERTTYPE,
3072 conn->sslCertType);
3074 if (result != CURLE_OK)
3075 raiseError(conn, result);
3077 CAMLreturn0;
3080 static void handleSSLCertPasswd(Connection *conn, value option)
3082 CAMLparam1(option);
3083 CURLcode result = CURLE_OK;
3085 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3087 if (conn->sslCertPasswd != NULL)
3088 free(conn->sslCertPasswd);
3090 conn->sslCertPasswd = strdup(String_val(option));
3092 result = curl_easy_setopt(conn->connection,
3093 CURLOPT_SSLCERTPASSWD,
3094 conn->sslCertPasswd);
3096 if (result != CURLE_OK)
3097 raiseError(conn, result);
3099 CAMLreturn0;
3102 static void handleSSLKey(Connection *conn, value option)
3104 CAMLparam1(option);
3105 CURLcode result = CURLE_OK;
3107 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3109 if (conn->sslKey != NULL)
3110 free(conn->sslKey);
3112 conn->sslKey = strdup(String_val(option));
3114 result = curl_easy_setopt(conn->connection,
3115 CURLOPT_SSLKEY,
3116 conn->sslKey);
3118 if (result != CURLE_OK)
3119 raiseError(conn, result);
3121 CAMLreturn0;
3124 static void handleSSLKeyType(Connection *conn, value option)
3126 CAMLparam1(option);
3127 CURLcode result = CURLE_OK;
3129 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3131 if (conn->sslKeyType != NULL)
3132 free(conn->sslKeyType);
3134 conn->sslKeyType = strdup(String_val(option));
3136 result = curl_easy_setopt(conn->connection,
3137 CURLOPT_SSLKEYTYPE,
3138 conn->sslKeyType);
3140 if (result != CURLE_OK)
3141 raiseError(conn, result);
3143 CAMLreturn0;
3146 static void handleSSLKeyPasswd(Connection *conn, value option)
3148 CAMLparam1(option);
3149 CURLcode result = CURLE_OK;
3151 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3153 if (conn->sslKeyPasswd != NULL)
3154 free(conn->sslKeyPasswd);
3156 conn->sslKeyPasswd = strdup(String_val(option));
3158 result = curl_easy_setopt(conn->connection,
3159 CURLOPT_SSLKEYPASSWD,
3160 conn->sslKeyPasswd);
3162 if (result != CURLE_OK)
3163 raiseError(conn, result);
3165 CAMLreturn0;
3168 static void handleSSLEngine(Connection *conn, value option)
3170 CAMLparam1(option);
3171 CURLcode result = CURLE_OK;
3173 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3175 if (conn->sslEngine != NULL)
3176 free(conn->sslEngine);
3178 conn->sslEngine = strdup(String_val(option));
3180 result = curl_easy_setopt(conn->connection,
3181 CURLOPT_SSLENGINE,
3182 conn->sslEngine);
3184 if (result != CURLE_OK)
3185 raiseError(conn, result);
3187 CAMLreturn0;
3190 static void handleSSLEngineDefault(Connection *conn, value option)
3192 CAMLparam1(option);
3193 CURLcode result = CURLE_OK;
3195 result = curl_easy_setopt(conn->connection,
3196 CURLOPT_SSLENGINE_DEFAULT,
3197 Bool_val(option));
3199 if (result != CURLE_OK)
3200 raiseError(conn, result);
3202 CAMLreturn0;
3205 static void handleCRLF(Connection *conn, value option)
3207 CAMLparam1(option);
3208 CURLcode result = CURLE_OK;
3210 result = curl_easy_setopt(conn->connection,
3211 CURLOPT_CRLF,
3212 Bool_val(option));
3214 if (result != CURLE_OK)
3215 raiseError(conn, result);
3217 CAMLreturn0;
3220 static void handleQuote(Connection *conn, value option)
3222 CAMLparam1(option);
3223 CAMLlocal1(listIter);
3224 CURLcode result = CURLE_OK;
3226 Store_field(conn->ocamlValues, OcamlQuote, option);
3228 free_curl_slist(conn->quote);
3229 conn->quote = NULL;
3231 listIter = option;
3233 while (!Is_long(listIter))
3235 conn->quote = curl_slist_append(conn->quote, String_val(Field(listIter, 0)));
3237 listIter = Field(listIter, 1);
3240 result = curl_easy_setopt(conn->connection,
3241 CURLOPT_QUOTE,
3242 conn->quote);
3244 if (result != CURLE_OK)
3245 raiseError(conn, result);
3247 CAMLreturn0;
3250 static void handlePostQuote(Connection *conn, value option)
3252 CAMLparam1(option);
3253 CAMLlocal1(listIter);
3254 CURLcode result = CURLE_OK;
3256 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3258 free_curl_slist(conn->postQuote);
3259 conn->postQuote = NULL;
3261 listIter = option;
3263 while (!Is_long(listIter))
3265 conn->postQuote = curl_slist_append(conn->postQuote, String_val(Field(listIter, 0)));
3267 listIter = Field(listIter, 1);
3270 result = curl_easy_setopt(conn->connection,
3271 CURLOPT_POSTQUOTE,
3272 conn->postQuote);
3274 if (result != CURLE_OK)
3275 raiseError(conn, result);
3277 CAMLreturn0;
3280 static void handleHeaderFunction(Connection *conn, value option)
3282 CAMLparam1(option);
3283 CURLcode result = CURLE_OK;
3285 if (Tag_val(option) == Closure_tag)
3286 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3287 else
3288 failwith("Not a proper closure");
3290 result = curl_easy_setopt(conn->connection,
3291 CURLOPT_HEADERFUNCTION,
3292 headerFunction);
3294 if (result != CURLE_OK)
3295 raiseError(conn, result);
3297 result = curl_easy_setopt(conn->connection,
3298 CURLOPT_WRITEHEADER,
3299 conn);
3301 if (result != CURLE_OK)
3302 raiseError(conn, result);
3304 CAMLreturn0;
3307 static void handleCookieFile(Connection *conn, value option)
3309 CAMLparam1(option);
3310 CURLcode result = CURLE_OK;
3312 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3314 if (conn->cookieFile != NULL)
3315 free(conn->cookieFile);
3317 conn->cookieFile = strdup(String_val(option));
3319 result = curl_easy_setopt(conn->connection,
3320 CURLOPT_COOKIEFILE,
3321 conn->cookieFile);
3323 if (result != CURLE_OK)
3324 raiseError(conn, result);
3326 CAMLreturn0;
3329 static void handleSSLVersion(Connection *conn, value option)
3331 CAMLparam1(option);
3332 CURLcode result = CURLE_OK;
3334 result = curl_easy_setopt(conn->connection,
3335 CURLOPT_SSLVERSION,
3336 Long_val(option));
3338 if (result != CURLE_OK)
3339 raiseError(conn, result);
3341 CAMLreturn0;
3344 static void handleTimeCondition(Connection *conn, value option)
3346 CAMLparam1(option);
3347 CURLcode result = CURLE_OK;
3349 switch (Long_val(option))
3351 case 0: /* TIMECOND_IFMODSINCE */
3352 result = curl_easy_setopt(conn->connection,
3353 CURLOPT_TIMECONDITION,
3354 CURL_TIMECOND_IFMODSINCE);
3355 break;
3357 case 1: /* TIMECOND_IFUNMODSINCE */
3358 result = curl_easy_setopt(conn->connection,
3359 CURLOPT_TIMECONDITION,
3360 CURL_TIMECOND_IFUNMODSINCE);
3361 break;
3363 default:
3364 failwith("Invalid TIMECOND Option");
3365 break;
3368 if (result != CURLE_OK)
3369 raiseError(conn, result);
3371 CAMLreturn0;
3374 static void handleTimeValue(Connection *conn, value option)
3376 CAMLparam1(option);
3377 CURLcode result = CURLE_OK;
3379 result = curl_easy_setopt(conn->connection,
3380 CURLOPT_TIMEVALUE,
3381 Int32_val(option));
3383 if (result != CURLE_OK)
3384 raiseError(conn, result);
3386 CAMLreturn0;
3389 static void handleCustomRequest(Connection *conn, value option)
3391 CAMLparam1(option);
3392 CURLcode result = CURLE_OK;
3394 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3396 if (conn->customRequest != NULL)
3397 free(conn->customRequest);
3399 conn->customRequest = strdup(String_val(option));
3401 result = curl_easy_setopt(conn->connection,
3402 CURLOPT_CUSTOMREQUEST,
3403 conn->customRequest);
3405 if (result != CURLE_OK)
3406 raiseError(conn, result);
3408 CAMLreturn0;
3411 static void handleInterface(Connection *conn, value option)
3413 CAMLparam1(option);
3414 CURLcode result = CURLE_OK;
3416 Store_field(conn->ocamlValues, OcamlInterface, option);
3418 if (conn->interface != NULL)
3419 free(conn->interface);
3421 conn->interface = strdup(String_val(option));
3423 result = curl_easy_setopt(conn->connection,
3424 CURLOPT_INTERFACE,
3425 conn->interface);
3427 if (result != CURLE_OK)
3428 raiseError(conn, result);
3430 CAMLreturn0;
3433 static void handleKRB4Level(Connection *conn, value option)
3435 CAMLparam1(option);
3436 CURLcode result = CURLE_OK;
3438 switch (Long_val(option))
3440 case 0: /* KRB4_NONE */
3441 result = curl_easy_setopt(conn->connection,
3442 CURLOPT_KRB4LEVEL,
3443 NULL);
3444 break;
3446 case 1: /* KRB4_CLEAR */
3447 result = curl_easy_setopt(conn->connection,
3448 CURLOPT_KRB4LEVEL,
3449 "clear");
3450 break;
3452 case 2: /* KRB4_SAFE */
3453 result = curl_easy_setopt(conn->connection,
3454 CURLOPT_KRB4LEVEL,
3455 "safe");
3456 break;
3458 case 3: /* KRB4_CONFIDENTIAL */
3459 result = curl_easy_setopt(conn->connection,
3460 CURLOPT_KRB4LEVEL,
3461 "confidential");
3462 break;
3464 case 4: /* KRB4_PRIVATE */
3465 result = curl_easy_setopt(conn->connection,
3466 CURLOPT_KRB4LEVEL,
3467 "private");
3468 break;
3470 default:
3471 failwith("Invalid KRB4 Option");
3472 break;
3475 if (result != CURLE_OK)
3476 raiseError(conn, result);
3478 CAMLreturn0;
3481 static void handleProgressFunction(Connection *conn, value option)
3483 CAMLparam1(option);
3484 CURLcode result = CURLE_OK;
3486 if (Tag_val(option) == Closure_tag)
3487 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3488 else
3489 failwith("Not a proper closure");
3491 result = curl_easy_setopt(conn->connection,
3492 CURLOPT_PROGRESSFUNCTION,
3493 progressFunction);
3494 if (result != CURLE_OK)
3495 raiseError(conn, result);
3497 result = curl_easy_setopt(conn->connection,
3498 CURLOPT_PROGRESSDATA,
3499 conn);
3501 if (result != CURLE_OK)
3502 raiseError(conn, result);
3504 CAMLreturn0;
3507 static void handleSSLVerifyPeer(Connection *conn, value option)
3509 CAMLparam1(option);
3510 CURLcode result = CURLE_OK;
3512 result = curl_easy_setopt(conn->connection,
3513 CURLOPT_SSL_VERIFYPEER,
3514 Bool_val(option));
3516 if (result != CURLE_OK)
3517 raiseError(conn, result);
3519 CAMLreturn0;
3522 static void handleCAInfo(Connection *conn, value option)
3524 CAMLparam1(option);
3525 CURLcode result = CURLE_OK;
3527 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3529 if (conn->caInfo != NULL)
3530 free(conn->caInfo);
3532 conn->caInfo = strdup(String_val(option));
3534 result = curl_easy_setopt(conn->connection,
3535 CURLOPT_CAINFO,
3536 conn->caInfo);
3538 if (result != CURLE_OK)
3539 raiseError(conn, result);
3541 CAMLreturn0;
3544 static void handleCAPath(Connection *conn, value option)
3546 CAMLparam1(option);
3547 CURLcode result = CURLE_OK;
3549 Store_field(conn->ocamlValues, OcamlCAPath, option);
3551 if (conn->caPath != NULL)
3552 free(conn->caPath);
3554 conn->caPath = strdup(String_val(option));
3556 result = curl_easy_setopt(conn->connection,
3557 CURLOPT_CAPATH,
3558 conn->caPath);
3560 if (result != CURLE_OK)
3561 raiseError(conn, result);
3563 CAMLreturn0;
3566 static void handleFileTime(Connection *conn, value option)
3568 CAMLparam1(option);
3569 CURLcode result = CURLE_OK;
3571 result = curl_easy_setopt(conn->connection,
3572 CURLOPT_FILETIME,
3573 Bool_val(option));
3575 if (result != CURLE_OK)
3576 raiseError(conn, result);
3578 CAMLreturn0;
3581 static void handleMaxRedirs(Connection *conn, value option)
3583 CAMLparam1(option);
3584 CURLcode result = CURLE_OK;
3586 result = curl_easy_setopt(conn->connection,
3587 CURLOPT_MAXREDIRS,
3588 Long_val(option));
3590 if (result != CURLE_OK)
3591 raiseError(conn, result);
3593 CAMLreturn0;
3596 static void handleMaxConnects(Connection *conn, value option)
3598 CAMLparam1(option);
3599 CURLcode result = CURLE_OK;
3601 result = curl_easy_setopt(conn->connection,
3602 CURLOPT_MAXCONNECTS,
3603 Long_val(option));
3605 if (result != CURLE_OK)
3606 raiseError(conn, result);
3608 CAMLreturn0;
3611 static void handleClosePolicy(Connection *conn, value option)
3613 CAMLparam1(option);
3614 CURLcode result = CURLE_OK;
3616 switch (Long_val(option))
3618 case 0: /* CLOSEPOLICY_OLDEST */
3619 result = curl_easy_setopt(conn->connection,
3620 CURLOPT_CLOSEPOLICY,
3621 CURLCLOSEPOLICY_OLDEST);
3622 break;
3624 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3625 result = curl_easy_setopt(conn->connection,
3626 CURLOPT_CLOSEPOLICY,
3627 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3628 break;
3630 default:
3631 failwith("Invalid CLOSEPOLICY Option");
3632 break;
3635 if (result != CURLE_OK)
3636 raiseError(conn, result);
3638 CAMLreturn0;
3641 static void handleFreshConnect(Connection *conn, value option)
3643 CAMLparam1(option);
3644 CURLcode result = CURLE_OK;
3646 result = curl_easy_setopt(conn->connection,
3647 CURLOPT_FRESH_CONNECT,
3648 Bool_val(option));
3650 if (result != CURLE_OK)
3651 raiseError(conn, result);
3653 CAMLreturn0;
3656 static void handleForbidReuse(Connection *conn, value option)
3658 CAMLparam1(option);
3659 CURLcode result = CURLE_OK;
3661 result = curl_easy_setopt(conn->connection,
3662 CURLOPT_FORBID_REUSE,
3663 Bool_val(option));
3665 if (result != CURLE_OK)
3666 raiseError(conn, result);
3668 CAMLreturn0;
3671 static void handleRandomFile(Connection *conn, value option)
3673 CAMLparam1(option);
3674 CURLcode result = CURLE_OK;
3676 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3678 if (conn->randomFile != NULL)
3679 free(conn->randomFile);
3681 conn->randomFile = strdup(String_val(option));
3683 result = curl_easy_setopt(conn->connection,
3684 CURLOPT_RANDOM_FILE,
3685 conn->randomFile);
3687 if (result != CURLE_OK)
3688 raiseError(conn, result);
3690 CAMLreturn0;
3693 static void handleEGDSocket(Connection *conn, value option)
3695 CAMLparam1(option);
3696 CURLcode result = CURLE_OK;
3698 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3700 if (conn->egdSocket != NULL)
3701 free(conn->egdSocket);
3703 conn->egdSocket = strdup(String_val(option));
3705 result = curl_easy_setopt(conn->connection,
3706 CURLOPT_EGDSOCKET,
3707 conn->egdSocket);
3709 if (result != CURLE_OK)
3710 raiseError(conn, result);
3712 CAMLreturn0;
3715 static void handleConnectTimeout(Connection *conn, value option)
3717 CAMLparam1(option);
3718 CURLcode result = CURLE_OK;
3720 result = curl_easy_setopt(conn->connection,
3721 CURLOPT_CONNECTTIMEOUT,
3722 Long_val(option));
3724 if (result != CURLE_OK)
3725 raiseError(conn, result);
3727 CAMLreturn0;
3730 static void handleHTTPGet(Connection *conn, value option)
3732 CAMLparam1(option);
3733 CURLcode result = CURLE_OK;
3735 result = curl_easy_setopt(conn->connection,
3736 CURLOPT_HTTPGET,
3737 Bool_val(option));
3739 if (result != CURLE_OK)
3740 raiseError(conn, result);
3742 CAMLreturn0;
3745 static void handleSSLVerifyHost(Connection *conn, value option)
3747 CAMLparam1(option);
3748 CURLcode result = CURLE_OK;
3750 switch (Long_val(option))
3752 case 0: /* SSLVERIFYHOST_NONE */
3753 case 1: /* SSLVERIFYHOST_EXISTENCE */
3754 case 2: /* SSLVERIFYHOST_HOSTNAME */
3755 result = curl_easy_setopt(conn->connection,
3756 CURLOPT_SSL_VERIFYHOST,
3757 Long_val(option));
3758 break;
3760 default:
3761 failwith("Invalid SSLVERIFYHOST Option");
3762 break;
3765 if (result != CURLE_OK)
3766 raiseError(conn, result);
3768 CAMLreturn0;
3771 static void handleCookieJar(Connection *conn, value option)
3773 CAMLparam1(option);
3774 CURLcode result = CURLE_OK;
3776 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3778 if (conn->cookieJar != NULL)
3779 free(conn->cookieJar);
3781 conn->cookieJar = strdup(String_val(option));
3783 result = curl_easy_setopt(conn->connection,
3784 CURLOPT_COOKIEJAR,
3785 conn->cookieJar);
3787 if (result != CURLE_OK)
3788 raiseError(conn, result);
3790 CAMLreturn0;
3793 static void handleSSLCipherList(Connection *conn, value option)
3795 CAMLparam1(option);
3796 CURLcode result = CURLE_OK;
3798 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3800 if (conn->sslCipherList != NULL)
3801 free(conn->sslCipherList);
3803 conn->sslCipherList = strdup(String_val(option));
3805 result = curl_easy_setopt(conn->connection,
3806 CURLOPT_SSL_CIPHER_LIST,
3807 conn->sslCipherList);
3809 if (result != CURLE_OK)
3810 raiseError(conn, result);
3812 CAMLreturn0;
3815 static void handleHTTPVersion(Connection *conn, value option)
3817 CAMLparam1(option);
3818 CURLcode result = CURLE_OK;
3820 switch (Long_val(option))
3822 case 0: /* HTTP_VERSION_NONE */
3823 result = curl_easy_setopt(conn->connection,
3824 CURLOPT_HTTP_VERSION,
3825 CURL_HTTP_VERSION_NONE);
3826 break;
3828 case 1: /* HTTP_VERSION_1_0 */
3829 result = curl_easy_setopt(conn->connection,
3830 CURLOPT_HTTP_VERSION,
3831 CURL_HTTP_VERSION_1_0);
3832 break;
3834 case 2: /* HTTP_VERSION_1_1 */
3835 result = curl_easy_setopt(conn->connection,
3836 CURLOPT_HTTP_VERSION,
3837 CURL_HTTP_VERSION_1_1);
3838 break;
3840 default:
3841 failwith("Invalid HTTP_VERSION Option");
3842 break;
3845 if (result != CURLE_OK)
3846 raiseError(conn, result);
3848 CAMLreturn0;
3851 static void handleFTPUseEPSV(Connection *conn, value option)
3853 CAMLparam1(option);
3854 CURLcode result = CURLE_OK;
3856 result = curl_easy_setopt(conn->connection,
3857 CURLOPT_FTP_USE_EPSV,
3858 Bool_val(option));
3860 if (result != CURLE_OK)
3861 raiseError(conn, result);
3863 CAMLreturn0;
3866 static void handleDNSCacheTimeout(Connection *conn, value option)
3868 CAMLparam1(option);
3869 CURLcode result = CURLE_OK;
3871 result = curl_easy_setopt(conn->connection,
3872 CURLOPT_DNS_CACHE_TIMEOUT,
3873 Long_val(option));
3875 if (result != CURLE_OK)
3876 raiseError(conn, result);
3878 CAMLreturn0;
3881 static void handleDNSUseGlobalCache(Connection *conn, value option)
3883 CAMLparam1(option);
3884 CURLcode result = CURLE_OK;
3886 result = curl_easy_setopt(conn->connection,
3887 CURLOPT_DNS_USE_GLOBAL_CACHE,
3888 Bool_val(option));
3890 if (result != CURLE_OK)
3891 raiseError(conn, result);
3893 CAMLreturn0;
3896 static void handleDebugFunction(Connection *conn, value option)
3898 CAMLparam1(option);
3899 CURLcode result = CURLE_OK;
3901 if (Tag_val(option) == Closure_tag)
3902 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3903 else
3904 failwith("Not a proper closure");
3906 result = curl_easy_setopt(conn->connection,
3907 CURLOPT_DEBUGFUNCTION,
3908 debugFunction);
3909 if (result != CURLE_OK)
3910 raiseError(conn, result);
3912 result = curl_easy_setopt(conn->connection,
3913 CURLOPT_DEBUGDATA,
3914 conn);
3916 if (result != CURLE_OK)
3917 raiseError(conn, result);
3919 CAMLreturn0;
3922 static void handlePrivate(Connection *conn, value option)
3924 #if HAVE_DECL_CURLOPT_PRIVATE
3925 CAMLparam1(option);
3926 CURLcode result = CURLE_OK;
3928 Store_field(conn->ocamlValues, OcamlPrivate, option);
3930 if (conn->private != NULL)
3931 free(conn->private);
3933 conn->private = strdup(String_val(option));
3935 result = curl_easy_setopt(conn->connection,
3936 CURLOPT_PRIVATE,
3937 conn->private);
3939 if (result != CURLE_OK)
3940 raiseError(conn, result);
3942 CAMLreturn0;
3943 #else
3944 #warning "libcurl does not implement CURLOPT_PRIVATE"
3945 failwith("libcurl does not implement CURLOPT_PRIVATE");
3946 #endif
3949 static void handleHTTP200Aliases(Connection *conn, value option)
3951 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3952 CAMLparam1(option);
3953 CAMLlocal1(listIter);
3954 CURLcode result = CURLE_OK;
3956 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3958 free_curl_slist(conn->http200Aliases);
3959 conn->http200Aliases = NULL;
3961 listIter = option;
3963 while (!Is_long(listIter))
3965 conn->http200Aliases = curl_slist_append(conn->http200Aliases, String_val(Field(listIter, 0)));
3967 listIter = Field(listIter, 1);
3970 result = curl_easy_setopt(conn->connection,
3971 CURLOPT_HTTP200ALIASES,
3972 conn->http200Aliases);
3974 if (result != CURLE_OK)
3975 raiseError(conn, result);
3977 CAMLreturn0;
3978 #else
3979 #warning "libcurl does not implement CURLOPT_HTTP200ALIASES"
3980 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
3981 #endif
3984 static void handleUnrestrictedAuth(Connection *conn, value option)
3986 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
3987 CAMLparam1(option);
3988 CURLcode result = CURLE_OK;
3990 result = curl_easy_setopt(conn->connection,
3991 CURLOPT_UNRESTRICTED_AUTH,
3992 Bool_val(option));
3994 if (result != CURLE_OK)
3995 raiseError(conn, result);
3997 CAMLreturn0;
3998 #else
3999 #warning "libcurl does not implement CURLOPT_UNRESTRICTED_AUTH"
4000 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4001 #endif
4004 static void handleFTPUseEPRT(Connection *conn, value option)
4006 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4007 CAMLparam1(option);
4008 CURLcode result = CURLE_OK;
4010 result = curl_easy_setopt(conn->connection,
4011 CURLOPT_FTP_USE_EPRT,
4012 Bool_val(option));
4014 if (result != CURLE_OK)
4015 raiseError(conn, result);
4017 CAMLreturn0;
4018 #else
4019 #warning "libcurl does not implement CURLOPT_FTP_USE_EPRT"
4020 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4021 #endif
4024 static void handleHTTPAuth(Connection *conn, value option)
4026 #if HAVE_DECL_CURLOPT_HTTPAUTH
4027 CAMLparam1(option);
4028 CAMLlocal1(listIter);
4029 CURLcode result = CURLE_OK;
4030 long auth = CURLAUTH_NONE;
4032 listIter = option;
4034 while (!Is_long(listIter))
4036 switch (Long_val(Field(listIter, 0)))
4038 case 0: /* CURLAUTH_BASIC */
4039 auth |= CURLAUTH_BASIC;
4040 break;
4042 case 1: /* CURLAUTH_DIGEST */
4043 auth |= CURLAUTH_DIGEST;
4044 break;
4046 case 2: /* CURLAUTH_GSSNEGOTIATE */
4047 auth |= CURLAUTH_GSSNEGOTIATE;
4048 break;
4050 case 3: /* CURLAUTH_NTLM */
4051 auth |= CURLAUTH_NTLM;
4052 break;
4054 case 4: /* CURLAUTH_ANY */
4055 auth |= CURLAUTH_ANY;
4056 break;
4058 case 5: /* CURLAUTH_ANYSAFE */
4059 auth |= CURLAUTH_ANYSAFE;
4060 break;
4062 default:
4063 failwith("Invalid HTTPAUTH Value");
4064 break;
4067 listIter = Field(listIter, 1);
4070 result = curl_easy_setopt(conn->connection,
4071 CURLOPT_HTTPAUTH,
4072 auth);
4074 if (result != CURLE_OK)
4075 raiseError(conn, result);
4077 CAMLreturn0;
4078 #else
4079 #warning "libcurl does not implement CURLOPT_HTTPAUTH"
4080 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4081 #endif
4084 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4086 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4087 CAMLparam1(option);
4088 CURLcode result = CURLE_OK;
4090 result = curl_easy_setopt(conn->connection,
4091 CURLOPT_FTP_CREATE_MISSING_DIRS,
4092 Bool_val(option));
4094 if (result != CURLE_OK)
4095 raiseError(conn, result);
4097 CAMLreturn0;
4098 #else
4099 #warning "libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS"
4100 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4101 #endif
4104 static void handleProxyAuth(Connection *conn, value option)
4106 #if HAVE_DECL_CURLOPT_PROXYAUTH
4107 CAMLparam1(option);
4108 CAMLlocal1(listIter);
4109 CURLcode result = CURLE_OK;
4110 long auth = CURLAUTH_NONE;
4112 listIter = option;
4114 while (!Is_long(listIter))
4116 switch (Long_val(Field(listIter, 0)))
4118 case 0: /* CURLAUTH_BASIC */
4119 auth |= CURLAUTH_BASIC;
4120 break;
4122 case 1: /* CURLAUTH_DIGEST */
4123 auth |= CURLAUTH_DIGEST;
4124 break;
4126 case 2: /* CURLAUTH_GSSNEGOTIATE */
4127 auth |= CURLAUTH_GSSNEGOTIATE;
4128 break;
4130 case 3: /* CURLAUTH_NTLM */
4131 auth |= CURLAUTH_NTLM;
4132 break;
4134 case 4: /* CURLAUTH_ANY */
4135 auth |= CURLAUTH_ANY;
4136 break;
4138 case 5: /* CURLAUTH_ANYSAFE */
4139 auth |= CURLAUTH_ANYSAFE;
4140 break;
4142 default:
4143 failwith("Invalid HTTPAUTH Value");
4144 break;
4147 listIter = Field(listIter, 1);
4150 result = curl_easy_setopt(conn->connection,
4151 CURLOPT_PROXYAUTH,
4152 auth);
4154 if (result != CURLE_OK)
4155 raiseError(conn, result);
4157 CAMLreturn0;
4158 #else
4159 #warning "libcurl does not implement CURLOPT_PROXYAUTH"
4160 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4161 #endif
4164 static void handleFTPResponseTimeout(Connection *conn, value option)
4166 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4167 CAMLparam1(option);
4168 CURLcode result = CURLE_OK;
4170 result = curl_easy_setopt(conn->connection,
4171 CURLOPT_FTP_RESPONSE_TIMEOUT,
4172 Long_val(option));
4174 if (result != CURLE_OK)
4175 raiseError(conn, result);
4177 CAMLreturn0;
4178 #else
4179 #warning "libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT"
4180 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4181 #endif
4184 static void handleIPResolve(Connection *conn, value option)
4186 #if HAVE_DECL_CURLOPT_IPRESOLVE
4187 CAMLparam1(option);
4188 CURLcode result = CURLE_OK;
4190 switch (Long_val(option))
4192 case 0: /* CURL_IPRESOLVE_WHATEVER */
4193 result = curl_easy_setopt(conn->connection,
4194 CURLOPT_IPRESOLVE,
4195 CURL_IPRESOLVE_WHATEVER);
4196 break;
4198 case 1: /* CURL_IPRESOLVE_V4 */
4199 result = curl_easy_setopt(conn->connection,
4200 CURLOPT_IPRESOLVE,
4201 CURL_IPRESOLVE_V4);
4202 break;
4204 case 2: /* CURL_IPRESOLVE_V6 */
4205 result = curl_easy_setopt(conn->connection,
4206 CURLOPT_IPRESOLVE,
4207 CURL_IPRESOLVE_V6);
4208 break;
4210 default:
4211 failwith("Invalid IPRESOLVE Value");
4212 break;
4215 if (result != CURLE_OK)
4216 raiseError(conn, result);
4218 CAMLreturn0;
4219 #else
4220 #warning "libcurl does not implement CURLOPT_IPRESOLVE"
4221 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4222 #endif
4225 static void handleMaxFileSize(Connection *conn, value option)
4227 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4228 CAMLparam1(option);
4229 CURLcode result = CURLE_OK;
4231 result = curl_easy_setopt(conn->connection,
4232 CURLOPT_MAXFILESIZE,
4233 Int32_val(option));
4235 if (result != CURLE_OK)
4236 raiseError(conn, result);
4238 CAMLreturn0;
4239 #else
4240 #warning "libcurl does not implement CURLOPT_MAXFILESIZE"
4241 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4242 #endif
4245 static void handleInFileSizeLarge(Connection *conn, value option)
4247 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4248 CAMLparam1(option);
4249 CURLcode result = CURLE_OK;
4251 result = curl_easy_setopt(conn->connection,
4252 CURLOPT_INFILESIZE_LARGE,
4253 Int64_val(option));
4255 if (result != CURLE_OK)
4256 raiseError(conn, result);
4258 CAMLreturn0;
4259 #else
4260 #warning("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4261 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4262 #endif
4265 static void handleResumeFromLarge(Connection *conn, value option)
4267 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4268 CAMLparam1(option);
4269 CURLcode result = CURLE_OK;
4271 result = curl_easy_setopt(conn->connection,
4272 CURLOPT_RESUME_FROM_LARGE,
4273 Int64_val(option));
4275 if (result != CURLE_OK)
4276 raiseError(conn, result);
4278 CAMLreturn0;
4279 #else
4280 #warning("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4281 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4282 #endif
4285 static void handleMaxFileSizeLarge(Connection *conn, value option)
4287 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4288 CAMLparam1(option);
4289 CURLcode result = CURLE_OK;
4291 result = curl_easy_setopt(conn->connection,
4292 CURLOPT_MAXFILESIZE_LARGE,
4293 Int64_val(option));
4295 if (result != CURLE_OK)
4296 raiseError(conn, result);
4298 CAMLreturn0;
4299 #else
4300 #warning "libcurl does not implement CURLOPT_MAXFILESIZE_LARGE"
4301 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4302 #endif
4305 static void handleNETRCFile(Connection *conn, value option)
4307 #if HAVE_DECL_CURLOPT_NETRC_FILE
4308 CAMLparam1(option);
4309 CURLcode result = CURLE_OK;
4311 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4313 if (conn->netrcFile != NULL)
4314 free(conn->netrcFile);
4316 conn->netrcFile = strdup(String_val(option));
4318 result = curl_easy_setopt(conn->connection,
4319 CURLOPT_NETRC_FILE,
4320 conn->netrcFile);
4322 if (result != CURLE_OK)
4323 raiseError(conn, result);
4325 CAMLreturn0;
4326 #else
4327 #warning "libcurl does not implement CURLOPT_NETRC_FILE"
4328 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4329 #endif
4332 static void handleFTPSSL(Connection *conn, value option)
4334 #if HAVE_DECL_CURLOPT_FTP_SSL
4335 CAMLparam1(option);
4336 CURLcode result = CURLE_OK;
4338 switch (Long_val(option))
4340 case 0: /* CURLFTPSSL_NONE */
4341 result = curl_easy_setopt(conn->connection,
4342 CURLOPT_FTP_SSL,
4343 CURLFTPSSL_NONE);
4344 break;
4346 case 1: /* CURLFTPSSL_TRY */
4347 result = curl_easy_setopt(conn->connection,
4348 CURLOPT_FTP_SSL,
4349 CURLFTPSSL_TRY);
4350 break;
4352 case 2: /* CURLFTPSSL_CONTROL */
4353 result = curl_easy_setopt(conn->connection,
4354 CURLOPT_FTP_SSL,
4355 CURLFTPSSL_CONTROL);
4356 break;
4358 case 3: /* CURLFTPSSL_ALL */
4359 result = curl_easy_setopt(conn->connection,
4360 CURLOPT_FTP_SSL,
4361 CURLFTPSSL_ALL);
4362 break;
4364 default:
4365 failwith("Invalid FTP_SSL Value");
4366 break;
4369 if (result != CURLE_OK)
4370 raiseError(conn, result);
4372 CAMLreturn0;
4373 #else
4374 #warning "libcurl does not implement CURLOPT_FTP_SSL"
4375 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4376 #endif
4379 static void handlePostFieldSizeLarge(Connection *conn, value option)
4381 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4382 CAMLparam1(option);
4383 CURLcode result = CURLE_OK;
4385 result = curl_easy_setopt(conn->connection,
4386 CURLOPT_POSTFIELDSIZE_LARGE,
4387 Int64_val(option));
4389 if (result != CURLE_OK)
4390 raiseError(conn, result);
4392 CAMLreturn0;
4393 #else
4394 #warning "libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE"
4395 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4396 #endif
4399 static void handleTCPNoDelay(Connection *conn, value option)
4401 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4402 CAMLparam1(option);
4403 CURLcode result = CURLE_OK;
4405 result = curl_easy_setopt(conn->connection,
4406 CURLOPT_TCP_NODELAY,
4407 Bool_val(option));
4409 if (result != CURLE_OK)
4410 raiseError(conn, result);
4412 CAMLreturn0;
4413 #else
4414 #warning "libcurl does not implement CURLOPT_TCP_NODELAY"
4415 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4416 #endif
4419 static void handleFTPSSLAuth(Connection *conn, value option)
4421 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4422 CAMLparam1(option);
4423 CURLcode result = CURLE_OK;
4425 switch (Long_val(option))
4427 case 0: /* CURLFTPAUTH_DEFAULT */
4428 result = curl_easy_setopt(conn->connection,
4429 CURLOPT_FTPSSLAUTH,
4430 CURLFTPAUTH_DEFAULT);
4431 break;
4433 case 1: /* CURLFTPAUTH_SSL */
4434 result = curl_easy_setopt(conn->connection,
4435 CURLOPT_FTPSSLAUTH,
4436 CURLFTPAUTH_SSL);
4437 break;
4439 case 2: /* CURLFTPAUTH_TLS */
4440 result = curl_easy_setopt(conn->connection,
4441 CURLOPT_FTPSSLAUTH,
4442 CURLFTPAUTH_TLS);
4443 break;
4445 default:
4446 failwith("Invalid FTPSSLAUTH value");
4447 break;
4450 if (result != CURLE_OK)
4451 raiseError(conn, result);
4453 CAMLreturn0;
4454 #else
4455 #warning "libcurl does not implement CURLOPT_FTPSSLAUTH"
4456 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4457 #endif
4460 static void handleIOCTLFunction(Connection *conn, value option)
4462 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4463 CAMLparam1(option);
4464 CURLcode result = CURLE_OK;
4466 if (Tag_val(option) == Closure_tag)
4467 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4468 else
4469 failwith("Not a proper closure");
4471 result = curl_easy_setopt(conn->connection,
4472 CURLOPT_IOCTLFUNCTION,
4473 ioctlFunction);
4474 if (result != CURLE_OK)
4475 raiseError(conn, result);
4477 result = curl_easy_setopt(conn->connection,
4478 CURLOPT_DEBUGDATA,
4479 conn);
4481 if (result != CURLE_OK)
4482 raiseError(conn, result);
4484 CAMLreturn0;
4485 #else
4486 #warning "libcurl does not implement CURLOPT_IOCTLFUNCTION"
4487 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4488 #endif
4491 static void handleFTPAccount(Connection *conn, value option)
4493 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4494 CAMLparam1(option);
4495 CURLcode result = CURLE_OK;
4497 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4499 if (conn->ftpaccount != NULL)
4500 free(conn->ftpaccount);
4502 conn->ftpaccount = strdup(String_val(option));
4504 result = curl_easy_setopt(conn->connection,
4505 CURLOPT_FTP_ACCOUNT,
4506 conn->ftpaccount);
4508 if (result != CURLE_OK)
4509 raiseError(conn, result);
4511 CAMLreturn0;
4512 #else
4513 #warning "libcurl does not implement CURLOPT_FTP_ACCOUNT"
4514 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4515 #endif
4518 static void handleCookieList(Connection *conn, value option)
4520 #if HAVE_DECL_CURLOPT_COOKIELIST
4521 CAMLparam1(option);
4522 CURLcode result = CURLE_OK;
4524 Store_field(conn->ocamlValues, OcamlCookieList, option);
4526 if (conn->cookielist != NULL)
4527 free(conn->cookielist);
4529 conn->cookielist = strdup(String_val(option));
4531 result = curl_easy_setopt(conn->connection,
4532 CURLOPT_COOKIELIST,
4533 conn->cookielist);
4535 if (result != CURLE_OK)
4536 raiseError(conn, result);
4538 CAMLreturn0;
4539 #else
4540 #warning "libcurl does not implement CURLOPT_COOKIELIST"
4541 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4542 #endif
4545 static void handleIgnoreContentLength(Connection *conn, value option)
4547 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4548 CAMLparam1(option);
4549 CURLcode result = CURLE_OK;
4551 result = curl_easy_setopt(conn->connection,
4552 CURLOPT_IGNORE_CONTENT_LENGTH,
4553 Bool_val(option));
4555 if (result != CURLE_OK)
4556 raiseError(conn, result);
4558 CAMLreturn0;
4559 #else
4560 #warning "libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH"
4561 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4562 #endif
4565 static void handleFTPSkipPASVIP(Connection *conn, value option)
4567 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4568 CAMLparam1(option);
4569 CURLcode result = CURLE_OK;
4571 result = curl_easy_setopt(conn->connection,
4572 CURLOPT_FTP_SKIP_PASV_IP,
4573 Bool_val(option));
4575 if (result != CURLE_OK)
4576 raiseError(conn, result);
4578 CAMLreturn0;
4579 #else
4580 #warning "libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP"
4581 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4582 #endif
4585 static void handleFTPFileMethod(Connection *conn, value option)
4587 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4588 CAMLparam1(option);
4589 CURLcode result = CURLE_OK;
4591 switch (Long_val(option))
4593 case 0: /* CURLFTPMETHOD_DEFAULT */
4594 result = curl_easy_setopt(conn->connection,
4595 CURLOPT_FTP_FILEMETHOD,
4596 CURLFTPMETHOD_DEFAULT);
4597 break;
4599 case 1: /* CURLFTMETHOD_MULTICWD */
4600 result = curl_easy_setopt(conn->connection,
4601 CURLOPT_FTP_FILEMETHOD,
4602 CURLFTPMETHOD_MULTICWD);
4603 break;
4605 case 2: /* CURLFTPMETHOD_NOCWD */
4606 result = curl_easy_setopt(conn->connection,
4607 CURLOPT_FTP_FILEMETHOD,
4608 CURLFTPMETHOD_NOCWD);
4609 break;
4611 case 3: /* CURLFTPMETHOD_SINGLECWD */
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_FILEMETHOD,
4614 CURLFTPMETHOD_SINGLECWD);
4616 default:
4617 failwith("Invalid FTP_FILEMETHOD value");
4618 break;
4621 if (result != CURLE_OK)
4622 raiseError(conn, result);
4624 CAMLreturn0;
4625 #else
4626 #warning "libcurl does not implement CURLOPT_FTP_FILEMETHOD"
4627 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4628 #endif
4631 static void handleLocalPort(Connection *conn, value option)
4633 #if HAVE_DECL_CURLOPT_LOCALPORT
4634 CAMLparam1(option);
4635 CURLcode result = CURLE_OK;
4637 result = curl_easy_setopt(conn->connection,
4638 CURLOPT_LOCALPORT,
4639 Long_val(option));
4641 if (result != CURLE_OK)
4642 raiseError(conn, result);
4644 CAMLreturn0;
4645 #else
4646 #warning "libcurl does not implement CURLOPT_LOCALPORT"
4647 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4648 #endif
4651 static void handleLocalPortRange(Connection *conn, value option)
4653 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4654 CAMLparam1(option);
4655 CURLcode result = CURLE_OK;
4657 result = curl_easy_setopt(conn->connection,
4658 CURLOPT_LOCALPORTRANGE,
4659 Long_val(option));
4661 if (result != CURLE_OK)
4662 raiseError(conn, result);
4664 CAMLreturn0;
4665 #else
4666 #warning "libcurl does not implement CURLOPT_LOCALPORTRANGE"
4667 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4668 #endif
4671 static void handleConnectOnly(Connection *conn, value option)
4673 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4674 CAMLparam1(option);
4675 CURLcode result = CURLE_OK;
4677 result = curl_easy_setopt(conn->connection,
4678 CURLOPT_CONNECT_ONLY,
4679 Bool_val(option));
4681 if (result != CURLE_OK)
4682 raiseError(conn, result);
4684 CAMLreturn0;
4685 #else
4686 #warning "libcurl does not implement CURLOPT_CONNECT_ONLY"
4687 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4688 #endif
4691 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4693 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4694 CAMLparam1(option);
4695 CURLcode result = CURLE_OK;
4697 result = curl_easy_setopt(conn->connection,
4698 CURLOPT_MAX_SEND_SPEED_LARGE,
4699 Int64_val(option));
4701 if (result != CURLE_OK)
4702 raiseError(conn, result);
4704 CAMLreturn0;
4705 #else
4706 #warning "libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE"
4707 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4708 #endif
4711 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4713 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4714 CAMLparam1(option);
4715 CURLcode result = CURLE_OK;
4717 result = curl_easy_setopt(conn->connection,
4718 CURLOPT_MAX_RECV_SPEED_LARGE,
4719 Int64_val(option));
4721 if (result != CURLE_OK)
4722 raiseError(conn, result);
4724 CAMLreturn0;
4725 #else
4726 #warning "libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE"
4727 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4728 #endif
4731 static void handleFTPAlternativeToUser(Connection *conn, value option)
4733 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4734 CAMLparam1(option);
4735 CURLcode result = CURLE_OK;
4737 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4739 if (conn->ftpAlternativeToUser != NULL)
4740 free(conn->ftpAlternativeToUser);
4742 conn->ftpAlternativeToUser = strdup(String_val(option));
4744 result = curl_easy_setopt(conn->connection,
4745 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4746 conn->ftpAlternativeToUser);
4748 if (result != CURLE_OK)
4749 raiseError(conn, result);
4751 CAMLreturn0;
4752 #else
4753 #warning "libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER"
4754 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4755 #endif
4758 static void handleSSLSessionIdCache(Connection *conn, value option)
4760 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4761 CAMLparam1(option);
4762 CURLcode result = CURLE_OK;
4764 result = curl_easy_setopt(conn->connection,
4765 CURLOPT_SSL_SESSIONID_CACHE,
4766 Bool_val(option));
4768 if (result != CURLE_OK)
4769 raiseError(conn, result);
4771 CAMLreturn0;
4772 #else
4773 #warning "libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE"
4774 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4775 #endif
4778 static void handleSSHAuthTypes(Connection *conn, value option)
4780 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4781 CAMLparam1(option);
4782 CAMLlocal1(listIter);
4783 CURLcode result = CURLE_OK;
4784 long authTypes = CURLSSH_AUTH_NONE;
4786 listIter = option;
4788 while (!Is_long(listIter))
4790 switch (Long_val(Field(listIter, 0)))
4792 case 0: /* CURLSSH_AUTH_ANY */
4793 authTypes |= CURLSSH_AUTH_ANY;
4794 break;
4796 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4797 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4798 break;
4800 case 2: /* CURLSSH_AUTH_PASSWORD */
4801 authTypes |= CURLSSH_AUTH_PASSWORD;
4802 break;
4804 case 3: /* CURLSSH_AUTH_HOST */
4805 authTypes |= CURLSSH_AUTH_HOST;
4806 break;
4808 case 4: /* CURLSSH_AUTH_KEYBOARD */
4809 authTypes |= CURLSSH_AUTH_KEYBOARD;
4810 break;
4812 default:
4813 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4814 break;
4817 listIter = Field(listIter, 1);
4820 result = curl_easy_setopt(conn->connection,
4821 CURLOPT_SSH_AUTH_TYPES,
4822 authTypes);
4824 if (result != CURLE_OK)
4825 raiseError(conn, result);
4827 CAMLreturn0;
4828 #else
4829 #warning "libcurl does not implement CURLOPT_SSH_AUTH_TYPES"
4830 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4831 #endif
4834 static void handleSSHPublicKeyFile(Connection *conn, value option)
4836 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4837 CAMLparam1(option);
4838 CURLcode result = CURLE_OK;
4840 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4842 if (conn->sshPublicKeyFile != NULL)
4843 free(conn->sshPublicKeyFile);
4845 conn->sshPublicKeyFile = strdup(String_val(option));
4847 result = curl_easy_setopt(conn->connection,
4848 CURLOPT_SSH_PUBLIC_KEYFILE,
4849 conn->sshPublicKeyFile);
4851 if (result != CURLE_OK)
4852 raiseError(conn, result);
4854 CAMLreturn0;
4855 #else
4856 #warning "libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE"
4857 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4858 #endif
4861 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4863 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4864 CAMLparam1(option);
4865 CURLcode result = CURLE_OK;
4867 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4869 if (conn->sshPrivateKeyFile != NULL)
4870 free(conn->sshPrivateKeyFile);
4872 conn->sshPrivateKeyFile = strdup(String_val(option));
4874 result = curl_easy_setopt(conn->connection,
4875 CURLOPT_SSH_PRIVATE_KEYFILE,
4876 conn->sshPrivateKeyFile);
4878 if (result != CURLE_OK)
4879 raiseError(conn, result);
4881 CAMLreturn0;
4882 #else
4883 #warning "libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE"
4884 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4885 #endif
4888 static void handleFTPSSLCCC(Connection *conn, value option)
4890 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4891 CAMLparam1(option);
4892 CURLcode result = CURLE_OK;
4894 switch (Long_val(option))
4896 case 0: /* CURLFTPSSL_CCC_NONE */
4897 result = curl_easy_setopt(conn->connection,
4898 CURLOPT_FTP_SSL_CCC,
4899 CURLFTPSSL_CCC_NONE);
4900 break;
4902 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4903 result = curl_easy_setopt(conn->connection,
4904 CURLOPT_FTP_SSL_CCC,
4905 CURLFTPSSL_CCC_PASSIVE);
4906 break;
4908 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4909 result = curl_easy_setopt(conn->connection,
4910 CURLOPT_FTP_SSL_CCC,
4911 CURLFTPSSL_CCC_ACTIVE);
4912 break;
4914 default:
4915 failwith("Invalid FTPSSL_CCC value");
4916 break;
4919 if (result != CURLE_OK)
4920 raiseError(conn, result);
4922 CAMLreturn0;
4923 #else
4924 #warning "libcurl does not implement CURLOPT_FTP_SSL_CCC"
4925 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4926 #endif
4929 static void handleTimeoutMS(Connection *conn, value option)
4931 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4932 CAMLparam1(option);
4933 CURLcode result = CURLE_OK;
4935 result = curl_easy_setopt(conn->connection,
4936 CURLOPT_TIMEOUT_MS,
4937 Long_val(option));
4939 if (result != CURLE_OK)
4940 raiseError(conn, result);
4942 CAMLreturn0;
4943 #else
4944 #warning "libcurl does not implement CURLOPT_TIMEOUT_MS"
4945 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4946 #endif
4949 static void handleConnectTimeoutMS(Connection *conn, value option)
4951 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4952 CAMLparam1(option);
4953 CURLcode result = CURLE_OK;
4955 result = curl_easy_setopt(conn->connection,
4956 CURLOPT_CONNECTTIMEOUT_MS,
4957 Long_val(option));
4959 if (result != CURLE_OK)
4960 raiseError(conn, result);
4962 CAMLreturn0;
4963 #else
4964 #warning "libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS"
4965 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
4966 #endif
4969 static void handleHTTPTransferDecoding(Connection *conn, value option)
4971 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4972 CAMLparam1(option);
4973 CURLcode result = CURLE_OK;
4975 result = curl_easy_setopt(conn->connection,
4976 CURLOPT_HTTP_TRANSFER_DECODING,
4977 Bool_val(option));
4979 if (result != CURLE_OK)
4980 raiseError(conn, result);
4982 CAMLreturn0;
4983 #else
4984 #warning "libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING"
4985 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
4986 #endif
4989 static void handleHTTPContentDecoding(Connection *conn, value option)
4991 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4992 CAMLparam1(option);
4993 CURLcode result = CURLE_OK;
4995 result = curl_easy_setopt(conn->connection,
4996 CURLOPT_HTTP_CONTENT_DECODING,
4997 Bool_val(option));
4999 if (result != CURLE_OK)
5000 raiseError(conn, result);
5002 CAMLreturn0;
5003 #else
5004 #warning "libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING"
5005 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5006 #endif
5009 static void handleNewFilePerms(Connection *conn, value option)
5011 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5012 CAMLparam1(option);
5013 CURLcode result = CURLE_OK;
5015 result = curl_easy_setopt(conn->connection,
5016 CURLOPT_NEW_FILE_PERMS,
5017 Long_val(option));
5019 if (result != CURLE_OK)
5020 raiseError(conn, result);
5022 CAMLreturn0;
5023 #else
5024 #warning "libcurl does not implement CURLOPT_NEW_FILE_PERMS"
5025 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5026 #endif
5029 static void handleNewDirectoryPerms(Connection *conn, value option)
5031 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5032 CAMLparam1(option);
5033 CURLcode result = CURLE_OK;
5035 result = curl_easy_setopt(conn->connection,
5036 CURLOPT_NEW_DIRECTORY_PERMS,
5037 Long_val(option));
5039 if (result != CURLE_OK)
5040 raiseError(conn, result);
5042 CAMLreturn0;
5043 #else
5044 #warning "libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS"
5045 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5046 #endif
5049 static void handlePost301(Connection *conn, value option)
5051 #if HAVE_DECL_CURLOPT_POST301
5052 CAMLparam1(option);
5053 CURLcode result = CURLE_OK;
5055 result = curl_easy_setopt(conn->connection,
5056 CURLOPT_POST301,
5057 Bool_val(option));
5059 if (result != CURLE_OK)
5060 raiseError(conn, result);
5062 CAMLreturn0;
5063 #else
5064 #warning "libcurl does not implement CURLOPT_POST301"
5065 failwith("libcurl does not implement CURLOPT_POST301");
5066 #endif
5069 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5071 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5072 CAMLparam1(option);
5073 CURLcode result = CURLE_OK;
5075 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5077 if (conn->sshHostPublicKeyMD5 != NULL)
5078 free(conn->sshHostPublicKeyMD5);
5080 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5082 result = curl_easy_setopt(conn->connection,
5083 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5084 conn->sshHostPublicKeyMD5);
5086 if (result != CURLE_OK)
5087 raiseError(conn, result);
5089 CAMLreturn0;
5090 #else
5091 #warning "libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"
5092 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5093 #endif
5096 static void handleCopyPostFields(Connection *conn, value option)
5098 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5099 CAMLparam1(option);
5100 CURLcode result = CURLE_OK;
5102 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5104 if (conn->copyPostFields != NULL)
5105 free(conn->copyPostFields);
5107 conn->copyPostFields = strdup(String_val(option));
5109 result = curl_easy_setopt(conn->connection,
5110 CURLOPT_COPYPOSTFIELDS,
5111 conn->copyPostFields);
5113 if (result != CURLE_OK)
5114 raiseError(conn, result);
5116 CAMLreturn0;
5117 #else
5118 #warning "libcurl does not implement CURLOPT_COPYPOSTFIELDS"
5119 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5120 #endif
5123 static void handleProxyTransferMode(Connection *conn, value option)
5125 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5126 CAMLparam1(option);
5127 CURLcode result = CURLE_OK;
5129 result = curl_easy_setopt(conn->connection,
5130 CURLOPT_PROXY_TRANSFER_MODE,
5131 Bool_val(option));
5133 if (result != CURLE_OK)
5134 raiseError(conn, result);
5136 CAMLreturn0;
5137 #else
5138 #warning "libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE"
5139 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5140 #endif
5143 static void handleSeekFunction(Connection *conn, value option)
5145 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5146 CAMLparam1(option);
5147 CURLcode result = CURLE_OK;
5149 if (Tag_val(option) == Closure_tag)
5150 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5151 else
5152 failwith("Not a proper closure");
5154 result = curl_easy_setopt(conn->connection,
5155 CURLOPT_SEEKFUNCTION,
5156 seekFunction);
5158 if (result != CURLE_OK)
5159 raiseError(conn, result);
5161 result = curl_easy_setopt(conn->connection,
5162 CURLOPT_SEEKDATA,
5163 conn);
5165 if (result != CURLE_OK)
5166 raiseError(conn, result);
5168 CAMLreturn0;
5169 #else
5170 #warning "libcurl does not implement CURLOPT_SEEKFUNCTION"
5171 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5172 #endif
5175 static void handleAutoReferer(Connection *conn, value option)
5177 #if HAVE_DECL_CURLOPT_AUTOREFERER
5178 CAMLparam1(option);
5179 CURLcode result = curl_easy_setopt(conn->connection,
5180 CURLOPT_AUTOREFERER,
5181 Bool_val(option));
5183 if (result != CURLE_OK)
5184 raiseError(conn, result);
5186 CAMLreturn0;
5187 #else
5188 #warning "libcurl does not implement CURLOPT_AUTOREFERER"
5189 failwith("libcurl does not implement CURLOPT_AUTOREFERER");
5190 #endif
5193 static void handleOpenSocketFunction(Connection *conn, value option)
5195 #if HAVE_DECL_CURLOPT_OPENSOCKETFUNCTION
5196 CAMLparam1(option);
5197 CURLcode result = CURLE_OK;
5199 Store_field(conn->ocamlValues, OcamlOpenSocketFunctionCallback, option);
5201 result = curl_easy_setopt(conn->connection,
5202 CURLOPT_OPENSOCKETDATA,
5203 conn);
5205 if (result != CURLE_OK)
5206 raiseError(conn, result);
5208 result = curl_easy_setopt(conn->connection,
5209 CURLOPT_OPENSOCKETFUNCTION,
5210 openSocketFunction);
5212 if (result != CURLE_OK)
5213 raiseError(conn, result);
5215 CAMLreturn0;
5216 #else
5217 #warning "libcurl does not implement CURLOPT_OPENSOCKETFUNCTION"
5218 failwith("libcurl does not implement CURLOPT_OPENSOCKETFUNCTION");
5219 #endif
5222 static void handleProxyType(Connection *conn, value option)
5224 #if HAVE_DECL_CURLOPT_PROXYTYPE
5225 CAMLparam1(option);
5226 CURLcode result = CURLE_OK;
5227 long proxy_type;
5229 switch (Long_val(option))
5231 case 0: proxy_type = CURLPROXY_HTTP; break;
5232 case 1: proxy_type = CURLPROXY_HTTP_1_0; break;
5233 case 2: proxy_type = CURLPROXY_SOCKS4; break;
5234 case 3: proxy_type = CURLPROXY_SOCKS5; break;
5235 case 4: proxy_type = CURLPROXY_SOCKS4A; break;
5236 case 5: proxy_type = CURLPROXY_SOCKS5_HOSTNAME; break;
5237 default:
5238 failwith("Invalid curl proxy type");
5241 result = curl_easy_setopt(conn->connection,
5242 CURLOPT_PROXYTYPE,
5243 proxy_type);
5245 if (result != CURLE_OK)
5246 raiseError(conn, result);
5248 CAMLreturn0;
5249 #else
5250 #warning "libcurl does not implement CURLOPT_PROXYTYPE"
5251 failwith("libcurl does not implement CURLOPT_PROXYTYPE");
5252 #endif
5258 ** curl_easy_setopt helper function
5261 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5263 CAMLparam2(conn, option);
5264 CAMLlocal1(data);
5265 Connection *connection = Connection_val(conn);
5267 checkConnection(connection);
5269 if (Is_long(option))
5271 char error[128];
5273 sprintf(error, "Unimplemented Option: %s",
5274 findOption(unimplementedOptionMap,
5275 (CURLoption)(Long_val(option))));
5277 failwith(error);
5280 if (!Is_block(option))
5281 failwith("Not a block");
5283 if (Wosize_val(option) < 1)
5284 failwith("Insufficient data in block");
5286 data = Field(option, 0);
5288 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5289 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5290 data);
5291 else
5292 failwith("Invalid CURLOPT Option");
5294 CAMLreturn(Val_unit);
5298 ** curl_easy_perform helper function
5301 CAMLprim value helper_curl_easy_perform(value conn)
5303 CAMLparam1(conn);
5304 CURLcode result = CURLE_OK;
5305 Connection *connection = Connection_val(conn);
5307 checkConnection(connection);
5309 enter_blocking_section();
5310 result = curl_easy_perform(connection->connection);
5311 leave_blocking_section();
5313 if (result != CURLE_OK)
5314 raiseError(connection, result);
5316 CAMLreturn(Val_unit);
5320 ** curl_easy_cleanup helper function
5323 CAMLprim value helper_curl_easy_cleanup(value conn)
5325 CAMLparam1(conn);
5326 Connection *connection = Connection_val(conn);
5328 checkConnection(connection);
5330 removeConnection(connection);
5332 CAMLreturn(Val_unit);
5336 ** curl_easy_duphandle helper function
5339 CAMLprim value helper_curl_easy_duphandle(value conn)
5341 CAMLparam1(conn);
5342 CAMLlocal1(result);
5343 Connection *connection = Connection_val(conn);
5345 checkConnection(connection);
5347 result = caml_alloc(1, Abstract_tag);
5348 Field(result, 0) = (value)duplicateConnection(connection);
5350 CAMLreturn(result);
5354 ** curl_easy_getinfo helper function
5357 enum GetInfoResultType {
5358 StringValue, LongValue, DoubleValue, StringListValue
5361 value convertStringList(struct curl_slist *slist)
5363 CAMLparam0();
5364 CAMLlocal3(result, current, next);
5365 struct curl_slist *p = slist;
5367 result = Val_int(0);
5368 current = Val_int(0);
5369 next = Val_int(0);
5371 while (p != NULL)
5373 next = alloc_tuple(2);
5374 Store_field(next, 0, copy_string(p->data));
5375 Store_field(next, 1, Val_int(0));
5377 if (result == Val_int(0))
5378 result = next;
5380 if (current != Val_int(0))
5381 Store_field(current, 1, next);
5383 current = next;
5385 p = p->next;
5388 curl_slist_free_all(slist);
5390 CAMLreturn(result);
5393 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5395 CAMLparam2(conn, option);
5396 CAMLlocal1(result);
5397 CURLcode curlResult;
5398 Connection *connection = Connection_val(conn);
5399 enum GetInfoResultType resultType;
5400 char *strValue = NULL;
5401 double doubleValue;
5402 long longValue;
5403 struct curl_slist *stringListValue = NULL;
5405 checkConnection(connection);
5407 switch(Long_val(option))
5409 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5410 case 0: /* CURLINFO_EFFECTIVE_URL */
5411 resultType = StringValue;
5413 curlResult = curl_easy_getinfo(connection->connection,
5414 CURLINFO_EFFECTIVE_URL,
5415 &strValue);
5416 break;
5417 #else
5418 #warning "libcurl does not provide CURLINFO_EFFECTIVE_URL"
5419 #endif
5421 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5422 case 1: /* CURLINFO_HTTP_CODE */
5423 case 2: /* CURLINFO_RESPONSE_CODE */
5424 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5425 resultType = LongValue;
5427 curlResult = curl_easy_getinfo(connection->connection,
5428 CURLINFO_RESPONSE_CODE,
5429 &longValue);
5430 #else
5431 resultType = LongValue;
5433 curlResult = curl_easy_getinfo(connection->connection,
5434 CURLINFO_HTTP_CODE,
5435 &longValue);
5436 #endif
5437 break;
5438 #endif
5440 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5441 case 3: /* CURLINFO_TOTAL_TIME */
5442 resultType = DoubleValue;
5444 curlResult = curl_easy_getinfo(connection->connection,
5445 CURLINFO_TOTAL_TIME,
5446 &doubleValue);
5447 break;
5448 #endif
5450 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5451 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5452 resultType = DoubleValue;
5454 curlResult = curl_easy_getinfo(connection->connection,
5455 CURLINFO_NAMELOOKUP_TIME,
5456 &doubleValue);
5457 break;
5458 #endif
5460 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5461 case 5: /* CURLINFO_CONNECT_TIME */
5462 resultType = DoubleValue;
5464 curlResult = curl_easy_getinfo(connection->connection,
5465 CURLINFO_CONNECT_TIME,
5466 &doubleValue);
5467 break;
5468 #endif
5470 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5471 case 6: /* CURLINFO_PRETRANSFER_TIME */
5472 resultType = DoubleValue;
5474 curlResult = curl_easy_getinfo(connection->connection,
5475 CURLINFO_PRETRANSFER_TIME,
5476 &doubleValue);
5477 break;
5478 #endif
5480 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5481 case 7: /* CURLINFO_SIZE_UPLOAD */
5482 resultType = DoubleValue;
5484 curlResult = curl_easy_getinfo(connection->connection,
5485 CURLINFO_SIZE_UPLOAD,
5486 &doubleValue);
5487 break;
5488 #endif
5490 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5491 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5492 resultType = DoubleValue;
5494 curlResult = curl_easy_getinfo(connection->connection,
5495 CURLINFO_SIZE_DOWNLOAD,
5496 &doubleValue);
5497 break;
5498 #endif
5500 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5501 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5502 resultType = DoubleValue;
5504 curlResult = curl_easy_getinfo(connection->connection,
5505 CURLINFO_SPEED_DOWNLOAD,
5506 &doubleValue);
5507 break;
5508 #endif
5510 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5511 case 10: /* CURLINFO_SPEED_UPLOAD */
5512 resultType = DoubleValue;
5514 curlResult = curl_easy_getinfo(connection->connection,
5515 CURLINFO_SPEED_UPLOAD,
5516 &doubleValue);
5517 break;
5519 #endif
5521 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5522 case 11: /* CURLINFO_HEADER_SIZE */
5523 resultType = LongValue;
5525 curlResult = curl_easy_getinfo(connection->connection,
5526 CURLINFO_HEADER_SIZE,
5527 &longValue);
5528 break;
5529 #endif
5531 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5532 case 12: /* CURLINFO_REQUEST_SIZE */
5533 resultType = LongValue;
5535 curlResult = curl_easy_getinfo(connection->connection,
5536 CURLINFO_REQUEST_SIZE,
5537 &longValue);
5538 break;
5539 #endif
5541 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5542 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5543 resultType = LongValue;
5545 curlResult = curl_easy_getinfo(connection->connection,
5546 CURLINFO_SSL_VERIFYRESULT,
5547 &longValue);
5548 break;
5549 #endif
5551 #if HAVE_DECL_CURLINFO_FILETIME
5552 case 14: /* CURLINFO_FILETIME */
5553 resultType = DoubleValue;
5555 curlResult = curl_easy_getinfo(connection->connection,
5556 CURLINFO_FILETIME,
5557 &longValue);
5559 doubleValue = longValue;
5560 break;
5561 #endif
5563 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5564 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5565 resultType = DoubleValue;
5567 curlResult = curl_easy_getinfo(connection->connection,
5568 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5569 &doubleValue);
5570 break;
5571 #endif
5573 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5574 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5575 resultType = DoubleValue;
5577 curlResult = curl_easy_getinfo(connection->connection,
5578 CURLINFO_CONTENT_LENGTH_UPLOAD,
5579 &doubleValue);
5580 break;
5581 #endif
5583 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5584 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5585 resultType = DoubleValue;
5587 curlResult = curl_easy_getinfo(connection->connection,
5588 CURLINFO_STARTTRANSFER_TIME,
5589 &doubleValue);
5590 break;
5591 #endif
5593 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5594 case 18: /* CURLINFO_CONTENT_TYPE */
5595 resultType = StringValue;
5597 curlResult = curl_easy_getinfo(connection->connection,
5598 CURLINFO_CONTENT_TYPE,
5599 &strValue);
5600 break;
5601 #endif
5603 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5604 case 19: /* CURLINFO_REDIRECT_TIME */
5605 resultType = DoubleValue;
5607 curlResult = curl_easy_getinfo(connection->connection,
5608 CURLINFO_REDIRECT_TIME,
5609 &doubleValue);
5610 break;
5611 #endif
5613 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5614 case 20: /* CURLINFO_REDIRECT_COUNT */
5615 resultType = LongValue;
5617 curlResult = curl_easy_getinfo(connection->connection,
5618 CURLINFO_REDIRECT_COUNT,
5619 &longValue);
5620 break;
5621 #endif
5623 #if HAVE_DECL_CURLINFO_PRIVATE
5624 case 21: /* CURLINFO_PRIVATE */
5625 resultType = StringValue;
5627 curlResult = curl_easy_getinfo(connection->connection,
5628 CURLINFO_PRIVATE,
5629 &strValue);
5630 break;
5631 #endif
5633 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5634 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5635 resultType = LongValue;
5637 curlResult = curl_easy_getinfo(connection->connection,
5638 CURLINFO_HTTP_CONNECTCODE,
5639 &longValue);
5640 break;
5641 #endif
5643 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5644 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5645 resultType = LongValue;
5647 curlResult = curl_easy_getinfo(connection->connection,
5648 CURLINFO_HTTPAUTH_AVAIL,
5649 &longValue);
5650 break;
5651 #endif
5653 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5654 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5655 resultType = LongValue;
5657 curlResult = curl_easy_getinfo(connection->connection,
5658 CURLINFO_PROXYAUTH_AVAIL,
5659 &longValue);
5660 break;
5661 #endif
5663 #if HAVE_DECL_CURLINFO_OS_ERRNO
5664 case 25: /* CURLINFO_OS_ERRNO */
5665 resultType = LongValue;
5667 curlResult = curl_easy_getinfo(connection->connection,
5668 CURLINFO_OS_ERRNO,
5669 &longValue);
5670 break;
5671 #endif
5673 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5674 case 26: /* CURLINFO_NUM_CONNECTS */
5675 resultType = LongValue;
5677 curlResult = curl_easy_getinfo(connection->connection,
5678 CURLINFO_NUM_CONNECTS,
5679 &longValue);
5680 break;
5681 #endif
5683 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5684 case 27: /* CURLINFO_SSL_ENGINES */
5685 resultType = StringListValue;
5687 curlResult = curl_easy_getinfo(connection->connection,
5688 CURLINFO_SSL_ENGINES,
5689 &stringListValue);
5690 break;
5691 #endif
5693 #if HAVE_DECL_CURLINFO_COOKIELIST
5694 case 28: /* CURLINFO_COOKIELIST */
5695 resultType = StringListValue;
5697 curlResult = curl_easy_getinfo(connection->connection,
5698 CURLINFO_COOKIELIST,
5699 &stringListValue);
5700 break;
5701 #endif
5703 #if HAVE_DECL_CURLINFO_LASTSOCKET
5704 case 29: /* CURLINFO_LASTSOCKET */
5705 resultType = LongValue;
5707 curlResult = curl_easy_getinfo(connection->connection,
5708 CURLINFO_LASTSOCKET,
5709 &longValue);
5710 break;
5711 #endif
5713 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5714 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5715 resultType = StringValue;
5717 curlResult = curl_easy_getinfo(connection->connection,
5718 CURLINFO_FTP_ENTRY_PATH,
5719 &strValue);
5720 break;
5721 #endif
5723 #if HAVE_DECL_CURLINFO_REDIRECT_URL
5724 case 31: /* CURLINFO_REDIRECT_URL */
5725 resultType = StringValue;
5727 curlResult = curl_easy_getinfo(connection->connection,
5728 CURLINFO_REDIRECT_URL,
5729 &strValue);
5730 break;
5731 #else
5732 #warning "libcurl does not provide CURLINFO_REDIRECT_URL"
5733 #endif
5735 #if HAVE_DECL_CURLINFO_PRIMARY_IP
5736 case 32: /* CURLINFO_PRIMARY_IP */
5737 resultType = StringValue;
5739 curlResult = curl_easy_getinfo(connection->connection,
5740 CURLINFO_PRIMARY_IP,
5741 &strValue);
5742 break;
5743 #else
5744 #warning "libcurl does not provide CURLINFO_PRIMARY_IP"
5745 #endif
5747 default:
5748 failwith("Invalid CURLINFO Option");
5749 break;
5752 if (curlResult != CURLE_OK)
5753 raiseError(connection, curlResult);
5755 switch (resultType)
5757 case StringValue:
5758 result = alloc(1, StringValue);
5759 Store_field(result, 0, copy_string(strValue?strValue:""));
5760 break;
5762 case LongValue:
5763 result = alloc(1, LongValue);
5764 Store_field(result, 0, Val_long(longValue));
5765 break;
5767 case DoubleValue:
5768 result = alloc(1, DoubleValue);
5769 Store_field(result, 0, copy_double(doubleValue));
5770 break;
5772 case StringListValue:
5773 result = alloc(1, StringListValue);
5774 Store_field(result, 0, convertStringList(stringListValue));
5775 break;
5778 CAMLreturn(result);
5782 ** curl_escape helper function
5785 CAMLprim value helper_curl_escape(value str)
5787 CAMLparam1(str);
5788 CAMLlocal1(result);
5789 char *curlResult;
5791 curlResult = curl_escape(String_val(str), string_length(str));
5792 result = copy_string(curlResult);
5793 free(curlResult);
5795 CAMLreturn(result);
5799 ** curl_unescape helper function
5802 CAMLprim value helper_curl_unescape(value str)
5804 CAMLparam1(str);
5805 CAMLlocal1(result);
5806 char *curlResult;
5808 curlResult = curl_unescape(String_val(str), string_length(str));
5809 result = copy_string(curlResult);
5810 free(curlResult);
5812 CAMLreturn(result);
5816 ** curl_getdate helper function
5819 CAMLprim value helper_curl_getdate(value str, value now)
5821 CAMLparam2(str, now);
5822 CAMLlocal1(result);
5823 time_t curlResult;
5824 time_t curlNow;
5826 curlNow = (time_t)Double_val(now);
5827 curlResult = curl_getdate(String_val(str), &curlNow);
5828 result = copy_double((double)curlResult);
5830 CAMLreturn(result);
5834 ** curl_version helper function
5837 CAMLprim value helper_curl_version(void)
5839 CAMLparam0();
5840 CAMLlocal1(result);
5841 char *str;
5843 str = curl_version();
5844 result = copy_string(str);
5846 CAMLreturn(result);
5849 CAMLprim value caml_curl_version_info(value unit)
5851 CAMLparam1(unit);
5852 CAMLlocal3(v, vlist, vnum);
5853 const char* const* p = NULL;
5855 curl_version_info_data* data = curl_version_info(CURLVERSION_NOW);
5856 if (NULL == data) caml_failwith("curl_version_info");
5858 vlist = Val_emptylist;
5859 for (p = data->protocols; NULL != *p; p++)
5861 vlist = Val_cons(vlist, caml_copy_string(*p));
5864 vnum = caml_alloc_tuple(3);
5865 Store_field(vnum,0,Val_int(0xFF & (data->version_num >> 16)));
5866 Store_field(vnum,1,Val_int(0xFF & (data->version_num >> 8)));
5867 Store_field(vnum,2,Val_int(0xFF & (data->version_num)));
5869 v = caml_alloc_tuple(7);
5870 Store_field(v,0,caml_copy_string(data->version));
5871 Store_field(v,1,vnum);
5872 Store_field(v,2,caml_copy_string(data->host));
5873 Store_field(v,3,Val_int(data->features));
5874 Store_field(v,4,data->ssl_version ? Val_some(caml_copy_string(data->ssl_version)) : Val_none);
5875 Store_field(v,5,data->libz_version ? Val_some(caml_copy_string(data->libz_version)) : Val_none);
5876 Store_field(v,6,vlist);
5878 CAMLreturn(v);
5882 * Curl multi stack support
5884 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
5885 * Other exported functions are prefixed with caml_curlm_, some of them
5886 * can/should be decomposed into smaller parts.
5889 struct ml_multi_handle
5891 CURLM* handle;
5892 value values; /* callbacks */
5895 enum
5897 curlmopt_socket_function,
5899 /* last, not used */
5900 multi_values_total,
5903 typedef struct ml_multi_handle ml_multi_handle;
5905 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
5906 #define CURLM_val(v) (Multi_val(v)->handle)
5908 static struct custom_operations curl_multi_ops = {
5909 "ygrek.curl_multi",
5910 custom_finalize_default,
5911 custom_compare_default,
5912 custom_hash_default,
5913 custom_serialize_default,
5914 custom_deserialize_default
5917 CAMLprim value caml_curl_multi_init(value unit)
5919 CAMLparam1(unit);
5920 CAMLlocal1(v);
5921 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
5922 CURLM* h = curl_multi_init();
5924 if (!h)
5926 caml_stat_free(multi);
5927 failwith("caml_curl_multi_init");
5930 multi->handle = h;
5931 multi->values = caml_alloc(multi_values_total, 0);
5932 caml_register_generational_global_root(&multi->values);
5934 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
5935 Multi_val(v) = multi;
5937 CAMLreturn(v);
5940 CAMLprim value caml_curl_multi_cleanup(value handle)
5942 CAMLparam1(handle);
5943 ml_multi_handle* h = Multi_val(handle);
5945 if (NULL == h)
5946 CAMLreturn(Val_unit);
5948 caml_remove_generational_global_root(&h->values);
5950 if (CURLM_OK != curl_multi_cleanup(h->handle))
5951 failwith("caml_curl_multi_cleanup");
5953 Multi_val(handle) = (ml_multi_handle*)NULL;
5955 CAMLreturn(Val_unit);
5958 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
5960 int msgs_in_queue = 0;
5962 while (1)
5964 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
5965 if (NULL == msg) return NULL;
5966 if (CURLMSG_DONE == msg->msg)
5968 CURL* easy_handle = msg->easy_handle;
5969 if (result) *result = msg->data.result;
5970 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
5972 //failwith("curlm_remove_finished");
5974 return easy_handle;
5979 CAMLprim value caml_curlm_remove_finished(value v_multi)
5981 CAMLparam1(v_multi);
5982 CAMLlocal2(v_easy, v_tuple);
5983 CURL* handle;
5984 CURLM* multi_handle;
5985 CURLcode result;
5987 multi_handle = CURLM_val(v_multi);
5989 caml_enter_blocking_section();
5990 handle = curlm_remove_finished(multi_handle,&result);
5991 caml_leave_blocking_section();
5993 if (NULL == handle)
5995 CAMLreturn(Val_none);
5997 else
5999 /* not good: same handle, but different block */
6000 v_easy = caml_alloc(1, Abstract_tag);
6001 Field(v_easy, 0) = (value)findConnection(handle);
6002 v_tuple = caml_alloc(2, 0);
6003 Store_field(v_tuple,0,v_easy);
6004 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
6005 CAMLreturn(Val_some(v_tuple));
6009 static int curlm_wait_data(CURLM* multi_handle)
6011 struct timeval timeout;
6012 CURLMcode ret;
6014 fd_set fdread;
6015 fd_set fdwrite;
6016 fd_set fdexcep;
6017 int maxfd;
6019 FD_ZERO(&fdread);
6020 FD_ZERO(&fdwrite);
6021 FD_ZERO(&fdexcep);
6023 /* set a suitable timeout */
6024 timeout.tv_sec = 1;
6025 timeout.tv_usec = 0;
6027 /* get file descriptors from the transfers */
6028 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
6030 if (ret == CURLM_OK && maxfd >= 0)
6032 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
6033 if (-1 != rc) return 0;
6034 //printf("select error\n");
6036 else
6038 //printf("curl_multi_fdset error\n");
6040 return 1;
6043 CAMLprim value caml_curlm_wait_data(value v_multi)
6045 CAMLparam1(v_multi);
6046 int ret;
6047 CURLM* h;
6049 h = CURLM_val(v_multi);
6051 caml_enter_blocking_section();
6052 ret = curlm_wait_data(h);
6053 caml_leave_blocking_section();
6055 CAMLreturn(Val_bool(0 == ret));
6058 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
6060 CAMLparam2(v_multi,v_easy);
6062 if (CURLM_OK != curl_multi_add_handle(CURLM_val(v_multi), Connection_val(v_easy)->connection))
6063 failwith("caml_curl_multi_add_handle");
6065 CAMLreturn(Val_unit);
6068 CAMLprim value caml_curl_multi_perform_all(value v_multi)
6070 CAMLparam1(v_multi);
6071 CURLM* h;
6072 int still_running = 0;
6074 h = CURLM_val(v_multi);
6076 caml_enter_blocking_section();
6077 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
6078 caml_leave_blocking_section();
6080 CAMLreturn(Val_int(still_running));
6083 CAMLprim value helper_curl_easy_strerror(value v_code)
6085 CAMLparam1(v_code);
6086 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));