fix: do not use Store_field on Abstract_tag blocks
[ocurl.git] / curl-helper.c
blob8a8e6970de07be8bf43038eef455d6be5f69adf5
1 /***
2 *** curl-helper.c
3 ***
4 *** Copyright (c) 2003-2008, Lars Nilsson, <lars@quantumchamaeleon.com>
5 ***/
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <curl/curl.h>
13 #include <caml/alloc.h>
14 #include <caml/memory.h>
15 #include <caml/mlvalues.h>
16 #include <caml/callback.h>
17 #include <caml/fail.h>
18 #include <caml/custom.h>
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #else
23 #warning "No config file given."
24 #endif
26 #if defined(_MSC_VER)
27 #ifdef interface
28 #undef interface
29 #endif
30 #endif
32 void leave_blocking_section(void);
33 void enter_blocking_section(void);
35 #define Val_none Val_int(0)
37 static __inline value
38 Val_some( value v )
40 CAMLparam1( v );
41 CAMLlocal1( some );
42 some = caml_alloc(1, 0);
43 Store_field( some, 0, v );
44 CAMLreturn( some );
47 typedef struct Connection Connection;
48 typedef struct ConnectionList ConnectionList;
50 #define Connection_val(v) ((Connection *)Field(v, 0))
52 enum OcamlValues
54 OcamlWriteCallback,
55 OcamlReadCallback,
56 OcamlErrorBuffer,
57 OcamlPostFields,
58 OcamlHTTPHeader,
59 OcamlHTTPPost,
60 OcamlQuote,
61 OcamlPostQuote,
62 OcamlHeaderCallback,
63 OcamlProgressCallback,
64 OcamlDebugCallback,
65 OcamlHTTP200Aliases,
66 OcamlIOCTLCallback,
67 OcamlSeekFunctionCallback,
69 OcamlURL,
70 OcamlProxy,
71 OcamlUserPWD,
72 OcamlProxyUserPWD,
73 OcamlRange,
74 OcamlReferer,
75 OcamlUserAgent,
76 OcamlFTPPort,
77 OcamlCookie,
78 OcamlHTTPPostStrings,
79 OcamlSSLCert,
80 OcamlSSLCertType,
81 OcamlSSLCertPasswd,
82 OcamlSSLKey,
83 OcamlSSLKeyType,
84 OcamlSSLKeyPasswd,
85 OcamlSSLEngine,
86 OcamlCookieFile,
87 OcamlCustomRequest,
88 OcamlInterface,
89 OcamlCAInfo,
90 OcamlCAPath,
91 OcamlRandomFile,
92 OcamlEGDSocket,
93 OcamlCookieJar,
94 OcamlSSLCipherList,
95 OcamlPrivate,
96 OcamlNETRCFile,
97 OcamlFTPAccount,
98 OcamlCookieList,
99 OcamlFTPAlternativeToUser,
100 OcamlSSHPublicKeyFile,
101 OcamlSSHPrivateKeyFile,
102 OcamlSSHHostPublicKeyMD5,
103 OcamlCopyPostFields,
105 /* Not used, last for size */
106 OcamlValuesSize
109 struct Connection
111 CURL *connection;
112 Connection *next;
113 Connection *prev;
115 value ocamlValues;
117 char *url;
118 char *proxy;
119 char *userPwd;
120 char *proxyUserPwd;
121 char *range;
122 char *errorBuffer;
123 char *postFields;
124 int postFieldSize;
125 char *referer;
126 char *userAgent;
127 char *ftpPort;
128 char *cookie;
129 struct curl_slist *httpHeader;
130 struct curl_httppost *httpPostFirst;
131 struct curl_httppost *httpPostLast;
132 struct curl_slist *httpPostStrings;
133 char *sslCert;
134 char *sslCertType;
135 char *sslCertPasswd;
136 char *sslKey;
137 char *sslKeyType;
138 char *sslKeyPasswd;
139 char *sslEngine;
140 struct curl_slist *quote;
141 struct curl_slist *postQuote;
142 char *cookieFile;
143 char *customRequest;
144 char *interface;
145 char *caInfo;
146 char *caPath;
147 char *randomFile;
148 char *egdSocket;
149 char *cookieJar;
150 char *sslCipherList;
151 char *private;
152 struct curl_slist *http200Aliases;
153 char *netrcFile;
154 char *ftpaccount;
155 char *cookielist;
156 char *ftpAlternativeToUser;
157 char *sshPublicKeyFile;
158 char *sshPrivateKeyFile;
159 char *sshHostPublicKeyMD5;
160 char *copyPostFields;
163 struct ConnectionList
165 Connection *head;
166 Connection *tail;
169 static ConnectionList connectionList = {NULL, NULL};
171 typedef struct CURLErrorMapping CURLErrorMapping;
173 struct CURLErrorMapping
175 char *name;
176 CURLcode error;
179 CURLErrorMapping errorMap[] =
181 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
182 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
183 #else
184 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
185 #endif
186 #if HAVE_DECL_CURLE_FAILED_INIT
187 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
188 #else
189 {"CURLE_FAILED_INIT", -1},
190 #endif
191 #if HAVE_DECL_CURLE_URL_MALFORMAT
192 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
193 #else
194 {"CURLE_URL_MALFORMAT", -1},
195 #endif
196 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
197 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
198 #else
199 {"CURLE_URL_MALFORMAT_USER", -1},
200 #endif
201 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
202 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
203 #else
204 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
205 #endif
206 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
207 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
208 #else
209 {"CURLE_COULDNT_RESOLVE_HOST", -1},
210 #endif
211 #if HAVE_DECL_CURLE_COULDNT_CONNECT
212 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
213 #else
214 {"CURLE_COULDNT_CONNECT", -1},
215 #endif
216 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
217 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
218 #else
219 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
220 #endif
221 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
222 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
223 #else
224 {"CURLE_FTP_ACCESS_DENIED", -1},
225 #endif
226 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
227 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
228 #else
229 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
230 #endif
231 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
232 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
233 #else
234 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
235 #endif
236 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
237 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
238 #else
239 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
240 #endif
241 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
242 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
243 #else
244 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
245 #endif
246 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
247 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
248 #else
249 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
250 #endif
251 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
252 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
253 #else
254 {"CURLE_FTP_CANT_GET_HOST", -1},
255 #endif
256 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
257 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
258 #else
259 {"CURLE_FTP_CANT_RECONNECT", -1},
260 #endif
261 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
262 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
263 #else
264 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
265 #endif
266 #if HAVE_DECL_CURLE_PARTIAL_FILE
267 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
268 #else
269 {"CURLE_PARTIAL_FILE", -1},
270 #endif
271 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
272 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
273 #else
274 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
275 #endif
276 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
277 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
278 #else
279 {"CURLE_FTP_WRITE_ERROR", -1},
280 #endif
281 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
282 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
283 #else
284 {"CURLE_FTP_QUOTE_ERROR", -1},
285 #endif
286 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
287 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
288 #else
289 {"CURLE_HTTP_NOT_FOUND", -1},
290 #endif
291 #if HAVE_DECL_CURLE_WRITE_ERROR
292 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
293 #else
294 {"CURLE_WRITE_ERROR", -1},
295 #endif
296 #if HAVE_DECL_CURLE_MALFORMAT_USER
297 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
298 #else
299 {"CURLE_MALFORMAT_USER", -1},
300 #endif
301 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
302 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
303 #else
304 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
305 #endif
306 #if HAVE_DECL_CURLE_READ_ERROR
307 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
308 #else
309 {"CURLE_READ_ERROR", -1},
310 #endif
311 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
312 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
313 #else
314 {"CURLE_OUT_OF_MEMORY", -1},
315 #endif
316 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
317 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
318 #else
319 {"CURLE_OPERATION_TIMEOUTED", -1},
320 #endif
321 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
322 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
323 #else
324 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
325 #endif
326 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
327 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
328 #else
329 {"CURLE_FTP_PORT_FAILED", -1},
330 #endif
331 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
332 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
333 #else
334 {"CURLE_FTP_COULDNT_USE_REST", -1},
335 #endif
336 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
337 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
338 #else
339 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
340 #endif
341 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
342 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
343 #else
344 {"CURLE_HTTP_RANGE_ERROR", -1},
345 #endif
346 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
347 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
348 #else
349 {"CURLE_HTTP_POST_ERROR", -1},
350 #endif
351 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
352 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
353 #else
354 {"CURLE_SSL_CONNECT_ERROR", -1},
355 #endif
356 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
357 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
358 #else
359 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
360 #endif
361 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
362 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
363 #else
364 {"CURLE_FILE_COULDNT_READ_FILE", -1},
365 #endif
366 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
367 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
368 #else
369 {"CURLE_LDAP_CANNOT_BIND", -1},
370 #endif
371 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
372 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
373 #else
374 {"CURLE_LDAP_SEARCH_FAILED", -1},
375 #endif
376 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
377 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
378 #else
379 {"CURLE_LIBRARY_NOT_FOUND", -1},
380 #endif
381 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
382 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
383 #else
384 {"CURLE_FUNCTION_NOT_FOUND", -1},
385 #endif
386 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
387 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
388 #else
389 {"CURLE_ABORTED_BY_CALLBACK", -1},
390 #endif
391 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
392 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
393 #else
394 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
395 #endif
396 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
397 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
398 #else
399 {"CURLE_BAD_CALLING_ORDER", -1},
400 #endif
401 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
402 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
403 #else
404 {"CURLE_HTTP_PORT_FAILED", -1},
405 #endif
406 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
407 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
408 #else
409 {"CURLE_BAD_PASSWORD_ENTERED", -1},
410 #endif
411 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
412 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
413 #else
414 {"CURLE_TOO_MANY_REDIRECTS", -1},
415 #endif
416 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
417 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
418 #else
419 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
420 #endif
421 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
422 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
423 #else
424 {"CURLE_TELNET_OPTION_SYNTAX", -1},
425 #endif
426 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
427 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
428 #else
429 {"CURLE_SSL_PEER_CERTIFICATE", -1},
430 #endif
431 #if HAVE_DECL_CURLE_GOT_NOTHING
432 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
433 #else
434 {"CURLE_GOT_NOTHING", -1},
435 #endif
436 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
437 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
438 #else
439 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
440 #endif
441 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
442 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
443 #else
444 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
445 #endif
446 #if HAVE_DECL_CURLE_SEND_ERROR
447 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
448 #else
449 {"CURLE_SEND_ERROR", -1},
450 #endif
451 #if HAVE_DECL_CURLE_RECV_ERROR
452 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
453 #else
454 {"CURLE_RECV_ERROR", -1},
455 #endif
456 #if HAVE_DECL_CURLE_SHARE_IN_USE
457 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
458 #else
459 {"CURLE_SHARE_IN_USE", -1},
460 #endif
461 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
462 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
463 #else
464 {"CURLE_SSL_CERTPROBLEN", -1},
465 #endif
466 #if HAVE_DECL_CURLE_SSL_CIPHER
467 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
468 #else
469 {"CURLE_SSL_CIPHER", -1},
470 #endif
471 #if HAVE_DECL_CURLE_SSL_CACERT
472 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
473 #else
474 {"CURLE_SSL_CACERT", -1},
475 #endif
476 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
477 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
478 #else
479 {"CURLE_BAD_CONTENT_ENCODING", -1},
480 #endif
481 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
482 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
483 #else
484 {"CURLE_LDAP_INVALID_URL", -1},
485 #endif
486 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
487 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
488 #else
489 {"CURLE_FILESIZE_EXCEEDED", -1},
490 #endif
491 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
492 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
493 #else
494 {"CURLE_FTP_SSL_FAILED", -1},
495 #endif
496 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
497 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
498 #else
499 {"CURLE_SEND_FAIL_REWIND", -1},
500 #endif
501 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
502 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
503 #else
504 {"CURLE_SSL_ENGINE_INITFAILED", -1},
505 #endif
506 #if HAVE_DECL_CURLE_LOGIN_DENIED
507 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
508 #else
509 {"CURLE_LOGIN_DENIED", -1},
510 #endif
511 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
512 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
513 #else
514 {"CURLE_TFTP_NOTFOUND", -1},
515 #endif
516 #if HAVE_DECL_CURLE_TFTP_PERM
517 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
518 #else
519 {"CURLE_TFTP_PERM", -1},
520 #endif
521 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
522 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
523 #else
524 {"CURLE_REMOTE_DISK_FULL", -1},
525 #endif
526 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
527 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
528 #else
529 {"CURLE_TFTP_ILLEGAL", -1},
530 #endif
531 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
532 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
533 #else
534 {"CURLE_TFTP_UNKNOWNID", -1},
535 #endif
536 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
537 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
538 #else
539 {"CURLE_REMOTE_FILE_EXISTS", -1},
540 #endif
541 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
542 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
543 #else
544 {"CURLE_TFTP_NOSUCHUSER", -1},
545 #endif
546 #if HAVE_DECL_CURLE_CONV_FAILED
547 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
548 #else
549 {"CURLE_CONV_FAILED", -1},
550 #endif
551 #if HAVE_DECL_CURLE_CONV_REQUIRED
552 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
553 #else
554 {"CURLE_CONV_REQUIRED", -1},
555 #endif
556 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
557 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
558 #else
559 {"CURLE_SSL_CACERT_BADFILE", -1},
560 #endif
561 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
562 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
563 #else
564 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
565 #endif
566 #if HAVE_DECL_CURLE_SSH
567 {"CURLE_SSH", CURLE_SSH},
568 #else
569 {"CURLE_SSH", -1},
570 #endif
571 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
572 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
573 #else
574 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
575 #endif
576 #if HAVE_DECL_CURLE_AGAIN
577 {"CURLE_AGAIN", CURLE_AGAIN},
578 #else
579 {"CURLE_AGAIN", -1},
580 #endif
581 {"CURLE_OK", CURLE_OK},
582 {NULL, 0}
585 typedef struct CURLOptionMapping CURLOptionMapping;
587 struct CURLOptionMapping
589 void (*optionHandler)(Connection *, value);
590 char *name;
591 CURLoption option;
594 CURLOptionMapping unimplementedOptionMap[] =
596 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
597 {NULL, NULL, 0}
600 static void handleWriteFunction(Connection *, value);
601 static void handleReadFunction(Connection *, value);
602 static void handleInFileSize(Connection *, value);
603 static void handleURL(Connection *, value);
604 static void handleProxy(Connection *, value);
605 static void handleProxyPort(Connection *, value);
606 static void handleHTTPProxyTunnel(Connection *, value);
607 static void handleVerbose(Connection *, value);
608 static void handleHeader(Connection *, value);
609 static void handleNoProgress(Connection *, value);
610 static void handleNoSignal(Connection *, value);
611 static void handleNoBody(Connection *, value);
612 static void handleFailOnError(Connection *, value);
613 static void handleUpload(Connection *, value);
614 static void handlePost(Connection *, value);
615 static void handleFTPListOnly(Connection *, value);
616 static void handleFTPAppend(Connection *, value);
617 static void handleNETRC(Connection *, value);
618 static void handleEncoding(Connection *, value);
619 static void handleFollowLocation(Connection *, value);
620 static void handleTransferText(Connection *, value);
621 static void handlePut(Connection *, value);
622 static void handleUserPwd(Connection *, value);
623 static void handleProxyUserPwd(Connection *, value);
624 static void handleRange(Connection *, value);
625 static void handleErrorBuffer(Connection *, value);
626 static void handleTimeout(Connection *, value);
627 static void handlePostFields(Connection *, value);
628 static void handlePostFieldSize(Connection *, value);
629 static void handleReferer(Connection *, value);
630 static void handleUserAgent(Connection *, value);
631 static void handleFTPPort(Connection *, value);
632 static void handleLowSpeedLimit(Connection *, value);
633 static void handleLowSpeedTime(Connection *, value);
634 static void handleResumeFrom(Connection *, value);
635 static void handleCookie(Connection *, value);
636 static void handleHTTPHeader(Connection *, value);
637 static void handleHTTPPost(Connection *, value);
638 static void handleSSLCert(Connection *, value);
639 static void handleSSLCertType(Connection *, value);
640 static void handleSSLCertPasswd(Connection *, value);
641 static void handleSSLKey(Connection *, value);
642 static void handleSSLKeyType(Connection *, value);
643 static void handleSSLKeyPasswd(Connection *, value);
644 static void handleSSLEngine(Connection *, value);
645 static void handleSSLEngineDefault(Connection *, value);
646 static void handleCRLF(Connection *, value);
647 static void handleQuote(Connection *, value);
648 static void handlePostQuote(Connection *, value);
649 static void handleHeaderFunction(Connection *, value);
650 static void handleCookieFile(Connection *, value);
651 static void handleSSLVersion(Connection *, value);
652 static void handleTimeCondition(Connection *, value);
653 static void handleTimeValue(Connection *, value);
654 static void handleCustomRequest(Connection *, value);
655 static void handleInterface(Connection *, value);
656 static void handleKRB4Level(Connection *, value);
657 static void handleProgressFunction(Connection *, value);
658 static void handleSSLVerifyPeer(Connection *, value);
659 static void handleCAInfo(Connection *, value);
660 static void handleCAPath(Connection *, value);
661 static void handleFileTime(Connection *, value);
662 static void handleMaxRedirs(Connection *, value);
663 static void handleMaxConnects(Connection *, value);
664 static void handleClosePolicy(Connection *, value);
665 static void handleFreshConnect(Connection *, value);
666 static void handleForbidReuse(Connection *, value);
667 static void handleRandomFile(Connection *, value);
668 static void handleEGDSocket(Connection *, value);
669 static void handleConnectTimeout(Connection *, value);
670 static void handleHTTPGet(Connection *, value);
671 static void handleSSLVerifyHost(Connection *, value);
672 static void handleCookieJar(Connection *, value);
673 static void handleSSLCipherList(Connection *, value);
674 static void handleHTTPVersion(Connection *, value);
675 static void handleFTPUseEPSV(Connection *, value);
676 static void handleDNSCacheTimeout(Connection *, value);
677 static void handleDNSUseGlobalCache(Connection *, value);
678 static void handleDebugFunction(Connection *, value);
679 static void handlePrivate(Connection *, value);
680 static void handleHTTP200Aliases(Connection *, value);
681 static void handleUnrestrictedAuth(Connection *, value);
682 static void handleFTPUseEPRT(Connection *, value);
683 static void handleHTTPAuth(Connection *, value);
684 static void handleFTPCreateMissingDirs(Connection *, value);
685 static void handleProxyAuth(Connection *, value);
686 static void handleFTPResponseTimeout(Connection *, value);
687 static void handleIPResolve(Connection *, value);
688 static void handleMaxFileSize(Connection *, value);
689 static void handleInFileSizeLarge(Connection *, value);
690 static void handleResumeFromLarge(Connection *, value);
691 static void handleMaxFileSizeLarge(Connection *, value);
692 static void handleNETRCFile(Connection *, value);
693 static void handleFTPSSL(Connection *, value);
694 static void handlePostFieldSizeLarge(Connection *, value);
695 static void handleTCPNoDelay(Connection *, value);
696 static void handleFTPSSLAuth(Connection *, value);
697 static void handleIOCTLFunction(Connection *, value);
698 static void handleFTPAccount(Connection *, value);
699 static void handleCookieList(Connection *, value);
700 static void handleIgnoreContentLength(Connection *, value);
701 static void handleFTPSkipPASVIP(Connection *, value);
702 static void handleFTPFileMethod(Connection *, value);
703 static void handleLocalPort(Connection *, value);
704 static void handleLocalPortRange(Connection *, value);
705 static void handleConnectOnly(Connection *, value);
706 static void handleMaxSendSpeedLarge(Connection *, value);
707 static void handleMaxRecvSpeedLarge(Connection *, value);
708 static void handleFTPAlternativeToUser(Connection *, value);
709 static void handleSSLSessionIdCache(Connection *, value);
710 static void handleSSHAuthTypes(Connection *, value);
711 static void handleSSHPublicKeyFile(Connection *, value);
712 static void handleSSHPrivateKeyFile(Connection *, value);
713 static void handleFTPSSLCCC(Connection *, value);
714 static void handleTimeoutMS(Connection *, value);
715 static void handleConnectTimeoutMS(Connection *, value);
716 static void handleHTTPTransferDecoding(Connection *, value);
717 static void handleHTTPContentDecoding(Connection *, value);
718 static void handleNewFilePerms(Connection *, value);
719 static void handleNewDirectoryPerms(Connection *, value);
720 static void handlePost301(Connection *, value);
721 static void handleSSHHostPublicKeyMD5(Connection *, value);
722 static void handleCopyPostFields(Connection *, value);
723 static void handleProxyTransferMode(Connection *, value);
724 static void handleSeekFunction(Connection *, value);
726 CURLOptionMapping implementedOptionMap[] =
728 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
729 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
730 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
731 {handleURL, "CURLOPT_URL", CURLOPT_URL},
732 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
733 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
734 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
735 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
736 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
737 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
738 #if HAVE_DECL_CURLOPT_NOSIGNAL
739 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
740 #else
741 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
742 #endif
743 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
744 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
745 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
746 {handlePost, "CURLOPT_POST", CURLOPT_POST},
747 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
748 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
749 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
750 #if HAVE_DECL_CURLOPT_ENCODING
751 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
752 #else
753 {handleEncoding, "CURLOPT_ENCODING", 0},
754 #endif
755 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
756 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
757 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
758 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
759 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
760 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
761 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
762 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
763 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
764 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
765 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
766 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
767 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
768 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
769 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
770 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
771 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
772 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
773 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
774 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
775 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
776 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
777 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
778 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
779 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
780 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
781 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
782 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
783 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
784 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
785 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
786 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
787 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
788 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
789 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
790 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
791 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
792 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
793 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
794 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
795 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
796 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
797 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
798 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
799 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
800 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
801 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
802 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
803 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
804 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
805 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
806 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
807 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
808 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
809 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
810 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
811 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
812 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
813 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
814 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
815 #if HAVE_DECL_CURLOPT_PRIVATE
816 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
817 #else
818 {handlePrivate, "CURLOPT_PRIVATE", 0},
819 #endif
820 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
821 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
822 #else
823 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
824 #endif
825 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
826 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
827 #else
828 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
829 #endif
830 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
831 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
832 #else
833 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
834 #endif
835 #if HAVE_DECL_CURLOPT_HTTPAUTH
836 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
837 #else
838 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
839 #endif
840 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
841 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
842 #else
843 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
844 #endif
845 #if HAVE_DECL_CURLOPT_PROXYAUTH
846 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
847 #else
848 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
849 #endif
850 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
851 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
852 #else
853 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
854 #endif
855 #if HAVE_DECL_CURLOPT_IPRESOLVE
856 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
857 #else
858 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
859 #endif
860 #if HAVE_DECL_CURLOPT_MAXFILESIZE
861 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
862 #else
863 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
864 #endif
865 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
866 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
867 #else
868 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
869 #endif
870 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
871 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
872 #else
873 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
874 #endif
875 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
876 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
877 #else
878 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
879 #endif
880 #if HAVE_DECL_CURLOPT_NETRC_FILE
881 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
882 #else
883 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
884 #endif
885 #if HAVE_DECL_CURLOPT_FTP_SSL
886 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
887 #else
888 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
889 #endif
890 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
891 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
892 #else
893 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
894 #endif
895 #if HAVE_DECL_CURLOPT_TCP_NODELAY
896 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
897 #else
898 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
899 #endif
900 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
901 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
902 #else
903 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
904 #endif
905 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
906 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
907 #else
908 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
909 #endif
910 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
911 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
912 #else
913 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
914 #endif
915 #if HAVE_DECL_CURLOPT_COOKIELIST
916 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
917 #else
918 {handleCookieList, "CURLOPT_COOKIELIST", 0},
919 #endif
920 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
921 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
922 #else
923 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
924 #endif
925 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
926 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
927 #else
928 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
929 #endif
930 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
931 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
932 #else
933 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
934 #endif
935 #if HAVE_DECL_CURLOPT_LOCALPORT
936 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
937 #else
938 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
939 #endif
940 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
941 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
942 #else
943 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
944 #endif
945 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
946 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
947 #else
948 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
949 #endif
950 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
951 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
952 #else
953 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
954 #endif
955 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
956 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
957 #else
958 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
959 #endif
960 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
961 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
962 #else
963 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
964 #endif
965 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
966 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
967 #else
968 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
969 #endif
970 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
971 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
972 #else
973 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
974 #endif
975 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
976 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
977 #else
978 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
979 #endif
980 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
981 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
982 #else
983 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
984 #endif
985 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
986 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
987 #else
988 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
989 #endif
990 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
991 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
992 #else
993 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
994 #endif
995 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
996 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
997 #else
998 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
999 #endif
1000 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1001 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1002 #else
1003 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1004 #endif
1005 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1006 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1007 #else
1008 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1009 #endif
1010 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1011 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1012 #else
1013 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1014 #endif
1015 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1016 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1017 #else
1018 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1019 #endif
1020 #if HAVE_DECL_CURLOPT_POST301
1021 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1022 #else
1023 {handlePost301, "CURLOPT_POST301", 0},
1024 #endif
1025 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1026 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1027 #else
1028 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1029 #endif
1030 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1031 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1032 #else
1033 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1034 #endif
1035 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1036 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1037 #else
1038 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1039 #endif
1040 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1041 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1042 #else
1043 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1044 #endif
1047 static char *findOption(CURLOptionMapping optionMap[],
1048 CURLoption option)
1050 return optionMap[option].name;
1053 static void free_curl_slist(struct curl_slist *slist)
1055 struct curl_slist *item;
1057 if (slist == NULL)
1058 return;
1060 item = slist;
1062 while (item != NULL)
1064 free(item->data);
1065 item->data = NULL;
1066 item = item->next;
1069 curl_slist_free_all(slist);
1072 static void raiseError(Connection *conn, CURLcode code)
1074 CAMLparam0();
1075 CAMLlocal1(exceptionData);
1076 value *exception;
1077 char *errorString = "Unknown Error";
1078 int i;
1080 for (i = 0; errorMap[i].name != NULL; i++)
1082 if (errorMap[i].error == code)
1084 errorString = errorMap[i].name;
1085 break;
1089 exceptionData = alloc(3, 0);
1091 Field(exceptionData, 0) = Val_int(code);
1092 Field(exceptionData, 1) = Val_int(code);
1093 Field(exceptionData, 2) = copy_string(errorString);
1095 if (conn != NULL && conn->errorBuffer != NULL)
1097 Field(Field(conn->ocamlValues, OcamlErrorBuffer), 0) =
1098 copy_string(conn->errorBuffer);
1101 exception = caml_named_value("CurlException");
1103 if (exception == NULL)
1104 failwith(errorString);
1106 raise_with_arg(*exception, exceptionData);
1108 CAMLreturn0;
1111 static void resetOcamlValues(Connection* connection)
1113 int i;
1115 for (i = 0; i < OcamlValuesSize; i++)
1116 Store_field(connection->ocamlValues, i, Val_unit);
1119 static Connection *newConnection(void)
1121 Connection *connection;
1123 connection = (Connection *)malloc(sizeof(Connection));
1125 enter_blocking_section();
1126 connection->connection = curl_easy_init();
1127 leave_blocking_section();
1129 connection->next = NULL;
1130 connection->prev = NULL;
1132 if (connectionList.tail == NULL)
1134 connectionList.tail = connection;
1135 connectionList.head = connection;
1137 else
1139 connection->prev = connectionList.head;
1140 connectionList.head->next = connection;
1141 connectionList.head = connection;
1144 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1145 resetOcamlValues(connection);
1146 register_global_root(&connection->ocamlValues);
1148 connection->url = NULL;
1149 connection->proxy = NULL;
1150 connection->userPwd = NULL;
1151 connection->proxyUserPwd = NULL;
1152 connection->range = NULL;
1153 connection->errorBuffer = NULL;
1154 connection->postFields = NULL;
1155 connection->postFieldSize = -1;
1156 connection->referer = NULL;
1157 connection->userAgent = NULL;
1158 connection->ftpPort = NULL;
1159 connection->cookie = NULL;
1160 connection->httpHeader = NULL;
1161 connection->httpPostFirst = NULL;
1162 connection->httpPostLast = NULL;
1163 connection->httpPostStrings = NULL;
1164 connection->sslCert = NULL;
1165 connection->sslCertType = NULL;
1166 connection->sslCertPasswd = NULL;
1167 connection->sslKey = NULL;
1168 connection->sslKeyType = NULL;
1169 connection->sslKeyPasswd = NULL;
1170 connection->sslEngine = NULL;
1171 connection->quote = NULL;
1172 connection->postQuote = NULL;
1173 connection->cookieFile = NULL;
1174 connection->customRequest = NULL;
1175 connection->interface = NULL;
1176 connection->caInfo = NULL;
1177 connection->caPath = NULL;
1178 connection->randomFile = NULL;
1179 connection->egdSocket = NULL;
1180 connection->cookieJar = NULL;
1181 connection->sslCipherList = NULL;
1182 connection->private = NULL;
1183 connection->http200Aliases = NULL;
1184 connection->netrcFile = NULL;
1185 connection->ftpaccount = NULL;
1186 connection->cookielist = NULL;
1187 connection->ftpAlternativeToUser = NULL;
1188 connection->sshPublicKeyFile = NULL;
1189 connection->sshPrivateKeyFile = NULL;
1190 connection->copyPostFields = NULL;
1192 return connection;
1195 static Connection *duplicateConnection(Connection *original)
1197 Connection *connection;
1199 connection = (Connection *)malloc(sizeof(Connection));
1201 enter_blocking_section();
1202 connection->connection = curl_easy_duphandle(original->connection);
1203 leave_blocking_section();
1205 connection->next = NULL;
1206 connection->prev = NULL;
1208 if (connectionList.tail == NULL)
1210 connectionList.tail = connection;
1211 connectionList.head = connection;
1213 else
1215 connection->prev = connectionList.head;
1216 connectionList.head->next = connection;
1217 connectionList.head = connection;
1220 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1221 resetOcamlValues(connection);
1222 register_global_root(&connection->ocamlValues);
1224 Store_field(connection->ocamlValues, OcamlWriteCallback,
1225 Field(original->ocamlValues, OcamlWriteCallback));
1226 Store_field(connection->ocamlValues, OcamlReadCallback,
1227 Field(original->ocamlValues, OcamlReadCallback));
1228 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1229 Field(original->ocamlValues, OcamlErrorBuffer));
1230 Store_field(connection->ocamlValues, OcamlPostFields,
1231 Field(original->ocamlValues, OcamlPostFields));
1232 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1233 Field(original->ocamlValues, OcamlHTTPHeader));
1234 Store_field(connection->ocamlValues, OcamlQuote,
1235 Field(original->ocamlValues, OcamlQuote));
1236 Store_field(connection->ocamlValues, OcamlPostQuote,
1237 Field(original->ocamlValues, OcamlPostQuote));
1238 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1239 Field(original->ocamlValues, OcamlHeaderCallback));
1240 Store_field(connection->ocamlValues, OcamlProgressCallback,
1241 Field(original->ocamlValues, OcamlProgressCallback));
1242 Store_field(connection->ocamlValues, OcamlDebugCallback,
1243 Field(original->ocamlValues, OcamlDebugCallback));
1244 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1245 Field(original->ocamlValues, OcamlHTTP200Aliases));
1246 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1247 Field(original->ocamlValues, OcamlIOCTLCallback));
1248 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1249 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1251 connection->url = NULL;
1252 connection->proxy = NULL;
1253 connection->userPwd = NULL;
1254 connection->proxyUserPwd = NULL;
1255 connection->range = NULL;
1256 connection->errorBuffer = NULL;
1257 connection->postFields = NULL;
1258 connection->postFieldSize = -1;
1259 connection->referer = NULL;
1260 connection->userAgent = NULL;
1261 connection->ftpPort = NULL;
1262 connection->cookie = NULL;
1263 connection->httpHeader = NULL;
1264 connection->httpPostFirst = NULL;
1265 connection->httpPostLast = NULL;
1266 connection->httpPostStrings = NULL;
1267 connection->sslCert = NULL;
1268 connection->sslCertType = NULL;
1269 connection->sslCertPasswd = NULL;
1270 connection->sslKey = NULL;
1271 connection->sslKeyType = NULL;
1272 connection->sslKeyPasswd = NULL;
1273 connection->sslEngine = NULL;
1274 connection->quote = NULL;
1275 connection->postQuote = NULL;
1276 connection->cookieFile = NULL;
1277 connection->customRequest = NULL;
1278 connection->interface = NULL;
1279 connection->caInfo = NULL;
1280 connection->caPath = NULL;
1281 connection->randomFile = NULL;
1282 connection->egdSocket = NULL;
1283 connection->cookieJar = NULL;
1284 connection->sslCipherList = NULL;
1285 connection->private = NULL;
1286 connection->http200Aliases = NULL;
1287 connection->netrcFile = NULL;
1288 connection->ftpaccount = NULL;
1289 connection->cookielist = NULL;
1290 connection->sshPublicKeyFile = NULL;
1291 connection->sshPrivateKeyFile = NULL;
1292 connection->copyPostFields = NULL;
1294 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1295 handleURL(connection, Field(original->ocamlValues,
1296 OcamlURL));
1297 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1298 handleProxy(connection, Field(original->ocamlValues,
1299 OcamlProxy));
1300 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1301 handleUserPwd(connection, Field(original->ocamlValues,
1302 OcamlUserPWD));
1303 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1304 handleProxyUserPwd(connection, Field(original->ocamlValues,
1305 OcamlProxyUserPWD));
1306 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1307 handleRange(connection, Field(original->ocamlValues,
1308 OcamlRange));
1309 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1310 handleErrorBuffer(connection, Field(original->ocamlValues,
1311 OcamlErrorBuffer));
1312 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1313 handlePostFields(connection, Field(original->ocamlValues,
1314 OcamlPostFields));
1315 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1316 handleReferer(connection, Field(original->ocamlValues,
1317 OcamlReferer));
1318 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1319 handleUserAgent(connection, Field(original->ocamlValues,
1320 OcamlUserAgent));
1321 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1322 handleFTPPort(connection, Field(original->ocamlValues,
1323 OcamlFTPPort));
1324 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1325 handleCookie(connection, Field(original->ocamlValues,
1326 OcamlCookie));
1327 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1328 handleHTTPHeader(connection, Field(original->ocamlValues,
1329 OcamlHTTPHeader));
1330 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1331 handleHTTPPost(connection, Field(original->ocamlValues,
1332 OcamlHTTPPost));
1333 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1334 handleSSLCert(connection, Field(original->ocamlValues,
1335 OcamlSSLCert));
1336 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1337 handleSSLCertType(connection, Field(original->ocamlValues,
1338 OcamlSSLCertType));
1339 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1340 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1341 OcamlSSLCertPasswd));
1342 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1343 handleSSLKey(connection, Field(original->ocamlValues,
1344 OcamlSSLKey));
1345 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1346 handleSSLKeyType(connection, Field(original->ocamlValues,
1347 OcamlSSLKeyType));
1348 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1349 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1350 OcamlSSLKeyPasswd));
1351 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1352 handleSSLEngine(connection, Field(original->ocamlValues,
1353 OcamlSSLEngine));
1354 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1355 handleQuote(connection, Field(original->ocamlValues,
1356 OcamlQuote));
1357 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1358 handlePostQuote(connection, Field(original->ocamlValues,
1359 OcamlPostQuote));
1360 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1361 handleCookieFile(connection, Field(original->ocamlValues,
1362 OcamlCookieFile));
1363 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1364 handleCustomRequest(connection, Field(original->ocamlValues,
1365 OcamlCustomRequest));
1366 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1367 handleInterface(connection, Field(original->ocamlValues,
1368 OcamlInterface));
1369 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1370 handleCAInfo(connection, Field(original->ocamlValues,
1371 OcamlCAInfo));
1372 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1373 handleCAPath(connection, Field(original->ocamlValues,
1374 OcamlCAPath));
1375 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1376 handleRandomFile(connection, Field(original->ocamlValues,
1377 OcamlRandomFile));
1378 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1379 handleEGDSocket(connection, Field(original->ocamlValues,
1380 OcamlEGDSocket));
1381 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1382 handleCookieJar(connection, Field(original->ocamlValues,
1383 OcamlCookieJar));
1384 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1385 handleSSLCipherList(connection, Field(original->ocamlValues,
1386 OcamlSSLCipherList));
1387 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1388 handlePrivate(connection, Field(original->ocamlValues,
1389 OcamlPrivate));
1390 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1391 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1392 OcamlHTTP200Aliases));
1393 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1394 handleNETRCFile(connection, Field(original->ocamlValues,
1395 OcamlNETRCFile));
1396 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1397 handleFTPAccount(connection, Field(original->ocamlValues,
1398 OcamlFTPAccount));
1399 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1400 handleCookieList(connection, Field(original->ocamlValues,
1401 OcamlCookieList));
1402 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1403 handleFTPAlternativeToUser(connection,
1404 Field(original->ocamlValues,
1405 OcamlFTPAlternativeToUser));
1406 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1407 handleSSHPublicKeyFile(connection,
1408 Field(original->ocamlValues,
1409 OcamlSSHPublicKeyFile));
1410 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1411 handleSSHPrivateKeyFile(connection,
1412 Field(original->ocamlValues,
1413 OcamlSSHPrivateKeyFile));
1414 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1415 handleCopyPostFields(connection,
1416 Field(original->ocamlValues,
1417 OcamlCopyPostFields));
1419 return connection;
1422 static void removeConnection(Connection *connection)
1424 enter_blocking_section();
1425 curl_easy_cleanup(connection->connection);
1426 leave_blocking_section();
1428 if (connectionList.tail == connection)
1429 connectionList.tail = connectionList.tail->next;
1430 if (connectionList.head == connection)
1431 connectionList.head = connectionList.head->prev;
1433 if (connection->next != NULL)
1434 connection->next->prev = connection->prev;
1435 if (connection->prev != NULL)
1436 connection->prev->next = connection->next;
1438 remove_global_root(&connection->ocamlValues);
1440 if (connection->url != NULL)
1441 free(connection->url);
1442 if (connection->proxy != NULL)
1443 free(connection->proxy);
1444 if (connection->userPwd != NULL)
1445 free(connection->userPwd);
1446 if (connection->proxyUserPwd != NULL)
1447 free(connection->proxyUserPwd);
1448 if (connection->range != NULL)
1449 free(connection->range);
1450 if (connection->errorBuffer != NULL)
1451 free(connection->range);
1452 if (connection->postFields != NULL)
1453 free(connection->postFields);
1454 if (connection->referer != NULL)
1455 free(connection->referer);
1456 if (connection->userAgent != NULL)
1457 free(connection->userAgent);
1458 if (connection->ftpPort != NULL)
1459 free(connection->ftpPort);
1460 if (connection->cookie != NULL)
1461 free(connection->cookie);
1462 if (connection->httpHeader != NULL)
1463 free_curl_slist(connection->httpHeader);
1464 if (connection->httpPostFirst != NULL)
1465 curl_formfree(connection->httpPostFirst);
1466 if (connection->httpPostStrings != NULL)
1467 free_curl_slist(connection->httpPostStrings);
1468 if (connection->sslCert != NULL)
1469 free(connection->sslCert);
1470 if (connection->sslCertType != NULL)
1471 free(connection->sslCertType);
1472 if (connection->sslCertPasswd != NULL)
1473 free(connection->sslCertPasswd);
1474 if (connection->sslKey != NULL)
1475 free(connection->sslKey);
1476 if (connection->sslKeyType != NULL)
1477 free(connection->sslKeyType);
1478 if (connection->sslKeyPasswd != NULL)
1479 free(connection->sslKeyPasswd);
1480 if (connection->sslEngine != NULL)
1481 free(connection->sslEngine);
1482 if (connection->quote != NULL)
1483 free_curl_slist(connection->quote);
1484 if (connection->postQuote != NULL)
1485 free_curl_slist(connection->postQuote);
1486 if (connection->cookieFile != NULL)
1487 free(connection->cookieFile);
1488 if (connection->customRequest != NULL)
1489 free(connection->customRequest);
1490 if (connection->interface != NULL)
1491 free(connection->interface);
1492 if (connection->caInfo != NULL)
1493 free(connection->caInfo);
1494 if (connection->caPath != NULL)
1495 free(connection->caPath);
1496 if (connection->randomFile != NULL)
1497 free(connection->randomFile);
1498 if (connection->egdSocket != NULL)
1499 free(connection->egdSocket);
1500 if (connection->cookieJar != NULL)
1501 free(connection->cookieJar);
1502 if (connection->sslCipherList != NULL)
1503 free(connection->sslCipherList);
1504 if (connection->private != NULL)
1505 free(connection->private);
1506 if (connection->http200Aliases != NULL)
1507 free_curl_slist(connection->http200Aliases);
1508 if (connection->netrcFile != NULL)
1509 free(connection->netrcFile);
1510 if (connection->ftpaccount != NULL)
1511 free(connection->ftpaccount);
1512 if (connection->cookielist != NULL)
1513 free(connection->cookielist);
1514 if (connection->ftpAlternativeToUser != NULL)
1515 free(connection->ftpAlternativeToUser);
1516 if (connection->sshPublicKeyFile != NULL)
1517 free(connection->sshPublicKeyFile);
1518 if (connection->sshPrivateKeyFile != NULL)
1519 free(connection->sshPrivateKeyFile);
1520 if (connection->copyPostFields != NULL)
1521 free(connection->copyPostFields);
1523 free(connection);
1526 static void checkConnection(Connection *connection)
1528 Connection *listIter;
1530 listIter = connectionList.tail;
1532 while (listIter != NULL)
1534 if (listIter == connection)
1535 return;
1537 listIter = listIter->next;
1540 failwith("Invalid Connection");
1543 static Connection* findConnection(CURL* h)
1545 Connection *listIter;
1547 listIter = connectionList.tail;
1549 while (listIter != NULL)
1551 if (listIter->connection == h)
1552 return listIter;
1554 listIter = listIter->next;
1557 failwith("Unknown handle");
1560 #define WRAP_DATA_CALLBACK(f) \
1561 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1563 size_t result;\
1564 leave_blocking_section();\
1565 result = f##_nolock(ptr,size,nmemb,data);\
1566 enter_blocking_section();\
1567 return result;\
1570 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1572 CAMLparam0();
1573 CAMLlocal2(result, str);
1574 Connection *conn = (Connection *)data;
1575 int i;
1577 checkConnection(conn);
1579 str = alloc_string(size*nmemb);
1581 for (i = 0; i < size*nmemb; i++)
1582 Byte(str, i) = ptr[i];
1584 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1586 CAMLreturnT(size_t, Int_val(result));
1589 WRAP_DATA_CALLBACK(writeFunction)
1591 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1593 CAMLparam0();
1594 CAMLlocal1(result);
1595 Connection *conn = (Connection *)data;
1596 int length;
1598 checkConnection(conn);
1600 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1601 Val_int(size*nmemb));
1603 length = string_length(result);
1605 if (length >= size*nmemb)
1606 length = size*nmemb;
1608 memcpy(ptr, String_val(result), length);
1610 CAMLreturnT(size_t,length);
1613 WRAP_DATA_CALLBACK(readFunction)
1615 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1617 CAMLparam0();
1618 CAMLlocal2(result,str);
1619 Connection *conn = (Connection *)data;
1620 int i;
1622 checkConnection(conn);
1624 str = alloc_string(size*nmemb);
1626 for (i = 0; i < size*nmemb; i++)
1627 Byte(str, i) = ptr[i];
1629 result = callback(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1631 CAMLreturnT(size_t, Int_val(result));
1634 WRAP_DATA_CALLBACK(headerFunction)
1636 static int progressFunction_nolock(void *data,
1637 double dlTotal,
1638 double dlNow,
1639 double ulTotal,
1640 double ulNow)
1642 CAMLparam0();
1643 CAMLlocal1(result);
1644 CAMLlocalN(callbackData, 4);
1645 Connection *conn = (Connection *)data;
1647 checkConnection(conn);
1649 callbackData[0] = copy_double(dlTotal);
1650 callbackData[1] = copy_double(dlNow);
1651 callbackData[2] = copy_double(ulTotal);
1652 callbackData[3] = copy_double(ulNow);
1654 result = callbackN(Field(conn->ocamlValues, OcamlProgressCallback),
1655 4, callbackData);
1657 CAMLreturnT(int, Bool_val(result));
1660 static int progressFunction(void *data,
1661 double dlTotal,
1662 double dlNow,
1663 double ulTotal,
1664 double ulNow)
1666 int r;
1667 leave_blocking_section();
1668 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1669 enter_blocking_section();
1670 return r;
1673 static int debugFunction_nolock(CURL *debugConnection,
1674 curl_infotype infoType,
1675 char *buffer,
1676 size_t bufferLength,
1677 void *data)
1679 CAMLparam0();
1680 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1681 int i;
1682 Connection *conn = (Connection *)data;
1684 checkConnection(conn);
1686 camlDebugConnection = (value)conn;
1687 camlInfoType = Val_long(infoType);
1688 camlMessage = alloc_string(bufferLength);
1690 for (i = 0; i < bufferLength; i++)
1691 Byte(camlMessage, i) = buffer[i];
1693 callback3(Field(conn->ocamlValues, OcamlDebugCallback),
1694 camlDebugConnection,
1695 camlInfoType,
1696 camlMessage);
1698 CAMLreturnT(int, 0);
1701 static int debugFunction(CURL *debugConnection,
1702 curl_infotype infoType,
1703 char *buffer,
1704 size_t bufferLength,
1705 void *data)
1707 int r;
1708 leave_blocking_section();
1709 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1710 enter_blocking_section();
1711 return r;
1714 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1715 int cmd,
1716 void *data)
1718 CAMLparam0();
1719 CAMLlocal3(camlResult, camlConnection, camlCmd);
1720 Connection *conn = (Connection *)data;
1721 curlioerr result = CURLIOE_OK;
1723 checkConnection(conn);
1725 if (cmd == CURLIOCMD_NOP)
1726 camlCmd = Val_long(0);
1727 else if (cmd == CURLIOCMD_RESTARTREAD)
1728 camlCmd = Val_long(1);
1729 else
1730 failwith("Invalid IOCTL Cmd!");
1732 camlConnection = caml_alloc(1, Abstract_tag);
1733 Field(camlConnection, 0) = (value)conn;
1735 camlResult = callback2(Field(conn->ocamlValues, OcamlIOCTLCallback),
1736 camlConnection,
1737 camlCmd);
1739 switch (Long_val(camlResult))
1741 case 0: /* CURLIOE_OK */
1742 result = CURLIOE_OK;
1743 break;
1745 case 1: /* CURLIOE_UNKNOWNCMD */
1746 result = CURLIOE_UNKNOWNCMD;
1747 break;
1749 case 2: /* CURLIOE_FAILRESTART */
1750 result = CURLIOE_FAILRESTART;
1751 break;
1753 default: /* Incorrect return value, but let's handle it */
1754 result = CURLIOE_FAILRESTART;
1755 break;
1758 CAMLreturnT(curlioerr, result);
1761 static curlioerr ioctlFunction(CURL *ioctl,
1762 int cmd,
1763 void *data)
1765 curlioerr r;
1766 leave_blocking_section();
1767 r = ioctlFunction_nolock(ioctl, cmd, data);
1768 enter_blocking_section();
1769 return r;
1772 #ifdef HAVE_DECL_CURLOPT_SEEKFUNCTION
1773 static int seekFunction_nolock(void *data,
1774 curl_off_t offset,
1775 int origin)
1777 CAMLparam0();
1778 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1779 Connection *conn = (Connection *)data;
1780 int result = 0;
1782 camlOffset = copy_int64(offset);
1784 if (origin == SEEK_SET)
1785 camlOrigin = Val_long(0);
1786 else if (origin == SEEK_CUR)
1787 camlOrigin = Val_long(1);
1788 else if (origin == SEEK_END)
1789 camlOrigin = Val_long(2);
1790 else
1791 camlOrigin = Val_long(0);
1793 camlResult = callback2(Field(conn->ocamlValues,
1794 OcamlSeekFunctionCallback),
1795 camlOffset,
1796 camlOrigin);
1798 result = Int_val(camlResult);
1800 CAMLreturnT(int, result);
1803 static int seekFunction(void *data,
1804 curl_off_t offset,
1805 int origin)
1807 int r;
1808 leave_blocking_section();
1809 r = seekFunction_nolock(data,offset,origin);
1810 enter_blocking_section();
1811 return r;
1814 #endif
1817 ** curl_global_init helper function
1820 CAMLprim value helper_curl_global_init(value initOption)
1822 CAMLparam1(initOption);
1824 switch (Long_val(initOption))
1826 case 0: /* CURLINIT_GLOBALALL */
1827 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1828 break;
1830 case 1: /* CURLINIT_GLOBALSSL */
1831 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1832 break;
1834 case 2: /* CURLINIT_GLOBALWIN32 */
1835 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1836 break;
1838 case 3: /* CURLINIT_GLOBALNOTHING */
1839 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1840 break;
1842 default:
1843 failwith("Invalid Initialization Option");
1844 break;
1847 /* Keep compiler happy, we should never get here due to failwith() */
1848 CAMLreturn(Val_unit);
1852 ** curl_global_cleanup helper function
1855 CAMLprim value helper_curl_global_cleanup(void)
1857 CAMLparam0();
1859 curl_global_cleanup();
1861 CAMLreturn(Val_unit);
1865 ** curl_easy_init helper function
1868 CAMLprim value helper_curl_easy_init(void)
1870 CAMLparam0();
1871 CAMLlocal1(result);
1873 Connection *conn = newConnection();
1875 result = caml_alloc(1, Abstract_tag);
1876 Field(result, 0) = (value)conn;
1878 CAMLreturn(result);
1881 CAMLprim value helper_curl_easy_reset(value conn)
1883 CAMLparam1(conn);
1884 Connection *connection = Connection_val(conn);
1886 checkConnection(connection);
1887 curl_easy_reset(connection->connection);
1888 resetOcamlValues(connection);
1890 CAMLreturn(Val_unit);
1894 ** curl_easy_setopt helper utility functions
1897 static void handleWriteFunction(Connection *conn, value option)
1899 CAMLparam1(option);
1900 CURLcode result = CURLE_OK;
1902 if (Tag_val(option) == Closure_tag)
1903 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1904 else
1905 failwith("Not a proper closure");
1907 result = curl_easy_setopt(conn->connection,
1908 CURLOPT_WRITEFUNCTION,
1909 writeFunction);
1911 if (result != CURLE_OK)
1912 raiseError(conn, result);
1914 result = curl_easy_setopt(conn->connection,
1915 CURLOPT_WRITEDATA,
1916 conn);
1918 if (result != CURLE_OK)
1919 raiseError(conn, result);
1921 CAMLreturn0;
1924 static void handleReadFunction(Connection *conn, value option)
1926 CAMLparam1(option);
1927 CURLcode result = CURLE_OK;
1929 if (Tag_val(option) == Closure_tag)
1930 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1931 else
1932 failwith("Not a proper closure");
1934 result = curl_easy_setopt(conn->connection,
1935 CURLOPT_READFUNCTION,
1936 readFunction);
1938 if (result != CURLE_OK)
1939 raiseError(conn, result);
1941 result = curl_easy_setopt(conn->connection,
1942 CURLOPT_READDATA,
1943 conn);
1945 if (result != CURLE_OK)
1946 raiseError(conn, result);
1948 CAMLreturn0;
1951 static void handleURL(Connection *conn, value option)
1953 CAMLparam1(option);
1954 CURLcode result = CURLE_OK;
1956 Store_field(conn->ocamlValues, OcamlURL, option);
1958 if (conn->url != NULL)
1959 free(conn->url);
1961 conn->url = strdup(String_val(option));
1963 result = curl_easy_setopt(conn->connection,
1964 CURLOPT_URL,
1965 conn->url);
1967 if (result != CURLE_OK)
1968 raiseError(conn, result);
1970 CAMLreturn0;
1973 static void handleInFileSize(Connection *conn, value option)
1975 CAMLparam1(option);
1976 CURLcode result = CURLE_OK;
1978 result = curl_easy_setopt(conn->connection,
1979 CURLOPT_INFILESIZE,
1980 Long_val(option));
1982 if (result != CURLE_OK)
1983 raiseError(conn, result);
1985 CAMLreturn0;
1988 static void handleProxy(Connection *conn, value option)
1990 CAMLparam1(option);
1991 CURLcode result = CURLE_OK;
1993 Store_field(conn->ocamlValues, OcamlProxy, option);
1995 if (conn->proxy != NULL)
1996 free(conn->proxy);
1998 conn->proxy = strdup(String_val(option));
2000 result = curl_easy_setopt(conn->connection,
2001 CURLOPT_PROXY,
2002 conn->proxy);
2004 if (result != CURLE_OK)
2005 raiseError(conn, result);
2007 CAMLreturn0;
2010 static void handleProxyPort(Connection *conn, value option)
2012 CAMLparam1(option);
2013 CURLcode result = CURLE_OK;
2015 result = curl_easy_setopt(conn->connection,
2016 CURLOPT_PROXYPORT,
2017 Long_val(option));
2019 if (result != CURLE_OK)
2020 raiseError(conn, result);
2022 CAMLreturn0;
2025 static void handleHTTPProxyTunnel(Connection *conn, value option)
2027 CAMLparam1(option);
2028 CURLcode result = CURLE_OK;
2030 result = curl_easy_setopt(conn->connection,
2031 CURLOPT_HTTPPROXYTUNNEL,
2032 Bool_val(option));
2034 if (result != CURLE_OK)
2035 raiseError(conn, result);
2037 CAMLreturn0;
2040 static void handleVerbose(Connection *conn, value option)
2042 CAMLparam1(option);
2043 CURLcode result = CURLE_OK;
2045 result = curl_easy_setopt(conn->connection,
2046 CURLOPT_VERBOSE,
2047 Bool_val(option));
2049 if (result != CURLE_OK)
2050 raiseError(conn, result);
2052 CAMLreturn0;
2055 static void handleHeader(Connection *conn, value option)
2057 CAMLparam1(option);
2058 CURLcode result = CURLE_OK;
2060 result = curl_easy_setopt(conn->connection,
2061 CURLOPT_HEADER,
2062 Bool_val(option));
2064 if (result != CURLE_OK)
2065 raiseError(conn, result);
2067 CAMLreturn0;
2070 static void handleNoProgress(Connection *conn, value option)
2072 CAMLparam1(option);
2073 CURLcode result = CURLE_OK;
2075 result = curl_easy_setopt(conn->connection,
2076 CURLOPT_NOPROGRESS,
2077 Bool_val(option));
2079 if (result != CURLE_OK)
2080 raiseError(conn, result);
2082 CAMLreturn0;
2085 static void handleNoSignal(Connection *conn, value option)
2087 #if HAVE_DECL_CURLOPT_NOSIGNAL
2088 CAMLparam1(option);
2089 CURLcode result = CURLE_OK;
2091 result = curl_easy_setopt(conn->connection,
2092 CURLOPT_NOSIGNAL,
2093 Bool_val(option));
2095 if (result != CURLE_OK)
2096 raiseError(conn, result);
2098 CAMLreturn0;
2099 #else
2100 #warning "libcurl does not implement CURLOPT_NOSIGNAL"
2101 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2102 #endif
2105 static void handleNoBody(Connection *conn, value option)
2107 CAMLparam1(option);
2108 CURLcode result = CURLE_OK;
2110 result = curl_easy_setopt(conn->connection,
2111 CURLOPT_NOBODY,
2112 Bool_val(option));
2114 if (result != CURLE_OK)
2115 raiseError(conn, result);
2117 CAMLreturn0;
2120 static void handleFailOnError(Connection *conn, value option)
2122 CAMLparam1(option);
2123 CURLcode result = CURLE_OK;
2125 result = curl_easy_setopt(conn->connection,
2126 CURLOPT_FAILONERROR,
2127 Bool_val(option));
2129 if (result != CURLE_OK)
2130 raiseError(conn, result);
2132 CAMLreturn0;
2135 static void handleUpload(Connection *conn, value option)
2137 CAMLparam1(option);
2138 CURLcode result = CURLE_OK;
2140 result = curl_easy_setopt(conn->connection,
2141 CURLOPT_UPLOAD,
2142 Bool_val(option));
2144 if (result != CURLE_OK)
2145 raiseError(conn, result);
2147 CAMLreturn0;
2150 static void handlePost(Connection *conn, value option)
2152 CAMLparam1(option);
2153 CURLcode result = CURLE_OK;
2155 result = curl_easy_setopt(conn->connection,
2156 CURLOPT_POST,
2157 Bool_val(option));
2159 if (result != CURLE_OK)
2160 raiseError(conn, result);
2162 CAMLreturn0;
2165 static void handleFTPListOnly(Connection *conn, value option)
2167 CAMLparam1(option);
2168 CURLcode result = CURLE_OK;
2170 result = curl_easy_setopt(conn->connection,
2171 CURLOPT_FTPLISTONLY,
2172 Bool_val(option));
2174 if (result != CURLE_OK)
2175 raiseError(conn, result);
2177 CAMLreturn0;
2180 static void handleFTPAppend(Connection *conn, value option)
2182 CAMLparam1(option);
2183 CURLcode result = CURLE_OK;
2185 result = curl_easy_setopt(conn->connection,
2186 CURLOPT_FTPAPPEND,
2187 Bool_val(option));
2189 if (result != CURLE_OK)
2190 raiseError(conn, result);
2192 CAMLreturn0;
2195 static void handleNETRC(Connection *conn, value option)
2197 CAMLparam1(option);
2198 CURLcode result = CURLE_OK;
2199 long netrc;
2201 switch (Long_val(option))
2203 case 0: /* CURL_NETRC_OPTIONAL */
2204 netrc = CURL_NETRC_OPTIONAL;
2205 break;
2207 case 1:/* CURL_NETRC_IGNORED */
2208 netrc = CURL_NETRC_IGNORED;
2209 break;
2211 case 2: /* CURL_NETRC_REQUIRED */
2212 netrc = CURL_NETRC_REQUIRED;
2213 break;
2215 default:
2216 failwith("Invalid NETRC Option");
2217 break;
2220 result = curl_easy_setopt(conn->connection,
2221 CURLOPT_NETRC,
2222 netrc);
2224 if (result != CURLE_OK)
2225 raiseError(conn, result);
2227 CAMLreturn0;
2230 static void handleEncoding(Connection *conn, value option)
2232 #if HAVE_DECL_CURLOPT_ENCODING
2233 CAMLparam1(option);
2234 CURLcode result = CURLE_OK;
2236 switch (Long_val(option))
2238 case 0: /* CURL_ENCODING_NONE */
2239 result = curl_easy_setopt(conn->connection,
2240 CURLOPT_ENCODING,
2241 "identity");
2242 break;
2244 case 1: /* CURL_ENCODING_DEFLATE */
2245 result = curl_easy_setopt(conn->connection,
2246 CURLOPT_ENCODING,
2247 "deflate");
2248 break;
2250 default:
2251 failwith("Invalid Encoding Option");
2252 break;
2255 if (result != CURLE_OK)
2256 raiseError(conn, result);
2258 CAMLreturn0;
2259 #else
2260 #warning "libcurl does not implement CURLOPT_ENCODING"
2261 failwith("libcurl does not implement CURLOPT_ENCODING");
2262 #endif
2265 static void handleFollowLocation(Connection *conn, value option)
2267 CAMLparam1(option);
2268 CURLcode result = CURLE_OK;
2270 result = curl_easy_setopt(conn->connection,
2271 CURLOPT_FOLLOWLOCATION,
2272 Bool_val(option));
2274 if (result != CURLE_OK)
2275 raiseError(conn, result);
2277 CAMLreturn0;
2280 static void handleTransferText(Connection *conn, value option)
2282 CAMLparam1(option);
2283 CURLcode result = CURLE_OK;
2285 result = curl_easy_setopt(conn->connection,
2286 CURLOPT_TRANSFERTEXT,
2287 Bool_val(option));
2289 if (result != CURLE_OK)
2290 raiseError(conn, result);
2292 CAMLreturn0;
2295 static void handlePut(Connection *conn, value option)
2297 CAMLparam1(option);
2298 CURLcode result = CURLE_OK;
2300 result = curl_easy_setopt(conn->connection,
2301 CURLOPT_PUT,
2302 Bool_val(option));
2304 if (result != CURLE_OK)
2305 raiseError(conn, result);
2307 CAMLreturn0;
2310 static void handleUserPwd(Connection *conn, value option)
2312 CAMLparam1(option);
2313 CURLcode result = CURLE_OK;
2315 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2317 if (conn->userPwd != NULL)
2318 free(conn->userPwd);
2320 conn->userPwd = strdup(String_val(option));
2322 result = curl_easy_setopt(conn->connection,
2323 CURLOPT_USERPWD,
2324 conn->userPwd);
2326 if (result != CURLE_OK)
2327 raiseError(conn, result);
2329 CAMLreturn0;
2332 static void handleProxyUserPwd(Connection *conn, value option)
2334 CAMLparam1(option);
2335 CURLcode result = CURLE_OK;
2337 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2339 if (conn->proxyUserPwd != NULL)
2340 free(conn->proxyUserPwd);
2342 conn->proxyUserPwd = strdup(String_val(option));
2344 result = curl_easy_setopt(conn->connection,
2345 CURLOPT_PROXYUSERPWD,
2346 conn->proxyUserPwd);
2348 if (result != CURLE_OK)
2349 raiseError(conn, result);
2351 CAMLreturn0;
2354 static void handleRange(Connection *conn, value option)
2356 CAMLparam1(option);
2357 CURLcode result = CURLE_OK;
2359 Store_field(conn->ocamlValues, OcamlRange, option);
2361 if (conn->range != NULL)
2362 free(conn->range);
2364 conn->range = strdup(String_val(option));
2366 result = curl_easy_setopt(conn->connection,
2367 CURLOPT_RANGE,
2368 conn->range);
2370 if (result != CURLE_OK)
2371 raiseError(conn, result);
2373 CAMLreturn0;
2376 static void handleErrorBuffer(Connection *conn, value option)
2378 CAMLparam1(option);
2379 CURLcode result = CURLE_OK;
2381 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2383 if (conn->errorBuffer != NULL)
2384 free(conn->errorBuffer);
2386 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2388 result = curl_easy_setopt(conn->connection,
2389 CURLOPT_ERRORBUFFER,
2390 conn->errorBuffer);
2392 if (result != CURLE_OK)
2393 raiseError(conn, result);
2395 CAMLreturn0;
2398 static void handleTimeout(Connection *conn, value option)
2400 CAMLparam1(option);
2401 CURLcode result = CURLE_OK;
2403 result = curl_easy_setopt(conn->connection,
2404 CURLOPT_TIMEOUT,
2405 Long_val(option));
2407 if (result != CURLE_OK)
2408 raiseError(conn, result);
2410 CAMLreturn0;
2413 static void handlePostFields(Connection *conn, value option)
2415 CAMLparam1(option);
2416 CURLcode result = CURLE_OK;
2418 Store_field(conn->ocamlValues, OcamlPostFields, option);
2420 if (conn->postFields != NULL)
2421 free(conn->postFields);
2423 conn->postFields = malloc(string_length(option)+1);
2424 memcpy(conn->postFields, String_val(option), string_length(option));
2426 result = curl_easy_setopt(conn->connection,
2427 CURLOPT_POSTFIELDS,
2428 conn->postFields);
2430 if (result != CURLE_OK)
2431 raiseError(conn, result);
2433 CAMLreturn0;
2436 static void handlePostFieldSize(Connection *conn, value option)
2438 CAMLparam1(option);
2439 CURLcode result = CURLE_OK;
2441 result = curl_easy_setopt(conn->connection,
2442 CURLOPT_POSTFIELDSIZE,
2443 Long_val(option));
2445 if (result != CURLE_OK)
2446 raiseError(conn, result);
2448 CAMLreturn0;
2451 static void handleReferer(Connection *conn, value option)
2453 CAMLparam1(option);
2454 CURLcode result = CURLE_OK;
2456 Store_field(conn->ocamlValues, OcamlReferer, option);
2458 if (conn->referer != NULL)
2459 free(conn->referer);
2461 conn->referer = strdup(String_val(option));
2463 result = curl_easy_setopt(conn->connection,
2464 CURLOPT_REFERER,
2465 conn->referer);
2467 if (result != CURLE_OK)
2468 raiseError(conn, result);
2470 CAMLreturn0;
2473 static void handleUserAgent(Connection *conn, value option)
2475 CAMLparam1(option);
2476 CURLcode result = CURLE_OK;
2478 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2480 if (conn->userAgent != NULL)
2481 free(conn->userAgent);
2483 conn->userAgent = strdup(String_val(option));
2485 result = curl_easy_setopt(conn->connection,
2486 CURLOPT_USERAGENT,
2487 conn->userAgent);
2489 if (result != CURLE_OK)
2490 raiseError(conn, result);
2492 CAMLreturn0;
2495 static void handleFTPPort(Connection *conn, value option)
2497 CAMLparam1(option);
2498 CURLcode result = CURLE_OK;
2500 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2502 if (conn->ftpPort != NULL)
2503 free(conn->ftpPort);
2505 conn->ftpPort = strdup(String_val(option));
2507 result = curl_easy_setopt(conn->connection,
2508 CURLOPT_FTPPORT,
2509 conn->ftpPort);
2511 if (result != CURLE_OK)
2512 raiseError(conn, result);
2514 CAMLreturn0;
2517 static void handleLowSpeedLimit(Connection *conn, value option)
2519 CAMLparam1(option);
2520 CURLcode result = CURLE_OK;
2522 result = curl_easy_setopt(conn->connection,
2523 CURLOPT_LOW_SPEED_LIMIT,
2524 Long_val(option));
2526 if (result != CURLE_OK)
2527 raiseError(conn, result);
2529 CAMLreturn0;
2532 static void handleLowSpeedTime(Connection *conn, value option)
2534 CAMLparam1(option);
2535 CURLcode result = CURLE_OK;
2537 result = curl_easy_setopt(conn->connection,
2538 CURLOPT_LOW_SPEED_TIME,
2539 Long_val(option));
2541 if (result != CURLE_OK)
2542 raiseError(conn, result);
2544 CAMLreturn0;
2547 static void handleResumeFrom(Connection *conn, value option)
2549 CAMLparam1(option);
2550 CURLcode result = CURLE_OK;
2552 result = curl_easy_setopt(conn->connection,
2553 CURLOPT_RESUME_FROM,
2554 Long_val(option));
2556 if (result != CURLE_OK)
2557 raiseError(conn, result);
2559 CAMLreturn0;
2562 static void handleCookie(Connection *conn, value option)
2564 CAMLparam1(option);
2565 CURLcode result = CURLE_OK;
2567 Store_field(conn->ocamlValues, OcamlCookie, option);
2569 if (conn->cookie != NULL)
2570 free(conn->cookie);
2572 conn->cookie = strdup(String_val(option));
2574 result = curl_easy_setopt(conn->connection,
2575 CURLOPT_COOKIE,
2576 conn->cookie);
2578 if (result != CURLE_OK)
2579 raiseError(conn, result);
2581 CAMLreturn0;
2584 static void handleHTTPHeader(Connection *conn, value option)
2586 CAMLparam1(option);
2587 CAMLlocal1(listIter);
2588 CURLcode result = CURLE_OK;
2589 char *str;
2591 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2593 if (conn->httpHeader != NULL)
2594 free_curl_slist(conn->httpHeader);
2596 conn->httpHeader = NULL;
2598 listIter = option;
2600 while (!Is_long(listIter))
2602 if (Tag_val(Field(listIter, 0)) != String_tag)
2603 failwith("Not a string");
2605 str = strdup(String_val(Field(listIter, 0)));
2607 conn->httpHeader = curl_slist_append(conn->httpHeader, str);
2609 listIter = Field(listIter, 1);
2612 result = curl_easy_setopt(conn->connection,
2613 CURLOPT_HTTPHEADER,
2614 conn->httpHeader);
2616 if (result != CURLE_OK)
2617 raiseError(conn, result);
2619 CAMLreturn0;
2622 static void handleHTTPPost(Connection *conn, value option)
2624 CAMLparam1(option);
2625 CAMLlocal3(listIter, formItem, contentType);
2626 CURLcode result = CURLE_OK;
2627 char *str1, *str2, *str3, *str4;
2629 listIter = option;
2631 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2633 if (conn->httpPostFirst != NULL)
2634 curl_formfree(conn->httpPostFirst);
2636 conn->httpPostFirst = NULL;
2637 conn->httpPostLast = NULL;
2639 if (conn->httpPostStrings != NULL)
2640 free_curl_slist(conn->httpPostStrings);
2642 while (!Is_long(listIter))
2644 formItem = Field(listIter, 0);
2646 switch (Tag_val(formItem))
2648 case 0: /* CURLFORM_CONTENT */
2649 if (Wosize_val(formItem) < 3)
2651 failwith("Incorrect CURLFORM_CONTENT parameters");
2654 if (Is_long(Field(formItem, 2)) &&
2655 Long_val(Field(formItem, 2)) == 0)
2657 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2658 memcpy(str1,
2659 String_val(Field(formItem, 0)),
2660 string_length(Field(formItem, 0)));
2661 str1[string_length(Field(formItem, 0))] = 0;
2662 conn->httpPostStrings =
2663 curl_slist_append(conn->httpPostStrings, str1);
2665 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2666 memcpy(str2,
2667 String_val(Field(formItem, 1)),
2668 string_length(Field(formItem, 1)));
2669 str2[string_length(Field(formItem, 1))] = 0;
2670 conn->httpPostStrings =
2671 curl_slist_append(conn->httpPostStrings, str2);
2673 curl_formadd(&conn->httpPostFirst,
2674 &conn->httpPostLast,
2675 CURLFORM_PTRNAME,
2676 str1,
2677 CURLFORM_NAMELENGTH,
2678 string_length(Field(formItem, 0)),
2679 CURLFORM_PTRCONTENTS,
2680 str2,
2681 CURLFORM_CONTENTSLENGTH,
2682 string_length(Field(formItem, 1)),
2683 CURLFORM_END);
2685 else if (Is_block(Field(formItem, 2)))
2687 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2688 memcpy(str1,
2689 String_val(Field(formItem, 0)),
2690 string_length(Field(formItem, 0)));
2691 str1[string_length(Field(formItem, 0))] = 0;
2692 conn->httpPostStrings =
2693 curl_slist_append(conn->httpPostStrings, str1);
2695 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2696 memcpy(str2,
2697 String_val(Field(formItem, 1)),
2698 string_length(Field(formItem, 1)));
2699 str2[string_length(Field(formItem, 1))] = 0;
2700 conn->httpPostStrings =
2701 curl_slist_append(conn->httpPostStrings, str2);
2703 contentType = Field(formItem, 2);
2705 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2706 memcpy(str3,
2707 String_val(Field(contentType, 0)),
2708 string_length(Field(contentType, 0)));
2709 str3[string_length(Field(contentType, 0))] = 0;
2710 conn->httpPostStrings =
2711 curl_slist_append(conn->httpPostStrings, str3);
2713 curl_formadd(&conn->httpPostFirst,
2714 &conn->httpPostLast,
2715 CURLFORM_PTRNAME,
2716 str1,
2717 CURLFORM_NAMELENGTH,
2718 string_length(Field(formItem, 0)),
2719 CURLFORM_PTRCONTENTS,
2720 str2,
2721 CURLFORM_CONTENTSLENGTH,
2722 string_length(Field(formItem, 1)),
2723 CURLFORM_CONTENTTYPE,
2724 str3,
2725 CURLFORM_END);
2727 else
2729 failwith("Incorrect CURLFORM_CONTENT parameters");
2731 break;
2733 case 1: /* CURLFORM_FILECONTENT */
2734 if (Wosize_val(formItem) < 3)
2736 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2739 if (Is_long(Field(formItem, 2)) &&
2740 Long_val(Field(formItem, 2)) == 0)
2742 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2743 memcpy(str1,
2744 String_val(Field(formItem, 0)),
2745 string_length(Field(formItem, 0)));
2746 str1[string_length(Field(formItem, 0))] = 0;
2747 conn->httpPostStrings =
2748 curl_slist_append(conn->httpPostStrings, str1);
2750 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2751 memcpy(str2,
2752 String_val(Field(formItem, 1)),
2753 string_length(Field(formItem, 1)));
2754 str2[string_length(Field(formItem, 1))] = 0;
2755 conn->httpPostStrings =
2756 curl_slist_append(conn->httpPostStrings, str2);
2758 curl_formadd(&conn->httpPostFirst,
2759 &conn->httpPostLast,
2760 CURLFORM_PTRNAME,
2761 str1,
2762 CURLFORM_NAMELENGTH,
2763 string_length(Field(formItem, 0)),
2764 CURLFORM_FILECONTENT,
2765 str2,
2766 CURLFORM_END);
2768 else if (Is_block(Field(formItem, 2)))
2770 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2771 memcpy(str1,
2772 String_val(Field(formItem, 0)),
2773 string_length(Field(formItem, 0)));
2774 str1[string_length(Field(formItem, 0))] = 0;
2775 conn->httpPostStrings =
2776 curl_slist_append(conn->httpPostStrings, str1);
2778 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2779 memcpy(str2,
2780 String_val(Field(formItem, 1)),
2781 string_length(Field(formItem, 1)));
2782 str2[string_length(Field(formItem, 1))] = 0;
2783 conn->httpPostStrings =
2784 curl_slist_append(conn->httpPostStrings, str2);
2786 contentType = Field(formItem, 2);
2788 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2789 memcpy(str3,
2790 String_val(Field(contentType, 0)),
2791 string_length(Field(contentType, 0)));
2792 str3[string_length(Field(contentType, 0))] = 0;
2793 conn->httpPostStrings =
2794 curl_slist_append(conn->httpPostStrings, str3);
2796 curl_formadd(&conn->httpPostFirst,
2797 &conn->httpPostLast,
2798 CURLFORM_PTRNAME,
2799 str1,
2800 CURLFORM_NAMELENGTH,
2801 string_length(Field(formItem, 0)),
2802 CURLFORM_FILECONTENT,
2803 str2,
2804 CURLFORM_CONTENTTYPE,
2805 str3,
2806 CURLFORM_END);
2808 else
2810 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2812 break;
2814 case 2: /* CURLFORM_FILE */
2815 if (Wosize_val(formItem) < 3)
2817 failwith("Incorrect CURLFORM_FILE parameters");
2820 if (Is_long(Field(formItem, 2)) &&
2821 Long_val(Field(formItem, 2)) == 0)
2823 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2824 memcpy(str1,
2825 String_val(Field(formItem, 0)),
2826 string_length(Field(formItem, 0)));
2827 str1[string_length(Field(formItem, 0))] = 0;
2828 conn->httpPostStrings =
2829 curl_slist_append(conn->httpPostStrings, str1);
2831 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2832 memcpy(str2,
2833 String_val(Field(formItem, 1)),
2834 string_length(Field(formItem, 1)));
2835 str2[string_length(Field(formItem, 1))] = 0;
2836 conn->httpPostStrings =
2837 curl_slist_append(conn->httpPostStrings, str2);
2839 curl_formadd(&conn->httpPostFirst,
2840 &conn->httpPostLast,
2841 CURLFORM_PTRNAME,
2842 str1,
2843 CURLFORM_NAMELENGTH,
2844 string_length(Field(formItem, 0)),
2845 CURLFORM_FILE,
2846 str2,
2847 CURLFORM_END);
2849 else if (Is_block(Field(formItem, 2)))
2851 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2852 memcpy(str1,
2853 String_val(Field(formItem, 0)),
2854 string_length(Field(formItem, 0)));
2855 str1[string_length(Field(formItem, 0))] = 0;
2856 conn->httpPostStrings =
2857 curl_slist_append(conn->httpPostStrings, str1);
2859 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2860 memcpy(str2,
2861 String_val(Field(formItem, 1)),
2862 string_length(Field(formItem, 1)));
2863 str2[string_length(Field(formItem, 1))] = 0;
2864 conn->httpPostStrings =
2865 curl_slist_append(conn->httpPostStrings, str2);
2867 contentType = Field(formItem, 2);
2869 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2870 memcpy(str3,
2871 String_val(Field(contentType, 0)),
2872 string_length(Field(contentType, 0)));
2873 str3[string_length(Field(contentType, 0))] = 0;
2874 conn->httpPostStrings =
2875 curl_slist_append(conn->httpPostStrings, str3);
2877 curl_formadd(&conn->httpPostFirst,
2878 &conn->httpPostLast,
2879 CURLFORM_PTRNAME,
2880 str1,
2881 CURLFORM_NAMELENGTH,
2882 string_length(Field(formItem, 0)),
2883 CURLFORM_FILE,
2884 str2,
2885 CURLFORM_CONTENTTYPE,
2886 str3,
2887 CURLFORM_END);
2889 else
2891 failwith("Incorrect CURLFORM_FILE parameters");
2893 break;
2895 case 3: /* CURLFORM_BUFFER */
2896 if (Wosize_val(formItem) < 4)
2898 failwith("Incorrect CURLFORM_BUFFER parameters");
2901 if (Is_long(Field(formItem, 3)) &&
2902 Long_val(Field(formItem, 3)) == 0)
2904 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2905 memcpy(str1,
2906 String_val(Field(formItem, 0)),
2907 string_length(Field(formItem, 0)));
2908 str1[string_length(Field(formItem, 0))] = 0;
2909 conn->httpPostStrings =
2910 curl_slist_append(conn->httpPostStrings, str1);
2912 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2913 memcpy(str2,
2914 String_val(Field(formItem, 1)),
2915 string_length(Field(formItem, 1)));
2916 str2[string_length(Field(formItem, 1))] = 0;
2917 conn->httpPostStrings =
2918 curl_slist_append(conn->httpPostStrings, str2);
2920 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2921 memcpy(str3,
2922 String_val(Field(formItem, 2)),
2923 string_length(Field(formItem, 2)));
2924 str3[string_length(Field(formItem, 2))] = 0;
2925 conn->httpPostStrings =
2926 curl_slist_append(conn->httpPostStrings, str3);
2928 curl_formadd(&conn->httpPostFirst,
2929 &conn->httpPostLast,
2930 CURLFORM_PTRNAME,
2931 str1,
2932 CURLFORM_NAMELENGTH,
2933 string_length(Field(formItem, 0)),
2934 CURLFORM_BUFFER,
2935 str2,
2936 CURLFORM_BUFFERPTR,
2937 str3,
2938 CURLFORM_BUFFERLENGTH,
2939 string_length(Field(formItem, 2)),
2940 CURLFORM_END);
2942 else if (Is_block(Field(formItem, 3)))
2944 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2945 memcpy(str1,
2946 String_val(Field(formItem, 0)),
2947 string_length(Field(formItem, 0)));
2948 str1[string_length(Field(formItem, 0))] = 0;
2949 conn->httpPostStrings =
2950 curl_slist_append(conn->httpPostStrings, str1);
2952 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2953 memcpy(str2,
2954 String_val(Field(formItem, 1)),
2955 string_length(Field(formItem, 1)));
2956 str2[string_length(Field(formItem, 1))] = 0;
2957 conn->httpPostStrings =
2958 curl_slist_append(conn->httpPostStrings, str2);
2960 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2961 memcpy(str3,
2962 String_val(Field(formItem, 2)),
2963 string_length(Field(formItem, 2)));
2964 str3[string_length(Field(formItem, 2))] = 0;
2965 conn->httpPostStrings =
2966 curl_slist_append(conn->httpPostStrings, str3);
2968 contentType = Field(formItem, 3);
2970 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
2971 memcpy(str4,
2972 String_val(Field(contentType, 0)),
2973 string_length(Field(contentType, 0)));
2974 str4[string_length(Field(contentType, 0))] = 0;
2975 conn->httpPostStrings =
2976 curl_slist_append(conn->httpPostStrings, str4);
2978 curl_formadd(&conn->httpPostFirst,
2979 &conn->httpPostLast,
2980 CURLFORM_PTRNAME,
2981 str1,
2982 CURLFORM_NAMELENGTH,
2983 string_length(Field(formItem, 0)),
2984 CURLFORM_BUFFER,
2985 str2,
2986 CURLFORM_BUFFERPTR,
2987 str3,
2988 CURLFORM_BUFFERLENGTH,
2989 string_length(Field(formItem, 2)),
2990 CURLFORM_CONTENTTYPE,
2991 str4,
2992 CURLFORM_END);
2994 else
2996 failwith("Incorrect CURLFORM_BUFFER parameters");
2998 break;
3001 listIter = Field(listIter, 1);
3004 result = curl_easy_setopt(conn->connection,
3005 CURLOPT_HTTPPOST,
3006 conn->httpPostFirst);
3008 if (result != CURLE_OK)
3009 raiseError(conn, result);
3011 CAMLreturn0;
3014 static void handleSSLCert(Connection *conn, value option)
3016 CAMLparam1(option);
3017 CURLcode result = CURLE_OK;
3019 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3021 if (conn->sslCert != NULL)
3022 free(conn->sslCert);
3024 conn->sslCert = strdup(String_val(option));
3026 result = curl_easy_setopt(conn->connection,
3027 CURLOPT_SSLCERT,
3028 conn->sslCert);
3030 if (result != CURLE_OK)
3031 raiseError(conn, result);
3033 CAMLreturn0;
3036 static void handleSSLCertType(Connection *conn, value option)
3038 CAMLparam1(option);
3039 CURLcode result = CURLE_OK;
3041 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3043 if (conn->sslCertType != NULL)
3044 free(conn->sslCertType);
3046 conn->sslCertType = strdup(String_val(option));
3048 result = curl_easy_setopt(conn->connection,
3049 CURLOPT_SSLCERTTYPE,
3050 conn->sslCertType);
3052 if (result != CURLE_OK)
3053 raiseError(conn, result);
3055 CAMLreturn0;
3058 static void handleSSLCertPasswd(Connection *conn, value option)
3060 CAMLparam1(option);
3061 CURLcode result = CURLE_OK;
3063 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3065 if (conn->sslCertPasswd != NULL)
3066 free(conn->sslCertPasswd);
3068 conn->sslCertPasswd = strdup(String_val(option));
3070 result = curl_easy_setopt(conn->connection,
3071 CURLOPT_SSLCERTPASSWD,
3072 conn->sslCertPasswd);
3074 if (result != CURLE_OK)
3075 raiseError(conn, result);
3077 CAMLreturn0;
3080 static void handleSSLKey(Connection *conn, value option)
3082 CAMLparam1(option);
3083 CURLcode result = CURLE_OK;
3085 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3087 if (conn->sslKey != NULL)
3088 free(conn->sslKey);
3090 conn->sslKey = strdup(String_val(option));
3092 result = curl_easy_setopt(conn->connection,
3093 CURLOPT_SSLKEY,
3094 conn->sslKey);
3096 if (result != CURLE_OK)
3097 raiseError(conn, result);
3099 CAMLreturn0;
3102 static void handleSSLKeyType(Connection *conn, value option)
3104 CAMLparam1(option);
3105 CURLcode result = CURLE_OK;
3107 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3109 if (conn->sslKeyType != NULL)
3110 free(conn->sslKeyType);
3112 conn->sslKeyType = strdup(String_val(option));
3114 result = curl_easy_setopt(conn->connection,
3115 CURLOPT_SSLKEYTYPE,
3116 conn->sslKeyType);
3118 if (result != CURLE_OK)
3119 raiseError(conn, result);
3121 CAMLreturn0;
3124 static void handleSSLKeyPasswd(Connection *conn, value option)
3126 CAMLparam1(option);
3127 CURLcode result = CURLE_OK;
3129 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3131 if (conn->sslKeyPasswd != NULL)
3132 free(conn->sslKeyPasswd);
3134 conn->sslKeyPasswd = strdup(String_val(option));
3136 result = curl_easy_setopt(conn->connection,
3137 CURLOPT_SSLKEYPASSWD,
3138 conn->sslKeyPasswd);
3140 if (result != CURLE_OK)
3141 raiseError(conn, result);
3143 CAMLreturn0;
3146 static void handleSSLEngine(Connection *conn, value option)
3148 CAMLparam1(option);
3149 CURLcode result = CURLE_OK;
3151 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3153 if (conn->sslEngine != NULL)
3154 free(conn->sslEngine);
3156 conn->sslEngine = strdup(String_val(option));
3158 result = curl_easy_setopt(conn->connection,
3159 CURLOPT_SSLENGINE,
3160 conn->sslEngine);
3162 if (result != CURLE_OK)
3163 raiseError(conn, result);
3165 CAMLreturn0;
3168 static void handleSSLEngineDefault(Connection *conn, value option)
3170 CAMLparam1(option);
3171 CURLcode result = CURLE_OK;
3173 result = curl_easy_setopt(conn->connection,
3174 CURLOPT_SSLENGINE_DEFAULT,
3175 Bool_val(option));
3177 if (result != CURLE_OK)
3178 raiseError(conn, result);
3180 CAMLreturn0;
3183 static void handleCRLF(Connection *conn, value option)
3185 CAMLparam1(option);
3186 CURLcode result = CURLE_OK;
3188 result = curl_easy_setopt(conn->connection,
3189 CURLOPT_CRLF,
3190 Bool_val(option));
3192 if (result != CURLE_OK)
3193 raiseError(conn, result);
3195 CAMLreturn0;
3198 static void handleQuote(Connection *conn, value option)
3200 CAMLparam1(option);
3201 CAMLlocal1(listIter);
3202 CURLcode result = CURLE_OK;
3203 char *str;
3205 Store_field(conn->ocamlValues, OcamlQuote, option);
3207 if (conn->quote != NULL)
3208 free_curl_slist(conn->quote);
3210 conn->quote = NULL;
3212 listIter = option;
3214 while (!Is_long(listIter))
3216 if (Tag_val(Field(listIter, 0)) != String_tag)
3217 failwith("Not a string");
3219 str = strdup(String_val(Field(listIter, 0)));
3221 conn->quote = curl_slist_append(conn->quote, str);
3223 listIter = Field(listIter, 1);
3226 result = curl_easy_setopt(conn->connection,
3227 CURLOPT_QUOTE,
3228 conn->quote);
3230 if (result != CURLE_OK)
3231 raiseError(conn, result);
3233 CAMLreturn0;
3236 static void handlePostQuote(Connection *conn, value option)
3238 CAMLparam1(option);
3239 CAMLlocal1(listIter);
3240 CURLcode result = CURLE_OK;
3241 char *str;
3243 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3245 if (conn->postQuote != NULL)
3246 free_curl_slist(conn->postQuote);
3248 conn->postQuote = NULL;
3250 listIter = option;
3252 while (!Is_long(listIter))
3254 if (Tag_val(Field(listIter, 0)) != String_tag)
3255 failwith("Not a string");
3257 str = strdup(String_val(Field(listIter, 0)));
3259 conn->postQuote = curl_slist_append(conn->postQuote, str);
3261 listIter = Field(listIter, 1);
3264 result = curl_easy_setopt(conn->connection,
3265 CURLOPT_POSTQUOTE,
3266 conn->postQuote);
3268 if (result != CURLE_OK)
3269 raiseError(conn, result);
3271 CAMLreturn0;
3274 static void handleHeaderFunction(Connection *conn, value option)
3276 CAMLparam1(option);
3277 CURLcode result = CURLE_OK;
3279 if (Tag_val(option) == Closure_tag)
3280 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3281 else
3282 failwith("Not a proper closure");
3284 result = curl_easy_setopt(conn->connection,
3285 CURLOPT_HEADERFUNCTION,
3286 headerFunction);
3288 if (result != CURLE_OK)
3289 raiseError(conn, result);
3291 result = curl_easy_setopt(conn->connection,
3292 CURLOPT_WRITEHEADER,
3293 conn);
3295 if (result != CURLE_OK)
3296 raiseError(conn, result);
3298 CAMLreturn0;
3301 static void handleCookieFile(Connection *conn, value option)
3303 CAMLparam1(option);
3304 CURLcode result = CURLE_OK;
3306 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3308 if (conn->cookieFile != NULL)
3309 free(conn->cookieFile);
3311 conn->cookieFile = strdup(String_val(option));
3313 result = curl_easy_setopt(conn->connection,
3314 CURLOPT_COOKIEFILE,
3315 conn->cookieFile);
3317 if (result != CURLE_OK)
3318 raiseError(conn, result);
3320 CAMLreturn0;
3323 static void handleSSLVersion(Connection *conn, value option)
3325 CAMLparam1(option);
3326 CURLcode result = CURLE_OK;
3328 result = curl_easy_setopt(conn->connection,
3329 CURLOPT_SSLVERSION,
3330 Long_val(option));
3332 if (result != CURLE_OK)
3333 raiseError(conn, result);
3335 CAMLreturn0;
3338 static void handleTimeCondition(Connection *conn, value option)
3340 CAMLparam1(option);
3341 CURLcode result = CURLE_OK;
3343 switch (Long_val(option))
3345 case 0: /* TIMECOND_IFMODSINCE */
3346 result = curl_easy_setopt(conn->connection,
3347 CURLOPT_TIMECONDITION,
3348 CURL_TIMECOND_IFMODSINCE);
3349 break;
3351 case 1: /* TIMECOND_IFUNMODSINCE */
3352 result = curl_easy_setopt(conn->connection,
3353 CURLOPT_TIMECONDITION,
3354 CURL_TIMECOND_IFUNMODSINCE);
3355 break;
3357 default:
3358 failwith("Invalid TIMECOND Option");
3359 break;
3362 if (result != CURLE_OK)
3363 raiseError(conn, result);
3365 CAMLreturn0;
3368 static void handleTimeValue(Connection *conn, value option)
3370 CAMLparam1(option);
3371 CURLcode result = CURLE_OK;
3373 result = curl_easy_setopt(conn->connection,
3374 CURLOPT_TIMEVALUE,
3375 Int32_val(option));
3377 if (result != CURLE_OK)
3378 raiseError(conn, result);
3380 CAMLreturn0;
3383 static void handleCustomRequest(Connection *conn, value option)
3385 CAMLparam1(option);
3386 CURLcode result = CURLE_OK;
3388 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3390 if (conn->customRequest != NULL)
3391 free(conn->customRequest);
3393 conn->customRequest = strdup(String_val(option));
3395 result = curl_easy_setopt(conn->connection,
3396 CURLOPT_CUSTOMREQUEST,
3397 conn->customRequest);
3399 if (result != CURLE_OK)
3400 raiseError(conn, result);
3402 CAMLreturn0;
3405 static void handleInterface(Connection *conn, value option)
3407 CAMLparam1(option);
3408 CURLcode result = CURLE_OK;
3410 Store_field(conn->ocamlValues, OcamlInterface, option);
3412 if (conn->interface != NULL)
3413 free(conn->interface);
3415 conn->interface = strdup(String_val(option));
3417 result = curl_easy_setopt(conn->connection,
3418 CURLOPT_INTERFACE,
3419 conn->interface);
3421 if (result != CURLE_OK)
3422 raiseError(conn, result);
3424 CAMLreturn0;
3427 static void handleKRB4Level(Connection *conn, value option)
3429 CAMLparam1(option);
3430 CURLcode result = CURLE_OK;
3432 switch (Long_val(option))
3434 case 0: /* KRB4_NONE */
3435 result = curl_easy_setopt(conn->connection,
3436 CURLOPT_KRB4LEVEL,
3437 NULL);
3438 break;
3440 case 1: /* KRB4_CLEAR */
3441 result = curl_easy_setopt(conn->connection,
3442 CURLOPT_KRB4LEVEL,
3443 "clear");
3444 break;
3446 case 2: /* KRB4_SAFE */
3447 result = curl_easy_setopt(conn->connection,
3448 CURLOPT_KRB4LEVEL,
3449 "safe");
3450 break;
3452 case 3: /* KRB4_CONFIDENTIAL */
3453 result = curl_easy_setopt(conn->connection,
3454 CURLOPT_KRB4LEVEL,
3455 "confidential");
3456 break;
3458 case 4: /* KRB4_PRIVATE */
3459 result = curl_easy_setopt(conn->connection,
3460 CURLOPT_KRB4LEVEL,
3461 "private");
3462 break;
3464 default:
3465 failwith("Invalid KRB4 Option");
3466 break;
3469 if (result != CURLE_OK)
3470 raiseError(conn, result);
3472 CAMLreturn0;
3475 static void handleProgressFunction(Connection *conn, value option)
3477 CAMLparam1(option);
3478 CURLcode result = CURLE_OK;
3480 if (Tag_val(option) == Closure_tag)
3481 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3482 else
3483 failwith("Not a proper closure");
3485 result = curl_easy_setopt(conn->connection,
3486 CURLOPT_PROGRESSFUNCTION,
3487 progressFunction);
3488 if (result != CURLE_OK)
3489 raiseError(conn, result);
3491 result = curl_easy_setopt(conn->connection,
3492 CURLOPT_PROGRESSDATA,
3493 conn);
3495 if (result != CURLE_OK)
3496 raiseError(conn, result);
3498 CAMLreturn0;
3501 static void handleSSLVerifyPeer(Connection *conn, value option)
3503 CAMLparam1(option);
3504 CURLcode result = CURLE_OK;
3506 result = curl_easy_setopt(conn->connection,
3507 CURLOPT_SSL_VERIFYPEER,
3508 Bool_val(option));
3510 if (result != CURLE_OK)
3511 raiseError(conn, result);
3513 CAMLreturn0;
3516 static void handleCAInfo(Connection *conn, value option)
3518 CAMLparam1(option);
3519 CURLcode result = CURLE_OK;
3521 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3523 if (conn->caInfo != NULL)
3524 free(conn->caInfo);
3526 conn->caInfo = strdup(String_val(option));
3528 result = curl_easy_setopt(conn->connection,
3529 CURLOPT_CAINFO,
3530 conn->caInfo);
3532 if (result != CURLE_OK)
3533 raiseError(conn, result);
3535 CAMLreturn0;
3538 static void handleCAPath(Connection *conn, value option)
3540 CAMLparam1(option);
3541 CURLcode result = CURLE_OK;
3543 Store_field(conn->ocamlValues, OcamlCAPath, option);
3545 if (conn->caPath != NULL)
3546 free(conn->caPath);
3548 conn->caPath = strdup(String_val(option));
3550 result = curl_easy_setopt(conn->connection,
3551 CURLOPT_CAPATH,
3552 conn->caPath);
3554 if (result != CURLE_OK)
3555 raiseError(conn, result);
3557 CAMLreturn0;
3560 static void handleFileTime(Connection *conn, value option)
3562 CAMLparam1(option);
3563 CURLcode result = CURLE_OK;
3565 result = curl_easy_setopt(conn->connection,
3566 CURLOPT_FILETIME,
3567 Bool_val(option));
3569 if (result != CURLE_OK)
3570 raiseError(conn, result);
3572 CAMLreturn0;
3575 static void handleMaxRedirs(Connection *conn, value option)
3577 CAMLparam1(option);
3578 CURLcode result = CURLE_OK;
3580 result = curl_easy_setopt(conn->connection,
3581 CURLOPT_MAXREDIRS,
3582 Long_val(option));
3584 if (result != CURLE_OK)
3585 raiseError(conn, result);
3587 CAMLreturn0;
3590 static void handleMaxConnects(Connection *conn, value option)
3592 CAMLparam1(option);
3593 CURLcode result = CURLE_OK;
3595 result = curl_easy_setopt(conn->connection,
3596 CURLOPT_MAXCONNECTS,
3597 Long_val(option));
3599 if (result != CURLE_OK)
3600 raiseError(conn, result);
3602 CAMLreturn0;
3605 static void handleClosePolicy(Connection *conn, value option)
3607 CAMLparam1(option);
3608 CURLcode result = CURLE_OK;
3610 switch (Long_val(option))
3612 case 0: /* CLOSEPOLICY_OLDEST */
3613 result = curl_easy_setopt(conn->connection,
3614 CURLOPT_CLOSEPOLICY,
3615 CURLCLOSEPOLICY_OLDEST);
3616 break;
3618 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3619 result = curl_easy_setopt(conn->connection,
3620 CURLOPT_CLOSEPOLICY,
3621 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3622 break;
3624 default:
3625 failwith("Invalid CLOSEPOLICY Option");
3626 break;
3629 if (result != CURLE_OK)
3630 raiseError(conn, result);
3632 CAMLreturn0;
3635 static void handleFreshConnect(Connection *conn, value option)
3637 CAMLparam1(option);
3638 CURLcode result = CURLE_OK;
3640 result = curl_easy_setopt(conn->connection,
3641 CURLOPT_FRESH_CONNECT,
3642 Bool_val(option));
3644 if (result != CURLE_OK)
3645 raiseError(conn, result);
3647 CAMLreturn0;
3650 static void handleForbidReuse(Connection *conn, value option)
3652 CAMLparam1(option);
3653 CURLcode result = CURLE_OK;
3655 result = curl_easy_setopt(conn->connection,
3656 CURLOPT_FORBID_REUSE,
3657 Bool_val(option));
3659 if (result != CURLE_OK)
3660 raiseError(conn, result);
3662 CAMLreturn0;
3665 static void handleRandomFile(Connection *conn, value option)
3667 CAMLparam1(option);
3668 CURLcode result = CURLE_OK;
3670 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3672 if (conn->randomFile != NULL)
3673 free(conn->randomFile);
3675 conn->randomFile = strdup(String_val(option));
3677 result = curl_easy_setopt(conn->connection,
3678 CURLOPT_RANDOM_FILE,
3679 conn->randomFile);
3681 if (result != CURLE_OK)
3682 raiseError(conn, result);
3684 CAMLreturn0;
3687 static void handleEGDSocket(Connection *conn, value option)
3689 CAMLparam1(option);
3690 CURLcode result = CURLE_OK;
3692 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3694 if (conn->egdSocket != NULL)
3695 free(conn->egdSocket);
3697 conn->egdSocket = strdup(String_val(option));
3699 result = curl_easy_setopt(conn->connection,
3700 CURLOPT_EGDSOCKET,
3701 conn->egdSocket);
3703 if (result != CURLE_OK)
3704 raiseError(conn, result);
3706 CAMLreturn0;
3709 static void handleConnectTimeout(Connection *conn, value option)
3711 CAMLparam1(option);
3712 CURLcode result = CURLE_OK;
3714 result = curl_easy_setopt(conn->connection,
3715 CURLOPT_CONNECTTIMEOUT,
3716 Long_val(option));
3718 if (result != CURLE_OK)
3719 raiseError(conn, result);
3721 CAMLreturn0;
3724 static void handleHTTPGet(Connection *conn, value option)
3726 CAMLparam1(option);
3727 CURLcode result = CURLE_OK;
3729 result = curl_easy_setopt(conn->connection,
3730 CURLOPT_HTTPGET,
3731 Bool_val(option));
3733 if (result != CURLE_OK)
3734 raiseError(conn, result);
3736 CAMLreturn0;
3739 static void handleSSLVerifyHost(Connection *conn, value option)
3741 CAMLparam1(option);
3742 CURLcode result = CURLE_OK;
3744 switch (Long_val(option))
3746 case 0: /* SSLVERIFYHOST_EXISTENCE */
3747 result = curl_easy_setopt(conn->connection,
3748 CURLOPT_SSL_VERIFYHOST,
3750 break;
3752 case 1: /* SSLVERIFYHOST_HOSTNAME */
3753 result = curl_easy_setopt(conn->connection,
3754 CURLOPT_SSL_VERIFYHOST,
3756 break;
3758 default:
3759 failwith("Invalid SSLVERIFYHOST Option");
3760 break;
3763 if (result != CURLE_OK)
3764 raiseError(conn, result);
3766 CAMLreturn0;
3769 static void handleCookieJar(Connection *conn, value option)
3771 CAMLparam1(option);
3772 CURLcode result = CURLE_OK;
3774 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3776 if (conn->cookieJar != NULL)
3777 free(conn->cookieJar);
3779 conn->cookieJar = strdup(String_val(option));
3781 result = curl_easy_setopt(conn->connection,
3782 CURLOPT_COOKIEJAR,
3783 conn->cookieJar);
3785 if (result != CURLE_OK)
3786 raiseError(conn, result);
3788 CAMLreturn0;
3791 static void handleSSLCipherList(Connection *conn, value option)
3793 CAMLparam1(option);
3794 CURLcode result = CURLE_OK;
3796 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3798 if (conn->sslCipherList != NULL)
3799 free(conn->sslCipherList);
3801 conn->sslCipherList = strdup(String_val(option));
3803 result = curl_easy_setopt(conn->connection,
3804 CURLOPT_SSL_CIPHER_LIST,
3805 conn->sslCipherList);
3807 if (result != CURLE_OK)
3808 raiseError(conn, result);
3810 CAMLreturn0;
3813 static void handleHTTPVersion(Connection *conn, value option)
3815 CAMLparam1(option);
3816 CURLcode result = CURLE_OK;
3818 switch (Long_val(option))
3820 case 0: /* HTTP_VERSION_NONE */
3821 result = curl_easy_setopt(conn->connection,
3822 CURLOPT_HTTP_VERSION,
3823 CURL_HTTP_VERSION_NONE);
3824 break;
3826 case 1: /* HTTP_VERSION_1_0 */
3827 result = curl_easy_setopt(conn->connection,
3828 CURLOPT_HTTP_VERSION,
3829 CURL_HTTP_VERSION_1_0);
3830 break;
3832 case 2: /* HTTP_VERSION_1_1 */
3833 result = curl_easy_setopt(conn->connection,
3834 CURLOPT_HTTP_VERSION,
3835 CURL_HTTP_VERSION_1_1);
3836 break;
3838 default:
3839 failwith("Invalid HTTP_VERSION Option");
3840 break;
3843 if (result != CURLE_OK)
3844 raiseError(conn, result);
3846 CAMLreturn0;
3849 static void handleFTPUseEPSV(Connection *conn, value option)
3851 CAMLparam1(option);
3852 CURLcode result = CURLE_OK;
3854 result = curl_easy_setopt(conn->connection,
3855 CURLOPT_FTP_USE_EPSV,
3856 Bool_val(option));
3858 if (result != CURLE_OK)
3859 raiseError(conn, result);
3861 CAMLreturn0;
3864 static void handleDNSCacheTimeout(Connection *conn, value option)
3866 CAMLparam1(option);
3867 CURLcode result = CURLE_OK;
3869 result = curl_easy_setopt(conn->connection,
3870 CURLOPT_DNS_CACHE_TIMEOUT,
3871 Long_val(option));
3873 if (result != CURLE_OK)
3874 raiseError(conn, result);
3876 CAMLreturn0;
3879 static void handleDNSUseGlobalCache(Connection *conn, value option)
3881 CAMLparam1(option);
3882 CURLcode result = CURLE_OK;
3884 result = curl_easy_setopt(conn->connection,
3885 CURLOPT_DNS_USE_GLOBAL_CACHE,
3886 Bool_val(option));
3888 if (result != CURLE_OK)
3889 raiseError(conn, result);
3891 CAMLreturn0;
3894 static void handleDebugFunction(Connection *conn, value option)
3896 CAMLparam1(option);
3897 CURLcode result = CURLE_OK;
3899 if (Tag_val(option) == Closure_tag)
3900 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3901 else
3902 failwith("Not a proper closure");
3904 result = curl_easy_setopt(conn->connection,
3905 CURLOPT_DEBUGFUNCTION,
3906 debugFunction);
3907 if (result != CURLE_OK)
3908 raiseError(conn, result);
3910 result = curl_easy_setopt(conn->connection,
3911 CURLOPT_DEBUGDATA,
3912 conn);
3914 if (result != CURLE_OK)
3915 raiseError(conn, result);
3917 CAMLreturn0;
3920 static void handlePrivate(Connection *conn, value option)
3922 #if HAVE_DECL_CURLOPT_PRIVATE
3923 CAMLparam1(option);
3924 CURLcode result = CURLE_OK;
3926 Store_field(conn->ocamlValues, OcamlPrivate, option);
3928 if (conn->private != NULL)
3929 free(conn->private);
3931 conn->private = strdup(String_val(option));
3933 result = curl_easy_setopt(conn->connection,
3934 CURLOPT_PRIVATE,
3935 conn->private);
3937 if (result != CURLE_OK)
3938 raiseError(conn, result);
3940 CAMLreturn0;
3941 #else
3942 #warning "libcurl does not implement CURLOPT_PRIVATE"
3943 failwith("libcurl does not implement CURLOPT_PRIVATE");
3944 #endif
3947 static void handleHTTP200Aliases(Connection *conn, value option)
3949 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3950 CAMLparam1(option);
3951 CAMLlocal1(listIter);
3952 CURLcode result = CURLE_OK;
3953 char *str;
3955 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3957 if (conn->http200Aliases != NULL)
3958 free_curl_slist(conn->http200Aliases);
3960 conn->http200Aliases = NULL;
3962 listIter = option;
3964 while (!Is_long(listIter))
3966 if (Tag_val(Field(listIter, 0)) != String_tag)
3967 failwith("Not a string");
3969 str = strdup(String_val(Field(listIter, 0)));
3971 conn->http200Aliases = curl_slist_append(conn->http200Aliases, str);
3973 listIter = Field(listIter, 1);
3976 result = curl_easy_setopt(conn->connection,
3977 CURLOPT_HTTP200ALIASES,
3978 conn->http200Aliases);
3980 if (result != CURLE_OK)
3981 raiseError(conn, result);
3983 CAMLreturn0;
3984 #else
3985 #warning "libcurl does not implement CURLOPT_HTTP200ALIASES"
3986 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
3987 #endif
3990 static void handleUnrestrictedAuth(Connection *conn, value option)
3992 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
3993 CAMLparam1(option);
3994 CURLcode result = CURLE_OK;
3996 result = curl_easy_setopt(conn->connection,
3997 CURLOPT_UNRESTRICTED_AUTH,
3998 Bool_val(option));
4000 if (result != CURLE_OK)
4001 raiseError(conn, result);
4003 CAMLreturn0;
4004 #else
4005 #warning "libcurl does not implement CURLOPT_UNRESTRICTED_AUTH"
4006 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4007 #endif
4010 static void handleFTPUseEPRT(Connection *conn, value option)
4012 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4013 CAMLparam1(option);
4014 CURLcode result = CURLE_OK;
4016 result = curl_easy_setopt(conn->connection,
4017 CURLOPT_FTP_USE_EPRT,
4018 Bool_val(option));
4020 if (result != CURLE_OK)
4021 raiseError(conn, result);
4023 CAMLreturn0;
4024 #else
4025 #warning "libcurl does not implement CURLOPT_FTP_USE_EPRT"
4026 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4027 #endif
4030 static void handleHTTPAuth(Connection *conn, value option)
4032 #if HAVE_DECL_CURLOPT_HTTPAUTH
4033 CAMLparam1(option);
4034 CAMLlocal1(listIter);
4035 CURLcode result = CURLE_OK;
4036 long auth = CURLAUTH_NONE;
4038 listIter = option;
4040 while (!Is_long(listIter))
4042 switch (Long_val(Field(listIter, 0)))
4044 case 0: /* CURLAUTH_BASIC */
4045 auth |= CURLAUTH_BASIC;
4046 break;
4048 case 1: /* CURLAUTH_DIGEST */
4049 auth |= CURLAUTH_DIGEST;
4050 break;
4052 case 2: /* CURLAUTH_GSSNEGOTIATE */
4053 auth |= CURLAUTH_GSSNEGOTIATE;
4054 break;
4056 case 3: /* CURLAUTH_NTLM */
4057 auth |= CURLAUTH_NTLM;
4058 break;
4060 case 4: /* CURLAUTH_ANY */
4061 auth |= CURLAUTH_ANY;
4062 break;
4064 case 5: /* CURLAUTH_ANYSAFE */
4065 auth |= CURLAUTH_ANYSAFE;
4066 break;
4068 default:
4069 failwith("Invalid HTTPAUTH Value");
4070 break;
4073 listIter = Field(listIter, 1);
4076 result = curl_easy_setopt(conn->connection,
4077 CURLOPT_HTTPAUTH,
4078 auth);
4080 if (result != CURLE_OK)
4081 raiseError(conn, result);
4083 CAMLreturn0;
4084 #else
4085 #warning "libcurl does not implement CURLOPT_HTTPAUTH"
4086 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4087 #endif
4090 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4092 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4093 CAMLparam1(option);
4094 CURLcode result = CURLE_OK;
4096 result = curl_easy_setopt(conn->connection,
4097 CURLOPT_FTP_CREATE_MISSING_DIRS,
4098 Bool_val(option));
4100 if (result != CURLE_OK)
4101 raiseError(conn, result);
4103 CAMLreturn0;
4104 #else
4105 #warning "libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS"
4106 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4107 #endif
4110 static void handleProxyAuth(Connection *conn, value option)
4112 #if HAVE_DECL_CURLOPT_PROXYAUTH
4113 CAMLparam1(option);
4114 CAMLlocal1(listIter);
4115 CURLcode result = CURLE_OK;
4116 long auth = CURLAUTH_NONE;
4118 listIter = option;
4120 while (!Is_long(listIter))
4122 switch (Long_val(Field(listIter, 0)))
4124 case 0: /* CURLAUTH_BASIC */
4125 auth |= CURLAUTH_BASIC;
4126 break;
4128 case 1: /* CURLAUTH_DIGEST */
4129 auth |= CURLAUTH_DIGEST;
4130 break;
4132 case 2: /* CURLAUTH_GSSNEGOTIATE */
4133 auth |= CURLAUTH_GSSNEGOTIATE;
4134 break;
4136 case 3: /* CURLAUTH_NTLM */
4137 auth |= CURLAUTH_NTLM;
4138 break;
4140 case 4: /* CURLAUTH_ANY */
4141 auth |= CURLAUTH_ANY;
4142 break;
4144 case 5: /* CURLAUTH_ANYSAFE */
4145 auth |= CURLAUTH_ANYSAFE;
4146 break;
4148 default:
4149 failwith("Invalid HTTPAUTH Value");
4150 break;
4153 listIter = Field(listIter, 1);
4156 result = curl_easy_setopt(conn->connection,
4157 CURLOPT_PROXYAUTH,
4158 auth);
4160 if (result != CURLE_OK)
4161 raiseError(conn, result);
4163 CAMLreturn0;
4164 #else
4165 #warning "libcurl does not implement CURLOPT_PROXYAUTH"
4166 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4167 #endif
4170 static void handleFTPResponseTimeout(Connection *conn, value option)
4172 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4173 CAMLparam1(option);
4174 CURLcode result = CURLE_OK;
4176 result = curl_easy_setopt(conn->connection,
4177 CURLOPT_FTP_RESPONSE_TIMEOUT,
4178 Long_val(option));
4180 if (result != CURLE_OK)
4181 raiseError(conn, result);
4183 CAMLreturn0;
4184 #else
4185 #warning "libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT"
4186 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4187 #endif
4190 static void handleIPResolve(Connection *conn, value option)
4192 #if HAVE_DECL_CURLOPT_IPRESOLVE
4193 CAMLparam1(option);
4194 CURLcode result = CURLE_OK;
4196 switch (Long_val(option))
4198 case 0: /* CURL_IPRESOLVE_WHATEVER */
4199 result = curl_easy_setopt(conn->connection,
4200 CURLOPT_IPRESOLVE,
4201 CURL_IPRESOLVE_WHATEVER);
4202 break;
4204 case 1: /* CURL_IPRESOLVE_V4 */
4205 result = curl_easy_setopt(conn->connection,
4206 CURLOPT_IPRESOLVE,
4207 CURL_IPRESOLVE_V4);
4208 break;
4210 case 2: /* CURL_IPRESOLVE_V6 */
4211 result = curl_easy_setopt(conn->connection,
4212 CURLOPT_IPRESOLVE,
4213 CURL_IPRESOLVE_V6);
4214 break;
4216 default:
4217 failwith("Invalid IPRESOLVE Value");
4218 break;
4221 if (result != CURLE_OK)
4222 raiseError(conn, result);
4224 CAMLreturn0;
4225 #else
4226 #warning "libcurl does not implement CURLOPT_IPRESOLVE"
4227 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4228 #endif
4231 static void handleMaxFileSize(Connection *conn, value option)
4233 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4234 CAMLparam1(option);
4235 CURLcode result = CURLE_OK;
4237 result = curl_easy_setopt(conn->connection,
4238 CURLOPT_MAXFILESIZE,
4239 Int32_val(option));
4241 if (result != CURLE_OK)
4242 raiseError(conn, result);
4244 CAMLreturn0;
4245 #else
4246 #warning "libcurl does not implement CURLOPT_MAXFILESIZE"
4247 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4248 #endif
4251 static void handleInFileSizeLarge(Connection *conn, value option)
4253 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4254 CAMLparam1(option);
4255 CURLcode result = CURLE_OK;
4257 result = curl_easy_setopt(conn->connection,
4258 CURLOPT_INFILESIZE_LARGE,
4259 Int64_val(option));
4261 if (result != CURLE_OK)
4262 raiseError(conn, result);
4264 CAMLreturn0;
4265 #else
4266 #warning("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4267 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4268 #endif
4271 static void handleResumeFromLarge(Connection *conn, value option)
4273 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4274 CAMLparam1(option);
4275 CURLcode result = CURLE_OK;
4277 result = curl_easy_setopt(conn->connection,
4278 CURLOPT_RESUME_FROM_LARGE,
4279 Int64_val(option));
4281 if (result != CURLE_OK)
4282 raiseError(conn, result);
4284 CAMLreturn0;
4285 #else
4286 #warning("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4287 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4288 #endif
4291 static void handleMaxFileSizeLarge(Connection *conn, value option)
4293 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4294 CAMLparam1(option);
4295 CURLcode result = CURLE_OK;
4297 result = curl_easy_setopt(conn->connection,
4298 CURLOPT_MAXFILESIZE_LARGE,
4299 Int64_val(option));
4301 if (result != CURLE_OK)
4302 raiseError(conn, result);
4304 CAMLreturn0;
4305 #else
4306 #warning "libcurl does not implement CURLOPT_MAXFILESIZE_LARGE"
4307 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4308 #endif
4311 static void handleNETRCFile(Connection *conn, value option)
4313 #if HAVE_DECL_CURLOPT_NETRC_FILE
4314 CAMLparam1(option);
4315 CURLcode result = CURLE_OK;
4317 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4319 if (conn->netrcFile != NULL)
4320 free(conn->netrcFile);
4322 conn->netrcFile = strdup(String_val(option));
4324 result = curl_easy_setopt(conn->connection,
4325 CURLOPT_NETRC_FILE,
4326 conn->netrcFile);
4328 if (result != CURLE_OK)
4329 raiseError(conn, result);
4331 CAMLreturn0;
4332 #else
4333 #warning "libcurl does not implement CURLOPT_NETRC_FILE"
4334 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4335 #endif
4338 static void handleFTPSSL(Connection *conn, value option)
4340 #if HAVE_DECL_CURLOPT_FTP_SSL
4341 CAMLparam1(option);
4342 CURLcode result = CURLE_OK;
4344 switch (Long_val(option))
4346 case 0: /* CURLFTPSSL_NONE */
4347 result = curl_easy_setopt(conn->connection,
4348 CURLOPT_FTP_SSL,
4349 CURLFTPSSL_NONE);
4350 break;
4352 case 1: /* CURLFTPSSL_TRY */
4353 result = curl_easy_setopt(conn->connection,
4354 CURLOPT_FTP_SSL,
4355 CURLFTPSSL_TRY);
4356 break;
4358 case 2: /* CURLFTPSSL_CONTROL */
4359 result = curl_easy_setopt(conn->connection,
4360 CURLOPT_FTP_SSL,
4361 CURLFTPSSL_CONTROL);
4362 break;
4364 case 3: /* CURLFTPSSL_ALL */
4365 result = curl_easy_setopt(conn->connection,
4366 CURLOPT_FTP_SSL,
4367 CURLFTPSSL_ALL);
4368 break;
4370 default:
4371 failwith("Invalid FTP_SSL Value");
4372 break;
4375 if (result != CURLE_OK)
4376 raiseError(conn, result);
4378 CAMLreturn0;
4379 #else
4380 #warning "libcurl does not implement CURLOPT_FTP_SSL"
4381 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4382 #endif
4385 static void handlePostFieldSizeLarge(Connection *conn, value option)
4387 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4388 CAMLparam1(option);
4389 CURLcode result = CURLE_OK;
4391 result = curl_easy_setopt(conn->connection,
4392 CURLOPT_POSTFIELDSIZE_LARGE,
4393 Int64_val(option));
4395 if (result != CURLE_OK)
4396 raiseError(conn, result);
4398 CAMLreturn0;
4399 #else
4400 #warning "libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE"
4401 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4402 #endif
4405 static void handleTCPNoDelay(Connection *conn, value option)
4407 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4408 CAMLparam1(option);
4409 CURLcode result = CURLE_OK;
4411 result = curl_easy_setopt(conn->connection,
4412 CURLOPT_TCP_NODELAY,
4413 Bool_val(option));
4415 if (result != CURLE_OK)
4416 raiseError(conn, result);
4418 CAMLreturn0;
4419 #else
4420 #warning "libcurl does not implement CURLOPT_TCP_NODELAY"
4421 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4422 #endif
4425 static void handleFTPSSLAuth(Connection *conn, value option)
4427 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4428 CAMLparam1(option);
4429 CURLcode result = CURLE_OK;
4431 switch (Long_val(option))
4433 case 0: /* CURLFTPAUTH_DEFAULT */
4434 result = curl_easy_setopt(conn->connection,
4435 CURLOPT_FTPSSLAUTH,
4436 CURLFTPAUTH_DEFAULT);
4437 break;
4439 case 1: /* CURLFTPAUTH_SSL */
4440 result = curl_easy_setopt(conn->connection,
4441 CURLOPT_FTPSSLAUTH,
4442 CURLFTPAUTH_SSL);
4443 break;
4445 case 2: /* CURLFTPAUTH_TLS */
4446 result = curl_easy_setopt(conn->connection,
4447 CURLOPT_FTPSSLAUTH,
4448 CURLFTPAUTH_TLS);
4449 break;
4451 default:
4452 failwith("Invalid FTPSSLAUTH value");
4453 break;
4456 if (result != CURLE_OK)
4457 raiseError(conn, result);
4459 CAMLreturn0;
4460 #else
4461 #warning "libcurl does not implement CURLOPT_FTPSSLAUTH"
4462 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4463 #endif
4466 static void handleIOCTLFunction(Connection *conn, value option)
4468 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4469 CAMLparam1(option);
4470 CURLcode result = CURLE_OK;
4472 if (Tag_val(option) == Closure_tag)
4473 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4474 else
4475 failwith("Not a proper closure");
4477 result = curl_easy_setopt(conn->connection,
4478 CURLOPT_IOCTLFUNCTION,
4479 ioctlFunction);
4480 if (result != CURLE_OK)
4481 raiseError(conn, result);
4483 result = curl_easy_setopt(conn->connection,
4484 CURLOPT_DEBUGDATA,
4485 conn);
4487 if (result != CURLE_OK)
4488 raiseError(conn, result);
4490 CAMLreturn0;
4491 #else
4492 #warning "libcurl does not implement CURLOPT_IOCTLFUNCTION"
4493 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4494 #endif
4497 static void handleFTPAccount(Connection *conn, value option)
4499 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4500 CAMLparam1(option);
4501 CURLcode result = CURLE_OK;
4503 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4505 if (conn->ftpaccount != NULL)
4506 free(conn->ftpaccount);
4508 conn->ftpaccount = strdup(String_val(option));
4510 result = curl_easy_setopt(conn->connection,
4511 CURLOPT_FTP_ACCOUNT,
4512 conn->ftpaccount);
4514 if (result != CURLE_OK)
4515 raiseError(conn, result);
4517 CAMLreturn0;
4518 #else
4519 #warning "libcurl does not implement CURLOPT_FTP_ACCOUNT"
4520 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4521 #endif
4524 static void handleCookieList(Connection *conn, value option)
4526 #if HAVE_DECL_CURLOPT_COOKIELIST
4527 CAMLparam1(option);
4528 CURLcode result = CURLE_OK;
4530 Store_field(conn->ocamlValues, OcamlCookieList, option);
4532 if (conn->cookielist != NULL)
4533 free(conn->cookielist);
4535 conn->cookielist = strdup(String_val(option));
4537 result = curl_easy_setopt(conn->connection,
4538 CURLOPT_COOKIELIST,
4539 conn->cookielist);
4541 if (result != CURLE_OK)
4542 raiseError(conn, result);
4544 CAMLreturn0;
4545 #else
4546 #warning "libcurl does not implement CURLOPT_COOKIELIST"
4547 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4548 #endif
4551 static void handleIgnoreContentLength(Connection *conn, value option)
4553 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4554 CAMLparam1(option);
4555 CURLcode result = CURLE_OK;
4557 result = curl_easy_setopt(conn->connection,
4558 CURLOPT_IGNORE_CONTENT_LENGTH,
4559 Bool_val(option));
4561 if (result != CURLE_OK)
4562 raiseError(conn, result);
4564 CAMLreturn0;
4565 #else
4566 #warning "libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH"
4567 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4568 #endif
4571 static void handleFTPSkipPASVIP(Connection *conn, value option)
4573 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4574 CAMLparam1(option);
4575 CURLcode result = CURLE_OK;
4577 result = curl_easy_setopt(conn->connection,
4578 CURLOPT_FTP_SKIP_PASV_IP,
4579 Bool_val(option));
4581 if (result != CURLE_OK)
4582 raiseError(conn, result);
4584 CAMLreturn0;
4585 #else
4586 #warning "libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP"
4587 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4588 #endif
4591 static void handleFTPFileMethod(Connection *conn, value option)
4593 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4594 CAMLparam1(option);
4595 CURLcode result = CURLE_OK;
4597 switch (Long_val(option))
4599 case 0: /* CURLFTPMETHOD_DEFAULT */
4600 result = curl_easy_setopt(conn->connection,
4601 CURLOPT_FTP_FILEMETHOD,
4602 CURLFTPMETHOD_DEFAULT);
4603 break;
4605 case 1: /* CURLFTMETHOD_MULTICWD */
4606 result = curl_easy_setopt(conn->connection,
4607 CURLOPT_FTP_FILEMETHOD,
4608 CURLFTPMETHOD_MULTICWD);
4609 break;
4611 case 2: /* CURLFTPMETHOD_NOCWD */
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_FILEMETHOD,
4614 CURLFTPMETHOD_NOCWD);
4615 break;
4617 case 3: /* CURLFTPMETHOD_SINGLECWD */
4618 result = curl_easy_setopt(conn->connection,
4619 CURLOPT_FTP_FILEMETHOD,
4620 CURLFTPMETHOD_SINGLECWD);
4622 default:
4623 failwith("Invalid FTP_FILEMETHOD value");
4624 break;
4627 if (result != CURLE_OK)
4628 raiseError(conn, result);
4630 CAMLreturn0;
4631 #else
4632 #warning "libcurl does not implement CURLOPT_FTP_FILEMETHOD"
4633 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4634 #endif
4637 static void handleLocalPort(Connection *conn, value option)
4639 #if HAVE_DECL_CURLOPT_LOCALPORT
4640 CAMLparam1(option);
4641 CURLcode result = CURLE_OK;
4643 result = curl_easy_setopt(conn->connection,
4644 CURLOPT_LOCALPORT,
4645 Long_val(option));
4647 if (result != CURLE_OK)
4648 raiseError(conn, result);
4650 CAMLreturn0;
4651 #else
4652 #warning "libcurl does not implement CURLOPT_LOCALPORT"
4653 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4654 #endif
4657 static void handleLocalPortRange(Connection *conn, value option)
4659 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4660 CAMLparam1(option);
4661 CURLcode result = CURLE_OK;
4663 result = curl_easy_setopt(conn->connection,
4664 CURLOPT_LOCALPORTRANGE,
4665 Long_val(option));
4667 if (result != CURLE_OK)
4668 raiseError(conn, result);
4670 CAMLreturn0;
4671 #else
4672 #warning "libcurl does not implement CURLOPT_LOCALPORTRANGE"
4673 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4674 #endif
4677 static void handleConnectOnly(Connection *conn, value option)
4679 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4680 CAMLparam1(option);
4681 CURLcode result = CURLE_OK;
4683 result = curl_easy_setopt(conn->connection,
4684 CURLOPT_CONNECT_ONLY,
4685 Bool_val(option));
4687 if (result != CURLE_OK)
4688 raiseError(conn, result);
4690 CAMLreturn0;
4691 #else
4692 #warning "libcurl does not implement CURLOPT_CONNECT_ONLY"
4693 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4694 #endif
4697 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4699 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4700 CAMLparam1(option);
4701 CURLcode result = CURLE_OK;
4703 result = curl_easy_setopt(conn->connection,
4704 CURLOPT_MAX_SEND_SPEED_LARGE,
4705 Int64_val(option));
4707 if (result != CURLE_OK)
4708 raiseError(conn, result);
4710 CAMLreturn0;
4711 #else
4712 #warning "libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE"
4713 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4714 #endif
4717 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4719 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4720 CAMLparam1(option);
4721 CURLcode result = CURLE_OK;
4723 result = curl_easy_setopt(conn->connection,
4724 CURLOPT_MAX_RECV_SPEED_LARGE,
4725 Int64_val(option));
4727 if (result != CURLE_OK)
4728 raiseError(conn, result);
4730 CAMLreturn0;
4731 #else
4732 #warning "libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE"
4733 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4734 #endif
4737 static void handleFTPAlternativeToUser(Connection *conn, value option)
4739 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4740 CAMLparam1(option);
4741 CURLcode result = CURLE_OK;
4743 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4745 if (conn->ftpAlternativeToUser != NULL)
4746 free(conn->ftpAlternativeToUser);
4748 conn->ftpAlternativeToUser = strdup(String_val(option));
4750 result = curl_easy_setopt(conn->connection,
4751 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4752 conn->ftpAlternativeToUser);
4754 if (result != CURLE_OK)
4755 raiseError(conn, result);
4757 CAMLreturn0;
4758 #else
4759 #warning "libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER"
4760 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4761 #endif
4764 static void handleSSLSessionIdCache(Connection *conn, value option)
4766 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4767 CAMLparam1(option);
4768 CURLcode result = CURLE_OK;
4770 result = curl_easy_setopt(conn->connection,
4771 CURLOPT_SSL_SESSIONID_CACHE,
4772 Bool_val(option));
4774 if (result != CURLE_OK)
4775 raiseError(conn, result);
4777 CAMLreturn0;
4778 #else
4779 #warning "libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE"
4780 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4781 #endif
4784 static void handleSSHAuthTypes(Connection *conn, value option)
4786 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4787 CAMLparam1(option);
4788 CAMLlocal1(listIter);
4789 CURLcode result = CURLE_OK;
4790 long authTypes = CURLSSH_AUTH_NONE;
4792 listIter = option;
4794 while (!Is_long(listIter))
4796 switch (Long_val(Field(listIter, 0)))
4798 case 0: /* CURLSSH_AUTH_ANY */
4799 authTypes |= CURLSSH_AUTH_ANY;
4800 break;
4802 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4803 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4804 break;
4806 case 2: /* CURLSSH_AUTH_PASSWORD */
4807 authTypes |= CURLSSH_AUTH_PASSWORD;
4808 break;
4810 case 3: /* CURLSSH_AUTH_HOST */
4811 authTypes |= CURLSSH_AUTH_HOST;
4812 break;
4814 case 4: /* CURLSSH_AUTH_KEYBOARD */
4815 authTypes |= CURLSSH_AUTH_KEYBOARD;
4816 break;
4818 default:
4819 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4820 break;
4823 listIter = Field(listIter, 1);
4826 result = curl_easy_setopt(conn->connection,
4827 CURLOPT_SSH_AUTH_TYPES,
4828 authTypes);
4830 if (result != CURLE_OK)
4831 raiseError(conn, result);
4833 CAMLreturn0;
4834 #else
4835 #warning "libcurl does not implement CURLOPT_SSH_AUTH_TYPES"
4836 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4837 #endif
4840 static void handleSSHPublicKeyFile(Connection *conn, value option)
4842 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4843 CAMLparam1(option);
4844 CURLcode result = CURLE_OK;
4846 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4848 if (conn->sshPublicKeyFile != NULL)
4849 free(conn->sshPublicKeyFile);
4851 conn->sshPublicKeyFile = strdup(String_val(option));
4853 result = curl_easy_setopt(conn->connection,
4854 CURLOPT_SSH_PUBLIC_KEYFILE,
4855 conn->sshPublicKeyFile);
4857 if (result != CURLE_OK)
4858 raiseError(conn, result);
4860 CAMLreturn0;
4861 #else
4862 #warning "libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE"
4863 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4864 #endif
4867 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4869 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4870 CAMLparam1(option);
4871 CURLcode result = CURLE_OK;
4873 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4875 if (conn->sshPrivateKeyFile != NULL)
4876 free(conn->sshPrivateKeyFile);
4878 conn->sshPrivateKeyFile = strdup(String_val(option));
4880 result = curl_easy_setopt(conn->connection,
4881 CURLOPT_SSH_PRIVATE_KEYFILE,
4882 conn->sshPrivateKeyFile);
4884 if (result != CURLE_OK)
4885 raiseError(conn, result);
4887 CAMLreturn0;
4888 #else
4889 #warning "libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE"
4890 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4891 #endif
4894 static void handleFTPSSLCCC(Connection *conn, value option)
4896 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4897 CAMLparam1(option);
4898 CURLcode result = CURLE_OK;
4900 switch (Long_val(option))
4902 case 0: /* CURLFTPSSL_CCC_NONE */
4903 result = curl_easy_setopt(conn->connection,
4904 CURLOPT_FTP_SSL_CCC,
4905 CURLFTPSSL_CCC_NONE);
4906 break;
4908 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4909 result = curl_easy_setopt(conn->connection,
4910 CURLOPT_FTP_SSL_CCC,
4911 CURLFTPSSL_CCC_PASSIVE);
4912 break;
4914 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4915 result = curl_easy_setopt(conn->connection,
4916 CURLOPT_FTP_SSL_CCC,
4917 CURLFTPSSL_CCC_ACTIVE);
4918 break;
4920 default:
4921 failwith("Invalid FTPSSL_CCC value");
4922 break;
4925 if (result != CURLE_OK)
4926 raiseError(conn, result);
4928 CAMLreturn0;
4929 #else
4930 #warning "libcurl does not implement CURLOPT_FTP_SSL_CCC"
4931 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4932 #endif
4935 static void handleTimeoutMS(Connection *conn, value option)
4937 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4938 CAMLparam1(option);
4939 CURLcode result = CURLE_OK;
4941 result = curl_easy_setopt(conn->connection,
4942 CURLOPT_TIMEOUT_MS,
4943 Long_val(option));
4945 if (result != CURLE_OK)
4946 raiseError(conn, result);
4948 CAMLreturn0;
4949 #else
4950 #warning "libcurl does not implement CURLOPT_TIMEOUT_MS"
4951 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4952 #endif
4955 static void handleConnectTimeoutMS(Connection *conn, value option)
4957 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4958 CAMLparam1(option);
4959 CURLcode result = CURLE_OK;
4961 result = curl_easy_setopt(conn->connection,
4962 CURLOPT_CONNECTTIMEOUT_MS,
4963 Long_val(option));
4965 if (result != CURLE_OK)
4966 raiseError(conn, result);
4968 CAMLreturn0;
4969 #else
4970 #warning "libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS"
4971 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
4972 #endif
4975 static void handleHTTPTransferDecoding(Connection *conn, value option)
4977 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4978 CAMLparam1(option);
4979 CURLcode result = CURLE_OK;
4981 result = curl_easy_setopt(conn->connection,
4982 CURLOPT_HTTP_TRANSFER_DECODING,
4983 Bool_val(option));
4985 if (result != CURLE_OK)
4986 raiseError(conn, result);
4988 CAMLreturn0;
4989 #else
4990 #warning "libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING"
4991 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
4992 #endif
4995 static void handleHTTPContentDecoding(Connection *conn, value option)
4997 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4998 CAMLparam1(option);
4999 CURLcode result = CURLE_OK;
5001 result = curl_easy_setopt(conn->connection,
5002 CURLOPT_HTTP_CONTENT_DECODING,
5003 Bool_val(option));
5005 if (result != CURLE_OK)
5006 raiseError(conn, result);
5008 CAMLreturn0;
5009 #else
5010 #warning "libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING"
5011 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5012 #endif
5015 static void handleNewFilePerms(Connection *conn, value option)
5017 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5018 CAMLparam1(option);
5019 CURLcode result = CURLE_OK;
5021 result = curl_easy_setopt(conn->connection,
5022 CURLOPT_NEW_FILE_PERMS,
5023 Long_val(option));
5025 if (result != CURLE_OK)
5026 raiseError(conn, result);
5028 CAMLreturn0;
5029 #else
5030 #warning "libcurl does not implement CURLOPT_NEW_FILE_PERMS"
5031 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5032 #endif
5035 static void handleNewDirectoryPerms(Connection *conn, value option)
5037 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5038 CAMLparam1(option);
5039 CURLcode result = CURLE_OK;
5041 result = curl_easy_setopt(conn->connection,
5042 CURLOPT_NEW_DIRECTORY_PERMS,
5043 Long_val(option));
5045 if (result != CURLE_OK)
5046 raiseError(conn, result);
5048 CAMLreturn0;
5049 #else
5050 #warning "libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS"
5051 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5052 #endif
5055 static void handlePost301(Connection *conn, value option)
5057 #if HAVE_DECL_CURLOPT_POST301
5058 CAMLparam1(option);
5059 CURLcode result = CURLE_OK;
5061 result = curl_easy_setopt(conn->connection,
5062 CURLOPT_POST301,
5063 Bool_val(option));
5065 if (result != CURLE_OK)
5066 raiseError(conn, result);
5068 CAMLreturn0;
5069 #else
5070 #warning "libcurl does not implement CURLOPT_POST301"
5071 failwith("libcurl does not implement CURLOPT_POST301");
5072 #endif
5075 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5077 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5078 CAMLparam1(option);
5079 CURLcode result = CURLE_OK;
5081 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5083 if (conn->sshHostPublicKeyMD5 != NULL)
5084 free(conn->sshHostPublicKeyMD5);
5086 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5088 result = curl_easy_setopt(conn->connection,
5089 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5090 conn->sshHostPublicKeyMD5);
5092 if (result != CURLE_OK)
5093 raiseError(conn, result);
5095 CAMLreturn0;
5096 #else
5097 #warning "libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"
5098 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5099 #endif
5102 static void handleCopyPostFields(Connection *conn, value option)
5104 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5105 CAMLparam1(option);
5106 CURLcode result = CURLE_OK;
5108 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5110 if (conn->copyPostFields != NULL)
5111 free(conn->copyPostFields);
5113 conn->copyPostFields = strdup(String_val(option));
5115 result = curl_easy_setopt(conn->connection,
5116 CURLOPT_COPYPOSTFIELDS,
5117 conn->copyPostFields);
5119 if (result != CURLE_OK)
5120 raiseError(conn, result);
5122 CAMLreturn0;
5123 #else
5124 #warning "libcurl does not implement CURLOPT_COPYPOSTFIELDS"
5125 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5126 #endif
5129 static void handleProxyTransferMode(Connection *conn, value option)
5131 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5132 CAMLparam1(option);
5133 CURLcode result = CURLE_OK;
5135 result = curl_easy_setopt(conn->connection,
5136 CURLOPT_PROXY_TRANSFER_MODE,
5137 Bool_val(option));
5139 if (result != CURLE_OK)
5140 raiseError(conn, result);
5142 CAMLreturn0;
5143 #else
5144 #warning "libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE"
5145 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5146 #endif
5149 static void handleSeekFunction(Connection *conn, value option)
5151 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5152 CAMLparam1(option);
5153 CURLcode result = CURLE_OK;
5155 if (Tag_val(option) == Closure_tag)
5156 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5157 else
5158 failwith("Not a proper closure");
5160 result = curl_easy_setopt(conn->connection,
5161 CURLOPT_SEEKFUNCTION,
5162 seekFunction);
5164 if (result != CURLE_OK)
5165 raiseError(conn, result);
5167 result = curl_easy_setopt(conn->connection,
5168 CURLOPT_SEEKDATA,
5169 conn);
5171 if (result != CURLE_OK)
5172 raiseError(conn, result);
5174 CAMLreturn0;
5175 #else
5176 #warning "libcurl does not implement CURLOPT_SEEKFUNCTION"
5177 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5178 #endif
5182 ** curl_easy_setopt helper function
5185 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5187 CAMLparam2(conn, option);
5188 CAMLlocal1(data);
5189 Connection *connection = Connection_val(conn);
5191 checkConnection(connection);
5193 if (Is_long(option))
5195 char error[128];
5197 sprintf(error, "Unimplemented Option: %s",
5198 findOption(unimplementedOptionMap,
5199 (CURLoption)(Long_val(option))));
5201 failwith(error);
5204 if (!Is_block(option))
5205 failwith("Not a block");
5207 if (Wosize_val(option) < 1)
5208 failwith("Insufficient data in block");
5210 data = Field(option, 0);
5212 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5213 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5214 data);
5215 else
5216 failwith("Invalid CURLOPT Option");
5218 CAMLreturn(Val_unit);
5222 ** curl_easy_perform helper function
5225 CAMLprim value helper_curl_easy_perform(value conn)
5227 CAMLparam1(conn);
5228 CURLcode result = CURLE_OK;
5229 Connection *connection = Connection_val(conn);
5231 checkConnection(connection);
5233 enter_blocking_section();
5234 result = curl_easy_perform(connection->connection);
5235 leave_blocking_section();
5237 if (result != CURLE_OK)
5238 raiseError(connection, result);
5240 CAMLreturn(Val_unit);
5244 ** curl_easy_cleanup helper function
5247 CAMLprim value helper_curl_easy_cleanup(value conn)
5249 CAMLparam1(conn);
5250 Connection *connection = Connection_val(conn);
5252 checkConnection(connection);
5254 removeConnection(connection);
5256 CAMLreturn(Val_unit);
5260 ** curl_easy_duphandle helper function
5263 CAMLprim value helper_curl_easy_duphandle(value conn)
5265 CAMLparam1(conn);
5266 CAMLlocal1(result);
5267 Connection *connection = Connection_val(conn);
5269 checkConnection(connection);
5271 result = caml_alloc(1, Abstract_tag);
5272 Field(result, 0) = (value)duplicateConnection(connection);
5274 CAMLreturn(result);
5278 ** curl_easy_getinfo helper function
5281 enum GetInfoResultType {
5282 StringValue, LongValue, DoubleValue, StringListValue
5285 value convertStringList(struct curl_slist *slist)
5287 CAMLparam0();
5288 CAMLlocal3(result, current, next);
5289 struct curl_slist *p = slist;
5291 result = Val_int(0);
5292 current = Val_int(0);
5293 next = Val_int(0);
5295 while (p != NULL)
5297 next = alloc_tuple(2);
5298 Store_field(next, 0, copy_string(p->data));
5299 Store_field(next, 1, Val_int(0));
5301 if (result == Val_int(0))
5302 result = next;
5304 if (current != Val_int(0))
5305 Store_field(current, 1, next);
5307 current = next;
5309 p = p->next;
5312 curl_slist_free_all(slist);
5314 CAMLreturn(result);
5317 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5319 CAMLparam2(conn, option);
5320 CAMLlocal1(result);
5321 CURLcode curlResult;
5322 Connection *connection = Connection_val(conn);
5323 enum GetInfoResultType resultType;
5324 char *strValue = NULL;
5325 double doubleValue;
5326 long longValue;
5327 struct curl_slist *stringListValue = NULL;
5329 checkConnection(connection);
5331 switch(Long_val(option))
5333 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5334 case 0: /* CURLINFO_EFFECTIVE_URL */
5335 resultType = StringValue;
5337 curlResult = curl_easy_getinfo(connection->connection,
5338 CURLINFO_EFFECTIVE_URL,
5339 &strValue);
5340 break;
5341 #else
5342 #warning "libcurl does not provide CURLINFO_EFFECTIVE_URL"
5343 #endif
5345 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5346 case 1: /* CURLINFO_HTTP_CODE */
5347 case 2: /* CURLINFO_RESPONSE_CODE */
5348 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5349 resultType = LongValue;
5351 curlResult = curl_easy_getinfo(connection->connection,
5352 CURLINFO_RESPONSE_CODE,
5353 &longValue);
5354 #else
5355 resultType = LongValue;
5357 curlResult = curl_easy_getinfo(connection->connection,
5358 CURLINFO_HTTP_CODE,
5359 &longValue);
5360 #endif
5361 break;
5362 #endif
5364 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5365 case 3: /* CURLINFO_TOTAL_TIME */
5366 resultType = DoubleValue;
5368 curlResult = curl_easy_getinfo(connection->connection,
5369 CURLINFO_TOTAL_TIME,
5370 &doubleValue);
5371 break;
5372 #endif
5374 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5375 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5376 resultType = DoubleValue;
5378 curlResult = curl_easy_getinfo(connection->connection,
5379 CURLINFO_NAMELOOKUP_TIME,
5380 &doubleValue);
5381 break;
5382 #endif
5384 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5385 case 5: /* CURLINFO_CONNECT_TIME */
5386 resultType = DoubleValue;
5388 curlResult = curl_easy_getinfo(connection->connection,
5389 CURLINFO_CONNECT_TIME,
5390 &doubleValue);
5391 break;
5392 #endif
5394 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5395 case 6: /* CURLINFO_PRETRANSFER_TIME */
5396 resultType = DoubleValue;
5398 curlResult = curl_easy_getinfo(connection->connection,
5399 CURLINFO_PRETRANSFER_TIME,
5400 &doubleValue);
5401 break;
5402 #endif
5404 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5405 case 7: /* CURLINFO_SIZE_UPLOAD */
5406 resultType = DoubleValue;
5408 curlResult = curl_easy_getinfo(connection->connection,
5409 CURLINFO_SIZE_UPLOAD,
5410 &doubleValue);
5411 break;
5412 #endif
5414 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5415 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5416 resultType = DoubleValue;
5418 curlResult = curl_easy_getinfo(connection->connection,
5419 CURLINFO_SIZE_DOWNLOAD,
5420 &doubleValue);
5421 break;
5422 #endif
5424 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5425 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5426 resultType = DoubleValue;
5428 curlResult = curl_easy_getinfo(connection->connection,
5429 CURLINFO_SPEED_DOWNLOAD,
5430 &doubleValue);
5431 break;
5432 #endif
5434 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5435 case 10: /* CURLINFO_SPEED_UPLOAD */
5436 resultType = DoubleValue;
5438 curlResult = curl_easy_getinfo(connection->connection,
5439 CURLINFO_SPEED_UPLOAD,
5440 &doubleValue);
5441 break;
5443 #endif
5445 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5446 case 11: /* CURLINFO_HEADER_SIZE */
5447 resultType = LongValue;
5449 curlResult = curl_easy_getinfo(connection->connection,
5450 CURLINFO_HEADER_SIZE,
5451 &longValue);
5452 break;
5453 #endif
5455 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5456 case 12: /* CURLINFO_REQUEST_SIZE */
5457 resultType = LongValue;
5459 curlResult = curl_easy_getinfo(connection->connection,
5460 CURLINFO_REQUEST_SIZE,
5461 &longValue);
5462 break;
5463 #endif
5465 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5466 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5467 resultType = LongValue;
5469 curlResult = curl_easy_getinfo(connection->connection,
5470 CURLINFO_SSL_VERIFYRESULT,
5471 &longValue);
5472 break;
5473 #endif
5475 #if HAVE_DECL_CURLINFO_FILETIME
5476 case 14: /* CURLINFO_FILETIME */
5477 resultType = DoubleValue;
5479 curlResult = curl_easy_getinfo(connection->connection,
5480 CURLINFO_FILETIME,
5481 &doubleValue);
5482 break;
5483 #endif
5485 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5486 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5487 resultType = DoubleValue;
5489 curlResult = curl_easy_getinfo(connection->connection,
5490 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5491 &doubleValue);
5492 break;
5493 #endif
5495 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5496 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5497 resultType = DoubleValue;
5499 curlResult = curl_easy_getinfo(connection->connection,
5500 CURLINFO_CONTENT_LENGTH_UPLOAD,
5501 &doubleValue);
5502 break;
5503 #endif
5505 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5506 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5507 resultType = DoubleValue;
5509 curlResult = curl_easy_getinfo(connection->connection,
5510 CURLINFO_STARTTRANSFER_TIME,
5511 &doubleValue);
5512 break;
5513 #endif
5515 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5516 case 18: /* CURLINFO_CONTENT_TYPE */
5517 resultType = StringValue;
5519 curlResult = curl_easy_getinfo(connection->connection,
5520 CURLINFO_CONTENT_TYPE,
5521 &strValue);
5522 break;
5523 #endif
5525 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5526 case 19: /* CURLINFO_REDIRECT_TIME */
5527 resultType = DoubleValue;
5529 curlResult = curl_easy_getinfo(connection->connection,
5530 CURLINFO_REDIRECT_TIME,
5531 &doubleValue);
5532 break;
5533 #endif
5535 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5536 case 20: /* CURLINFO_REDIRECT_COUNT */
5537 resultType = LongValue;
5539 curlResult = curl_easy_getinfo(connection->connection,
5540 CURLINFO_REDIRECT_COUNT,
5541 &longValue);
5542 break;
5543 #endif
5545 #if HAVE_DECL_CURLINFO_PRIVATE
5546 case 21: /* CURLINFO_PRIVATE */
5547 resultType = StringValue;
5549 curlResult = curl_easy_getinfo(connection->connection,
5550 CURLINFO_PRIVATE,
5551 &strValue);
5552 break;
5553 #endif
5555 #if HAVE_DECL_CURLINFO_HTTP_CONNECT_CODE
5556 case 22: /* CURLINFO_HTTP_CONNECT_CODE */
5557 resultType = LongValue;
5559 curlResult = curl_easy_getinfo(connection->connection,
5560 CURLINFO_HTTP_CONNECT_CODE,
5561 &longValue);
5562 break;
5563 #endif
5565 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5566 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5567 resultType = LongValue;
5569 curlResult = curl_easy_getinfo(connection->connection,
5570 CURLINFO_HTTPAUTH_AVAIL,
5571 &longValue);
5572 break;
5573 #endif
5575 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5576 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5577 resultType = LongValue;
5579 curlResult = curl_easy_getinfo(connection->connection,
5580 CURLINFO_PROXYAUTH_AVAIL,
5581 &longValue);
5582 break;
5583 #endif
5585 #if HAVE_DECL_CURLINFO_OS_ERRNO
5586 case 25: /* CURLINFO_OS_ERRNO */
5587 resultType = LongValue;
5589 curlResult = curl_easy_getinfo(connection->connection,
5590 CURLINFO_OS_ERRNO,
5591 &longValue);
5592 break;
5593 #endif
5595 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5596 case 26: /* CURLINFO_NUM_CONNECTS */
5597 resultType = LongValue;
5599 curlResult = curl_easy_getinfo(connection->connection,
5600 CURLINFO_NUM_CONNECTS,
5601 &longValue);
5602 break;
5603 #endif
5605 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5606 case 27: /* CURLINFO_SSL_ENGINES */
5607 resultType = StringListValue;
5609 curlResult = curl_easy_getinfo(connection->connection,
5610 CURLINFO_SSL_ENGINES,
5611 &stringListValue);
5612 break;
5613 #endif
5615 #if HAVE_DECL_CURLINFO_COOKIELIST
5616 case 28: /* CURLINFO_COOKIELIST */
5617 resultType = StringListValue;
5619 curlResult = curl_easy_getinfo(connection->connection,
5620 CURLINFO_COOKIELIST,
5621 &stringListValue);
5622 break;
5623 #endif
5625 #if HAVE_DECL_CURLINFO_LASTSOCKET
5626 case 29: /* CURLINFO_LASTSOCKET */
5627 resultType = LongValue;
5629 curlResult = curl_easy_getinfo(connection->connection,
5630 CURLINFO_LASTSOCKET,
5631 &longValue);
5632 break;
5633 #endif
5635 default:
5636 failwith("Invalid CURLINFO Option");
5637 break;
5640 if (curlResult != CURLE_OK)
5641 raiseError(connection, curlResult);
5643 switch (resultType)
5645 case StringValue:
5646 result = alloc(1, StringValue);
5648 libcurl can return NULL, e.g. for CONTENT_TYPE or PRIVATE
5649 alternative: add StringOptionValue and break API..
5651 Store_field(result, 0, copy_string(strValue?strValue:""));
5652 break;
5654 case LongValue:
5655 result = alloc(1, LongValue);
5656 Store_field(result, 0, Val_long(longValue));
5657 break;
5659 case DoubleValue:
5660 result = alloc(1, DoubleValue);
5661 Store_field(result, 0, copy_double(doubleValue));
5662 break;
5664 case StringListValue:
5665 result = alloc(1, StringListValue);
5666 Store_field(result, 0, convertStringList(stringListValue));
5667 break;
5670 CAMLreturn(result);
5674 ** curl_escape helper function
5677 CAMLprim value helper_curl_escape(value str)
5679 CAMLparam1(str);
5680 CAMLlocal1(result);
5681 char *curlResult;
5683 curlResult = curl_escape(String_val(str), string_length(str));
5684 result = copy_string(curlResult);
5685 free(curlResult);
5687 CAMLreturn(result);
5691 ** curl_unescape helper function
5694 CAMLprim value helper_curl_unescape(value str)
5696 CAMLparam1(str);
5697 CAMLlocal1(result);
5698 char *curlResult;
5700 curlResult = curl_unescape(String_val(str), string_length(str));
5701 result = copy_string(curlResult);
5702 free(curlResult);
5704 CAMLreturn(result);
5708 ** curl_getdate helper function
5711 CAMLprim value helper_curl_getdate(value str, value now)
5713 CAMLparam2(str, now);
5714 CAMLlocal1(result);
5715 time_t curlResult;
5716 time_t curlNow;
5718 curlNow = (time_t)Double_val(now);
5719 curlResult = curl_getdate(String_val(str), &curlNow);
5720 result = copy_double((double)curlResult);
5722 CAMLreturn(result);
5726 ** curl_version helper function
5729 CAMLprim value helper_curl_version(void)
5731 CAMLparam0();
5732 CAMLlocal1(result);
5733 char *str;
5735 str = curl_version();
5736 result = copy_string(str);
5738 CAMLreturn(result);
5742 * Curl multi stack support
5744 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
5745 * Other exported functions are prefixed with caml_curlm_, some of them
5746 * can/should be decomposed into smaller parts.
5749 struct ml_multi_handle
5751 CURLM* handle;
5752 value values; /* callbacks */
5755 enum
5757 curlmopt_socket_function,
5759 /* last, not used */
5760 multi_values_total,
5763 typedef struct ml_multi_handle ml_multi_handle;
5765 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
5766 #define CURLM_val(v) (Multi_val(v)->handle)
5768 static struct custom_operations curl_multi_ops = {
5769 "ygrek.curl_multi",
5770 custom_finalize_default,
5771 custom_compare_default,
5772 custom_hash_default,
5773 custom_serialize_default,
5774 custom_deserialize_default
5777 CAMLprim value caml_curl_multi_init(value unit)
5779 CAMLparam1(unit);
5780 CAMLlocal1(v);
5781 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
5782 CURLM* h = curl_multi_init();
5784 if (!h)
5786 caml_stat_free(multi);
5787 failwith("caml_curl_multi_init");
5790 multi->handle = h;
5791 multi->values = caml_alloc(multi_values_total, 0);
5792 caml_register_generational_global_root(&multi->values);
5794 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
5795 Multi_val(v) = multi;
5797 CAMLreturn(v);
5800 CAMLprim value caml_curl_multi_cleanup(value handle)
5802 CAMLparam1(handle);
5803 ml_multi_handle* h = Multi_val(handle);
5805 if (NULL == h)
5806 CAMLreturn(Val_unit);
5808 caml_remove_generational_global_root(&h->values);
5810 if (CURLM_OK != curl_multi_cleanup(h->handle))
5811 failwith("caml_curl_multi_cleanup");
5813 Multi_val(handle) = (ml_multi_handle*)NULL;
5815 CAMLreturn(Val_unit);
5818 static CURL* curlm_remove_finished(CURLM* multi_handle)
5820 int msgs_in_queue = 0;
5822 while (1)
5824 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
5825 if (NULL == msg) return NULL;
5826 if (CURLMSG_DONE == msg->msg)
5828 CURL* easy_handle = msg->easy_handle;
5829 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
5831 //failwith("curlm_remove_finished");
5833 return easy_handle;
5838 CAMLprim value caml_curlm_remove_finished(value v_multi)
5840 CAMLparam1(v_multi);
5841 CAMLlocal1(v_easy);
5842 CURL* handle;
5843 CURLM* multi_handle;
5845 multi_handle = CURLM_val(v_multi);
5847 caml_enter_blocking_section();
5848 handle = curlm_remove_finished(multi_handle);
5849 caml_leave_blocking_section();
5851 if (NULL == handle)
5853 CAMLreturn(Val_none);
5855 else
5857 /* not good: same handle, but different block */
5858 v_easy = caml_alloc(1, Abstract_tag);
5859 Field(v_easy, 0) = (value)findConnection(handle);
5860 CAMLreturn(Val_some(v_easy));
5864 static int curlm_wait_data(CURLM* multi_handle)
5866 struct timeval timeout;
5867 CURLMcode ret;
5869 fd_set fdread;
5870 fd_set fdwrite;
5871 fd_set fdexcep;
5872 int maxfd;
5874 FD_ZERO(&fdread);
5875 FD_ZERO(&fdwrite);
5876 FD_ZERO(&fdexcep);
5878 /* set a suitable timeout */
5879 timeout.tv_sec = 1;
5880 timeout.tv_usec = 0;
5882 /* get file descriptors from the transfers */
5883 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
5885 if (ret == CURLM_OK && maxfd >= 0)
5887 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
5888 if (-1 != rc) return 0;
5889 //printf("select error\n");
5891 else
5893 //printf("curl_multi_fdset error\n");
5895 return 1;
5898 CAMLprim value caml_curlm_wait_data(value v_multi)
5900 CAMLparam1(v_multi);
5901 int ret;
5902 CURLM* h;
5904 h = CURLM_val(v_multi);
5906 caml_enter_blocking_section();
5907 ret = curlm_wait_data(h);
5908 caml_leave_blocking_section();
5910 CAMLreturn(Val_bool(0 == ret));
5913 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
5915 CAMLparam2(v_multi,v_easy);
5917 if (CURLM_OK != curl_multi_add_handle(CURLM_val(v_multi), Connection_val(v_easy)->connection))
5918 failwith("caml_curl_multi_add_handle");
5920 CAMLreturn(Val_unit);
5923 CAMLprim value caml_curl_multi_perform_all(value v_multi)
5925 CAMLparam1(v_multi);
5926 CURLM* h;
5927 int still_running = 0;
5929 h = CURLM_val(v_multi);
5931 caml_enter_blocking_section();
5932 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
5933 caml_leave_blocking_section();
5935 CAMLreturn(Val_int(still_running));