less allocations on callbacks
[ocurl.git] / curl-helper.c
blob0d73cfa9679dae3d1b4b9f2d0b32f6ff49385a88
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 void leave_blocking_section(void);
27 void enter_blocking_section(void);
29 #define Val_none Val_int(0)
31 static inline value
32 Val_some( value v )
34 CAMLparam1( v );
35 CAMLlocal1( some );
36 some = caml_alloc(1, 0);
37 Store_field( some, 0, v );
38 CAMLreturn( some );
41 typedef struct Connection Connection;
42 typedef struct ConnectionList ConnectionList;
44 #define Connection_val(v) ((Connection *)Field(v, 0))
46 enum OcamlValues
48 OcamlWriteCallback,
49 OcamlReadCallback,
50 OcamlErrorBuffer,
51 OcamlPostFields,
52 OcamlHTTPHeader,
53 OcamlHTTPPost,
54 OcamlQuote,
55 OcamlPostQuote,
56 OcamlHeaderCallback,
57 OcamlProgressCallback,
58 OcamlDebugCallback,
59 OcamlHTTP200Aliases,
60 OcamlIOCTLCallback,
61 OcamlSeekFunctionCallback,
63 OcamlURL,
64 OcamlProxy,
65 OcamlUserPWD,
66 OcamlProxyUserPWD,
67 OcamlRange,
68 OcamlReferer,
69 OcamlUserAgent,
70 OcamlFTPPort,
71 OcamlCookie,
72 OcamlHTTPPostStrings,
73 OcamlSSLCert,
74 OcamlSSLCertType,
75 OcamlSSLCertPasswd,
76 OcamlSSLKey,
77 OcamlSSLKeyType,
78 OcamlSSLKeyPasswd,
79 OcamlSSLEngine,
80 OcamlCookieFile,
81 OcamlCustomRequest,
82 OcamlInterface,
83 OcamlCAInfo,
84 OcamlCAPath,
85 OcamlRandomFile,
86 OcamlEGDSocket,
87 OcamlCookieJar,
88 OcamlSSLCipherList,
89 OcamlPrivate,
90 OcamlNETRCFile,
91 OcamlFTPAccount,
92 OcamlCookieList,
93 OcamlFTPAlternativeToUser,
94 OcamlSSHPublicKeyFile,
95 OcamlSSHPrivateKeyFile,
96 OcamlSSHHostPublicKeyMD5,
97 OcamlCopyPostFields,
99 /* Not used, last for size */
100 OcamlValuesSize
103 struct Connection
105 CURL *connection;
106 Connection *next;
107 Connection *prev;
109 value ocamlValues;
111 char *url;
112 char *proxy;
113 char *userPwd;
114 char *proxyUserPwd;
115 char *range;
116 char *errorBuffer;
117 char *postFields;
118 int postFieldSize;
119 char *referer;
120 char *userAgent;
121 char *ftpPort;
122 char *cookie;
123 struct curl_slist *httpHeader;
124 struct curl_httppost *httpPostFirst;
125 struct curl_httppost *httpPostLast;
126 struct curl_slist *httpPostStrings;
127 char *sslCert;
128 char *sslCertType;
129 char *sslCertPasswd;
130 char *sslKey;
131 char *sslKeyType;
132 char *sslKeyPasswd;
133 char *sslEngine;
134 struct curl_slist *quote;
135 struct curl_slist *postQuote;
136 char *cookieFile;
137 char *customRequest;
138 char *interface;
139 char *caInfo;
140 char *caPath;
141 char *randomFile;
142 char *egdSocket;
143 char *cookieJar;
144 char *sslCipherList;
145 char *private;
146 struct curl_slist *http200Aliases;
147 char *netrcFile;
148 char *ftpaccount;
149 char *cookielist;
150 char *ftpAlternativeToUser;
151 char *sshPublicKeyFile;
152 char *sshPrivateKeyFile;
153 char *sshHostPublicKeyMD5;
154 char *copyPostFields;
157 struct ConnectionList
159 Connection *head;
160 Connection *tail;
163 static ConnectionList connectionList = {NULL, NULL};
165 typedef struct CURLErrorMapping CURLErrorMapping;
167 struct CURLErrorMapping
169 char *name;
170 CURLcode error;
173 CURLErrorMapping errorMap[] =
175 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
176 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
177 #else
178 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
179 #endif
180 #if HAVE_DECL_CURLE_FAILED_INIT
181 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
182 #else
183 {"CURLE_FAILED_INIT", -1},
184 #endif
185 #if HAVE_DECL_CURLE_URL_MALFORMAT
186 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
187 #else
188 {"CURLE_URL_MALFORMAT", -1},
189 #endif
190 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
191 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
192 #else
193 {"CURLE_URL_MALFORMAT_USER", -1},
194 #endif
195 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
196 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
197 #else
198 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
199 #endif
200 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
201 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
202 #else
203 {"CURLE_COULDNT_RESOLVE_HOST", -1},
204 #endif
205 #if HAVE_DECL_CURLE_COULDNT_CONNECT
206 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
207 #else
208 {"CURLE_COULDNT_CONNECT", -1},
209 #endif
210 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
211 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
212 #else
213 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
214 #endif
215 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
216 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
217 #else
218 {"CURLE_FTP_ACCESS_DENIED", -1},
219 #endif
220 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
221 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
222 #else
223 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
224 #endif
225 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
226 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
227 #else
228 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
229 #endif
230 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
231 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
232 #else
233 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
234 #endif
235 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
236 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
237 #else
238 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
239 #endif
240 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
241 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
242 #else
243 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
244 #endif
245 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
246 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
247 #else
248 {"CURLE_FTP_CANT_GET_HOST", -1},
249 #endif
250 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
251 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
252 #else
253 {"CURLE_FTP_CANT_RECONNECT", -1},
254 #endif
255 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
256 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
257 #else
258 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
259 #endif
260 #if HAVE_DECL_CURLE_PARTIAL_FILE
261 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
262 #else
263 {"CURLE_PARTIAL_FILE", -1},
264 #endif
265 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
266 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
267 #else
268 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
269 #endif
270 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
271 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
272 #else
273 {"CURLE_FTP_WRITE_ERROR", -1},
274 #endif
275 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
276 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
277 #else
278 {"CURLE_FTP_QUOTE_ERROR", -1},
279 #endif
280 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
281 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
282 #else
283 {"CURLE_HTTP_NOT_FOUND", -1},
284 #endif
285 #if HAVE_DECL_CURLE_WRITE_ERROR
286 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
287 #else
288 {"CURLE_WRITE_ERROR", -1},
289 #endif
290 #if HAVE_DECL_CURLE_MALFORMAT_USER
291 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
292 #else
293 {"CURLE_MALFORMAT_USER", -1},
294 #endif
295 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
296 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
297 #else
298 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
299 #endif
300 #if HAVE_DECL_CURLE_READ_ERROR
301 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
302 #else
303 {"CURLE_READ_ERROR", -1},
304 #endif
305 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
306 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
307 #else
308 {"CURLE_OUT_OF_MEMORY", -1},
309 #endif
310 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
311 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
312 #else
313 {"CURLE_OPERATION_TIMEOUTED", -1},
314 #endif
315 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
316 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
317 #else
318 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
319 #endif
320 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
321 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
322 #else
323 {"CURLE_FTP_PORT_FAILED", -1},
324 #endif
325 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
326 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
327 #else
328 {"CURLE_FTP_COULDNT_USE_REST", -1},
329 #endif
330 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
331 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
332 #else
333 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
334 #endif
335 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
336 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
337 #else
338 {"CURLE_HTTP_RANGE_ERROR", -1},
339 #endif
340 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
341 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
342 #else
343 {"CURLE_HTTP_POST_ERROR", -1},
344 #endif
345 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
346 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
347 #else
348 {"CURLE_SSL_CONNECT_ERROR", -1},
349 #endif
350 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
351 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
352 #else
353 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
354 #endif
355 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
356 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
357 #else
358 {"CURLE_FILE_COULDNT_READ_FILE", -1},
359 #endif
360 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
361 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
362 #else
363 {"CURLE_LDAP_CANNOT_BIND", -1},
364 #endif
365 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
366 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
367 #else
368 {"CURLE_LDAP_SEARCH_FAILED", -1},
369 #endif
370 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
371 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
372 #else
373 {"CURLE_LIBRARY_NOT_FOUND", -1},
374 #endif
375 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
376 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
377 #else
378 {"CURLE_FUNCTION_NOT_FOUND", -1},
379 #endif
380 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
381 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
382 #else
383 {"CURLE_ABORTED_BY_CALLBACK", -1},
384 #endif
385 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
386 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
387 #else
388 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
389 #endif
390 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
391 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
392 #else
393 {"CURLE_BAD_CALLING_ORDER", -1},
394 #endif
395 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
396 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
397 #else
398 {"CURLE_HTTP_PORT_FAILED", -1},
399 #endif
400 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
401 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
402 #else
403 {"CURLE_BAD_PASSWORD_ENTERED", -1},
404 #endif
405 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
406 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
407 #else
408 {"CURLE_TOO_MANY_REDIRECTS", -1},
409 #endif
410 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
411 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
412 #else
413 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
414 #endif
415 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
416 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
417 #else
418 {"CURLE_TELNET_OPTION_SYNTAX", -1},
419 #endif
420 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
421 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
422 #else
423 {"CURLE_SSL_PEER_CERTIFICATE", -1},
424 #endif
425 #if HAVE_DECL_CURLE_GOT_NOTHING
426 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
427 #else
428 {"CURLE_GOT_NOTHING", -1},
429 #endif
430 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
431 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
432 #else
433 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
434 #endif
435 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
436 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
437 #else
438 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
439 #endif
440 #if HAVE_DECL_CURLE_SEND_ERROR
441 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
442 #else
443 {"CURLE_SEND_ERROR", -1},
444 #endif
445 #if HAVE_DECL_CURLE_RECV_ERROR
446 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
447 #else
448 {"CURLE_RECV_ERROR", -1},
449 #endif
450 #if HAVE_DECL_CURLE_SHARE_IN_USE
451 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
452 #else
453 {"CURLE_SHARE_IN_USE", -1},
454 #endif
455 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
456 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
457 #else
458 {"CURLE_SSL_CERTPROBLEN", -1},
459 #endif
460 #if HAVE_DECL_CURLE_SSL_CIPHER
461 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
462 #else
463 {"CURLE_SSL_CIPHER", -1},
464 #endif
465 #if HAVE_DECL_CURLE_SSL_CACERT
466 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
467 #else
468 {"CURLE_SSL_CACERT", -1},
469 #endif
470 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
471 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
472 #else
473 {"CURLE_BAD_CONTENT_ENCODING", -1},
474 #endif
475 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
476 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
477 #else
478 {"CURLE_LDAP_INVALID_URL", -1},
479 #endif
480 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
481 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
482 #else
483 {"CURLE_FILESIZE_EXCEEDED", -1},
484 #endif
485 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
486 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
487 #else
488 {"CURLE_FTP_SSL_FAILED", -1},
489 #endif
490 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
491 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
492 #else
493 {"CURLE_SEND_FAIL_REWIND", -1},
494 #endif
495 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
496 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
497 #else
498 {"CURLE_SSL_ENGINE_INITFAILED", -1},
499 #endif
500 #if HAVE_DECL_CURLE_LOGIN_DENIED
501 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
502 #else
503 {"CURLE_LOGIN_DENIED", -1},
504 #endif
505 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
506 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
507 #else
508 {"CURLE_TFTP_NOTFOUND", -1},
509 #endif
510 #if HAVE_DECL_CURLE_TFTP_PERM
511 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
512 #else
513 {"CURLE_TFTP_PERM", -1},
514 #endif
515 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
516 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
517 #else
518 {"CURLE_REMOTE_DISK_FULL", -1},
519 #endif
520 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
521 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
522 #else
523 {"CURLE_TFTP_ILLEGAL", -1},
524 #endif
525 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
526 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
527 #else
528 {"CURLE_TFTP_UNKNOWNID", -1},
529 #endif
530 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
531 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
532 #else
533 {"CURLE_REMOTE_FILE_EXISTS", -1},
534 #endif
535 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
536 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
537 #else
538 {"CURLE_TFTP_NOSUCHUSER", -1},
539 #endif
540 #if HAVE_DECL_CURLE_CONV_FAILED
541 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
542 #else
543 {"CURLE_CONV_FAILED", -1},
544 #endif
545 #if HAVE_DECL_CURLE_CONV_REQUIRED
546 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
547 #else
548 {"CURLE_CONV_REQUIRED", -1},
549 #endif
550 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
551 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
552 #else
553 {"CURLE_SSL_CACERT_BADFILE", -1},
554 #endif
555 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
556 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
557 #else
558 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
559 #endif
560 #if HAVE_DECL_CURLE_SSH
561 {"CURLE_SSH", CURLE_SSH},
562 #else
563 {"CURLE_SSH", -1},
564 #endif
565 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
566 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
567 #else
568 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
569 #endif
570 #if HAVE_DECL_CURLE_AGAIN
571 {"CURLE_AGAIN", CURLE_AGAIN},
572 #else
573 {"CURLE_AGAIN", -1},
574 #endif
575 {"CURLE_OK", CURLE_OK},
576 {NULL, 0}
579 typedef struct CURLOptionMapping CURLOptionMapping;
581 struct CURLOptionMapping
583 void (*optionHandler)(Connection *, value);
584 char *name;
585 CURLoption option;
588 CURLOptionMapping unimplementedOptionMap[] =
590 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
591 {NULL, NULL, 0}
594 static void handleWriteFunction(Connection *, value);
595 static void handleReadFunction(Connection *, value);
596 static void handleInFileSize(Connection *, value);
597 static void handleURL(Connection *, value);
598 static void handleProxy(Connection *, value);
599 static void handleProxyPort(Connection *, value);
600 static void handleHTTPProxyTunnel(Connection *, value);
601 static void handleVerbose(Connection *, value);
602 static void handleHeader(Connection *, value);
603 static void handleNoProgress(Connection *, value);
604 static void handleNoSignal(Connection *, value);
605 static void handleNoBody(Connection *, value);
606 static void handleFailOnError(Connection *, value);
607 static void handleUpload(Connection *, value);
608 static void handlePost(Connection *, value);
609 static void handleFTPListOnly(Connection *, value);
610 static void handleFTPAppend(Connection *, value);
611 static void handleNETRC(Connection *, value);
612 static void handleEncoding(Connection *, value);
613 static void handleFollowLocation(Connection *, value);
614 static void handleTransferText(Connection *, value);
615 static void handlePut(Connection *, value);
616 static void handleUserPwd(Connection *, value);
617 static void handleProxyUserPwd(Connection *, value);
618 static void handleRange(Connection *, value);
619 static void handleErrorBuffer(Connection *, value);
620 static void handleTimeout(Connection *, value);
621 static void handlePostFields(Connection *, value);
622 static void handlePostFieldSize(Connection *, value);
623 static void handleReferer(Connection *, value);
624 static void handleUserAgent(Connection *, value);
625 static void handleFTPPort(Connection *, value);
626 static void handleLowSpeedLimit(Connection *, value);
627 static void handleLowSpeedTime(Connection *, value);
628 static void handleResumeFrom(Connection *, value);
629 static void handleCookie(Connection *, value);
630 static void handleHTTPHeader(Connection *, value);
631 static void handleHTTPPost(Connection *, value);
632 static void handleSSLCert(Connection *, value);
633 static void handleSSLCertType(Connection *, value);
634 static void handleSSLCertPasswd(Connection *, value);
635 static void handleSSLKey(Connection *, value);
636 static void handleSSLKeyType(Connection *, value);
637 static void handleSSLKeyPasswd(Connection *, value);
638 static void handleSSLEngine(Connection *, value);
639 static void handleSSLEngineDefault(Connection *, value);
640 static void handleCRLF(Connection *, value);
641 static void handleQuote(Connection *, value);
642 static void handlePostQuote(Connection *, value);
643 static void handleHeaderFunction(Connection *, value);
644 static void handleCookieFile(Connection *, value);
645 static void handleSSLVersion(Connection *, value);
646 static void handleTimeCondition(Connection *, value);
647 static void handleTimeValue(Connection *, value);
648 static void handleCustomRequest(Connection *, value);
649 static void handleInterface(Connection *, value);
650 static void handleKRB4Level(Connection *, value);
651 static void handleProgressFunction(Connection *, value);
652 static void handleSSLVerifyPeer(Connection *, value);
653 static void handleCAInfo(Connection *, value);
654 static void handleCAPath(Connection *, value);
655 static void handleFileTime(Connection *, value);
656 static void handleMaxRedirs(Connection *, value);
657 static void handleMaxConnects(Connection *, value);
658 static void handleClosePolicy(Connection *, value);
659 static void handleFreshConnect(Connection *, value);
660 static void handleForbidReuse(Connection *, value);
661 static void handleRandomFile(Connection *, value);
662 static void handleEGDSocket(Connection *, value);
663 static void handleConnectTimeout(Connection *, value);
664 static void handleHTTPGet(Connection *, value);
665 static void handleSSLVerifyHost(Connection *, value);
666 static void handleCookieJar(Connection *, value);
667 static void handleSSLCipherList(Connection *, value);
668 static void handleHTTPVersion(Connection *, value);
669 static void handleFTPUseEPSV(Connection *, value);
670 static void handleDNSCacheTimeout(Connection *, value);
671 static void handleDNSUseGlobalCache(Connection *, value);
672 static void handleDebugFunction(Connection *, value);
673 static void handlePrivate(Connection *, value);
674 static void handleHTTP200Aliases(Connection *, value);
675 static void handleUnrestrictedAuth(Connection *, value);
676 static void handleFTPUseEPRT(Connection *, value);
677 static void handleHTTPAuth(Connection *, value);
678 static void handleFTPCreateMissingDirs(Connection *, value);
679 static void handleProxyAuth(Connection *, value);
680 static void handleFTPResponseTimeout(Connection *, value);
681 static void handleIPResolve(Connection *, value);
682 static void handleMaxFileSize(Connection *, value);
683 static void handleInFileSizeLarge(Connection *, value);
684 static void handleResumeFromLarge(Connection *, value);
685 static void handleMaxFileSizeLarge(Connection *, value);
686 static void handleNETRCFile(Connection *, value);
687 static void handleFTPSSL(Connection *, value);
688 static void handlePostFieldSizeLarge(Connection *, value);
689 static void handleTCPNoDelay(Connection *, value);
690 static void handleFTPSSLAuth(Connection *, value);
691 static void handleIOCTLFunction(Connection *, value);
692 static void handleFTPAccount(Connection *, value);
693 static void handleCookieList(Connection *, value);
694 static void handleIgnoreContentLength(Connection *, value);
695 static void handleFTPSkipPASVIP(Connection *, value);
696 static void handleFTPFileMethod(Connection *, value);
697 static void handleLocalPort(Connection *, value);
698 static void handleLocalPortRange(Connection *, value);
699 static void handleConnectOnly(Connection *, value);
700 static void handleMaxSendSpeedLarge(Connection *, value);
701 static void handleMaxRecvSpeedLarge(Connection *, value);
702 static void handleFTPAlternativeToUser(Connection *, value);
703 static void handleSSLSessionIdCache(Connection *, value);
704 static void handleSSHAuthTypes(Connection *, value);
705 static void handleSSHPublicKeyFile(Connection *, value);
706 static void handleSSHPrivateKeyFile(Connection *, value);
707 static void handleFTPSSLCCC(Connection *, value);
708 static void handleTimeoutMS(Connection *, value);
709 static void handleConnectTimeoutMS(Connection *, value);
710 static void handleHTTPTransferDecoding(Connection *, value);
711 static void handleHTTPContentDecoding(Connection *, value);
712 static void handleNewFilePerms(Connection *, value);
713 static void handleNewDirectoryPerms(Connection *, value);
714 static void handlePost301(Connection *, value);
715 static void handleSSHHostPublicKeyMD5(Connection *, value);
716 static void handleCopyPostFields(Connection *, value);
717 static void handleProxyTransferMode(Connection *, value);
718 static void handleSeekFunction(Connection *, value);
720 CURLOptionMapping implementedOptionMap[] =
722 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
723 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
724 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
725 {handleURL, "CURLOPT_URL", CURLOPT_URL},
726 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
727 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
728 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
729 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
730 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
731 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
732 #if HAVE_DECL_CURLOPT_NOSIGNAL
733 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
734 #else
735 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
736 #endif
737 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
738 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
739 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
740 {handlePost, "CURLOPT_POST", CURLOPT_POST},
741 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
742 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
743 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
744 #if HAVE_DECL_CURLOPT_ENCODING
745 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
746 #else
747 {handleEncoding, "CURLOPT_ENCODING", 0},
748 #endif
749 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
750 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
751 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
752 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
753 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
754 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
755 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
756 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
757 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
758 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
759 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
760 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
761 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
762 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
763 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
764 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
765 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
766 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
767 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
768 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
769 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
770 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
771 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
772 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
773 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
774 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
775 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
776 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
777 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
778 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
779 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
780 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
781 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
782 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
783 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
784 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
785 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
786 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
787 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
788 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
789 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
790 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
791 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
792 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
793 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
794 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
795 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
796 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
797 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
798 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
799 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
800 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
801 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
802 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
803 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
804 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
805 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
806 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
807 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
808 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
809 #if HAVE_DECL_CURLOPT_PRIVATE
810 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
811 #else
812 {handlePrivate, "CURLOPT_PRIVATE", 0},
813 #endif
814 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
815 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
816 #else
817 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
818 #endif
819 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
820 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
821 #else
822 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
823 #endif
824 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
825 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
826 #else
827 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
828 #endif
829 #if HAVE_DECL_CURLOPT_HTTPAUTH
830 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
831 #else
832 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
833 #endif
834 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
835 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
836 #else
837 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
838 #endif
839 #if HAVE_DECL_CURLOPT_PROXYAUTH
840 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
841 #else
842 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
843 #endif
844 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
845 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
846 #else
847 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
848 #endif
849 #if HAVE_DECL_CURLOPT_IPRESOLVE
850 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
851 #else
852 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
853 #endif
854 #if HAVE_DECL_CURLOPT_MAXFILESIZE
855 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
856 #else
857 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
858 #endif
859 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
860 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
861 #else
862 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
863 #endif
864 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
865 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
866 #else
867 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
868 #endif
869 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
870 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
871 #else
872 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
873 #endif
874 #if HAVE_DECL_CURLOPT_NETRC_FILE
875 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
876 #else
877 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
878 #endif
879 #if HAVE_DECL_CURLOPT_FTP_SSL
880 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
881 #else
882 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
883 #endif
884 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
885 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
886 #else
887 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
888 #endif
889 #if HAVE_DECL_CURLOPT_TCP_NODELAY
890 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
891 #else
892 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
893 #endif
894 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
895 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
896 #else
897 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
898 #endif
899 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
900 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
901 #else
902 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
903 #endif
904 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
905 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
906 #else
907 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
908 #endif
909 #if HAVE_DECL_CURLOPT_COOKIELIST
910 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
911 #else
912 {handleCookieList, "CURLOPT_COOKIELIST", 0},
913 #endif
914 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
915 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
916 #else
917 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
918 #endif
919 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
920 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
921 #else
922 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
923 #endif
924 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
925 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
926 #else
927 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
928 #endif
929 #if HAVE_DECL_CURLOPT_LOCALPORT
930 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
931 #else
932 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
933 #endif
934 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
935 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
936 #else
937 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
938 #endif
939 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
940 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
941 #else
942 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
943 #endif
944 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
945 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
946 #else
947 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
948 #endif
949 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
950 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
951 #else
952 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
953 #endif
954 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
955 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
956 #else
957 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
958 #endif
959 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
960 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
961 #else
962 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
963 #endif
964 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
965 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
966 #else
967 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
968 #endif
969 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
970 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
971 #else
972 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
973 #endif
974 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
975 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
976 #else
977 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
978 #endif
979 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
980 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
981 #else
982 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
983 #endif
984 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
985 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
986 #else
987 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
988 #endif
989 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
990 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
991 #else
992 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
993 #endif
994 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
995 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
996 #else
997 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
998 #endif
999 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1000 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1001 #else
1002 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1003 #endif
1004 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1005 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1006 #else
1007 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1008 #endif
1009 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1010 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1011 #else
1012 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1013 #endif
1014 #if HAVE_DECL_CURLOPT_POST301
1015 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1016 #else
1017 {handlePost301, "CURLOPT_POST301", 0},
1018 #endif
1019 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1020 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1021 #else
1022 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1023 #endif
1024 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1025 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1026 #else
1027 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1028 #endif
1029 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1030 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1031 #else
1032 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1033 #endif
1034 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1035 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1036 #else
1037 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1038 #endif
1041 static char *findOption(CURLOptionMapping optionMap[],
1042 CURLoption option)
1044 return optionMap[option].name;
1047 static void free_curl_slist(struct curl_slist *slist)
1049 struct curl_slist *item;
1051 if (slist == NULL)
1052 return;
1054 item = slist;
1056 while (item != NULL)
1058 free(item->data);
1059 item->data = NULL;
1060 item = item->next;
1063 curl_slist_free_all(slist);
1066 static void raiseError(Connection *conn, CURLcode code)
1068 CAMLparam0();
1069 CAMLlocal1(exceptionData);
1070 value *exception;
1071 char *errorString = "Unknown Error";
1072 int i;
1074 for (i = 0; errorMap[i].name != NULL; i++)
1076 if (errorMap[i].error == code)
1078 errorString = errorMap[i].name;
1079 break;
1083 exceptionData = alloc(3, 0);
1085 Field(exceptionData, 0) = Val_int(code);
1086 Field(exceptionData, 1) = Val_int(code);
1087 Field(exceptionData, 2) = copy_string(errorString);
1089 if (conn != NULL && conn->errorBuffer != NULL)
1091 Field(Field(conn->ocamlValues, OcamlErrorBuffer), 0) =
1092 copy_string(conn->errorBuffer);
1095 exception = caml_named_value("CurlException");
1097 if (exception == NULL)
1098 failwith(errorString);
1100 raise_with_arg(*exception, exceptionData);
1102 CAMLreturn0;
1105 static void resetOcamlValues(Connection* connection)
1107 int i;
1109 for (i = 0; i < OcamlValuesSize; i++)
1110 Store_field(connection->ocamlValues, i, Val_unit);
1113 static Connection *newConnection(void)
1115 Connection *connection;
1117 connection = (Connection *)malloc(sizeof(Connection));
1119 enter_blocking_section();
1120 connection->connection = curl_easy_init();
1121 leave_blocking_section();
1123 connection->next = NULL;
1124 connection->prev = NULL;
1126 if (connectionList.tail == NULL)
1128 connectionList.tail = connection;
1129 connectionList.head = connection;
1131 else
1133 connection->prev = connectionList.head;
1134 connectionList.head->next = connection;
1135 connectionList.head = connection;
1138 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1139 resetOcamlValues(connection);
1140 register_global_root(&connection->ocamlValues);
1142 connection->url = NULL;
1143 connection->proxy = NULL;
1144 connection->userPwd = NULL;
1145 connection->proxyUserPwd = NULL;
1146 connection->range = NULL;
1147 connection->errorBuffer = NULL;
1148 connection->postFields = NULL;
1149 connection->postFieldSize = -1;
1150 connection->referer = NULL;
1151 connection->userAgent = NULL;
1152 connection->ftpPort = NULL;
1153 connection->cookie = NULL;
1154 connection->httpHeader = NULL;
1155 connection->httpPostFirst = NULL;
1156 connection->httpPostLast = NULL;
1157 connection->httpPostStrings = NULL;
1158 connection->sslCert = NULL;
1159 connection->sslCertType = NULL;
1160 connection->sslCertPasswd = NULL;
1161 connection->sslKey = NULL;
1162 connection->sslKeyType = NULL;
1163 connection->sslKeyPasswd = NULL;
1164 connection->sslEngine = NULL;
1165 connection->quote = NULL;
1166 connection->postQuote = NULL;
1167 connection->cookieFile = NULL;
1168 connection->customRequest = NULL;
1169 connection->interface = NULL;
1170 connection->caInfo = NULL;
1171 connection->caPath = NULL;
1172 connection->randomFile = NULL;
1173 connection->egdSocket = NULL;
1174 connection->cookieJar = NULL;
1175 connection->sslCipherList = NULL;
1176 connection->private = NULL;
1177 connection->http200Aliases = NULL;
1178 connection->netrcFile = NULL;
1179 connection->ftpaccount = NULL;
1180 connection->cookielist = NULL;
1181 connection->ftpAlternativeToUser = NULL;
1182 connection->sshPublicKeyFile = NULL;
1183 connection->sshPrivateKeyFile = NULL;
1184 connection->copyPostFields = NULL;
1186 return connection;
1189 static Connection *duplicateConnection(Connection *original)
1191 Connection *connection;
1193 connection = (Connection *)malloc(sizeof(Connection));
1195 enter_blocking_section();
1196 connection->connection = curl_easy_duphandle(original->connection);
1197 leave_blocking_section();
1199 connection->next = NULL;
1200 connection->prev = NULL;
1202 if (connectionList.tail == NULL)
1204 connectionList.tail = connection;
1205 connectionList.head = connection;
1207 else
1209 connection->prev = connectionList.head;
1210 connectionList.head->next = connection;
1211 connectionList.head = connection;
1214 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1215 resetOcamlValues(connection);
1216 register_global_root(&connection->ocamlValues);
1218 Store_field(connection->ocamlValues, OcamlWriteCallback,
1219 Field(original->ocamlValues, OcamlWriteCallback));
1220 Store_field(connection->ocamlValues, OcamlReadCallback,
1221 Field(original->ocamlValues, OcamlReadCallback));
1222 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1223 Field(original->ocamlValues, OcamlErrorBuffer));
1224 Store_field(connection->ocamlValues, OcamlPostFields,
1225 Field(original->ocamlValues, OcamlPostFields));
1226 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1227 Field(original->ocamlValues, OcamlHTTPHeader));
1228 Store_field(connection->ocamlValues, OcamlQuote,
1229 Field(original->ocamlValues, OcamlQuote));
1230 Store_field(connection->ocamlValues, OcamlPostQuote,
1231 Field(original->ocamlValues, OcamlPostQuote));
1232 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1233 Field(original->ocamlValues, OcamlHeaderCallback));
1234 Store_field(connection->ocamlValues, OcamlProgressCallback,
1235 Field(original->ocamlValues, OcamlProgressCallback));
1236 Store_field(connection->ocamlValues, OcamlDebugCallback,
1237 Field(original->ocamlValues, OcamlDebugCallback));
1238 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1239 Field(original->ocamlValues, OcamlHTTP200Aliases));
1240 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1241 Field(original->ocamlValues, OcamlIOCTLCallback));
1242 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1243 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1245 connection->url = NULL;
1246 connection->proxy = NULL;
1247 connection->userPwd = NULL;
1248 connection->proxyUserPwd = NULL;
1249 connection->range = NULL;
1250 connection->errorBuffer = NULL;
1251 connection->postFields = NULL;
1252 connection->postFieldSize = -1;
1253 connection->referer = NULL;
1254 connection->userAgent = NULL;
1255 connection->ftpPort = NULL;
1256 connection->cookie = NULL;
1257 connection->httpHeader = NULL;
1258 connection->httpPostFirst = NULL;
1259 connection->httpPostLast = NULL;
1260 connection->httpPostStrings = NULL;
1261 connection->sslCert = NULL;
1262 connection->sslCertType = NULL;
1263 connection->sslCertPasswd = NULL;
1264 connection->sslKey = NULL;
1265 connection->sslKeyType = NULL;
1266 connection->sslKeyPasswd = NULL;
1267 connection->sslEngine = NULL;
1268 connection->quote = NULL;
1269 connection->postQuote = NULL;
1270 connection->cookieFile = NULL;
1271 connection->customRequest = NULL;
1272 connection->interface = NULL;
1273 connection->caInfo = NULL;
1274 connection->caPath = NULL;
1275 connection->randomFile = NULL;
1276 connection->egdSocket = NULL;
1277 connection->cookieJar = NULL;
1278 connection->sslCipherList = NULL;
1279 connection->private = NULL;
1280 connection->http200Aliases = NULL;
1281 connection->netrcFile = NULL;
1282 connection->ftpaccount = NULL;
1283 connection->cookielist = NULL;
1284 connection->sshPublicKeyFile = NULL;
1285 connection->sshPrivateKeyFile = NULL;
1286 connection->copyPostFields = NULL;
1288 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1289 handleURL(connection, Field(original->ocamlValues,
1290 OcamlURL));
1291 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1292 handleProxy(connection, Field(original->ocamlValues,
1293 OcamlProxy));
1294 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1295 handleUserPwd(connection, Field(original->ocamlValues,
1296 OcamlUserPWD));
1297 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1298 handleProxyUserPwd(connection, Field(original->ocamlValues,
1299 OcamlProxyUserPWD));
1300 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1301 handleRange(connection, Field(original->ocamlValues,
1302 OcamlRange));
1303 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1304 handleErrorBuffer(connection, Field(original->ocamlValues,
1305 OcamlErrorBuffer));
1306 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1307 handlePostFields(connection, Field(original->ocamlValues,
1308 OcamlPostFields));
1309 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1310 handleReferer(connection, Field(original->ocamlValues,
1311 OcamlReferer));
1312 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1313 handleUserAgent(connection, Field(original->ocamlValues,
1314 OcamlUserAgent));
1315 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1316 handleFTPPort(connection, Field(original->ocamlValues,
1317 OcamlFTPPort));
1318 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1319 handleCookie(connection, Field(original->ocamlValues,
1320 OcamlCookie));
1321 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1322 handleHTTPHeader(connection, Field(original->ocamlValues,
1323 OcamlHTTPHeader));
1324 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1325 handleHTTPPost(connection, Field(original->ocamlValues,
1326 OcamlHTTPPost));
1327 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1328 handleSSLCert(connection, Field(original->ocamlValues,
1329 OcamlSSLCert));
1330 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1331 handleSSLCertType(connection, Field(original->ocamlValues,
1332 OcamlSSLCertType));
1333 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1334 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1335 OcamlSSLCertPasswd));
1336 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1337 handleSSLKey(connection, Field(original->ocamlValues,
1338 OcamlSSLKey));
1339 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1340 handleSSLKeyType(connection, Field(original->ocamlValues,
1341 OcamlSSLKeyType));
1342 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1343 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1344 OcamlSSLKeyPasswd));
1345 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1346 handleSSLEngine(connection, Field(original->ocamlValues,
1347 OcamlSSLEngine));
1348 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1349 handleQuote(connection, Field(original->ocamlValues,
1350 OcamlQuote));
1351 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1352 handlePostQuote(connection, Field(original->ocamlValues,
1353 OcamlPostQuote));
1354 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1355 handleCookieFile(connection, Field(original->ocamlValues,
1356 OcamlCookieFile));
1357 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1358 handleCustomRequest(connection, Field(original->ocamlValues,
1359 OcamlCustomRequest));
1360 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1361 handleInterface(connection, Field(original->ocamlValues,
1362 OcamlInterface));
1363 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1364 handleCAInfo(connection, Field(original->ocamlValues,
1365 OcamlCAInfo));
1366 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1367 handleCAPath(connection, Field(original->ocamlValues,
1368 OcamlCAPath));
1369 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1370 handleRandomFile(connection, Field(original->ocamlValues,
1371 OcamlRandomFile));
1372 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1373 handleEGDSocket(connection, Field(original->ocamlValues,
1374 OcamlEGDSocket));
1375 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1376 handleCookieJar(connection, Field(original->ocamlValues,
1377 OcamlCookieJar));
1378 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1379 handleSSLCipherList(connection, Field(original->ocamlValues,
1380 OcamlSSLCipherList));
1381 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1382 handlePrivate(connection, Field(original->ocamlValues,
1383 OcamlPrivate));
1384 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1385 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1386 OcamlHTTP200Aliases));
1387 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1388 handleNETRCFile(connection, Field(original->ocamlValues,
1389 OcamlNETRCFile));
1390 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1391 handleFTPAccount(connection, Field(original->ocamlValues,
1392 OcamlFTPAccount));
1393 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1394 handleCookieList(connection, Field(original->ocamlValues,
1395 OcamlCookieList));
1396 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1397 handleFTPAlternativeToUser(connection,
1398 Field(original->ocamlValues,
1399 OcamlFTPAlternativeToUser));
1400 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1401 handleSSHPublicKeyFile(connection,
1402 Field(original->ocamlValues,
1403 OcamlSSHPublicKeyFile));
1404 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1405 handleSSHPrivateKeyFile(connection,
1406 Field(original->ocamlValues,
1407 OcamlSSHPrivateKeyFile));
1408 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1409 handleCopyPostFields(connection,
1410 Field(original->ocamlValues,
1411 OcamlCopyPostFields));
1413 return connection;
1416 static void removeConnection(Connection *connection)
1418 enter_blocking_section();
1419 curl_easy_cleanup(connection->connection);
1420 leave_blocking_section();
1422 if (connectionList.tail == connection)
1423 connectionList.tail = connectionList.tail->next;
1424 if (connectionList.head == connection)
1425 connectionList.head = connectionList.head->prev;
1427 if (connection->next != NULL)
1428 connection->next->prev = connection->prev;
1429 if (connection->prev != NULL)
1430 connection->prev->next = connection->next;
1432 remove_global_root(&connection->ocamlValues);
1434 if (connection->url != NULL)
1435 free(connection->url);
1436 if (connection->proxy != NULL)
1437 free(connection->proxy);
1438 if (connection->userPwd != NULL)
1439 free(connection->userPwd);
1440 if (connection->proxyUserPwd != NULL)
1441 free(connection->proxyUserPwd);
1442 if (connection->range != NULL)
1443 free(connection->range);
1444 if (connection->errorBuffer != NULL)
1445 free(connection->range);
1446 if (connection->postFields != NULL)
1447 free(connection->postFields);
1448 if (connection->referer != NULL)
1449 free(connection->referer);
1450 if (connection->userAgent != NULL)
1451 free(connection->userAgent);
1452 if (connection->ftpPort != NULL)
1453 free(connection->ftpPort);
1454 if (connection->cookie != NULL)
1455 free(connection->cookie);
1456 if (connection->httpHeader != NULL)
1457 free_curl_slist(connection->httpHeader);
1458 if (connection->httpPostFirst != NULL)
1459 curl_formfree(connection->httpPostFirst);
1460 if (connection->httpPostStrings != NULL)
1461 free_curl_slist(connection->httpPostStrings);
1462 if (connection->sslCert != NULL)
1463 free(connection->sslCert);
1464 if (connection->sslCertType != NULL)
1465 free(connection->sslCertType);
1466 if (connection->sslCertPasswd != NULL)
1467 free(connection->sslCertPasswd);
1468 if (connection->sslKey != NULL)
1469 free(connection->sslKey);
1470 if (connection->sslKeyType != NULL)
1471 free(connection->sslKeyType);
1472 if (connection->sslKeyPasswd != NULL)
1473 free(connection->sslKeyPasswd);
1474 if (connection->sslEngine != NULL)
1475 free(connection->sslEngine);
1476 if (connection->quote != NULL)
1477 free_curl_slist(connection->quote);
1478 if (connection->postQuote != NULL)
1479 free_curl_slist(connection->postQuote);
1480 if (connection->cookieFile != NULL)
1481 free(connection->cookieFile);
1482 if (connection->customRequest != NULL)
1483 free(connection->customRequest);
1484 if (connection->interface != NULL)
1485 free(connection->interface);
1486 if (connection->caInfo != NULL)
1487 free(connection->caInfo);
1488 if (connection->caPath != NULL)
1489 free(connection->caPath);
1490 if (connection->randomFile != NULL)
1491 free(connection->randomFile);
1492 if (connection->egdSocket != NULL)
1493 free(connection->egdSocket);
1494 if (connection->cookieJar != NULL)
1495 free(connection->cookieJar);
1496 if (connection->sslCipherList != NULL)
1497 free(connection->sslCipherList);
1498 if (connection->private != NULL)
1499 free(connection->private);
1500 if (connection->http200Aliases != NULL)
1501 free_curl_slist(connection->http200Aliases);
1502 if (connection->netrcFile != NULL)
1503 free(connection->netrcFile);
1504 if (connection->ftpaccount != NULL)
1505 free(connection->ftpaccount);
1506 if (connection->cookielist != NULL)
1507 free(connection->cookielist);
1508 if (connection->ftpAlternativeToUser != NULL)
1509 free(connection->ftpAlternativeToUser);
1510 if (connection->sshPublicKeyFile != NULL)
1511 free(connection->sshPublicKeyFile);
1512 if (connection->sshPrivateKeyFile != NULL)
1513 free(connection->sshPrivateKeyFile);
1514 if (connection->copyPostFields != NULL)
1515 free(connection->copyPostFields);
1517 free(connection);
1520 static void checkConnection(Connection *connection)
1522 Connection *listIter;
1524 listIter = connectionList.tail;
1526 while (listIter != NULL)
1528 if (listIter == connection)
1529 return;
1531 listIter = listIter->next;
1534 failwith("Invalid Connection");
1537 static Connection* findConnection(CURL* h)
1539 Connection *listIter;
1541 listIter = connectionList.tail;
1543 while (listIter != NULL)
1545 if (listIter->connection == h)
1546 return listIter;
1548 listIter = listIter->next;
1551 failwith("Unknown handle");
1554 #define WRAP_DATA_CALLBACK(f) \
1555 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1557 size_t result;\
1558 leave_blocking_section();\
1559 result = f##_nolock(ptr,size,nmemb,data);\
1560 enter_blocking_section();\
1561 return result;\
1564 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1566 CAMLparam0();
1567 CAMLlocal2(result, str);
1568 Connection *conn = (Connection *)data;
1569 int i;
1571 checkConnection(conn);
1573 str = alloc_string(size*nmemb);
1575 for (i = 0; i < size*nmemb; i++)
1576 Byte(str, i) = ptr[i];
1578 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1580 CAMLreturnT(size_t, Int_val(result));
1583 WRAP_DATA_CALLBACK(writeFunction)
1585 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1587 CAMLparam0();
1588 CAMLlocal1(result);
1589 Connection *conn = (Connection *)data;
1590 int length;
1592 checkConnection(conn);
1594 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1595 Val_int(size*nmemb));
1597 length = string_length(result);
1599 if (length >= size*nmemb)
1600 length = size*nmemb;
1602 memcpy(ptr, String_val(result), length);
1604 CAMLreturnT(size_t,length);
1607 WRAP_DATA_CALLBACK(readFunction)
1609 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1611 CAMLparam0();
1612 CAMLlocal2(result,str);
1613 Connection *conn = (Connection *)data;
1614 int i;
1616 checkConnection(conn);
1618 str = alloc_string(size*nmemb);
1620 for (i = 0; i < size*nmemb; i++)
1621 Byte(str, i) = ptr[i];
1623 result = callback(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1625 CAMLreturnT(size_t, Int_val(result));
1628 WRAP_DATA_CALLBACK(headerFunction)
1630 static int progressFunction_nolock(void *data,
1631 double dlTotal,
1632 double dlNow,
1633 double ulTotal,
1634 double ulNow)
1636 CAMLparam0();
1637 CAMLlocal1(result);
1638 CAMLlocalN(callbackData, 4);
1639 Connection *conn = (Connection *)data;
1641 checkConnection(conn);
1643 callbackData[0] = copy_double(dlTotal);
1644 callbackData[1] = copy_double(dlNow);
1645 callbackData[2] = copy_double(ulTotal);
1646 callbackData[3] = copy_double(ulNow);
1648 result = callbackN(Field(conn->ocamlValues, OcamlProgressCallback),
1649 4, callbackData);
1651 CAMLreturnT(int, Bool_val(result));
1654 static int progressFunction(void *data,
1655 double dlTotal,
1656 double dlNow,
1657 double ulTotal,
1658 double ulNow)
1660 int r;
1661 leave_blocking_section();
1662 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1663 enter_blocking_section();
1664 return r;
1667 static int debugFunction_nolock(CURL *debugConnection,
1668 curl_infotype infoType,
1669 char *buffer,
1670 size_t bufferLength,
1671 void *data)
1673 CAMLparam0();
1674 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1675 int i;
1676 Connection *conn = (Connection *)data;
1678 checkConnection(conn);
1680 camlDebugConnection = (value)conn;
1681 camlInfoType = Val_long(infoType);
1682 camlMessage = alloc_string(bufferLength);
1684 for (i = 0; i < bufferLength; i++)
1685 Byte(camlMessage, i) = buffer[i];
1687 callback3(Field(conn->ocamlValues, OcamlDebugCallback),
1688 camlDebugConnection,
1689 camlInfoType,
1690 camlMessage);
1692 CAMLreturnT(int, 0);
1695 static int debugFunction(CURL *debugConnection,
1696 curl_infotype infoType,
1697 char *buffer,
1698 size_t bufferLength,
1699 void *data)
1701 int r;
1702 leave_blocking_section();
1703 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1704 enter_blocking_section();
1705 return r;
1708 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1709 int cmd,
1710 void *data)
1712 CAMLparam0();
1713 CAMLlocal3(camlResult, camlConnection, camlCmd);
1714 Connection *conn = (Connection *)data;
1715 curlioerr result = CURLIOE_OK;
1717 checkConnection(conn);
1719 if (cmd == CURLIOCMD_NOP)
1720 camlCmd = Val_long(0);
1721 else if (cmd == CURLIOCMD_RESTARTREAD)
1722 camlCmd = Val_long(1);
1723 else
1724 failwith("Invalid IOCTL Cmd!");
1726 camlConnection = alloc(1, Abstract_tag);
1727 Store_field(camlConnection, 0, (value)conn);
1729 camlResult = callback2(Field(conn->ocamlValues, OcamlIOCTLCallback),
1730 camlConnection,
1731 camlCmd);
1733 switch (Long_val(camlResult))
1735 case 0: /* CURLIOE_OK */
1736 result = CURLIOE_OK;
1737 break;
1739 case 1: /* CURLIOE_UNKNOWNCMD */
1740 result = CURLIOE_UNKNOWNCMD;
1741 break;
1743 case 2: /* CURLIOE_FAILRESTART */
1744 result = CURLIOE_FAILRESTART;
1745 break;
1747 default: /* Incorrect return value, but let's handle it */
1748 result = CURLIOE_FAILRESTART;
1749 break;
1752 CAMLreturnT(curlioerr, result);
1755 static curlioerr ioctlFunction(CURL *ioctl,
1756 int cmd,
1757 void *data)
1759 curlioerr r;
1760 leave_blocking_section();
1761 r = ioctlFunction_nolock(ioctl, cmd, data);
1762 enter_blocking_section();
1763 return r;
1766 #ifdef HAVE_DECL_CURLOPT_SEEKFUNCTION
1767 static int seekFunction_nolock(void *data,
1768 curl_off_t offset,
1769 int origin)
1771 CAMLparam0();
1772 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1773 Connection *conn = (Connection *)data;
1774 int result = 0;
1776 camlOffset = copy_int64(offset);
1778 if (origin == SEEK_SET)
1779 camlOrigin = Val_long(0);
1780 else if (origin == SEEK_CUR)
1781 camlOrigin = Val_long(1);
1782 else if (origin == SEEK_END)
1783 camlOrigin = Val_long(2);
1784 else
1785 camlOrigin = Val_long(0);
1787 camlResult = callback2(Field(conn->ocamlValues,
1788 OcamlSeekFunctionCallback),
1789 camlOffset,
1790 camlOrigin);
1792 result = Int_val(camlResult);
1794 CAMLreturnT(int, result);
1797 static int seekFunction(void *data,
1798 curl_off_t offset,
1799 int origin)
1801 int r;
1802 leave_blocking_section();
1803 r = seekFunction_nolock(data,offset,origin);
1804 enter_blocking_section();
1805 return r;
1808 #endif
1811 ** curl_global_init helper function
1814 CAMLprim value helper_curl_global_init(value initOption)
1816 CAMLparam1(initOption);
1818 switch (Long_val(initOption))
1820 case 0: /* CURLINIT_GLOBALALL */
1821 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1822 break;
1824 case 1: /* CURLINIT_GLOBALSSL */
1825 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1826 break;
1828 case 2: /* CURLINIT_GLOBALWIN32 */
1829 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1830 break;
1832 case 3: /* CURLINIT_GLOBALNOTHING */
1833 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1834 break;
1836 default:
1837 failwith("Invalid Initialization Option");
1838 break;
1841 /* Keep compiler happy, we should never get here due to failwith() */
1842 CAMLreturn(Val_unit);
1846 ** curl_global_cleanup helper function
1849 CAMLprim value helper_curl_global_cleanup(void)
1851 CAMLparam0();
1853 curl_global_cleanup();
1855 CAMLreturn(Val_unit);
1859 ** curl_easy_init helper function
1862 CAMLprim value helper_curl_easy_init(void)
1864 CAMLparam0();
1865 CAMLlocal1(result);
1867 Connection *conn = newConnection();
1869 result = alloc(1, Abstract_tag);
1870 Store_field(result, 0, (value)conn);
1872 CAMLreturn(result);
1875 CAMLprim value helper_curl_easy_reset(value conn)
1877 CAMLparam1(conn);
1878 Connection *connection = Connection_val(conn);
1880 checkConnection(connection);
1881 curl_easy_reset(connection->connection);
1882 resetOcamlValues(connection);
1884 CAMLreturn(Val_unit);
1888 ** curl_easy_setopt helper utility functions
1891 static void handleWriteFunction(Connection *conn, value option)
1893 CAMLparam1(option);
1894 CURLcode result = CURLE_OK;
1896 if (Tag_val(option) == Closure_tag)
1897 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1898 else
1899 failwith("Not a proper closure");
1901 result = curl_easy_setopt(conn->connection,
1902 CURLOPT_WRITEFUNCTION,
1903 writeFunction);
1905 if (result != CURLE_OK)
1906 raiseError(conn, result);
1908 result = curl_easy_setopt(conn->connection,
1909 CURLOPT_WRITEDATA,
1910 conn);
1912 if (result != CURLE_OK)
1913 raiseError(conn, result);
1915 CAMLreturn0;
1918 static void handleReadFunction(Connection *conn, value option)
1920 CAMLparam1(option);
1921 CURLcode result = CURLE_OK;
1923 if (Tag_val(option) == Closure_tag)
1924 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1925 else
1926 failwith("Not a proper closure");
1928 result = curl_easy_setopt(conn->connection,
1929 CURLOPT_READFUNCTION,
1930 readFunction);
1932 if (result != CURLE_OK)
1933 raiseError(conn, result);
1935 result = curl_easy_setopt(conn->connection,
1936 CURLOPT_READDATA,
1937 conn);
1939 if (result != CURLE_OK)
1940 raiseError(conn, result);
1942 CAMLreturn0;
1945 static void handleURL(Connection *conn, value option)
1947 CAMLparam1(option);
1948 CURLcode result = CURLE_OK;
1950 Store_field(conn->ocamlValues, OcamlURL, option);
1952 if (conn->url != NULL)
1953 free(conn->url);
1955 conn->url = strdup(String_val(option));
1957 result = curl_easy_setopt(conn->connection,
1958 CURLOPT_URL,
1959 conn->url);
1961 if (result != CURLE_OK)
1962 raiseError(conn, result);
1964 CAMLreturn0;
1967 static void handleInFileSize(Connection *conn, value option)
1969 CAMLparam1(option);
1970 CURLcode result = CURLE_OK;
1972 result = curl_easy_setopt(conn->connection,
1973 CURLOPT_INFILESIZE,
1974 Long_val(option));
1976 if (result != CURLE_OK)
1977 raiseError(conn, result);
1979 CAMLreturn0;
1982 static void handleProxy(Connection *conn, value option)
1984 CAMLparam1(option);
1985 CURLcode result = CURLE_OK;
1987 Store_field(conn->ocamlValues, OcamlProxy, option);
1989 if (conn->proxy != NULL)
1990 free(conn->proxy);
1992 conn->proxy = strdup(String_val(option));
1994 result = curl_easy_setopt(conn->connection,
1995 CURLOPT_PROXY,
1996 conn->proxy);
1998 if (result != CURLE_OK)
1999 raiseError(conn, result);
2001 CAMLreturn0;
2004 static void handleProxyPort(Connection *conn, value option)
2006 CAMLparam1(option);
2007 CURLcode result = CURLE_OK;
2009 result = curl_easy_setopt(conn->connection,
2010 CURLOPT_PROXYPORT,
2011 Long_val(option));
2013 if (result != CURLE_OK)
2014 raiseError(conn, result);
2016 CAMLreturn0;
2019 static void handleHTTPProxyTunnel(Connection *conn, value option)
2021 CAMLparam1(option);
2022 CURLcode result = CURLE_OK;
2024 result = curl_easy_setopt(conn->connection,
2025 CURLOPT_HTTPPROXYTUNNEL,
2026 Bool_val(option));
2028 if (result != CURLE_OK)
2029 raiseError(conn, result);
2031 CAMLreturn0;
2034 static void handleVerbose(Connection *conn, value option)
2036 CAMLparam1(option);
2037 CURLcode result = CURLE_OK;
2039 result = curl_easy_setopt(conn->connection,
2040 CURLOPT_VERBOSE,
2041 Bool_val(option));
2043 if (result != CURLE_OK)
2044 raiseError(conn, result);
2046 CAMLreturn0;
2049 static void handleHeader(Connection *conn, value option)
2051 CAMLparam1(option);
2052 CURLcode result = CURLE_OK;
2054 result = curl_easy_setopt(conn->connection,
2055 CURLOPT_HEADER,
2056 Bool_val(option));
2058 if (result != CURLE_OK)
2059 raiseError(conn, result);
2061 CAMLreturn0;
2064 static void handleNoProgress(Connection *conn, value option)
2066 CAMLparam1(option);
2067 CURLcode result = CURLE_OK;
2069 result = curl_easy_setopt(conn->connection,
2070 CURLOPT_NOPROGRESS,
2071 Bool_val(option));
2073 if (result != CURLE_OK)
2074 raiseError(conn, result);
2076 CAMLreturn0;
2079 static void handleNoSignal(Connection *conn, value option)
2081 #if HAVE_DECL_CURLOPT_NOSIGNAL
2082 CAMLparam1(option);
2083 CURLcode result = CURLE_OK;
2085 result = curl_easy_setopt(conn->connection,
2086 CURLOPT_NOSIGNAL,
2087 Bool_val(option));
2089 if (result != CURLE_OK)
2090 raiseError(conn, result);
2092 CAMLreturn0;
2093 #else
2094 #warning "libcurl does not implement CURLOPT_NOSIGNAL"
2095 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2096 #endif
2099 static void handleNoBody(Connection *conn, value option)
2101 CAMLparam1(option);
2102 CURLcode result = CURLE_OK;
2104 result = curl_easy_setopt(conn->connection,
2105 CURLOPT_NOBODY,
2106 Bool_val(option));
2108 if (result != CURLE_OK)
2109 raiseError(conn, result);
2111 CAMLreturn0;
2114 static void handleFailOnError(Connection *conn, value option)
2116 CAMLparam1(option);
2117 CURLcode result = CURLE_OK;
2119 result = curl_easy_setopt(conn->connection,
2120 CURLOPT_FAILONERROR,
2121 Bool_val(option));
2123 if (result != CURLE_OK)
2124 raiseError(conn, result);
2126 CAMLreturn0;
2129 static void handleUpload(Connection *conn, value option)
2131 CAMLparam1(option);
2132 CURLcode result = CURLE_OK;
2134 result = curl_easy_setopt(conn->connection,
2135 CURLOPT_UPLOAD,
2136 Bool_val(option));
2138 if (result != CURLE_OK)
2139 raiseError(conn, result);
2141 CAMLreturn0;
2144 static void handlePost(Connection *conn, value option)
2146 CAMLparam1(option);
2147 CURLcode result = CURLE_OK;
2149 result = curl_easy_setopt(conn->connection,
2150 CURLOPT_POST,
2151 Bool_val(option));
2153 if (result != CURLE_OK)
2154 raiseError(conn, result);
2156 CAMLreturn0;
2159 static void handleFTPListOnly(Connection *conn, value option)
2161 CAMLparam1(option);
2162 CURLcode result = CURLE_OK;
2164 result = curl_easy_setopt(conn->connection,
2165 CURLOPT_FTPLISTONLY,
2166 Bool_val(option));
2168 if (result != CURLE_OK)
2169 raiseError(conn, result);
2171 CAMLreturn0;
2174 static void handleFTPAppend(Connection *conn, value option)
2176 CAMLparam1(option);
2177 CURLcode result = CURLE_OK;
2179 result = curl_easy_setopt(conn->connection,
2180 CURLOPT_FTPAPPEND,
2181 Bool_val(option));
2183 if (result != CURLE_OK)
2184 raiseError(conn, result);
2186 CAMLreturn0;
2189 static void handleNETRC(Connection *conn, value option)
2191 CAMLparam1(option);
2192 CURLcode result = CURLE_OK;
2193 long netrc;
2195 switch (Long_val(option))
2197 case 0: /* CURL_NETRC_OPTIONAL */
2198 netrc = CURL_NETRC_OPTIONAL;
2199 break;
2201 case 1:/* CURL_NETRC_IGNORED */
2202 netrc = CURL_NETRC_IGNORED;
2203 break;
2205 case 2: /* CURL_NETRC_REQUIRED */
2206 netrc = CURL_NETRC_REQUIRED;
2207 break;
2209 default:
2210 failwith("Invalid NETRC Option");
2211 break;
2214 result = curl_easy_setopt(conn->connection,
2215 CURLOPT_NETRC,
2216 netrc);
2218 if (result != CURLE_OK)
2219 raiseError(conn, result);
2221 CAMLreturn0;
2224 static void handleEncoding(Connection *conn, value option)
2226 #if HAVE_DECL_CURLOPT_ENCODING
2227 CAMLparam1(option);
2228 CURLcode result = CURLE_OK;
2230 switch (Long_val(option))
2232 case 0: /* CURL_ENCODING_NONE */
2233 result = curl_easy_setopt(conn->connection,
2234 CURLOPT_ENCODING,
2235 "identity");
2236 break;
2238 case 1: /* CURL_ENCODING_DEFLATE */
2239 result = curl_easy_setopt(conn->connection,
2240 CURLOPT_ENCODING,
2241 "deflate");
2242 break;
2244 default:
2245 failwith("Invalid Encoding Option");
2246 break;
2249 if (result != CURLE_OK)
2250 raiseError(conn, result);
2252 CAMLreturn0;
2253 #else
2254 #warning "libcurl does not implement CURLOPT_ENCODING"
2255 failwith("libcurl does not implement CURLOPT_ENCODING");
2256 #endif
2259 static void handleFollowLocation(Connection *conn, value option)
2261 CAMLparam1(option);
2262 CURLcode result = CURLE_OK;
2264 result = curl_easy_setopt(conn->connection,
2265 CURLOPT_FOLLOWLOCATION,
2266 Bool_val(option));
2268 if (result != CURLE_OK)
2269 raiseError(conn, result);
2271 CAMLreturn0;
2274 static void handleTransferText(Connection *conn, value option)
2276 CAMLparam1(option);
2277 CURLcode result = CURLE_OK;
2279 result = curl_easy_setopt(conn->connection,
2280 CURLOPT_TRANSFERTEXT,
2281 Bool_val(option));
2283 if (result != CURLE_OK)
2284 raiseError(conn, result);
2286 CAMLreturn0;
2289 static void handlePut(Connection *conn, value option)
2291 CAMLparam1(option);
2292 CURLcode result = CURLE_OK;
2294 result = curl_easy_setopt(conn->connection,
2295 CURLOPT_PUT,
2296 Bool_val(option));
2298 if (result != CURLE_OK)
2299 raiseError(conn, result);
2301 CAMLreturn0;
2304 static void handleUserPwd(Connection *conn, value option)
2306 CAMLparam1(option);
2307 CURLcode result = CURLE_OK;
2309 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2311 if (conn->userPwd != NULL)
2312 free(conn->userPwd);
2314 conn->userPwd = strdup(String_val(option));
2316 result = curl_easy_setopt(conn->connection,
2317 CURLOPT_USERPWD,
2318 conn->userPwd);
2320 if (result != CURLE_OK)
2321 raiseError(conn, result);
2323 CAMLreturn0;
2326 static void handleProxyUserPwd(Connection *conn, value option)
2328 CAMLparam1(option);
2329 CURLcode result = CURLE_OK;
2331 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2333 if (conn->proxyUserPwd != NULL)
2334 free(conn->proxyUserPwd);
2336 conn->proxyUserPwd = strdup(String_val(option));
2338 result = curl_easy_setopt(conn->connection,
2339 CURLOPT_PROXYUSERPWD,
2340 conn->proxyUserPwd);
2342 if (result != CURLE_OK)
2343 raiseError(conn, result);
2345 CAMLreturn0;
2348 static void handleRange(Connection *conn, value option)
2350 CAMLparam1(option);
2351 CURLcode result = CURLE_OK;
2353 Store_field(conn->ocamlValues, OcamlRange, option);
2355 if (conn->range != NULL)
2356 free(conn->range);
2358 conn->range = strdup(String_val(option));
2360 result = curl_easy_setopt(conn->connection,
2361 CURLOPT_RANGE,
2362 conn->range);
2364 if (result != CURLE_OK)
2365 raiseError(conn, result);
2367 CAMLreturn0;
2370 static void handleErrorBuffer(Connection *conn, value option)
2372 CAMLparam1(option);
2373 CURLcode result = CURLE_OK;
2375 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2377 if (conn->errorBuffer != NULL)
2378 free(conn->errorBuffer);
2380 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2382 result = curl_easy_setopt(conn->connection,
2383 CURLOPT_ERRORBUFFER,
2384 conn->errorBuffer);
2386 if (result != CURLE_OK)
2387 raiseError(conn, result);
2389 CAMLreturn0;
2392 static void handleTimeout(Connection *conn, value option)
2394 CAMLparam1(option);
2395 CURLcode result = CURLE_OK;
2397 result = curl_easy_setopt(conn->connection,
2398 CURLOPT_TIMEOUT,
2399 Long_val(option));
2401 if (result != CURLE_OK)
2402 raiseError(conn, result);
2404 CAMLreturn0;
2407 static void handlePostFields(Connection *conn, value option)
2409 CAMLparam1(option);
2410 CURLcode result = CURLE_OK;
2412 Store_field(conn->ocamlValues, OcamlPostFields, option);
2414 if (conn->postFields != NULL)
2415 free(conn->postFields);
2417 conn->postFields = malloc(string_length(option)+1);
2418 memcpy(conn->postFields, String_val(option), string_length(option));
2420 result = curl_easy_setopt(conn->connection,
2421 CURLOPT_POSTFIELDS,
2422 conn->postFields);
2424 if (result != CURLE_OK)
2425 raiseError(conn, result);
2427 CAMLreturn0;
2430 static void handlePostFieldSize(Connection *conn, value option)
2432 CAMLparam1(option);
2433 CURLcode result = CURLE_OK;
2435 result = curl_easy_setopt(conn->connection,
2436 CURLOPT_POSTFIELDSIZE,
2437 Long_val(option));
2439 if (result != CURLE_OK)
2440 raiseError(conn, result);
2442 CAMLreturn0;
2445 static void handleReferer(Connection *conn, value option)
2447 CAMLparam1(option);
2448 CURLcode result = CURLE_OK;
2450 Store_field(conn->ocamlValues, OcamlReferer, option);
2452 if (conn->referer != NULL)
2453 free(conn->referer);
2455 conn->referer = strdup(String_val(option));
2457 result = curl_easy_setopt(conn->connection,
2458 CURLOPT_REFERER,
2459 conn->referer);
2461 if (result != CURLE_OK)
2462 raiseError(conn, result);
2464 CAMLreturn0;
2467 static void handleUserAgent(Connection *conn, value option)
2469 CAMLparam1(option);
2470 CURLcode result = CURLE_OK;
2472 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2474 if (conn->userAgent != NULL)
2475 free(conn->userAgent);
2477 conn->userAgent = strdup(String_val(option));
2479 result = curl_easy_setopt(conn->connection,
2480 CURLOPT_USERAGENT,
2481 conn->userAgent);
2483 if (result != CURLE_OK)
2484 raiseError(conn, result);
2486 CAMLreturn0;
2489 static void handleFTPPort(Connection *conn, value option)
2491 CAMLparam1(option);
2492 CURLcode result = CURLE_OK;
2494 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2496 if (conn->ftpPort != NULL)
2497 free(conn->ftpPort);
2499 conn->ftpPort = strdup(String_val(option));
2501 result = curl_easy_setopt(conn->connection,
2502 CURLOPT_FTPPORT,
2503 conn->ftpPort);
2505 if (result != CURLE_OK)
2506 raiseError(conn, result);
2508 CAMLreturn0;
2511 static void handleLowSpeedLimit(Connection *conn, value option)
2513 CAMLparam1(option);
2514 CURLcode result = CURLE_OK;
2516 result = curl_easy_setopt(conn->connection,
2517 CURLOPT_LOW_SPEED_LIMIT,
2518 Long_val(option));
2520 if (result != CURLE_OK)
2521 raiseError(conn, result);
2523 CAMLreturn0;
2526 static void handleLowSpeedTime(Connection *conn, value option)
2528 CAMLparam1(option);
2529 CURLcode result = CURLE_OK;
2531 result = curl_easy_setopt(conn->connection,
2532 CURLOPT_LOW_SPEED_TIME,
2533 Long_val(option));
2535 if (result != CURLE_OK)
2536 raiseError(conn, result);
2538 CAMLreturn0;
2541 static void handleResumeFrom(Connection *conn, value option)
2543 CAMLparam1(option);
2544 CURLcode result = CURLE_OK;
2546 result = curl_easy_setopt(conn->connection,
2547 CURLOPT_RESUME_FROM,
2548 Long_val(option));
2550 if (result != CURLE_OK)
2551 raiseError(conn, result);
2553 CAMLreturn0;
2556 static void handleCookie(Connection *conn, value option)
2558 CAMLparam1(option);
2559 CURLcode result = CURLE_OK;
2561 Store_field(conn->ocamlValues, OcamlCookie, option);
2563 if (conn->cookie != NULL)
2564 free(conn->cookie);
2566 conn->cookie = strdup(String_val(option));
2568 result = curl_easy_setopt(conn->connection,
2569 CURLOPT_COOKIE,
2570 conn->cookie);
2572 if (result != CURLE_OK)
2573 raiseError(conn, result);
2575 CAMLreturn0;
2578 static void handleHTTPHeader(Connection *conn, value option)
2580 CAMLparam1(option);
2581 CAMLlocal1(listIter);
2582 CURLcode result = CURLE_OK;
2583 char *str;
2585 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2587 if (conn->httpHeader != NULL)
2588 free_curl_slist(conn->httpHeader);
2590 conn->httpHeader = NULL;
2592 listIter = option;
2594 while (!Is_long(listIter))
2596 if (Tag_val(Field(listIter, 0)) != String_tag)
2597 failwith("Not a string");
2599 str = strdup(String_val(Field(listIter, 0)));
2601 conn->httpHeader = curl_slist_append(conn->httpHeader, str);
2603 listIter = Field(listIter, 1);
2606 result = curl_easy_setopt(conn->connection,
2607 CURLOPT_HTTPHEADER,
2608 conn->httpHeader);
2610 if (result != CURLE_OK)
2611 raiseError(conn, result);
2613 CAMLreturn0;
2616 static void handleHTTPPost(Connection *conn, value option)
2618 CAMLparam1(option);
2619 CAMLlocal3(listIter, formItem, contentType);
2620 CURLcode result = CURLE_OK;
2621 char *str1, *str2, *str3, *str4;
2623 listIter = option;
2625 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2627 if (conn->httpPostFirst != NULL)
2628 curl_formfree(conn->httpPostFirst);
2630 conn->httpPostFirst = NULL;
2631 conn->httpPostLast = NULL;
2633 if (conn->httpPostStrings != NULL)
2634 free_curl_slist(conn->httpPostStrings);
2636 while (!Is_long(listIter))
2638 formItem = Field(listIter, 0);
2640 switch (Tag_val(formItem))
2642 case 0: /* CURLFORM_CONTENT */
2643 if (Wosize_val(formItem) < 3)
2645 failwith("Incorrect CURLFORM_CONTENT parameters");
2648 if (Is_long(Field(formItem, 2)) &&
2649 Long_val(Field(formItem, 2)) == 0)
2651 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2652 memcpy(str1,
2653 String_val(Field(formItem, 0)),
2654 string_length(Field(formItem, 0)));
2655 str1[string_length(Field(formItem, 0))] = 0;
2656 conn->httpPostStrings =
2657 curl_slist_append(conn->httpPostStrings, str1);
2659 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2660 memcpy(str2,
2661 String_val(Field(formItem, 1)),
2662 string_length(Field(formItem, 1)));
2663 str2[string_length(Field(formItem, 1))] = 0;
2664 conn->httpPostStrings =
2665 curl_slist_append(conn->httpPostStrings, str2);
2667 curl_formadd(&conn->httpPostFirst,
2668 &conn->httpPostLast,
2669 CURLFORM_PTRNAME,
2670 str1,
2671 CURLFORM_NAMELENGTH,
2672 string_length(Field(formItem, 0)),
2673 CURLFORM_PTRCONTENTS,
2674 str2,
2675 CURLFORM_CONTENTSLENGTH,
2676 string_length(Field(formItem, 1)),
2677 CURLFORM_END);
2679 else if (Is_block(Field(formItem, 2)))
2681 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2682 memcpy(str1,
2683 String_val(Field(formItem, 0)),
2684 string_length(Field(formItem, 0)));
2685 str1[string_length(Field(formItem, 0))] = 0;
2686 conn->httpPostStrings =
2687 curl_slist_append(conn->httpPostStrings, str1);
2689 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2690 memcpy(str2,
2691 String_val(Field(formItem, 1)),
2692 string_length(Field(formItem, 1)));
2693 str2[string_length(Field(formItem, 1))] = 0;
2694 conn->httpPostStrings =
2695 curl_slist_append(conn->httpPostStrings, str2);
2697 contentType = Field(formItem, 2);
2699 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2700 memcpy(str3,
2701 String_val(Field(contentType, 0)),
2702 string_length(Field(contentType, 0)));
2703 str3[string_length(Field(contentType, 0))] = 0;
2704 conn->httpPostStrings =
2705 curl_slist_append(conn->httpPostStrings, str3);
2707 curl_formadd(&conn->httpPostFirst,
2708 &conn->httpPostLast,
2709 CURLFORM_PTRNAME,
2710 str1,
2711 CURLFORM_NAMELENGTH,
2712 string_length(Field(formItem, 0)),
2713 CURLFORM_PTRCONTENTS,
2714 str2,
2715 CURLFORM_CONTENTSLENGTH,
2716 string_length(Field(formItem, 1)),
2717 CURLFORM_CONTENTTYPE,
2718 str3,
2719 CURLFORM_END);
2721 else
2723 failwith("Incorrect CURLFORM_CONTENT parameters");
2725 break;
2727 case 1: /* CURLFORM_FILECONTENT */
2728 if (Wosize_val(formItem) < 3)
2730 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2733 if (Is_long(Field(formItem, 2)) &&
2734 Long_val(Field(formItem, 2)) == 0)
2736 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2737 memcpy(str1,
2738 String_val(Field(formItem, 0)),
2739 string_length(Field(formItem, 0)));
2740 str1[string_length(Field(formItem, 0))] = 0;
2741 conn->httpPostStrings =
2742 curl_slist_append(conn->httpPostStrings, str1);
2744 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2745 memcpy(str2,
2746 String_val(Field(formItem, 1)),
2747 string_length(Field(formItem, 1)));
2748 str2[string_length(Field(formItem, 1))] = 0;
2749 conn->httpPostStrings =
2750 curl_slist_append(conn->httpPostStrings, str2);
2752 curl_formadd(&conn->httpPostFirst,
2753 &conn->httpPostLast,
2754 CURLFORM_PTRNAME,
2755 str1,
2756 CURLFORM_NAMELENGTH,
2757 string_length(Field(formItem, 0)),
2758 CURLFORM_FILECONTENT,
2759 str2,
2760 CURLFORM_END);
2762 else if (Is_block(Field(formItem, 2)))
2764 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2765 memcpy(str1,
2766 String_val(Field(formItem, 0)),
2767 string_length(Field(formItem, 0)));
2768 str1[string_length(Field(formItem, 0))] = 0;
2769 conn->httpPostStrings =
2770 curl_slist_append(conn->httpPostStrings, str1);
2772 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2773 memcpy(str2,
2774 String_val(Field(formItem, 1)),
2775 string_length(Field(formItem, 1)));
2776 str2[string_length(Field(formItem, 1))] = 0;
2777 conn->httpPostStrings =
2778 curl_slist_append(conn->httpPostStrings, str2);
2780 contentType = Field(formItem, 2);
2782 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2783 memcpy(str3,
2784 String_val(Field(contentType, 0)),
2785 string_length(Field(contentType, 0)));
2786 str3[string_length(Field(contentType, 0))] = 0;
2787 conn->httpPostStrings =
2788 curl_slist_append(conn->httpPostStrings, str3);
2790 curl_formadd(&conn->httpPostFirst,
2791 &conn->httpPostLast,
2792 CURLFORM_PTRNAME,
2793 str1,
2794 CURLFORM_NAMELENGTH,
2795 string_length(Field(formItem, 0)),
2796 CURLFORM_FILECONTENT,
2797 str2,
2798 CURLFORM_CONTENTTYPE,
2799 str3,
2800 CURLFORM_END);
2802 else
2804 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2806 break;
2808 case 2: /* CURLFORM_FILE */
2809 if (Wosize_val(formItem) < 3)
2811 failwith("Incorrect CURLFORM_FILE parameters");
2814 if (Is_long(Field(formItem, 2)) &&
2815 Long_val(Field(formItem, 2)) == 0)
2817 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2818 memcpy(str1,
2819 String_val(Field(formItem, 0)),
2820 string_length(Field(formItem, 0)));
2821 str1[string_length(Field(formItem, 0))] = 0;
2822 conn->httpPostStrings =
2823 curl_slist_append(conn->httpPostStrings, str1);
2825 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2826 memcpy(str2,
2827 String_val(Field(formItem, 1)),
2828 string_length(Field(formItem, 1)));
2829 str2[string_length(Field(formItem, 1))] = 0;
2830 conn->httpPostStrings =
2831 curl_slist_append(conn->httpPostStrings, str2);
2833 curl_formadd(&conn->httpPostFirst,
2834 &conn->httpPostLast,
2835 CURLFORM_PTRNAME,
2836 str1,
2837 CURLFORM_NAMELENGTH,
2838 string_length(Field(formItem, 0)),
2839 CURLFORM_FILE,
2840 str2,
2841 CURLFORM_END);
2843 else if (Is_block(Field(formItem, 2)))
2845 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2846 memcpy(str1,
2847 String_val(Field(formItem, 0)),
2848 string_length(Field(formItem, 0)));
2849 str1[string_length(Field(formItem, 0))] = 0;
2850 conn->httpPostStrings =
2851 curl_slist_append(conn->httpPostStrings, str1);
2853 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2854 memcpy(str2,
2855 String_val(Field(formItem, 1)),
2856 string_length(Field(formItem, 1)));
2857 str2[string_length(Field(formItem, 1))] = 0;
2858 conn->httpPostStrings =
2859 curl_slist_append(conn->httpPostStrings, str2);
2861 contentType = Field(formItem, 2);
2863 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2864 memcpy(str3,
2865 String_val(Field(contentType, 0)),
2866 string_length(Field(contentType, 0)));
2867 str3[string_length(Field(contentType, 0))] = 0;
2868 conn->httpPostStrings =
2869 curl_slist_append(conn->httpPostStrings, str3);
2871 curl_formadd(&conn->httpPostFirst,
2872 &conn->httpPostLast,
2873 CURLFORM_PTRNAME,
2874 str1,
2875 CURLFORM_NAMELENGTH,
2876 string_length(Field(formItem, 0)),
2877 CURLFORM_FILE,
2878 str2,
2879 CURLFORM_CONTENTTYPE,
2880 str3,
2881 CURLFORM_END);
2883 else
2885 failwith("Incorrect CURLFORM_FILE parameters");
2887 break;
2889 case 3: /* CURLFORM_BUFFER */
2890 if (Wosize_val(formItem) < 4)
2892 failwith("Incorrect CURLFORM_BUFFER parameters");
2895 if (Is_long(Field(formItem, 3)) &&
2896 Long_val(Field(formItem, 3)) == 0)
2898 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2899 memcpy(str1,
2900 String_val(Field(formItem, 0)),
2901 string_length(Field(formItem, 0)));
2902 str1[string_length(Field(formItem, 0))] = 0;
2903 conn->httpPostStrings =
2904 curl_slist_append(conn->httpPostStrings, str1);
2906 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2907 memcpy(str2,
2908 String_val(Field(formItem, 1)),
2909 string_length(Field(formItem, 1)));
2910 str2[string_length(Field(formItem, 1))] = 0;
2911 conn->httpPostStrings =
2912 curl_slist_append(conn->httpPostStrings, str2);
2914 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2915 memcpy(str3,
2916 String_val(Field(formItem, 2)),
2917 string_length(Field(formItem, 2)));
2918 str3[string_length(Field(formItem, 2))] = 0;
2919 conn->httpPostStrings =
2920 curl_slist_append(conn->httpPostStrings, str3);
2922 curl_formadd(&conn->httpPostFirst,
2923 &conn->httpPostLast,
2924 CURLFORM_PTRNAME,
2925 str1,
2926 CURLFORM_NAMELENGTH,
2927 string_length(Field(formItem, 0)),
2928 CURLFORM_BUFFER,
2929 str2,
2930 CURLFORM_BUFFERPTR,
2931 str3,
2932 CURLFORM_BUFFERLENGTH,
2933 string_length(Field(formItem, 2)),
2934 CURLFORM_END);
2936 else if (Is_block(Field(formItem, 3)))
2938 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2939 memcpy(str1,
2940 String_val(Field(formItem, 0)),
2941 string_length(Field(formItem, 0)));
2942 str1[string_length(Field(formItem, 0))] = 0;
2943 conn->httpPostStrings =
2944 curl_slist_append(conn->httpPostStrings, str1);
2946 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2947 memcpy(str2,
2948 String_val(Field(formItem, 1)),
2949 string_length(Field(formItem, 1)));
2950 str2[string_length(Field(formItem, 1))] = 0;
2951 conn->httpPostStrings =
2952 curl_slist_append(conn->httpPostStrings, str2);
2954 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2955 memcpy(str3,
2956 String_val(Field(formItem, 2)),
2957 string_length(Field(formItem, 2)));
2958 str3[string_length(Field(formItem, 2))] = 0;
2959 conn->httpPostStrings =
2960 curl_slist_append(conn->httpPostStrings, str3);
2962 contentType = Field(formItem, 3);
2964 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
2965 memcpy(str4,
2966 String_val(Field(contentType, 0)),
2967 string_length(Field(contentType, 0)));
2968 str4[string_length(Field(contentType, 0))] = 0;
2969 conn->httpPostStrings =
2970 curl_slist_append(conn->httpPostStrings, str4);
2972 curl_formadd(&conn->httpPostFirst,
2973 &conn->httpPostLast,
2974 CURLFORM_PTRNAME,
2975 str1,
2976 CURLFORM_NAMELENGTH,
2977 string_length(Field(formItem, 0)),
2978 CURLFORM_BUFFER,
2979 str2,
2980 CURLFORM_BUFFERPTR,
2981 str3,
2982 CURLFORM_BUFFERLENGTH,
2983 string_length(Field(formItem, 2)),
2984 CURLFORM_CONTENTTYPE,
2985 str4,
2986 CURLFORM_END);
2988 else
2990 failwith("Incorrect CURLFORM_BUFFER parameters");
2992 break;
2995 listIter = Field(listIter, 1);
2998 result = curl_easy_setopt(conn->connection,
2999 CURLOPT_HTTPPOST,
3000 conn->httpPostFirst);
3002 if (result != CURLE_OK)
3003 raiseError(conn, result);
3005 CAMLreturn0;
3008 static void handleSSLCert(Connection *conn, value option)
3010 CAMLparam1(option);
3011 CURLcode result = CURLE_OK;
3013 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3015 if (conn->sslCert != NULL)
3016 free(conn->sslCert);
3018 conn->sslCert = strdup(String_val(option));
3020 result = curl_easy_setopt(conn->connection,
3021 CURLOPT_SSLCERT,
3022 conn->sslCert);
3024 if (result != CURLE_OK)
3025 raiseError(conn, result);
3027 CAMLreturn0;
3030 static void handleSSLCertType(Connection *conn, value option)
3032 CAMLparam1(option);
3033 CURLcode result = CURLE_OK;
3035 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3037 if (conn->sslCertType != NULL)
3038 free(conn->sslCertType);
3040 conn->sslCertType = strdup(String_val(option));
3042 result = curl_easy_setopt(conn->connection,
3043 CURLOPT_SSLCERTTYPE,
3044 conn->sslCertType);
3046 if (result != CURLE_OK)
3047 raiseError(conn, result);
3049 CAMLreturn0;
3052 static void handleSSLCertPasswd(Connection *conn, value option)
3054 CAMLparam1(option);
3055 CURLcode result = CURLE_OK;
3057 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3059 if (conn->sslCertPasswd != NULL)
3060 free(conn->sslCertPasswd);
3062 conn->sslCertPasswd = strdup(String_val(option));
3064 result = curl_easy_setopt(conn->connection,
3065 CURLOPT_SSLCERTPASSWD,
3066 conn->sslCertPasswd);
3068 if (result != CURLE_OK)
3069 raiseError(conn, result);
3071 CAMLreturn0;
3074 static void handleSSLKey(Connection *conn, value option)
3076 CAMLparam1(option);
3077 CURLcode result = CURLE_OK;
3079 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3081 if (conn->sslKey != NULL)
3082 free(conn->sslKey);
3084 conn->sslKey = strdup(String_val(option));
3086 result = curl_easy_setopt(conn->connection,
3087 CURLOPT_SSLKEY,
3088 conn->sslKey);
3090 if (result != CURLE_OK)
3091 raiseError(conn, result);
3093 CAMLreturn0;
3096 static void handleSSLKeyType(Connection *conn, value option)
3098 CAMLparam1(option);
3099 CURLcode result = CURLE_OK;
3101 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3103 if (conn->sslKeyType != NULL)
3104 free(conn->sslKeyType);
3106 conn->sslKeyType = strdup(String_val(option));
3108 result = curl_easy_setopt(conn->connection,
3109 CURLOPT_SSLKEYTYPE,
3110 conn->sslKeyType);
3112 if (result != CURLE_OK)
3113 raiseError(conn, result);
3115 CAMLreturn0;
3118 static void handleSSLKeyPasswd(Connection *conn, value option)
3120 CAMLparam1(option);
3121 CURLcode result = CURLE_OK;
3123 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3125 if (conn->sslKeyPasswd != NULL)
3126 free(conn->sslKeyPasswd);
3128 conn->sslKeyPasswd = strdup(String_val(option));
3130 result = curl_easy_setopt(conn->connection,
3131 CURLOPT_SSLKEYPASSWD,
3132 conn->sslKeyPasswd);
3134 if (result != CURLE_OK)
3135 raiseError(conn, result);
3137 CAMLreturn0;
3140 static void handleSSLEngine(Connection *conn, value option)
3142 CAMLparam1(option);
3143 CURLcode result = CURLE_OK;
3145 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3147 if (conn->sslEngine != NULL)
3148 free(conn->sslEngine);
3150 conn->sslEngine = strdup(String_val(option));
3152 result = curl_easy_setopt(conn->connection,
3153 CURLOPT_SSLENGINE,
3154 conn->sslEngine);
3156 if (result != CURLE_OK)
3157 raiseError(conn, result);
3159 CAMLreturn0;
3162 static void handleSSLEngineDefault(Connection *conn, value option)
3164 CAMLparam1(option);
3165 CURLcode result = CURLE_OK;
3167 result = curl_easy_setopt(conn->connection,
3168 CURLOPT_SSLENGINE_DEFAULT,
3169 Bool_val(option));
3171 if (result != CURLE_OK)
3172 raiseError(conn, result);
3174 CAMLreturn0;
3177 static void handleCRLF(Connection *conn, value option)
3179 CAMLparam1(option);
3180 CURLcode result = CURLE_OK;
3182 result = curl_easy_setopt(conn->connection,
3183 CURLOPT_CRLF,
3184 Bool_val(option));
3186 if (result != CURLE_OK)
3187 raiseError(conn, result);
3189 CAMLreturn0;
3192 static void handleQuote(Connection *conn, value option)
3194 CAMLparam1(option);
3195 CAMLlocal1(listIter);
3196 CURLcode result = CURLE_OK;
3197 char *str;
3199 Store_field(conn->ocamlValues, OcamlQuote, option);
3201 if (conn->quote != NULL)
3202 free_curl_slist(conn->quote);
3204 conn->quote = NULL;
3206 listIter = option;
3208 while (!Is_long(listIter))
3210 if (Tag_val(Field(listIter, 0)) != String_tag)
3211 failwith("Not a string");
3213 str = strdup(String_val(Field(listIter, 0)));
3215 conn->quote = curl_slist_append(conn->quote, str);
3217 listIter = Field(listIter, 1);
3220 result = curl_easy_setopt(conn->connection,
3221 CURLOPT_QUOTE,
3222 conn->quote);
3224 if (result != CURLE_OK)
3225 raiseError(conn, result);
3227 CAMLreturn0;
3230 static void handlePostQuote(Connection *conn, value option)
3232 CAMLparam1(option);
3233 CAMLlocal1(listIter);
3234 CURLcode result = CURLE_OK;
3235 char *str;
3237 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3239 if (conn->postQuote != NULL)
3240 free_curl_slist(conn->postQuote);
3242 conn->postQuote = NULL;
3244 listIter = option;
3246 while (!Is_long(listIter))
3248 if (Tag_val(Field(listIter, 0)) != String_tag)
3249 failwith("Not a string");
3251 str = strdup(String_val(Field(listIter, 0)));
3253 conn->postQuote = curl_slist_append(conn->postQuote, str);
3255 listIter = Field(listIter, 1);
3258 result = curl_easy_setopt(conn->connection,
3259 CURLOPT_POSTQUOTE,
3260 conn->postQuote);
3262 if (result != CURLE_OK)
3263 raiseError(conn, result);
3265 CAMLreturn0;
3268 static void handleHeaderFunction(Connection *conn, value option)
3270 CAMLparam1(option);
3271 CURLcode result = CURLE_OK;
3273 if (Tag_val(option) == Closure_tag)
3274 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3275 else
3276 failwith("Not a proper closure");
3278 result = curl_easy_setopt(conn->connection,
3279 CURLOPT_HEADERFUNCTION,
3280 headerFunction);
3282 if (result != CURLE_OK)
3283 raiseError(conn, result);
3285 result = curl_easy_setopt(conn->connection,
3286 CURLOPT_WRITEHEADER,
3287 conn);
3289 if (result != CURLE_OK)
3290 raiseError(conn, result);
3292 CAMLreturn0;
3295 static void handleCookieFile(Connection *conn, value option)
3297 CAMLparam1(option);
3298 CURLcode result = CURLE_OK;
3300 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3302 if (conn->cookieFile != NULL)
3303 free(conn->cookieFile);
3305 conn->cookieFile = strdup(String_val(option));
3307 result = curl_easy_setopt(conn->connection,
3308 CURLOPT_COOKIEFILE,
3309 conn->cookieFile);
3311 if (result != CURLE_OK)
3312 raiseError(conn, result);
3314 CAMLreturn0;
3317 static void handleSSLVersion(Connection *conn, value option)
3319 CAMLparam1(option);
3320 CURLcode result = CURLE_OK;
3322 result = curl_easy_setopt(conn->connection,
3323 CURLOPT_SSLVERSION,
3324 Long_val(option));
3326 if (result != CURLE_OK)
3327 raiseError(conn, result);
3329 CAMLreturn0;
3332 static void handleTimeCondition(Connection *conn, value option)
3334 CAMLparam1(option);
3335 CURLcode result = CURLE_OK;
3337 switch (Long_val(option))
3339 case 0: /* TIMECOND_IFMODSINCE */
3340 result = curl_easy_setopt(conn->connection,
3341 CURLOPT_TIMECONDITION,
3342 CURL_TIMECOND_IFMODSINCE);
3343 break;
3345 case 1: /* TIMECOND_IFUNMODSINCE */
3346 result = curl_easy_setopt(conn->connection,
3347 CURLOPT_TIMECONDITION,
3348 CURL_TIMECOND_IFUNMODSINCE);
3349 break;
3351 default:
3352 failwith("Invalid TIMECOND Option");
3353 break;
3356 if (result != CURLE_OK)
3357 raiseError(conn, result);
3359 CAMLreturn0;
3362 static void handleTimeValue(Connection *conn, value option)
3364 CAMLparam1(option);
3365 CURLcode result = CURLE_OK;
3367 result = curl_easy_setopt(conn->connection,
3368 CURLOPT_TIMEVALUE,
3369 Int32_val(option));
3371 if (result != CURLE_OK)
3372 raiseError(conn, result);
3374 CAMLreturn0;
3377 static void handleCustomRequest(Connection *conn, value option)
3379 CAMLparam1(option);
3380 CURLcode result = CURLE_OK;
3382 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3384 if (conn->customRequest != NULL)
3385 free(conn->customRequest);
3387 conn->customRequest = strdup(String_val(option));
3389 result = curl_easy_setopt(conn->connection,
3390 CURLOPT_CUSTOMREQUEST,
3391 conn->customRequest);
3393 if (result != CURLE_OK)
3394 raiseError(conn, result);
3396 CAMLreturn0;
3399 static void handleInterface(Connection *conn, value option)
3401 CAMLparam1(option);
3402 CURLcode result = CURLE_OK;
3404 Store_field(conn->ocamlValues, OcamlInterface, option);
3406 if (conn->interface != NULL)
3407 free(conn->interface);
3409 conn->interface = strdup(String_val(option));
3411 result = curl_easy_setopt(conn->connection,
3412 CURLOPT_INTERFACE,
3413 conn->interface);
3415 if (result != CURLE_OK)
3416 raiseError(conn, result);
3418 CAMLreturn0;
3421 static void handleKRB4Level(Connection *conn, value option)
3423 CAMLparam1(option);
3424 CURLcode result = CURLE_OK;
3426 switch (Long_val(option))
3428 case 0: /* KRB4_NONE */
3429 result = curl_easy_setopt(conn->connection,
3430 CURLOPT_KRB4LEVEL,
3431 NULL);
3432 break;
3434 case 1: /* KRB4_CLEAR */
3435 result = curl_easy_setopt(conn->connection,
3436 CURLOPT_KRB4LEVEL,
3437 "clear");
3438 break;
3440 case 2: /* KRB4_SAFE */
3441 result = curl_easy_setopt(conn->connection,
3442 CURLOPT_KRB4LEVEL,
3443 "safe");
3444 break;
3446 case 3: /* KRB4_CONFIDENTIAL */
3447 result = curl_easy_setopt(conn->connection,
3448 CURLOPT_KRB4LEVEL,
3449 "confidential");
3450 break;
3452 case 4: /* KRB4_PRIVATE */
3453 result = curl_easy_setopt(conn->connection,
3454 CURLOPT_KRB4LEVEL,
3455 "private");
3456 break;
3458 default:
3459 failwith("Invalid KRB4 Option");
3460 break;
3463 if (result != CURLE_OK)
3464 raiseError(conn, result);
3466 CAMLreturn0;
3469 static void handleProgressFunction(Connection *conn, value option)
3471 CAMLparam1(option);
3472 CURLcode result = CURLE_OK;
3474 if (Tag_val(option) == Closure_tag)
3475 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3476 else
3477 failwith("Not a proper closure");
3479 result = curl_easy_setopt(conn->connection,
3480 CURLOPT_PROGRESSFUNCTION,
3481 progressFunction);
3482 if (result != CURLE_OK)
3483 raiseError(conn, result);
3485 result = curl_easy_setopt(conn->connection,
3486 CURLOPT_PROGRESSDATA,
3487 conn);
3489 if (result != CURLE_OK)
3490 raiseError(conn, result);
3492 CAMLreturn0;
3495 static void handleSSLVerifyPeer(Connection *conn, value option)
3497 CAMLparam1(option);
3498 CURLcode result = CURLE_OK;
3500 result = curl_easy_setopt(conn->connection,
3501 CURLOPT_SSL_VERIFYPEER,
3502 Bool_val(option));
3504 if (result != CURLE_OK)
3505 raiseError(conn, result);
3507 CAMLreturn0;
3510 static void handleCAInfo(Connection *conn, value option)
3512 CAMLparam1(option);
3513 CURLcode result = CURLE_OK;
3515 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3517 if (conn->caInfo != NULL)
3518 free(conn->caInfo);
3520 conn->caInfo = strdup(String_val(option));
3522 result = curl_easy_setopt(conn->connection,
3523 CURLOPT_CAINFO,
3524 conn->caInfo);
3526 if (result != CURLE_OK)
3527 raiseError(conn, result);
3529 CAMLreturn0;
3532 static void handleCAPath(Connection *conn, value option)
3534 CAMLparam1(option);
3535 CURLcode result = CURLE_OK;
3537 Store_field(conn->ocamlValues, OcamlCAPath, option);
3539 if (conn->caPath != NULL)
3540 free(conn->caPath);
3542 conn->caPath = strdup(String_val(option));
3544 result = curl_easy_setopt(conn->connection,
3545 CURLOPT_CAPATH,
3546 conn->caPath);
3548 if (result != CURLE_OK)
3549 raiseError(conn, result);
3551 CAMLreturn0;
3554 static void handleFileTime(Connection *conn, value option)
3556 CAMLparam1(option);
3557 CURLcode result = CURLE_OK;
3559 result = curl_easy_setopt(conn->connection,
3560 CURLOPT_FILETIME,
3561 Bool_val(option));
3563 if (result != CURLE_OK)
3564 raiseError(conn, result);
3566 CAMLreturn0;
3569 static void handleMaxRedirs(Connection *conn, value option)
3571 CAMLparam1(option);
3572 CURLcode result = CURLE_OK;
3574 result = curl_easy_setopt(conn->connection,
3575 CURLOPT_MAXREDIRS,
3576 Long_val(option));
3578 if (result != CURLE_OK)
3579 raiseError(conn, result);
3581 CAMLreturn0;
3584 static void handleMaxConnects(Connection *conn, value option)
3586 CAMLparam1(option);
3587 CURLcode result = CURLE_OK;
3589 result = curl_easy_setopt(conn->connection,
3590 CURLOPT_MAXCONNECTS,
3591 Long_val(option));
3593 if (result != CURLE_OK)
3594 raiseError(conn, result);
3596 CAMLreturn0;
3599 static void handleClosePolicy(Connection *conn, value option)
3601 CAMLparam1(option);
3602 CURLcode result = CURLE_OK;
3604 switch (Long_val(option))
3606 case 0: /* CLOSEPOLICY_OLDEST */
3607 result = curl_easy_setopt(conn->connection,
3608 CURLOPT_CLOSEPOLICY,
3609 CURLCLOSEPOLICY_OLDEST);
3610 break;
3612 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3613 result = curl_easy_setopt(conn->connection,
3614 CURLOPT_CLOSEPOLICY,
3615 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3616 break;
3618 default:
3619 failwith("Invalid CLOSEPOLICY Option");
3620 break;
3623 if (result != CURLE_OK)
3624 raiseError(conn, result);
3626 CAMLreturn0;
3629 static void handleFreshConnect(Connection *conn, value option)
3631 CAMLparam1(option);
3632 CURLcode result = CURLE_OK;
3634 result = curl_easy_setopt(conn->connection,
3635 CURLOPT_FRESH_CONNECT,
3636 Bool_val(option));
3638 if (result != CURLE_OK)
3639 raiseError(conn, result);
3641 CAMLreturn0;
3644 static void handleForbidReuse(Connection *conn, value option)
3646 CAMLparam1(option);
3647 CURLcode result = CURLE_OK;
3649 result = curl_easy_setopt(conn->connection,
3650 CURLOPT_FORBID_REUSE,
3651 Bool_val(option));
3653 if (result != CURLE_OK)
3654 raiseError(conn, result);
3656 CAMLreturn0;
3659 static void handleRandomFile(Connection *conn, value option)
3661 CAMLparam1(option);
3662 CURLcode result = CURLE_OK;
3664 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3666 if (conn->randomFile != NULL)
3667 free(conn->randomFile);
3669 conn->randomFile = strdup(String_val(option));
3671 result = curl_easy_setopt(conn->connection,
3672 CURLOPT_RANDOM_FILE,
3673 conn->randomFile);
3675 if (result != CURLE_OK)
3676 raiseError(conn, result);
3678 CAMLreturn0;
3681 static void handleEGDSocket(Connection *conn, value option)
3683 CAMLparam1(option);
3684 CURLcode result = CURLE_OK;
3686 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3688 if (conn->egdSocket != NULL)
3689 free(conn->egdSocket);
3691 conn->egdSocket = strdup(String_val(option));
3693 result = curl_easy_setopt(conn->connection,
3694 CURLOPT_EGDSOCKET,
3695 conn->egdSocket);
3697 if (result != CURLE_OK)
3698 raiseError(conn, result);
3700 CAMLreturn0;
3703 static void handleConnectTimeout(Connection *conn, value option)
3705 CAMLparam1(option);
3706 CURLcode result = CURLE_OK;
3708 result = curl_easy_setopt(conn->connection,
3709 CURLOPT_CONNECTTIMEOUT,
3710 Long_val(option));
3712 if (result != CURLE_OK)
3713 raiseError(conn, result);
3715 CAMLreturn0;
3718 static void handleHTTPGet(Connection *conn, value option)
3720 CAMLparam1(option);
3721 CURLcode result = CURLE_OK;
3723 result = curl_easy_setopt(conn->connection,
3724 CURLOPT_HTTPGET,
3725 Bool_val(option));
3727 if (result != CURLE_OK)
3728 raiseError(conn, result);
3730 CAMLreturn0;
3733 static void handleSSLVerifyHost(Connection *conn, value option)
3735 CAMLparam1(option);
3736 CURLcode result = CURLE_OK;
3738 switch (Long_val(option))
3740 case 0: /* SSLVERIFYHOST_EXISTENCE */
3741 result = curl_easy_setopt(conn->connection,
3742 CURLOPT_SSL_VERIFYHOST,
3744 break;
3746 case 1: /* SSLVERIFYHOST_HOSTNAME */
3747 result = curl_easy_setopt(conn->connection,
3748 CURLOPT_SSL_VERIFYHOST,
3750 break;
3752 default:
3753 failwith("Invalid SSLVERIFYHOST Option");
3754 break;
3757 if (result != CURLE_OK)
3758 raiseError(conn, result);
3760 CAMLreturn0;
3763 static void handleCookieJar(Connection *conn, value option)
3765 CAMLparam1(option);
3766 CURLcode result = CURLE_OK;
3768 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3770 if (conn->cookieJar != NULL)
3771 free(conn->cookieJar);
3773 conn->cookieJar = strdup(String_val(option));
3775 result = curl_easy_setopt(conn->connection,
3776 CURLOPT_COOKIEJAR,
3777 conn->cookieJar);
3779 if (result != CURLE_OK)
3780 raiseError(conn, result);
3782 CAMLreturn0;
3785 static void handleSSLCipherList(Connection *conn, value option)
3787 CAMLparam1(option);
3788 CURLcode result = CURLE_OK;
3790 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3792 if (conn->sslCipherList != NULL)
3793 free(conn->sslCipherList);
3795 conn->sslCipherList = strdup(String_val(option));
3797 result = curl_easy_setopt(conn->connection,
3798 CURLOPT_SSL_CIPHER_LIST,
3799 conn->sslCipherList);
3801 if (result != CURLE_OK)
3802 raiseError(conn, result);
3804 CAMLreturn0;
3807 static void handleHTTPVersion(Connection *conn, value option)
3809 CAMLparam1(option);
3810 CURLcode result = CURLE_OK;
3812 switch (Long_val(option))
3814 case 0: /* HTTP_VERSION_NONE */
3815 result = curl_easy_setopt(conn->connection,
3816 CURLOPT_HTTP_VERSION,
3817 CURL_HTTP_VERSION_NONE);
3818 break;
3820 case 1: /* HTTP_VERSION_1_0 */
3821 result = curl_easy_setopt(conn->connection,
3822 CURLOPT_HTTP_VERSION,
3823 CURL_HTTP_VERSION_1_0);
3824 break;
3826 case 2: /* HTTP_VERSION_1_1 */
3827 result = curl_easy_setopt(conn->connection,
3828 CURLOPT_HTTP_VERSION,
3829 CURL_HTTP_VERSION_1_1);
3830 break;
3832 default:
3833 failwith("Invalid HTTP_VERSION Option");
3834 break;
3837 if (result != CURLE_OK)
3838 raiseError(conn, result);
3840 CAMLreturn0;
3843 static void handleFTPUseEPSV(Connection *conn, value option)
3845 CAMLparam1(option);
3846 CURLcode result = CURLE_OK;
3848 result = curl_easy_setopt(conn->connection,
3849 CURLOPT_FTP_USE_EPSV,
3850 Bool_val(option));
3852 if (result != CURLE_OK)
3853 raiseError(conn, result);
3855 CAMLreturn0;
3858 static void handleDNSCacheTimeout(Connection *conn, value option)
3860 CAMLparam1(option);
3861 CURLcode result = CURLE_OK;
3863 result = curl_easy_setopt(conn->connection,
3864 CURLOPT_DNS_CACHE_TIMEOUT,
3865 Long_val(option));
3867 if (result != CURLE_OK)
3868 raiseError(conn, result);
3870 CAMLreturn0;
3873 static void handleDNSUseGlobalCache(Connection *conn, value option)
3875 CAMLparam1(option);
3876 CURLcode result = CURLE_OK;
3878 result = curl_easy_setopt(conn->connection,
3879 CURLOPT_DNS_USE_GLOBAL_CACHE,
3880 Bool_val(option));
3882 if (result != CURLE_OK)
3883 raiseError(conn, result);
3885 CAMLreturn0;
3888 static void handleDebugFunction(Connection *conn, value option)
3890 CAMLparam1(option);
3891 CURLcode result = CURLE_OK;
3893 if (Tag_val(option) == Closure_tag)
3894 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3895 else
3896 failwith("Not a proper closure");
3898 result = curl_easy_setopt(conn->connection,
3899 CURLOPT_DEBUGFUNCTION,
3900 debugFunction);
3901 if (result != CURLE_OK)
3902 raiseError(conn, result);
3904 result = curl_easy_setopt(conn->connection,
3905 CURLOPT_DEBUGDATA,
3906 conn);
3908 if (result != CURLE_OK)
3909 raiseError(conn, result);
3911 CAMLreturn0;
3914 static void handlePrivate(Connection *conn, value option)
3916 #if HAVE_DECL_CURLOPT_PRIVATE
3917 CAMLparam1(option);
3918 CURLcode result = CURLE_OK;
3920 Store_field(conn->ocamlValues, OcamlPrivate, option);
3922 if (conn->private != NULL)
3923 free(conn->private);
3925 conn->private = strdup(String_val(option));
3927 result = curl_easy_setopt(conn->connection,
3928 CURLOPT_PRIVATE,
3929 conn->private);
3931 if (result != CURLE_OK)
3932 raiseError(conn, result);
3934 CAMLreturn0;
3935 #else
3936 #warning "libcurl does not implement CURLOPT_PRIVATE"
3937 failwith("libcurl does not implement CURLOPT_PRIVATE");
3938 #endif
3941 static void handleHTTP200Aliases(Connection *conn, value option)
3943 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3944 CAMLparam1(option);
3945 CAMLlocal1(listIter);
3946 CURLcode result = CURLE_OK;
3947 char *str;
3949 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3951 if (conn->http200Aliases != NULL)
3952 free_curl_slist(conn->http200Aliases);
3954 conn->http200Aliases = NULL;
3956 listIter = option;
3958 while (!Is_long(listIter))
3960 if (Tag_val(Field(listIter, 0)) != String_tag)
3961 failwith("Not a string");
3963 str = strdup(String_val(Field(listIter, 0)));
3965 conn->http200Aliases = curl_slist_append(conn->http200Aliases, str);
3967 listIter = Field(listIter, 1);
3970 result = curl_easy_setopt(conn->connection,
3971 CURLOPT_HTTP200ALIASES,
3972 conn->http200Aliases);
3974 if (result != CURLE_OK)
3975 raiseError(conn, result);
3977 CAMLreturn0;
3978 #else
3979 #warning "libcurl does not implement CURLOPT_HTTP200ALIASES"
3980 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
3981 #endif
3984 static void handleUnrestrictedAuth(Connection *conn, value option)
3986 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
3987 CAMLparam1(option);
3988 CURLcode result = CURLE_OK;
3990 result = curl_easy_setopt(conn->connection,
3991 CURLOPT_UNRESTRICTED_AUTH,
3992 Bool_val(option));
3994 if (result != CURLE_OK)
3995 raiseError(conn, result);
3997 CAMLreturn0;
3998 #else
3999 #warning "libcurl does not implement CURLOPT_UNRESTRICTED_AUTH"
4000 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4001 #endif
4004 static void handleFTPUseEPRT(Connection *conn, value option)
4006 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4007 CAMLparam1(option);
4008 CURLcode result = CURLE_OK;
4010 result = curl_easy_setopt(conn->connection,
4011 CURLOPT_FTP_USE_EPRT,
4012 Bool_val(option));
4014 if (result != CURLE_OK)
4015 raiseError(conn, result);
4017 CAMLreturn0;
4018 #else
4019 #warning "libcurl does not implement CURLOPT_FTP_USE_EPRT"
4020 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4021 #endif
4024 static void handleHTTPAuth(Connection *conn, value option)
4026 #if HAVE_DECL_CURLOPT_HTTPAUTH
4027 CAMLparam1(option);
4028 CAMLlocal1(listIter);
4029 CURLcode result = CURLE_OK;
4030 long auth = CURLAUTH_NONE;
4032 listIter = option;
4034 while (!Is_long(listIter))
4036 switch (Long_val(Field(listIter, 0)))
4038 case 0: /* CURLAUTH_BASIC */
4039 auth |= CURLAUTH_BASIC;
4040 break;
4042 case 1: /* CURLAUTH_DIGEST */
4043 auth |= CURLAUTH_DIGEST;
4044 break;
4046 case 2: /* CURLAUTH_GSSNEGOTIATE */
4047 auth |= CURLAUTH_GSSNEGOTIATE;
4048 break;
4050 case 3: /* CURLAUTH_NTLM */
4051 auth |= CURLAUTH_NTLM;
4052 break;
4054 case 4: /* CURLAUTH_ANY */
4055 auth |= CURLAUTH_ANY;
4056 break;
4058 case 5: /* CURLAUTH_ANYSAFE */
4059 auth |= CURLAUTH_ANYSAFE;
4060 break;
4062 default:
4063 failwith("Invalid HTTPAUTH Value");
4064 break;
4067 listIter = Field(listIter, 1);
4070 result = curl_easy_setopt(conn->connection,
4071 CURLOPT_HTTPAUTH,
4072 auth);
4074 if (result != CURLE_OK)
4075 raiseError(conn, result);
4077 CAMLreturn0;
4078 #else
4079 #warning "libcurl does not implement CURLOPT_HTTPAUTH"
4080 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4081 #endif
4084 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4086 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4087 CAMLparam1(option);
4088 CURLcode result = CURLE_OK;
4090 result = curl_easy_setopt(conn->connection,
4091 CURLOPT_FTP_CREATE_MISSING_DIRS,
4092 Bool_val(option));
4094 if (result != CURLE_OK)
4095 raiseError(conn, result);
4097 CAMLreturn0;
4098 #else
4099 #warning "libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS"
4100 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4101 #endif
4104 static void handleProxyAuth(Connection *conn, value option)
4106 #if HAVE_DECL_CURLOPT_PROXYAUTH
4107 CAMLparam1(option);
4108 CAMLlocal1(listIter);
4109 CURLcode result = CURLE_OK;
4110 long auth = CURLAUTH_NONE;
4112 listIter = option;
4114 while (!Is_long(listIter))
4116 switch (Long_val(Field(listIter, 0)))
4118 case 0: /* CURLAUTH_BASIC */
4119 auth |= CURLAUTH_BASIC;
4120 break;
4122 case 1: /* CURLAUTH_DIGEST */
4123 auth |= CURLAUTH_DIGEST;
4124 break;
4126 case 2: /* CURLAUTH_GSSNEGOTIATE */
4127 auth |= CURLAUTH_GSSNEGOTIATE;
4128 break;
4130 case 3: /* CURLAUTH_NTLM */
4131 auth |= CURLAUTH_NTLM;
4132 break;
4134 case 4: /* CURLAUTH_ANY */
4135 auth |= CURLAUTH_ANY;
4136 break;
4138 case 5: /* CURLAUTH_ANYSAFE */
4139 auth |= CURLAUTH_ANYSAFE;
4140 break;
4142 default:
4143 failwith("Invalid HTTPAUTH Value");
4144 break;
4147 listIter = Field(listIter, 1);
4150 result = curl_easy_setopt(conn->connection,
4151 CURLOPT_PROXYAUTH,
4152 auth);
4154 if (result != CURLE_OK)
4155 raiseError(conn, result);
4157 CAMLreturn0;
4158 #else
4159 #warning "libcurl does not implement CURLOPT_PROXYAUTH"
4160 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4161 #endif
4164 static void handleFTPResponseTimeout(Connection *conn, value option)
4166 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4167 CAMLparam1(option);
4168 CURLcode result = CURLE_OK;
4170 result = curl_easy_setopt(conn->connection,
4171 CURLOPT_FTP_RESPONSE_TIMEOUT,
4172 Long_val(option));
4174 if (result != CURLE_OK)
4175 raiseError(conn, result);
4177 CAMLreturn0;
4178 #else
4179 #warning "libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT"
4180 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4181 #endif
4184 static void handleIPResolve(Connection *conn, value option)
4186 #if HAVE_DECL_CURLOPT_IPRESOLVE
4187 CAMLparam1(option);
4188 CURLcode result = CURLE_OK;
4190 switch (Long_val(option))
4192 case 0: /* CURL_IPRESOLVE_WHATEVER */
4193 result = curl_easy_setopt(conn->connection,
4194 CURLOPT_IPRESOLVE,
4195 CURL_IPRESOLVE_WHATEVER);
4196 break;
4198 case 1: /* CURL_IPRESOLVE_V4 */
4199 result = curl_easy_setopt(conn->connection,
4200 CURLOPT_IPRESOLVE,
4201 CURL_IPRESOLVE_V4);
4202 break;
4204 case 2: /* CURL_IPRESOLVE_V6 */
4205 result = curl_easy_setopt(conn->connection,
4206 CURLOPT_IPRESOLVE,
4207 CURL_IPRESOLVE_V6);
4208 break;
4210 default:
4211 failwith("Invalid IPRESOLVE Value");
4212 break;
4215 if (result != CURLE_OK)
4216 raiseError(conn, result);
4218 CAMLreturn0;
4219 #else
4220 #warning "libcurl does not implement CURLOPT_IPRESOLVE"
4221 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4222 #endif
4225 static void handleMaxFileSize(Connection *conn, value option)
4227 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4228 CAMLparam1(option);
4229 CURLcode result = CURLE_OK;
4231 result = curl_easy_setopt(conn->connection,
4232 CURLOPT_MAXFILESIZE,
4233 Int32_val(option));
4235 if (result != CURLE_OK)
4236 raiseError(conn, result);
4238 CAMLreturn0;
4239 #else
4240 #warning "libcurl does not implement CURLOPT_MAXFILESIZE"
4241 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4242 #endif
4245 static void handleInFileSizeLarge(Connection *conn, value option)
4247 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4248 CAMLparam1(option);
4249 CURLcode result = CURLE_OK;
4251 result = curl_easy_setopt(conn->connection,
4252 CURLOPT_INFILESIZE_LARGE,
4253 Int64_val(option));
4255 if (result != CURLE_OK)
4256 raiseError(conn, result);
4258 CAMLreturn0;
4259 #else
4260 #warning("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4261 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4262 #endif
4265 static void handleResumeFromLarge(Connection *conn, value option)
4267 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4268 CAMLparam1(option);
4269 CURLcode result = CURLE_OK;
4271 result = curl_easy_setopt(conn->connection,
4272 CURLOPT_RESUME_FROM_LARGE,
4273 Int64_val(option));
4275 if (result != CURLE_OK)
4276 raiseError(conn, result);
4278 CAMLreturn0;
4279 #else
4280 #warning("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4281 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4282 #endif
4285 static void handleMaxFileSizeLarge(Connection *conn, value option)
4287 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4288 CAMLparam1(option);
4289 CURLcode result = CURLE_OK;
4291 result = curl_easy_setopt(conn->connection,
4292 CURLOPT_MAXFILESIZE_LARGE,
4293 Int64_val(option));
4295 if (result != CURLE_OK)
4296 raiseError(conn, result);
4298 CAMLreturn0;
4299 #else
4300 #warning "libcurl does not implement CURLOPT_MAXFILESIZE_LARGE"
4301 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4302 #endif
4305 static void handleNETRCFile(Connection *conn, value option)
4307 #if HAVE_DECL_CURLOPT_NETRC_FILE
4308 CAMLparam1(option);
4309 CURLcode result = CURLE_OK;
4311 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4313 if (conn->netrcFile != NULL)
4314 free(conn->netrcFile);
4316 conn->netrcFile = strdup(String_val(option));
4318 result = curl_easy_setopt(conn->connection,
4319 CURLOPT_NETRC_FILE,
4320 conn->netrcFile);
4322 if (result != CURLE_OK)
4323 raiseError(conn, result);
4325 CAMLreturn0;
4326 #else
4327 #warning "libcurl does not implement CURLOPT_NETRC_FILE"
4328 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4329 #endif
4332 static void handleFTPSSL(Connection *conn, value option)
4334 #if HAVE_DECL_CURLOPT_FTP_SSL
4335 CAMLparam1(option);
4336 CURLcode result = CURLE_OK;
4338 switch (Long_val(option))
4340 case 0: /* CURLFTPSSL_NONE */
4341 result = curl_easy_setopt(conn->connection,
4342 CURLOPT_FTP_SSL,
4343 CURLFTPSSL_NONE);
4344 break;
4346 case 1: /* CURLFTPSSL_TRY */
4347 result = curl_easy_setopt(conn->connection,
4348 CURLOPT_FTP_SSL,
4349 CURLFTPSSL_TRY);
4350 break;
4352 case 2: /* CURLFTPSSL_CONTROL */
4353 result = curl_easy_setopt(conn->connection,
4354 CURLOPT_FTP_SSL,
4355 CURLFTPSSL_CONTROL);
4356 break;
4358 case 3: /* CURLFTPSSL_ALL */
4359 result = curl_easy_setopt(conn->connection,
4360 CURLOPT_FTP_SSL,
4361 CURLFTPSSL_ALL);
4362 break;
4364 default:
4365 failwith("Invalid FTP_SSL Value");
4366 break;
4369 if (result != CURLE_OK)
4370 raiseError(conn, result);
4372 CAMLreturn0;
4373 #else
4374 #warning "libcurl does not implement CURLOPT_FTP_SSL"
4375 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4376 #endif
4379 static void handlePostFieldSizeLarge(Connection *conn, value option)
4381 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4382 CAMLparam1(option);
4383 CURLcode result = CURLE_OK;
4385 result = curl_easy_setopt(conn->connection,
4386 CURLOPT_POSTFIELDSIZE_LARGE,
4387 Int64_val(option));
4389 if (result != CURLE_OK)
4390 raiseError(conn, result);
4392 CAMLreturn0;
4393 #else
4394 #warning "libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE"
4395 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4396 #endif
4399 static void handleTCPNoDelay(Connection *conn, value option)
4401 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4402 CAMLparam1(option);
4403 CURLcode result = CURLE_OK;
4405 result = curl_easy_setopt(conn->connection,
4406 CURLOPT_TCP_NODELAY,
4407 Bool_val(option));
4409 if (result != CURLE_OK)
4410 raiseError(conn, result);
4412 CAMLreturn0;
4413 #else
4414 #warning "libcurl does not implement CURLOPT_TCP_NODELAY"
4415 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4416 #endif
4419 static void handleFTPSSLAuth(Connection *conn, value option)
4421 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4422 CAMLparam1(option);
4423 CURLcode result = CURLE_OK;
4425 switch (Long_val(option))
4427 case 0: /* CURLFTPAUTH_DEFAULT */
4428 result = curl_easy_setopt(conn->connection,
4429 CURLOPT_FTPSSLAUTH,
4430 CURLFTPAUTH_DEFAULT);
4431 break;
4433 case 1: /* CURLFTPAUTH_SSL */
4434 result = curl_easy_setopt(conn->connection,
4435 CURLOPT_FTPSSLAUTH,
4436 CURLFTPAUTH_SSL);
4437 break;
4439 case 2: /* CURLFTPAUTH_TLS */
4440 result = curl_easy_setopt(conn->connection,
4441 CURLOPT_FTPSSLAUTH,
4442 CURLFTPAUTH_TLS);
4443 break;
4445 default:
4446 failwith("Invalid FTPSSLAUTH value");
4447 break;
4450 if (result != CURLE_OK)
4451 raiseError(conn, result);
4453 CAMLreturn0;
4454 #else
4455 #warning "libcurl does not implement CURLOPT_FTPSSLAUTH"
4456 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4457 #endif
4460 static void handleIOCTLFunction(Connection *conn, value option)
4462 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4463 CAMLparam1(option);
4464 CURLcode result = CURLE_OK;
4466 if (Tag_val(option) == Closure_tag)
4467 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4468 else
4469 failwith("Not a proper closure");
4471 result = curl_easy_setopt(conn->connection,
4472 CURLOPT_IOCTLFUNCTION,
4473 ioctlFunction);
4474 if (result != CURLE_OK)
4475 raiseError(conn, result);
4477 result = curl_easy_setopt(conn->connection,
4478 CURLOPT_DEBUGDATA,
4479 conn);
4481 if (result != CURLE_OK)
4482 raiseError(conn, result);
4484 CAMLreturn0;
4485 #else
4486 #warning "libcurl does not implement CURLOPT_IOCTLFUNCTION"
4487 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4488 #endif
4491 static void handleFTPAccount(Connection *conn, value option)
4493 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4494 CAMLparam1(option);
4495 CURLcode result = CURLE_OK;
4497 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4499 if (conn->ftpaccount != NULL)
4500 free(conn->ftpaccount);
4502 conn->ftpaccount = strdup(String_val(option));
4504 result = curl_easy_setopt(conn->connection,
4505 CURLOPT_FTP_ACCOUNT,
4506 conn->ftpaccount);
4508 if (result != CURLE_OK)
4509 raiseError(conn, result);
4511 CAMLreturn0;
4512 #else
4513 #warning "libcurl does not implement CURLOPT_FTP_ACCOUNT"
4514 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4515 #endif
4518 static void handleCookieList(Connection *conn, value option)
4520 #if HAVE_DECL_CURLOPT_COOKIELIST
4521 CAMLparam1(option);
4522 CURLcode result = CURLE_OK;
4524 Store_field(conn->ocamlValues, OcamlCookieList, option);
4526 if (conn->cookielist != NULL)
4527 free(conn->cookielist);
4529 conn->cookielist = strdup(String_val(option));
4531 result = curl_easy_setopt(conn->connection,
4532 CURLOPT_COOKIELIST,
4533 conn->cookielist);
4535 if (result != CURLE_OK)
4536 raiseError(conn, result);
4538 CAMLreturn0;
4539 #else
4540 #warning "libcurl does not implement CURLOPT_COOKIELIST"
4541 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4542 #endif
4545 static void handleIgnoreContentLength(Connection *conn, value option)
4547 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4548 CAMLparam1(option);
4549 CURLcode result = CURLE_OK;
4551 result = curl_easy_setopt(conn->connection,
4552 CURLOPT_IGNORE_CONTENT_LENGTH,
4553 Bool_val(option));
4555 if (result != CURLE_OK)
4556 raiseError(conn, result);
4558 CAMLreturn0;
4559 #else
4560 #warning "libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH"
4561 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4562 #endif
4565 static void handleFTPSkipPASVIP(Connection *conn, value option)
4567 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4568 CAMLparam1(option);
4569 CURLcode result = CURLE_OK;
4571 result = curl_easy_setopt(conn->connection,
4572 CURLOPT_FTP_SKIP_PASV_IP,
4573 Bool_val(option));
4575 if (result != CURLE_OK)
4576 raiseError(conn, result);
4578 CAMLreturn0;
4579 #else
4580 #warning "libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP"
4581 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4582 #endif
4585 static void handleFTPFileMethod(Connection *conn, value option)
4587 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4588 CAMLparam1(option);
4589 CURLcode result = CURLE_OK;
4591 switch (Long_val(option))
4593 case 0: /* CURLFTPMETHOD_DEFAULT */
4594 result = curl_easy_setopt(conn->connection,
4595 CURLOPT_FTP_FILEMETHOD,
4596 CURLFTPMETHOD_DEFAULT);
4597 break;
4599 case 1: /* CURLFTMETHOD_MULTICWD */
4600 result = curl_easy_setopt(conn->connection,
4601 CURLOPT_FTP_FILEMETHOD,
4602 CURLFTPMETHOD_MULTICWD);
4603 break;
4605 case 2: /* CURLFTPMETHOD_NOCWD */
4606 result = curl_easy_setopt(conn->connection,
4607 CURLOPT_FTP_FILEMETHOD,
4608 CURLFTPMETHOD_NOCWD);
4609 break;
4611 case 3: /* CURLFTPMETHOD_SINGLECWD */
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_FILEMETHOD,
4614 CURLFTPMETHOD_SINGLECWD);
4616 default:
4617 failwith("Invalid FTP_FILEMETHOD value");
4618 break;
4621 if (result != CURLE_OK)
4622 raiseError(conn, result);
4624 CAMLreturn0;
4625 #else
4626 #warning "libcurl does not implement CURLOPT_FTP_FILEMETHOD"
4627 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4628 #endif
4631 static void handleLocalPort(Connection *conn, value option)
4633 #if HAVE_DECL_CURLOPT_LOCALPORT
4634 CAMLparam1(option);
4635 CURLcode result = CURLE_OK;
4637 result = curl_easy_setopt(conn->connection,
4638 CURLOPT_LOCALPORT,
4639 Long_val(option));
4641 if (result != CURLE_OK)
4642 raiseError(conn, result);
4644 CAMLreturn0;
4645 #else
4646 #warning "libcurl does not implement CURLOPT_LOCALPORT"
4647 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4648 #endif
4651 static void handleLocalPortRange(Connection *conn, value option)
4653 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4654 CAMLparam1(option);
4655 CURLcode result = CURLE_OK;
4657 result = curl_easy_setopt(conn->connection,
4658 CURLOPT_LOCALPORTRANGE,
4659 Long_val(option));
4661 if (result != CURLE_OK)
4662 raiseError(conn, result);
4664 CAMLreturn0;
4665 #else
4666 #warning "libcurl does not implement CURLOPT_LOCALPORTRANGE"
4667 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4668 #endif
4671 static void handleConnectOnly(Connection *conn, value option)
4673 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4674 CAMLparam1(option);
4675 CURLcode result = CURLE_OK;
4677 result = curl_easy_setopt(conn->connection,
4678 CURLOPT_CONNECT_ONLY,
4679 Bool_val(option));
4681 if (result != CURLE_OK)
4682 raiseError(conn, result);
4684 CAMLreturn0;
4685 #else
4686 #warning "libcurl does not implement CURLOPT_CONNECT_ONLY"
4687 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4688 #endif
4691 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4693 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4694 CAMLparam1(option);
4695 CURLcode result = CURLE_OK;
4697 result = curl_easy_setopt(conn->connection,
4698 CURLOPT_MAX_SEND_SPEED_LARGE,
4699 Int64_val(option));
4701 if (result != CURLE_OK)
4702 raiseError(conn, result);
4704 CAMLreturn0;
4705 #else
4706 #warning "libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE"
4707 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4708 #endif
4711 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4713 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4714 CAMLparam1(option);
4715 CURLcode result = CURLE_OK;
4717 result = curl_easy_setopt(conn->connection,
4718 CURLOPT_MAX_RECV_SPEED_LARGE,
4719 Int64_val(option));
4721 if (result != CURLE_OK)
4722 raiseError(conn, result);
4724 CAMLreturn0;
4725 #else
4726 #warning "libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE"
4727 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4728 #endif
4731 static void handleFTPAlternativeToUser(Connection *conn, value option)
4733 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4734 CAMLparam1(option);
4735 CURLcode result = CURLE_OK;
4737 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4739 if (conn->ftpAlternativeToUser != NULL)
4740 free(conn->ftpAlternativeToUser);
4742 conn->ftpAlternativeToUser = strdup(String_val(option));
4744 result = curl_easy_setopt(conn->connection,
4745 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4746 conn->ftpAlternativeToUser);
4748 if (result != CURLE_OK)
4749 raiseError(conn, result);
4751 CAMLreturn0;
4752 #else
4753 #warning "libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER"
4754 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4755 #endif
4758 static void handleSSLSessionIdCache(Connection *conn, value option)
4760 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4761 CAMLparam1(option);
4762 CURLcode result = CURLE_OK;
4764 result = curl_easy_setopt(conn->connection,
4765 CURLOPT_SSL_SESSIONID_CACHE,
4766 Bool_val(option));
4768 if (result != CURLE_OK)
4769 raiseError(conn, result);
4771 CAMLreturn0;
4772 #else
4773 #warning "libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE"
4774 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4775 #endif
4778 static void handleSSHAuthTypes(Connection *conn, value option)
4780 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4781 CAMLparam1(option);
4782 CAMLlocal1(listIter);
4783 CURLcode result = CURLE_OK;
4784 long authTypes = CURLSSH_AUTH_NONE;
4786 listIter = option;
4788 while (!Is_long(listIter))
4790 switch (Long_val(Field(listIter, 0)))
4792 case 0: /* CURLSSH_AUTH_ANY */
4793 authTypes |= CURLSSH_AUTH_ANY;
4794 break;
4796 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4797 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4798 break;
4800 case 2: /* CURLSSH_AUTH_PASSWORD */
4801 authTypes |= CURLSSH_AUTH_PASSWORD;
4802 break;
4804 case 3: /* CURLSSH_AUTH_HOST */
4805 authTypes |= CURLSSH_AUTH_HOST;
4806 break;
4808 case 4: /* CURLSSH_AUTH_KEYBOARD */
4809 authTypes |= CURLSSH_AUTH_KEYBOARD;
4810 break;
4812 default:
4813 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4814 break;
4817 listIter = Field(listIter, 1);
4820 result = curl_easy_setopt(conn->connection,
4821 CURLOPT_SSH_AUTH_TYPES,
4822 authTypes);
4824 if (result != CURLE_OK)
4825 raiseError(conn, result);
4827 CAMLreturn0;
4828 #else
4829 #warning "libcurl does not implement CURLOPT_SSH_AUTH_TYPES"
4830 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4831 #endif
4834 static void handleSSHPublicKeyFile(Connection *conn, value option)
4836 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4837 CAMLparam1(option);
4838 CURLcode result = CURLE_OK;
4840 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4842 if (conn->sshPublicKeyFile != NULL)
4843 free(conn->sshPublicKeyFile);
4845 conn->sshPublicKeyFile = strdup(String_val(option));
4847 result = curl_easy_setopt(conn->connection,
4848 CURLOPT_SSH_PUBLIC_KEYFILE,
4849 conn->sshPublicKeyFile);
4851 if (result != CURLE_OK)
4852 raiseError(conn, result);
4854 CAMLreturn0;
4855 #else
4856 #warning "libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE"
4857 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4858 #endif
4861 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4863 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4864 CAMLparam1(option);
4865 CURLcode result = CURLE_OK;
4867 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4869 if (conn->sshPrivateKeyFile != NULL)
4870 free(conn->sshPrivateKeyFile);
4872 conn->sshPrivateKeyFile = strdup(String_val(option));
4874 result = curl_easy_setopt(conn->connection,
4875 CURLOPT_SSH_PRIVATE_KEYFILE,
4876 conn->sshPrivateKeyFile);
4878 if (result != CURLE_OK)
4879 raiseError(conn, result);
4881 CAMLreturn0;
4882 #else
4883 #warning "libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE"
4884 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4885 #endif
4888 static void handleFTPSSLCCC(Connection *conn, value option)
4890 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4891 CAMLparam1(option);
4892 CURLcode result = CURLE_OK;
4894 switch (Long_val(option))
4896 case 0: /* CURLFTPSSL_CCC_NONE */
4897 result = curl_easy_setopt(conn->connection,
4898 CURLOPT_FTP_SSL_CCC,
4899 CURLFTPSSL_CCC_NONE);
4900 break;
4902 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4903 result = curl_easy_setopt(conn->connection,
4904 CURLOPT_FTP_SSL_CCC,
4905 CURLFTPSSL_CCC_PASSIVE);
4906 break;
4908 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4909 result = curl_easy_setopt(conn->connection,
4910 CURLOPT_FTP_SSL_CCC,
4911 CURLFTPSSL_CCC_ACTIVE);
4912 break;
4914 default:
4915 failwith("Invalid FTPSSL_CCC value");
4916 break;
4919 if (result != CURLE_OK)
4920 raiseError(conn, result);
4922 CAMLreturn0;
4923 #else
4924 #warning "libcurl does not implement CURLOPT_FTP_SSL_CCC"
4925 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4926 #endif
4929 static void handleTimeoutMS(Connection *conn, value option)
4931 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4932 CAMLparam1(option);
4933 CURLcode result = CURLE_OK;
4935 result = curl_easy_setopt(conn->connection,
4936 CURLOPT_TIMEOUT_MS,
4937 Long_val(option));
4939 if (result != CURLE_OK)
4940 raiseError(conn, result);
4942 CAMLreturn0;
4943 #else
4944 #warning "libcurl does not implement CURLOPT_TIMEOUT_MS"
4945 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4946 #endif
4949 static void handleConnectTimeoutMS(Connection *conn, value option)
4951 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4952 CAMLparam1(option);
4953 CURLcode result = CURLE_OK;
4955 result = curl_easy_setopt(conn->connection,
4956 CURLOPT_CONNECTTIMEOUT_MS,
4957 Long_val(option));
4959 if (result != CURLE_OK)
4960 raiseError(conn, result);
4962 CAMLreturn0;
4963 #else
4964 #warning "libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS"
4965 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
4966 #endif
4969 static void handleHTTPTransferDecoding(Connection *conn, value option)
4971 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4972 CAMLparam1(option);
4973 CURLcode result = CURLE_OK;
4975 result = curl_easy_setopt(conn->connection,
4976 CURLOPT_HTTP_TRANSFER_DECODING,
4977 Bool_val(option));
4979 if (result != CURLE_OK)
4980 raiseError(conn, result);
4982 CAMLreturn0;
4983 #else
4984 #warning "libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING"
4985 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
4986 #endif
4989 static void handleHTTPContentDecoding(Connection *conn, value option)
4991 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
4992 CAMLparam1(option);
4993 CURLcode result = CURLE_OK;
4995 result = curl_easy_setopt(conn->connection,
4996 CURLOPT_HTTP_CONTENT_DECODING,
4997 Bool_val(option));
4999 if (result != CURLE_OK)
5000 raiseError(conn, result);
5002 CAMLreturn0;
5003 #else
5004 #warning "libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING"
5005 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5006 #endif
5009 static void handleNewFilePerms(Connection *conn, value option)
5011 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5012 CAMLparam1(option);
5013 CURLcode result = CURLE_OK;
5015 result = curl_easy_setopt(conn->connection,
5016 CURLOPT_NEW_FILE_PERMS,
5017 Long_val(option));
5019 if (result != CURLE_OK)
5020 raiseError(conn, result);
5022 CAMLreturn0;
5023 #else
5024 #warning "libcurl does not implement CURLOPT_NEW_FILE_PERMS"
5025 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5026 #endif
5029 static void handleNewDirectoryPerms(Connection *conn, value option)
5031 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5032 CAMLparam1(option);
5033 CURLcode result = CURLE_OK;
5035 result = curl_easy_setopt(conn->connection,
5036 CURLOPT_NEW_DIRECTORY_PERMS,
5037 Long_val(option));
5039 if (result != CURLE_OK)
5040 raiseError(conn, result);
5042 CAMLreturn0;
5043 #else
5044 #warning "libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS"
5045 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5046 #endif
5049 static void handlePost301(Connection *conn, value option)
5051 #if HAVE_DECL_CURLOPT_POST301
5052 CAMLparam1(option);
5053 CURLcode result = CURLE_OK;
5055 result = curl_easy_setopt(conn->connection,
5056 CURLOPT_POST301,
5057 Bool_val(option));
5059 if (result != CURLE_OK)
5060 raiseError(conn, result);
5062 CAMLreturn0;
5063 #else
5064 #warning "libcurl does not implement CURLOPT_POST301"
5065 failwith("libcurl does not implement CURLOPT_POST301");
5066 #endif
5069 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5071 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5072 CAMLparam1(option);
5073 CURLcode result = CURLE_OK;
5075 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5077 if (conn->sshHostPublicKeyMD5 != NULL)
5078 free(conn->sshHostPublicKeyMD5);
5080 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5082 result = curl_easy_setopt(conn->connection,
5083 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5084 conn->sshHostPublicKeyMD5);
5086 if (result != CURLE_OK)
5087 raiseError(conn, result);
5089 CAMLreturn0;
5090 #else
5091 #warning "libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"
5092 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5093 #endif
5096 static void handleCopyPostFields(Connection *conn, value option)
5098 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5099 CAMLparam1(option);
5100 CURLcode result = CURLE_OK;
5102 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5104 if (conn->copyPostFields != NULL)
5105 free(conn->copyPostFields);
5107 conn->copyPostFields = strdup(String_val(option));
5109 result = curl_easy_setopt(conn->connection,
5110 CURLOPT_COPYPOSTFIELDS,
5111 conn->copyPostFields);
5113 if (result != CURLE_OK)
5114 raiseError(conn, result);
5116 CAMLreturn0;
5117 #else
5118 #warning "libcurl does not implement CURLOPT_COPYPOSTFIELDS"
5119 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5120 #endif
5123 static void handleProxyTransferMode(Connection *conn, value option)
5125 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5126 CAMLparam1(option);
5127 CURLcode result = CURLE_OK;
5129 result = curl_easy_setopt(conn->connection,
5130 CURLOPT_PROXY_TRANSFER_MODE,
5131 Bool_val(option));
5133 if (result != CURLE_OK)
5134 raiseError(conn, result);
5136 CAMLreturn0;
5137 #else
5138 #warning "libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE"
5139 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5140 #endif
5143 static void handleSeekFunction(Connection *conn, value option)
5145 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5146 CAMLparam1(option);
5147 CURLcode result = CURLE_OK;
5149 if (Tag_val(option) == Closure_tag)
5150 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5151 else
5152 failwith("Not a proper closure");
5154 result = curl_easy_setopt(conn->connection,
5155 CURLOPT_SEEKFUNCTION,
5156 seekFunction);
5158 if (result != CURLE_OK)
5159 raiseError(conn, result);
5161 result = curl_easy_setopt(conn->connection,
5162 CURLOPT_SEEKDATA,
5163 conn);
5165 if (result != CURLE_OK)
5166 raiseError(conn, result);
5168 CAMLreturn0;
5169 #else
5170 #warning "libcurl does not implement CURLOPT_SEEKFUNCTION"
5171 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5172 #endif
5176 ** curl_easy_setopt helper function
5179 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5181 CAMLparam2(conn, option);
5182 CAMLlocal1(data);
5183 Connection *connection = Connection_val(conn);
5185 checkConnection(connection);
5187 if (Is_long(option))
5189 char error[128];
5191 sprintf(error, "Unimplemented Option: %s",
5192 findOption(unimplementedOptionMap,
5193 (CURLoption)(Long_val(option))));
5195 failwith(error);
5198 if (!Is_block(option))
5199 failwith("Not a block");
5201 if (Wosize_val(option) < 1)
5202 failwith("Insufficient data in block");
5204 data = Field(option, 0);
5206 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5207 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5208 data);
5209 else
5210 failwith("Invalid CURLOPT Option");
5212 CAMLreturn(Val_unit);
5216 ** curl_easy_perform helper function
5219 CAMLprim value helper_curl_easy_perform(value conn)
5221 CAMLparam1(conn);
5222 CURLcode result = CURLE_OK;
5223 Connection *connection = Connection_val(conn);
5225 checkConnection(connection);
5227 enter_blocking_section();
5228 result = curl_easy_perform(connection->connection);
5229 leave_blocking_section();
5231 if (result != CURLE_OK)
5232 raiseError(connection, result);
5234 CAMLreturn(Val_unit);
5238 ** curl_easy_cleanup helper function
5241 CAMLprim value helper_curl_easy_cleanup(value conn)
5243 CAMLparam1(conn);
5244 Connection *connection = Connection_val(conn);
5246 checkConnection(connection);
5248 removeConnection(connection);
5250 CAMLreturn(Val_unit);
5254 ** curl_easy_duphandle helper function
5257 CAMLprim value helper_curl_easy_duphandle(value conn)
5259 CAMLparam1(conn);
5260 CAMLlocal1(result);
5261 Connection *connection = Connection_val(conn);
5263 checkConnection(connection);
5265 result = alloc(1, Abstract_tag);
5266 Store_field(result, 0, (value)duplicateConnection(connection));
5268 CAMLreturn(result);
5272 ** curl_easy_getinfo helper function
5275 enum GetInfoResultType {
5276 StringValue, LongValue, DoubleValue, StringListValue
5279 value convertStringList(struct curl_slist *slist)
5281 CAMLparam0();
5282 CAMLlocal3(result, current, next);
5283 struct curl_slist *p = slist;
5285 result = Val_int(0);
5286 current = Val_int(0);
5287 next = Val_int(0);
5289 while (p != NULL)
5291 next = alloc_tuple(2);
5292 Store_field(next, 0, copy_string(p->data));
5293 Store_field(next, 1, Val_int(0));
5295 if (result == Val_int(0))
5296 result = next;
5298 if (current != Val_int(0))
5299 Store_field(current, 1, next);
5301 current = next;
5303 p = p->next;
5306 curl_slist_free_all(slist);
5308 CAMLreturn(result);
5311 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5313 CAMLparam2(conn, option);
5314 CAMLlocal1(result);
5315 CURLcode curlResult;
5316 Connection *connection = Connection_val(conn);
5317 enum GetInfoResultType resultType;
5318 char *strValue = NULL;
5319 double doubleValue;
5320 long longValue;
5321 struct curl_slist *stringListValue = NULL;
5323 checkConnection(connection);
5325 switch(Long_val(option))
5327 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5328 case 0: /* CURLINFO_EFFECTIVE_URL */
5329 resultType = StringValue;
5331 curlResult = curl_easy_getinfo(connection->connection,
5332 CURLINFO_EFFECTIVE_URL,
5333 &strValue);
5334 break;
5335 #else
5336 #warning "libcurl does not provide CURLINFO_EFFECTIVE_URL"
5337 #endif
5339 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5340 case 1: /* CURLINFO_HTTP_CODE */
5341 case 2: /* CURLINFO_RESPONSE_CODE */
5342 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5343 resultType = LongValue;
5345 curlResult = curl_easy_getinfo(connection->connection,
5346 CURLINFO_RESPONSE_CODE,
5347 &longValue);
5348 #else
5349 resultType = LongValue;
5351 curlResult = curl_easy_getinfo(connection->connection,
5352 CURLINFO_HTTP_CODE,
5353 &longValue);
5354 #endif
5355 break;
5356 #endif
5358 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5359 case 3: /* CURLINFO_TOTAL_TIME */
5360 resultType = DoubleValue;
5362 curlResult = curl_easy_getinfo(connection->connection,
5363 CURLINFO_TOTAL_TIME,
5364 &doubleValue);
5365 break;
5366 #endif
5368 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5369 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5370 resultType = DoubleValue;
5372 curlResult = curl_easy_getinfo(connection->connection,
5373 CURLINFO_NAMELOOKUP_TIME,
5374 &doubleValue);
5375 break;
5376 #endif
5378 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5379 case 5: /* CURLINFO_CONNECT_TIME */
5380 resultType = DoubleValue;
5382 curlResult = curl_easy_getinfo(connection->connection,
5383 CURLINFO_CONNECT_TIME,
5384 &doubleValue);
5385 break;
5386 #endif
5388 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5389 case 6: /* CURLINFO_PRETRANSFER_TIME */
5390 resultType = DoubleValue;
5392 curlResult = curl_easy_getinfo(connection->connection,
5393 CURLINFO_PRETRANSFER_TIME,
5394 &doubleValue);
5395 break;
5396 #endif
5398 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5399 case 7: /* CURLINFO_SIZE_UPLOAD */
5400 resultType = DoubleValue;
5402 curlResult = curl_easy_getinfo(connection->connection,
5403 CURLINFO_SIZE_UPLOAD,
5404 &doubleValue);
5405 break;
5406 #endif
5408 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5409 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5410 resultType = DoubleValue;
5412 curlResult = curl_easy_getinfo(connection->connection,
5413 CURLINFO_SIZE_DOWNLOAD,
5414 &doubleValue);
5415 break;
5416 #endif
5418 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5419 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5420 resultType = DoubleValue;
5422 curlResult = curl_easy_getinfo(connection->connection,
5423 CURLINFO_SPEED_DOWNLOAD,
5424 &doubleValue);
5425 break;
5426 #endif
5428 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5429 case 10: /* CURLINFO_SPEED_UPLOAD */
5430 resultType = DoubleValue;
5432 curlResult = curl_easy_getinfo(connection->connection,
5433 CURLINFO_SPEED_UPLOAD,
5434 &doubleValue);
5435 break;
5437 #endif
5439 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5440 case 11: /* CURLINFO_HEADER_SIZE */
5441 resultType = LongValue;
5443 curlResult = curl_easy_getinfo(connection->connection,
5444 CURLINFO_HEADER_SIZE,
5445 &longValue);
5446 break;
5447 #endif
5449 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5450 case 12: /* CURLINFO_REQUEST_SIZE */
5451 resultType = LongValue;
5453 curlResult = curl_easy_getinfo(connection->connection,
5454 CURLINFO_REQUEST_SIZE,
5455 &longValue);
5456 break;
5457 #endif
5459 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5460 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5461 resultType = LongValue;
5463 curlResult = curl_easy_getinfo(connection->connection,
5464 CURLINFO_SSL_VERIFYRESULT,
5465 &longValue);
5466 break;
5467 #endif
5469 #if HAVE_DECL_CURLINFO_FILETIME
5470 case 14: /* CURLINFO_FILETIME */
5471 resultType = DoubleValue;
5473 curlResult = curl_easy_getinfo(connection->connection,
5474 CURLINFO_FILETIME,
5475 &doubleValue);
5476 break;
5477 #endif
5479 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5480 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5481 resultType = DoubleValue;
5483 curlResult = curl_easy_getinfo(connection->connection,
5484 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5485 &doubleValue);
5486 break;
5487 #endif
5489 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5490 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5491 resultType = DoubleValue;
5493 curlResult = curl_easy_getinfo(connection->connection,
5494 CURLINFO_CONTENT_LENGTH_UPLOAD,
5495 &doubleValue);
5496 break;
5497 #endif
5499 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5500 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5501 resultType = DoubleValue;
5503 curlResult = curl_easy_getinfo(connection->connection,
5504 CURLINFO_STARTTRANSFER_TIME,
5505 &doubleValue);
5506 break;
5507 #endif
5509 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5510 case 18: /* CURLINFO_CONTENT_TYPE */
5511 resultType = StringValue;
5513 curlResult = curl_easy_getinfo(connection->connection,
5514 CURLINFO_CONTENT_TYPE,
5515 &strValue);
5516 break;
5517 #endif
5519 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5520 case 19: /* CURLINFO_REDIRECT_TIME */
5521 resultType = DoubleValue;
5523 curlResult = curl_easy_getinfo(connection->connection,
5524 CURLINFO_REDIRECT_TIME,
5525 &doubleValue);
5526 break;
5527 #endif
5529 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5530 case 20: /* CURLINFO_REDIRECT_COUNT */
5531 resultType = LongValue;
5533 curlResult = curl_easy_getinfo(connection->connection,
5534 CURLINFO_REDIRECT_COUNT,
5535 &longValue);
5536 break;
5537 #endif
5539 #if HAVE_DECL_CURLINFO_PRIVATE
5540 case 21: /* CURLINFO_PRIVATE */
5541 resultType = StringValue;
5543 curlResult = curl_easy_getinfo(connection->connection,
5544 CURLINFO_PRIVATE,
5545 &strValue);
5546 break;
5547 #endif
5549 #if HAVE_DECL_CURLINFO_HTTP_CONNECT_CODE
5550 case 22: /* CURLINFO_HTTP_CONNECT_CODE */
5551 resultType = LongValue;
5553 curlResult = curl_easy_getinfo(connection->connection,
5554 CURLINFO_HTTP_CONNECT_CODE,
5555 &longValue);
5556 break;
5557 #endif
5559 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5560 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5561 resultType = LongValue;
5563 curlResult = curl_easy_getinfo(connection->connection,
5564 CURLINFO_HTTPAUTH_AVAIL,
5565 &longValue);
5566 break;
5567 #endif
5569 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5570 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5571 resultType = LongValue;
5573 curlResult = curl_easy_getinfo(connection->connection,
5574 CURLINFO_PROXYAUTH_AVAIL,
5575 &longValue);
5576 break;
5577 #endif
5579 #if HAVE_DECL_CURLINFO_OS_ERRNO
5580 case 25: /* CURLINFO_OS_ERRNO */
5581 resultType = LongValue;
5583 curlResult = curl_easy_getinfo(connection->connection,
5584 CURLINFO_OS_ERRNO,
5585 &longValue);
5586 break;
5587 #endif
5589 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5590 case 26: /* CURLINFO_NUM_CONNECTS */
5591 resultType = LongValue;
5593 curlResult = curl_easy_getinfo(connection->connection,
5594 CURLINFO_NUM_CONNECTS,
5595 &longValue);
5596 break;
5597 #endif
5599 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5600 case 27: /* CURLINFO_SSL_ENGINES */
5601 resultType = StringListValue;
5603 curlResult = curl_easy_getinfo(connection->connection,
5604 CURLINFO_SSL_ENGINES,
5605 &stringListValue);
5606 break;
5607 #endif
5609 #if HAVE_DECL_CURLINFO_COOKIELIST
5610 case 28: /* CURLINFO_COOKIELIST */
5611 resultType = StringListValue;
5613 curlResult = curl_easy_getinfo(connection->connection,
5614 CURLINFO_COOKIELIST,
5615 &stringListValue);
5616 break;
5617 #endif
5619 #if HAVE_DECL_CURLINFO_LASTSOCKET
5620 case 29: /* CURLINFO_LASTSOCKET */
5621 resultType = LongValue;
5623 curlResult = curl_easy_getinfo(connection->connection,
5624 CURLINFO_LASTSOCKET,
5625 &longValue);
5626 break;
5627 #endif
5629 default:
5630 failwith("Invalid CURLINFO Option");
5631 break;
5634 if (curlResult != CURLE_OK)
5635 raiseError(connection, curlResult);
5637 switch (resultType)
5639 case StringValue:
5640 result = alloc(1, StringValue);
5642 libcurl can return NULL, e.g. for CONTENT_TYPE or PRIVATE
5643 alternative: add StringOptionValue and break API..
5645 Store_field(result, 0, copy_string(strValue?strValue:""));
5646 break;
5648 case LongValue:
5649 result = alloc(1, LongValue);
5650 Store_field(result, 0, Val_long(longValue));
5651 break;
5653 case DoubleValue:
5654 result = alloc(1, DoubleValue);
5655 Store_field(result, 0, copy_double(doubleValue));
5656 break;
5658 case StringListValue:
5659 result = alloc(1, StringListValue);
5660 Store_field(result, 0, convertStringList(stringListValue));
5661 break;
5664 CAMLreturn(result);
5668 ** curl_escape helper function
5671 CAMLprim value helper_curl_escape(value str)
5673 CAMLparam1(str);
5674 CAMLlocal1(result);
5675 char *curlResult;
5677 curlResult = curl_escape(String_val(str), string_length(str));
5678 result = copy_string(curlResult);
5679 free(curlResult);
5681 CAMLreturn(result);
5685 ** curl_unescape helper function
5688 CAMLprim value helper_curl_unescape(value str)
5690 CAMLparam1(str);
5691 CAMLlocal1(result);
5692 char *curlResult;
5694 curlResult = curl_unescape(String_val(str), string_length(str));
5695 result = copy_string(curlResult);
5696 free(curlResult);
5698 CAMLreturn(result);
5702 ** curl_getdate helper function
5705 CAMLprim value helper_curl_getdate(value str, value now)
5707 CAMLparam2(str, now);
5708 CAMLlocal1(result);
5709 time_t curlResult;
5710 time_t curlNow;
5712 curlNow = (time_t)Double_val(now);
5713 curlResult = curl_getdate(String_val(str), &curlNow);
5714 result = copy_double((double)curlResult);
5716 CAMLreturn(result);
5720 ** curl_version helper function
5723 CAMLprim value helper_curl_version(void)
5725 CAMLparam0();
5726 CAMLlocal1(result);
5727 char *str;
5729 str = curl_version();
5730 result = copy_string(str);
5732 CAMLreturn(result);
5736 * Curl multi stack support
5738 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
5739 * Other exported functions are prefixed with caml_curlm_, some of them
5740 * can/should be decomposed into smaller parts.
5743 struct ml_multi_handle
5745 CURLM* handle;
5746 value values; /* callbacks */
5749 enum
5751 curlmopt_socket_function,
5752 curlmopt_timer_function,
5754 /* last, not used */
5755 multi_values_total,
5758 typedef struct ml_multi_handle ml_multi_handle;
5760 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
5761 #define CURLM_val(v) (Multi_val(v)->handle)
5763 static struct custom_operations curl_multi_ops = {
5764 "ygrek.curl_multi",
5765 custom_finalize_default,
5766 custom_compare_default,
5767 custom_hash_default,
5768 custom_serialize_default,
5769 custom_deserialize_default
5772 CAMLprim value caml_curl_multi_init(value unit)
5774 CAMLparam1(unit);
5775 CAMLlocal1(v);
5776 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
5777 CURLM* h = curl_multi_init();
5779 if (!h)
5781 caml_stat_free(multi);
5782 failwith("caml_curl_multi_init");
5785 multi->handle = h;
5786 multi->values = caml_alloc(multi_values_total, 0);
5787 caml_register_generational_global_root(&multi->values);
5789 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
5790 Multi_val(v) = multi;
5792 CAMLreturn(v);
5795 CAMLprim value caml_curl_multi_cleanup(value handle)
5797 CAMLparam1(handle);
5798 ml_multi_handle* h = Multi_val(handle);
5800 if (NULL == h)
5801 CAMLreturn(Val_unit);
5803 caml_remove_generational_global_root(&h->values);
5805 if (CURLM_OK != curl_multi_cleanup(h->handle))
5806 failwith("caml_curl_multi_cleanup");
5808 Multi_val(handle) = (ml_multi_handle*)NULL;
5810 CAMLreturn(Val_unit);
5813 static CURL* curlm_remove_finished(CURLM* multi_handle)
5815 int msgs_in_queue = 0;
5817 while (1)
5819 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
5820 if (NULL == msg) return NULL;
5821 if (CURLMSG_DONE == msg->msg)
5823 CURL* easy_handle = msg->easy_handle;
5824 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
5826 failwith("curlm_remove_finished");
5828 return easy_handle;
5833 CAMLprim value caml_curlm_remove_finished(value v_multi)
5835 CAMLparam1(v_multi);
5836 CAMLlocal1(v_easy);
5837 CURL* handle;
5838 CURLM* multi_handle;
5840 multi_handle = CURLM_val(v_multi);
5842 caml_enter_blocking_section();
5843 handle = curlm_remove_finished(multi_handle);
5844 caml_leave_blocking_section();
5846 if (NULL == handle)
5848 CAMLreturn(Val_none);
5850 else
5852 /* not good */
5853 v_easy = alloc(1, Abstract_tag);
5854 Store_field(v_easy, 0, (value)findConnection(handle));
5855 CAMLreturn(Val_some(v_easy));
5859 static int curlm_wait_data(CURLM* multi_handle)
5861 struct timeval timeout;
5863 fd_set fdread;
5864 fd_set fdwrite;
5865 fd_set fdexcep;
5866 int maxfd = -1;
5868 FD_ZERO(&fdread);
5869 FD_ZERO(&fdwrite);
5870 FD_ZERO(&fdexcep);
5872 /* set a suitable timeout */
5873 timeout.tv_sec = 1;
5874 timeout.tv_usec = 0;
5876 /* get file descriptors from the transfers */
5877 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
5879 if (ret == CURLM_OK && maxfd >= 0)
5881 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
5882 if (-1 != rc) return 0;
5884 return 1;
5887 CAMLprim value caml_curlm_wait_data(value v_multi)
5889 CAMLparam1(v_multi);
5890 int ret;
5891 CURLM* h = CURLM_val(v_multi);
5893 caml_enter_blocking_section();
5894 ret = curlm_wait_data(h);
5895 caml_leave_blocking_section();
5897 CAMLreturn(Val_bool(0 == ret));
5900 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
5902 CAMLparam2(v_multi,v_easy);
5903 CURLM* multi = CURLM_val(v_multi);
5904 CURL* easy = Connection_val(v_easy)->connection;
5906 /* may invoke callbacks so need to be consistent with locks */
5907 caml_enter_blocking_section();
5908 if (CURLM_OK != curl_multi_add_handle(multi, easy))
5910 caml_leave_blocking_section();
5911 failwith("caml_curl_multi_add_handle");
5913 caml_leave_blocking_section();
5915 CAMLreturn(Val_unit);
5918 CAMLprim value caml_curl_multi_perform_all(value v_multi)
5920 CAMLparam1(v_multi);
5921 int still_running = 0;
5922 CURLM* h = CURLM_val(v_multi);
5924 caml_enter_blocking_section();
5925 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
5926 caml_leave_blocking_section();
5928 CAMLreturn(Val_int(still_running));
5932 * Wrappers for the curl_multi_socket_action infrastructure
5933 * Based on curl hiperfifo.c example
5936 /* FIXME win32unix */
5937 #define Socket_val(v) Int_val(v)
5938 #define Val_socket(v) Val_int(v)
5940 CAMLprim value caml_curl_multi_socket_action(value v_multi, value v_fd, value v_kind)
5942 CAMLparam3(v_multi, v_fd, v_kind);
5943 CURLM* h = CURLM_val(v_multi);
5944 int still_running = 0;
5945 CURLMcode rc;
5946 int socket = Socket_val(v_fd);
5947 int kind = 0;
5949 switch (Int_val(v_kind))
5951 case 0 : break;
5952 case 1 : kind |= CURL_CSELECT_IN; break;
5953 case 2 : kind |= CURL_CSELECT_OUT; break;
5954 case 3 : kind |= CURL_CSELECT_IN | CURL_CSELECT_OUT; break;
5955 default:
5956 failwith("caml_curl_multi_socket_action");
5959 /* fprintf(stdout,"fd %u kind %u\n",Socket_val(v_fd), kind); fflush(stdout); */
5961 caml_enter_blocking_section();
5962 do {
5963 rc = curl_multi_socket_action(h, socket, kind, &still_running);
5964 } while (rc == CURLM_CALL_MULTI_PERFORM);
5965 caml_leave_blocking_section();
5967 /* mcode_or_die("event_cb: curl_multi_socket", rc);*/
5969 check_run_count(g);
5970 if ( g->still_running <= 0 ) {
5971 fprintf(MSG_OUT, "last transfer done, kill timeout\n");
5972 if (evtimer_pending(&g->timer_event, NULL)) {
5973 evtimer_del(&g->timer_event);
5977 CAMLreturn(Val_int(still_running));
5980 CAMLprim value caml_curl_multi_socket_all(value v_multi)
5982 CAMLparam1(v_multi);
5983 int still_running = 0;
5984 CURLM* h = CURLM_val(v_multi);
5986 caml_enter_blocking_section();
5987 while (CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(h, &still_running));
5988 caml_leave_blocking_section();
5990 CAMLreturn(Val_int(still_running));
5993 static int curlm_sock_cb_nolock(CURL *e, curl_socket_t sock, int what, ml_multi_handle* multi, void *sockp)
5995 CAMLparam0();
5996 CAMLlocal1(v_what);
5998 /* v_what = Val_int(what); */
5999 switch (what)
6001 case CURL_POLL_NONE : v_what = Val_int(0); break;
6002 case CURL_POLL_IN : v_what = Val_int(1); break;
6003 case CURL_POLL_OUT : v_what = Val_int(2); break;
6004 case CURL_POLL_INOUT : v_what = Val_int(3); break;
6005 case CURL_POLL_REMOVE : v_what = Val_int(4); break;
6006 default:
6007 caml_failwith("curlm_sock_cb");
6010 caml_callback2(Field(multi->values,curlmopt_socket_function),
6011 Val_socket(sock), v_what);
6013 CAMLreturn(0);
6016 static int curlm_sock_cb(CURL *e, curl_socket_t sock, int what, void *cbp, void *sockp)
6018 int ret;
6019 caml_leave_blocking_section();
6020 ret = curlm_sock_cb_nolock(e, sock, what, (ml_multi_handle*)cbp, sockp);
6021 caml_enter_blocking_section();
6022 return ret;
6025 CAMLprim value caml_curl_multi_socketfunction(value v_multi, value v_cb)
6027 CAMLparam2(v_multi, v_cb);
6028 ml_multi_handle* multi = Multi_val(v_multi);
6030 Store_field(multi->values, curlmopt_socket_function, v_cb);
6032 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETFUNCTION, curlm_sock_cb);
6033 curl_multi_setopt(multi->handle, CURLMOPT_SOCKETDATA, multi);
6035 CAMLreturn(Val_unit);
6038 static void curlm_timer_cb_nolock(ml_multi_handle *multi, long timeout_ms)
6040 CAMLparam0();
6041 caml_callback(Field(multi->values,curlmopt_timer_function), Val_long(timeout_ms));
6042 CAMLreturn0;
6045 static int curlm_timer_cb(CURLM *multi, long timeout_ms, void *userp)
6047 caml_leave_blocking_section();
6048 curlm_timer_cb_nolock((ml_multi_handle*)userp, timeout_ms);
6049 caml_enter_blocking_section();
6050 return 0;
6053 CAMLprim value caml_curl_multi_timerfunction(value v_multi, value v_cb)
6055 CAMLparam2(v_multi, v_cb);
6056 ml_multi_handle* multi = Multi_val(v_multi);
6058 Store_field(multi->values, curlmopt_timer_function, v_cb);
6060 curl_multi_setopt(multi->handle, CURLMOPT_TIMERFUNCTION, curlm_timer_cb);
6061 curl_multi_setopt(multi->handle, CURLMOPT_TIMERDATA, multi);
6063 CAMLreturn(Val_unit);