6f5f6997a675ace4e9d0041c0ca56f07329dc29d
[plcapi.git] / pycurl / src / pycurl.c
1 /* $Id: pycurl.c,v 1.86 2005/03/04 08:39:30 kjetilja Exp $ */
2
3 /* PycURL -- cURL Python module
4  *
5  * Authors:
6  *  Copyright (C) 2001-2005 by Kjetil Jacobsen <kjetilja at cs.uit.no>
7  *  Copyright (C) 2001-2005 by Markus F.X.J. Oberhumer <markus at oberhumer.com>
8  *
9  * Contributions:
10  *  Tino Lange <Tino.Lange at gmx.de>
11  *  Matt King <matt at gnik.com>
12  *  Conrad Steenberg <conrad at hep.caltech.edu>
13  *  Amit Mongia <amit_mongia at hotmail.com>
14  *  Eric S. Raymond <esr at thyrsus.com>
15  *  Martin Muenstermann <mamuema at sourceforge.net>
16  *  Domenico Andreoli <cavok at libero.it>
17  *
18  * See file COPYING for license information.
19  *
20  * Some quick info on Python's refcount:
21  *   Py_BuildValue          does incref the item(s)
22  *   PyArg_ParseTuple       does NOT incref the item
23  *   PyList_Append          does incref the item
24  *   PyTuple_SET_ITEM       does NOT incref the item
25  *   PyTuple_SetItem        does NOT incref the item
26  *   PyXXX_GetItem          returns a borrowed reference
27  */
28
29 #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
30 #  define WIN32 1
31 #endif
32 #if defined(WIN32)
33 #  define CURL_STATICLIB 1
34 #endif
35 #include <Python.h>
36 #include <sys/types.h>
37 #include <stddef.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <limits.h>
42 #include <curl/curl.h>
43 #include <curl/multi.h>
44 #undef NDEBUG
45 #include <assert.h>
46
47 /* Ensure we have updated versions */
48 #if !defined(PY_VERSION_HEX) || (PY_VERSION_HEX < 0x02020000)
49 #  error "Need Python version 2.2 or greater to compile pycurl."
50 #endif
51 #if !defined(LIBCURL_VERSION_NUM) || (LIBCURL_VERSION_NUM < 0x070d01)
52 #  error "Need libcurl version 7.13.1 or greater to compile pycurl."
53 #endif
54
55 #undef UNUSED
56 #define UNUSED(var)     ((void)&var)
57
58 #undef COMPILE_TIME_ASSERT
59 #define COMPILE_TIME_ASSERT(expr) \
60      { typedef int compile_time_assert_fail__[1 - 2 * !(expr)]; }
61
62
63 /* Calculate the number of OBJECTPOINT options we need to store */
64 #define OPTIONS_SIZE    ((int)CURLOPT_LASTENTRY % 10000)
65 static int OPT_INDEX(int o)
66 {
67     assert(o >= CURLOPTTYPE_OBJECTPOINT);
68     assert(o < CURLOPTTYPE_OBJECTPOINT + OPTIONS_SIZE);
69     return o - CURLOPTTYPE_OBJECTPOINT;
70 }
71
72
73 static PyObject *ErrorObject = NULL;
74 static PyTypeObject *p_Curl_Type = NULL;
75 static PyTypeObject *p_CurlMulti_Type = NULL;
76
77 typedef struct {
78     PyObject_HEAD
79     PyObject *dict;                 /* Python attributes dictionary */
80     CURLM *multi_handle;
81     PyThreadState *state;
82     fd_set read_fd_set;
83     fd_set write_fd_set;
84     fd_set exc_fd_set;
85 } CurlMultiObject;
86
87 typedef struct {
88     PyObject_HEAD
89     PyObject *dict;                 /* Python attributes dictionary */
90     CURL *handle;
91     PyThreadState *state;
92     CurlMultiObject *multi_stack;
93     struct curl_httppost *httppost;
94     struct curl_slist *httpheader;
95     struct curl_slist *http200aliases;
96     struct curl_slist *quote;
97     struct curl_slist *postquote;
98     struct curl_slist *prequote;
99     struct curl_slist *source_prequote;
100     struct curl_slist *source_postquote;
101     /* callbacks */
102     PyObject *w_cb;
103     PyObject *h_cb;
104     PyObject *r_cb;
105     PyObject *pro_cb;
106     PyObject *debug_cb;
107     PyObject *ioctl_cb;
108     /* file objects */
109     PyObject *readdata_fp;
110     PyObject *writedata_fp;
111     PyObject *writeheader_fp;
112     /* misc */
113     void *options[OPTIONS_SIZE];    /* for OBJECTPOINT options */
114     char error[CURL_ERROR_SIZE+1];
115 } CurlObject;
116
117 /* Throw exception based on return value `res' and `self->error' */
118 #define CURLERROR_RETVAL() do {\
119     PyObject *v; \
120     self->error[sizeof(self->error) - 1] = 0; \
121     v = Py_BuildValue("(is)", (int) (res), self->error); \
122     if (v != NULL) { PyErr_SetObject(ErrorObject, v); Py_DECREF(v); } \
123     return NULL; \
124 } while (0)
125
126 /* Throw exception based on return value `res' and custom message */
127 #define CURLERROR_MSG(msg) do {\
128     PyObject *v; const char *m = (msg); \
129     v = Py_BuildValue("(is)", (int) (res), (m)); \
130     if (v != NULL) { PyErr_SetObject(ErrorObject, v); Py_DECREF(v); } \
131     return NULL; \
132 } while (0)
133
134
135 /* Safe XDECREF for object states that handles nested deallocations */
136 #define ZAP(v) do {\
137     PyObject *tmp = (PyObject *)(v); \
138     (v) = NULL; \
139     Py_XDECREF(tmp); \
140 } while (0)
141
142
143 /*************************************************************************
144 // python utility functions
145 **************************************************************************/
146
147 #if (PY_VERSION_HEX < 0x02030000) && !defined(PY_LONG_LONG)
148 #  define PY_LONG_LONG LONG_LONG
149 #endif
150
151 /* Like PyString_AsString(), but set an exception if the string contains
152  * embedded NULs. Actually PyString_AsStringAndSize() already does that for
153  * us if the `len' parameter is NULL - see Objects/stringobject.c.
154  */
155
156 static char *PyString_AsString_NoNUL(PyObject *obj)
157 {
158     char *s = NULL;
159     int r;
160     r = PyString_AsStringAndSize(obj, &s, NULL);
161     if (r != 0)
162         return NULL;    /* exception already set */
163     assert(s != NULL);
164     return s;
165 }
166
167
168 /* Convert a curl slist (a list of strings) to a Python list.
169  * In case of error return NULL with an exception set.
170  */
171 static PyObject *convert_slist(struct curl_slist *slist, int free_flags)
172 {
173     PyObject *ret = NULL;
174
175     ret = PyList_New(0);
176     if (ret == NULL) goto error;
177
178     for ( ; slist != NULL; slist = slist->next) {
179         PyObject *v = NULL;
180
181         if (slist->data != NULL) {
182             v = PyString_FromString(slist->data);
183             if (v == NULL || PyList_Append(ret, v) != 0) {
184                 Py_XDECREF(v);
185                 goto error;
186             }
187             Py_DECREF(v);
188         }
189     }
190
191     if ((free_flags & 1) && slist)
192         curl_slist_free_all(slist);
193     return ret;
194
195 error:
196     Py_XDECREF(ret);
197     if ((free_flags & 2) && slist)
198         curl_slist_free_all(slist);
199     return NULL;
200 }
201
202
203 /*************************************************************************
204 // static utility functions
205 **************************************************************************/
206
207 static PyThreadState *
208 get_thread_state(const CurlObject *self)
209 {
210     /* Get the thread state for callbacks to run in.
211      * This is either `self->state' when running inside perform() or
212      * `self->multi_stack->state' when running inside multi_perform().
213      * When the result is != NULL we also implicitly assert
214      * a valid `self->handle'.
215      */
216     if (self == NULL)
217         return NULL;
218     assert(self->ob_type == p_Curl_Type);
219     if (self->state != NULL)
220     {
221         /* inside perform() */
222         assert(self->handle != NULL);
223         if (self->multi_stack != NULL) {
224             assert(self->multi_stack->state == NULL);
225         }
226         return self->state;
227     }
228     if (self->multi_stack != NULL && self->multi_stack->state != NULL)
229     {
230         /* inside multi_perform() */
231         assert(self->handle != NULL);
232         assert(self->multi_stack->multi_handle != NULL);
233         assert(self->state == NULL);
234         return self->multi_stack->state;
235     }
236     return NULL;
237 }
238
239
240 /* assert some CurlObject invariants */
241 static void
242 assert_curl_state(const CurlObject *self)
243 {
244     assert(self != NULL);
245     assert(self->ob_type == p_Curl_Type);
246     (void) get_thread_state(self);
247 }
248
249
250 /* assert some CurlMultiObject invariants */
251 static void
252 assert_multi_state(const CurlMultiObject *self)
253 {
254     assert(self != NULL);
255     assert(self->ob_type == p_CurlMulti_Type);
256     if (self->state != NULL) {
257         assert(self->multi_handle != NULL);
258     }
259 }
260
261
262 /* check state for methods */
263 static int
264 check_curl_state(const CurlObject *self, int flags, const char *name)
265 {
266     assert_curl_state(self);
267     if ((flags & 1) && self->handle == NULL) {
268         PyErr_Format(ErrorObject, "cannot invoke %s() - no curl handle", name);
269         return -1;
270     }
271     if ((flags & 2) && get_thread_state(self) != NULL) {
272         PyErr_Format(ErrorObject, "cannot invoke %s() - perform() is currently running", name);
273         return -1;
274     }
275     return 0;
276 }
277
278 static int
279 check_multi_state(const CurlMultiObject *self, int flags, const char *name)
280 {
281     assert_multi_state(self);
282     if ((flags & 1) && self->multi_handle == NULL) {
283         PyErr_Format(ErrorObject, "cannot invoke %s() - no multi handle", name);
284         return -1;
285     }
286     if ((flags & 2) && self->state != NULL) {
287         PyErr_Format(ErrorObject, "cannot invoke %s() - multi_perform() is currently running", name);
288         return -1;
289     }
290     return 0;
291 }
292
293
294 /*************************************************************************
295 // CurlObject
296 **************************************************************************/
297
298 /* --------------- construct/destruct (i.e. open/close) --------------- */
299
300 /* Allocate a new python curl object */
301 static CurlObject *
302 util_curl_new(void)
303 {
304     CurlObject *self;
305
306     self = (CurlObject *) PyObject_GC_New(CurlObject, p_Curl_Type);
307     if (self == NULL)
308         return NULL;
309     PyObject_GC_Track(self);
310
311     /* Set python curl object initial values */
312     self->dict = NULL;
313     self->handle = NULL;
314     self->state = NULL;
315     self->multi_stack = NULL;
316     self->httppost = NULL;
317     self->httpheader = NULL;
318     self->http200aliases = NULL;
319     self->quote = NULL;
320     self->postquote = NULL;
321     self->prequote = NULL;
322     self->source_postquote = NULL;
323     self->source_prequote = NULL;
324
325     /* Set callback pointers to NULL by default */
326     self->w_cb = NULL;
327     self->h_cb = NULL;
328     self->r_cb = NULL;
329     self->pro_cb = NULL;
330     self->debug_cb = NULL;
331     self->ioctl_cb = NULL;
332
333     /* Set file object pointers to NULL by default */
334     self->readdata_fp = NULL;
335     self->writedata_fp = NULL;
336     self->writeheader_fp = NULL;
337
338     /* Zero string pointer memory buffer used by setopt */
339     memset(self->options, 0, sizeof(self->options));
340     memset(self->error, 0, sizeof(self->error));
341
342     return self;
343 }
344
345
346 /* constructor - this is a module-level function returning a new instance */
347 static CurlObject *
348 do_curl_new(PyObject *dummy)
349 {
350     CurlObject *self = NULL;
351     int res;
352     char *s = NULL;
353
354     UNUSED(dummy);
355
356     /* Allocate python curl object */
357     self = util_curl_new();
358     if (self == NULL)
359         return NULL;
360
361     /* Initialize curl handle */
362     self->handle = curl_easy_init();
363     if (self->handle == NULL)
364         goto error;
365
366     /* Set curl error buffer and zero it */
367     res = curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->error);
368     if (res != CURLE_OK)
369         goto error;
370     memset(self->error, 0, sizeof(self->error));
371
372     /* Set backreference */
373     res = curl_easy_setopt(self->handle, CURLOPT_PRIVATE, (char *) self);
374     if (res != CURLE_OK)
375         goto error;
376
377     /* Enable NOPROGRESS by default, i.e. no progress output */
378     res = curl_easy_setopt(self->handle, CURLOPT_NOPROGRESS, (long)1);
379     if (res != CURLE_OK)
380         goto error;
381
382     /* Disable VERBOSE by default, i.e. no verbose output */
383     res = curl_easy_setopt(self->handle, CURLOPT_VERBOSE, (long)0);
384     if (res != CURLE_OK)
385         goto error;
386
387     /* Set FTP_ACCOUNT to NULL by default */
388     res = curl_easy_setopt(self->handle, CURLOPT_FTP_ACCOUNT, NULL);
389     if (res != CURLE_OK)
390         goto error;
391
392     /* Set default USERAGENT */
393     s = (char *) malloc(7 + strlen(LIBCURL_VERSION) + 1);
394     if (s == NULL)
395         goto error;
396     strcpy(s, "PycURL/"); strcpy(s+7, LIBCURL_VERSION);
397     res = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, (char *) s);
398     if (res != CURLE_OK) {
399         free(s);
400         goto error;
401     }
402     self->options[ OPT_INDEX(CURLOPT_USERAGENT) ] = s; s = NULL;
403
404     /* Success - return new object */
405     return self;
406
407 error:
408     Py_DECREF(self);    /* this also closes self->handle */
409     PyErr_SetString(ErrorObject, "initializing curl failed");
410     return NULL;
411 }
412
413
414 /* util function shared by close() and clear() */
415 static void
416 util_curl_xdecref(CurlObject *self, int flags, CURL *handle)
417 {
418     if (flags & 1) {
419         /* Decrement refcount for attributes dictionary. */
420         ZAP(self->dict);
421     }
422
423     if (flags & 2) {
424         /* Decrement refcount for multi_stack. */
425         if (self->multi_stack != NULL) {
426             CurlMultiObject *multi_stack = self->multi_stack;
427             self->multi_stack = NULL;
428             if (multi_stack->multi_handle != NULL && handle != NULL) {
429                 (void) curl_multi_remove_handle(multi_stack->multi_handle, handle);
430             }
431             Py_DECREF(multi_stack);
432         }
433     }
434
435     if (flags & 4) {
436         /* Decrement refcount for python callbacks. */
437         ZAP(self->w_cb);
438         ZAP(self->h_cb);
439         ZAP(self->r_cb);
440         ZAP(self->pro_cb);
441         ZAP(self->debug_cb);
442         ZAP(self->ioctl_cb);
443     }
444
445     if (flags & 8) {
446         /* Decrement refcount for python file objects. */
447         ZAP(self->readdata_fp);
448         ZAP(self->writedata_fp);
449         ZAP(self->writeheader_fp);
450     }
451 }
452
453
454 static void
455 util_curl_close(CurlObject *self)
456 {
457     CURL *handle;
458     int i;
459
460     /* Zero handle and thread-state to disallow any operations to be run
461      * from now on */
462     assert(self != NULL);
463     assert(self->ob_type == p_Curl_Type);
464     handle = self->handle;
465     self->handle = NULL;
466     if (handle == NULL) {
467         /* Some paranoia assertions just to make sure the object
468          * deallocation problem is finally really fixed... */
469         assert(self->state == NULL);
470         assert(self->multi_stack == NULL);
471         return;             /* already closed */
472     }
473     self->state = NULL;
474
475     /* Decref multi stuff which uses this handle */
476     util_curl_xdecref(self, 2, handle);
477
478     /* Cleanup curl handle - must be done without the gil */
479     Py_BEGIN_ALLOW_THREADS
480     curl_easy_cleanup(handle);
481     Py_END_ALLOW_THREADS
482     handle = NULL;
483
484     /* Decref callbacks and file handles */
485     util_curl_xdecref(self, 4 | 8, handle);
486
487     /* Free all variables allocated by setopt */
488 #undef SFREE
489 #define SFREE(v)   if ((v) != NULL) (curl_formfree(v), (v) = NULL)
490     SFREE(self->httppost);
491 #undef SFREE
492 #define SFREE(v)   if ((v) != NULL) (curl_slist_free_all(v), (v) = NULL)
493     SFREE(self->httpheader);
494     SFREE(self->http200aliases);
495     SFREE(self->quote);
496     SFREE(self->postquote);
497     SFREE(self->prequote);
498     SFREE(self->source_postquote);
499     SFREE(self->source_prequote);
500 #undef SFREE
501
502     /* Last, free the options.  This must be done after the curl handle
503      * is closed since libcurl assumes that some options are valid when
504      * invoking curl_easy_cleanup(). */
505     for (i = 0; i < OPTIONS_SIZE; i++) {
506         if (self->options[i] != NULL) {
507             free(self->options[i]);
508             self->options[i] = NULL;
509         }
510     }
511 }
512
513
514 static void
515 do_curl_dealloc(CurlObject *self)
516 {
517     PyObject_GC_UnTrack(self);
518     Py_TRASHCAN_SAFE_BEGIN(self)
519
520     ZAP(self->dict);
521     util_curl_close(self);
522
523     PyObject_GC_Del(self);
524     Py_TRASHCAN_SAFE_END(self)
525 }
526
527
528 static PyObject *
529 do_curl_close(CurlObject *self)
530 {
531     if (check_curl_state(self, 2, "close") != 0) {
532         return NULL;
533     }
534     util_curl_close(self);
535     Py_INCREF(Py_None);
536     return Py_None;
537 }
538
539
540 static PyObject *
541 do_curl_errstr(CurlObject *self)
542 {
543     if (check_curl_state(self, 1 | 2, "errstr") != 0) {
544         return NULL;
545     }
546     self->error[sizeof(self->error) - 1] = 0;
547     return PyString_FromString(self->error);
548 }
549
550
551 /* --------------- GC support --------------- */
552
553 /* Drop references that may have created reference cycles. */
554 static int
555 do_curl_clear(CurlObject *self)
556 {
557     assert(get_thread_state(self) == NULL);
558     util_curl_xdecref(self, 1 | 2 | 4 | 8, self->handle);
559     return 0;
560 }
561
562 /* Traverse all refcounted objects. */
563 static int
564 do_curl_traverse(CurlObject *self, visitproc visit, void *arg)
565 {
566     int err;
567 #undef VISIT
568 #define VISIT(v)    if ((v) != NULL && ((err = visit(v, arg)) != 0)) return err
569
570     VISIT(self->dict);
571     VISIT((PyObject *) self->multi_stack);
572
573     VISIT(self->w_cb);
574     VISIT(self->h_cb);
575     VISIT(self->r_cb);
576     VISIT(self->pro_cb);
577     VISIT(self->debug_cb);
578     VISIT(self->ioctl_cb);
579
580     VISIT(self->readdata_fp);
581     VISIT(self->writedata_fp);
582     VISIT(self->writeheader_fp);
583
584     return 0;
585 #undef VISIT
586 }
587
588
589 /* --------------- perform --------------- */
590
591 static PyObject *
592 do_curl_perform(CurlObject *self)
593 {
594     int res;
595
596     if (check_curl_state(self, 1 | 2, "perform") != 0) {
597         return NULL;
598     }
599
600     /* Save handle to current thread (used as context for python callbacks) */
601     self->state = PyThreadState_Get();
602     assert(self->state != NULL);
603
604     /* Release global lock and start */
605     Py_BEGIN_ALLOW_THREADS
606     res = curl_easy_perform(self->handle);
607     Py_END_ALLOW_THREADS
608
609     /* Zero thread-state to disallow callbacks to be run from now on */
610     self->state = NULL;
611
612     if (res != CURLE_OK) {
613         CURLERROR_RETVAL();
614     }
615     Py_INCREF(Py_None);
616     return Py_None;
617 }
618
619
620 /* --------------- callback handlers --------------- */
621
622 /* IMPORTANT NOTE: due to threading issues, we cannot call _any_ Python
623  * function without acquiring the thread state in the callback handlers.
624  */
625
626 static size_t
627 util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *stream)
628 {
629     CurlObject *self;
630     PyThreadState *tmp_state;
631     PyObject *arglist;
632     PyObject *result = NULL;
633     size_t ret = 0;     /* assume error */
634     PyObject *cb;
635     int total_size;
636
637     /* acquire thread */
638     self = (CurlObject *)stream;
639     tmp_state = get_thread_state(self);
640     if (tmp_state == NULL)
641         return ret;
642     PyEval_AcquireThread(tmp_state);
643
644     /* check args */
645     cb = flags ? self->h_cb : self->w_cb;
646     if (cb == NULL)
647         goto silent_error;
648     if (size <= 0 || nmemb <= 0)
649         goto done;
650     total_size = (int)(size * nmemb);
651     if (total_size < 0 || (size_t)total_size / size != nmemb) {
652         PyErr_SetString(ErrorObject, "integer overflow in write callback");
653         goto verbose_error;
654     }
655
656     /* run callback */
657     arglist = Py_BuildValue("(s#)", ptr, total_size);
658     if (arglist == NULL)
659         goto verbose_error;
660     result = PyEval_CallObject(cb, arglist);
661     Py_DECREF(arglist);
662     if (result == NULL)
663         goto verbose_error;
664
665     /* handle result */
666     if (result == Py_None) {
667         ret = total_size;           /* None means success */
668     }
669     else if (PyInt_Check(result)) {
670         long obj_size = PyInt_AsLong(result);
671         if (obj_size < 0 || obj_size > total_size) {
672             PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
673             goto verbose_error;
674         }
675         ret = (size_t) obj_size;    /* success */
676     }
677     else if (PyLong_Check(result)) {
678         long obj_size = PyLong_AsLong(result);
679         if (obj_size < 0 || obj_size > total_size) {
680             PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
681             goto verbose_error;
682         }
683         ret = (size_t) obj_size;    /* success */
684     }
685     else {
686         PyErr_SetString(ErrorObject, "write callback must return int or None");
687         goto verbose_error;
688     }
689
690 done:
691 silent_error:
692     Py_XDECREF(result);
693     PyEval_ReleaseThread(tmp_state);
694     return ret;
695 verbose_error:
696     PyErr_Print();
697     goto silent_error;
698 }
699
700
701 static size_t
702 write_callback(char *ptr, size_t size, size_t nmemb, void *stream)
703 {
704     return util_write_callback(0, ptr, size, nmemb, stream);
705 }
706
707 static size_t
708 header_callback(char *ptr, size_t size, size_t nmemb, void *stream)
709 {
710     return util_write_callback(1, ptr, size, nmemb, stream);
711 }
712
713
714 static size_t
715 read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
716 {
717     CurlObject *self;
718     PyThreadState *tmp_state;
719     PyObject *arglist;
720     PyObject *result = NULL;
721
722     size_t ret = CURL_READFUNC_ABORT;     /* assume error, this actually works */
723     int total_size;
724
725     /* acquire thread */
726     self = (CurlObject *)stream;
727     tmp_state = get_thread_state(self);
728     if (tmp_state == NULL)
729         return ret;
730     PyEval_AcquireThread(tmp_state);
731
732     /* check args */
733     if (self->r_cb == NULL)
734         goto silent_error;
735     if (size <= 0 || nmemb <= 0)
736         goto done;
737     total_size = (int)(size * nmemb);
738     if (total_size < 0 || (size_t)total_size / size != nmemb) {
739         PyErr_SetString(ErrorObject, "integer overflow in read callback");
740         goto verbose_error;
741     }
742
743     /* run callback */
744     arglist = Py_BuildValue("(i)", total_size);
745     if (arglist == NULL)
746         goto verbose_error;
747     result = PyEval_CallObject(self->r_cb, arglist);
748     Py_DECREF(arglist);
749     if (result == NULL)
750         goto verbose_error;
751
752     /* handle result */
753     if (PyString_Check(result)) {
754         char *buf = NULL;
755         int obj_size = -1;
756         int r;
757         r = PyString_AsStringAndSize(result, &buf, &obj_size);
758         if (r != 0 || obj_size < 0 || obj_size > total_size) {
759             PyErr_Format(ErrorObject, "invalid return value for read callback %ld %ld", (long)obj_size, (long)total_size);
760             goto verbose_error;
761         }
762         memcpy(ptr, buf, obj_size);
763         ret = obj_size;             /* success */
764     }
765     else if (PyInt_Check(result)) {
766         long r = PyInt_AsLong(result);
767         if (r != CURL_READFUNC_ABORT) {
768             goto type_error;
769         }
770         /* ret is CURL_READUNC_ABORT */
771     }
772     else if (PyLong_Check(result)) {
773         long r = PyLong_AsLong(result);
774         if (r != CURL_READFUNC_ABORT) {
775             goto type_error;
776         }
777         /* ret is CURL_READUNC_ABORT */
778     }
779     else {
780     type_error:
781         PyErr_SetString(ErrorObject, "read callback must return string");
782         goto verbose_error;
783     }
784
785 done:
786 silent_error:
787     Py_XDECREF(result);
788     PyEval_ReleaseThread(tmp_state);
789     return ret;
790 verbose_error:
791     PyErr_Print();
792     goto silent_error;
793 }
794
795
796 static int
797 progress_callback(void *stream,
798                   double dltotal, double dlnow, double ultotal, double ulnow)
799 {
800     CurlObject *self;
801     PyThreadState *tmp_state;
802     PyObject *arglist;
803     PyObject *result = NULL;
804     int ret = 1;       /* assume error */
805
806     /* acquire thread */
807     self = (CurlObject *)stream;
808     tmp_state = get_thread_state(self);
809     if (tmp_state == NULL)
810         return ret;
811     PyEval_AcquireThread(tmp_state);
812
813     /* check args */
814     if (self->pro_cb == NULL)
815         goto silent_error;
816
817     /* run callback */
818     arglist = Py_BuildValue("(dddd)", dltotal, dlnow, ultotal, ulnow);
819     if (arglist == NULL)
820         goto verbose_error;
821     result = PyEval_CallObject(self->pro_cb, arglist);
822     Py_DECREF(arglist);
823     if (result == NULL)
824         goto verbose_error;
825
826     /* handle result */
827     if (result == Py_None) {
828         ret = 0;        /* None means success */
829     }
830     else if (PyInt_Check(result)) {
831         ret = (int) PyInt_AsLong(result);
832     }
833     else {
834         ret = PyObject_IsTrue(result);  /* FIXME ??? */
835     }
836
837 silent_error:
838     Py_XDECREF(result);
839     PyEval_ReleaseThread(tmp_state);
840     return ret;
841 verbose_error:
842     PyErr_Print();
843     goto silent_error;
844 }
845
846
847 static int
848 debug_callback(CURL *curlobj, curl_infotype type,
849                char *buffer, size_t total_size, void *stream)
850 {
851     CurlObject *self;
852     PyThreadState *tmp_state;
853     PyObject *arglist;
854     PyObject *result = NULL;
855     int ret = 0;       /* always success */
856
857     UNUSED(curlobj);
858
859     /* acquire thread */
860     self = (CurlObject *)stream;
861     tmp_state = get_thread_state(self);
862     if (tmp_state == NULL)
863         return ret;
864     PyEval_AcquireThread(tmp_state);
865
866     /* check args */
867     if (self->debug_cb == NULL)
868         goto silent_error;
869     if ((int)total_size < 0 || (size_t)((int)total_size) != total_size) {
870         PyErr_SetString(ErrorObject, "integer overflow in debug callback");
871         goto verbose_error;
872     }
873
874     /* run callback */
875     arglist = Py_BuildValue("(is#)", (int)type, buffer, (int)total_size);
876     if (arglist == NULL)
877         goto verbose_error;
878     result = PyEval_CallObject(self->debug_cb, arglist);
879     Py_DECREF(arglist);
880     if (result == NULL)
881         goto verbose_error;
882
883     /* return values from debug callbacks should be ignored */
884
885 silent_error:
886     Py_XDECREF(result);
887     PyEval_ReleaseThread(tmp_state);
888     return ret;
889 verbose_error:
890     PyErr_Print();
891     goto silent_error;
892 }
893
894
895 static curlioerr
896 ioctl_callback(CURL *curlobj, int cmd, void *stream)
897 {
898     CurlObject *self;
899     PyThreadState *tmp_state;
900     PyObject *arglist;
901     PyObject *result = NULL;
902     int ret = CURLIOE_FAILRESTART;       /* assume error */
903
904     UNUSED(curlobj);
905
906     /* acquire thread */
907     self = (CurlObject *)stream;
908     tmp_state = get_thread_state(self);
909     if (tmp_state == NULL)
910         return (curlioerr) ret;
911     PyEval_AcquireThread(tmp_state);
912
913     /* check args */
914     if (self->ioctl_cb == NULL)
915         goto silent_error;
916
917     /* run callback */
918     arglist = Py_BuildValue("(i)", (int)cmd);
919     if (arglist == NULL)
920         goto verbose_error;
921     result = PyEval_CallObject(self->ioctl_cb, arglist);
922     Py_DECREF(arglist);
923     if (result == NULL)
924         goto verbose_error;
925
926     /* handle result */
927     if (result == Py_None) {
928         ret = CURLIOE_OK;        /* None means success */
929     }
930     else if (PyInt_Check(result)) {
931         ret = (int) PyInt_AsLong(result);
932         if (ret >= CURLIOE_LAST || ret < 0) {
933             PyErr_SetString(ErrorObject, "ioctl callback returned invalid value");
934             goto verbose_error;
935         }
936     }
937
938 silent_error:
939     Py_XDECREF(result);
940     PyEval_ReleaseThread(tmp_state);
941     return (curlioerr) ret;
942 verbose_error:
943     PyErr_Print();
944     goto silent_error;
945 }
946
947
948 /* --------------- unsetopt/setopt/getinfo --------------- */
949
950 static PyObject *
951 util_curl_unsetopt(CurlObject *self, int option)
952 {
953     int res;
954     int opt_index = -1;
955
956 #define SETOPT2(o,x) \
957     if ((res = curl_easy_setopt(self->handle, (o), (x))) != CURLE_OK) goto error
958 #define SETOPT(x)   SETOPT2((CURLoption)option, (x))
959
960     /* FIXME: implement more options. Have to carefully check lib/url.c in the
961      *   libcurl source code to see if it's actually safe to simply
962      *   unset the option. */
963     switch (option)
964     {
965     case CURLOPT_HTTPPOST:
966         SETOPT((void *) 0);
967         curl_formfree(self->httppost);
968         self->httppost = NULL;
969         /* FIXME: what about data->set.httpreq ?? */
970         break;
971     case CURLOPT_INFILESIZE:
972         SETOPT((long) -1);
973         break;
974     case CURLOPT_WRITEHEADER:
975         SETOPT((void *) 0);
976         ZAP(self->writeheader_fp);
977         break;
978     case CURLOPT_CAINFO:
979     case CURLOPT_CAPATH:
980     case CURLOPT_COOKIE:
981     case CURLOPT_COOKIEJAR:
982     case CURLOPT_CUSTOMREQUEST:
983     case CURLOPT_EGDSOCKET:
984     case CURLOPT_FTPPORT:
985     case CURLOPT_PROXYUSERPWD:
986     case CURLOPT_RANDOM_FILE:
987     case CURLOPT_SSL_CIPHER_LIST:
988     case CURLOPT_USERPWD:
989         SETOPT((char *) 0);
990         opt_index = OPT_INDEX(option);
991         break;
992
993     /* info: we explicitly list unsupported options here */
994     case CURLOPT_COOKIEFILE:
995     default:
996         PyErr_SetString(PyExc_TypeError, "unsetopt() is not supported for this option");
997         return NULL;
998     }
999
1000     if (opt_index >= 0 && self->options[opt_index] != NULL) {
1001         free(self->options[opt_index]);
1002         self->options[opt_index] = NULL;
1003     }
1004
1005     Py_INCREF(Py_None);
1006     return Py_None;
1007
1008 error:
1009     CURLERROR_RETVAL();
1010
1011 #undef SETOPT
1012 #undef SETOPT2
1013 }
1014
1015
1016 static PyObject *
1017 do_curl_unsetopt(CurlObject *self, PyObject *args)
1018 {
1019     int option;
1020
1021     if (!PyArg_ParseTuple(args, "i:unsetopt", &option)) {
1022         return NULL;
1023     }
1024     if (check_curl_state(self, 1 | 2, "unsetopt") != 0) {
1025         return NULL;
1026     }
1027
1028     /* early checks of option value */
1029     if (option <= 0)
1030         goto error;
1031     if (option >= (int)CURLOPTTYPE_OFF_T + OPTIONS_SIZE)
1032         goto error;
1033     if (option % 10000 >= OPTIONS_SIZE)
1034         goto error;
1035
1036     return util_curl_unsetopt(self, option);
1037
1038 error:
1039     PyErr_SetString(PyExc_TypeError, "invalid arguments to unsetopt");
1040     return NULL;
1041 }
1042
1043
1044 static PyObject *
1045 do_curl_setopt(CurlObject *self, PyObject *args)
1046 {
1047     int option;
1048     PyObject *obj;
1049     int res;
1050
1051     if (!PyArg_ParseTuple(args, "iO:setopt", &option, &obj))
1052         return NULL;
1053     if (check_curl_state(self, 1 | 2, "setopt") != 0)
1054         return NULL;
1055
1056     /* early checks of option value */
1057     if (option <= 0)
1058         goto error;
1059     if (option >= (int)CURLOPTTYPE_OFF_T + OPTIONS_SIZE)
1060         goto error;
1061     if (option % 10000 >= OPTIONS_SIZE)
1062         goto error;
1063
1064 #if 0 /* XXX - should we ??? */
1065     /* Handle the case of None */
1066     if (obj == Py_None) {
1067         return util_curl_unsetopt(self, option);
1068     }
1069 #endif
1070
1071     /* Handle the case of string arguments */
1072     if (PyString_Check(obj)) {
1073         char *str = NULL;
1074         int len = -1;
1075         char *buf;
1076         int opt_index;
1077
1078         /* Check that the option specified a string as well as the input */
1079         switch (option) {
1080         case CURLOPT_CAINFO:
1081         case CURLOPT_CAPATH:
1082         case CURLOPT_COOKIE:
1083         case CURLOPT_COOKIEFILE:
1084         case CURLOPT_COOKIEJAR:
1085         case CURLOPT_CUSTOMREQUEST:
1086         case CURLOPT_EGDSOCKET:
1087         case CURLOPT_ENCODING:
1088         case CURLOPT_FTPPORT:
1089         case CURLOPT_INTERFACE:
1090         case CURLOPT_KRB4LEVEL:
1091         case CURLOPT_NETRC_FILE:
1092         case CURLOPT_PROXY:
1093         case CURLOPT_PROXYUSERPWD:
1094         case CURLOPT_RANDOM_FILE:
1095         case CURLOPT_RANGE:
1096         case CURLOPT_REFERER:
1097         case CURLOPT_SSLCERT:
1098         case CURLOPT_SSLCERTTYPE:
1099         case CURLOPT_SSLENGINE:
1100         case CURLOPT_SSLKEY:
1101         case CURLOPT_SSLKEYPASSWD:
1102         case CURLOPT_SSLKEYTYPE:
1103         case CURLOPT_SSL_CIPHER_LIST:
1104         case CURLOPT_URL:
1105         case CURLOPT_USERAGENT:
1106         case CURLOPT_USERPWD:
1107         case CURLOPT_SOURCE_HOST:
1108         case CURLOPT_SOURCE_USERPWD:
1109         case CURLOPT_SOURCE_PATH:
1110 /* FIXME: check if more of these options allow binary data */
1111             str = PyString_AsString_NoNUL(obj);
1112             if (str == NULL)
1113                 return NULL;
1114             break;
1115         case CURLOPT_POSTFIELDS:
1116             if (PyString_AsStringAndSize(obj, &str, &len) != 0)
1117                 return NULL;
1118             /* automatically set POSTFIELDSIZE */
1119             res = curl_easy_setopt(self->handle, CURLOPT_POSTFIELDSIZE, (long)len);
1120             if (res != CURLE_OK) {
1121                 CURLERROR_RETVAL();
1122             }
1123             break;
1124         default:
1125             PyErr_SetString(PyExc_TypeError, "strings are not supported for this option");
1126             return NULL;
1127         }
1128         /* Allocate memory to hold the string */
1129         assert(str != NULL);
1130         if (len <= 0)
1131             buf = strdup(str);
1132         else {
1133             buf = (char *) malloc(len);
1134             if (buf) memcpy(buf, str, len);
1135         }
1136         if (buf == NULL)
1137             return PyErr_NoMemory();
1138         /* Call setopt */
1139         res = curl_easy_setopt(self->handle, (CURLoption)option, buf);
1140         /* Check for errors */
1141         if (res != CURLE_OK) {
1142             free(buf);
1143             CURLERROR_RETVAL();
1144         }
1145         /* Save allocated option buffer */
1146         opt_index = OPT_INDEX(option);
1147         if (self->options[opt_index] != NULL) {
1148             free(self->options[opt_index]);
1149             self->options[opt_index] = NULL;
1150         }
1151         self->options[opt_index] = buf;
1152         Py_INCREF(Py_None);
1153         return Py_None;
1154     }
1155
1156 #define IS_LONG_OPTION(o)   (o < CURLOPTTYPE_OBJECTPOINT)
1157 #define IS_OFF_T_OPTION(o)  (o >= CURLOPTTYPE_OFF_T)
1158
1159     /* Handle the case of integer arguments */
1160     if (PyInt_Check(obj)) {
1161         long d = PyInt_AsLong(obj);
1162
1163         if (IS_LONG_OPTION(option))
1164             res = curl_easy_setopt(self->handle, (CURLoption)option, (long)d);
1165         else if (IS_OFF_T_OPTION(option))
1166             res = curl_easy_setopt(self->handle, (CURLoption)option, (curl_off_t)d);
1167         else {
1168             PyErr_SetString(PyExc_TypeError, "integers are not supported for this option");
1169             return NULL;
1170         }
1171         if (res != CURLE_OK) {
1172             CURLERROR_RETVAL();
1173         }
1174         Py_INCREF(Py_None);
1175         return Py_None;
1176     }
1177
1178     /* Handle the case of long arguments (used by *_LARGE options) */
1179     if (PyLong_Check(obj)) {
1180         PY_LONG_LONG d = PyLong_AsLongLong(obj);
1181         if (d == -1 && PyErr_Occurred())
1182             return NULL;
1183
1184         if (IS_LONG_OPTION(option) && (long)d == d)
1185             res = curl_easy_setopt(self->handle, (CURLoption)option, (long)d);
1186         else if (IS_OFF_T_OPTION(option) && (curl_off_t)d == d)
1187             res = curl_easy_setopt(self->handle, (CURLoption)option, (curl_off_t)d);
1188         else {
1189             PyErr_SetString(PyExc_TypeError, "longs are not supported for this option");
1190             return NULL;
1191         }
1192         if (res != CURLE_OK) {
1193             CURLERROR_RETVAL();
1194         }
1195         Py_INCREF(Py_None);
1196         return Py_None;
1197     }
1198
1199 #undef IS_LONG_OPTION
1200 #undef IS_OFF_T_OPTION
1201
1202     /* Handle the case of file objects */
1203     if (PyFile_Check(obj)) {
1204         FILE *fp;
1205
1206         /* Ensure the option specified a file as well as the input */
1207         switch (option) {
1208         case CURLOPT_READDATA:
1209         case CURLOPT_WRITEDATA:
1210             break;
1211         case CURLOPT_WRITEHEADER:
1212             if (self->w_cb != NULL) {
1213                 PyErr_SetString(ErrorObject, "cannot combine WRITEHEADER with WRITEFUNCTION.");
1214                 return NULL;
1215             }
1216             break;
1217         default:
1218             PyErr_SetString(PyExc_TypeError, "files are not supported for this option");
1219             return NULL;
1220         }
1221
1222         fp = PyFile_AsFile(obj);
1223         if (fp == NULL) {
1224             PyErr_SetString(PyExc_TypeError, "second argument must be open file");
1225             return NULL;
1226         }
1227         res = curl_easy_setopt(self->handle, (CURLoption)option, fp);
1228         if (res != CURLE_OK) {
1229             CURLERROR_RETVAL();
1230         }
1231         Py_INCREF(obj);
1232
1233         switch (option) {
1234         case CURLOPT_READDATA:
1235             ZAP(self->readdata_fp);
1236             self->readdata_fp = obj;
1237             break;
1238         case CURLOPT_WRITEDATA:
1239             ZAP(self->writedata_fp);
1240             self->writedata_fp = obj;
1241             break;
1242         case CURLOPT_WRITEHEADER:
1243             ZAP(self->writeheader_fp);
1244             self->writeheader_fp = obj;
1245             break;
1246         default:
1247             assert(0);
1248             break;
1249         }
1250         /* Return success */
1251         Py_INCREF(Py_None);
1252         return Py_None;
1253     }
1254
1255     /* Handle the case of list objects */
1256     if (PyList_Check(obj)) {
1257         struct curl_slist **old_slist = NULL;
1258         struct curl_slist *slist = NULL;
1259         int i, len;
1260
1261         switch (option) {
1262         case CURLOPT_HTTP200ALIASES:
1263             old_slist = &self->http200aliases;
1264             break;
1265         case CURLOPT_HTTPHEADER:
1266             old_slist = &self->httpheader;
1267             break;
1268         case CURLOPT_QUOTE:
1269             old_slist = &self->quote;
1270             break;
1271         case CURLOPT_POSTQUOTE:
1272             old_slist = &self->postquote;
1273             break;
1274         case CURLOPT_PREQUOTE:
1275             old_slist = &self->prequote;
1276             break;
1277         case CURLOPT_SOURCE_PREQUOTE:
1278             old_slist = &self->source_prequote;
1279             break;
1280         case CURLOPT_SOURCE_POSTQUOTE:
1281             old_slist = &self->source_postquote;
1282             break;
1283         case CURLOPT_HTTPPOST:
1284             break;
1285         default:
1286             /* None of the list options were recognized, throw exception */
1287             PyErr_SetString(PyExc_TypeError, "lists are not supported for this option");
1288             return NULL;
1289         }
1290
1291         len = PyList_Size(obj);
1292         if (len == 0) {
1293             /* Empty list - do nothing */
1294             Py_INCREF(Py_None);
1295             return Py_None;
1296         }
1297
1298         /* Handle HTTPPOST different since we construct a HttpPost form struct */
1299         if (option == CURLOPT_HTTPPOST) {
1300             struct curl_httppost *post = NULL;
1301             struct curl_httppost *last = NULL;
1302
1303             for (i = 0; i < len; i++) {
1304                 char *nstr = NULL, *cstr = NULL;
1305                 int nlen = -1, clen = -1;
1306                 PyObject *listitem = PyList_GetItem(obj, i);
1307
1308                 if (!PyTuple_Check(listitem)) {
1309                     curl_formfree(post);
1310                     PyErr_SetString(PyExc_TypeError, "list items must be tuple objects");
1311                     return NULL;
1312                 }
1313                 if (PyTuple_GET_SIZE(listitem) != 2) {
1314                     curl_formfree(post);
1315                     PyErr_SetString(PyExc_TypeError, "tuple must contain two elements (name, value)");
1316                     return NULL;
1317                 }
1318                 if (PyString_AsStringAndSize(PyTuple_GET_ITEM(listitem, 0), &nstr, &nlen) != 0) {
1319                     curl_formfree(post);
1320                     PyErr_SetString(PyExc_TypeError, "tuple must contain string as first element");
1321                     return NULL;
1322                 }
1323                 if (PyString_Check(PyTuple_GET_ITEM(listitem, 1))) {
1324                     /* Handle strings as second argument for backwards compatibility */
1325                     PyString_AsStringAndSize(PyTuple_GET_ITEM(listitem, 1), &cstr, &clen);
1326                     /* INFO: curl_formadd() internally does memdup() the data, so
1327                      * embedded NUL characters _are_ allowed here. */
1328                     res = curl_formadd(&post, &last,
1329                                        CURLFORM_COPYNAME, nstr,
1330                                        CURLFORM_NAMELENGTH, (long) nlen,
1331                                        CURLFORM_COPYCONTENTS, cstr,
1332                                        CURLFORM_CONTENTSLENGTH, (long) clen,
1333                                        CURLFORM_END);
1334                     if (res != CURLE_OK) {
1335                         curl_formfree(post);
1336                         CURLERROR_RETVAL();
1337                     }
1338                 }
1339                 else if (PyTuple_Check(PyTuple_GET_ITEM(listitem, 1))) {
1340                     /* Supports content, file and content-type */
1341                     PyObject *t = PyTuple_GET_ITEM(listitem, 1);
1342                     int tlen = PyTuple_Size(t);
1343                     int j, k, l;
1344                     struct curl_forms *forms = NULL;
1345
1346                     /* Sanity check that there are at least two tuple items */
1347                     if (tlen < 2) {
1348                         curl_formfree(post);
1349                         PyErr_SetString(PyExc_TypeError, "tuple must contain at least one option and one value");
1350                         return NULL;
1351                     }
1352
1353                     /* Allocate enough space to accommodate length options for content */
1354                     forms = PyMem_Malloc(sizeof(struct curl_forms) * ((tlen*2) + 1));
1355                     if (forms == NULL) {
1356                         curl_formfree(post);
1357                         PyErr_NoMemory();
1358                         return NULL;
1359                     }
1360
1361                     /* Iterate all the tuple members pairwise */
1362                     for (j = 0, k = 0, l = 0; j < tlen; j += 2, l++) {
1363                         char *ostr;
1364                         int olen, val;
1365
1366                         if (j == (tlen-1)) {
1367                             PyErr_SetString(PyExc_TypeError, "expected value");
1368                             PyMem_Free(forms);
1369                             curl_formfree(post);
1370                             return NULL;
1371                         }
1372                         if (!PyInt_Check(PyTuple_GET_ITEM(t, j))) {
1373                             PyErr_SetString(PyExc_TypeError, "option must be long");
1374                             PyMem_Free(forms);
1375                             curl_formfree(post);
1376                             return NULL;
1377                         }
1378                         if (!PyString_Check(PyTuple_GET_ITEM(t, j+1))) {
1379                             PyErr_SetString(PyExc_TypeError, "value must be string");
1380                             PyMem_Free(forms);
1381                             curl_formfree(post);
1382                             return NULL;
1383                         }
1384
1385                         val = PyLong_AsLong(PyTuple_GET_ITEM(t, j));
1386                         if (val != CURLFORM_COPYCONTENTS &&
1387                             val != CURLFORM_FILE &&
1388                             val != CURLFORM_CONTENTTYPE)
1389                         {
1390                             PyErr_SetString(PyExc_TypeError, "unsupported option");
1391                             PyMem_Free(forms);
1392                             curl_formfree(post);
1393                             return NULL;
1394                         }
1395                         PyString_AsStringAndSize(PyTuple_GET_ITEM(t, j+1), &ostr, &olen);
1396                         forms[k].option = val;
1397                         forms[k].value = ostr;
1398                         ++k;
1399                         if (val == CURLFORM_COPYCONTENTS) {
1400                             /* Contents can contain \0 bytes so we specify the length */
1401                             forms[k].option = CURLFORM_CONTENTSLENGTH;
1402                             forms[k].value = (char *)olen;
1403                             ++k;
1404                         }
1405                     }
1406                     forms[k].option = CURLFORM_END;
1407                     res = curl_formadd(&post, &last,
1408                                        CURLFORM_COPYNAME, nstr,
1409                                        CURLFORM_NAMELENGTH, (long) nlen,
1410                                        CURLFORM_ARRAY, forms,
1411                                        CURLFORM_END);
1412                     PyMem_Free(forms);
1413                     if (res != CURLE_OK) {
1414                         curl_formfree(post);
1415                         CURLERROR_RETVAL();
1416                     }
1417                 } else {
1418                     /* Some other type was given, ignore */
1419                     curl_formfree(post);
1420                     PyErr_SetString(PyExc_TypeError, "unsupported second type in tuple");
1421                     return NULL;
1422                 }
1423             }
1424             res = curl_easy_setopt(self->handle, CURLOPT_HTTPPOST, post);
1425             /* Check for errors */
1426             if (res != CURLE_OK) {
1427                 curl_formfree(post);
1428                 CURLERROR_RETVAL();
1429             }
1430             /* Finally, free previously allocated httppost and update */
1431             curl_formfree(self->httppost);
1432             self->httppost = post;
1433
1434             Py_INCREF(Py_None);
1435             return Py_None;
1436         }
1437
1438         /* Just to be sure we do not bug off here */
1439         assert(old_slist != NULL && slist == NULL);
1440
1441         /* Handle regular list operations on the other options */
1442         for (i = 0; i < len; i++) {
1443             PyObject *listitem = PyList_GetItem(obj, i);
1444             struct curl_slist *nlist;
1445             char *str;
1446
1447             if (!PyString_Check(listitem)) {
1448                 curl_slist_free_all(slist);
1449                 PyErr_SetString(PyExc_TypeError, "list items must be string objects");
1450                 return NULL;
1451             }
1452             /* INFO: curl_slist_append() internally does strdup() the data, so
1453              * no embedded NUL characters allowed here. */
1454             str = PyString_AsString_NoNUL(listitem);
1455             if (str == NULL) {
1456                 curl_slist_free_all(slist);
1457                 return NULL;
1458             }
1459             nlist = curl_slist_append(slist, str);
1460             if (nlist == NULL || nlist->data == NULL) {
1461                 curl_slist_free_all(slist);
1462                 return PyErr_NoMemory();
1463             }
1464             slist = nlist;
1465         }
1466         res = curl_easy_setopt(self->handle, (CURLoption)option, slist);
1467         /* Check for errors */
1468         if (res != CURLE_OK) {
1469             curl_slist_free_all(slist);
1470             CURLERROR_RETVAL();
1471         }
1472         /* Finally, free previously allocated list and update */
1473         curl_slist_free_all(*old_slist);
1474         *old_slist = slist;
1475
1476         Py_INCREF(Py_None);
1477         return Py_None;
1478     }
1479
1480     /* Handle the case of function objects for callbacks */
1481     if (PyFunction_Check(obj) || PyCFunction_Check(obj) || PyMethod_Check(obj)) {
1482         /* We use function types here to make sure that our callback
1483          * definitions exactly match the <curl/curl.h> interface.
1484          */
1485         const curl_write_callback w_cb = write_callback;
1486         const curl_write_callback h_cb = header_callback;
1487         const curl_read_callback r_cb = read_callback;
1488         const curl_progress_callback pro_cb = progress_callback;
1489         const curl_debug_callback debug_cb = debug_callback;
1490         const curl_ioctl_callback ioctl_cb = ioctl_callback;
1491
1492         switch(option) {
1493         case CURLOPT_WRITEFUNCTION:
1494             if (self->writeheader_fp != NULL) {
1495                 PyErr_SetString(ErrorObject, "cannot combine WRITEFUNCTION with WRITEHEADER option.");
1496                 return NULL;
1497             }
1498             Py_INCREF(obj);
1499             ZAP(self->writedata_fp);
1500             ZAP(self->w_cb);
1501             self->w_cb = obj;
1502             curl_easy_setopt(self->handle, CURLOPT_WRITEFUNCTION, w_cb);
1503             curl_easy_setopt(self->handle, CURLOPT_WRITEDATA, self);
1504             break;
1505         case CURLOPT_HEADERFUNCTION:
1506             Py_INCREF(obj);
1507             ZAP(self->h_cb);
1508             self->h_cb = obj;
1509             curl_easy_setopt(self->handle, CURLOPT_HEADERFUNCTION, h_cb);
1510             curl_easy_setopt(self->handle, CURLOPT_WRITEHEADER, self);
1511             break;
1512         case CURLOPT_READFUNCTION:
1513             Py_INCREF(obj);
1514             ZAP(self->readdata_fp);
1515             ZAP(self->r_cb);
1516             self->r_cb = obj;
1517             curl_easy_setopt(self->handle, CURLOPT_READFUNCTION, r_cb);
1518             curl_easy_setopt(self->handle, CURLOPT_READDATA, self);
1519             break;
1520         case CURLOPT_PROGRESSFUNCTION:
1521             Py_INCREF(obj);
1522             ZAP(self->pro_cb);
1523             self->pro_cb = obj;
1524             curl_easy_setopt(self->handle, CURLOPT_PROGRESSFUNCTION, pro_cb);
1525             curl_easy_setopt(self->handle, CURLOPT_PROGRESSDATA, self);
1526             break;
1527         case CURLOPT_DEBUGFUNCTION:
1528             Py_INCREF(obj);
1529             ZAP(self->debug_cb);
1530             self->debug_cb = obj;
1531             curl_easy_setopt(self->handle, CURLOPT_DEBUGFUNCTION, debug_cb);
1532             curl_easy_setopt(self->handle, CURLOPT_DEBUGDATA, self);
1533             break;
1534         case CURLOPT_IOCTLFUNCTION:
1535             Py_INCREF(obj);
1536             ZAP(self->ioctl_cb);
1537             self->ioctl_cb = obj;
1538             curl_easy_setopt(self->handle, CURLOPT_IOCTLFUNCTION, ioctl_cb);
1539             curl_easy_setopt(self->handle, CURLOPT_IOCTLDATA, self);
1540             break;
1541
1542         default:
1543             /* None of the function options were recognized, throw exception */
1544             PyErr_SetString(PyExc_TypeError, "functions are not supported for this option");
1545             return NULL;
1546         }
1547         Py_INCREF(Py_None);
1548         return Py_None;
1549     }
1550
1551     /* Failed to match any of the function signatures -- return error */
1552 error:
1553     PyErr_SetString(PyExc_TypeError, "invalid arguments to setopt");
1554     return NULL;
1555 }
1556
1557
1558 static PyObject *
1559 do_curl_getinfo(CurlObject *self, PyObject *args)
1560 {
1561     int option;
1562     int res;
1563
1564     if (!PyArg_ParseTuple(args, "i:getinfo", &option)) {
1565         return NULL;
1566     }
1567     if (check_curl_state(self, 1 | 2, "getinfo") != 0) {
1568         return NULL;
1569     }
1570
1571     switch (option) {
1572     case CURLINFO_FILETIME:
1573     case CURLINFO_HEADER_SIZE:
1574     case CURLINFO_HTTP_CODE:
1575     case CURLINFO_REDIRECT_COUNT:
1576     case CURLINFO_REQUEST_SIZE:
1577     case CURLINFO_SSL_VERIFYRESULT:
1578     case CURLINFO_HTTP_CONNECTCODE:
1579     case CURLINFO_HTTPAUTH_AVAIL:
1580     case CURLINFO_PROXYAUTH_AVAIL:
1581     case CURLINFO_OS_ERRNO:
1582     case CURLINFO_NUM_CONNECTS:
1583         {
1584             /* Return PyInt as result */
1585             long l_res = -1;
1586
1587             res = curl_easy_getinfo(self->handle, (CURLINFO)option, &l_res);
1588             /* Check for errors and return result */
1589             if (res != CURLE_OK) {
1590                 CURLERROR_RETVAL();
1591             }
1592             return PyInt_FromLong(l_res);
1593         }
1594
1595     case CURLINFO_CONTENT_TYPE:
1596     case CURLINFO_EFFECTIVE_URL:
1597         {
1598             /* Return PyString as result */
1599             char *s_res = NULL;
1600
1601             res = curl_easy_getinfo(self->handle, (CURLINFO)option, &s_res);
1602             if (res != CURLE_OK) {
1603                 CURLERROR_RETVAL();
1604             }
1605             /* If the resulting string is NULL, return None */
1606             if (s_res == NULL) {
1607                 Py_INCREF(Py_None);
1608                 return Py_None;
1609             }
1610             return PyString_FromString(s_res);
1611         }
1612
1613     case CURLINFO_CONNECT_TIME:
1614     case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
1615     case CURLINFO_CONTENT_LENGTH_UPLOAD:
1616     case CURLINFO_NAMELOOKUP_TIME:
1617     case CURLINFO_PRETRANSFER_TIME:
1618     case CURLINFO_REDIRECT_TIME:
1619     case CURLINFO_SIZE_DOWNLOAD:
1620     case CURLINFO_SIZE_UPLOAD:
1621     case CURLINFO_SPEED_DOWNLOAD:
1622     case CURLINFO_SPEED_UPLOAD:
1623     case CURLINFO_STARTTRANSFER_TIME:
1624     case CURLINFO_TOTAL_TIME:
1625         {
1626             /* Return PyFloat as result */
1627             double d_res = 0.0;
1628
1629             res = curl_easy_getinfo(self->handle, (CURLINFO)option, &d_res);
1630             if (res != CURLE_OK) {
1631                 CURLERROR_RETVAL();
1632             }
1633             return PyFloat_FromDouble(d_res);
1634         }
1635
1636     case CURLINFO_SSL_ENGINES:
1637         {
1638             /* Return a list of strings */
1639             struct curl_slist *slist = NULL;
1640
1641             res = curl_easy_getinfo(self->handle, (CURLINFO)option, &slist);
1642             if (res != CURLE_OK) {
1643                 CURLERROR_RETVAL();
1644             }
1645             return convert_slist(slist, 1 | 2);
1646         }
1647     }
1648
1649     /* Got wrong option on the method call */
1650     PyErr_SetString(PyExc_ValueError, "invalid argument to getinfo");
1651     return NULL;
1652 }
1653
1654
1655 /*************************************************************************
1656 // CurlMultiObject
1657 **************************************************************************/
1658
1659 /* --------------- construct/destruct (i.e. open/close) --------------- */
1660
1661 /* constructor - this is a module-level function returning a new instance */
1662 static CurlMultiObject *
1663 do_multi_new(PyObject *dummy)
1664 {
1665     CurlMultiObject *self;
1666
1667     UNUSED(dummy);
1668
1669     /* Allocate python curl-multi object */
1670     self = (CurlMultiObject *) PyObject_GC_New(CurlMultiObject, p_CurlMulti_Type);
1671     if (self) {
1672         PyObject_GC_Track(self);
1673     }
1674     else {
1675         return NULL;
1676     }
1677
1678     /* Initialize object attributes */
1679     self->dict = NULL;
1680     self->state = NULL;
1681
1682     /* Allocate libcurl multi handle */
1683     self->multi_handle = curl_multi_init();
1684     if (self->multi_handle == NULL) {
1685         Py_DECREF(self);
1686         PyErr_SetString(ErrorObject, "initializing curl-multi failed");
1687         return NULL;
1688     }
1689     return self;
1690 }
1691
1692
1693 static void
1694 util_multi_close(CurlMultiObject *self)
1695 {
1696     assert(self != NULL);
1697     self->state = NULL;
1698     if (self->multi_handle != NULL) {
1699         CURLM *multi_handle = self->multi_handle;
1700         self->multi_handle = NULL;
1701         curl_multi_cleanup(multi_handle);
1702     }
1703 }
1704
1705
1706 static void
1707 do_multi_dealloc(CurlMultiObject *self)
1708 {
1709     PyObject_GC_UnTrack(self);
1710     Py_TRASHCAN_SAFE_BEGIN(self)
1711
1712     ZAP(self->dict);
1713     util_multi_close(self);
1714
1715     PyObject_GC_Del(self);
1716     Py_TRASHCAN_SAFE_END(self)
1717 }
1718
1719
1720 static PyObject *
1721 do_multi_close(CurlMultiObject *self)
1722 {
1723     if (check_multi_state(self, 2, "close") != 0) {
1724         return NULL;
1725     }
1726     util_multi_close(self);
1727     Py_INCREF(Py_None);
1728     return Py_None;
1729 }
1730
1731
1732 /* --------------- GC support --------------- */
1733
1734 /* Drop references that may have created reference cycles. */
1735 static int
1736 do_multi_clear(CurlMultiObject *self)
1737 {
1738     ZAP(self->dict);
1739     return 0;
1740 }
1741
1742 static int
1743 do_multi_traverse(CurlMultiObject *self, visitproc visit, void *arg)
1744 {
1745     int err;
1746 #undef VISIT
1747 #define VISIT(v)    if ((v) != NULL && ((err = visit(v, arg)) != 0)) return err
1748
1749     VISIT(self->dict);
1750
1751     return 0;
1752 #undef VISIT
1753 }
1754
1755 /* --------------- perform --------------- */
1756
1757
1758 static PyObject *
1759 do_multi_perform(CurlMultiObject *self)
1760 {
1761     CURLMcode res;
1762     int running = -1;
1763
1764     if (check_multi_state(self, 1 | 2, "perform") != 0) {
1765         return NULL;
1766     }
1767
1768     /* Release global lock and start */
1769     self->state = PyThreadState_Get();
1770     assert(self->state != NULL);
1771     Py_BEGIN_ALLOW_THREADS
1772     res = curl_multi_perform(self->multi_handle, &running);
1773     Py_END_ALLOW_THREADS
1774     self->state = NULL;
1775
1776     /* We assume these errors are ok, otherwise throw exception */
1777     if (res != CURLM_OK && res != CURLM_CALL_MULTI_PERFORM) {
1778         CURLERROR_MSG("perform failed");
1779     }
1780
1781     /* Return a tuple with the result and the number of running handles */
1782     return Py_BuildValue("(ii)", (int)res, running);
1783 }
1784
1785
1786 /* --------------- add_handle/remove_handle --------------- */
1787
1788 /* static utility function */
1789 static int
1790 check_multi_add_remove(const CurlMultiObject *self, const CurlObject *obj)
1791 {
1792     /* check CurlMultiObject status */
1793     assert_multi_state(self);
1794     if (self->multi_handle == NULL) {
1795         PyErr_SetString(ErrorObject, "cannot add/remove handle - multi-stack is closed");
1796         return -1;
1797     }
1798     if (self->state != NULL) {
1799         PyErr_SetString(ErrorObject, "cannot add/remove handle - multi_perform() already running");
1800         return -1;
1801     }
1802     /* check CurlObject status */
1803     assert_curl_state(obj);
1804     if (obj->state != NULL) {
1805         PyErr_SetString(ErrorObject, "cannot add/remove handle - perform() of curl object already running");
1806         return -1;
1807     }
1808     if (obj->multi_stack != NULL && obj->multi_stack != self) {
1809         PyErr_SetString(ErrorObject, "cannot add/remove handle - curl object already on another multi-stack");
1810         return -1;
1811     }
1812     return 0;
1813 }
1814
1815
1816 static PyObject *
1817 do_multi_add_handle(CurlMultiObject *self, PyObject *args)
1818 {
1819     CurlObject *obj;
1820     CURLMcode res;
1821
1822     if (!PyArg_ParseTuple(args, "O!:add_handle", p_Curl_Type, &obj)) {
1823         return NULL;
1824     }
1825     if (check_multi_add_remove(self, obj) != 0) {
1826         return NULL;
1827     }
1828     if (obj->handle == NULL) {
1829         PyErr_SetString(ErrorObject, "curl object already closed");
1830         return NULL;
1831     }
1832     if (obj->multi_stack == self) {
1833         PyErr_SetString(ErrorObject, "curl object already on this multi-stack");
1834         return NULL;
1835     }
1836     assert(obj->multi_stack == NULL);
1837     res = curl_multi_add_handle(self->multi_handle, obj->handle);
1838     if (res != CURLM_OK) {
1839         CURLERROR_MSG("curl_multi_add_handle() failed due to internal errors");
1840     }
1841     obj->multi_stack = self;
1842     Py_INCREF(self);
1843     Py_INCREF(Py_None);
1844     return Py_None;
1845 }
1846
1847
1848 static PyObject *
1849 do_multi_remove_handle(CurlMultiObject *self, PyObject *args)
1850 {
1851     CurlObject *obj;
1852     CURLMcode res;
1853
1854     if (!PyArg_ParseTuple(args, "O!:remove_handle", p_Curl_Type, &obj)) {
1855         return NULL;
1856     }
1857     if (check_multi_add_remove(self, obj) != 0) {
1858         return NULL;
1859     }
1860     if (obj->handle == NULL) {
1861         /* CurlObject handle already closed -- ignore */
1862         goto done;
1863     }
1864     if (obj->multi_stack != self) {
1865         PyErr_SetString(ErrorObject, "curl object not on this multi-stack");
1866         return NULL;
1867     }
1868     res = curl_multi_remove_handle(self->multi_handle, obj->handle);
1869     if (res != CURLM_OK) {
1870         CURLERROR_MSG("curl_multi_remove_handle() failed due to internal errors");
1871     }
1872     assert(obj->multi_stack == self);
1873     obj->multi_stack = NULL;
1874     Py_DECREF(self);
1875 done:
1876     Py_INCREF(Py_None);
1877     return Py_None;
1878 }
1879
1880
1881 /* --------------- fdset ---------------------- */
1882
1883 static PyObject *
1884 do_multi_fdset(CurlMultiObject *self)
1885 {
1886     CURLMcode res;
1887     int max_fd = -1, fd;
1888     PyObject *ret = NULL;
1889     PyObject *read_list = NULL, *write_list = NULL, *except_list = NULL;
1890     PyObject *py_fd = NULL;
1891
1892     if (check_multi_state(self, 1 | 2, "fdset") != 0) {
1893         return NULL;
1894     }
1895
1896     /* Clear file descriptor sets */
1897     FD_ZERO(&self->read_fd_set);
1898     FD_ZERO(&self->write_fd_set);
1899     FD_ZERO(&self->exc_fd_set);
1900
1901     /* Don't bother releasing the gil as this is just a data structure operation */
1902     res = curl_multi_fdset(self->multi_handle, &self->read_fd_set,
1903                            &self->write_fd_set, &self->exc_fd_set, &max_fd);
1904     if (res != CURLM_OK || max_fd < 0) {
1905         CURLERROR_MSG("curl_multi_fdset() failed due to internal errors");
1906     }
1907
1908     /* Allocate lists. */
1909     if ((read_list = PyList_New(0)) == NULL) goto error;
1910     if ((write_list = PyList_New(0)) == NULL) goto error;
1911     if ((except_list = PyList_New(0)) == NULL) goto error;
1912
1913     /* Populate lists */
1914     for (fd = 0; fd < max_fd + 1; fd++) {
1915         if (FD_ISSET(fd, &self->read_fd_set)) {
1916             if ((py_fd = PyInt_FromLong((long)fd)) == NULL) goto error;
1917             if (PyList_Append(read_list, py_fd) != 0) goto error;
1918             Py_DECREF(py_fd);
1919             py_fd = NULL;
1920         }
1921         if (FD_ISSET(fd, &self->write_fd_set)) {
1922             if ((py_fd = PyInt_FromLong((long)fd)) == NULL) goto error;
1923             if (PyList_Append(write_list, py_fd) != 0) goto error;
1924             Py_DECREF(py_fd);
1925             py_fd = NULL;
1926         }
1927         if (FD_ISSET(fd, &self->exc_fd_set)) {
1928             if ((py_fd = PyInt_FromLong((long)fd)) == NULL) goto error;
1929             if (PyList_Append(except_list, py_fd) != 0) goto error;
1930             Py_DECREF(py_fd);
1931             py_fd = NULL;
1932         }
1933     }
1934
1935     /* Return a tuple with the 3 lists */
1936     ret = Py_BuildValue("(OOO)", read_list, write_list, except_list);
1937 error:
1938     Py_XDECREF(py_fd);
1939     Py_XDECREF(except_list);
1940     Py_XDECREF(write_list);
1941     Py_XDECREF(read_list);
1942     return ret;
1943 }
1944
1945
1946 /* --------------- info_read --------------- */
1947
1948 static PyObject *
1949 do_multi_info_read(CurlMultiObject *self, PyObject *args)
1950 {
1951     PyObject *ret = NULL;
1952     PyObject *ok_list = NULL, *err_list = NULL;
1953     CURLMsg *msg;
1954     int in_queue = 0, num_results = INT_MAX;
1955
1956     /* Sanity checks */
1957     if (!PyArg_ParseTuple(args, "|i:info_read", &num_results)) {
1958         return NULL;
1959     }
1960     if (num_results <= 0) {
1961         PyErr_SetString(ErrorObject, "argument to info_read must be greater than zero");
1962         return NULL;
1963     }
1964     if (check_multi_state(self, 1 | 2, "info_read") != 0) {
1965         return NULL;
1966     }
1967
1968     if ((ok_list = PyList_New(0)) == NULL) goto error;
1969     if ((err_list = PyList_New(0)) == NULL) goto error;
1970
1971     /* Loop through all messages */
1972     while ((msg = curl_multi_info_read(self->multi_handle, &in_queue)) != NULL) {
1973         CURLcode res;
1974         CurlObject *co = NULL;
1975
1976         /* Check for termination as specified by the user */
1977         if (num_results-- <= 0) {
1978             break;
1979         }
1980
1981         /* Fetch the curl object that corresponds to the curl handle in the message */
1982         res = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &co);
1983         if (res != CURLE_OK || co == NULL) {
1984             Py_DECREF(err_list);
1985             Py_DECREF(ok_list);
1986             CURLERROR_MSG("Unable to fetch curl handle from curl object");
1987         }
1988         assert(co->ob_type == p_Curl_Type);
1989         if (msg->msg != CURLMSG_DONE) {
1990             /* FIXME: what does this mean ??? */
1991         }
1992         if (msg->data.result == CURLE_OK) {
1993             /* Append curl object to list of objects which succeeded */
1994             if (PyList_Append(ok_list, (PyObject *)co) != 0) {
1995                 goto error;
1996             }
1997         }
1998         else {
1999             /* Create a result tuple that will get added to err_list. */
2000             PyObject *v = Py_BuildValue("(Ois)", (PyObject *)co, (int)msg->data.result, co->error);
2001             /* Append curl object to list of objects which failed */
2002             if (v == NULL || PyList_Append(err_list, v) != 0) {
2003                 Py_XDECREF(v);
2004                 goto error;
2005             }
2006             Py_DECREF(v);
2007         }
2008     }
2009     /* Return (number of queued messages, [ok_objects], [error_objects]) */
2010     ret = Py_BuildValue("(iOO)", in_queue, ok_list, err_list);
2011 error:
2012     Py_XDECREF(err_list);
2013     Py_XDECREF(ok_list);
2014     return ret;
2015 }
2016
2017
2018 /* --------------- select --------------- */
2019
2020 static PyObject *
2021 do_multi_select(CurlMultiObject *self, PyObject *args)
2022 {
2023     int max_fd = -1, n;
2024     double timeout = -1.0;
2025     struct timeval tv, *tvp;
2026     CURLMcode res;
2027
2028     if (!PyArg_ParseTuple(args, "|d:select", &timeout)) {
2029         return NULL;
2030     }
2031     if (check_multi_state(self, 1 | 2, "select") != 0) {
2032         return NULL;
2033     }
2034
2035    if (timeout == -1.0) {
2036         /* no timeout given - wait forever */
2037         tvp = NULL;
2038    } else if (timeout < 0 || timeout >= 365 * 24 * 60 * 60) {
2039         PyErr_SetString(PyExc_OverflowError, "invalid timeout period");
2040         return NULL;
2041    } else {
2042         long seconds = (long)timeout;
2043         timeout = timeout - (double)seconds;
2044         assert(timeout >= 0.0); assert(timeout < 1.0);
2045         tv.tv_sec = seconds;
2046         tv.tv_usec = (long)(timeout*1000000.0);
2047         tvp = &tv;
2048     }
2049
2050     FD_ZERO(&self->read_fd_set);
2051     FD_ZERO(&self->write_fd_set);
2052     FD_ZERO(&self->exc_fd_set);
2053
2054     res = curl_multi_fdset(self->multi_handle, &self->read_fd_set,
2055                            &self->write_fd_set, &self->exc_fd_set, &max_fd);
2056     if (res != CURLM_OK) {
2057         CURLERROR_MSG("multi_fdset failed");
2058     }
2059
2060     if (max_fd < 0) {
2061         n = 0;
2062     }
2063     else {
2064         Py_BEGIN_ALLOW_THREADS
2065         n = select(max_fd + 1, &self->read_fd_set, &self->write_fd_set, &self->exc_fd_set, tvp);
2066         Py_END_ALLOW_THREADS
2067         /* info: like Python's socketmodule.c we do not raise an exception
2068          *       if select() fails - we'll leave it to the actual libcurl
2069          *       socket code to report any errors.
2070          */
2071     }
2072
2073     return PyInt_FromLong(n);
2074 }
2075
2076
2077 /*************************************************************************
2078 // type definitions
2079 **************************************************************************/
2080
2081 /* --------------- methods --------------- */
2082
2083 static char co_close_doc [] = "close() -> None.  Close handle and end curl session.\n";
2084 static char co_errstr_doc [] = "errstr() -> String.  Return the internal libcurl error buffer string.\n";
2085 static char co_getinfo_doc [] = "getinfo(info) -> Res.  Extract and return information from a curl session.  Throws pycurl.error exception upon failure.\n";
2086 static char co_perform_doc [] = "perform() -> None.  Perform a file transfer.  Throws pycurl.error exception upon failure.\n";
2087 static char co_setopt_doc [] = "setopt(option, parameter) -> None.  Set curl session option.  Throws pycurl.error exception upon failure.\n";
2088 static char co_unsetopt_doc [] = "unsetopt(option) -> None.  Reset curl session option to default value.  Throws pycurl.error exception upon failure.\n";
2089
2090 static char co_multi_fdset_doc [] = "fdset() -> Tuple.  Returns a tuple of three lists that can be passed to the select.select() method .\n";
2091 static char co_multi_info_read_doc [] = "info_read([max_objects]) -> Tuple. Returns a tuple (number of queued handles, [curl objects]).\n";
2092 static char co_multi_select_doc [] = "select([timeout]) -> Int.  Returns result from doing a select() on the curl multi file descriptor with the given timeout.\n";
2093
2094 static PyMethodDef curlobject_methods[] = {
2095     {"close", (PyCFunction)do_curl_close, METH_NOARGS, co_close_doc},
2096     {"errstr", (PyCFunction)do_curl_errstr, METH_NOARGS, co_errstr_doc},
2097     {"getinfo", (PyCFunction)do_curl_getinfo, METH_VARARGS, co_getinfo_doc},
2098     {"perform", (PyCFunction)do_curl_perform, METH_NOARGS, co_perform_doc},
2099     {"setopt", (PyCFunction)do_curl_setopt, METH_VARARGS, co_setopt_doc},
2100     {"unsetopt", (PyCFunction)do_curl_unsetopt, METH_VARARGS, co_unsetopt_doc},
2101     {NULL, NULL, 0, NULL}
2102 };
2103
2104 static PyMethodDef curlmultiobject_methods[] = {
2105     {"add_handle", (PyCFunction)do_multi_add_handle, METH_VARARGS, NULL},
2106     {"close", (PyCFunction)do_multi_close, METH_NOARGS, NULL},
2107     {"fdset", (PyCFunction)do_multi_fdset, METH_NOARGS, co_multi_fdset_doc},
2108     {"info_read", (PyCFunction)do_multi_info_read, METH_VARARGS, co_multi_info_read_doc},
2109     {"perform", (PyCFunction)do_multi_perform, METH_NOARGS, NULL},
2110     {"remove_handle", (PyCFunction)do_multi_remove_handle, METH_VARARGS, NULL},
2111     {"select", (PyCFunction)do_multi_select, METH_VARARGS, co_multi_select_doc},
2112     {NULL, NULL, 0, NULL}
2113 };
2114
2115
2116 /* --------------- setattr/getattr --------------- */
2117
2118 static PyObject *curlobject_constants = NULL;
2119 static PyObject *curlmultiobject_constants = NULL;
2120
2121 static int
2122 my_setattr(PyObject **dict, char *name, PyObject *v)
2123 {
2124     if (v == NULL) {
2125         int rv = -1;
2126         if (*dict != NULL)
2127             rv = PyDict_DelItemString(*dict, name);
2128         if (rv < 0)
2129             PyErr_SetString(PyExc_AttributeError, "delete non-existing attribute");
2130         return rv;
2131     }
2132     if (*dict == NULL) {
2133         *dict = PyDict_New();
2134         if (*dict == NULL)
2135             return -1;
2136     }
2137     return PyDict_SetItemString(*dict, name, v);
2138 }
2139
2140 static PyObject *
2141 my_getattr(PyObject *co, char *name, PyObject *dict1, PyObject *dict2, PyMethodDef *m)
2142 {
2143     PyObject *v = NULL;
2144     if (v == NULL && dict1 != NULL)
2145         v = PyDict_GetItemString(dict1, name);
2146     if (v == NULL && dict2 != NULL)
2147         v = PyDict_GetItemString(dict2, name);
2148     if (v != NULL) {
2149         Py_INCREF(v);
2150         return v;
2151     }
2152     return Py_FindMethod(m, co, name);
2153 }
2154
2155 static int
2156 do_curl_setattr(CurlObject *co, char *name, PyObject *v)
2157 {
2158     assert_curl_state(co);
2159     return my_setattr(&co->dict, name, v);
2160 }
2161
2162 static int
2163 do_multi_setattr(CurlMultiObject *co, char *name, PyObject *v)
2164 {
2165     assert_multi_state(co);
2166     return my_setattr(&co->dict, name, v);
2167 }
2168
2169 static PyObject *
2170 do_curl_getattr(CurlObject *co, char *name)
2171 {
2172     assert_curl_state(co);
2173     return my_getattr((PyObject *)co, name, co->dict,
2174                       curlobject_constants, curlobject_methods);
2175 }
2176
2177 static PyObject *
2178 do_multi_getattr(CurlMultiObject *co, char *name)
2179 {
2180     assert_multi_state(co);
2181     return my_getattr((PyObject *)co, name, co->dict,
2182                       curlmultiobject_constants, curlmultiobject_methods);
2183 }
2184
2185
2186 /* --------------- actual type definitions --------------- */
2187
2188 static PyTypeObject Curl_Type = {
2189     PyObject_HEAD_INIT(NULL)
2190     0,                          /* ob_size */
2191     "pycurl.Curl",              /* tp_name */
2192     sizeof(CurlObject),         /* tp_basicsize */
2193     0,                          /* tp_itemsize */
2194     /* Methods */
2195     (destructor)do_curl_dealloc,   /* tp_dealloc */
2196     0,                          /* tp_print */
2197     (getattrfunc)do_curl_getattr,  /* tp_getattr */
2198     (setattrfunc)do_curl_setattr,  /* tp_setattr */
2199     0,                          /* tp_compare */
2200     0,                          /* tp_repr */
2201     0,                          /* tp_as_number */
2202     0,                          /* tp_as_sequence */
2203     0,                          /* tp_as_mapping */
2204     0,                          /* tp_hash */
2205     0,                          /* tp_call */
2206     0,                          /* tp_str */
2207     0,                          /* tp_getattro */
2208     0,                          /* tp_setattro */
2209     0,                          /* tp_as_buffer */
2210     Py_TPFLAGS_HAVE_GC,         /* tp_flags */
2211     0,                          /* tp_doc */
2212     (traverseproc)do_curl_traverse, /* tp_traverse */
2213     (inquiry)do_curl_clear      /* tp_clear */
2214     /* More fields follow here, depending on your Python version. You can
2215      * safely ignore any compiler warnings about missing initializers.
2216      */
2217 };
2218
2219 static PyTypeObject CurlMulti_Type = {
2220     PyObject_HEAD_INIT(NULL)
2221     0,                          /* ob_size */
2222     "pycurl.CurlMulti",         /* tp_name */
2223     sizeof(CurlMultiObject),    /* tp_basicsize */
2224     0,                          /* tp_itemsize */
2225     /* Methods */
2226     (destructor)do_multi_dealloc,   /* tp_dealloc */
2227     0,                          /* tp_print */
2228     (getattrfunc)do_multi_getattr,  /* tp_getattr */
2229     (setattrfunc)do_multi_setattr,  /* tp_setattr */
2230     0,                          /* tp_compare */
2231     0,                          /* tp_repr */
2232     0,                          /* tp_as_number */
2233     0,                          /* tp_as_sequence */
2234     0,                          /* tp_as_mapping */
2235     0,                          /* tp_hash */
2236     0,                          /* tp_call */
2237     0,                          /* tp_str */
2238     0,                          /* tp_getattro */
2239     0,                          /* tp_setattro */
2240     0,                          /* tp_as_buffer */
2241     Py_TPFLAGS_HAVE_GC,         /* tp_flags */
2242     0,                          /* tp_doc */
2243     (traverseproc)do_multi_traverse, /* tp_traverse */
2244     (inquiry)do_multi_clear     /* tp_clear */
2245     /* More fields follow here, depending on your Python version. You can
2246      * safely ignore any compiler warnings about missing initializers.
2247      */
2248 };
2249
2250
2251 /*************************************************************************
2252 // module level
2253 // Note that the object constructors (do_curl_new, do_multi_new)
2254 // are module-level functions as well.
2255 **************************************************************************/
2256
2257 static PyObject *
2258 do_global_init(PyObject *dummy, PyObject *args)
2259 {
2260     int res, option;
2261
2262     UNUSED(dummy);
2263     if (!PyArg_ParseTuple(args, "i:global_init", &option)) {
2264         return NULL;
2265     }
2266
2267     if (!(option == CURL_GLOBAL_SSL ||
2268           option == CURL_GLOBAL_WIN32 ||
2269           option == CURL_GLOBAL_ALL ||
2270           option == CURL_GLOBAL_NOTHING)) {
2271         PyErr_SetString(PyExc_ValueError, "invalid option to global_init");
2272         return NULL;
2273     }
2274
2275     res = curl_global_init(option);
2276     if (res != CURLE_OK) {
2277         PyErr_SetString(ErrorObject, "unable to set global option");
2278         return NULL;
2279     }
2280
2281     Py_INCREF(Py_None);
2282     return Py_None;
2283 }
2284
2285
2286 static PyObject *
2287 do_global_cleanup(PyObject *dummy)
2288 {
2289     UNUSED(dummy);
2290     curl_global_cleanup();
2291     Py_INCREF(Py_None);
2292     return Py_None;
2293 }
2294
2295
2296
2297 static PyObject *vi_str(const char *s)
2298 {
2299     if (s == NULL) {
2300         Py_INCREF(Py_None);
2301         return Py_None;
2302     }
2303     while (*s == ' ' || *s == '\t')
2304         s++;
2305     return PyString_FromString(s);
2306 }
2307
2308 static PyObject *
2309 do_version_info(PyObject *dummy, PyObject *args)
2310 {
2311     const curl_version_info_data *vi;
2312     PyObject *ret = NULL;
2313     PyObject *protocols = NULL;
2314     PyObject *tmp;
2315     int i;
2316     int stamp = CURLVERSION_NOW;
2317
2318     UNUSED(dummy);
2319     if (!PyArg_ParseTuple(args, "|i:version_info", &stamp)) {
2320         return NULL;
2321     }
2322     vi = curl_version_info((CURLversion) stamp);
2323     if (vi == NULL) {
2324         PyErr_SetString(ErrorObject, "unable to get version info");
2325         return NULL;
2326     }
2327
2328     /* Note: actually libcurl in lib/version.c does ignore
2329      * the "stamp" parm, and so do we */
2330
2331     for (i = 0; vi->protocols[i] != NULL; )
2332         i++;
2333     protocols = PyTuple_New(i);
2334     if (protocols == NULL)
2335         goto error;
2336     for (i = 0; vi->protocols[i] != NULL; i++) {
2337         tmp = vi_str(vi->protocols[i]);
2338         if (tmp == NULL)
2339             goto error;
2340         PyTuple_SET_ITEM(protocols, i, tmp);
2341     }
2342     ret = PyTuple_New(12);
2343     if (ret == NULL)
2344         goto error;
2345
2346 #define SET(i, v) \
2347         tmp = (v); if (tmp == NULL) goto error; PyTuple_SET_ITEM(ret, i, tmp)
2348     SET(0, PyInt_FromLong((long) vi->age));
2349     SET(1, vi_str(vi->version));
2350     SET(2, PyInt_FromLong(vi->version_num));
2351     SET(3, vi_str(vi->host));
2352     SET(4, PyInt_FromLong(vi->features));
2353     SET(5, vi_str(vi->ssl_version));
2354     SET(6, PyInt_FromLong(vi->ssl_version_num));
2355     SET(7, vi_str(vi->libz_version));
2356     SET(8, protocols);
2357     SET(9, vi_str(vi->ares));
2358     SET(10, PyInt_FromLong(vi->ares_num));
2359     SET(11, vi_str(vi->libidn));
2360 #undef SET
2361     return ret;
2362
2363 error:
2364     Py_XDECREF(ret);
2365     Py_XDECREF(protocols);
2366     return NULL;
2367 }
2368
2369
2370 /* Per function docstrings */
2371 static char pycurl_global_init_doc [] =
2372 "global_init(option) -> None.  Initialize curl environment.\n";
2373
2374 static char pycurl_global_cleanup_doc [] =
2375 "global_cleanup() -> None.  Cleanup curl environment.\n";
2376
2377 static char pycurl_version_info_doc [] =
2378 "version_info() -> tuple.  Returns a 12-tuple with the version info.\n";
2379
2380 static char pycurl_curl_new_doc [] =
2381 "Curl() -> New curl object.  Implicitly calls global_init() if not called.\n";
2382
2383 static char pycurl_multi_new_doc [] =
2384 "CurlMulti() -> New curl multi-object.\n";
2385
2386
2387 /* List of functions defined in this module */
2388 static PyMethodDef curl_methods[] = {
2389     {"global_init", (PyCFunction)do_global_init, METH_VARARGS, pycurl_global_init_doc},
2390     {"global_cleanup", (PyCFunction)do_global_cleanup, METH_NOARGS, pycurl_global_cleanup_doc},
2391     {"version_info", (PyCFunction)do_version_info, METH_VARARGS, pycurl_version_info_doc},
2392     {"Curl", (PyCFunction)do_curl_new, METH_NOARGS, pycurl_curl_new_doc},
2393     {"CurlMulti", (PyCFunction)do_multi_new, METH_NOARGS, pycurl_multi_new_doc},
2394     {NULL, NULL, 0, NULL}
2395 };
2396
2397
2398 /* Module docstring */
2399 static char module_doc [] =
2400 "This module implements an interface to the cURL library.\n"
2401 "\n"
2402 "Types:\n"
2403 "\n"
2404 "Curl() -> New object.  Create a new curl object.\n"
2405 "CurlMulti() -> New object.  Create a new curl multi-object.\n"
2406 "\n"
2407 "Functions:\n"
2408 "\n"
2409 "global_init(option) -> None.  Initialize curl environment.\n"
2410 "global_cleanup() -> None.  Cleanup curl environment.\n"
2411 "version_info() -> tuple.  Return version information.\n"
2412 ;
2413
2414
2415 /* Helper functions for inserting constants into the module namespace */
2416
2417 static void
2418 insobj2(PyObject *dict1, PyObject *dict2, char *name, PyObject *value)
2419 {
2420     /* Insert an object into one or two dicts. Eats a reference to value.
2421      * See also the implementation of PyDict_SetItemString(). */
2422     PyObject *key = NULL;
2423
2424     if (dict1 == NULL && dict2 == NULL)
2425         goto error;
2426     if (value == NULL)
2427         goto error;
2428     key = PyString_FromString(name);
2429     if (key == NULL)
2430         goto error;
2431 #if 0
2432     PyString_InternInPlace(&key);   /* XXX Should we really? */
2433 #endif
2434     if (dict1 != NULL) {
2435         assert(PyDict_GetItem(dict1, key) == NULL);
2436         if (PyDict_SetItem(dict1, key, value) != 0)
2437             goto error;
2438     }
2439     if (dict2 != NULL && dict2 != dict1) {
2440         assert(PyDict_GetItem(dict2, key) == NULL);
2441         if (PyDict_SetItem(dict2, key, value) != 0)
2442             goto error;
2443     }
2444     Py_DECREF(key);
2445     Py_DECREF(value);
2446     return;
2447 error:
2448     Py_FatalError("pycurl: FATAL: insobj2() failed");
2449     assert(0);
2450 }
2451
2452 static void
2453 insstr(PyObject *d, char *name, char *value)
2454 {
2455     PyObject *v = PyString_FromString(value);
2456     insobj2(d, NULL, name, v);
2457 }
2458
2459 static void
2460 insint(PyObject *d, char *name, long value)
2461 {
2462     PyObject *v = PyInt_FromLong(value);
2463     insobj2(d, NULL, name, v);
2464 }
2465
2466 static void
2467 insint_c(PyObject *d, char *name, long value)
2468 {
2469     PyObject *v = PyInt_FromLong(value);
2470     insobj2(d, curlobject_constants, name, v);
2471 }
2472
2473 static void
2474 insint_m(PyObject *d, char *name, long value)
2475 {
2476     PyObject *v = PyInt_FromLong(value);
2477     insobj2(d, curlmultiobject_constants, name, v);
2478 }
2479
2480
2481 /* Initialization function for the module */
2482 #if defined(PyMODINIT_FUNC)
2483 PyMODINIT_FUNC
2484 #else
2485 #if defined(__cplusplus)
2486 extern "C"
2487 #endif
2488 DL_EXPORT(void)
2489 #endif
2490 initpycurl(void)
2491 {
2492     PyObject *m, *d;
2493     const curl_version_info_data *vi;
2494
2495     /* Initialize the type of the new type objects here; doing it here
2496      * is required for portability to Windows without requiring C++. */
2497     p_Curl_Type = &Curl_Type;
2498     p_CurlMulti_Type = &CurlMulti_Type;
2499     Curl_Type.ob_type = &PyType_Type;
2500     CurlMulti_Type.ob_type = &PyType_Type;
2501
2502     /* Create the module and add the functions */
2503     m = Py_InitModule3("pycurl", curl_methods, module_doc);
2504     assert(m != NULL && PyModule_Check(m));
2505
2506     /* Add error object to the module */
2507     d = PyModule_GetDict(m);
2508     assert(d != NULL);
2509     ErrorObject = PyErr_NewException("pycurl.error", NULL, NULL);
2510     assert(ErrorObject != NULL);
2511     PyDict_SetItemString(d, "error", ErrorObject);
2512
2513     curlobject_constants = PyDict_New();
2514     assert(curlobject_constants != NULL);
2515
2516     /* Add version strings to the module */
2517     insstr(d, "version", curl_version());
2518     insstr(d, "COMPILE_DATE", __DATE__ " " __TIME__);
2519     insint(d, "COMPILE_PY_VERSION_HEX", PY_VERSION_HEX);
2520     insint(d, "COMPILE_LIBCURL_VERSION_NUM", LIBCURL_VERSION_NUM);
2521
2522     /**
2523      ** the order of these constants mostly follows <curl/curl.h>
2524      **/
2525
2526     /* Abort curl_read_callback(). */
2527     insint_c(d, "READFUNC_ABORT", CURL_READFUNC_ABORT);
2528
2529     /* constants for ioctl callback return values */
2530     insint_c(d, "IOE_OK", CURLIOE_OK);
2531     insint_c(d, "IOE_UNKNOWNCMD", CURLIOE_UNKNOWNCMD);
2532     insint_c(d, "IOE_FAILRESTART", CURLIOE_FAILRESTART);
2533
2534     /* curl_infotype: the kind of data that is passed to information_callback */
2535 /* XXX do we actually need curl_infotype in pycurl ??? */
2536     insint_c(d, "INFOTYPE_TEXT", CURLINFO_TEXT);
2537     insint_c(d, "INFOTYPE_HEADER_IN", CURLINFO_HEADER_IN);
2538     insint_c(d, "INFOTYPE_HEADER_OUT", CURLINFO_HEADER_OUT);
2539     insint_c(d, "INFOTYPE_DATA_IN", CURLINFO_DATA_IN);
2540     insint_c(d, "INFOTYPE_DATA_OUT", CURLINFO_DATA_OUT);
2541     insint_c(d, "INFOTYPE_SSL_DATA_IN", CURLINFO_SSL_DATA_IN);
2542     insint_c(d, "INFOTYPE_SSL_DATA_OUT", CURLINFO_SSL_DATA_OUT);
2543
2544     /* CURLcode: error codes */
2545 /* FIXME: lots of error codes are missing */
2546     insint_c(d, "E_OK", CURLE_OK);
2547     insint_c(d, "E_UNSUPPORTED_PROTOCOL", CURLE_UNSUPPORTED_PROTOCOL);
2548
2549     /* curl_proxytype: constants for setopt(PROXYTYPE, x) */
2550     insint_c(d, "PROXYTYPE_HTTP", CURLPROXY_HTTP);
2551     insint_c(d, "PROXYTYPE_SOCKS4", CURLPROXY_SOCKS4);
2552     insint_c(d, "PROXYTYPE_SOCKS5", CURLPROXY_SOCKS5);
2553
2554     /* curl_httpauth: constants for setopt(HTTPAUTH, x) */
2555     insint_c(d, "HTTPAUTH_NONE", CURLAUTH_NONE);
2556     insint_c(d, "HTTPAUTH_BASIC", CURLAUTH_BASIC);
2557     insint_c(d, "HTTPAUTH_DIGEST", CURLAUTH_DIGEST);
2558     insint_c(d, "HTTPAUTH_GSSNEGOTIATE", CURLAUTH_GSSNEGOTIATE);
2559     insint_c(d, "HTTPAUTH_NTLM", CURLAUTH_NTLM);
2560     insint_c(d, "HTTPAUTH_ANY", CURLAUTH_ANY);
2561     insint_c(d, "HTTPAUTH_ANYSAFE", CURLAUTH_ANYSAFE);
2562
2563     /* curl_ftpssl: constants for setopt(FTP_SSL, x) */
2564     insint_c(d, "FTPSSL_NONE", CURLFTPSSL_NONE);
2565     insint_c(d, "FTPSSL_TRY", CURLFTPSSL_TRY);
2566     insint_c(d, "FTPSSL_CONTROL", CURLFTPSSL_CONTROL);
2567     insint_c(d, "FTPSSL_ALL", CURLFTPSSL_ALL);
2568
2569     /* curl_ftpauth: constants for setopt(FTPSSLAUTH, x) */
2570     insint_c(d, "FTPAUTH_DEFAULT", CURLFTPAUTH_DEFAULT);
2571     insint_c(d, "FTPAUTH_SSL", CURLFTPAUTH_SSL);
2572     insint_c(d, "FTPAUTH_TLS", CURLFTPAUTH_TLS);
2573
2574     /* curl_ftpauth: constants for setopt(FTPSSLAUTH, x) */
2575     insint_c(d, "FORM_CONTENTS", CURLFORM_COPYCONTENTS);
2576     insint_c(d, "FORM_FILE", CURLFORM_FILE);
2577     insint_c(d, "FORM_CONTENTTYPE", CURLFORM_CONTENTTYPE);
2578
2579     /* CURLoption: symbolic constants for setopt() */
2580 /* FIXME: reorder these to match <curl/curl.h> */
2581     insint_c(d, "FILE", CURLOPT_WRITEDATA);
2582     insint_c(d, "URL", CURLOPT_URL);
2583     insint_c(d, "PORT", CURLOPT_PORT);
2584     insint_c(d, "PROXY", CURLOPT_PROXY);
2585     insint_c(d, "USERPWD", CURLOPT_USERPWD);
2586     insint_c(d, "PROXYUSERPWD", CURLOPT_PROXYUSERPWD);
2587     insint_c(d, "RANGE", CURLOPT_RANGE);
2588     insint_c(d, "INFILE", CURLOPT_READDATA);
2589     /* ERRORBUFFER is not supported */
2590     insint_c(d, "WRITEFUNCTION", CURLOPT_WRITEFUNCTION);
2591     insint_c(d, "READFUNCTION", CURLOPT_READFUNCTION);
2592     insint_c(d, "TIMEOUT", CURLOPT_TIMEOUT);
2593     insint_c(d, "INFILESIZE", CURLOPT_INFILESIZE_LARGE);    /* _LARGE ! */
2594     insint_c(d, "POSTFIELDS", CURLOPT_POSTFIELDS);
2595     insint_c(d, "REFERER", CURLOPT_REFERER);
2596     insint_c(d, "FTPPORT", CURLOPT_FTPPORT);
2597     insint_c(d, "USERAGENT", CURLOPT_USERAGENT);
2598     insint_c(d, "LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT);
2599     insint_c(d, "LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME);
2600     insint_c(d, "RESUME_FROM", CURLOPT_RESUME_FROM_LARGE);  /* _LARGE ! */
2601     insint_c(d, "WRITEDATA", CURLOPT_WRITEDATA);
2602     insint_c(d, "READDATA", CURLOPT_READDATA);
2603     insint_c(d, "PROXYPORT", CURLOPT_PROXYPORT);
2604     insint_c(d, "HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL);
2605     insint_c(d, "VERBOSE", CURLOPT_VERBOSE);
2606     insint_c(d, "HEADER", CURLOPT_HEADER);
2607     insint_c(d, "NOPROGRESS", CURLOPT_NOPROGRESS);
2608     insint_c(d, "NOBODY", CURLOPT_NOBODY);
2609     insint_c(d, "FAILONERROR", CURLOPT_FAILONERROR);
2610     insint_c(d, "UPLOAD", CURLOPT_UPLOAD);
2611     insint_c(d, "POST", CURLOPT_POST);
2612     insint_c(d, "FTPLISTONLY", CURLOPT_FTPLISTONLY);
2613     insint_c(d, "FTPAPPEND", CURLOPT_FTPAPPEND);
2614     insint_c(d, "NETRC", CURLOPT_NETRC);
2615     insint_c(d, "FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION);
2616     insint_c(d, "TRANSFERTEXT", CURLOPT_TRANSFERTEXT);
2617     insint_c(d, "PUT", CURLOPT_PUT);
2618     insint_c(d, "POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE_LARGE);  /* _LARGE ! */
2619     insint_c(d, "COOKIE", CURLOPT_COOKIE);
2620     insint_c(d, "HTTPHEADER", CURLOPT_HTTPHEADER);
2621     insint_c(d, "HTTPPOST", CURLOPT_HTTPPOST);
2622     insint_c(d, "SSLCERT", CURLOPT_SSLCERT);
2623     insint_c(d, "SSLCERTPASSWD", CURLOPT_SSLCERTPASSWD);
2624     insint_c(d, "CRLF", CURLOPT_CRLF);
2625     insint_c(d, "QUOTE", CURLOPT_QUOTE);
2626     insint_c(d, "POSTQUOTE", CURLOPT_POSTQUOTE);
2627     insint_c(d, "PREQUOTE", CURLOPT_PREQUOTE);
2628     insint_c(d, "WRITEHEADER", CURLOPT_WRITEHEADER);
2629     insint_c(d, "HEADERFUNCTION", CURLOPT_HEADERFUNCTION);
2630     insint_c(d, "COOKIEFILE", CURLOPT_COOKIEFILE);
2631     insint_c(d, "SSLVERSION", CURLOPT_SSLVERSION);
2632     insint_c(d, "TIMECONDITION", CURLOPT_TIMECONDITION);
2633     insint_c(d, "TIMEVALUE", CURLOPT_TIMEVALUE);
2634     insint_c(d, "CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST);
2635     insint_c(d, "STDERR", CURLOPT_STDERR);
2636     insint_c(d, "INTERFACE", CURLOPT_INTERFACE);
2637     insint_c(d, "KRB4LEVEL", CURLOPT_KRB4LEVEL);
2638     insint_c(d, "PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION);
2639     insint_c(d, "SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER);
2640     insint_c(d, "CAPATH", CURLOPT_CAPATH);
2641     insint_c(d, "CAINFO", CURLOPT_CAINFO);
2642     insint_c(d, "OPT_FILETIME", CURLOPT_FILETIME);
2643     insint_c(d, "MAXREDIRS", CURLOPT_MAXREDIRS);
2644     insint_c(d, "MAXCONNECTS", CURLOPT_MAXCONNECTS);
2645     insint_c(d, "CLOSEPOLICY", CURLOPT_CLOSEPOLICY);
2646     insint_c(d, "FRESH_CONNECT", CURLOPT_FRESH_CONNECT);
2647     insint_c(d, "FORBID_REUSE", CURLOPT_FORBID_REUSE);
2648     insint_c(d, "RANDOM_FILE", CURLOPT_RANDOM_FILE);
2649     insint_c(d, "EGDSOCKET", CURLOPT_EGDSOCKET);
2650     insint_c(d, "CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT);
2651     insint_c(d, "HTTPGET", CURLOPT_HTTPGET);
2652     insint_c(d, "SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST);
2653     insint_c(d, "COOKIEJAR", CURLOPT_COOKIEJAR);
2654     insint_c(d, "SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST);
2655     insint_c(d, "HTTP_VERSION", CURLOPT_HTTP_VERSION);
2656     insint_c(d, "FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV);
2657     insint_c(d, "SSLCERTTYPE", CURLOPT_SSLCERTTYPE);
2658     insint_c(d, "SSLKEY", CURLOPT_SSLKEY);
2659     insint_c(d, "SSLKEYTYPE", CURLOPT_SSLKEYTYPE);
2660     insint_c(d, "SSLKEYPASSWD", CURLOPT_SSLKEYPASSWD);
2661     insint_c(d, "SSLENGINE", CURLOPT_SSLENGINE);
2662     insint_c(d, "SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT);
2663     insint_c(d, "DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT);
2664     insint_c(d, "DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE);
2665     insint_c(d, "DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION);
2666     insint_c(d, "BUFFERSIZE", CURLOPT_BUFFERSIZE);
2667     insint_c(d, "NOSIGNAL", CURLOPT_NOSIGNAL);
2668     insint_c(d, "SHARE", CURLOPT_SHARE);
2669     insint_c(d, "PROXYTYPE", CURLOPT_PROXYTYPE);
2670     insint_c(d, "ENCODING", CURLOPT_ENCODING);
2671     insint_c(d, "HTTP200ALIASES", CURLOPT_HTTP200ALIASES);
2672     insint_c(d, "UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH);
2673     insint_c(d, "FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT);
2674     insint_c(d, "HTTPAUTH", CURLOPT_HTTPAUTH);
2675     insint_c(d, "FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS);
2676     insint_c(d, "PROXYAUTH", CURLOPT_PROXYAUTH);
2677     insint_c(d, "FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT);
2678     insint_c(d, "IPRESOLVE", CURLOPT_IPRESOLVE);
2679     insint_c(d, "MAXFILESIZE", CURLOPT_MAXFILESIZE_LARGE);  /* _LARGE ! */
2680     insint_c(d, "INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE);
2681     insint_c(d, "RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE);
2682     insint_c(d, "MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE);
2683     insint_c(d, "NETRC_FILE", CURLOPT_NETRC_FILE);
2684     insint_c(d, "FTP_SSL", CURLOPT_FTP_SSL);
2685     insint_c(d, "POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE);
2686     insint_c(d, "TCP_NODELAY", CURLOPT_TCP_NODELAY);
2687     insint_c(d, "SOURCE_USERPWD", CURLOPT_SOURCE_USERPWD);
2688     insint_c(d, "SOURCE_PREQUOTE", CURLOPT_SOURCE_PREQUOTE);
2689     insint_c(d, "SOURCE_POSTQUOTE", CURLOPT_SOURCE_POSTQUOTE);
2690     insint_c(d, "FTPSSLAUTH", CURLOPT_FTPSSLAUTH);
2691     insint_c(d, "IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION);
2692     insint_c(d, "IOCTLDATA", CURLOPT_IOCTLDATA);
2693     insint_c(d, "SOURCE_URL", CURLOPT_SOURCE_URL);
2694     insint_c(d, "SOURCE_QUOTE", CURLOPT_SOURCE_QUOTE);
2695     insint_c(d, "FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT);
2696
2697     /* constants for setopt(IPRESOLVE, x) */
2698     insint_c(d, "IPRESOLVE_WHATEVER", CURL_IPRESOLVE_WHATEVER);
2699     insint_c(d, "IPRESOLVE_V4", CURL_IPRESOLVE_V4);
2700     insint_c(d, "IPRESOLVE_V6", CURL_IPRESOLVE_V6);
2701
2702     /* constants for setopt(HTTP_VERSION, x) */
2703     insint_c(d, "CURL_HTTP_VERSION_NONE", CURL_HTTP_VERSION_NONE);
2704     insint_c(d, "CURL_HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0);
2705     insint_c(d, "CURL_HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1);
2706     insint_c(d, "CURL_HTTP_VERSION_LAST", CURL_HTTP_VERSION_LAST);
2707
2708     /* CURL_NETRC_OPTION: constants for setopt(NETRC, x) */
2709     insint_c(d, "NETRC_OPTIONAL", CURL_NETRC_OPTIONAL);
2710     insint_c(d, "NETRC_IGNORED", CURL_NETRC_IGNORED);
2711     insint_c(d, "NETRC_REQUIRED", CURL_NETRC_REQUIRED);
2712
2713     /* constants for setopt(SSLVERSION, x) */
2714     insint_c(d, "SSLVERSION_DEFAULT", CURL_SSLVERSION_DEFAULT);
2715     insint_c(d, "SSLVERSION_TLSv1", CURL_SSLVERSION_TLSv1);
2716     insint_c(d, "SSLVERSION_SSLv2", CURL_SSLVERSION_SSLv2);
2717     insint_c(d, "SSLVERSION_SSLv3", CURL_SSLVERSION_SSLv3);
2718
2719     /* curl_TimeCond: constants for setopt(TIMECONDITION, x) */
2720     insint_c(d, "TIMECONDITION_NONE", CURL_TIMECOND_NONE);
2721     insint_c(d, "TIMECONDITION_IFMODSINCE", CURL_TIMECOND_IFMODSINCE);
2722     insint_c(d, "TIMECONDITION_IFUNMODSINCE", CURL_TIMECOND_IFUNMODSINCE);
2723     insint_c(d, "TIMECONDITION_LASTMOD", CURL_TIMECOND_LASTMOD);
2724
2725     /* CURLINFO: symbolic constants for getinfo(x) */
2726     insint_c(d, "EFFECTIVE_URL", CURLINFO_EFFECTIVE_URL);
2727     insint_c(d, "HTTP_CODE", CURLINFO_HTTP_CODE);
2728     insint_c(d, "RESPONSE_CODE", CURLINFO_HTTP_CODE);
2729     insint_c(d, "TOTAL_TIME", CURLINFO_TOTAL_TIME);
2730     insint_c(d, "NAMELOOKUP_TIME", CURLINFO_NAMELOOKUP_TIME);
2731     insint_c(d, "CONNECT_TIME", CURLINFO_CONNECT_TIME);
2732     insint_c(d, "PRETRANSFER_TIME", CURLINFO_PRETRANSFER_TIME);
2733     insint_c(d, "SIZE_UPLOAD", CURLINFO_SIZE_UPLOAD);
2734     insint_c(d, "SIZE_DOWNLOAD", CURLINFO_SIZE_DOWNLOAD);
2735     insint_c(d, "SPEED_DOWNLOAD", CURLINFO_SPEED_DOWNLOAD);
2736     insint_c(d, "SPEED_UPLOAD", CURLINFO_SPEED_UPLOAD);
2737     insint_c(d, "HEADER_SIZE", CURLINFO_HEADER_SIZE);
2738     insint_c(d, "REQUEST_SIZE", CURLINFO_REQUEST_SIZE);
2739     insint_c(d, "SSL_VERIFYRESULT", CURLINFO_SSL_VERIFYRESULT);
2740     insint_c(d, "INFO_FILETIME", CURLINFO_FILETIME);
2741     insint_c(d, "CONTENT_LENGTH_DOWNLOAD", CURLINFO_CONTENT_LENGTH_DOWNLOAD);
2742     insint_c(d, "CONTENT_LENGTH_UPLOAD", CURLINFO_CONTENT_LENGTH_UPLOAD);
2743     insint_c(d, "STARTTRANSFER_TIME", CURLINFO_STARTTRANSFER_TIME);
2744     insint_c(d, "CONTENT_TYPE", CURLINFO_CONTENT_TYPE);
2745     insint_c(d, "REDIRECT_TIME", CURLINFO_REDIRECT_TIME);
2746     insint_c(d, "REDIRECT_COUNT", CURLINFO_REDIRECT_COUNT);
2747     insint_c(d, "HTTP_CONNECTCODE", CURLINFO_HTTP_CONNECTCODE);
2748     insint_c(d, "HTTPAUTH_AVAIL", CURLINFO_HTTPAUTH_AVAIL);
2749     insint_c(d, "PROXYAUTH_AVAIL", CURLINFO_PROXYAUTH_AVAIL);
2750     insint_c(d, "OS_ERRNO", CURLINFO_OS_ERRNO);
2751     insint_c(d, "NUM_CONNECTS", CURLINFO_NUM_CONNECTS);
2752     insint_c(d, "SSL_ENGINES", CURLINFO_SSL_ENGINES);
2753
2754     /* curl_closepolicy: constants for setopt(CLOSEPOLICY, x) */
2755     insint_c(d, "CLOSEPOLICY_OLDEST", CURLCLOSEPOLICY_OLDEST);
2756     insint_c(d, "CLOSEPOLICY_LEAST_RECENTLY_USED", CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
2757     insint_c(d, "CLOSEPOLICY_LEAST_TRAFFIC", CURLCLOSEPOLICY_LEAST_TRAFFIC);
2758     insint_c(d, "CLOSEPOLICY_SLOWEST", CURLCLOSEPOLICY_SLOWEST);
2759     insint_c(d, "CLOSEPOLICY_CALLBACK", CURLCLOSEPOLICY_CALLBACK);
2760
2761     /* options for global_init() */
2762     insint(d, "GLOBAL_SSL", CURL_GLOBAL_SSL);
2763     insint(d, "GLOBAL_WIN32", CURL_GLOBAL_WIN32);
2764     insint(d, "GLOBAL_ALL", CURL_GLOBAL_ALL);
2765     insint(d, "GLOBAL_NOTHING", CURL_GLOBAL_NOTHING);
2766     insint(d, "GLOBAL_DEFAULT", CURL_GLOBAL_DEFAULT);
2767
2768     /* curl_lock_data: XXX do we need this in pycurl ??? */
2769     /* curl_lock_access: XXX do we need this in pycurl ??? */
2770     /* CURLSHcode: XXX do we need this in pycurl ??? */
2771     /* CURLSHoption: XXX do we need this in pycurl ??? */
2772
2773     /* CURLversion: constants for curl_version_info(x) */
2774 #if 0
2775     /* XXX - do we need these ?? */
2776     insint(d, "VERSION_FIRST", CURLVERSION_FIRST);
2777     insint(d, "VERSION_SECOND", CURLVERSION_SECOND);
2778     insint(d, "VERSION_THIRD", CURLVERSION_THIRD);
2779     insint(d, "VERSION_NOW", CURLVERSION_NOW);
2780 #endif
2781
2782     /* version features - bitmasks for curl_version_info_data.features */
2783 #if 0
2784     /* XXX - do we need these ?? */
2785     /* XXX - should we really rename these ?? */
2786     insint(d, "VERSION_FEATURE_IPV6", CURL_VERSION_IPV6);
2787     insint(d, "VERSION_FEATURE_KERBEROS4", CURL_VERSION_KERBEROS4);
2788     insint(d, "VERSION_FEATURE_SSL", CURL_VERSION_SSL);
2789     insint(d, "VERSION_FEATURE_LIBZ", CURL_VERSION_LIBZ);
2790     insint(d, "VERSION_FEATURE_NTLM", CURL_VERSION_NTLM);
2791     insint(d, "VERSION_FEATURE_GSSNEGOTIATE", CURL_VERSION_GSSNEGOTIATE);
2792     insint(d, "VERSION_FEATURE_DEBUG", CURL_VERSION_DEBUG);
2793     insint(d, "VERSION_FEATURE_ASYNCHDNS", CURL_VERSION_ASYNCHDNS);
2794     insint(d, "VERSION_FEATURE_SPNEGO", CURL_VERSION_SPNEGO);
2795     insint(d, "VERSION_FEATURE_LARGEFILE", CURL_VERSION_LARGEFILE);
2796     insint(d, "VERSION_FEATURE_IDN", CURL_VERSION_IDN);
2797 #endif
2798
2799     /**
2800      ** the order of these constants mostly follows <curl/multi.h>
2801      **/
2802
2803     /* CURLMcode: multi error codes */
2804     insint_m(d, "E_CALL_MULTI_PERFORM", CURLM_CALL_MULTI_PERFORM);
2805     insint_m(d, "E_MULTI_OK", CURLM_OK);
2806     insint_m(d, "E_MULTI_BAD_HANDLE", CURLM_BAD_HANDLE);
2807     insint_m(d, "E_MULTI_BAD_EASY_HANDLE", CURLM_BAD_EASY_HANDLE);
2808     insint_m(d, "E_MULTI_OUT_OF_MEMORY", CURLM_OUT_OF_MEMORY);
2809     insint_m(d, "E_MULTI_INTERNAL_ERROR", CURLM_INTERNAL_ERROR);
2810
2811     /* Check the version, as this has caused nasty problems in
2812      * some cases. */
2813     vi = curl_version_info(CURLVERSION_NOW);
2814     if (vi == NULL) {
2815         Py_FatalError("pycurl: FATAL: curl_version_info() failed");
2816         assert(0);
2817     }
2818     if (vi->version_num < LIBCURL_VERSION_NUM) {
2819         Py_FatalError("pycurl: FATAL: libcurl link-time version is older than compile-time version");
2820         assert(0);
2821     }
2822
2823     /* Finally initialize global interpreter lock */
2824     PyEval_InitThreads();
2825 }
2826
2827 /* vi:ts=4:et:nowrap
2828  */