support all encodings
[ocurl.git] / curl-helper.c
blobc924dff733fe4f7f673f1252fee52b7a1267665e
1 /***
2 *** curl-helper.c
3 ***
4 *** Copyright (c) 2003-2008, Lars Nilsson, <lars@quantumchamaeleon.com>
5 ***/
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <curl/curl.h>
13 #include <caml/alloc.h>
14 #include <caml/memory.h>
15 #include <caml/mlvalues.h>
16 #include <caml/callback.h>
17 #include <caml/fail.h>
18 #include <caml/custom.h>
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #else
23 #warning "No config file given."
24 #endif
26 #if defined(_MSC_VER)
27 #ifdef interface
28 #undef interface
29 #endif
30 #endif
32 void leave_blocking_section(void);
33 void enter_blocking_section(void);
35 #define Val_none Val_int(0)
37 static __inline value
38 Val_some( value v )
40 CAMLparam1( v );
41 CAMLlocal1( some );
42 some = caml_alloc(1, 0);
43 Store_field( some, 0, v );
44 CAMLreturn( some );
47 typedef struct Connection Connection;
48 typedef struct ConnectionList ConnectionList;
50 #define Connection_val(v) ((Connection *)Field(v, 0))
52 enum OcamlValues
54 OcamlWriteCallback,
55 OcamlReadCallback,
56 OcamlErrorBuffer,
57 OcamlPostFields,
58 OcamlHTTPHeader,
59 OcamlHTTPPost,
60 OcamlQuote,
61 OcamlPostQuote,
62 OcamlHeaderCallback,
63 OcamlProgressCallback,
64 OcamlDebugCallback,
65 OcamlHTTP200Aliases,
66 OcamlIOCTLCallback,
67 OcamlSeekFunctionCallback,
69 OcamlURL,
70 OcamlProxy,
71 OcamlUserPWD,
72 OcamlProxyUserPWD,
73 OcamlRange,
74 OcamlReferer,
75 OcamlUserAgent,
76 OcamlFTPPort,
77 OcamlCookie,
78 OcamlHTTPPostStrings,
79 OcamlSSLCert,
80 OcamlSSLCertType,
81 OcamlSSLCertPasswd,
82 OcamlSSLKey,
83 OcamlSSLKeyType,
84 OcamlSSLKeyPasswd,
85 OcamlSSLEngine,
86 OcamlCookieFile,
87 OcamlCustomRequest,
88 OcamlInterface,
89 OcamlCAInfo,
90 OcamlCAPath,
91 OcamlRandomFile,
92 OcamlEGDSocket,
93 OcamlCookieJar,
94 OcamlSSLCipherList,
95 OcamlPrivate,
96 OcamlNETRCFile,
97 OcamlFTPAccount,
98 OcamlCookieList,
99 OcamlFTPAlternativeToUser,
100 OcamlSSHPublicKeyFile,
101 OcamlSSHPrivateKeyFile,
102 OcamlSSHHostPublicKeyMD5,
103 OcamlCopyPostFields,
105 /* Not used, last for size */
106 OcamlValuesSize
109 struct Connection
111 CURL *connection;
112 Connection *next;
113 Connection *prev;
115 value ocamlValues;
117 char *url;
118 char *proxy;
119 char *userPwd;
120 char *proxyUserPwd;
121 char *range;
122 char *errorBuffer;
123 char *postFields;
124 int postFieldSize;
125 char *referer;
126 char *userAgent;
127 char *ftpPort;
128 char *cookie;
129 struct curl_slist *httpHeader;
130 struct curl_httppost *httpPostFirst;
131 struct curl_httppost *httpPostLast;
132 struct curl_slist *httpPostStrings;
133 char *sslCert;
134 char *sslCertType;
135 char *sslCertPasswd;
136 char *sslKey;
137 char *sslKeyType;
138 char *sslKeyPasswd;
139 char *sslEngine;
140 struct curl_slist *quote;
141 struct curl_slist *postQuote;
142 char *cookieFile;
143 char *customRequest;
144 char *interface;
145 char *caInfo;
146 char *caPath;
147 char *randomFile;
148 char *egdSocket;
149 char *cookieJar;
150 char *sslCipherList;
151 char *private;
152 struct curl_slist *http200Aliases;
153 char *netrcFile;
154 char *ftpaccount;
155 char *cookielist;
156 char *ftpAlternativeToUser;
157 char *sshPublicKeyFile;
158 char *sshPrivateKeyFile;
159 char *sshHostPublicKeyMD5;
160 char *copyPostFields;
163 struct ConnectionList
165 Connection *head;
166 Connection *tail;
169 static ConnectionList connectionList = {NULL, NULL};
171 typedef struct CURLErrorMapping CURLErrorMapping;
173 struct CURLErrorMapping
175 char *name;
176 CURLcode error;
179 CURLErrorMapping errorMap[] =
181 #if HAVE_DECL_CURLE_UNSUPPORTED_PROTOCOL
182 {"CURLE_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL},
183 #else
184 {"CURLE_UNSUPPORTED_PROTOCOL", -1},
185 #endif
186 #if HAVE_DECL_CURLE_FAILED_INIT
187 {"CURLE_FAILED_INIT", CURLE_FAILED_INIT},
188 #else
189 {"CURLE_FAILED_INIT", -1},
190 #endif
191 #if HAVE_DECL_CURLE_URL_MALFORMAT
192 {"CURLE_URL_MALFORMAT", CURLE_URL_MALFORMAT},
193 #else
194 {"CURLE_URL_MALFORMAT", -1},
195 #endif
196 #if HAVE_DECL_CURLE_URL_MALFORMAT_USER
197 {"CURLE_URL_MALFORMAT_USER", CURLE_URL_MALFORMAT_USER},
198 #else
199 {"CURLE_URL_MALFORMAT_USER", -1},
200 #endif
201 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_PROXY
202 {"CURLE_COULDNT_RESOLVE_PROXY", CURLE_COULDNT_RESOLVE_PROXY},
203 #else
204 {"CURLE_COULDNT_RESOLVE_PROXY", -1},
205 #endif
206 #if HAVE_DECL_CURLE_COULDNT_RESOLVE_HOST
207 {"CURLE_COULDNT_RESOLVE_HOST", CURLE_COULDNT_RESOLVE_HOST},
208 #else
209 {"CURLE_COULDNT_RESOLVE_HOST", -1},
210 #endif
211 #if HAVE_DECL_CURLE_COULDNT_CONNECT
212 {"CURLE_COULDNT_CONNECT", CURLE_COULDNT_CONNECT},
213 #else
214 {"CURLE_COULDNT_CONNECT", -1},
215 #endif
216 #if HAVE_DECL_CURLE_FTP_WEIRD_SERVER_REPLY
217 {"CURLE_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY},
218 #else
219 {"CURLE_FTP_WEIRD_SERVER_REPLY", -1},
220 #endif
221 #if HAVE_DECL_CURLE_FTP_ACCESS_DENIED
222 {"CURLE_FTP_ACCESS_DENIED", CURLE_FTP_ACCESS_DENIED},
223 #else
224 {"CURLE_FTP_ACCESS_DENIED", -1},
225 #endif
226 #if HAVE_DECL_CURLE_FTP_USER_PASSWORD_INCORRECT
227 {"CURLE_FTP_USER_PASSWORD_INCORRECT", CURLE_FTP_USER_PASSWORD_INCORRECT},
228 #else
229 {"CURLE_FTP_USER_PASSWORD_INCORRECT", -1},
230 #endif
231 #if HAVE_DECL_CURLE_FTP_WEIRD_PASS_REPLY
232 {"CURLE_FTP_WEIRD_PASS_REPLY", CURLE_FTP_WEIRD_PASS_REPLY},
233 #else
234 {"CURLE_FTP_WEIRD_PASS_REPLY", -1},
235 #endif
236 #if HAVE_DECL_CURLE_FTP_WEIRD_USER_REPLY
237 {"CURLE_FTP_WEIRD_USER_REPLY", CURLE_FTP_WEIRD_USER_REPLY},
238 #else
239 {"CURLE_FTP_WEIRD_USER_REPLY", -1},
240 #endif
241 #if HAVE_DECL_CURLE_FTP_WEIRD_PASV_REPLY
242 {"CURLE_FTP_WEIRD_PASV_REPLY", CURLE_FTP_WEIRD_PASV_REPLY},
243 #else
244 {"CURLE_FTP_WEIRD_PASV_REPLY", -1},
245 #endif
246 #if HAVE_DECL_CURLE_FTP_WEIRD_227_FORMAT
247 {"CURLE_FTP_WEIRD_227_FORMAT", CURLE_FTP_WEIRD_227_FORMAT},
248 #else
249 {"CURLE_FTP_WEIRD_227_FORMAT", -1},
250 #endif
251 #if HAVE_DECL_CURLE_FTP_CANT_GET_HOST
252 {"CURLE_FTP_CANT_GET_HOST", CURLE_FTP_CANT_GET_HOST},
253 #else
254 {"CURLE_FTP_CANT_GET_HOST", -1},
255 #endif
256 #if HAVE_DECL_CURLE_FTP_CANT_RECONNECT
257 {"CURLE_FTP_CANT_RECONNECT", CURLE_FTP_CANT_RECONNECT},
258 #else
259 {"CURLE_FTP_CANT_RECONNECT", -1},
260 #endif
261 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_BINARY
262 {"CURLE_FTP_COULDNT_SET_BINARY", CURLE_FTP_COULDNT_SET_BINARY},
263 #else
264 {"CURLE_FTP_COULDNT_SET_BINARY", -1},
265 #endif
266 #if HAVE_DECL_CURLE_PARTIAL_FILE
267 {"CURLE_PARTIAL_FILE", CURLE_PARTIAL_FILE},
268 #else
269 {"CURLE_PARTIAL_FILE", -1},
270 #endif
271 #if HAVE_DECL_CURLE_FTP_COULDNT_RETR_FILE
272 {"CURLE_FTP_COULDNT_RETR_FILE", CURLE_FTP_COULDNT_RETR_FILE},
273 #else
274 {"CURLE_FTP_COULDNT_RETR_FILE", -1},
275 #endif
276 #if HAVE_DECL_CURLE_FTP_WRITE_ERROR
277 {"CURLE_FTP_WRITE_ERROR", CURLE_FTP_WRITE_ERROR},
278 #else
279 {"CURLE_FTP_WRITE_ERROR", -1},
280 #endif
281 #if HAVE_DECL_CURLE_FTP_QUOTE_ERROR
282 {"CURLE_FTP_QUOTE_ERROR", CURLE_FTP_QUOTE_ERROR},
283 #else
284 {"CURLE_FTP_QUOTE_ERROR", -1},
285 #endif
286 #if HAVE_DECL_CURLE_HTTP_NOT_FOUND
287 {"CURLE_HTTP_NOT_FOUND", CURLE_HTTP_NOT_FOUND},
288 #else
289 {"CURLE_HTTP_NOT_FOUND", -1},
290 #endif
291 #if HAVE_DECL_CURLE_WRITE_ERROR
292 {"CURLE_WRITE_ERROR", CURLE_WRITE_ERROR},
293 #else
294 {"CURLE_WRITE_ERROR", -1},
295 #endif
296 #if HAVE_DECL_CURLE_MALFORMAT_USER
297 {"CURLE_MALFORMAT_USER", CURLE_MALFORMAT_USER},
298 #else
299 {"CURLE_MALFORMAT_USER", -1},
300 #endif
301 #if HAVE_DECL_CURLE_FTP_COULDNT_STOR_FILE
302 {"CURLE_FTP_COULDNT_STOR_FILE", CURLE_FTP_COULDNT_STOR_FILE},
303 #else
304 {"CURLE_FTP_COULDNT_STOR_FILE", -1},
305 #endif
306 #if HAVE_DECL_CURLE_READ_ERROR
307 {"CURLE_READ_ERROR", CURLE_READ_ERROR},
308 #else
309 {"CURLE_READ_ERROR", -1},
310 #endif
311 #if HAVE_DECL_CURLE_OUT_OF_MEMORY
312 {"CURLE_OUT_OF_MEMORY", CURLE_OUT_OF_MEMORY},
313 #else
314 {"CURLE_OUT_OF_MEMORY", -1},
315 #endif
316 #if HAVE_DECL_CURLE_OPERATION_TIMEOUTED
317 {"CURLE_OPERATION_TIMEOUTED", CURLE_OPERATION_TIMEOUTED},
318 #else
319 {"CURLE_OPERATION_TIMEOUTED", -1},
320 #endif
321 #if HAVE_DECL_CURLE_FTP_COULDNT_SET_ASCII
322 {"CURLE_FTP_COULDNT_SET_ASCII", CURLE_FTP_COULDNT_SET_ASCII},
323 #else
324 {"CURLE_FTP_COULDNT_SET_ASCII", -1},
325 #endif
326 #if HAVE_DECL_CURLE_FTP_PORT_FAILED
327 {"CURLE_FTP_PORT_FAILED", CURLE_FTP_PORT_FAILED},
328 #else
329 {"CURLE_FTP_PORT_FAILED", -1},
330 #endif
331 #if HAVE_DECL_CURLE_FTP_COULDNT_USE_REST
332 {"CURLE_FTP_COULDNT_USE_REST", CURLE_FTP_COULDNT_USE_REST},
333 #else
334 {"CURLE_FTP_COULDNT_USE_REST", -1},
335 #endif
336 #if HAVE_DECL_CURLE_FTP_COULDNT_GET_SIZE
337 {"CURLE_FTP_COULDNT_GET_SIZE", CURLE_FTP_COULDNT_GET_SIZE},
338 #else
339 {"CURLE_FTP_COULDNT_GET_SIZE", -1},
340 #endif
341 #if HAVE_DECL_CURLE_HTTP_RANGE_ERROR
342 {"CURLE_HTTP_RANGE_ERROR", CURLE_HTTP_RANGE_ERROR},
343 #else
344 {"CURLE_HTTP_RANGE_ERROR", -1},
345 #endif
346 #if HAVE_DECL_CURLE_HTTP_POST_ERROR
347 {"CURLE_HTTP_POST_ERROR", CURLE_HTTP_POST_ERROR},
348 #else
349 {"CURLE_HTTP_POST_ERROR", -1},
350 #endif
351 #if HAVE_DECL_CURLE_SSL_CONNECT_ERROR
352 {"CURLE_SSL_CONNECT_ERROR", CURLE_SSL_CONNECT_ERROR},
353 #else
354 {"CURLE_SSL_CONNECT_ERROR", -1},
355 #endif
356 #if HAVE_DECL_CURLE_FTP_BAD_DOWNLOAD_RESUME
357 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", CURLE_FTP_BAD_DOWNLOAD_RESUME},
358 #else
359 {"CURLE_FTP_BAD_DOWNLOAD_RESUME", -1},
360 #endif
361 #if HAVE_DECL_CURLE_FILE_COULDNT_READ_FILE
362 {"CURLE_FILE_COULDNT_READ_FILE", CURLE_FILE_COULDNT_READ_FILE},
363 #else
364 {"CURLE_FILE_COULDNT_READ_FILE", -1},
365 #endif
366 #if HAVE_DECL_CURLE_LDAP_CANNOT_BIND
367 {"CURLE_LDAP_CANNOT_BIND", CURLE_LDAP_CANNOT_BIND},
368 #else
369 {"CURLE_LDAP_CANNOT_BIND", -1},
370 #endif
371 #if HAVE_DECL_CURLE_LDAP_SEARCH_FAILED
372 {"CURLE_LDAP_SEARCH_FAILED", CURLE_LDAP_SEARCH_FAILED},
373 #else
374 {"CURLE_LDAP_SEARCH_FAILED", -1},
375 #endif
376 #if HAVE_DECL_CURLE_LIBRARY_NOT_FOUND
377 {"CURLE_LIBRARY_NOT_FOUND", CURLE_LIBRARY_NOT_FOUND},
378 #else
379 {"CURLE_LIBRARY_NOT_FOUND", -1},
380 #endif
381 #if HAVE_DECL_CURLE_FUNCTION_NOT_FOUND
382 {"CURLE_FUNCTION_NOT_FOUND", CURLE_FUNCTION_NOT_FOUND},
383 #else
384 {"CURLE_FUNCTION_NOT_FOUND", -1},
385 #endif
386 #if HAVE_DECL_CURLE_ABORTED_BY_CALLBACK
387 {"CURLE_ABORTED_BY_CALLBACK", CURLE_ABORTED_BY_CALLBACK},
388 #else
389 {"CURLE_ABORTED_BY_CALLBACK", -1},
390 #endif
391 #if HAVE_DECL_CURLE_BAD_FUNCTION_ARGUMENT
392 {"CURLE_BAD_FUNCTION_ARGUMENT", CURLE_BAD_FUNCTION_ARGUMENT},
393 #else
394 {"CURLE_BAD_FUNCTION_ARGUMENT", -1},
395 #endif
396 #if HAVE_DECL_CURLE_BAD_CALLING_ORDER
397 {"CURLE_BAD_CALLING_ORDER", CURLE_BAD_CALLING_ORDER},
398 #else
399 {"CURLE_BAD_CALLING_ORDER", -1},
400 #endif
401 #if HAVE_DECL_CURLE_HTTP_PORT_FAILED
402 {"CURLE_HTTP_PORT_FAILED", CURLE_HTTP_PORT_FAILED},
403 #else
404 {"CURLE_HTTP_PORT_FAILED", -1},
405 #endif
406 #if HAVE_DECL_CURLE_BAD_PASSWORD_ENTERED
407 {"CURLE_BAD_PASSWORD_ENTERED", CURLE_BAD_PASSWORD_ENTERED},
408 #else
409 {"CURLE_BAD_PASSWORD_ENTERED", -1},
410 #endif
411 #if HAVE_DECL_CURLE_TOO_MANY_REDIRECTS
412 {"CURLE_TOO_MANY_REDIRECTS", CURLE_TOO_MANY_REDIRECTS},
413 #else
414 {"CURLE_TOO_MANY_REDIRECTS", -1},
415 #endif
416 #if HAVE_DECL_CURLE_UNKNOWN_TELNET_OPTION
417 {"CURLE_UNKNOWN_TELNET_OPTION", CURLE_UNKNOWN_TELNET_OPTION},
418 #else
419 {"CURLE_UNKNOWN_TELNET_OPTION", -1},
420 #endif
421 #if HAVE_DECL_CURLE_TELNET_OPTION_SYNTAX
422 {"CURLE_TELNET_OPTION_SYNTAX", CURLE_TELNET_OPTION_SYNTAX},
423 #else
424 {"CURLE_TELNET_OPTION_SYNTAX", -1},
425 #endif
426 #if HAVE_DECL_CURLE_SSL_PEER_CERTIFICATE
427 {"CURLE_SSL_PEER_CERTIFICATE", CURLE_SSL_PEER_CERTIFICATE},
428 #else
429 {"CURLE_SSL_PEER_CERTIFICATE", -1},
430 #endif
431 #if HAVE_DECL_CURLE_GOT_NOTHING
432 {"CURLE_GOT_NOTHING", CURLE_GOT_NOTHING},
433 #else
434 {"CURLE_GOT_NOTHING", -1},
435 #endif
436 #if HAVE_DECL_CURLE_SSL_ENGINE_NOT_FOUND
437 {"CURLE_SSL_ENGINE_NOT_FOUND", CURLE_SSL_ENGINE_NOTFOUND},
438 #else
439 {"CURLE_SSL_ENGINE_NOT_FOUND", -1},
440 #endif
441 #if HAVE_DECL_CURLE_SSL_ENGINE_SET_FAILED
442 {"CURLE_SSL_ENGINE_SET_FAILED", CURLE_SSL_ENGINE_SETFAILED},
443 #else
444 {"CURLE_SSL_ENGINE_SET_FAILED", -1},
445 #endif
446 #if HAVE_DECL_CURLE_SEND_ERROR
447 {"CURLE_SEND_ERROR", CURLE_SEND_ERROR},
448 #else
449 {"CURLE_SEND_ERROR", -1},
450 #endif
451 #if HAVE_DECL_CURLE_RECV_ERROR
452 {"CURLE_RECV_ERROR", CURLE_RECV_ERROR},
453 #else
454 {"CURLE_RECV_ERROR", -1},
455 #endif
456 #if HAVE_DECL_CURLE_SHARE_IN_USE
457 {"CURLE_SHARE_IN_USE", CURLE_SHARE_IN_USE},
458 #else
459 {"CURLE_SHARE_IN_USE", -1},
460 #endif
461 #if HAVE_DECL_CURLE_SSL_CERTPROBLEM
462 {"CURLE_SSL_CERTPROBLEN", CURLE_SSL_CERTPROBLEM},
463 #else
464 {"CURLE_SSL_CERTPROBLEN", -1},
465 #endif
466 #if HAVE_DECL_CURLE_SSL_CIPHER
467 {"CURLE_SSL_CIPHER", CURLE_SSL_CIPHER},
468 #else
469 {"CURLE_SSL_CIPHER", -1},
470 #endif
471 #if HAVE_DECL_CURLE_SSL_CACERT
472 {"CURLE_SSL_CACERT", CURLE_SSL_CACERT},
473 #else
474 {"CURLE_SSL_CACERT", -1},
475 #endif
476 #if HAVE_DECL_CURLE_BAD_CONTENT_ENCODING
477 {"CURLE_BAD_CONTENT_ENCODING", CURLE_BAD_CONTENT_ENCODING},
478 #else
479 {"CURLE_BAD_CONTENT_ENCODING", -1},
480 #endif
481 #if HAVE_DECL_CURLE_LDAP_INVALID_URL
482 {"CURLE_LDAP_INVALID_URL", CURLE_LDAP_INVALID_URL},
483 #else
484 {"CURLE_LDAP_INVALID_URL", -1},
485 #endif
486 #if HAVE_DECL_CURLE_FILESIZE_EXCEEDED
487 {"CURLE_FILESIZE_EXCEEDED", CURLE_FILESIZE_EXCEEDED},
488 #else
489 {"CURLE_FILESIZE_EXCEEDED", -1},
490 #endif
491 #if HAVE_DECL_CURLE_FTP_SSL_FAILED
492 {"CURLE_FTP_SSL_FAILED", CURLE_FTP_SSL_FAILED},
493 #else
494 {"CURLE_FTP_SSL_FAILED", -1},
495 #endif
496 #if HAVE_DECL_CURLE_SEND_FAIL_REWIND
497 {"CURLE_SEND_FAIL_REWIND", CURLE_SEND_FAIL_REWIND},
498 #else
499 {"CURLE_SEND_FAIL_REWIND", -1},
500 #endif
501 #if HAVE_DECL_CURLE_SSL_ENGINE_INITFAILED
502 {"CURLE_SSL_ENGINE_INITFAILED", CURLE_SSL_ENGINE_INITFAILED},
503 #else
504 {"CURLE_SSL_ENGINE_INITFAILED", -1},
505 #endif
506 #if HAVE_DECL_CURLE_LOGIN_DENIED
507 {"CURLE_LOGIN_DENIED", CURLE_LOGIN_DENIED},
508 #else
509 {"CURLE_LOGIN_DENIED", -1},
510 #endif
511 #if HAVE_DECL_CURLE_TFTP_NOTFOUND
512 {"CURLE_TFTP_NOTFOUND", CURLE_TFTP_NOTFOUND},
513 #else
514 {"CURLE_TFTP_NOTFOUND", -1},
515 #endif
516 #if HAVE_DECL_CURLE_TFTP_PERM
517 {"CURLE_TFTP_PERM", CURLE_TFTP_PERM},
518 #else
519 {"CURLE_TFTP_PERM", -1},
520 #endif
521 #if HAVE_DECL_CURLE_REMOTE_DISK_FULL
522 {"CURLE_REMOTE_DISK_FULL", CURLE_REMOTE_DISK_FULL},
523 #else
524 {"CURLE_REMOTE_DISK_FULL", -1},
525 #endif
526 #if HAVE_DECL_CURLE_TFTP_ILLEGAL
527 {"CURLE_TFTP_ILLEGAL", CURLE_TFTP_ILLEGAL},
528 #else
529 {"CURLE_TFTP_ILLEGAL", -1},
530 #endif
531 #if HAVE_DECL_CURLE_TFTP_UNKNOWNID
532 {"CURLE_TFTP_UNKNOWNID", CURLE_TFTP_UNKNOWNID},
533 #else
534 {"CURLE_TFTP_UNKNOWNID", -1},
535 #endif
536 #if HAVE_DECL_CURLE_REMOTE_FILE_EXISTS
537 {"CURLE_REMOTE_FILE_EXISTS", CURLE_REMOTE_FILE_EXISTS},
538 #else
539 {"CURLE_REMOTE_FILE_EXISTS", -1},
540 #endif
541 #if HAVE_DECL_CURLE_TFTP_NOSUCHUSER
542 {"CURLE_TFTP_NOSUCHUSER", CURLE_TFTP_NOSUCHUSER},
543 #else
544 {"CURLE_TFTP_NOSUCHUSER", -1},
545 #endif
546 #if HAVE_DECL_CURLE_CONV_FAILED
547 {"CURLE_CONV_FAILED", CURLE_CONV_FAILED},
548 #else
549 {"CURLE_CONV_FAILED", -1},
550 #endif
551 #if HAVE_DECL_CURLE_CONV_REQUIRED
552 {"CURLE_CONV_REQUIRED", CURLE_CONV_REQUIRED},
553 #else
554 {"CURLE_CONV_REQUIRED", -1},
555 #endif
556 #if HAVE_DECL_CURLE_SSL_CACERT_BADFILE
557 {"CURLE_SSL_CACERT_BADFILE", CURLE_SSL_CACERT_BADFILE},
558 #else
559 {"CURLE_SSL_CACERT_BADFILE", -1},
560 #endif
561 #if HAVE_DECL_CURLE_REMOTE_FILE_NOT_FOUND
562 {"CURLE_REMOTE_FILE_NOT_FOUND", CURLE_REMOTE_FILE_NOT_FOUND},
563 #else
564 {"CURLE_REMOTE_FILE_NOT_FOUND", -1},
565 #endif
566 #if HAVE_DECL_CURLE_SSH
567 {"CURLE_SSH", CURLE_SSH},
568 #else
569 {"CURLE_SSH", -1},
570 #endif
571 #if HAVE_DECL_CURLE_SSL_SHUTDOWN_FAILED
572 {"CURLE_SSL_SHUTDOWN_FAILED", CURLE_SSL_SHUTDOWN_FAILED},
573 #else
574 {"CURLE_SSL_SHUTDOWN_FAILED", -1},
575 #endif
576 #if HAVE_DECL_CURLE_AGAIN
577 {"CURLE_AGAIN", CURLE_AGAIN},
578 #else
579 {"CURLE_AGAIN", -1},
580 #endif
581 {"CURLE_OK", CURLE_OK},
582 {NULL, 0}
585 typedef struct CURLOptionMapping CURLOptionMapping;
587 struct CURLOptionMapping
589 void (*optionHandler)(Connection *, value);
590 char *name;
591 CURLoption option;
594 CURLOptionMapping unimplementedOptionMap[] =
596 {NULL, "CURLOPT_STDERR", CURLOPT_STDERR},
597 {NULL, NULL, 0}
600 static void handleWriteFunction(Connection *, value);
601 static void handleReadFunction(Connection *, value);
602 static void handleInFileSize(Connection *, value);
603 static void handleURL(Connection *, value);
604 static void handleProxy(Connection *, value);
605 static void handleProxyPort(Connection *, value);
606 static void handleHTTPProxyTunnel(Connection *, value);
607 static void handleVerbose(Connection *, value);
608 static void handleHeader(Connection *, value);
609 static void handleNoProgress(Connection *, value);
610 static void handleNoSignal(Connection *, value);
611 static void handleNoBody(Connection *, value);
612 static void handleFailOnError(Connection *, value);
613 static void handleUpload(Connection *, value);
614 static void handlePost(Connection *, value);
615 static void handleFTPListOnly(Connection *, value);
616 static void handleFTPAppend(Connection *, value);
617 static void handleNETRC(Connection *, value);
618 static void handleEncoding(Connection *, value);
619 static void handleFollowLocation(Connection *, value);
620 static void handleTransferText(Connection *, value);
621 static void handlePut(Connection *, value);
622 static void handleUserPwd(Connection *, value);
623 static void handleProxyUserPwd(Connection *, value);
624 static void handleRange(Connection *, value);
625 static void handleErrorBuffer(Connection *, value);
626 static void handleTimeout(Connection *, value);
627 static void handlePostFields(Connection *, value);
628 static void handlePostFieldSize(Connection *, value);
629 static void handleReferer(Connection *, value);
630 static void handleUserAgent(Connection *, value);
631 static void handleFTPPort(Connection *, value);
632 static void handleLowSpeedLimit(Connection *, value);
633 static void handleLowSpeedTime(Connection *, value);
634 static void handleResumeFrom(Connection *, value);
635 static void handleCookie(Connection *, value);
636 static void handleHTTPHeader(Connection *, value);
637 static void handleHTTPPost(Connection *, value);
638 static void handleSSLCert(Connection *, value);
639 static void handleSSLCertType(Connection *, value);
640 static void handleSSLCertPasswd(Connection *, value);
641 static void handleSSLKey(Connection *, value);
642 static void handleSSLKeyType(Connection *, value);
643 static void handleSSLKeyPasswd(Connection *, value);
644 static void handleSSLEngine(Connection *, value);
645 static void handleSSLEngineDefault(Connection *, value);
646 static void handleCRLF(Connection *, value);
647 static void handleQuote(Connection *, value);
648 static void handlePostQuote(Connection *, value);
649 static void handleHeaderFunction(Connection *, value);
650 static void handleCookieFile(Connection *, value);
651 static void handleSSLVersion(Connection *, value);
652 static void handleTimeCondition(Connection *, value);
653 static void handleTimeValue(Connection *, value);
654 static void handleCustomRequest(Connection *, value);
655 static void handleInterface(Connection *, value);
656 static void handleKRB4Level(Connection *, value);
657 static void handleProgressFunction(Connection *, value);
658 static void handleSSLVerifyPeer(Connection *, value);
659 static void handleCAInfo(Connection *, value);
660 static void handleCAPath(Connection *, value);
661 static void handleFileTime(Connection *, value);
662 static void handleMaxRedirs(Connection *, value);
663 static void handleMaxConnects(Connection *, value);
664 static void handleClosePolicy(Connection *, value);
665 static void handleFreshConnect(Connection *, value);
666 static void handleForbidReuse(Connection *, value);
667 static void handleRandomFile(Connection *, value);
668 static void handleEGDSocket(Connection *, value);
669 static void handleConnectTimeout(Connection *, value);
670 static void handleHTTPGet(Connection *, value);
671 static void handleSSLVerifyHost(Connection *, value);
672 static void handleCookieJar(Connection *, value);
673 static void handleSSLCipherList(Connection *, value);
674 static void handleHTTPVersion(Connection *, value);
675 static void handleFTPUseEPSV(Connection *, value);
676 static void handleDNSCacheTimeout(Connection *, value);
677 static void handleDNSUseGlobalCache(Connection *, value);
678 static void handleDebugFunction(Connection *, value);
679 static void handlePrivate(Connection *, value);
680 static void handleHTTP200Aliases(Connection *, value);
681 static void handleUnrestrictedAuth(Connection *, value);
682 static void handleFTPUseEPRT(Connection *, value);
683 static void handleHTTPAuth(Connection *, value);
684 static void handleFTPCreateMissingDirs(Connection *, value);
685 static void handleProxyAuth(Connection *, value);
686 static void handleFTPResponseTimeout(Connection *, value);
687 static void handleIPResolve(Connection *, value);
688 static void handleMaxFileSize(Connection *, value);
689 static void handleInFileSizeLarge(Connection *, value);
690 static void handleResumeFromLarge(Connection *, value);
691 static void handleMaxFileSizeLarge(Connection *, value);
692 static void handleNETRCFile(Connection *, value);
693 static void handleFTPSSL(Connection *, value);
694 static void handlePostFieldSizeLarge(Connection *, value);
695 static void handleTCPNoDelay(Connection *, value);
696 static void handleFTPSSLAuth(Connection *, value);
697 static void handleIOCTLFunction(Connection *, value);
698 static void handleFTPAccount(Connection *, value);
699 static void handleCookieList(Connection *, value);
700 static void handleIgnoreContentLength(Connection *, value);
701 static void handleFTPSkipPASVIP(Connection *, value);
702 static void handleFTPFileMethod(Connection *, value);
703 static void handleLocalPort(Connection *, value);
704 static void handleLocalPortRange(Connection *, value);
705 static void handleConnectOnly(Connection *, value);
706 static void handleMaxSendSpeedLarge(Connection *, value);
707 static void handleMaxRecvSpeedLarge(Connection *, value);
708 static void handleFTPAlternativeToUser(Connection *, value);
709 static void handleSSLSessionIdCache(Connection *, value);
710 static void handleSSHAuthTypes(Connection *, value);
711 static void handleSSHPublicKeyFile(Connection *, value);
712 static void handleSSHPrivateKeyFile(Connection *, value);
713 static void handleFTPSSLCCC(Connection *, value);
714 static void handleTimeoutMS(Connection *, value);
715 static void handleConnectTimeoutMS(Connection *, value);
716 static void handleHTTPTransferDecoding(Connection *, value);
717 static void handleHTTPContentDecoding(Connection *, value);
718 static void handleNewFilePerms(Connection *, value);
719 static void handleNewDirectoryPerms(Connection *, value);
720 static void handlePost301(Connection *, value);
721 static void handleSSHHostPublicKeyMD5(Connection *, value);
722 static void handleCopyPostFields(Connection *, value);
723 static void handleProxyTransferMode(Connection *, value);
724 static void handleSeekFunction(Connection *, value);
726 CURLOptionMapping implementedOptionMap[] =
728 {handleWriteFunction, "CURLOPT_WRITEFUNCTION", CURLOPT_WRITEFUNCTION},
729 {handleReadFunction, "CURLOPT_READFUNCTION", CURLOPT_READFUNCTION},
730 {handleInFileSize, "CURLOPT_INFILESIZE", CURLOPT_INFILESIZE},
731 {handleURL, "CURLOPT_URL", CURLOPT_URL},
732 {handleProxy, "CURLOPT_PROXY", CURLOPT_PROXY},
733 {handleProxyPort, "CURLOPT_PROXYPORT", CURLOPT_PROXYPORT},
734 {handleHTTPProxyTunnel, "CURLOPT_HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
735 {handleVerbose, "CURLOPT_VERBOSE", CURLOPT_VERBOSE},
736 {handleHeader, "CURLOPT_HEADER", CURLOPT_HEADER},
737 {handleNoProgress, "CURLOPT_NOPROGRESS", CURLOPT_NOPROGRESS},
738 #if HAVE_DECL_CURLOPT_NOSIGNAL
739 {handleNoSignal, "CURLOPT_NOSIGNAL", CURLOPT_NOSIGNAL},
740 #else
741 {handleNoSignal, "CURLOPT_NOSIGNAL", 0},
742 #endif
743 {handleNoBody, "CURLOPT_NOBODY", CURLOPT_NOBODY},
744 {handleFailOnError, "CURLOPT_FAILONERROR", CURLOPT_FAILONERROR},
745 {handleUpload, "CURLOPT_UPLOAD", CURLOPT_UPLOAD},
746 {handlePost, "CURLOPT_POST", CURLOPT_POST},
747 {handleFTPListOnly, "CURLOPT_FTPLISTONLY", CURLOPT_FTPLISTONLY},
748 {handleFTPAppend, "CURLOPT_FTPAPPEND", CURLOPT_FTPAPPEND},
749 {handleNETRC, "CURLOPT_NETRC", CURLOPT_NETRC},
750 #if HAVE_DECL_CURLOPT_ENCODING
751 {handleEncoding, "CURLOPT_ENCODING", CURLOPT_ENCODING},
752 #else
753 {handleEncoding, "CURLOPT_ENCODING", 0},
754 #endif
755 {handleFollowLocation, "CURLOPT_FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
756 {handleTransferText, "CURLOPT_TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
757 {handlePut, "CURLOPT_PUT", CURLOPT_PUT},
758 {handleUserPwd, "CURLOPT_USERPWD", CURLOPT_USERPWD},
759 {handleProxyUserPwd, "CURLOPT_PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
760 {handleRange, "CURLOPT_RANGE", CURLOPT_RANGE},
761 {handleErrorBuffer, "CURLOPT_ERRORBUFFER", CURLOPT_ERRORBUFFER},
762 {handleTimeout, "CURLOPT_TIMEOUT", CURLOPT_TIMEOUT},
763 {handlePostFields, "CURLOPT_POSTFIELDS", CURLOPT_POSTFIELDS},
764 {handlePostFieldSize, "CURLOPT_POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
765 {handleReferer, "CURLOPT_REFERER", CURLOPT_REFERER},
766 {handleUserAgent, "CURLOPT_USERAGENT", CURLOPT_USERAGENT},
767 {handleFTPPort, "CURLOPT_FTPPORT", CURLOPT_FTPPORT},
768 {handleLowSpeedLimit, "CURLOPT_LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
769 {handleLowSpeedTime, "CURLOPT_LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
770 {handleResumeFrom, "CURLOPT_RESUME_FROM", CURLOPT_RESUME_FROM},
771 {handleCookie, "CURLOPT_COOKIE", CURLOPT_COOKIE},
772 {handleHTTPHeader, "CURLOPT_HTTPHEADER", CURLOPT_HTTPHEADER},
773 {handleHTTPPost, "CURLOPT_HTTPPOST", CURLOPT_HTTPPOST},
774 {handleSSLCert, "CURLOPT_SSLCERT", CURLOPT_SSLCERT},
775 {handleSSLCertType, "CURLOPT_SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
776 {handleSSLCertPasswd, "CURLOPT_SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD},
777 {handleSSLKey, "CURLOPT_SSLKEY", CURLOPT_SSLKEY},
778 {handleSSLKeyType, "CURLOPT_SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
779 {handleSSLKeyPasswd, "CURLOPT_SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD},
780 {handleSSLEngine, "CURLOPT_SSLENGINE", CURLOPT_SSLENGINE},
781 {handleSSLEngineDefault, "CURLOPT_SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
782 {handleCRLF, "CURLOPT_CRLF", CURLOPT_CRLF},
783 {handleQuote, "CURLOPT_QUOTE", CURLOPT_QUOTE},
784 {handlePostQuote, "CURLOPT_POSTQUOTE", CURLOPT_POSTQUOTE},
785 {handleHeaderFunction, "CURLOPT_HEADERFUNCTION", CURLOPT_HEADERFUNCTION},
786 {handleCookieFile, "CURLOPT_COOKIEFILE", CURLOPT_COOKIEFILE},
787 {handleSSLVersion, "CURLOPT_SSLVERSION", CURLOPT_SSLVERSION},
788 {handleTimeCondition, "CURLOPT_TIMECONDITION", CURLOPT_TIMECONDITION},
789 {handleTimeValue, "CURLOPT_TIMEVALUE", CURLOPT_TIMEVALUE},
790 {handleCustomRequest, "CURLOPT_CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
791 {handleInterface, "CURLOPT_INTERFACE", CURLOPT_INTERFACE},
792 {handleKRB4Level, "CURLOPT_KRB4LEVEL", CURLOPT_KRB4LEVEL},
793 {handleProgressFunction, "CURLOPT_PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION},
794 {handleSSLVerifyPeer, "CURLOPT_SSLVERIFYPEER", CURLOPT_SSL_VERIFYPEER},
795 {handleCAInfo, "CURLOPT_CAINFO", CURLOPT_CAINFO},
796 {handleCAPath, "CURLOPT_CAPATH", CURLOPT_CAPATH},
797 {handleFileTime, "CURLOPT_FILETIME", CURLOPT_FILETIME},
798 {handleMaxRedirs, "CURLOPT_MAXREDIRS", CURLOPT_MAXREDIRS},
799 {handleMaxConnects, "CURLOPT_MAXCONNECTS", CURLOPT_MAXCONNECTS},
800 {handleClosePolicy, "CURLOPT_CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
801 {handleFreshConnect, "CURLOPT_FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
802 {handleForbidReuse, "CURLOPT_FORBID_REUSE", CURLOPT_FORBID_REUSE},
803 {handleRandomFile, "CURLOPT_RANDOM_FILE", CURLOPT_RANDOM_FILE},
804 {handleEGDSocket, "CURLOPT_EGDSOCKET", CURLOPT_EGDSOCKET},
805 {handleConnectTimeout, "CURLOPT_CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
806 {handleHTTPGet, "CURLOPT_HTTPGET", CURLOPT_HTTPGET},
807 {handleSSLVerifyHost, "CURLOPT_SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
808 {handleCookieJar, "CURLOPT_COOKIEJAR", CURLOPT_COOKIEJAR},
809 {handleSSLCipherList, "CURLOPT_SSL_CIPHERLIST", CURLOPT_SSL_CIPHER_LIST},
810 {handleHTTPVersion, "CURLOPT_HTTP_VERSION", CURLOPT_HTTP_VERSION},
811 {handleFTPUseEPSV, "CURLOPT_FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
812 {handleDNSCacheTimeout, "CURLOPT_DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
813 {handleDNSUseGlobalCache, "CURLOPT_DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
814 {handleDebugFunction, "CURLOPT_DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION},
815 #if HAVE_DECL_CURLOPT_PRIVATE
816 {handlePrivate, "CURLOPT_PRIVATE", CURLOPT_PRIVATE},
817 #else
818 {handlePrivate, "CURLOPT_PRIVATE", 0},
819 #endif
820 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
821 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
822 #else
823 {handleHTTP200Aliases, "CURLOPT_HTTP200ALIASES", 0},
824 #endif
825 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
826 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
827 #else
828 {handleUnrestrictedAuth, "CURLOPT_UNRESTRICTED_AUTH", 0},
829 #endif
830 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
831 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
832 #else
833 {handleFTPUseEPRT, "CURLOPT_FTP_USE_EPRT", 0},
834 #endif
835 #if HAVE_DECL_CURLOPT_HTTPAUTH
836 {handleHTTPAuth, "CURLOPT_HTTPAUTH", CURLOPT_HTTPAUTH},
837 #else
838 {handleHTTPAuth, "CURLOPT_HTTPAUTH", 0},
839 #endif
840 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
841 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
842 #else
843 {handleFTPCreateMissingDirs, "CURLOPT_FTP_CREATE_MISSING_DIRS", 0},
844 #endif
845 #if HAVE_DECL_CURLOPT_PROXYAUTH
846 {handleProxyAuth, "CURLOPT_PROXYAUTH", CURLOPT_PROXYAUTH},
847 #else
848 {handleProxyAuth, "CURLOPT_PROXYAUTH", 0},
849 #endif
850 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
851 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
852 #else
853 {handleFTPResponseTimeout, "CURLOPT_FTP_RESPONSE_TIMEOUT", 0},
854 #endif
855 #if HAVE_DECL_CURLOPT_IPRESOLVE
856 {handleIPResolve, "CURLOPT_IPRESOLVE", CURLOPT_IPRESOLVE},
857 #else
858 {handleIPResolve, "CURLOPT_IPRESOLVE", 0},
859 #endif
860 #if HAVE_DECL_CURLOPT_MAXFILESIZE
861 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", CURLOPT_MAXFILESIZE},
862 #else
863 {handleMaxFileSize, "CURLOPT_MAXFILESIZE", 0},
864 #endif
865 #if HAVE_DECL_CURLOPT_INFILSIZE_LARGE
866 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE},
867 #else
868 {handleInFileSizeLarge, "CURLOPT_INFILESIZE_LARGE", 0},
869 #endif
870 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
871 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE},
872 #else
873 {handleResumeFromLarge, "CURLOPT_RESUME_FROM_LARGE", 0},
874 #endif
875 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
876 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE},
877 #else
878 {handleMaxFileSizeLarge, "CURLOPT_MAXFILESIZE_LARGE", 0},
879 #endif
880 #if HAVE_DECL_CURLOPT_NETRC_FILE
881 {handleNETRCFile, "CURLOPT_NETRC_FILE", CURLOPT_NETRC_FILE},
882 #else
883 {handleNETRCFile, "CURLOPT_NETRC_FILE", 0},
884 #endif
885 #if HAVE_DECL_CURLOPT_FTP_SSL
886 {handleFTPSSL, "CURLOPT_FTP_SSL", CURLOPT_FTP_SSL},
887 #else
888 {handleFTPSSL, "CURLOPT_FTP_SSL", 0},
889 #endif
890 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
891 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE},
892 #else
893 {handlePostFieldSizeLarge, "CURLOPT_POSTFIELDSIZE_LARGE", 0},
894 #endif
895 #if HAVE_DECL_CURLOPT_TCP_NODELAY
896 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", CURLOPT_TCP_NODELAY},
897 #else
898 {handleTCPNoDelay, "CURLOPT_TCP_NODELAY", 0},
899 #endif
900 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
901 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
902 #else
903 {handleFTPSSLAuth, "CURLOPT_FTPSSLAUTH", 0},
904 #endif
905 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
906 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION},
907 #else
908 {handleIOCTLFunction, "CURLOPT_IOCTLFUNCTION", 0},
909 #endif
910 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
911 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
912 #else
913 {handleFTPAccount, "CURLOPT_FTP_ACCOUNT", 0},
914 #endif
915 #if HAVE_DECL_CURLOPT_COOKIELIST
916 {handleCookieList, "CURLOPT_COOKIELIST", CURLOPT_COOKIELIST},
917 #else
918 {handleCookieList, "CURLOPT_COOKIELIST", 0},
919 #endif
920 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
921 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
922 #else
923 {handleIgnoreContentLength, "CURLOPT_IGNORE_CONTENT_LENGTH", 0},
924 #endif
925 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
926 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
927 #else
928 {handleFTPSkipPASVIP, "CURLOPT_FTP_SKIP_PASV_IP", 0},
929 #endif
930 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
931 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
932 #else
933 {handleFTPFileMethod, "CURLOPT_FTP_FILEMETHOD", 0},
934 #endif
935 #if HAVE_DECL_CURLOPT_LOCALPORT
936 {handleLocalPort, "CURLOPT_LOCALPORT", CURLOPT_LOCALPORT},
937 #else
938 {handleLocalPort, "CURLOPT_LOCALPORT", 0},
939 #endif
940 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
941 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
942 #else
943 {handleLocalPortRange, "CURLOPT_LOCALPORTRANGE", 0},
944 #endif
945 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
946 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
947 #else
948 {handleConnectOnly, "CURLOPT_CONNECT_ONLY", 0},
949 #endif
950 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
951 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE},
952 #else
953 {handleMaxSendSpeedLarge, "CURLOPT_MAX_SEND_SPEED_LARGE", 0},
954 #endif
955 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
956 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE},
957 #else
958 {handleMaxRecvSpeedLarge, "CURLOPT_MAX_RECV_SPEED_LARGE", 0},
959 #endif
960 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
961 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
962 #else
963 {handleFTPAlternativeToUser, "CURLOPT_FTP_ALTERMATIVE_TO_USER", 0},
964 #endif
965 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
966 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
967 #else
968 {handleSSLSessionIdCache, "CURLOPT_SSL_SESSIONID_CACHE", 0},
969 #endif
970 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
971 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
972 #else
973 {handleSSHAuthTypes, "CURLOPT_SSH_AUTH_TYPES", 0},
974 #endif
975 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
976 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
977 #else
978 {handleSSHPublicKeyFile, "CURLOPT_SSH_PUBLIC_KEYFILE", 0},
979 #endif
980 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
981 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
982 #else
983 {handleSSHPrivateKeyFile, "CURLOPT_SSH_PRIVATE_KEYFILE", 0},
984 #endif
985 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
986 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
987 #else
988 {handleFTPSSLCCC, "CURLOPT_FTP_SSL_CCC", 0},
989 #endif
990 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
991 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
992 #else
993 {handleTimeoutMS, "CURLOPT_TIMEOUT_MS", 0},
994 #endif
995 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
996 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
997 #else
998 {handleConnectTimeoutMS, "CURLOPT_CONNECTTIMEOUT_MS", 0},
999 #endif
1000 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
1001 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
1002 #else
1003 {handleHTTPTransferDecoding, "CURLOPT_HTTP_TRANSFER_DECODING", 0},
1004 #endif
1005 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
1006 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
1007 #else
1008 {handleHTTPContentDecoding, "CURLOPT_HTTP_CONTENT_DECODING", 0},
1009 #endif
1010 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
1011 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
1012 #else
1013 {handleNewFilePerms, "CURLOPT_NEW_FILE_PERMS", 0},
1014 #endif
1015 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
1016 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
1017 #else
1018 {handleNewDirectoryPerms, "CURLOPT_NEW_DIRECTORY_PERMS", 0},
1019 #endif
1020 #if HAVE_DECL_CURLOPT_POST301
1021 {handlePost301, "CURLOPT_POST301", CURLOPT_POST301},
1022 #else
1023 {handlePost301, "CURLOPT_POST301", 0},
1024 #endif
1025 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEY_MD5
1026 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
1027 #else
1028 {handleSSHHostPublicKeyMD5, "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 0},
1029 #endif
1030 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
1031 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
1032 #else
1033 {handleCopyPostFields, "CURLOPT_COPYPOSTFIELDS", 0},
1034 #endif
1035 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
1036 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
1037 #else
1038 {handleProxyTransferMode, "CURLOPT_PROXY_TRANSFER_MODE", 0},
1039 #endif
1040 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
1041 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", CURLOPT_SEEKFUNCTION},
1042 #else
1043 {handleSeekFunction, "CURLOPT_SEEKFUNCTION", 0},
1044 #endif
1047 static char *findOption(CURLOptionMapping optionMap[],
1048 CURLoption option)
1050 return optionMap[option].name;
1053 static void free_curl_slist(struct curl_slist *slist)
1055 struct curl_slist *item;
1057 if (slist == NULL)
1058 return;
1060 item = slist;
1062 while (item != NULL)
1064 free(item->data);
1065 item->data = NULL;
1066 item = item->next;
1069 curl_slist_free_all(slist);
1072 static void raiseError(Connection *conn, CURLcode code)
1074 CAMLparam0();
1075 CAMLlocal1(exceptionData);
1076 value *exception;
1077 char *errorString = "Unknown Error";
1078 int i;
1080 for (i = 0; errorMap[i].name != NULL; i++)
1082 if (errorMap[i].error == code)
1084 errorString = errorMap[i].name;
1085 break;
1089 exceptionData = caml_alloc(3, 0);
1091 Store_field(exceptionData, 0, Val_int(code));
1092 Store_field(exceptionData, 1, Val_int(code));
1093 Store_field(exceptionData, 2, copy_string(errorString));
1095 if (conn != NULL && conn->errorBuffer != NULL)
1097 Store_field(Field(conn->ocamlValues, OcamlErrorBuffer), 0,
1098 copy_string(conn->errorBuffer));
1101 exception = caml_named_value("CurlException");
1103 if (exception == NULL)
1104 caml_failwith("CurlException not registered");
1106 raise_with_arg(*exception, exceptionData);
1108 CAMLreturn0;
1111 static void resetOcamlValues(Connection* connection)
1113 int i;
1115 for (i = 0; i < OcamlValuesSize; i++)
1116 Store_field(connection->ocamlValues, i, Val_unit);
1119 static Connection *newConnection(void)
1121 Connection *connection;
1123 connection = (Connection *)malloc(sizeof(Connection));
1125 enter_blocking_section();
1126 connection->connection = curl_easy_init();
1127 leave_blocking_section();
1129 connection->next = NULL;
1130 connection->prev = NULL;
1132 if (connectionList.tail == NULL)
1134 connectionList.tail = connection;
1135 connectionList.head = connection;
1137 else
1139 connection->prev = connectionList.head;
1140 connectionList.head->next = connection;
1141 connectionList.head = connection;
1144 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1145 resetOcamlValues(connection);
1146 register_global_root(&connection->ocamlValues);
1148 connection->url = NULL;
1149 connection->proxy = NULL;
1150 connection->userPwd = NULL;
1151 connection->proxyUserPwd = NULL;
1152 connection->range = NULL;
1153 connection->errorBuffer = NULL;
1154 connection->postFields = NULL;
1155 connection->postFieldSize = -1;
1156 connection->referer = NULL;
1157 connection->userAgent = NULL;
1158 connection->ftpPort = NULL;
1159 connection->cookie = NULL;
1160 connection->httpHeader = NULL;
1161 connection->httpPostFirst = NULL;
1162 connection->httpPostLast = NULL;
1163 connection->httpPostStrings = NULL;
1164 connection->sslCert = NULL;
1165 connection->sslCertType = NULL;
1166 connection->sslCertPasswd = NULL;
1167 connection->sslKey = NULL;
1168 connection->sslKeyType = NULL;
1169 connection->sslKeyPasswd = NULL;
1170 connection->sslEngine = NULL;
1171 connection->quote = NULL;
1172 connection->postQuote = NULL;
1173 connection->cookieFile = NULL;
1174 connection->customRequest = NULL;
1175 connection->interface = NULL;
1176 connection->caInfo = NULL;
1177 connection->caPath = NULL;
1178 connection->randomFile = NULL;
1179 connection->egdSocket = NULL;
1180 connection->cookieJar = NULL;
1181 connection->sslCipherList = NULL;
1182 connection->private = NULL;
1183 connection->http200Aliases = NULL;
1184 connection->netrcFile = NULL;
1185 connection->ftpaccount = NULL;
1186 connection->cookielist = NULL;
1187 connection->ftpAlternativeToUser = NULL;
1188 connection->sshPublicKeyFile = NULL;
1189 connection->sshPrivateKeyFile = NULL;
1190 connection->copyPostFields = NULL;
1192 return connection;
1195 static Connection *duplicateConnection(Connection *original)
1197 Connection *connection;
1199 connection = (Connection *)malloc(sizeof(Connection));
1201 enter_blocking_section();
1202 connection->connection = curl_easy_duphandle(original->connection);
1203 leave_blocking_section();
1205 connection->next = NULL;
1206 connection->prev = NULL;
1208 if (connectionList.tail == NULL)
1210 connectionList.tail = connection;
1211 connectionList.head = connection;
1213 else
1215 connection->prev = connectionList.head;
1216 connectionList.head->next = connection;
1217 connectionList.head = connection;
1220 connection->ocamlValues = alloc(OcamlValuesSize, 0);
1221 resetOcamlValues(connection);
1222 register_global_root(&connection->ocamlValues);
1224 Store_field(connection->ocamlValues, OcamlWriteCallback,
1225 Field(original->ocamlValues, OcamlWriteCallback));
1226 Store_field(connection->ocamlValues, OcamlReadCallback,
1227 Field(original->ocamlValues, OcamlReadCallback));
1228 Store_field(connection->ocamlValues, OcamlErrorBuffer,
1229 Field(original->ocamlValues, OcamlErrorBuffer));
1230 Store_field(connection->ocamlValues, OcamlPostFields,
1231 Field(original->ocamlValues, OcamlPostFields));
1232 Store_field(connection->ocamlValues, OcamlHTTPHeader,
1233 Field(original->ocamlValues, OcamlHTTPHeader));
1234 Store_field(connection->ocamlValues, OcamlQuote,
1235 Field(original->ocamlValues, OcamlQuote));
1236 Store_field(connection->ocamlValues, OcamlPostQuote,
1237 Field(original->ocamlValues, OcamlPostQuote));
1238 Store_field(connection->ocamlValues, OcamlHeaderCallback,
1239 Field(original->ocamlValues, OcamlHeaderCallback));
1240 Store_field(connection->ocamlValues, OcamlProgressCallback,
1241 Field(original->ocamlValues, OcamlProgressCallback));
1242 Store_field(connection->ocamlValues, OcamlDebugCallback,
1243 Field(original->ocamlValues, OcamlDebugCallback));
1244 Store_field(connection->ocamlValues, OcamlHTTP200Aliases,
1245 Field(original->ocamlValues, OcamlHTTP200Aliases));
1246 Store_field(connection->ocamlValues, OcamlIOCTLCallback,
1247 Field(original->ocamlValues, OcamlIOCTLCallback));
1248 Store_field(connection->ocamlValues, OcamlSeekFunctionCallback,
1249 Field(original->ocamlValues, OcamlSeekFunctionCallback));
1251 connection->url = NULL;
1252 connection->proxy = NULL;
1253 connection->userPwd = NULL;
1254 connection->proxyUserPwd = NULL;
1255 connection->range = NULL;
1256 connection->errorBuffer = NULL;
1257 connection->postFields = NULL;
1258 connection->postFieldSize = -1;
1259 connection->referer = NULL;
1260 connection->userAgent = NULL;
1261 connection->ftpPort = NULL;
1262 connection->cookie = NULL;
1263 connection->httpHeader = NULL;
1264 connection->httpPostFirst = NULL;
1265 connection->httpPostLast = NULL;
1266 connection->httpPostStrings = NULL;
1267 connection->sslCert = NULL;
1268 connection->sslCertType = NULL;
1269 connection->sslCertPasswd = NULL;
1270 connection->sslKey = NULL;
1271 connection->sslKeyType = NULL;
1272 connection->sslKeyPasswd = NULL;
1273 connection->sslEngine = NULL;
1274 connection->quote = NULL;
1275 connection->postQuote = NULL;
1276 connection->cookieFile = NULL;
1277 connection->customRequest = NULL;
1278 connection->interface = NULL;
1279 connection->caInfo = NULL;
1280 connection->caPath = NULL;
1281 connection->randomFile = NULL;
1282 connection->egdSocket = NULL;
1283 connection->cookieJar = NULL;
1284 connection->sslCipherList = NULL;
1285 connection->private = NULL;
1286 connection->http200Aliases = NULL;
1287 connection->netrcFile = NULL;
1288 connection->ftpaccount = NULL;
1289 connection->cookielist = NULL;
1290 connection->sshPublicKeyFile = NULL;
1291 connection->sshPrivateKeyFile = NULL;
1292 connection->copyPostFields = NULL;
1294 if (Field(original->ocamlValues, OcamlURL) != Val_unit)
1295 handleURL(connection, Field(original->ocamlValues,
1296 OcamlURL));
1297 if (Field(original->ocamlValues, OcamlProxy) != Val_unit)
1298 handleProxy(connection, Field(original->ocamlValues,
1299 OcamlProxy));
1300 if (Field(original->ocamlValues, OcamlUserPWD) != Val_unit)
1301 handleUserPwd(connection, Field(original->ocamlValues,
1302 OcamlUserPWD));
1303 if (Field(original->ocamlValues, OcamlProxyUserPWD) != Val_unit)
1304 handleProxyUserPwd(connection, Field(original->ocamlValues,
1305 OcamlProxyUserPWD));
1306 if (Field(original->ocamlValues, OcamlRange) != Val_unit)
1307 handleRange(connection, Field(original->ocamlValues,
1308 OcamlRange));
1309 if (Field(original->ocamlValues, OcamlErrorBuffer) != Val_unit)
1310 handleErrorBuffer(connection, Field(original->ocamlValues,
1311 OcamlErrorBuffer));
1312 if (Field(original->ocamlValues, OcamlPostFields) != Val_unit)
1313 handlePostFields(connection, Field(original->ocamlValues,
1314 OcamlPostFields));
1315 if (Field(original->ocamlValues, OcamlReferer) != Val_unit)
1316 handleReferer(connection, Field(original->ocamlValues,
1317 OcamlReferer));
1318 if (Field(original->ocamlValues, OcamlUserAgent) != Val_unit)
1319 handleUserAgent(connection, Field(original->ocamlValues,
1320 OcamlUserAgent));
1321 if (Field(original->ocamlValues, OcamlFTPPort) != Val_unit)
1322 handleFTPPort(connection, Field(original->ocamlValues,
1323 OcamlFTPPort));
1324 if (Field(original->ocamlValues, OcamlCookie) != Val_unit)
1325 handleCookie(connection, Field(original->ocamlValues,
1326 OcamlCookie));
1327 if (Field(original->ocamlValues, OcamlHTTPHeader) != Val_unit)
1328 handleHTTPHeader(connection, Field(original->ocamlValues,
1329 OcamlHTTPHeader));
1330 if (Field(original->ocamlValues, OcamlHTTPPost) != Val_unit)
1331 handleHTTPPost(connection, Field(original->ocamlValues,
1332 OcamlHTTPPost));
1333 if (Field(original->ocamlValues, OcamlSSLCert) != Val_unit)
1334 handleSSLCert(connection, Field(original->ocamlValues,
1335 OcamlSSLCert));
1336 if (Field(original->ocamlValues, OcamlSSLCertType) != Val_unit)
1337 handleSSLCertType(connection, Field(original->ocamlValues,
1338 OcamlSSLCertType));
1339 if (Field(original->ocamlValues, OcamlSSLCertPasswd) != Val_unit)
1340 handleSSLCertPasswd(connection, Field(original->ocamlValues,
1341 OcamlSSLCertPasswd));
1342 if (Field(original->ocamlValues, OcamlSSLKey) != Val_unit)
1343 handleSSLKey(connection, Field(original->ocamlValues,
1344 OcamlSSLKey));
1345 if (Field(original->ocamlValues, OcamlSSLKeyType) != Val_unit)
1346 handleSSLKeyType(connection, Field(original->ocamlValues,
1347 OcamlSSLKeyType));
1348 if (Field(original->ocamlValues, OcamlSSLKeyPasswd) != Val_unit)
1349 handleSSLKeyPasswd(connection, Field(original->ocamlValues,
1350 OcamlSSLKeyPasswd));
1351 if (Field(original->ocamlValues, OcamlSSLEngine) != Val_unit)
1352 handleSSLEngine(connection, Field(original->ocamlValues,
1353 OcamlSSLEngine));
1354 if (Field(original->ocamlValues, OcamlQuote) != Val_unit)
1355 handleQuote(connection, Field(original->ocamlValues,
1356 OcamlQuote));
1357 if (Field(original->ocamlValues, OcamlPostQuote) != Val_unit)
1358 handlePostQuote(connection, Field(original->ocamlValues,
1359 OcamlPostQuote));
1360 if (Field(original->ocamlValues, OcamlCookieFile) != Val_unit)
1361 handleCookieFile(connection, Field(original->ocamlValues,
1362 OcamlCookieFile));
1363 if (Field(original->ocamlValues, OcamlCustomRequest) != Val_unit)
1364 handleCustomRequest(connection, Field(original->ocamlValues,
1365 OcamlCustomRequest));
1366 if (Field(original->ocamlValues, OcamlInterface) != Val_unit)
1367 handleInterface(connection, Field(original->ocamlValues,
1368 OcamlInterface));
1369 if (Field(original->ocamlValues, OcamlCAInfo) != Val_unit)
1370 handleCAInfo(connection, Field(original->ocamlValues,
1371 OcamlCAInfo));
1372 if (Field(original->ocamlValues, OcamlCAPath) != Val_unit)
1373 handleCAPath(connection, Field(original->ocamlValues,
1374 OcamlCAPath));
1375 if (Field(original->ocamlValues, OcamlRandomFile) != Val_unit)
1376 handleRandomFile(connection, Field(original->ocamlValues,
1377 OcamlRandomFile));
1378 if (Field(original->ocamlValues, OcamlEGDSocket) != Val_unit)
1379 handleEGDSocket(connection, Field(original->ocamlValues,
1380 OcamlEGDSocket));
1381 if (Field(original->ocamlValues, OcamlCookieJar) != Val_unit)
1382 handleCookieJar(connection, Field(original->ocamlValues,
1383 OcamlCookieJar));
1384 if (Field(original->ocamlValues, OcamlSSLCipherList) != Val_unit)
1385 handleSSLCipherList(connection, Field(original->ocamlValues,
1386 OcamlSSLCipherList));
1387 if (Field(original->ocamlValues, OcamlPrivate) != Val_unit)
1388 handlePrivate(connection, Field(original->ocamlValues,
1389 OcamlPrivate));
1390 if (Field(original->ocamlValues, OcamlHTTP200Aliases) != Val_unit)
1391 handleHTTP200Aliases(connection, Field(original->ocamlValues,
1392 OcamlHTTP200Aliases));
1393 if (Field(original->ocamlValues, OcamlNETRCFile) != Val_unit)
1394 handleNETRCFile(connection, Field(original->ocamlValues,
1395 OcamlNETRCFile));
1396 if (Field(original->ocamlValues, OcamlFTPAccount) != Val_unit)
1397 handleFTPAccount(connection, Field(original->ocamlValues,
1398 OcamlFTPAccount));
1399 if (Field(original->ocamlValues, OcamlCookieList) != Val_unit)
1400 handleCookieList(connection, Field(original->ocamlValues,
1401 OcamlCookieList));
1402 if (Field(original->ocamlValues, OcamlFTPAlternativeToUser) != Val_unit)
1403 handleFTPAlternativeToUser(connection,
1404 Field(original->ocamlValues,
1405 OcamlFTPAlternativeToUser));
1406 if (Field(original->ocamlValues, OcamlSSHPublicKeyFile) != Val_unit)
1407 handleSSHPublicKeyFile(connection,
1408 Field(original->ocamlValues,
1409 OcamlSSHPublicKeyFile));
1410 if (Field(original->ocamlValues, OcamlSSHPrivateKeyFile) != Val_unit)
1411 handleSSHPrivateKeyFile(connection,
1412 Field(original->ocamlValues,
1413 OcamlSSHPrivateKeyFile));
1414 if (Field(original->ocamlValues, OcamlCopyPostFields) != Val_unit)
1415 handleCopyPostFields(connection,
1416 Field(original->ocamlValues,
1417 OcamlCopyPostFields));
1419 return connection;
1422 static void removeConnection(Connection *connection)
1424 enter_blocking_section();
1425 curl_easy_cleanup(connection->connection);
1426 leave_blocking_section();
1428 if (connectionList.tail == connection)
1429 connectionList.tail = connectionList.tail->next;
1430 if (connectionList.head == connection)
1431 connectionList.head = connectionList.head->prev;
1433 if (connection->next != NULL)
1434 connection->next->prev = connection->prev;
1435 if (connection->prev != NULL)
1436 connection->prev->next = connection->next;
1438 remove_global_root(&connection->ocamlValues);
1440 if (connection->url != NULL)
1441 free(connection->url);
1442 if (connection->proxy != NULL)
1443 free(connection->proxy);
1444 if (connection->userPwd != NULL)
1445 free(connection->userPwd);
1446 if (connection->proxyUserPwd != NULL)
1447 free(connection->proxyUserPwd);
1448 if (connection->range != NULL)
1449 free(connection->range);
1450 if (connection->errorBuffer != NULL)
1451 free(connection->range);
1452 if (connection->postFields != NULL)
1453 free(connection->postFields);
1454 if (connection->referer != NULL)
1455 free(connection->referer);
1456 if (connection->userAgent != NULL)
1457 free(connection->userAgent);
1458 if (connection->ftpPort != NULL)
1459 free(connection->ftpPort);
1460 if (connection->cookie != NULL)
1461 free(connection->cookie);
1462 if (connection->httpHeader != NULL)
1463 free_curl_slist(connection->httpHeader);
1464 if (connection->httpPostFirst != NULL)
1465 curl_formfree(connection->httpPostFirst);
1466 if (connection->httpPostStrings != NULL)
1467 free_curl_slist(connection->httpPostStrings);
1468 if (connection->sslCert != NULL)
1469 free(connection->sslCert);
1470 if (connection->sslCertType != NULL)
1471 free(connection->sslCertType);
1472 if (connection->sslCertPasswd != NULL)
1473 free(connection->sslCertPasswd);
1474 if (connection->sslKey != NULL)
1475 free(connection->sslKey);
1476 if (connection->sslKeyType != NULL)
1477 free(connection->sslKeyType);
1478 if (connection->sslKeyPasswd != NULL)
1479 free(connection->sslKeyPasswd);
1480 if (connection->sslEngine != NULL)
1481 free(connection->sslEngine);
1482 if (connection->quote != NULL)
1483 free_curl_slist(connection->quote);
1484 if (connection->postQuote != NULL)
1485 free_curl_slist(connection->postQuote);
1486 if (connection->cookieFile != NULL)
1487 free(connection->cookieFile);
1488 if (connection->customRequest != NULL)
1489 free(connection->customRequest);
1490 if (connection->interface != NULL)
1491 free(connection->interface);
1492 if (connection->caInfo != NULL)
1493 free(connection->caInfo);
1494 if (connection->caPath != NULL)
1495 free(connection->caPath);
1496 if (connection->randomFile != NULL)
1497 free(connection->randomFile);
1498 if (connection->egdSocket != NULL)
1499 free(connection->egdSocket);
1500 if (connection->cookieJar != NULL)
1501 free(connection->cookieJar);
1502 if (connection->sslCipherList != NULL)
1503 free(connection->sslCipherList);
1504 if (connection->private != NULL)
1505 free(connection->private);
1506 if (connection->http200Aliases != NULL)
1507 free_curl_slist(connection->http200Aliases);
1508 if (connection->netrcFile != NULL)
1509 free(connection->netrcFile);
1510 if (connection->ftpaccount != NULL)
1511 free(connection->ftpaccount);
1512 if (connection->cookielist != NULL)
1513 free(connection->cookielist);
1514 if (connection->ftpAlternativeToUser != NULL)
1515 free(connection->ftpAlternativeToUser);
1516 if (connection->sshPublicKeyFile != NULL)
1517 free(connection->sshPublicKeyFile);
1518 if (connection->sshPrivateKeyFile != NULL)
1519 free(connection->sshPrivateKeyFile);
1520 if (connection->copyPostFields != NULL)
1521 free(connection->copyPostFields);
1523 free(connection);
1526 static void checkConnection(Connection *connection)
1528 Connection *listIter;
1530 listIter = connectionList.tail;
1532 while (listIter != NULL)
1534 if (listIter == connection)
1535 return;
1537 listIter = listIter->next;
1540 failwith("Invalid Connection");
1543 static Connection* findConnection(CURL* h)
1545 Connection *listIter;
1547 listIter = connectionList.tail;
1549 while (listIter != NULL)
1551 if (listIter->connection == h)
1552 return listIter;
1554 listIter = listIter->next;
1557 failwith("Unknown handle");
1560 #define WRAP_DATA_CALLBACK(f) \
1561 static size_t f(char *ptr, size_t size, size_t nmemb, void *data)\
1563 size_t result;\
1564 leave_blocking_section();\
1565 result = f##_nolock(ptr,size,nmemb,data);\
1566 enter_blocking_section();\
1567 return result;\
1570 static size_t writeFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1572 CAMLparam0();
1573 CAMLlocal2(result, str);
1574 Connection *conn = (Connection *)data;
1575 int i;
1577 checkConnection(conn);
1579 str = alloc_string(size*nmemb);
1581 for (i = 0; i < size*nmemb; i++)
1582 Byte(str, i) = ptr[i];
1584 result = callback(Field(conn->ocamlValues, OcamlWriteCallback), str);
1586 CAMLreturnT(size_t, Int_val(result));
1589 WRAP_DATA_CALLBACK(writeFunction)
1591 static size_t readFunction_nolock(void *ptr, size_t size, size_t nmemb, void *data)
1593 CAMLparam0();
1594 CAMLlocal1(result);
1595 Connection *conn = (Connection *)data;
1596 int length;
1598 checkConnection(conn);
1600 result = callback(Field(conn->ocamlValues, OcamlReadCallback),
1601 Val_int(size*nmemb));
1603 length = string_length(result);
1605 if (length >= size*nmemb)
1606 length = size*nmemb;
1608 memcpy(ptr, String_val(result), length);
1610 CAMLreturnT(size_t,length);
1613 WRAP_DATA_CALLBACK(readFunction)
1615 static size_t headerFunction_nolock(char *ptr, size_t size, size_t nmemb, void *data)
1617 CAMLparam0();
1618 CAMLlocal2(result,str);
1619 Connection *conn = (Connection *)data;
1620 int i;
1622 checkConnection(conn);
1624 str = alloc_string(size*nmemb);
1626 for (i = 0; i < size*nmemb; i++)
1627 Byte(str, i) = ptr[i];
1629 result = callback(Field(conn->ocamlValues, OcamlHeaderCallback), str);
1631 CAMLreturnT(size_t, Int_val(result));
1634 WRAP_DATA_CALLBACK(headerFunction)
1636 static int progressFunction_nolock(void *data,
1637 double dlTotal,
1638 double dlNow,
1639 double ulTotal,
1640 double ulNow)
1642 CAMLparam0();
1643 CAMLlocal1(result);
1644 CAMLlocalN(callbackData, 4);
1645 Connection *conn = (Connection *)data;
1647 checkConnection(conn);
1649 callbackData[0] = copy_double(dlTotal);
1650 callbackData[1] = copy_double(dlNow);
1651 callbackData[2] = copy_double(ulTotal);
1652 callbackData[3] = copy_double(ulNow);
1654 result = callbackN(Field(conn->ocamlValues, OcamlProgressCallback),
1655 4, callbackData);
1657 CAMLreturnT(int, Bool_val(result));
1660 static int progressFunction(void *data,
1661 double dlTotal,
1662 double dlNow,
1663 double ulTotal,
1664 double ulNow)
1666 int r;
1667 leave_blocking_section();
1668 r = progressFunction_nolock(data,dlTotal,dlNow,ulTotal,ulNow);
1669 enter_blocking_section();
1670 return r;
1673 static int debugFunction_nolock(CURL *debugConnection,
1674 curl_infotype infoType,
1675 char *buffer,
1676 size_t bufferLength,
1677 void *data)
1679 CAMLparam0();
1680 CAMLlocal3(camlDebugConnection, camlInfoType, camlMessage);
1681 int i;
1682 Connection *conn = (Connection *)data;
1684 checkConnection(conn);
1686 camlDebugConnection = (value)conn;
1687 camlInfoType = Val_long(infoType);
1688 camlMessage = alloc_string(bufferLength);
1690 for (i = 0; i < bufferLength; i++)
1691 Byte(camlMessage, i) = buffer[i];
1693 callback3(Field(conn->ocamlValues, OcamlDebugCallback),
1694 camlDebugConnection,
1695 camlInfoType,
1696 camlMessage);
1698 CAMLreturnT(int, 0);
1701 static int debugFunction(CURL *debugConnection,
1702 curl_infotype infoType,
1703 char *buffer,
1704 size_t bufferLength,
1705 void *data)
1707 int r;
1708 leave_blocking_section();
1709 r = debugFunction_nolock(debugConnection, infoType, buffer, bufferLength, data);
1710 enter_blocking_section();
1711 return r;
1714 static curlioerr ioctlFunction_nolock(CURL *ioctl,
1715 int cmd,
1716 void *data)
1718 CAMLparam0();
1719 CAMLlocal3(camlResult, camlConnection, camlCmd);
1720 Connection *conn = (Connection *)data;
1721 curlioerr result = CURLIOE_OK;
1723 checkConnection(conn);
1725 if (cmd == CURLIOCMD_NOP)
1726 camlCmd = Val_long(0);
1727 else if (cmd == CURLIOCMD_RESTARTREAD)
1728 camlCmd = Val_long(1);
1729 else
1730 failwith("Invalid IOCTL Cmd!");
1732 camlConnection = caml_alloc(1, Abstract_tag);
1733 Field(camlConnection, 0) = (value)conn;
1735 camlResult = callback2(Field(conn->ocamlValues, OcamlIOCTLCallback),
1736 camlConnection,
1737 camlCmd);
1739 switch (Long_val(camlResult))
1741 case 0: /* CURLIOE_OK */
1742 result = CURLIOE_OK;
1743 break;
1745 case 1: /* CURLIOE_UNKNOWNCMD */
1746 result = CURLIOE_UNKNOWNCMD;
1747 break;
1749 case 2: /* CURLIOE_FAILRESTART */
1750 result = CURLIOE_FAILRESTART;
1751 break;
1753 default: /* Incorrect return value, but let's handle it */
1754 result = CURLIOE_FAILRESTART;
1755 break;
1758 CAMLreturnT(curlioerr, result);
1761 static curlioerr ioctlFunction(CURL *ioctl,
1762 int cmd,
1763 void *data)
1765 curlioerr r;
1766 leave_blocking_section();
1767 r = ioctlFunction_nolock(ioctl, cmd, data);
1768 enter_blocking_section();
1769 return r;
1772 #ifdef HAVE_DECL_CURLOPT_SEEKFUNCTION
1773 static int seekFunction_nolock(void *data,
1774 curl_off_t offset,
1775 int origin)
1777 CAMLparam0();
1778 CAMLlocal3(camlResult, camlOffset, camlOrigin);
1779 Connection *conn = (Connection *)data;
1780 int result = 0;
1782 camlOffset = copy_int64(offset);
1784 if (origin == SEEK_SET)
1785 camlOrigin = Val_long(0);
1786 else if (origin == SEEK_CUR)
1787 camlOrigin = Val_long(1);
1788 else if (origin == SEEK_END)
1789 camlOrigin = Val_long(2);
1790 else
1791 camlOrigin = Val_long(0);
1793 camlResult = callback2(Field(conn->ocamlValues,
1794 OcamlSeekFunctionCallback),
1795 camlOffset,
1796 camlOrigin);
1798 result = Int_val(camlResult);
1800 CAMLreturnT(int, result);
1803 static int seekFunction(void *data,
1804 curl_off_t offset,
1805 int origin)
1807 int r;
1808 leave_blocking_section();
1809 r = seekFunction_nolock(data,offset,origin);
1810 enter_blocking_section();
1811 return r;
1814 #endif
1817 ** curl_global_init helper function
1820 CAMLprim value helper_curl_global_init(value initOption)
1822 CAMLparam1(initOption);
1824 switch (Long_val(initOption))
1826 case 0: /* CURLINIT_GLOBALALL */
1827 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_ALL)));
1828 break;
1830 case 1: /* CURLINIT_GLOBALSSL */
1831 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_SSL)));
1832 break;
1834 case 2: /* CURLINIT_GLOBALWIN32 */
1835 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_WIN32)));
1836 break;
1838 case 3: /* CURLINIT_GLOBALNOTHING */
1839 CAMLreturn(Val_long(curl_global_init(CURL_GLOBAL_NOTHING)));
1840 break;
1842 default:
1843 failwith("Invalid Initialization Option");
1844 break;
1847 /* Keep compiler happy, we should never get here due to failwith() */
1848 CAMLreturn(Val_unit);
1852 ** curl_global_cleanup helper function
1855 CAMLprim value helper_curl_global_cleanup(void)
1857 CAMLparam0();
1859 curl_global_cleanup();
1861 CAMLreturn(Val_unit);
1865 ** curl_easy_init helper function
1868 CAMLprim value helper_curl_easy_init(void)
1870 CAMLparam0();
1871 CAMLlocal1(result);
1873 Connection *conn = newConnection();
1875 result = caml_alloc(1, Abstract_tag);
1876 Field(result, 0) = (value)conn;
1878 CAMLreturn(result);
1881 CAMLprim value helper_curl_easy_reset(value conn)
1883 CAMLparam1(conn);
1884 Connection *connection = Connection_val(conn);
1886 checkConnection(connection);
1887 curl_easy_reset(connection->connection);
1888 resetOcamlValues(connection);
1890 CAMLreturn(Val_unit);
1894 ** curl_easy_setopt helper utility functions
1897 static void handleWriteFunction(Connection *conn, value option)
1899 CAMLparam1(option);
1900 CURLcode result = CURLE_OK;
1902 if (Tag_val(option) == Closure_tag)
1903 Store_field(conn->ocamlValues, OcamlWriteCallback, option);
1904 else
1905 failwith("Not a proper closure");
1907 result = curl_easy_setopt(conn->connection,
1908 CURLOPT_WRITEFUNCTION,
1909 writeFunction);
1911 if (result != CURLE_OK)
1912 raiseError(conn, result);
1914 result = curl_easy_setopt(conn->connection,
1915 CURLOPT_WRITEDATA,
1916 conn);
1918 if (result != CURLE_OK)
1919 raiseError(conn, result);
1921 CAMLreturn0;
1924 static void handleReadFunction(Connection *conn, value option)
1926 CAMLparam1(option);
1927 CURLcode result = CURLE_OK;
1929 if (Tag_val(option) == Closure_tag)
1930 Store_field(conn->ocamlValues, OcamlReadCallback, option);
1931 else
1932 failwith("Not a proper closure");
1934 result = curl_easy_setopt(conn->connection,
1935 CURLOPT_READFUNCTION,
1936 readFunction);
1938 if (result != CURLE_OK)
1939 raiseError(conn, result);
1941 result = curl_easy_setopt(conn->connection,
1942 CURLOPT_READDATA,
1943 conn);
1945 if (result != CURLE_OK)
1946 raiseError(conn, result);
1948 CAMLreturn0;
1951 static void handleURL(Connection *conn, value option)
1953 CAMLparam1(option);
1954 CURLcode result = CURLE_OK;
1956 Store_field(conn->ocamlValues, OcamlURL, option);
1958 if (conn->url != NULL)
1959 free(conn->url);
1961 conn->url = strdup(String_val(option));
1963 result = curl_easy_setopt(conn->connection,
1964 CURLOPT_URL,
1965 conn->url);
1967 if (result != CURLE_OK)
1968 raiseError(conn, result);
1970 CAMLreturn0;
1973 static void handleInFileSize(Connection *conn, value option)
1975 CAMLparam1(option);
1976 CURLcode result = CURLE_OK;
1978 result = curl_easy_setopt(conn->connection,
1979 CURLOPT_INFILESIZE,
1980 Long_val(option));
1982 if (result != CURLE_OK)
1983 raiseError(conn, result);
1985 CAMLreturn0;
1988 static void handleProxy(Connection *conn, value option)
1990 CAMLparam1(option);
1991 CURLcode result = CURLE_OK;
1993 Store_field(conn->ocamlValues, OcamlProxy, option);
1995 if (conn->proxy != NULL)
1996 free(conn->proxy);
1998 conn->proxy = strdup(String_val(option));
2000 result = curl_easy_setopt(conn->connection,
2001 CURLOPT_PROXY,
2002 conn->proxy);
2004 if (result != CURLE_OK)
2005 raiseError(conn, result);
2007 CAMLreturn0;
2010 static void handleProxyPort(Connection *conn, value option)
2012 CAMLparam1(option);
2013 CURLcode result = CURLE_OK;
2015 result = curl_easy_setopt(conn->connection,
2016 CURLOPT_PROXYPORT,
2017 Long_val(option));
2019 if (result != CURLE_OK)
2020 raiseError(conn, result);
2022 CAMLreturn0;
2025 static void handleHTTPProxyTunnel(Connection *conn, value option)
2027 CAMLparam1(option);
2028 CURLcode result = CURLE_OK;
2030 result = curl_easy_setopt(conn->connection,
2031 CURLOPT_HTTPPROXYTUNNEL,
2032 Bool_val(option));
2034 if (result != CURLE_OK)
2035 raiseError(conn, result);
2037 CAMLreturn0;
2040 static void handleVerbose(Connection *conn, value option)
2042 CAMLparam1(option);
2043 CURLcode result = CURLE_OK;
2045 result = curl_easy_setopt(conn->connection,
2046 CURLOPT_VERBOSE,
2047 Bool_val(option));
2049 if (result != CURLE_OK)
2050 raiseError(conn, result);
2052 CAMLreturn0;
2055 static void handleHeader(Connection *conn, value option)
2057 CAMLparam1(option);
2058 CURLcode result = CURLE_OK;
2060 result = curl_easy_setopt(conn->connection,
2061 CURLOPT_HEADER,
2062 Bool_val(option));
2064 if (result != CURLE_OK)
2065 raiseError(conn, result);
2067 CAMLreturn0;
2070 static void handleNoProgress(Connection *conn, value option)
2072 CAMLparam1(option);
2073 CURLcode result = CURLE_OK;
2075 result = curl_easy_setopt(conn->connection,
2076 CURLOPT_NOPROGRESS,
2077 Bool_val(option));
2079 if (result != CURLE_OK)
2080 raiseError(conn, result);
2082 CAMLreturn0;
2085 static void handleNoSignal(Connection *conn, value option)
2087 #if HAVE_DECL_CURLOPT_NOSIGNAL
2088 CAMLparam1(option);
2089 CURLcode result = CURLE_OK;
2091 result = curl_easy_setopt(conn->connection,
2092 CURLOPT_NOSIGNAL,
2093 Bool_val(option));
2095 if (result != CURLE_OK)
2096 raiseError(conn, result);
2098 CAMLreturn0;
2099 #else
2100 #warning "libcurl does not implement CURLOPT_NOSIGNAL"
2101 failwith("libcurl does not implement CURLOPT_NOSIGNAL");
2102 #endif
2105 static void handleNoBody(Connection *conn, value option)
2107 CAMLparam1(option);
2108 CURLcode result = CURLE_OK;
2110 result = curl_easy_setopt(conn->connection,
2111 CURLOPT_NOBODY,
2112 Bool_val(option));
2114 if (result != CURLE_OK)
2115 raiseError(conn, result);
2117 CAMLreturn0;
2120 static void handleFailOnError(Connection *conn, value option)
2122 CAMLparam1(option);
2123 CURLcode result = CURLE_OK;
2125 result = curl_easy_setopt(conn->connection,
2126 CURLOPT_FAILONERROR,
2127 Bool_val(option));
2129 if (result != CURLE_OK)
2130 raiseError(conn, result);
2132 CAMLreturn0;
2135 static void handleUpload(Connection *conn, value option)
2137 CAMLparam1(option);
2138 CURLcode result = CURLE_OK;
2140 result = curl_easy_setopt(conn->connection,
2141 CURLOPT_UPLOAD,
2142 Bool_val(option));
2144 if (result != CURLE_OK)
2145 raiseError(conn, result);
2147 CAMLreturn0;
2150 static void handlePost(Connection *conn, value option)
2152 CAMLparam1(option);
2153 CURLcode result = CURLE_OK;
2155 result = curl_easy_setopt(conn->connection,
2156 CURLOPT_POST,
2157 Bool_val(option));
2159 if (result != CURLE_OK)
2160 raiseError(conn, result);
2162 CAMLreturn0;
2165 static void handleFTPListOnly(Connection *conn, value option)
2167 CAMLparam1(option);
2168 CURLcode result = CURLE_OK;
2170 result = curl_easy_setopt(conn->connection,
2171 CURLOPT_FTPLISTONLY,
2172 Bool_val(option));
2174 if (result != CURLE_OK)
2175 raiseError(conn, result);
2177 CAMLreturn0;
2180 static void handleFTPAppend(Connection *conn, value option)
2182 CAMLparam1(option);
2183 CURLcode result = CURLE_OK;
2185 result = curl_easy_setopt(conn->connection,
2186 CURLOPT_FTPAPPEND,
2187 Bool_val(option));
2189 if (result != CURLE_OK)
2190 raiseError(conn, result);
2192 CAMLreturn0;
2195 static void handleNETRC(Connection *conn, value option)
2197 CAMLparam1(option);
2198 CURLcode result = CURLE_OK;
2199 long netrc;
2201 switch (Long_val(option))
2203 case 0: /* CURL_NETRC_OPTIONAL */
2204 netrc = CURL_NETRC_OPTIONAL;
2205 break;
2207 case 1:/* CURL_NETRC_IGNORED */
2208 netrc = CURL_NETRC_IGNORED;
2209 break;
2211 case 2: /* CURL_NETRC_REQUIRED */
2212 netrc = CURL_NETRC_REQUIRED;
2213 break;
2215 default:
2216 failwith("Invalid NETRC Option");
2217 break;
2220 result = curl_easy_setopt(conn->connection,
2221 CURLOPT_NETRC,
2222 netrc);
2224 if (result != CURLE_OK)
2225 raiseError(conn, result);
2227 CAMLreturn0;
2230 static void handleEncoding(Connection *conn, value option)
2232 #if HAVE_DECL_CURLOPT_ENCODING
2233 CAMLparam1(option);
2234 CURLcode result = CURLE_OK;
2236 switch (Long_val(option))
2238 case 0: /* CURL_ENCODING_NONE */
2239 result = curl_easy_setopt(conn->connection,
2240 CURLOPT_ENCODING,
2241 "identity");
2242 break;
2244 case 1: /* CURL_ENCODING_DEFLATE */
2245 result = curl_easy_setopt(conn->connection,
2246 CURLOPT_ENCODING,
2247 "deflate");
2248 break;
2250 case 2: /* CURL_ENCODING_GZIP */
2251 result = curl_easy_setopt(conn->connection,
2252 CURLOPT_ENCODING,
2253 "gzip");
2254 break;
2256 case 3: /* CURL_ENCODING_ANY */
2257 result = curl_easy_setopt(conn->connection,
2258 CURLOPT_ENCODING,
2259 "");
2260 break;
2262 default:
2263 failwith("Invalid Encoding Option");
2264 break;
2267 if (result != CURLE_OK)
2268 raiseError(conn, result);
2270 CAMLreturn0;
2271 #else
2272 #warning "libcurl does not implement CURLOPT_ENCODING"
2273 failwith("libcurl does not implement CURLOPT_ENCODING");
2274 #endif
2277 static void handleFollowLocation(Connection *conn, value option)
2279 CAMLparam1(option);
2280 CURLcode result = CURLE_OK;
2282 result = curl_easy_setopt(conn->connection,
2283 CURLOPT_FOLLOWLOCATION,
2284 Bool_val(option));
2286 if (result != CURLE_OK)
2287 raiseError(conn, result);
2289 CAMLreturn0;
2292 static void handleTransferText(Connection *conn, value option)
2294 CAMLparam1(option);
2295 CURLcode result = CURLE_OK;
2297 result = curl_easy_setopt(conn->connection,
2298 CURLOPT_TRANSFERTEXT,
2299 Bool_val(option));
2301 if (result != CURLE_OK)
2302 raiseError(conn, result);
2304 CAMLreturn0;
2307 static void handlePut(Connection *conn, value option)
2309 CAMLparam1(option);
2310 CURLcode result = CURLE_OK;
2312 result = curl_easy_setopt(conn->connection,
2313 CURLOPT_PUT,
2314 Bool_val(option));
2316 if (result != CURLE_OK)
2317 raiseError(conn, result);
2319 CAMLreturn0;
2322 static void handleUserPwd(Connection *conn, value option)
2324 CAMLparam1(option);
2325 CURLcode result = CURLE_OK;
2327 Store_field(conn->ocamlValues, OcamlUserPWD, option);
2329 if (conn->userPwd != NULL)
2330 free(conn->userPwd);
2332 conn->userPwd = strdup(String_val(option));
2334 result = curl_easy_setopt(conn->connection,
2335 CURLOPT_USERPWD,
2336 conn->userPwd);
2338 if (result != CURLE_OK)
2339 raiseError(conn, result);
2341 CAMLreturn0;
2344 static void handleProxyUserPwd(Connection *conn, value option)
2346 CAMLparam1(option);
2347 CURLcode result = CURLE_OK;
2349 Store_field(conn->ocamlValues, OcamlProxyUserPWD, option);
2351 if (conn->proxyUserPwd != NULL)
2352 free(conn->proxyUserPwd);
2354 conn->proxyUserPwd = strdup(String_val(option));
2356 result = curl_easy_setopt(conn->connection,
2357 CURLOPT_PROXYUSERPWD,
2358 conn->proxyUserPwd);
2360 if (result != CURLE_OK)
2361 raiseError(conn, result);
2363 CAMLreturn0;
2366 static void handleRange(Connection *conn, value option)
2368 CAMLparam1(option);
2369 CURLcode result = CURLE_OK;
2371 Store_field(conn->ocamlValues, OcamlRange, option);
2373 if (conn->range != NULL)
2374 free(conn->range);
2376 conn->range = strdup(String_val(option));
2378 result = curl_easy_setopt(conn->connection,
2379 CURLOPT_RANGE,
2380 conn->range);
2382 if (result != CURLE_OK)
2383 raiseError(conn, result);
2385 CAMLreturn0;
2388 static void handleErrorBuffer(Connection *conn, value option)
2390 CAMLparam1(option);
2391 CURLcode result = CURLE_OK;
2393 Store_field(conn->ocamlValues, OcamlErrorBuffer, option);
2395 if (conn->errorBuffer != NULL)
2396 free(conn->errorBuffer);
2398 conn->errorBuffer = malloc(sizeof(char) * CURL_ERROR_SIZE);
2400 result = curl_easy_setopt(conn->connection,
2401 CURLOPT_ERRORBUFFER,
2402 conn->errorBuffer);
2404 if (result != CURLE_OK)
2405 raiseError(conn, result);
2407 CAMLreturn0;
2410 static void handleTimeout(Connection *conn, value option)
2412 CAMLparam1(option);
2413 CURLcode result = CURLE_OK;
2415 result = curl_easy_setopt(conn->connection,
2416 CURLOPT_TIMEOUT,
2417 Long_val(option));
2419 if (result != CURLE_OK)
2420 raiseError(conn, result);
2422 CAMLreturn0;
2425 static void handlePostFields(Connection *conn, value option)
2427 CAMLparam1(option);
2428 CURLcode result = CURLE_OK;
2430 Store_field(conn->ocamlValues, OcamlPostFields, option);
2432 if (conn->postFields != NULL)
2433 free(conn->postFields);
2435 conn->postFields = malloc(string_length(option)+1);
2436 memcpy(conn->postFields, String_val(option), string_length(option));
2438 result = curl_easy_setopt(conn->connection,
2439 CURLOPT_POSTFIELDS,
2440 conn->postFields);
2442 if (result != CURLE_OK)
2443 raiseError(conn, result);
2445 CAMLreturn0;
2448 static void handlePostFieldSize(Connection *conn, value option)
2450 CAMLparam1(option);
2451 CURLcode result = CURLE_OK;
2453 result = curl_easy_setopt(conn->connection,
2454 CURLOPT_POSTFIELDSIZE,
2455 Long_val(option));
2457 if (result != CURLE_OK)
2458 raiseError(conn, result);
2460 CAMLreturn0;
2463 static void handleReferer(Connection *conn, value option)
2465 CAMLparam1(option);
2466 CURLcode result = CURLE_OK;
2468 Store_field(conn->ocamlValues, OcamlReferer, option);
2470 if (conn->referer != NULL)
2471 free(conn->referer);
2473 conn->referer = strdup(String_val(option));
2475 result = curl_easy_setopt(conn->connection,
2476 CURLOPT_REFERER,
2477 conn->referer);
2479 if (result != CURLE_OK)
2480 raiseError(conn, result);
2482 CAMLreturn0;
2485 static void handleUserAgent(Connection *conn, value option)
2487 CAMLparam1(option);
2488 CURLcode result = CURLE_OK;
2490 Store_field(conn->ocamlValues, OcamlUserAgent, option);
2492 if (conn->userAgent != NULL)
2493 free(conn->userAgent);
2495 conn->userAgent = strdup(String_val(option));
2497 result = curl_easy_setopt(conn->connection,
2498 CURLOPT_USERAGENT,
2499 conn->userAgent);
2501 if (result != CURLE_OK)
2502 raiseError(conn, result);
2504 CAMLreturn0;
2507 static void handleFTPPort(Connection *conn, value option)
2509 CAMLparam1(option);
2510 CURLcode result = CURLE_OK;
2512 Store_field(conn->ocamlValues, OcamlFTPPort, option);
2514 if (conn->ftpPort != NULL)
2515 free(conn->ftpPort);
2517 conn->ftpPort = strdup(String_val(option));
2519 result = curl_easy_setopt(conn->connection,
2520 CURLOPT_FTPPORT,
2521 conn->ftpPort);
2523 if (result != CURLE_OK)
2524 raiseError(conn, result);
2526 CAMLreturn0;
2529 static void handleLowSpeedLimit(Connection *conn, value option)
2531 CAMLparam1(option);
2532 CURLcode result = CURLE_OK;
2534 result = curl_easy_setopt(conn->connection,
2535 CURLOPT_LOW_SPEED_LIMIT,
2536 Long_val(option));
2538 if (result != CURLE_OK)
2539 raiseError(conn, result);
2541 CAMLreturn0;
2544 static void handleLowSpeedTime(Connection *conn, value option)
2546 CAMLparam1(option);
2547 CURLcode result = CURLE_OK;
2549 result = curl_easy_setopt(conn->connection,
2550 CURLOPT_LOW_SPEED_TIME,
2551 Long_val(option));
2553 if (result != CURLE_OK)
2554 raiseError(conn, result);
2556 CAMLreturn0;
2559 static void handleResumeFrom(Connection *conn, value option)
2561 CAMLparam1(option);
2562 CURLcode result = CURLE_OK;
2564 result = curl_easy_setopt(conn->connection,
2565 CURLOPT_RESUME_FROM,
2566 Long_val(option));
2568 if (result != CURLE_OK)
2569 raiseError(conn, result);
2571 CAMLreturn0;
2574 static void handleCookie(Connection *conn, value option)
2576 CAMLparam1(option);
2577 CURLcode result = CURLE_OK;
2579 Store_field(conn->ocamlValues, OcamlCookie, option);
2581 if (conn->cookie != NULL)
2582 free(conn->cookie);
2584 conn->cookie = strdup(String_val(option));
2586 result = curl_easy_setopt(conn->connection,
2587 CURLOPT_COOKIE,
2588 conn->cookie);
2590 if (result != CURLE_OK)
2591 raiseError(conn, result);
2593 CAMLreturn0;
2596 static void handleHTTPHeader(Connection *conn, value option)
2598 CAMLparam1(option);
2599 CAMLlocal1(listIter);
2600 CURLcode result = CURLE_OK;
2601 char *str;
2603 Store_field(conn->ocamlValues, OcamlHTTPHeader, option);
2605 if (conn->httpHeader != NULL)
2606 free_curl_slist(conn->httpHeader);
2608 conn->httpHeader = NULL;
2610 listIter = option;
2612 while (!Is_long(listIter))
2614 if (Tag_val(Field(listIter, 0)) != String_tag)
2615 failwith("Not a string");
2617 str = strdup(String_val(Field(listIter, 0)));
2619 conn->httpHeader = curl_slist_append(conn->httpHeader, str);
2621 listIter = Field(listIter, 1);
2624 result = curl_easy_setopt(conn->connection,
2625 CURLOPT_HTTPHEADER,
2626 conn->httpHeader);
2628 if (result != CURLE_OK)
2629 raiseError(conn, result);
2631 CAMLreturn0;
2634 static void handleHTTPPost(Connection *conn, value option)
2636 CAMLparam1(option);
2637 CAMLlocal3(listIter, formItem, contentType);
2638 CURLcode result = CURLE_OK;
2639 char *str1, *str2, *str3, *str4;
2641 listIter = option;
2643 Store_field(conn->ocamlValues, OcamlHTTPPost, option);
2645 if (conn->httpPostFirst != NULL)
2646 curl_formfree(conn->httpPostFirst);
2648 conn->httpPostFirst = NULL;
2649 conn->httpPostLast = NULL;
2651 if (conn->httpPostStrings != NULL)
2652 free_curl_slist(conn->httpPostStrings);
2654 while (!Is_long(listIter))
2656 formItem = Field(listIter, 0);
2658 switch (Tag_val(formItem))
2660 case 0: /* CURLFORM_CONTENT */
2661 if (Wosize_val(formItem) < 3)
2663 failwith("Incorrect CURLFORM_CONTENT parameters");
2666 if (Is_long(Field(formItem, 2)) &&
2667 Long_val(Field(formItem, 2)) == 0)
2669 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2670 memcpy(str1,
2671 String_val(Field(formItem, 0)),
2672 string_length(Field(formItem, 0)));
2673 str1[string_length(Field(formItem, 0))] = 0;
2674 conn->httpPostStrings =
2675 curl_slist_append(conn->httpPostStrings, str1);
2677 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2678 memcpy(str2,
2679 String_val(Field(formItem, 1)),
2680 string_length(Field(formItem, 1)));
2681 str2[string_length(Field(formItem, 1))] = 0;
2682 conn->httpPostStrings =
2683 curl_slist_append(conn->httpPostStrings, str2);
2685 curl_formadd(&conn->httpPostFirst,
2686 &conn->httpPostLast,
2687 CURLFORM_PTRNAME,
2688 str1,
2689 CURLFORM_NAMELENGTH,
2690 string_length(Field(formItem, 0)),
2691 CURLFORM_PTRCONTENTS,
2692 str2,
2693 CURLFORM_CONTENTSLENGTH,
2694 string_length(Field(formItem, 1)),
2695 CURLFORM_END);
2697 else if (Is_block(Field(formItem, 2)))
2699 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2700 memcpy(str1,
2701 String_val(Field(formItem, 0)),
2702 string_length(Field(formItem, 0)));
2703 str1[string_length(Field(formItem, 0))] = 0;
2704 conn->httpPostStrings =
2705 curl_slist_append(conn->httpPostStrings, str1);
2707 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2708 memcpy(str2,
2709 String_val(Field(formItem, 1)),
2710 string_length(Field(formItem, 1)));
2711 str2[string_length(Field(formItem, 1))] = 0;
2712 conn->httpPostStrings =
2713 curl_slist_append(conn->httpPostStrings, str2);
2715 contentType = Field(formItem, 2);
2717 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2718 memcpy(str3,
2719 String_val(Field(contentType, 0)),
2720 string_length(Field(contentType, 0)));
2721 str3[string_length(Field(contentType, 0))] = 0;
2722 conn->httpPostStrings =
2723 curl_slist_append(conn->httpPostStrings, str3);
2725 curl_formadd(&conn->httpPostFirst,
2726 &conn->httpPostLast,
2727 CURLFORM_PTRNAME,
2728 str1,
2729 CURLFORM_NAMELENGTH,
2730 string_length(Field(formItem, 0)),
2731 CURLFORM_PTRCONTENTS,
2732 str2,
2733 CURLFORM_CONTENTSLENGTH,
2734 string_length(Field(formItem, 1)),
2735 CURLFORM_CONTENTTYPE,
2736 str3,
2737 CURLFORM_END);
2739 else
2741 failwith("Incorrect CURLFORM_CONTENT parameters");
2743 break;
2745 case 1: /* CURLFORM_FILECONTENT */
2746 if (Wosize_val(formItem) < 3)
2748 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2751 if (Is_long(Field(formItem, 2)) &&
2752 Long_val(Field(formItem, 2)) == 0)
2754 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2755 memcpy(str1,
2756 String_val(Field(formItem, 0)),
2757 string_length(Field(formItem, 0)));
2758 str1[string_length(Field(formItem, 0))] = 0;
2759 conn->httpPostStrings =
2760 curl_slist_append(conn->httpPostStrings, str1);
2762 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2763 memcpy(str2,
2764 String_val(Field(formItem, 1)),
2765 string_length(Field(formItem, 1)));
2766 str2[string_length(Field(formItem, 1))] = 0;
2767 conn->httpPostStrings =
2768 curl_slist_append(conn->httpPostStrings, str2);
2770 curl_formadd(&conn->httpPostFirst,
2771 &conn->httpPostLast,
2772 CURLFORM_PTRNAME,
2773 str1,
2774 CURLFORM_NAMELENGTH,
2775 string_length(Field(formItem, 0)),
2776 CURLFORM_FILECONTENT,
2777 str2,
2778 CURLFORM_END);
2780 else if (Is_block(Field(formItem, 2)))
2782 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2783 memcpy(str1,
2784 String_val(Field(formItem, 0)),
2785 string_length(Field(formItem, 0)));
2786 str1[string_length(Field(formItem, 0))] = 0;
2787 conn->httpPostStrings =
2788 curl_slist_append(conn->httpPostStrings, str1);
2790 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2791 memcpy(str2,
2792 String_val(Field(formItem, 1)),
2793 string_length(Field(formItem, 1)));
2794 str2[string_length(Field(formItem, 1))] = 0;
2795 conn->httpPostStrings =
2796 curl_slist_append(conn->httpPostStrings, str2);
2798 contentType = Field(formItem, 2);
2800 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2801 memcpy(str3,
2802 String_val(Field(contentType, 0)),
2803 string_length(Field(contentType, 0)));
2804 str3[string_length(Field(contentType, 0))] = 0;
2805 conn->httpPostStrings =
2806 curl_slist_append(conn->httpPostStrings, str3);
2808 curl_formadd(&conn->httpPostFirst,
2809 &conn->httpPostLast,
2810 CURLFORM_PTRNAME,
2811 str1,
2812 CURLFORM_NAMELENGTH,
2813 string_length(Field(formItem, 0)),
2814 CURLFORM_FILECONTENT,
2815 str2,
2816 CURLFORM_CONTENTTYPE,
2817 str3,
2818 CURLFORM_END);
2820 else
2822 failwith("Incorrect CURLFORM_FILECONTENT parameters");
2824 break;
2826 case 2: /* CURLFORM_FILE */
2827 if (Wosize_val(formItem) < 3)
2829 failwith("Incorrect CURLFORM_FILE parameters");
2832 if (Is_long(Field(formItem, 2)) &&
2833 Long_val(Field(formItem, 2)) == 0)
2835 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2836 memcpy(str1,
2837 String_val(Field(formItem, 0)),
2838 string_length(Field(formItem, 0)));
2839 str1[string_length(Field(formItem, 0))] = 0;
2840 conn->httpPostStrings =
2841 curl_slist_append(conn->httpPostStrings, str1);
2843 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2844 memcpy(str2,
2845 String_val(Field(formItem, 1)),
2846 string_length(Field(formItem, 1)));
2847 str2[string_length(Field(formItem, 1))] = 0;
2848 conn->httpPostStrings =
2849 curl_slist_append(conn->httpPostStrings, str2);
2851 curl_formadd(&conn->httpPostFirst,
2852 &conn->httpPostLast,
2853 CURLFORM_PTRNAME,
2854 str1,
2855 CURLFORM_NAMELENGTH,
2856 string_length(Field(formItem, 0)),
2857 CURLFORM_FILE,
2858 str2,
2859 CURLFORM_END);
2861 else if (Is_block(Field(formItem, 2)))
2863 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2864 memcpy(str1,
2865 String_val(Field(formItem, 0)),
2866 string_length(Field(formItem, 0)));
2867 str1[string_length(Field(formItem, 0))] = 0;
2868 conn->httpPostStrings =
2869 curl_slist_append(conn->httpPostStrings, str1);
2871 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2872 memcpy(str2,
2873 String_val(Field(formItem, 1)),
2874 string_length(Field(formItem, 1)));
2875 str2[string_length(Field(formItem, 1))] = 0;
2876 conn->httpPostStrings =
2877 curl_slist_append(conn->httpPostStrings, str2);
2879 contentType = Field(formItem, 2);
2881 str3 = (char *)malloc(string_length(Field(contentType, 0))+1);
2882 memcpy(str3,
2883 String_val(Field(contentType, 0)),
2884 string_length(Field(contentType, 0)));
2885 str3[string_length(Field(contentType, 0))] = 0;
2886 conn->httpPostStrings =
2887 curl_slist_append(conn->httpPostStrings, str3);
2889 curl_formadd(&conn->httpPostFirst,
2890 &conn->httpPostLast,
2891 CURLFORM_PTRNAME,
2892 str1,
2893 CURLFORM_NAMELENGTH,
2894 string_length(Field(formItem, 0)),
2895 CURLFORM_FILE,
2896 str2,
2897 CURLFORM_CONTENTTYPE,
2898 str3,
2899 CURLFORM_END);
2901 else
2903 failwith("Incorrect CURLFORM_FILE parameters");
2905 break;
2907 case 3: /* CURLFORM_BUFFER */
2908 if (Wosize_val(formItem) < 4)
2910 failwith("Incorrect CURLFORM_BUFFER parameters");
2913 if (Is_long(Field(formItem, 3)) &&
2914 Long_val(Field(formItem, 3)) == 0)
2916 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2917 memcpy(str1,
2918 String_val(Field(formItem, 0)),
2919 string_length(Field(formItem, 0)));
2920 str1[string_length(Field(formItem, 0))] = 0;
2921 conn->httpPostStrings =
2922 curl_slist_append(conn->httpPostStrings, str1);
2924 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2925 memcpy(str2,
2926 String_val(Field(formItem, 1)),
2927 string_length(Field(formItem, 1)));
2928 str2[string_length(Field(formItem, 1))] = 0;
2929 conn->httpPostStrings =
2930 curl_slist_append(conn->httpPostStrings, str2);
2932 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2933 memcpy(str3,
2934 String_val(Field(formItem, 2)),
2935 string_length(Field(formItem, 2)));
2936 str3[string_length(Field(formItem, 2))] = 0;
2937 conn->httpPostStrings =
2938 curl_slist_append(conn->httpPostStrings, str3);
2940 curl_formadd(&conn->httpPostFirst,
2941 &conn->httpPostLast,
2942 CURLFORM_PTRNAME,
2943 str1,
2944 CURLFORM_NAMELENGTH,
2945 string_length(Field(formItem, 0)),
2946 CURLFORM_BUFFER,
2947 str2,
2948 CURLFORM_BUFFERPTR,
2949 str3,
2950 CURLFORM_BUFFERLENGTH,
2951 string_length(Field(formItem, 2)),
2952 CURLFORM_END);
2954 else if (Is_block(Field(formItem, 3)))
2956 str1 = (char *)malloc(string_length(Field(formItem, 0))+1);
2957 memcpy(str1,
2958 String_val(Field(formItem, 0)),
2959 string_length(Field(formItem, 0)));
2960 str1[string_length(Field(formItem, 0))] = 0;
2961 conn->httpPostStrings =
2962 curl_slist_append(conn->httpPostStrings, str1);
2964 str2 = (char *)malloc(string_length(Field(formItem, 1))+1);
2965 memcpy(str2,
2966 String_val(Field(formItem, 1)),
2967 string_length(Field(formItem, 1)));
2968 str2[string_length(Field(formItem, 1))] = 0;
2969 conn->httpPostStrings =
2970 curl_slist_append(conn->httpPostStrings, str2);
2972 str3 = (char *)malloc(string_length(Field(formItem, 2))+1);
2973 memcpy(str3,
2974 String_val(Field(formItem, 2)),
2975 string_length(Field(formItem, 2)));
2976 str3[string_length(Field(formItem, 2))] = 0;
2977 conn->httpPostStrings =
2978 curl_slist_append(conn->httpPostStrings, str3);
2980 contentType = Field(formItem, 3);
2982 str4 = (char *)malloc(string_length(Field(contentType, 0))+1);
2983 memcpy(str4,
2984 String_val(Field(contentType, 0)),
2985 string_length(Field(contentType, 0)));
2986 str4[string_length(Field(contentType, 0))] = 0;
2987 conn->httpPostStrings =
2988 curl_slist_append(conn->httpPostStrings, str4);
2990 curl_formadd(&conn->httpPostFirst,
2991 &conn->httpPostLast,
2992 CURLFORM_PTRNAME,
2993 str1,
2994 CURLFORM_NAMELENGTH,
2995 string_length(Field(formItem, 0)),
2996 CURLFORM_BUFFER,
2997 str2,
2998 CURLFORM_BUFFERPTR,
2999 str3,
3000 CURLFORM_BUFFERLENGTH,
3001 string_length(Field(formItem, 2)),
3002 CURLFORM_CONTENTTYPE,
3003 str4,
3004 CURLFORM_END);
3006 else
3008 failwith("Incorrect CURLFORM_BUFFER parameters");
3010 break;
3013 listIter = Field(listIter, 1);
3016 result = curl_easy_setopt(conn->connection,
3017 CURLOPT_HTTPPOST,
3018 conn->httpPostFirst);
3020 if (result != CURLE_OK)
3021 raiseError(conn, result);
3023 CAMLreturn0;
3026 static void handleSSLCert(Connection *conn, value option)
3028 CAMLparam1(option);
3029 CURLcode result = CURLE_OK;
3031 Store_field(conn->ocamlValues, OcamlSSLCert, option);
3033 if (conn->sslCert != NULL)
3034 free(conn->sslCert);
3036 conn->sslCert = strdup(String_val(option));
3038 result = curl_easy_setopt(conn->connection,
3039 CURLOPT_SSLCERT,
3040 conn->sslCert);
3042 if (result != CURLE_OK)
3043 raiseError(conn, result);
3045 CAMLreturn0;
3048 static void handleSSLCertType(Connection *conn, value option)
3050 CAMLparam1(option);
3051 CURLcode result = CURLE_OK;
3053 Store_field(conn->ocamlValues, OcamlSSLCertType, option);
3055 if (conn->sslCertType != NULL)
3056 free(conn->sslCertType);
3058 conn->sslCertType = strdup(String_val(option));
3060 result = curl_easy_setopt(conn->connection,
3061 CURLOPT_SSLCERTTYPE,
3062 conn->sslCertType);
3064 if (result != CURLE_OK)
3065 raiseError(conn, result);
3067 CAMLreturn0;
3070 static void handleSSLCertPasswd(Connection *conn, value option)
3072 CAMLparam1(option);
3073 CURLcode result = CURLE_OK;
3075 Store_field(conn->ocamlValues, OcamlSSLCertPasswd, option);
3077 if (conn->sslCertPasswd != NULL)
3078 free(conn->sslCertPasswd);
3080 conn->sslCertPasswd = strdup(String_val(option));
3082 result = curl_easy_setopt(conn->connection,
3083 CURLOPT_SSLCERTPASSWD,
3084 conn->sslCertPasswd);
3086 if (result != CURLE_OK)
3087 raiseError(conn, result);
3089 CAMLreturn0;
3092 static void handleSSLKey(Connection *conn, value option)
3094 CAMLparam1(option);
3095 CURLcode result = CURLE_OK;
3097 Store_field(conn->ocamlValues, OcamlSSLKey, option);
3099 if (conn->sslKey != NULL)
3100 free(conn->sslKey);
3102 conn->sslKey = strdup(String_val(option));
3104 result = curl_easy_setopt(conn->connection,
3105 CURLOPT_SSLKEY,
3106 conn->sslKey);
3108 if (result != CURLE_OK)
3109 raiseError(conn, result);
3111 CAMLreturn0;
3114 static void handleSSLKeyType(Connection *conn, value option)
3116 CAMLparam1(option);
3117 CURLcode result = CURLE_OK;
3119 Store_field(conn->ocamlValues, OcamlSSLKeyType, option);
3121 if (conn->sslKeyType != NULL)
3122 free(conn->sslKeyType);
3124 conn->sslKeyType = strdup(String_val(option));
3126 result = curl_easy_setopt(conn->connection,
3127 CURLOPT_SSLKEYTYPE,
3128 conn->sslKeyType);
3130 if (result != CURLE_OK)
3131 raiseError(conn, result);
3133 CAMLreturn0;
3136 static void handleSSLKeyPasswd(Connection *conn, value option)
3138 CAMLparam1(option);
3139 CURLcode result = CURLE_OK;
3141 Store_field(conn->ocamlValues, OcamlSSLKeyPasswd, option);
3143 if (conn->sslKeyPasswd != NULL)
3144 free(conn->sslKeyPasswd);
3146 conn->sslKeyPasswd = strdup(String_val(option));
3148 result = curl_easy_setopt(conn->connection,
3149 CURLOPT_SSLKEYPASSWD,
3150 conn->sslKeyPasswd);
3152 if (result != CURLE_OK)
3153 raiseError(conn, result);
3155 CAMLreturn0;
3158 static void handleSSLEngine(Connection *conn, value option)
3160 CAMLparam1(option);
3161 CURLcode result = CURLE_OK;
3163 Store_field(conn->ocamlValues, OcamlSSLEngine, option);
3165 if (conn->sslEngine != NULL)
3166 free(conn->sslEngine);
3168 conn->sslEngine = strdup(String_val(option));
3170 result = curl_easy_setopt(conn->connection,
3171 CURLOPT_SSLENGINE,
3172 conn->sslEngine);
3174 if (result != CURLE_OK)
3175 raiseError(conn, result);
3177 CAMLreturn0;
3180 static void handleSSLEngineDefault(Connection *conn, value option)
3182 CAMLparam1(option);
3183 CURLcode result = CURLE_OK;
3185 result = curl_easy_setopt(conn->connection,
3186 CURLOPT_SSLENGINE_DEFAULT,
3187 Bool_val(option));
3189 if (result != CURLE_OK)
3190 raiseError(conn, result);
3192 CAMLreturn0;
3195 static void handleCRLF(Connection *conn, value option)
3197 CAMLparam1(option);
3198 CURLcode result = CURLE_OK;
3200 result = curl_easy_setopt(conn->connection,
3201 CURLOPT_CRLF,
3202 Bool_val(option));
3204 if (result != CURLE_OK)
3205 raiseError(conn, result);
3207 CAMLreturn0;
3210 static void handleQuote(Connection *conn, value option)
3212 CAMLparam1(option);
3213 CAMLlocal1(listIter);
3214 CURLcode result = CURLE_OK;
3215 char *str;
3217 Store_field(conn->ocamlValues, OcamlQuote, option);
3219 if (conn->quote != NULL)
3220 free_curl_slist(conn->quote);
3222 conn->quote = NULL;
3224 listIter = option;
3226 while (!Is_long(listIter))
3228 if (Tag_val(Field(listIter, 0)) != String_tag)
3229 failwith("Not a string");
3231 str = strdup(String_val(Field(listIter, 0)));
3233 conn->quote = curl_slist_append(conn->quote, str);
3235 listIter = Field(listIter, 1);
3238 result = curl_easy_setopt(conn->connection,
3239 CURLOPT_QUOTE,
3240 conn->quote);
3242 if (result != CURLE_OK)
3243 raiseError(conn, result);
3245 CAMLreturn0;
3248 static void handlePostQuote(Connection *conn, value option)
3250 CAMLparam1(option);
3251 CAMLlocal1(listIter);
3252 CURLcode result = CURLE_OK;
3253 char *str;
3255 Store_field(conn->ocamlValues, OcamlPostQuote, option);
3257 if (conn->postQuote != NULL)
3258 free_curl_slist(conn->postQuote);
3260 conn->postQuote = NULL;
3262 listIter = option;
3264 while (!Is_long(listIter))
3266 if (Tag_val(Field(listIter, 0)) != String_tag)
3267 failwith("Not a string");
3269 str = strdup(String_val(Field(listIter, 0)));
3271 conn->postQuote = curl_slist_append(conn->postQuote, str);
3273 listIter = Field(listIter, 1);
3276 result = curl_easy_setopt(conn->connection,
3277 CURLOPT_POSTQUOTE,
3278 conn->postQuote);
3280 if (result != CURLE_OK)
3281 raiseError(conn, result);
3283 CAMLreturn0;
3286 static void handleHeaderFunction(Connection *conn, value option)
3288 CAMLparam1(option);
3289 CURLcode result = CURLE_OK;
3291 if (Tag_val(option) == Closure_tag)
3292 Store_field(conn->ocamlValues, OcamlHeaderCallback, option);
3293 else
3294 failwith("Not a proper closure");
3296 result = curl_easy_setopt(conn->connection,
3297 CURLOPT_HEADERFUNCTION,
3298 headerFunction);
3300 if (result != CURLE_OK)
3301 raiseError(conn, result);
3303 result = curl_easy_setopt(conn->connection,
3304 CURLOPT_WRITEHEADER,
3305 conn);
3307 if (result != CURLE_OK)
3308 raiseError(conn, result);
3310 CAMLreturn0;
3313 static void handleCookieFile(Connection *conn, value option)
3315 CAMLparam1(option);
3316 CURLcode result = CURLE_OK;
3318 Store_field(conn->ocamlValues, OcamlCookieFile, option);
3320 if (conn->cookieFile != NULL)
3321 free(conn->cookieFile);
3323 conn->cookieFile = strdup(String_val(option));
3325 result = curl_easy_setopt(conn->connection,
3326 CURLOPT_COOKIEFILE,
3327 conn->cookieFile);
3329 if (result != CURLE_OK)
3330 raiseError(conn, result);
3332 CAMLreturn0;
3335 static void handleSSLVersion(Connection *conn, value option)
3337 CAMLparam1(option);
3338 CURLcode result = CURLE_OK;
3340 result = curl_easy_setopt(conn->connection,
3341 CURLOPT_SSLVERSION,
3342 Long_val(option));
3344 if (result != CURLE_OK)
3345 raiseError(conn, result);
3347 CAMLreturn0;
3350 static void handleTimeCondition(Connection *conn, value option)
3352 CAMLparam1(option);
3353 CURLcode result = CURLE_OK;
3355 switch (Long_val(option))
3357 case 0: /* TIMECOND_IFMODSINCE */
3358 result = curl_easy_setopt(conn->connection,
3359 CURLOPT_TIMECONDITION,
3360 CURL_TIMECOND_IFMODSINCE);
3361 break;
3363 case 1: /* TIMECOND_IFUNMODSINCE */
3364 result = curl_easy_setopt(conn->connection,
3365 CURLOPT_TIMECONDITION,
3366 CURL_TIMECOND_IFUNMODSINCE);
3367 break;
3369 default:
3370 failwith("Invalid TIMECOND Option");
3371 break;
3374 if (result != CURLE_OK)
3375 raiseError(conn, result);
3377 CAMLreturn0;
3380 static void handleTimeValue(Connection *conn, value option)
3382 CAMLparam1(option);
3383 CURLcode result = CURLE_OK;
3385 result = curl_easy_setopt(conn->connection,
3386 CURLOPT_TIMEVALUE,
3387 Int32_val(option));
3389 if (result != CURLE_OK)
3390 raiseError(conn, result);
3392 CAMLreturn0;
3395 static void handleCustomRequest(Connection *conn, value option)
3397 CAMLparam1(option);
3398 CURLcode result = CURLE_OK;
3400 Store_field(conn->ocamlValues, OcamlCustomRequest, option);
3402 if (conn->customRequest != NULL)
3403 free(conn->customRequest);
3405 conn->customRequest = strdup(String_val(option));
3407 result = curl_easy_setopt(conn->connection,
3408 CURLOPT_CUSTOMREQUEST,
3409 conn->customRequest);
3411 if (result != CURLE_OK)
3412 raiseError(conn, result);
3414 CAMLreturn0;
3417 static void handleInterface(Connection *conn, value option)
3419 CAMLparam1(option);
3420 CURLcode result = CURLE_OK;
3422 Store_field(conn->ocamlValues, OcamlInterface, option);
3424 if (conn->interface != NULL)
3425 free(conn->interface);
3427 conn->interface = strdup(String_val(option));
3429 result = curl_easy_setopt(conn->connection,
3430 CURLOPT_INTERFACE,
3431 conn->interface);
3433 if (result != CURLE_OK)
3434 raiseError(conn, result);
3436 CAMLreturn0;
3439 static void handleKRB4Level(Connection *conn, value option)
3441 CAMLparam1(option);
3442 CURLcode result = CURLE_OK;
3444 switch (Long_val(option))
3446 case 0: /* KRB4_NONE */
3447 result = curl_easy_setopt(conn->connection,
3448 CURLOPT_KRB4LEVEL,
3449 NULL);
3450 break;
3452 case 1: /* KRB4_CLEAR */
3453 result = curl_easy_setopt(conn->connection,
3454 CURLOPT_KRB4LEVEL,
3455 "clear");
3456 break;
3458 case 2: /* KRB4_SAFE */
3459 result = curl_easy_setopt(conn->connection,
3460 CURLOPT_KRB4LEVEL,
3461 "safe");
3462 break;
3464 case 3: /* KRB4_CONFIDENTIAL */
3465 result = curl_easy_setopt(conn->connection,
3466 CURLOPT_KRB4LEVEL,
3467 "confidential");
3468 break;
3470 case 4: /* KRB4_PRIVATE */
3471 result = curl_easy_setopt(conn->connection,
3472 CURLOPT_KRB4LEVEL,
3473 "private");
3474 break;
3476 default:
3477 failwith("Invalid KRB4 Option");
3478 break;
3481 if (result != CURLE_OK)
3482 raiseError(conn, result);
3484 CAMLreturn0;
3487 static void handleProgressFunction(Connection *conn, value option)
3489 CAMLparam1(option);
3490 CURLcode result = CURLE_OK;
3492 if (Tag_val(option) == Closure_tag)
3493 Store_field(conn->ocamlValues, OcamlProgressCallback, option);
3494 else
3495 failwith("Not a proper closure");
3497 result = curl_easy_setopt(conn->connection,
3498 CURLOPT_PROGRESSFUNCTION,
3499 progressFunction);
3500 if (result != CURLE_OK)
3501 raiseError(conn, result);
3503 result = curl_easy_setopt(conn->connection,
3504 CURLOPT_PROGRESSDATA,
3505 conn);
3507 if (result != CURLE_OK)
3508 raiseError(conn, result);
3510 CAMLreturn0;
3513 static void handleSSLVerifyPeer(Connection *conn, value option)
3515 CAMLparam1(option);
3516 CURLcode result = CURLE_OK;
3518 result = curl_easy_setopt(conn->connection,
3519 CURLOPT_SSL_VERIFYPEER,
3520 Bool_val(option));
3522 if (result != CURLE_OK)
3523 raiseError(conn, result);
3525 CAMLreturn0;
3528 static void handleCAInfo(Connection *conn, value option)
3530 CAMLparam1(option);
3531 CURLcode result = CURLE_OK;
3533 Store_field(conn->ocamlValues, OcamlCAInfo, option);
3535 if (conn->caInfo != NULL)
3536 free(conn->caInfo);
3538 conn->caInfo = strdup(String_val(option));
3540 result = curl_easy_setopt(conn->connection,
3541 CURLOPT_CAINFO,
3542 conn->caInfo);
3544 if (result != CURLE_OK)
3545 raiseError(conn, result);
3547 CAMLreturn0;
3550 static void handleCAPath(Connection *conn, value option)
3552 CAMLparam1(option);
3553 CURLcode result = CURLE_OK;
3555 Store_field(conn->ocamlValues, OcamlCAPath, option);
3557 if (conn->caPath != NULL)
3558 free(conn->caPath);
3560 conn->caPath = strdup(String_val(option));
3562 result = curl_easy_setopt(conn->connection,
3563 CURLOPT_CAPATH,
3564 conn->caPath);
3566 if (result != CURLE_OK)
3567 raiseError(conn, result);
3569 CAMLreturn0;
3572 static void handleFileTime(Connection *conn, value option)
3574 CAMLparam1(option);
3575 CURLcode result = CURLE_OK;
3577 result = curl_easy_setopt(conn->connection,
3578 CURLOPT_FILETIME,
3579 Bool_val(option));
3581 if (result != CURLE_OK)
3582 raiseError(conn, result);
3584 CAMLreturn0;
3587 static void handleMaxRedirs(Connection *conn, value option)
3589 CAMLparam1(option);
3590 CURLcode result = CURLE_OK;
3592 result = curl_easy_setopt(conn->connection,
3593 CURLOPT_MAXREDIRS,
3594 Long_val(option));
3596 if (result != CURLE_OK)
3597 raiseError(conn, result);
3599 CAMLreturn0;
3602 static void handleMaxConnects(Connection *conn, value option)
3604 CAMLparam1(option);
3605 CURLcode result = CURLE_OK;
3607 result = curl_easy_setopt(conn->connection,
3608 CURLOPT_MAXCONNECTS,
3609 Long_val(option));
3611 if (result != CURLE_OK)
3612 raiseError(conn, result);
3614 CAMLreturn0;
3617 static void handleClosePolicy(Connection *conn, value option)
3619 CAMLparam1(option);
3620 CURLcode result = CURLE_OK;
3622 switch (Long_val(option))
3624 case 0: /* CLOSEPOLICY_OLDEST */
3625 result = curl_easy_setopt(conn->connection,
3626 CURLOPT_CLOSEPOLICY,
3627 CURLCLOSEPOLICY_OLDEST);
3628 break;
3630 case 1: /* CLOSEPOLICY_LEAST_RECENTLY_USED */
3631 result = curl_easy_setopt(conn->connection,
3632 CURLOPT_CLOSEPOLICY,
3633 CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
3634 break;
3636 default:
3637 failwith("Invalid CLOSEPOLICY Option");
3638 break;
3641 if (result != CURLE_OK)
3642 raiseError(conn, result);
3644 CAMLreturn0;
3647 static void handleFreshConnect(Connection *conn, value option)
3649 CAMLparam1(option);
3650 CURLcode result = CURLE_OK;
3652 result = curl_easy_setopt(conn->connection,
3653 CURLOPT_FRESH_CONNECT,
3654 Bool_val(option));
3656 if (result != CURLE_OK)
3657 raiseError(conn, result);
3659 CAMLreturn0;
3662 static void handleForbidReuse(Connection *conn, value option)
3664 CAMLparam1(option);
3665 CURLcode result = CURLE_OK;
3667 result = curl_easy_setopt(conn->connection,
3668 CURLOPT_FORBID_REUSE,
3669 Bool_val(option));
3671 if (result != CURLE_OK)
3672 raiseError(conn, result);
3674 CAMLreturn0;
3677 static void handleRandomFile(Connection *conn, value option)
3679 CAMLparam1(option);
3680 CURLcode result = CURLE_OK;
3682 Store_field(conn->ocamlValues, OcamlRandomFile, option);
3684 if (conn->randomFile != NULL)
3685 free(conn->randomFile);
3687 conn->randomFile = strdup(String_val(option));
3689 result = curl_easy_setopt(conn->connection,
3690 CURLOPT_RANDOM_FILE,
3691 conn->randomFile);
3693 if (result != CURLE_OK)
3694 raiseError(conn, result);
3696 CAMLreturn0;
3699 static void handleEGDSocket(Connection *conn, value option)
3701 CAMLparam1(option);
3702 CURLcode result = CURLE_OK;
3704 Store_field(conn->ocamlValues, OcamlEGDSocket, option);
3706 if (conn->egdSocket != NULL)
3707 free(conn->egdSocket);
3709 conn->egdSocket = strdup(String_val(option));
3711 result = curl_easy_setopt(conn->connection,
3712 CURLOPT_EGDSOCKET,
3713 conn->egdSocket);
3715 if (result != CURLE_OK)
3716 raiseError(conn, result);
3718 CAMLreturn0;
3721 static void handleConnectTimeout(Connection *conn, value option)
3723 CAMLparam1(option);
3724 CURLcode result = CURLE_OK;
3726 result = curl_easy_setopt(conn->connection,
3727 CURLOPT_CONNECTTIMEOUT,
3728 Long_val(option));
3730 if (result != CURLE_OK)
3731 raiseError(conn, result);
3733 CAMLreturn0;
3736 static void handleHTTPGet(Connection *conn, value option)
3738 CAMLparam1(option);
3739 CURLcode result = CURLE_OK;
3741 result = curl_easy_setopt(conn->connection,
3742 CURLOPT_HTTPGET,
3743 Bool_val(option));
3745 if (result != CURLE_OK)
3746 raiseError(conn, result);
3748 CAMLreturn0;
3751 static void handleSSLVerifyHost(Connection *conn, value option)
3753 CAMLparam1(option);
3754 CURLcode result = CURLE_OK;
3756 switch (Long_val(option))
3758 case 0: /* SSLVERIFYHOST_EXISTENCE */
3759 result = curl_easy_setopt(conn->connection,
3760 CURLOPT_SSL_VERIFYHOST,
3762 break;
3764 case 1: /* SSLVERIFYHOST_HOSTNAME */
3765 result = curl_easy_setopt(conn->connection,
3766 CURLOPT_SSL_VERIFYHOST,
3768 break;
3770 default:
3771 failwith("Invalid SSLVERIFYHOST Option");
3772 break;
3775 if (result != CURLE_OK)
3776 raiseError(conn, result);
3778 CAMLreturn0;
3781 static void handleCookieJar(Connection *conn, value option)
3783 CAMLparam1(option);
3784 CURLcode result = CURLE_OK;
3786 Store_field(conn->ocamlValues, OcamlCookieJar, option);
3788 if (conn->cookieJar != NULL)
3789 free(conn->cookieJar);
3791 conn->cookieJar = strdup(String_val(option));
3793 result = curl_easy_setopt(conn->connection,
3794 CURLOPT_COOKIEJAR,
3795 conn->cookieJar);
3797 if (result != CURLE_OK)
3798 raiseError(conn, result);
3800 CAMLreturn0;
3803 static void handleSSLCipherList(Connection *conn, value option)
3805 CAMLparam1(option);
3806 CURLcode result = CURLE_OK;
3808 Store_field(conn->ocamlValues, OcamlSSLCipherList, option);
3810 if (conn->sslCipherList != NULL)
3811 free(conn->sslCipherList);
3813 conn->sslCipherList = strdup(String_val(option));
3815 result = curl_easy_setopt(conn->connection,
3816 CURLOPT_SSL_CIPHER_LIST,
3817 conn->sslCipherList);
3819 if (result != CURLE_OK)
3820 raiseError(conn, result);
3822 CAMLreturn0;
3825 static void handleHTTPVersion(Connection *conn, value option)
3827 CAMLparam1(option);
3828 CURLcode result = CURLE_OK;
3830 switch (Long_val(option))
3832 case 0: /* HTTP_VERSION_NONE */
3833 result = curl_easy_setopt(conn->connection,
3834 CURLOPT_HTTP_VERSION,
3835 CURL_HTTP_VERSION_NONE);
3836 break;
3838 case 1: /* HTTP_VERSION_1_0 */
3839 result = curl_easy_setopt(conn->connection,
3840 CURLOPT_HTTP_VERSION,
3841 CURL_HTTP_VERSION_1_0);
3842 break;
3844 case 2: /* HTTP_VERSION_1_1 */
3845 result = curl_easy_setopt(conn->connection,
3846 CURLOPT_HTTP_VERSION,
3847 CURL_HTTP_VERSION_1_1);
3848 break;
3850 default:
3851 failwith("Invalid HTTP_VERSION Option");
3852 break;
3855 if (result != CURLE_OK)
3856 raiseError(conn, result);
3858 CAMLreturn0;
3861 static void handleFTPUseEPSV(Connection *conn, value option)
3863 CAMLparam1(option);
3864 CURLcode result = CURLE_OK;
3866 result = curl_easy_setopt(conn->connection,
3867 CURLOPT_FTP_USE_EPSV,
3868 Bool_val(option));
3870 if (result != CURLE_OK)
3871 raiseError(conn, result);
3873 CAMLreturn0;
3876 static void handleDNSCacheTimeout(Connection *conn, value option)
3878 CAMLparam1(option);
3879 CURLcode result = CURLE_OK;
3881 result = curl_easy_setopt(conn->connection,
3882 CURLOPT_DNS_CACHE_TIMEOUT,
3883 Long_val(option));
3885 if (result != CURLE_OK)
3886 raiseError(conn, result);
3888 CAMLreturn0;
3891 static void handleDNSUseGlobalCache(Connection *conn, value option)
3893 CAMLparam1(option);
3894 CURLcode result = CURLE_OK;
3896 result = curl_easy_setopt(conn->connection,
3897 CURLOPT_DNS_USE_GLOBAL_CACHE,
3898 Bool_val(option));
3900 if (result != CURLE_OK)
3901 raiseError(conn, result);
3903 CAMLreturn0;
3906 static void handleDebugFunction(Connection *conn, value option)
3908 CAMLparam1(option);
3909 CURLcode result = CURLE_OK;
3911 if (Tag_val(option) == Closure_tag)
3912 Store_field(conn->ocamlValues, OcamlDebugCallback, option);
3913 else
3914 failwith("Not a proper closure");
3916 result = curl_easy_setopt(conn->connection,
3917 CURLOPT_DEBUGFUNCTION,
3918 debugFunction);
3919 if (result != CURLE_OK)
3920 raiseError(conn, result);
3922 result = curl_easy_setopt(conn->connection,
3923 CURLOPT_DEBUGDATA,
3924 conn);
3926 if (result != CURLE_OK)
3927 raiseError(conn, result);
3929 CAMLreturn0;
3932 static void handlePrivate(Connection *conn, value option)
3934 #if HAVE_DECL_CURLOPT_PRIVATE
3935 CAMLparam1(option);
3936 CURLcode result = CURLE_OK;
3938 Store_field(conn->ocamlValues, OcamlPrivate, option);
3940 if (conn->private != NULL)
3941 free(conn->private);
3943 conn->private = strdup(String_val(option));
3945 result = curl_easy_setopt(conn->connection,
3946 CURLOPT_PRIVATE,
3947 conn->private);
3949 if (result != CURLE_OK)
3950 raiseError(conn, result);
3952 CAMLreturn0;
3953 #else
3954 #warning "libcurl does not implement CURLOPT_PRIVATE"
3955 failwith("libcurl does not implement CURLOPT_PRIVATE");
3956 #endif
3959 static void handleHTTP200Aliases(Connection *conn, value option)
3961 #if HAVE_DECL_CURLOPT_HTTP200ALIASES
3962 CAMLparam1(option);
3963 CAMLlocal1(listIter);
3964 CURLcode result = CURLE_OK;
3965 char *str;
3967 Store_field(conn->ocamlValues, OcamlHTTP200Aliases, option);
3969 if (conn->http200Aliases != NULL)
3970 free_curl_slist(conn->http200Aliases);
3972 conn->http200Aliases = NULL;
3974 listIter = option;
3976 while (!Is_long(listIter))
3978 if (Tag_val(Field(listIter, 0)) != String_tag)
3979 failwith("Not a string");
3981 str = strdup(String_val(Field(listIter, 0)));
3983 conn->http200Aliases = curl_slist_append(conn->http200Aliases, str);
3985 listIter = Field(listIter, 1);
3988 result = curl_easy_setopt(conn->connection,
3989 CURLOPT_HTTP200ALIASES,
3990 conn->http200Aliases);
3992 if (result != CURLE_OK)
3993 raiseError(conn, result);
3995 CAMLreturn0;
3996 #else
3997 #warning "libcurl does not implement CURLOPT_HTTP200ALIASES"
3998 failwith("libcurl does not implement CURLOPT_HTTP200ALIASES");
3999 #endif
4002 static void handleUnrestrictedAuth(Connection *conn, value option)
4004 #if HAVE_DECL_CURLOPT_UNRESTRICTED_AUTH
4005 CAMLparam1(option);
4006 CURLcode result = CURLE_OK;
4008 result = curl_easy_setopt(conn->connection,
4009 CURLOPT_UNRESTRICTED_AUTH,
4010 Bool_val(option));
4012 if (result != CURLE_OK)
4013 raiseError(conn, result);
4015 CAMLreturn0;
4016 #else
4017 #warning "libcurl does not implement CURLOPT_UNRESTRICTED_AUTH"
4018 failwith("libcurl does not implement CURLOPT_UNRESTRICTED_AUTH");
4019 #endif
4022 static void handleFTPUseEPRT(Connection *conn, value option)
4024 #if HAVE_DECL_CURLOPT_FTP_USE_EPRT
4025 CAMLparam1(option);
4026 CURLcode result = CURLE_OK;
4028 result = curl_easy_setopt(conn->connection,
4029 CURLOPT_FTP_USE_EPRT,
4030 Bool_val(option));
4032 if (result != CURLE_OK)
4033 raiseError(conn, result);
4035 CAMLreturn0;
4036 #else
4037 #warning "libcurl does not implement CURLOPT_FTP_USE_EPRT"
4038 failwith("libcurl does not implement CURLOPT_FTP_USE_EPRT");
4039 #endif
4042 static void handleHTTPAuth(Connection *conn, value option)
4044 #if HAVE_DECL_CURLOPT_HTTPAUTH
4045 CAMLparam1(option);
4046 CAMLlocal1(listIter);
4047 CURLcode result = CURLE_OK;
4048 long auth = CURLAUTH_NONE;
4050 listIter = option;
4052 while (!Is_long(listIter))
4054 switch (Long_val(Field(listIter, 0)))
4056 case 0: /* CURLAUTH_BASIC */
4057 auth |= CURLAUTH_BASIC;
4058 break;
4060 case 1: /* CURLAUTH_DIGEST */
4061 auth |= CURLAUTH_DIGEST;
4062 break;
4064 case 2: /* CURLAUTH_GSSNEGOTIATE */
4065 auth |= CURLAUTH_GSSNEGOTIATE;
4066 break;
4068 case 3: /* CURLAUTH_NTLM */
4069 auth |= CURLAUTH_NTLM;
4070 break;
4072 case 4: /* CURLAUTH_ANY */
4073 auth |= CURLAUTH_ANY;
4074 break;
4076 case 5: /* CURLAUTH_ANYSAFE */
4077 auth |= CURLAUTH_ANYSAFE;
4078 break;
4080 default:
4081 failwith("Invalid HTTPAUTH Value");
4082 break;
4085 listIter = Field(listIter, 1);
4088 result = curl_easy_setopt(conn->connection,
4089 CURLOPT_HTTPAUTH,
4090 auth);
4092 if (result != CURLE_OK)
4093 raiseError(conn, result);
4095 CAMLreturn0;
4096 #else
4097 #warning "libcurl does not implement CURLOPT_HTTPAUTH"
4098 failwith("libcurl does not implement CURLOPT_HTTPAUTH");
4099 #endif
4102 static void handleFTPCreateMissingDirs(Connection *conn, value option)
4104 #if HAVE_DECL_CURLOPT_FTP_CREATE_MISSING_DIRS
4105 CAMLparam1(option);
4106 CURLcode result = CURLE_OK;
4108 result = curl_easy_setopt(conn->connection,
4109 CURLOPT_FTP_CREATE_MISSING_DIRS,
4110 Bool_val(option));
4112 if (result != CURLE_OK)
4113 raiseError(conn, result);
4115 CAMLreturn0;
4116 #else
4117 #warning "libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS"
4118 failwith("libcurl does not implement CURLOPT_FTP_CREATE_MISSING_DIRS");
4119 #endif
4122 static void handleProxyAuth(Connection *conn, value option)
4124 #if HAVE_DECL_CURLOPT_PROXYAUTH
4125 CAMLparam1(option);
4126 CAMLlocal1(listIter);
4127 CURLcode result = CURLE_OK;
4128 long auth = CURLAUTH_NONE;
4130 listIter = option;
4132 while (!Is_long(listIter))
4134 switch (Long_val(Field(listIter, 0)))
4136 case 0: /* CURLAUTH_BASIC */
4137 auth |= CURLAUTH_BASIC;
4138 break;
4140 case 1: /* CURLAUTH_DIGEST */
4141 auth |= CURLAUTH_DIGEST;
4142 break;
4144 case 2: /* CURLAUTH_GSSNEGOTIATE */
4145 auth |= CURLAUTH_GSSNEGOTIATE;
4146 break;
4148 case 3: /* CURLAUTH_NTLM */
4149 auth |= CURLAUTH_NTLM;
4150 break;
4152 case 4: /* CURLAUTH_ANY */
4153 auth |= CURLAUTH_ANY;
4154 break;
4156 case 5: /* CURLAUTH_ANYSAFE */
4157 auth |= CURLAUTH_ANYSAFE;
4158 break;
4160 default:
4161 failwith("Invalid HTTPAUTH Value");
4162 break;
4165 listIter = Field(listIter, 1);
4168 result = curl_easy_setopt(conn->connection,
4169 CURLOPT_PROXYAUTH,
4170 auth);
4172 if (result != CURLE_OK)
4173 raiseError(conn, result);
4175 CAMLreturn0;
4176 #else
4177 #warning "libcurl does not implement CURLOPT_PROXYAUTH"
4178 failwith("libcurl does not implement CURLOPT_PROXYAUTH");
4179 #endif
4182 static void handleFTPResponseTimeout(Connection *conn, value option)
4184 #if HAVE_DECL_CURLOPT_FTP_RESPONSE_TIMEOUT
4185 CAMLparam1(option);
4186 CURLcode result = CURLE_OK;
4188 result = curl_easy_setopt(conn->connection,
4189 CURLOPT_FTP_RESPONSE_TIMEOUT,
4190 Long_val(option));
4192 if (result != CURLE_OK)
4193 raiseError(conn, result);
4195 CAMLreturn0;
4196 #else
4197 #warning "libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT"
4198 failwith("libcurl does not implement CURLOPT_FTP_RESPONSE_TIMEOUT");
4199 #endif
4202 static void handleIPResolve(Connection *conn, value option)
4204 #if HAVE_DECL_CURLOPT_IPRESOLVE
4205 CAMLparam1(option);
4206 CURLcode result = CURLE_OK;
4208 switch (Long_val(option))
4210 case 0: /* CURL_IPRESOLVE_WHATEVER */
4211 result = curl_easy_setopt(conn->connection,
4212 CURLOPT_IPRESOLVE,
4213 CURL_IPRESOLVE_WHATEVER);
4214 break;
4216 case 1: /* CURL_IPRESOLVE_V4 */
4217 result = curl_easy_setopt(conn->connection,
4218 CURLOPT_IPRESOLVE,
4219 CURL_IPRESOLVE_V4);
4220 break;
4222 case 2: /* CURL_IPRESOLVE_V6 */
4223 result = curl_easy_setopt(conn->connection,
4224 CURLOPT_IPRESOLVE,
4225 CURL_IPRESOLVE_V6);
4226 break;
4228 default:
4229 failwith("Invalid IPRESOLVE Value");
4230 break;
4233 if (result != CURLE_OK)
4234 raiseError(conn, result);
4236 CAMLreturn0;
4237 #else
4238 #warning "libcurl does not implement CURLOPT_IPRESOLVE"
4239 failwith("libcurl does not implement CURLOPT_IPRESOLVE");
4240 #endif
4243 static void handleMaxFileSize(Connection *conn, value option)
4245 #if HAVE_DECL_CURLOPT_MAXFILESIZE
4246 CAMLparam1(option);
4247 CURLcode result = CURLE_OK;
4249 result = curl_easy_setopt(conn->connection,
4250 CURLOPT_MAXFILESIZE,
4251 Int32_val(option));
4253 if (result != CURLE_OK)
4254 raiseError(conn, result);
4256 CAMLreturn0;
4257 #else
4258 #warning "libcurl does not implement CURLOPT_MAXFILESIZE"
4259 failwith("libcurl does not implement CURLOPT_MAXFILESIZE");
4260 #endif
4263 static void handleInFileSizeLarge(Connection *conn, value option)
4265 #if HAVE_DECL_CURLOPT_INFILESIZE_LARGE
4266 CAMLparam1(option);
4267 CURLcode result = CURLE_OK;
4269 result = curl_easy_setopt(conn->connection,
4270 CURLOPT_INFILESIZE_LARGE,
4271 Int64_val(option));
4273 if (result != CURLE_OK)
4274 raiseError(conn, result);
4276 CAMLreturn0;
4277 #else
4278 #warning("libcurl does not implement CURLOPT_INFILESIZE_LARGE")
4279 failwith("libcurl does not implement CURLOPT_INFILESIZE_LARGE");
4280 #endif
4283 static void handleResumeFromLarge(Connection *conn, value option)
4285 #if HAVE_DECL_CURLOPT_RESUME_FROM_LARGE
4286 CAMLparam1(option);
4287 CURLcode result = CURLE_OK;
4289 result = curl_easy_setopt(conn->connection,
4290 CURLOPT_RESUME_FROM_LARGE,
4291 Int64_val(option));
4293 if (result != CURLE_OK)
4294 raiseError(conn, result);
4296 CAMLreturn0;
4297 #else
4298 #warning("libcurl does not implement CURLOPT_RESUME_FROM_LARGE")
4299 failwith("libcurl does not implement CURLOPT_RESUME_FROM_LARGE");
4300 #endif
4303 static void handleMaxFileSizeLarge(Connection *conn, value option)
4305 #if HAVE_DECL_CURLOPT_MAXFILESIZE_LARGE
4306 CAMLparam1(option);
4307 CURLcode result = CURLE_OK;
4309 result = curl_easy_setopt(conn->connection,
4310 CURLOPT_MAXFILESIZE_LARGE,
4311 Int64_val(option));
4313 if (result != CURLE_OK)
4314 raiseError(conn, result);
4316 CAMLreturn0;
4317 #else
4318 #warning "libcurl does not implement CURLOPT_MAXFILESIZE_LARGE"
4319 failwith("libcurl does not implement CURLOPT_MAXFILESIZE_LARGE");
4320 #endif
4323 static void handleNETRCFile(Connection *conn, value option)
4325 #if HAVE_DECL_CURLOPT_NETRC_FILE
4326 CAMLparam1(option);
4327 CURLcode result = CURLE_OK;
4329 Store_field(conn->ocamlValues, OcamlNETRCFile, option);
4331 if (conn->netrcFile != NULL)
4332 free(conn->netrcFile);
4334 conn->netrcFile = strdup(String_val(option));
4336 result = curl_easy_setopt(conn->connection,
4337 CURLOPT_NETRC_FILE,
4338 conn->netrcFile);
4340 if (result != CURLE_OK)
4341 raiseError(conn, result);
4343 CAMLreturn0;
4344 #else
4345 #warning "libcurl does not implement CURLOPT_NETRC_FILE"
4346 failwith("libcurl does not implement CURLOPT_NETRC_FILE");
4347 #endif
4350 static void handleFTPSSL(Connection *conn, value option)
4352 #if HAVE_DECL_CURLOPT_FTP_SSL
4353 CAMLparam1(option);
4354 CURLcode result = CURLE_OK;
4356 switch (Long_val(option))
4358 case 0: /* CURLFTPSSL_NONE */
4359 result = curl_easy_setopt(conn->connection,
4360 CURLOPT_FTP_SSL,
4361 CURLFTPSSL_NONE);
4362 break;
4364 case 1: /* CURLFTPSSL_TRY */
4365 result = curl_easy_setopt(conn->connection,
4366 CURLOPT_FTP_SSL,
4367 CURLFTPSSL_TRY);
4368 break;
4370 case 2: /* CURLFTPSSL_CONTROL */
4371 result = curl_easy_setopt(conn->connection,
4372 CURLOPT_FTP_SSL,
4373 CURLFTPSSL_CONTROL);
4374 break;
4376 case 3: /* CURLFTPSSL_ALL */
4377 result = curl_easy_setopt(conn->connection,
4378 CURLOPT_FTP_SSL,
4379 CURLFTPSSL_ALL);
4380 break;
4382 default:
4383 failwith("Invalid FTP_SSL Value");
4384 break;
4387 if (result != CURLE_OK)
4388 raiseError(conn, result);
4390 CAMLreturn0;
4391 #else
4392 #warning "libcurl does not implement CURLOPT_FTP_SSL"
4393 failwith("libcurl does not implement CURLOPT_FTP_SSL");
4394 #endif
4397 static void handlePostFieldSizeLarge(Connection *conn, value option)
4399 #if HAVE_DECL_CURLOPT_POSTFIELDSIZE_LARGE
4400 CAMLparam1(option);
4401 CURLcode result = CURLE_OK;
4403 result = curl_easy_setopt(conn->connection,
4404 CURLOPT_POSTFIELDSIZE_LARGE,
4405 Int64_val(option));
4407 if (result != CURLE_OK)
4408 raiseError(conn, result);
4410 CAMLreturn0;
4411 #else
4412 #warning "libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE"
4413 failwith("libcurl does not implement CURLOPT_POSTFIELDSIZE_LARGE");
4414 #endif
4417 static void handleTCPNoDelay(Connection *conn, value option)
4419 #if HAVE_DECL_CURLOPT_TCP_NODELAY
4420 CAMLparam1(option);
4421 CURLcode result = CURLE_OK;
4423 result = curl_easy_setopt(conn->connection,
4424 CURLOPT_TCP_NODELAY,
4425 Bool_val(option));
4427 if (result != CURLE_OK)
4428 raiseError(conn, result);
4430 CAMLreturn0;
4431 #else
4432 #warning "libcurl does not implement CURLOPT_TCP_NODELAY"
4433 failwith("libcurl does not implement CURLOPT_TCP_NODELAY");
4434 #endif
4437 static void handleFTPSSLAuth(Connection *conn, value option)
4439 #if HAVE_DECL_CURLOPT_FTPSSLAUTH
4440 CAMLparam1(option);
4441 CURLcode result = CURLE_OK;
4443 switch (Long_val(option))
4445 case 0: /* CURLFTPAUTH_DEFAULT */
4446 result = curl_easy_setopt(conn->connection,
4447 CURLOPT_FTPSSLAUTH,
4448 CURLFTPAUTH_DEFAULT);
4449 break;
4451 case 1: /* CURLFTPAUTH_SSL */
4452 result = curl_easy_setopt(conn->connection,
4453 CURLOPT_FTPSSLAUTH,
4454 CURLFTPAUTH_SSL);
4455 break;
4457 case 2: /* CURLFTPAUTH_TLS */
4458 result = curl_easy_setopt(conn->connection,
4459 CURLOPT_FTPSSLAUTH,
4460 CURLFTPAUTH_TLS);
4461 break;
4463 default:
4464 failwith("Invalid FTPSSLAUTH value");
4465 break;
4468 if (result != CURLE_OK)
4469 raiseError(conn, result);
4471 CAMLreturn0;
4472 #else
4473 #warning "libcurl does not implement CURLOPT_FTPSSLAUTH"
4474 failwith("libcurl does not implement CURLOPT_FTPSSLAUTH");
4475 #endif
4478 static void handleIOCTLFunction(Connection *conn, value option)
4480 #if HAVE_DECL_CURLOPT_IOCTLFUNCTION
4481 CAMLparam1(option);
4482 CURLcode result = CURLE_OK;
4484 if (Tag_val(option) == Closure_tag)
4485 Store_field(conn->ocamlValues, OcamlIOCTLCallback, option);
4486 else
4487 failwith("Not a proper closure");
4489 result = curl_easy_setopt(conn->connection,
4490 CURLOPT_IOCTLFUNCTION,
4491 ioctlFunction);
4492 if (result != CURLE_OK)
4493 raiseError(conn, result);
4495 result = curl_easy_setopt(conn->connection,
4496 CURLOPT_DEBUGDATA,
4497 conn);
4499 if (result != CURLE_OK)
4500 raiseError(conn, result);
4502 CAMLreturn0;
4503 #else
4504 #warning "libcurl does not implement CURLOPT_IOCTLFUNCTION"
4505 failwith("libcurl does not implement CURLOPT_IOCTLFUNCTION");
4506 #endif
4509 static void handleFTPAccount(Connection *conn, value option)
4511 #if HAVE_DECL_CURLOPT_FTP_ACCOUNT
4512 CAMLparam1(option);
4513 CURLcode result = CURLE_OK;
4515 Store_field(conn->ocamlValues, OcamlFTPAccount, option);
4517 if (conn->ftpaccount != NULL)
4518 free(conn->ftpaccount);
4520 conn->ftpaccount = strdup(String_val(option));
4522 result = curl_easy_setopt(conn->connection,
4523 CURLOPT_FTP_ACCOUNT,
4524 conn->ftpaccount);
4526 if (result != CURLE_OK)
4527 raiseError(conn, result);
4529 CAMLreturn0;
4530 #else
4531 #warning "libcurl does not implement CURLOPT_FTP_ACCOUNT"
4532 failwith("libcurl does not implement CURLOPT_FTP_ACCOUNT");
4533 #endif
4536 static void handleCookieList(Connection *conn, value option)
4538 #if HAVE_DECL_CURLOPT_COOKIELIST
4539 CAMLparam1(option);
4540 CURLcode result = CURLE_OK;
4542 Store_field(conn->ocamlValues, OcamlCookieList, option);
4544 if (conn->cookielist != NULL)
4545 free(conn->cookielist);
4547 conn->cookielist = strdup(String_val(option));
4549 result = curl_easy_setopt(conn->connection,
4550 CURLOPT_COOKIELIST,
4551 conn->cookielist);
4553 if (result != CURLE_OK)
4554 raiseError(conn, result);
4556 CAMLreturn0;
4557 #else
4558 #warning "libcurl does not implement CURLOPT_COOKIELIST"
4559 failwith("libcurl does not implement CURLOPT_COOKIELIST");
4560 #endif
4563 static void handleIgnoreContentLength(Connection *conn, value option)
4565 #if HAVE_DECL_CURLOPT_IGNORE_CONTENT_LENGTH
4566 CAMLparam1(option);
4567 CURLcode result = CURLE_OK;
4569 result = curl_easy_setopt(conn->connection,
4570 CURLOPT_IGNORE_CONTENT_LENGTH,
4571 Bool_val(option));
4573 if (result != CURLE_OK)
4574 raiseError(conn, result);
4576 CAMLreturn0;
4577 #else
4578 #warning "libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH"
4579 failwith("libcurl does not implement CURLOPT_IGNORE_CONTENT_LENGTH");
4580 #endif
4583 static void handleFTPSkipPASVIP(Connection *conn, value option)
4585 #if HAVE_DECL_CURLOPT_FTP_SKIP_PASV_IP
4586 CAMLparam1(option);
4587 CURLcode result = CURLE_OK;
4589 result = curl_easy_setopt(conn->connection,
4590 CURLOPT_FTP_SKIP_PASV_IP,
4591 Bool_val(option));
4593 if (result != CURLE_OK)
4594 raiseError(conn, result);
4596 CAMLreturn0;
4597 #else
4598 #warning "libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP"
4599 failwith("libcurl does not implement CURLOPT_FTP_SKIP_PASV_IP");
4600 #endif
4603 static void handleFTPFileMethod(Connection *conn, value option)
4605 #if HAVE_DECL_CURLOPT_FTP_FILEMETHOD
4606 CAMLparam1(option);
4607 CURLcode result = CURLE_OK;
4609 switch (Long_val(option))
4611 case 0: /* CURLFTPMETHOD_DEFAULT */
4612 result = curl_easy_setopt(conn->connection,
4613 CURLOPT_FTP_FILEMETHOD,
4614 CURLFTPMETHOD_DEFAULT);
4615 break;
4617 case 1: /* CURLFTMETHOD_MULTICWD */
4618 result = curl_easy_setopt(conn->connection,
4619 CURLOPT_FTP_FILEMETHOD,
4620 CURLFTPMETHOD_MULTICWD);
4621 break;
4623 case 2: /* CURLFTPMETHOD_NOCWD */
4624 result = curl_easy_setopt(conn->connection,
4625 CURLOPT_FTP_FILEMETHOD,
4626 CURLFTPMETHOD_NOCWD);
4627 break;
4629 case 3: /* CURLFTPMETHOD_SINGLECWD */
4630 result = curl_easy_setopt(conn->connection,
4631 CURLOPT_FTP_FILEMETHOD,
4632 CURLFTPMETHOD_SINGLECWD);
4634 default:
4635 failwith("Invalid FTP_FILEMETHOD value");
4636 break;
4639 if (result != CURLE_OK)
4640 raiseError(conn, result);
4642 CAMLreturn0;
4643 #else
4644 #warning "libcurl does not implement CURLOPT_FTP_FILEMETHOD"
4645 failwith("libcurl does not implement CURLOPT_FTP_FILEMETHOD");
4646 #endif
4649 static void handleLocalPort(Connection *conn, value option)
4651 #if HAVE_DECL_CURLOPT_LOCALPORT
4652 CAMLparam1(option);
4653 CURLcode result = CURLE_OK;
4655 result = curl_easy_setopt(conn->connection,
4656 CURLOPT_LOCALPORT,
4657 Long_val(option));
4659 if (result != CURLE_OK)
4660 raiseError(conn, result);
4662 CAMLreturn0;
4663 #else
4664 #warning "libcurl does not implement CURLOPT_LOCALPORT"
4665 failwith("libcurl does not implement CURLOPT_LOCALPORT");
4666 #endif
4669 static void handleLocalPortRange(Connection *conn, value option)
4671 #if HAVE_DECL_CURLOPT_LOCALPORTRANGE
4672 CAMLparam1(option);
4673 CURLcode result = CURLE_OK;
4675 result = curl_easy_setopt(conn->connection,
4676 CURLOPT_LOCALPORTRANGE,
4677 Long_val(option));
4679 if (result != CURLE_OK)
4680 raiseError(conn, result);
4682 CAMLreturn0;
4683 #else
4684 #warning "libcurl does not implement CURLOPT_LOCALPORTRANGE"
4685 failwith("libcurl does not implement CURLOPT_LOCALPORTRANGE");
4686 #endif
4689 static void handleConnectOnly(Connection *conn, value option)
4691 #if HAVE_DECL_CURLOPT_CONNECT_ONLY
4692 CAMLparam1(option);
4693 CURLcode result = CURLE_OK;
4695 result = curl_easy_setopt(conn->connection,
4696 CURLOPT_CONNECT_ONLY,
4697 Bool_val(option));
4699 if (result != CURLE_OK)
4700 raiseError(conn, result);
4702 CAMLreturn0;
4703 #else
4704 #warning "libcurl does not implement CURLOPT_CONNECT_ONLY"
4705 failwith("libcurl does not implement CURLOPT_CONNECT_ONLY");
4706 #endif
4709 static void handleMaxSendSpeedLarge(Connection *conn, value option)
4711 #if HAVE_DECL_CURLOPT_MAX_SEND_SPEED_LARGE
4712 CAMLparam1(option);
4713 CURLcode result = CURLE_OK;
4715 result = curl_easy_setopt(conn->connection,
4716 CURLOPT_MAX_SEND_SPEED_LARGE,
4717 Int64_val(option));
4719 if (result != CURLE_OK)
4720 raiseError(conn, result);
4722 CAMLreturn0;
4723 #else
4724 #warning "libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE"
4725 failwith("libcurl does not implement CURLOPT_MAX_SEND_SPEED_LARGE");
4726 #endif
4729 static void handleMaxRecvSpeedLarge(Connection *conn, value option)
4731 #if HAVE_DECL_CURLOPT_MAX_RECV_SPEED_LARGE
4732 CAMLparam1(option);
4733 CURLcode result = CURLE_OK;
4735 result = curl_easy_setopt(conn->connection,
4736 CURLOPT_MAX_RECV_SPEED_LARGE,
4737 Int64_val(option));
4739 if (result != CURLE_OK)
4740 raiseError(conn, result);
4742 CAMLreturn0;
4743 #else
4744 #warning "libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE"
4745 failwith("libcurl does not implement CURLOPT_MAX_RECV_SPEED_LARGE");
4746 #endif
4749 static void handleFTPAlternativeToUser(Connection *conn, value option)
4751 #if HAVE_DECL_CURLOPT_FTP_ALTERNATIVE_TO_USER
4752 CAMLparam1(option);
4753 CURLcode result = CURLE_OK;
4755 Store_field(conn->ocamlValues, OcamlFTPAlternativeToUser, option);
4757 if (conn->ftpAlternativeToUser != NULL)
4758 free(conn->ftpAlternativeToUser);
4760 conn->ftpAlternativeToUser = strdup(String_val(option));
4762 result = curl_easy_setopt(conn->connection,
4763 CURLOPT_FTP_ALTERNATIVE_TO_USER,
4764 conn->ftpAlternativeToUser);
4766 if (result != CURLE_OK)
4767 raiseError(conn, result);
4769 CAMLreturn0;
4770 #else
4771 #warning "libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER"
4772 failwith("libcurl does not implement CURLOPT_FTP_ALTERNATIVE_TO_USER");
4773 #endif
4776 static void handleSSLSessionIdCache(Connection *conn, value option)
4778 #if HAVE_DECL_CURLOPT_SSL_SESSIONID_CACHE
4779 CAMLparam1(option);
4780 CURLcode result = CURLE_OK;
4782 result = curl_easy_setopt(conn->connection,
4783 CURLOPT_SSL_SESSIONID_CACHE,
4784 Bool_val(option));
4786 if (result != CURLE_OK)
4787 raiseError(conn, result);
4789 CAMLreturn0;
4790 #else
4791 #warning "libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE"
4792 failwith("libcurl does not implement CURLOPT_SSL_SESSIONID_CACHE");
4793 #endif
4796 static void handleSSHAuthTypes(Connection *conn, value option)
4798 #if HAVE_DECL_CURLOPT_SSH_AUTH_TYPES
4799 CAMLparam1(option);
4800 CAMLlocal1(listIter);
4801 CURLcode result = CURLE_OK;
4802 long authTypes = CURLSSH_AUTH_NONE;
4804 listIter = option;
4806 while (!Is_long(listIter))
4808 switch (Long_val(Field(listIter, 0)))
4810 case 0: /* CURLSSH_AUTH_ANY */
4811 authTypes |= CURLSSH_AUTH_ANY;
4812 break;
4814 case 1: /* CURLSSH_AUTH_PUBLICKEY */
4815 authTypes |= CURLSSH_AUTH_PUBLICKEY;
4816 break;
4818 case 2: /* CURLSSH_AUTH_PASSWORD */
4819 authTypes |= CURLSSH_AUTH_PASSWORD;
4820 break;
4822 case 3: /* CURLSSH_AUTH_HOST */
4823 authTypes |= CURLSSH_AUTH_HOST;
4824 break;
4826 case 4: /* CURLSSH_AUTH_KEYBOARD */
4827 authTypes |= CURLSSH_AUTH_KEYBOARD;
4828 break;
4830 default:
4831 failwith("Invalid CURLSSH_AUTH_TYPES Value");
4832 break;
4835 listIter = Field(listIter, 1);
4838 result = curl_easy_setopt(conn->connection,
4839 CURLOPT_SSH_AUTH_TYPES,
4840 authTypes);
4842 if (result != CURLE_OK)
4843 raiseError(conn, result);
4845 CAMLreturn0;
4846 #else
4847 #warning "libcurl does not implement CURLOPT_SSH_AUTH_TYPES"
4848 failwith("libcurl does not implement CURLOPT_SSH_AUTH_TYPES");
4849 #endif
4852 static void handleSSHPublicKeyFile(Connection *conn, value option)
4854 #if HAVE_DECL_CURLOPT_SSH_PUBLIC_KEYFILE
4855 CAMLparam1(option);
4856 CURLcode result = CURLE_OK;
4858 Store_field(conn->ocamlValues, OcamlSSHPublicKeyFile, option);
4860 if (conn->sshPublicKeyFile != NULL)
4861 free(conn->sshPublicKeyFile);
4863 conn->sshPublicKeyFile = strdup(String_val(option));
4865 result = curl_easy_setopt(conn->connection,
4866 CURLOPT_SSH_PUBLIC_KEYFILE,
4867 conn->sshPublicKeyFile);
4869 if (result != CURLE_OK)
4870 raiseError(conn, result);
4872 CAMLreturn0;
4873 #else
4874 #warning "libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE"
4875 failwith("libcurl does not implement CURLOPT_SSH_PUBLIC_KEYFILE");
4876 #endif
4879 static void handleSSHPrivateKeyFile(Connection *conn, value option)
4881 #if HAVE_DECL_CURLOPT_SSH_PRIVATE_KEYFILE
4882 CAMLparam1(option);
4883 CURLcode result = CURLE_OK;
4885 Store_field(conn->ocamlValues, OcamlSSHPrivateKeyFile, option);
4887 if (conn->sshPrivateKeyFile != NULL)
4888 free(conn->sshPrivateKeyFile);
4890 conn->sshPrivateKeyFile = strdup(String_val(option));
4892 result = curl_easy_setopt(conn->connection,
4893 CURLOPT_SSH_PRIVATE_KEYFILE,
4894 conn->sshPrivateKeyFile);
4896 if (result != CURLE_OK)
4897 raiseError(conn, result);
4899 CAMLreturn0;
4900 #else
4901 #warning "libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE"
4902 failwith("libcurl does not implement CURLOPT_SSH_PRIVATE_KEYFILE");
4903 #endif
4906 static void handleFTPSSLCCC(Connection *conn, value option)
4908 #if HAVE_DECL_CURLOPT_FTP_SSL_CCC
4909 CAMLparam1(option);
4910 CURLcode result = CURLE_OK;
4912 switch (Long_val(option))
4914 case 0: /* CURLFTPSSL_CCC_NONE */
4915 result = curl_easy_setopt(conn->connection,
4916 CURLOPT_FTP_SSL_CCC,
4917 CURLFTPSSL_CCC_NONE);
4918 break;
4920 case 1: /* CURLFTPSSL_CCC_PASSIVE */
4921 result = curl_easy_setopt(conn->connection,
4922 CURLOPT_FTP_SSL_CCC,
4923 CURLFTPSSL_CCC_PASSIVE);
4924 break;
4926 case 2: /* CURLFTPSSL_CCC_ACTIVE */
4927 result = curl_easy_setopt(conn->connection,
4928 CURLOPT_FTP_SSL_CCC,
4929 CURLFTPSSL_CCC_ACTIVE);
4930 break;
4932 default:
4933 failwith("Invalid FTPSSL_CCC value");
4934 break;
4937 if (result != CURLE_OK)
4938 raiseError(conn, result);
4940 CAMLreturn0;
4941 #else
4942 #warning "libcurl does not implement CURLOPT_FTP_SSL_CCC"
4943 failwith("libcurl does not implement CURLOPT_FTP_SSL_CCC");
4944 #endif
4947 static void handleTimeoutMS(Connection *conn, value option)
4949 #if HAVE_DECL_CURLOPT_TIMEOUT_MS
4950 CAMLparam1(option);
4951 CURLcode result = CURLE_OK;
4953 result = curl_easy_setopt(conn->connection,
4954 CURLOPT_TIMEOUT_MS,
4955 Long_val(option));
4957 if (result != CURLE_OK)
4958 raiseError(conn, result);
4960 CAMLreturn0;
4961 #else
4962 #warning "libcurl does not implement CURLOPT_TIMEOUT_MS"
4963 failwith("libcurl does not implement CURLOPT_TIMEOUT_MS");
4964 #endif
4967 static void handleConnectTimeoutMS(Connection *conn, value option)
4969 #if HAVE_DECL_CURLOPT_CONNECTTIMEOUT_MS
4970 CAMLparam1(option);
4971 CURLcode result = CURLE_OK;
4973 result = curl_easy_setopt(conn->connection,
4974 CURLOPT_CONNECTTIMEOUT_MS,
4975 Long_val(option));
4977 if (result != CURLE_OK)
4978 raiseError(conn, result);
4980 CAMLreturn0;
4981 #else
4982 #warning "libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS"
4983 failwith("libcurl does not implement CURLOPT_CONNECTTIMEOUT_MS");
4984 #endif
4987 static void handleHTTPTransferDecoding(Connection *conn, value option)
4989 #if HAVE_DECL_CURLOPT_HTTP_TRANSFER_DECODING
4990 CAMLparam1(option);
4991 CURLcode result = CURLE_OK;
4993 result = curl_easy_setopt(conn->connection,
4994 CURLOPT_HTTP_TRANSFER_DECODING,
4995 Bool_val(option));
4997 if (result != CURLE_OK)
4998 raiseError(conn, result);
5000 CAMLreturn0;
5001 #else
5002 #warning "libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING"
5003 failwith("libcurl does not implement CURLOPT_HTTP_TRANSFER_DECODING");
5004 #endif
5007 static void handleHTTPContentDecoding(Connection *conn, value option)
5009 #if HAVE_DECL_CURLOPT_HTTP_CONTENT_DECODING
5010 CAMLparam1(option);
5011 CURLcode result = CURLE_OK;
5013 result = curl_easy_setopt(conn->connection,
5014 CURLOPT_HTTP_CONTENT_DECODING,
5015 Bool_val(option));
5017 if (result != CURLE_OK)
5018 raiseError(conn, result);
5020 CAMLreturn0;
5021 #else
5022 #warning "libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING"
5023 failwith("libcurl does not implement CURLOPT_HTTP_CONTENT_DECODING");
5024 #endif
5027 static void handleNewFilePerms(Connection *conn, value option)
5029 #if HAVE_DECL_CURLOPT_NEW_FILE_PERMS
5030 CAMLparam1(option);
5031 CURLcode result = CURLE_OK;
5033 result = curl_easy_setopt(conn->connection,
5034 CURLOPT_NEW_FILE_PERMS,
5035 Long_val(option));
5037 if (result != CURLE_OK)
5038 raiseError(conn, result);
5040 CAMLreturn0;
5041 #else
5042 #warning "libcurl does not implement CURLOPT_NEW_FILE_PERMS"
5043 failwith("libcurl does not implement CURLOPT_NEW_FILE_PERMS");
5044 #endif
5047 static void handleNewDirectoryPerms(Connection *conn, value option)
5049 #if HAVE_DECL_CURLOPT_NEW_DIRECTORY_PERMS
5050 CAMLparam1(option);
5051 CURLcode result = CURLE_OK;
5053 result = curl_easy_setopt(conn->connection,
5054 CURLOPT_NEW_DIRECTORY_PERMS,
5055 Long_val(option));
5057 if (result != CURLE_OK)
5058 raiseError(conn, result);
5060 CAMLreturn0;
5061 #else
5062 #warning "libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS"
5063 failwith("libcurl does not implement CURLOPT_NEW_DIRECTORY_PERMS");
5064 #endif
5067 static void handlePost301(Connection *conn, value option)
5069 #if HAVE_DECL_CURLOPT_POST301
5070 CAMLparam1(option);
5071 CURLcode result = CURLE_OK;
5073 result = curl_easy_setopt(conn->connection,
5074 CURLOPT_POST301,
5075 Bool_val(option));
5077 if (result != CURLE_OK)
5078 raiseError(conn, result);
5080 CAMLreturn0;
5081 #else
5082 #warning "libcurl does not implement CURLOPT_POST301"
5083 failwith("libcurl does not implement CURLOPT_POST301");
5084 #endif
5087 static void handleSSHHostPublicKeyMD5(Connection *conn, value option)
5089 #if HAVE_DECL_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
5090 CAMLparam1(option);
5091 CURLcode result = CURLE_OK;
5093 Store_field(conn->ocamlValues, OcamlSSHHostPublicKeyMD5, option);
5095 if (conn->sshHostPublicKeyMD5 != NULL)
5096 free(conn->sshHostPublicKeyMD5);
5098 conn->sshHostPublicKeyMD5 = strdup(String_val(option));
5100 result = curl_easy_setopt(conn->connection,
5101 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
5102 conn->sshHostPublicKeyMD5);
5104 if (result != CURLE_OK)
5105 raiseError(conn, result);
5107 CAMLreturn0;
5108 #else
5109 #warning "libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5"
5110 failwith("libcurl does not implement CURLOPT_SSH_HOST_PUBLIC_KEY_MD5");
5111 #endif
5114 static void handleCopyPostFields(Connection *conn, value option)
5116 #if HAVE_DECL_CURLOPT_COPYPOSTFIELDS
5117 CAMLparam1(option);
5118 CURLcode result = CURLE_OK;
5120 Store_field(conn->ocamlValues, OcamlCopyPostFields, option);
5122 if (conn->copyPostFields != NULL)
5123 free(conn->copyPostFields);
5125 conn->copyPostFields = strdup(String_val(option));
5127 result = curl_easy_setopt(conn->connection,
5128 CURLOPT_COPYPOSTFIELDS,
5129 conn->copyPostFields);
5131 if (result != CURLE_OK)
5132 raiseError(conn, result);
5134 CAMLreturn0;
5135 #else
5136 #warning "libcurl does not implement CURLOPT_COPYPOSTFIELDS"
5137 failwith("libcurl does not implement CURLOPT_COPYPOSTFIELDS");
5138 #endif
5141 static void handleProxyTransferMode(Connection *conn, value option)
5143 #if HAVE_DECL_CURLOPT_PROXY_TRANSFER_MODE
5144 CAMLparam1(option);
5145 CURLcode result = CURLE_OK;
5147 result = curl_easy_setopt(conn->connection,
5148 CURLOPT_PROXY_TRANSFER_MODE,
5149 Bool_val(option));
5151 if (result != CURLE_OK)
5152 raiseError(conn, result);
5154 CAMLreturn0;
5155 #else
5156 #warning "libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE"
5157 failwith("libcurl does not implement CURLOPT_PROXY_TRANSFER_MODE");
5158 #endif
5161 static void handleSeekFunction(Connection *conn, value option)
5163 #if HAVE_DECL_CURLOPT_SEEKFUNCTION
5164 CAMLparam1(option);
5165 CURLcode result = CURLE_OK;
5167 if (Tag_val(option) == Closure_tag)
5168 Store_field(conn->ocamlValues, OcamlSeekFunctionCallback, option);
5169 else
5170 failwith("Not a proper closure");
5172 result = curl_easy_setopt(conn->connection,
5173 CURLOPT_SEEKFUNCTION,
5174 seekFunction);
5176 if (result != CURLE_OK)
5177 raiseError(conn, result);
5179 result = curl_easy_setopt(conn->connection,
5180 CURLOPT_SEEKDATA,
5181 conn);
5183 if (result != CURLE_OK)
5184 raiseError(conn, result);
5186 CAMLreturn0;
5187 #else
5188 #warning "libcurl does not implement CURLOPT_SEEKFUNCTION"
5189 failwith("libcurl does not implement CURLOPT_SEEKFUNCTION");
5190 #endif
5194 ** curl_easy_setopt helper function
5197 CAMLprim value helper_curl_easy_setopt(value conn, value option)
5199 CAMLparam2(conn, option);
5200 CAMLlocal1(data);
5201 Connection *connection = Connection_val(conn);
5203 checkConnection(connection);
5205 if (Is_long(option))
5207 char error[128];
5209 sprintf(error, "Unimplemented Option: %s",
5210 findOption(unimplementedOptionMap,
5211 (CURLoption)(Long_val(option))));
5213 failwith(error);
5216 if (!Is_block(option))
5217 failwith("Not a block");
5219 if (Wosize_val(option) < 1)
5220 failwith("Insufficient data in block");
5222 data = Field(option, 0);
5224 if (Tag_val(option) < sizeof(implementedOptionMap)/sizeof(CURLOptionMapping))
5225 (*implementedOptionMap[Tag_val(option)].optionHandler)(connection,
5226 data);
5227 else
5228 failwith("Invalid CURLOPT Option");
5230 CAMLreturn(Val_unit);
5234 ** curl_easy_perform helper function
5237 CAMLprim value helper_curl_easy_perform(value conn)
5239 CAMLparam1(conn);
5240 CURLcode result = CURLE_OK;
5241 Connection *connection = Connection_val(conn);
5243 checkConnection(connection);
5245 enter_blocking_section();
5246 result = curl_easy_perform(connection->connection);
5247 leave_blocking_section();
5249 if (result != CURLE_OK)
5250 raiseError(connection, result);
5252 CAMLreturn(Val_unit);
5256 ** curl_easy_cleanup helper function
5259 CAMLprim value helper_curl_easy_cleanup(value conn)
5261 CAMLparam1(conn);
5262 Connection *connection = Connection_val(conn);
5264 checkConnection(connection);
5266 removeConnection(connection);
5268 CAMLreturn(Val_unit);
5272 ** curl_easy_duphandle helper function
5275 CAMLprim value helper_curl_easy_duphandle(value conn)
5277 CAMLparam1(conn);
5278 CAMLlocal1(result);
5279 Connection *connection = Connection_val(conn);
5281 checkConnection(connection);
5283 result = caml_alloc(1, Abstract_tag);
5284 Field(result, 0) = (value)duplicateConnection(connection);
5286 CAMLreturn(result);
5290 ** curl_easy_getinfo helper function
5293 enum GetInfoResultType {
5294 StringValue, LongValue, DoubleValue, StringListValue
5297 value convertStringList(struct curl_slist *slist)
5299 CAMLparam0();
5300 CAMLlocal3(result, current, next);
5301 struct curl_slist *p = slist;
5303 result = Val_int(0);
5304 current = Val_int(0);
5305 next = Val_int(0);
5307 while (p != NULL)
5309 next = alloc_tuple(2);
5310 Store_field(next, 0, copy_string(p->data));
5311 Store_field(next, 1, Val_int(0));
5313 if (result == Val_int(0))
5314 result = next;
5316 if (current != Val_int(0))
5317 Store_field(current, 1, next);
5319 current = next;
5321 p = p->next;
5324 curl_slist_free_all(slist);
5326 CAMLreturn(result);
5329 CAMLprim value helper_curl_easy_getinfo(value conn, value option)
5331 CAMLparam2(conn, option);
5332 CAMLlocal1(result);
5333 CURLcode curlResult;
5334 Connection *connection = Connection_val(conn);
5335 enum GetInfoResultType resultType;
5336 char *strValue = NULL;
5337 double doubleValue;
5338 long longValue;
5339 struct curl_slist *stringListValue = NULL;
5341 checkConnection(connection);
5343 switch(Long_val(option))
5345 #if HAVE_DECL_CURLINFO_EFFECTIVE_URL
5346 case 0: /* CURLINFO_EFFECTIVE_URL */
5347 resultType = StringValue;
5349 curlResult = curl_easy_getinfo(connection->connection,
5350 CURLINFO_EFFECTIVE_URL,
5351 &strValue);
5352 break;
5353 #else
5354 #warning "libcurl does not provide CURLINFO_EFFECTIVE_URL"
5355 #endif
5357 #if HAVE_DECL_CURLINFO_RESPONSE_CODE || HAVE_DECL_CURLINFO_HTTP_CODE
5358 case 1: /* CURLINFO_HTTP_CODE */
5359 case 2: /* CURLINFO_RESPONSE_CODE */
5360 #if HAVE_DECL_CURLINFO_RESPONSE_CODE
5361 resultType = LongValue;
5363 curlResult = curl_easy_getinfo(connection->connection,
5364 CURLINFO_RESPONSE_CODE,
5365 &longValue);
5366 #else
5367 resultType = LongValue;
5369 curlResult = curl_easy_getinfo(connection->connection,
5370 CURLINFO_HTTP_CODE,
5371 &longValue);
5372 #endif
5373 break;
5374 #endif
5376 #if HAVE_DECL_CURLINFO_TOTAL_TIME
5377 case 3: /* CURLINFO_TOTAL_TIME */
5378 resultType = DoubleValue;
5380 curlResult = curl_easy_getinfo(connection->connection,
5381 CURLINFO_TOTAL_TIME,
5382 &doubleValue);
5383 break;
5384 #endif
5386 #if HAVE_DECL_CURLINFO_NAMELOOKUP_TIME
5387 case 4: /* CURLINFO_NAMELOOKUP_TIME */
5388 resultType = DoubleValue;
5390 curlResult = curl_easy_getinfo(connection->connection,
5391 CURLINFO_NAMELOOKUP_TIME,
5392 &doubleValue);
5393 break;
5394 #endif
5396 #if HAVE_DECL_CURLINFO_CONNECT_TIME
5397 case 5: /* CURLINFO_CONNECT_TIME */
5398 resultType = DoubleValue;
5400 curlResult = curl_easy_getinfo(connection->connection,
5401 CURLINFO_CONNECT_TIME,
5402 &doubleValue);
5403 break;
5404 #endif
5406 #if HAVE_DECL_CURLINFO_PRETRANSFER_TIME
5407 case 6: /* CURLINFO_PRETRANSFER_TIME */
5408 resultType = DoubleValue;
5410 curlResult = curl_easy_getinfo(connection->connection,
5411 CURLINFO_PRETRANSFER_TIME,
5412 &doubleValue);
5413 break;
5414 #endif
5416 #if HAVE_DECL_CURLINFO_SIZE_UPLOAD
5417 case 7: /* CURLINFO_SIZE_UPLOAD */
5418 resultType = DoubleValue;
5420 curlResult = curl_easy_getinfo(connection->connection,
5421 CURLINFO_SIZE_UPLOAD,
5422 &doubleValue);
5423 break;
5424 #endif
5426 #if HAVE_DECL_CURLINFO_SIZE_DOWNLOAD
5427 case 8: /* CURLINFO_SIZE_DOWNLOAD */
5428 resultType = DoubleValue;
5430 curlResult = curl_easy_getinfo(connection->connection,
5431 CURLINFO_SIZE_DOWNLOAD,
5432 &doubleValue);
5433 break;
5434 #endif
5436 #if HAVE_DECL_CURLINFO_SPEED_DOWNLOAD
5437 case 9: /* CURLINFO_SPEED_DOWNLOAD */
5438 resultType = DoubleValue;
5440 curlResult = curl_easy_getinfo(connection->connection,
5441 CURLINFO_SPEED_DOWNLOAD,
5442 &doubleValue);
5443 break;
5444 #endif
5446 #if HAVE_DECL_CURLINFO_SPEED_UPLOAD
5447 case 10: /* CURLINFO_SPEED_UPLOAD */
5448 resultType = DoubleValue;
5450 curlResult = curl_easy_getinfo(connection->connection,
5451 CURLINFO_SPEED_UPLOAD,
5452 &doubleValue);
5453 break;
5455 #endif
5457 #if HAVE_DECL_CURLINFO_HEADER_SIZE
5458 case 11: /* CURLINFO_HEADER_SIZE */
5459 resultType = LongValue;
5461 curlResult = curl_easy_getinfo(connection->connection,
5462 CURLINFO_HEADER_SIZE,
5463 &longValue);
5464 break;
5465 #endif
5467 #if HAVE_DECL_CURLINFO_REQUEST_SIZE
5468 case 12: /* CURLINFO_REQUEST_SIZE */
5469 resultType = LongValue;
5471 curlResult = curl_easy_getinfo(connection->connection,
5472 CURLINFO_REQUEST_SIZE,
5473 &longValue);
5474 break;
5475 #endif
5477 #if HAVE_DECL_CURLINFO_SSL_VERIFYRESULT
5478 case 13: /* CURLINFO_SSL_VERIFYRESULT */
5479 resultType = LongValue;
5481 curlResult = curl_easy_getinfo(connection->connection,
5482 CURLINFO_SSL_VERIFYRESULT,
5483 &longValue);
5484 break;
5485 #endif
5487 #if HAVE_DECL_CURLINFO_FILETIME
5488 case 14: /* CURLINFO_FILETIME */
5489 resultType = DoubleValue;
5491 curlResult = curl_easy_getinfo(connection->connection,
5492 CURLINFO_FILETIME,
5493 &longValue);
5495 doubleValue = longValue;
5496 break;
5497 #endif
5499 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_DOWNLOAD
5500 case 15: /* CURLINFO_CONTENT_LENGTH_DOWNLOAD */
5501 resultType = DoubleValue;
5503 curlResult = curl_easy_getinfo(connection->connection,
5504 CURLINFO_CONTENT_LENGTH_DOWNLOAD,
5505 &doubleValue);
5506 break;
5507 #endif
5509 #if HAVE_DECL_CURLINFO_CONTENT_LENGTH_UPLOAD
5510 case 16: /* CURLINFO_CONTENT_LENGTH_UPLOAD */
5511 resultType = DoubleValue;
5513 curlResult = curl_easy_getinfo(connection->connection,
5514 CURLINFO_CONTENT_LENGTH_UPLOAD,
5515 &doubleValue);
5516 break;
5517 #endif
5519 #if HAVE_DECL_CURLINFO_STARTTRANSFER_TIME
5520 case 17: /* CURLINFO_STARTTRANSFER_TIME */
5521 resultType = DoubleValue;
5523 curlResult = curl_easy_getinfo(connection->connection,
5524 CURLINFO_STARTTRANSFER_TIME,
5525 &doubleValue);
5526 break;
5527 #endif
5529 #if HAVE_DECL_CURLINFO_CONTENT_TYPE
5530 case 18: /* CURLINFO_CONTENT_TYPE */
5531 resultType = StringValue;
5533 curlResult = curl_easy_getinfo(connection->connection,
5534 CURLINFO_CONTENT_TYPE,
5535 &strValue);
5536 break;
5537 #endif
5539 #if HAVE_DECL_CURLINFO_REDIRECT_TIME
5540 case 19: /* CURLINFO_REDIRECT_TIME */
5541 resultType = DoubleValue;
5543 curlResult = curl_easy_getinfo(connection->connection,
5544 CURLINFO_REDIRECT_TIME,
5545 &doubleValue);
5546 break;
5547 #endif
5549 #if HAVE_DECL_CURLINFO_REDIRECT_COUNT
5550 case 20: /* CURLINFO_REDIRECT_COUNT */
5551 resultType = LongValue;
5553 curlResult = curl_easy_getinfo(connection->connection,
5554 CURLINFO_REDIRECT_COUNT,
5555 &longValue);
5556 break;
5557 #endif
5559 #if HAVE_DECL_CURLINFO_PRIVATE
5560 case 21: /* CURLINFO_PRIVATE */
5561 resultType = StringValue;
5563 curlResult = curl_easy_getinfo(connection->connection,
5564 CURLINFO_PRIVATE,
5565 &strValue);
5566 break;
5567 #endif
5569 #if HAVE_DECL_CURLINFO_HTTP_CONNECTCODE
5570 case 22: /* CURLINFO_HTTP_CONNECTCODE */
5571 resultType = LongValue;
5573 curlResult = curl_easy_getinfo(connection->connection,
5574 CURLINFO_HTTP_CONNECTCODE,
5575 &longValue);
5576 break;
5577 #endif
5579 #if HAVE_DECL_CURLINFO_HTTPAUTH_AVAIL
5580 case 23: /* CURLINFO_HTTPAUTH_AVAIL */
5581 resultType = LongValue;
5583 curlResult = curl_easy_getinfo(connection->connection,
5584 CURLINFO_HTTPAUTH_AVAIL,
5585 &longValue);
5586 break;
5587 #endif
5589 #if HAVE_DECL_CURLINFO_PROXYAUTH_AVAIL
5590 case 24: /* CURLINFO_PROXYAUTH_AVAIL */
5591 resultType = LongValue;
5593 curlResult = curl_easy_getinfo(connection->connection,
5594 CURLINFO_PROXYAUTH_AVAIL,
5595 &longValue);
5596 break;
5597 #endif
5599 #if HAVE_DECL_CURLINFO_OS_ERRNO
5600 case 25: /* CURLINFO_OS_ERRNO */
5601 resultType = LongValue;
5603 curlResult = curl_easy_getinfo(connection->connection,
5604 CURLINFO_OS_ERRNO,
5605 &longValue);
5606 break;
5607 #endif
5609 #if HAVE_DECL_CURLINFO_NUM_CONNECTS
5610 case 26: /* CURLINFO_NUM_CONNECTS */
5611 resultType = LongValue;
5613 curlResult = curl_easy_getinfo(connection->connection,
5614 CURLINFO_NUM_CONNECTS,
5615 &longValue);
5616 break;
5617 #endif
5619 #if HAVE_DECL_CURLINFO_SSL_ENGINES
5620 case 27: /* CURLINFO_SSL_ENGINES */
5621 resultType = StringListValue;
5623 curlResult = curl_easy_getinfo(connection->connection,
5624 CURLINFO_SSL_ENGINES,
5625 &stringListValue);
5626 break;
5627 #endif
5629 #if HAVE_DECL_CURLINFO_COOKIELIST
5630 case 28: /* CURLINFO_COOKIELIST */
5631 resultType = StringListValue;
5633 curlResult = curl_easy_getinfo(connection->connection,
5634 CURLINFO_COOKIELIST,
5635 &stringListValue);
5636 break;
5637 #endif
5639 #if HAVE_DECL_CURLINFO_LASTSOCKET
5640 case 29: /* CURLINFO_LASTSOCKET */
5641 resultType = LongValue;
5643 curlResult = curl_easy_getinfo(connection->connection,
5644 CURLINFO_LASTSOCKET,
5645 &longValue);
5646 break;
5647 #endif
5649 #if HAVE_DECL_CURLINFO_FTP_ENTRY_PATH
5650 case 30: /* CURLINFO_FTP_ENTRY_PATH */
5651 resultType = StringValue;
5653 curlResult = curl_easy_getinfo(connection->connection,
5654 CURLINFO_FTP_ENTRY_PATH,
5655 &strValue);
5656 break;
5657 #endif
5659 default:
5660 failwith("Invalid CURLINFO Option");
5661 break;
5664 if (curlResult != CURLE_OK)
5665 raiseError(connection, curlResult);
5667 switch (resultType)
5669 case StringValue:
5670 result = alloc(1, StringValue);
5671 Store_field(result, 0, copy_string(strValue?strValue:""));
5672 break;
5674 case LongValue:
5675 result = alloc(1, LongValue);
5676 Store_field(result, 0, Val_long(longValue));
5677 break;
5679 case DoubleValue:
5680 result = alloc(1, DoubleValue);
5681 Store_field(result, 0, copy_double(doubleValue));
5682 break;
5684 case StringListValue:
5685 result = alloc(1, StringListValue);
5686 Store_field(result, 0, convertStringList(stringListValue));
5687 break;
5690 CAMLreturn(result);
5694 ** curl_escape helper function
5697 CAMLprim value helper_curl_escape(value str)
5699 CAMLparam1(str);
5700 CAMLlocal1(result);
5701 char *curlResult;
5703 curlResult = curl_escape(String_val(str), string_length(str));
5704 result = copy_string(curlResult);
5705 free(curlResult);
5707 CAMLreturn(result);
5711 ** curl_unescape helper function
5714 CAMLprim value helper_curl_unescape(value str)
5716 CAMLparam1(str);
5717 CAMLlocal1(result);
5718 char *curlResult;
5720 curlResult = curl_unescape(String_val(str), string_length(str));
5721 result = copy_string(curlResult);
5722 free(curlResult);
5724 CAMLreturn(result);
5728 ** curl_getdate helper function
5731 CAMLprim value helper_curl_getdate(value str, value now)
5733 CAMLparam2(str, now);
5734 CAMLlocal1(result);
5735 time_t curlResult;
5736 time_t curlNow;
5738 curlNow = (time_t)Double_val(now);
5739 curlResult = curl_getdate(String_val(str), &curlNow);
5740 result = copy_double((double)curlResult);
5742 CAMLreturn(result);
5746 ** curl_version helper function
5749 CAMLprim value helper_curl_version(void)
5751 CAMLparam0();
5752 CAMLlocal1(result);
5753 char *str;
5755 str = curl_version();
5756 result = copy_string(str);
5758 CAMLreturn(result);
5762 * Curl multi stack support
5764 * Exported thin wrappers for libcurl are prefixed with caml_curl_multi_.
5765 * Other exported functions are prefixed with caml_curlm_, some of them
5766 * can/should be decomposed into smaller parts.
5769 struct ml_multi_handle
5771 CURLM* handle;
5772 value values; /* callbacks */
5775 enum
5777 curlmopt_socket_function,
5779 /* last, not used */
5780 multi_values_total,
5783 typedef struct ml_multi_handle ml_multi_handle;
5785 #define Multi_val(v) (*(ml_multi_handle**)Data_custom_val(v))
5786 #define CURLM_val(v) (Multi_val(v)->handle)
5788 static struct custom_operations curl_multi_ops = {
5789 "ygrek.curl_multi",
5790 custom_finalize_default,
5791 custom_compare_default,
5792 custom_hash_default,
5793 custom_serialize_default,
5794 custom_deserialize_default
5797 CAMLprim value caml_curl_multi_init(value unit)
5799 CAMLparam1(unit);
5800 CAMLlocal1(v);
5801 ml_multi_handle* multi = (ml_multi_handle*)caml_stat_alloc(sizeof(ml_multi_handle));
5802 CURLM* h = curl_multi_init();
5804 if (!h)
5806 caml_stat_free(multi);
5807 failwith("caml_curl_multi_init");
5810 multi->handle = h;
5811 multi->values = caml_alloc(multi_values_total, 0);
5812 caml_register_generational_global_root(&multi->values);
5814 v = caml_alloc_custom(&curl_multi_ops, sizeof(ml_multi_handle*), 0, 1);
5815 Multi_val(v) = multi;
5817 CAMLreturn(v);
5820 CAMLprim value caml_curl_multi_cleanup(value handle)
5822 CAMLparam1(handle);
5823 ml_multi_handle* h = Multi_val(handle);
5825 if (NULL == h)
5826 CAMLreturn(Val_unit);
5828 caml_remove_generational_global_root(&h->values);
5830 if (CURLM_OK != curl_multi_cleanup(h->handle))
5831 failwith("caml_curl_multi_cleanup");
5833 Multi_val(handle) = (ml_multi_handle*)NULL;
5835 CAMLreturn(Val_unit);
5838 static CURL* curlm_remove_finished(CURLM* multi_handle, CURLcode* result)
5840 int msgs_in_queue = 0;
5842 while (1)
5844 CURLMsg* msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
5845 if (NULL == msg) return NULL;
5846 if (CURLMSG_DONE == msg->msg)
5848 CURL* easy_handle = msg->easy_handle;
5849 if (result) *result = msg->data.result;
5850 if (CURLM_OK != curl_multi_remove_handle(multi_handle, easy_handle))
5852 //failwith("curlm_remove_finished");
5854 return easy_handle;
5859 CAMLprim value caml_curlm_remove_finished(value v_multi)
5861 CAMLparam1(v_multi);
5862 CAMLlocal2(v_easy, v_tuple);
5863 CURL* handle;
5864 CURLM* multi_handle;
5865 CURLcode result;
5867 multi_handle = CURLM_val(v_multi);
5869 caml_enter_blocking_section();
5870 handle = curlm_remove_finished(multi_handle,&result);
5871 caml_leave_blocking_section();
5873 if (NULL == handle)
5875 CAMLreturn(Val_none);
5877 else
5879 /* not good: same handle, but different block */
5880 v_easy = caml_alloc(1, Abstract_tag);
5881 Field(v_easy, 0) = (value)findConnection(handle);
5882 v_tuple = caml_alloc(2, 0);
5883 Store_field(v_tuple,0,v_easy);
5884 Store_field(v_tuple,1,Val_int(result)); /* CURLcode */
5885 CAMLreturn(Val_some(v_tuple));
5889 static int curlm_wait_data(CURLM* multi_handle)
5891 struct timeval timeout;
5892 CURLMcode ret;
5894 fd_set fdread;
5895 fd_set fdwrite;
5896 fd_set fdexcep;
5897 int maxfd;
5899 FD_ZERO(&fdread);
5900 FD_ZERO(&fdwrite);
5901 FD_ZERO(&fdexcep);
5903 /* set a suitable timeout */
5904 timeout.tv_sec = 1;
5905 timeout.tv_usec = 0;
5907 /* get file descriptors from the transfers */
5908 ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
5910 if (ret == CURLM_OK && maxfd >= 0)
5912 int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
5913 if (-1 != rc) return 0;
5914 //printf("select error\n");
5916 else
5918 //printf("curl_multi_fdset error\n");
5920 return 1;
5923 CAMLprim value caml_curlm_wait_data(value v_multi)
5925 CAMLparam1(v_multi);
5926 int ret;
5927 CURLM* h;
5929 h = CURLM_val(v_multi);
5931 caml_enter_blocking_section();
5932 ret = curlm_wait_data(h);
5933 caml_leave_blocking_section();
5935 CAMLreturn(Val_bool(0 == ret));
5938 CAMLprim value caml_curl_multi_add_handle(value v_multi, value v_easy)
5940 CAMLparam2(v_multi,v_easy);
5942 if (CURLM_OK != curl_multi_add_handle(CURLM_val(v_multi), Connection_val(v_easy)->connection))
5943 failwith("caml_curl_multi_add_handle");
5945 CAMLreturn(Val_unit);
5948 CAMLprim value caml_curl_multi_perform_all(value v_multi)
5950 CAMLparam1(v_multi);
5951 CURLM* h;
5952 int still_running = 0;
5954 h = CURLM_val(v_multi);
5956 caml_enter_blocking_section();
5957 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(h, &still_running));
5958 caml_leave_blocking_section();
5960 CAMLreturn(Val_int(still_running));
5963 CAMLprim value helper_curl_easy_strerror(value v_code)
5965 CAMLparam1(v_code);
5966 CAMLreturn(caml_copy_string(curl_easy_strerror(Int_val(v_code))));