]> granicus.if.org Git - php/blob
fdf855278eef6f32f26c49b54f56aca9bd7007c3
[php] /
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Sterling Hughes <sterling@php.net>                           |
16    +----------------------------------------------------------------------+
17 */
18
19 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26
27 #if HAVE_CURL
28
29 #include <stdio.h>
30 #include <string.h>
31
32 #ifdef PHP_WIN32
33 #include <winsock2.h>
34 #include <sys/types.h>
35 #endif
36
37 #include <curl/curl.h>
38 #include <curl/easy.h>
39
40 /* As of curl 7.11.1 this is no longer defined inside curl.h */
41 #ifndef HttpPost
42 #define HttpPost curl_httppost
43 #endif
44
45 /* {{{ cruft for thread safe SSL crypto locks */
46 #if defined(ZTS) && defined(HAVE_CURL_SSL)
47 # ifdef PHP_WIN32
48 #  define PHP_CURL_NEED_OPENSSL_TSL
49 #  include <openssl/crypto.h>
50 # else /* !PHP_WIN32 */
51 #  if defined(HAVE_CURL_OPENSSL)
52 #   if defined(HAVE_OPENSSL_CRYPTO_H)
53 #    define PHP_CURL_NEED_OPENSSL_TSL
54 #    include <openssl/crypto.h>
55 #   else
56 #    warning \
57         "libcurl was compiled with OpenSSL support, but configure could not find " \
58         "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
59         "cause random crashes on SSL requests"
60 #   endif
61 #  elif defined(HAVE_CURL_GNUTLS)
62     /* Modern versions of GnuTLS use the nette backend rather than gcrypt, so there
63          * is nothing to do here anymore. */
64 #  else
65 #   warning \
66         "libcurl was compiled with SSL support, but configure could not determine which" \
67         "library was used; thus no SSL crypto locking callbacks will be set, which may " \
68         "cause random crashes on SSL requests"
69 #  endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
70 # endif /* PHP_WIN32 */
71 #endif /* ZTS && HAVE_CURL_SSL */
72 /* }}} */
73
74 #define SMART_STR_PREALLOC 4096
75
76 #include "zend_smart_str.h"
77 #include "ext/standard/info.h"
78 #include "ext/standard/file.h"
79 #include "ext/standard/url.h"
80 #include "php_curl.h"
81
82 int  le_curl;
83 int  le_curl_multi_handle;
84 int  le_curl_share_handle;
85
86 #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
87 static MUTEX_T *php_curl_openssl_tsl = NULL;
88
89 /* Locking callbacks are no longer used since OpenSSL 1.1. Mark the functions as unused to
90  * avoid warnings due to this. */
91 static ZEND_ATTRIBUTE_UNUSED void php_curl_ssl_lock(int mode, int n, const char * file, int line)
92 {
93         if (mode & CRYPTO_LOCK) {
94                 tsrm_mutex_lock(php_curl_openssl_tsl[n]);
95         } else {
96                 tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
97         }
98 }
99
100 static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void)
101 {
102         return (unsigned long) tsrm_thread_id();
103 }
104 #endif
105 /* }}} */
106
107 static void _php_curl_close_ex(php_curl *ch);
108 static void _php_curl_close(zend_resource *rsrc);
109
110
111 #define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
112
113 #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v);
114 #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v);
115 #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : ""));
116 #define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, \
117                 v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC());
118 #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) -1 , (zval *) v);
119
120 #if defined(PHP_WIN32) || defined(__GNUC__)
121 # define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
122 #else
123 # define php_curl_ret(__ret) RETVAL_FALSE; return;
124 #endif
125
126 static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy)
127 {
128         CURLcode error = CURLE_OK;
129
130         if (strlen(str) != len) {
131                 php_error_docref(NULL, E_WARNING, "Curl option contains invalid characters (\\0)");
132                 return FAILURE;
133         }
134
135 #if LIBCURL_VERSION_NUM >= 0x071100
136         if (make_copy) {
137 #endif
138                 char *copystr;
139
140                 /* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */
141                 copystr = estrndup(str, len);
142                 error = curl_easy_setopt(ch->cp, option, copystr);
143                 zend_llist_add_element(&ch->to_free->str, &copystr);
144 #if LIBCURL_VERSION_NUM >= 0x071100
145         } else {
146                 error = curl_easy_setopt(ch->cp, option, str);
147         }
148 #endif
149
150         SAVE_CURL_ERROR(ch, error)
151
152         return error == CURLE_OK ? SUCCESS : FAILURE;
153 }
154
155 static int php_curl_option_url(php_curl *ch, const char *url, const size_t len) /* {{{ */
156 {
157         /* Disable file:// if open_basedir are used */
158         if (PG(open_basedir) && *PG(open_basedir)) {
159 #if LIBCURL_VERSION_NUM >= 0x071304
160                 curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
161 #else
162                 php_url *uri;
163
164                 if (!(uri = php_url_parse_ex(url, len))) {
165                         php_error_docref(NULL, E_WARNING, "Invalid URL '%s'", url);
166                         return FAILURE;
167                 }
168
169                 if (uri->scheme && zend_string_equals_literal_ci(uri->scheme, "file")) {
170                         php_error_docref(NULL, E_WARNING, "Protocol 'file' disabled in cURL");
171                         php_url_free(uri);
172                         return FAILURE;
173                 }
174                 php_url_free(uri);
175 #endif
176         }
177
178 #if LIBCURL_VERSION_NUM > 0x073800 && defined(PHP_WIN32)
179         if (len > sizeof("file://") - 1 && '/' != url[sizeof("file://") - 1] && !strncmp("file://", url, sizeof("file://") - 1) && len < MAXPATHLEN - 2) {
180                 char _tmp[MAXPATHLEN] = {0};
181
182                 memmove(_tmp, "file:///", sizeof("file:///") - 1);
183                 memmove(_tmp + sizeof("file:///") - 1, url + sizeof("file://") - 1, len - sizeof("file://") + 1);
184
185                 return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1, 0);
186         }
187 #endif
188
189         return php_curl_option_str(ch, CURLOPT_URL, url, len, 0);
190 }
191 /* }}} */
192
193 void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */
194 {
195         php_stream *stream;
196
197         ZEND_ASSERT(ch && ch->handlers);
198
199         if (!Z_ISUNDEF(ch->handlers->std_err)) {
200                 stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream());
201                 if (stream == NULL) {
202                         if (reporterror) {
203                                 php_error_docref(NULL, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr");
204                         }
205                         zval_ptr_dtor(&ch->handlers->std_err);
206                         ZVAL_UNDEF(&ch->handlers->std_err);
207
208                         curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
209                 }
210         }
211         if (ch->handlers->read && !Z_ISUNDEF(ch->handlers->read->stream)) {
212                 stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->read->stream, NULL, php_file_le_stream(), php_file_le_pstream());
213                 if (stream == NULL) {
214                         if (reporterror) {
215                                 php_error_docref(NULL, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default");
216                         }
217                         zval_ptr_dtor(&ch->handlers->read->stream);
218                         ZVAL_UNDEF(&ch->handlers->read->stream);
219                         ch->handlers->read->res = NULL;
220                         ch->handlers->read->fp = 0;
221
222                         curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
223                 }
224         }
225         if (ch->handlers->write_header && !Z_ISUNDEF(ch->handlers->write_header->stream)) {
226                 stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write_header->stream, NULL, php_file_le_stream(), php_file_le_pstream());
227                 if (stream == NULL) {
228                         if (reporterror) {
229                                 php_error_docref(NULL, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default");
230                         }
231                         zval_ptr_dtor(&ch->handlers->write_header->stream);
232                         ZVAL_UNDEF(&ch->handlers->write_header->stream);
233                         ch->handlers->write_header->fp = 0;
234
235                         ch->handlers->write_header->method = PHP_CURL_IGNORE;
236                         curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
237                 }
238         }
239         if (ch->handlers->write && !Z_ISUNDEF(ch->handlers->write->stream)) {
240                 stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write->stream, NULL, php_file_le_stream(), php_file_le_pstream());
241                 if (stream == NULL) {
242                         if (reporterror) {
243                                 php_error_docref(NULL, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default");
244                         }
245                         zval_ptr_dtor(&ch->handlers->write->stream);
246                         ZVAL_UNDEF(&ch->handlers->write->stream);
247                         ch->handlers->write->fp = 0;
248
249                         ch->handlers->write->method = PHP_CURL_STDOUT;
250                         curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
251                 }
252         }
253         return;
254 }
255 /* }}} */
256
257 /* {{{ arginfo */
258 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
259         ZEND_ARG_INFO(0, version)
260 ZEND_END_ARG_INFO()
261
262 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
263         ZEND_ARG_INFO(0, url)
264 ZEND_END_ARG_INFO()
265
266 ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
267         ZEND_ARG_INFO(0, ch)
268 ZEND_END_ARG_INFO()
269
270 ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
271         ZEND_ARG_INFO(0, ch)
272         ZEND_ARG_INFO(0, option)
273         ZEND_ARG_INFO(0, value)
274 ZEND_END_ARG_INFO()
275
276 ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
277         ZEND_ARG_INFO(0, ch)
278         ZEND_ARG_ARRAY_INFO(0, options, 0)
279 ZEND_END_ARG_INFO()
280
281 ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
282         ZEND_ARG_INFO(0, ch)
283 ZEND_END_ARG_INFO()
284
285 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
286         ZEND_ARG_INFO(0, ch)
287         ZEND_ARG_INFO(0, option)
288 ZEND_END_ARG_INFO()
289
290 ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
291         ZEND_ARG_INFO(0, ch)
292 ZEND_END_ARG_INFO()
293
294 ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
295         ZEND_ARG_INFO(0, ch)
296 ZEND_END_ARG_INFO()
297
298 ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
299         ZEND_ARG_INFO(0, ch)
300 ZEND_END_ARG_INFO()
301
302 ZEND_BEGIN_ARG_INFO(arginfo_curl_reset, 0)
303         ZEND_ARG_INFO(0, ch)
304 ZEND_END_ARG_INFO()
305
306 ZEND_BEGIN_ARG_INFO(arginfo_curl_escape, 0)
307         ZEND_ARG_INFO(0, ch)
308         ZEND_ARG_INFO(0, str)
309 ZEND_END_ARG_INFO()
310
311 ZEND_BEGIN_ARG_INFO(arginfo_curl_unescape, 0)
312         ZEND_ARG_INFO(0, ch)
313         ZEND_ARG_INFO(0, str)
314 ZEND_END_ARG_INFO()
315
316 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_setopt, 0)
317         ZEND_ARG_INFO(0, sh)
318         ZEND_ARG_INFO(0, option)
319         ZEND_ARG_INFO(0, value)
320 ZEND_END_ARG_INFO()
321
322 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
323 ZEND_END_ARG_INFO()
324
325 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
326         ZEND_ARG_INFO(0, mh)
327         ZEND_ARG_INFO(0, ch)
328 ZEND_END_ARG_INFO()
329
330 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
331         ZEND_ARG_INFO(0, mh)
332         ZEND_ARG_INFO(0, ch)
333 ZEND_END_ARG_INFO()
334
335 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
336         ZEND_ARG_INFO(0, mh)
337         ZEND_ARG_INFO(0, timeout)
338 ZEND_END_ARG_INFO()
339
340 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
341         ZEND_ARG_INFO(0, mh)
342         ZEND_ARG_INFO(1, still_running)
343 ZEND_END_ARG_INFO()
344
345 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
346         ZEND_ARG_INFO(0, ch)
347 ZEND_END_ARG_INFO()
348
349 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
350         ZEND_ARG_INFO(0, mh)
351         ZEND_ARG_INFO(1, msgs_in_queue)
352 ZEND_END_ARG_INFO()
353
354 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
355         ZEND_ARG_INFO(0, mh)
356 ZEND_END_ARG_INFO()
357
358 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_errno, 0)
359         ZEND_ARG_INFO(0, mh)
360 ZEND_END_ARG_INFO()
361
362 ZEND_BEGIN_ARG_INFO(arginfo_curl_strerror, 0)
363         ZEND_ARG_INFO(0, errornum)
364 ZEND_END_ARG_INFO()
365
366 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_strerror, 0)
367         ZEND_ARG_INFO(0, errornum)
368 ZEND_END_ARG_INFO()
369
370 ZEND_BEGIN_ARG_INFO(arginfo_curl_share_strerror, 0)
371         ZEND_ARG_INFO(0, errornum)
372 ZEND_END_ARG_INFO()
373
374 ZEND_BEGIN_ARG_INFO(arginfo_curl_share_init, 0)
375 ZEND_END_ARG_INFO()
376
377 ZEND_BEGIN_ARG_INFO(arginfo_curl_share_close, 0)
378         ZEND_ARG_INFO(0, sh)
379 ZEND_END_ARG_INFO()
380
381 ZEND_BEGIN_ARG_INFO(arginfo_curl_share_setopt, 0)
382         ZEND_ARG_INFO(0, sh)
383         ZEND_ARG_INFO(0, option)
384         ZEND_ARG_INFO(0, value)
385 ZEND_END_ARG_INFO()
386
387 ZEND_BEGIN_ARG_INFO(arginfo_curl_share_errno, 0)
388         ZEND_ARG_INFO(0, sh)
389 ZEND_END_ARG_INFO()
390
391 #if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
392 ZEND_BEGIN_ARG_INFO(arginfo_curl_pause, 0)
393         ZEND_ARG_INFO(0, ch)
394         ZEND_ARG_INFO(0, bitmask)
395 ZEND_END_ARG_INFO()
396 #endif
397
398 ZEND_BEGIN_ARG_INFO_EX(arginfo_curlfile_create, 0, 0, 1)
399         ZEND_ARG_INFO(0, filename)
400         ZEND_ARG_INFO(0, mimetype)
401         ZEND_ARG_INFO(0, postname)
402 ZEND_END_ARG_INFO()
403 /* }}} */
404
405 /* {{{ curl_functions[]
406  */
407 static const zend_function_entry curl_functions[] = {
408         PHP_FE(curl_init,                arginfo_curl_init)
409         PHP_FE(curl_copy_handle,         arginfo_curl_copy_handle)
410         PHP_FE(curl_version,             arginfo_curl_version)
411         PHP_FE(curl_setopt,              arginfo_curl_setopt)
412         PHP_FE(curl_setopt_array,        arginfo_curl_setopt_array)
413         PHP_FE(curl_exec,                arginfo_curl_exec)
414         PHP_FE(curl_getinfo,             arginfo_curl_getinfo)
415         PHP_FE(curl_error,               arginfo_curl_error)
416         PHP_FE(curl_errno,               arginfo_curl_errno)
417         PHP_FE(curl_close,               arginfo_curl_close)
418         PHP_FE(curl_strerror,            arginfo_curl_strerror)
419         PHP_FE(curl_multi_strerror,      arginfo_curl_multi_strerror)
420         PHP_FE(curl_share_strerror,      arginfo_curl_share_strerror)
421         PHP_FE(curl_reset,               arginfo_curl_reset)
422         PHP_FE(curl_escape,              arginfo_curl_escape)
423         PHP_FE(curl_unescape,            arginfo_curl_unescape)
424 #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
425         PHP_FE(curl_pause,               arginfo_curl_pause)
426 #endif
427         PHP_FE(curl_multi_init,          arginfo_curl_multi_init)
428         PHP_FE(curl_multi_add_handle,    arginfo_curl_multi_add_handle)
429         PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
430         PHP_FE(curl_multi_select,        arginfo_curl_multi_select)
431         PHP_FE(curl_multi_exec,          arginfo_curl_multi_exec)
432         PHP_FE(curl_multi_getcontent,    arginfo_curl_multi_getcontent)
433         PHP_FE(curl_multi_info_read,     arginfo_curl_multi_info_read)
434         PHP_FE(curl_multi_close,         arginfo_curl_multi_close)
435         PHP_FE(curl_multi_errno,         arginfo_curl_multi_errno)
436         PHP_FE(curl_multi_setopt,        arginfo_curl_multi_setopt)
437         PHP_FE(curl_share_init,          arginfo_curl_share_init)
438         PHP_FE(curl_share_close,         arginfo_curl_share_close)
439         PHP_FE(curl_share_setopt,        arginfo_curl_share_setopt)
440         PHP_FE(curl_share_errno,         arginfo_curl_share_errno)
441         PHP_FE(curl_file_create,         arginfo_curlfile_create)
442         PHP_FE_END
443 };
444 /* }}} */
445
446 /* {{{ curl_module_entry
447  */
448 zend_module_entry curl_module_entry = {
449         STANDARD_MODULE_HEADER,
450         "curl",
451         curl_functions,
452         PHP_MINIT(curl),
453         PHP_MSHUTDOWN(curl),
454         NULL,
455         NULL,
456         PHP_MINFO(curl),
457         PHP_CURL_VERSION,
458         STANDARD_MODULE_PROPERTIES
459 };
460 /* }}} */
461
462 #ifdef COMPILE_DL_CURL
463 ZEND_GET_MODULE (curl)
464 #endif
465
466 /* {{{ PHP_INI_BEGIN */
467 PHP_INI_BEGIN()
468         PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
469 PHP_INI_END()
470 /* }}} */
471
472 /* {{{ PHP_MINFO_FUNCTION
473  */
474 PHP_MINFO_FUNCTION(curl)
475 {
476         curl_version_info_data *d;
477         char **p;
478         char str[1024];
479         size_t n = 0;
480
481         d = curl_version_info(CURLVERSION_NOW);
482         php_info_print_table_start();
483         php_info_print_table_row(2, "cURL support",    "enabled");
484         php_info_print_table_row(2, "cURL Information", d->version);
485         sprintf(str, "%d", d->age);
486         php_info_print_table_row(2, "Age", str);
487
488         /* To update on each new cURL release using src/main.c in cURL sources */
489         if (d->features) {
490                 struct feat {
491                         const char *name;
492                         int bitmask;
493                 };
494
495                 unsigned int i;
496
497                 static const struct feat feats[] = {
498                         {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
499                         {"CharConv", CURL_VERSION_CONV},
500                         {"Debug", CURL_VERSION_DEBUG},
501                         {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
502                         {"IDN", CURL_VERSION_IDN},
503                         {"IPv6", CURL_VERSION_IPV6},
504                         {"krb4", CURL_VERSION_KERBEROS4},
505                         {"Largefile", CURL_VERSION_LARGEFILE},
506                         {"libz", CURL_VERSION_LIBZ},
507                         {"NTLM", CURL_VERSION_NTLM},
508 #if LIBCURL_VERSION_NUM >= 0x071600 /* 7.22.0 */
509                         {"NTLMWB", CURL_VERSION_NTLM_WB},
510 #endif
511                         {"SPNEGO", CURL_VERSION_SPNEGO},
512                         {"SSL",  CURL_VERSION_SSL},
513                         {"SSPI",  CURL_VERSION_SSPI},
514 #if LIBCURL_VERSION_NUM >= 0x071504 /* 7.21.4 */
515                         {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
516 #endif
517 #if LIBCURL_VERSION_NUM >= 0x072100 /* 7.33.0 */
518                         {"HTTP2", CURL_VERSION_HTTP2},
519 #endif
520 #if LIBCURL_VERSION_NUM >= 0x072600 /* 7.38.0 */
521                         {"GSSAPI", CURL_VERSION_GSSAPI},
522 #endif
523 #if LIBCURL_VERSION_NUM >= 0x072800 /* 7.40.0 */
524                         {"KERBEROS5", CURL_VERSION_KERBEROS5},
525                         {"UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS},
526 #endif
527 #if LIBCURL_VERSION_NUM >= 0x072f00 /* 7.47.0 */
528                         {"PSL", CURL_VERSION_PSL},
529 #endif
530 #if LIBCURL_VERSION_NUM >= 0x073400 /* 7.52.0 */
531                         {"HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY},
532 #endif
533 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
534                         {"MULTI_SSL", CURL_VERSION_MULTI_SSL},
535 #endif
536 #if LIBCURL_VERSION_NUM >= 0x073900 /* 7.57.0 */
537                         {"BROTLI", CURL_VERSION_BROTLI},
538 #endif
539                         {NULL, 0}
540                 };
541
542                 php_info_print_table_row(1, "Features");
543                 for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
544                         if (feats[i].name) {
545                                 php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
546                         }
547                 }
548         }
549
550         n = 0;
551         p = (char **) d->protocols;
552         while (*p != NULL) {
553                         n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : "");
554                         p++;
555         }
556         php_info_print_table_row(2, "Protocols", str);
557
558         php_info_print_table_row(2, "Host", d->host);
559
560         if (d->ssl_version) {
561                 php_info_print_table_row(2, "SSL Version", d->ssl_version);
562         }
563
564         if (d->libz_version) {
565                 php_info_print_table_row(2, "ZLib Version", d->libz_version);
566         }
567
568 #if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND
569         if (d->ares) {
570                 php_info_print_table_row(2, "ZLib Version", d->ares);
571         }
572 #endif
573
574 #if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD
575         if (d->libidn) {
576                 php_info_print_table_row(2, "libIDN Version", d->libidn);
577         }
578 #endif
579
580 #if LIBCURL_VERSION_NUM >= 0x071300
581
582         if (d->iconv_ver_num) {
583                 php_info_print_table_row(2, "IconV Version", d->iconv_ver_num);
584         }
585
586         if (d->libssh_version) {
587                 php_info_print_table_row(2, "libSSH Version", d->libssh_version);
588         }
589 #endif
590         php_info_print_table_end();
591
592         DISPLAY_INI_ENTRIES();
593 }
594 /* }}} */
595
596 #define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
597
598 /* {{{ PHP_MINIT_FUNCTION
599  */
600 PHP_MINIT_FUNCTION(curl)
601 {
602         le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
603         le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
604         le_curl_share_handle = zend_register_list_destructors_ex(_php_curl_share_close, NULL, "curl_share", module_number);
605
606         REGISTER_INI_ENTRIES();
607
608         /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
609            or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
610            of options and which version they were introduced */
611
612         /* Constants for curl_setopt() */
613         REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
614         REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
615         REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
616         REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
617         REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
618         REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
619         REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
620         REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
621         REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
622         REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
623         REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
624         REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
625         REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
626         REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
627         REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
628         REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
629         REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
630         REGISTER_CURL_CONSTANT(CURLOPT_FILE);
631         REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
632         REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
633         REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
634         REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
635         REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
636         REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
637         REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
638         REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
639         REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
640         REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
641         REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
642         REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
643         REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
644         REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
645         REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
646         REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
647         REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
648         REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
649         REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
650         REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
651         REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
652         REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
653         REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
654         REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
655         REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
656         REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
657         REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
658         REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
659         REGISTER_CURL_CONSTANT(CURLOPT_PORT);
660         REGISTER_CURL_CONSTANT(CURLOPT_POST);
661         REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
662         REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
663         REGISTER_CURL_CONSTANT(CURLOPT_PREQUOTE);
664         REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
665         REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION);
666         REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
667         REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
668         REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
669         REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
670         REGISTER_CURL_CONSTANT(CURLOPT_PUT);
671         REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
672         REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
673         REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
674         REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
675         REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
676         REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
677         REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
678         REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
679         REGISTER_CURL_CONSTANT(CURLOPT_SHARE);
680         REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
681         REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
682         REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
683         REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
684         REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
685         REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
686         REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
687         REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
688         REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
689         REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
690         REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
691         REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
692         REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
693         REGISTER_CURL_CONSTANT(CURLOPT_TELNETOPTIONS);
694         REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
695         REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
696         REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
697         REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
698         REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
699         REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
700         REGISTER_CURL_CONSTANT(CURLOPT_URL);
701         REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
702         REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
703         REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
704         REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
705         REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
706
707         /* */
708         REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
709         REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
710         REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
711         REGISTER_CURL_CONSTANT(CURLE_BAD_DOWNLOAD_RESUME);
712         REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
713         REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
714         REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
715         REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
716         REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
717         REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
718         REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
719         REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
720         REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
721         REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
722         REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
723         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
724         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
725         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
726         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
727         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
728         REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
729         REGISTER_CURL_CONSTANT(CURLE_FTP_PARTIAL_FILE);
730         REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
731         REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
732         REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
733         REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
734         REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
735         REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
736         REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
737         REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
738         REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
739         REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
740         REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
741         REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
742         REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
743         REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
744         REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
745         REGISTER_CURL_CONSTANT(CURLE_HTTP_RETURNED_ERROR);
746         REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
747         REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
748         REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
749         REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
750         REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
751         REGISTER_CURL_CONSTANT(CURLE_OK);
752         REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEDOUT);
753         REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
754         REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
755         REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
756         REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
757         REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
758         REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
759         REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
760         REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
761         REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
762         REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
763         REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
764         REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
765         REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
766         REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
767 #if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
768         REGISTER_CURL_CONSTANT(CURLE_SSL_PINNEDPUBKEYNOTMATCH);
769 #endif
770         REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
771         REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
772         REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
773         REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
774         REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
775         REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
776         REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
777
778         /* cURL info constants */
779         REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
780         REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
781         REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
782         REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
783         REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
784         REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
785         REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
786         REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
787         REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
788         REGISTER_CURL_CONSTANT(CURLINFO_LASTONE);
789         REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
790         REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
791         REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
792         REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
793         REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
794         REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
795         REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
796         REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
797         REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
798         REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
799         REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
800         REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
801         REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
802
803         /* Other */
804         REGISTER_CURL_CONSTANT(CURLMSG_DONE);
805         REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
806
807         /* Curl Multi Constants */
808         REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
809         REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
810         REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
811         REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
812         REGISTER_CURL_CONSTANT(CURLM_OK);
813         REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
814 #if LIBCURL_VERSION_NUM >= 0x072001 /* Available since 7.32.1 */
815         REGISTER_CURL_CONSTANT(CURLM_ADDED_ALREADY);
816 #endif
817
818         /* Curl proxy constants */
819         REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
820         REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
821         REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
822
823         /* Curl Share constants */
824         REGISTER_CURL_CONSTANT(CURLSHOPT_NONE);
825         REGISTER_CURL_CONSTANT(CURLSHOPT_SHARE);
826         REGISTER_CURL_CONSTANT(CURLSHOPT_UNSHARE);
827
828         /* Curl Http Version constants (CURLOPT_HTTP_VERSION) */
829         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
830         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
831         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
832
833         /* Curl Lock constants */
834         REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_COOKIE);
835         REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_DNS);
836         REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_SSL_SESSION);
837
838         /* Curl NETRC constants (CURLOPT_NETRC) */
839         REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
840         REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
841         REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
842
843         /* Curl SSL Version constants (CURLOPT_SSLVERSION) */
844         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_DEFAULT);
845         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv2);
846         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv3);
847         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1);
848
849         /* Curl TIMECOND constants (CURLOPT_TIMECONDITION) */
850         REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
851         REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
852         REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
853         REGISTER_CURL_CONSTANT(CURL_TIMECOND_NONE);
854
855         /* Curl version constants */
856         REGISTER_CURL_CONSTANT(CURL_VERSION_ASYNCHDNS);
857         REGISTER_CURL_CONSTANT(CURL_VERSION_CONV);
858         REGISTER_CURL_CONSTANT(CURL_VERSION_DEBUG);
859         REGISTER_CURL_CONSTANT(CURL_VERSION_GSSNEGOTIATE);
860         REGISTER_CURL_CONSTANT(CURL_VERSION_IDN);
861         REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
862         REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
863         REGISTER_CURL_CONSTANT(CURL_VERSION_LARGEFILE);
864         REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
865         REGISTER_CURL_CONSTANT(CURL_VERSION_NTLM);
866         REGISTER_CURL_CONSTANT(CURL_VERSION_SPNEGO);
867         REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
868         REGISTER_CURL_CONSTANT(CURL_VERSION_SSPI);
869
870         /* Available since 7.10.6 */
871         REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
872         /* http authentication options */
873         REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
874         REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
875         REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
876         REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
877         REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
878         REGISTER_CURL_CONSTANT(CURLAUTH_NONE);
879         REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
880
881         /* Available since 7.10.7 */
882         REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CONNECTCODE);
883         REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
884         REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
885
886         /* Available since 7.10.8 */
887         REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
888         REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
889         REGISTER_CURL_CONSTANT(CURLINFO_HTTPAUTH_AVAIL);
890         REGISTER_CURL_CONSTANT(CURLINFO_RESPONSE_CODE);
891         REGISTER_CURL_CONSTANT(CURLINFO_PROXYAUTH_AVAIL);
892         REGISTER_CURL_CONSTANT(CURLOPT_FTP_RESPONSE_TIMEOUT);
893         REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE);
894         REGISTER_CURL_CONSTANT(CURLOPT_MAXFILESIZE);
895         REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4);
896         REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6);
897         REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER);
898
899         /* Available since 7.11.0 */
900         REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
901         REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
902         REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
903         REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
904         REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
905         REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
906         REGISTER_CURL_CONSTANT(CURLOPT_NETRC_FILE);
907
908         /* Available since 7.11.2 */
909         REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
910
911         /* Available since 7.12.2 */
912         REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
913         REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
914         REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
915         REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
916
917         /* Available since 7.13.0 */
918         REGISTER_CURL_CONSTANT(CURLOPT_FTP_ACCOUNT);
919
920         /* Available since 7.12.2 */
921         REGISTER_CURL_CONSTANT(CURLINFO_OS_ERRNO);
922
923         /* Available since 7.12.3 */
924         REGISTER_CURL_CONSTANT(CURLINFO_NUM_CONNECTS);
925         REGISTER_CURL_CONSTANT(CURLINFO_SSL_ENGINES);
926
927         /* Available since 7.14.1 */
928         REGISTER_CURL_CONSTANT(CURLINFO_COOKIELIST);
929         REGISTER_CURL_CONSTANT(CURLOPT_COOKIELIST);
930         REGISTER_CURL_CONSTANT(CURLOPT_IGNORE_CONTENT_LENGTH);
931
932         /* Available since 7.15.0 */
933         REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP);
934
935         /* Available since 7.15.1 */
936         REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD);
937
938         /* Available since 7.15.2 */
939         REGISTER_CURL_CONSTANT(CURLOPT_CONNECT_ONLY);
940         REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORT);
941         REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORTRANGE);
942
943         /* Available since 7.15.3 */
944         REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD);
945         REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD);
946         REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD);
947
948         /* Available since 7.15.4 */
949         REGISTER_CURL_CONSTANT(CURLINFO_FTP_ENTRY_PATH);
950
951         /* Available since 7.15.5 */
952         REGISTER_CURL_CONSTANT(CURLOPT_FTP_ALTERNATIVE_TO_USER);
953         REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE);
954         REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE);
955
956 #if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */
957         REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT_BADFILE);
958         REGISTER_CURL_CONSTANT(CURLOPT_SSL_SESSIONID_CACHE);
959         REGISTER_CURL_CONSTANT(CURLMOPT_PIPELINING);
960 #endif
961
962 #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
963         REGISTER_CURL_CONSTANT(CURLE_SSH);
964         REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL_CCC);
965         REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES);
966         REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE);
967         REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE);
968         REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_ACTIVE);
969         REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_NONE);
970         REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_PASSIVE);
971 #endif
972
973 #if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */
974         REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
975         REGISTER_CURL_CONSTANT(CURLOPT_HTTP_CONTENT_DECODING);
976         REGISTER_CURL_CONSTANT(CURLOPT_HTTP_TRANSFER_DECODING);
977         REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
978 #endif
979
980 #if LIBCURL_VERSION_NUM >= 0x071003 /* Available since 7.16.3 */
981         REGISTER_CURL_CONSTANT(CURLMOPT_MAXCONNECTS);
982 #endif
983
984 #if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
985         REGISTER_CURL_CONSTANT(CURLOPT_KRBLEVEL);
986         REGISTER_CURL_CONSTANT(CURLOPT_NEW_DIRECTORY_PERMS);
987         REGISTER_CURL_CONSTANT(CURLOPT_NEW_FILE_PERMS);
988 #endif
989
990 #if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */
991         REGISTER_CURL_CONSTANT(CURLOPT_APPEND);
992         REGISTER_CURL_CONSTANT(CURLOPT_DIRLISTONLY);
993         REGISTER_CURL_CONSTANT(CURLOPT_USE_SSL);
994         /* Curl SSL Constants */
995         REGISTER_CURL_CONSTANT(CURLUSESSL_ALL);
996         REGISTER_CURL_CONSTANT(CURLUSESSL_CONTROL);
997         REGISTER_CURL_CONSTANT(CURLUSESSL_NONE);
998         REGISTER_CURL_CONSTANT(CURLUSESSL_TRY);
999 #endif
1000
1001 #if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */
1002         REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
1003 #endif
1004
1005 #if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
1006         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TRANSFER_MODE);
1007         REGISTER_CURL_CONSTANT(CURLPAUSE_ALL);
1008         REGISTER_CURL_CONSTANT(CURLPAUSE_CONT);
1009         REGISTER_CURL_CONSTANT(CURLPAUSE_RECV);
1010         REGISTER_CURL_CONSTANT(CURLPAUSE_RECV_CONT);
1011         REGISTER_CURL_CONSTANT(CURLPAUSE_SEND);
1012         REGISTER_CURL_CONSTANT(CURLPAUSE_SEND_CONT);
1013         REGISTER_CURL_CONSTANT(CURL_READFUNC_PAUSE);
1014         REGISTER_CURL_CONSTANT(CURL_WRITEFUNC_PAUSE);
1015
1016         REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4A);
1017         REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5_HOSTNAME);
1018 #endif
1019
1020 #if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */
1021         REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
1022 #endif
1023
1024 #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
1025         REGISTER_CURL_CONSTANT(CURLINFO_APPCONNECT_TIME);
1026         REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP);
1027
1028         REGISTER_CURL_CONSTANT(CURLOPT_ADDRESS_SCOPE);
1029         REGISTER_CURL_CONSTANT(CURLOPT_CRLFILE);
1030         REGISTER_CURL_CONSTANT(CURLOPT_ISSUERCERT);
1031         REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD);
1032
1033         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_ANY);
1034         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT);
1035         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST);
1036         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD);
1037         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE);
1038         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD);
1039         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY);
1040 #endif
1041
1042 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
1043         REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO);
1044         REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO);
1045         REGISTER_CURL_CONSTANT(CURLOPT_PASSWORD);
1046         REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR);
1047         REGISTER_CURL_CONSTANT(CURLOPT_PROXYPASSWORD);
1048         REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERNAME);
1049         REGISTER_CURL_CONSTANT(CURLOPT_USERNAME);
1050         REGISTER_CURL_CONSTANT(CURL_REDIR_POST_301);
1051         REGISTER_CURL_CONSTANT(CURL_REDIR_POST_302);
1052         REGISTER_CURL_CONSTANT(CURL_REDIR_POST_ALL);
1053 #endif
1054
1055 #if LIBCURL_VERSION_NUM >= 0x071303 /* Available since 7.19.3 */
1056         REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST_IE);
1057 #endif
1058
1059 #if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
1060         REGISTER_CURL_CONSTANT(CURLINFO_CONDITION_UNMET);
1061
1062         REGISTER_CURL_CONSTANT(CURLOPT_NOPROXY);
1063         REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
1064         REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
1065         REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_NEC);
1066         REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_SERVICE);
1067         REGISTER_CURL_CONSTANT(CURLOPT_TFTP_BLKSIZE);
1068
1069         REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
1070         REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
1071         REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
1072         REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
1073         REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
1074         REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
1075         REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
1076         REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
1077         REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
1078         REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
1079         REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
1080         REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
1081         REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
1082
1083         REGISTER_CURL_CONSTANT(CURLPROXY_HTTP_1_0);
1084
1085         REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR);
1086         REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR_NONE);
1087         REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR_RETRY);
1088 #endif
1089
1090 #if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */
1091         REGISTER_CURL_CONSTANT(CURL_VERSION_CURLDEBUG);
1092         REGISTER_CURL_CONSTANT(CURLOPT_SSH_KNOWNHOSTS);
1093 #endif
1094
1095 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
1096         REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CLIENT_CSEQ);
1097         REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CSEQ_RECV);
1098         REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SERVER_CSEQ);
1099         REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SESSION_ID);
1100         REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_PRET);
1101         REGISTER_CURL_CONSTANT(CURLOPT_MAIL_FROM);
1102         REGISTER_CURL_CONSTANT(CURLOPT_MAIL_RCPT);
1103         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_CLIENT_CSEQ);
1104         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_REQUEST);
1105         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SERVER_CSEQ);
1106         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SESSION_ID);
1107         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_STREAM_URI);
1108         REGISTER_CURL_CONSTANT(CURLOPT_RTSP_TRANSPORT);
1109         REGISTER_CURL_CONSTANT(CURLPROTO_IMAP);
1110         REGISTER_CURL_CONSTANT(CURLPROTO_IMAPS);
1111         REGISTER_CURL_CONSTANT(CURLPROTO_POP3);
1112         REGISTER_CURL_CONSTANT(CURLPROTO_POP3S);
1113         REGISTER_CURL_CONSTANT(CURLPROTO_RTSP);
1114         REGISTER_CURL_CONSTANT(CURLPROTO_SMTP);
1115         REGISTER_CURL_CONSTANT(CURLPROTO_SMTPS);
1116         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_ANNOUNCE);
1117         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_DESCRIBE);
1118         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_GET_PARAMETER);
1119         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_OPTIONS);
1120         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PAUSE);
1121         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PLAY);
1122         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECEIVE);
1123         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECORD);
1124         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SET_PARAMETER);
1125         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SETUP);
1126         REGISTER_CURL_CONSTANT(CURL_RTSPREQ_TEARDOWN);
1127 #endif
1128
1129 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1130         REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP);
1131         REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT);
1132         REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT);
1133         REGISTER_CURL_CONSTANT(CURLOPT_FNMATCH_FUNCTION);
1134         REGISTER_CURL_CONSTANT(CURLOPT_WILDCARDMATCH);
1135         REGISTER_CURL_CONSTANT(CURLPROTO_RTMP);
1136         REGISTER_CURL_CONSTANT(CURLPROTO_RTMPE);
1137         REGISTER_CURL_CONSTANT(CURLPROTO_RTMPS);
1138         REGISTER_CURL_CONSTANT(CURLPROTO_RTMPT);
1139         REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTE);
1140         REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTS);
1141         REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_FAIL);
1142         REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_MATCH);
1143         REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_NOMATCH);
1144 #endif
1145
1146 #if LIBCURL_VERSION_NUM >= 0x071502 /* Available since 7.21.2 */
1147         REGISTER_CURL_CONSTANT(CURLPROTO_GOPHER);
1148 #endif
1149
1150 #if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
1151         REGISTER_CURL_CONSTANT(CURLAUTH_ONLY);
1152         REGISTER_CURL_CONSTANT(CURLOPT_RESOLVE);
1153 #endif
1154
1155 #if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
1156         REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_PASSWORD);
1157         REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_TYPE);
1158         REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_USERNAME);
1159         REGISTER_CURL_CONSTANT(CURL_TLSAUTH_SRP);
1160         REGISTER_CURL_CONSTANT(CURL_VERSION_TLSAUTH_SRP);
1161 #endif
1162
1163 #if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */
1164         REGISTER_CURL_CONSTANT(CURLOPT_ACCEPT_ENCODING);
1165         REGISTER_CURL_CONSTANT(CURLOPT_TRANSFER_ENCODING);
1166 #endif
1167
1168 #if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */
1169         REGISTER_CURL_CONSTANT(CURLAUTH_NTLM_WB);
1170         REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_FLAG);
1171         REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_POLICY_FLAG);
1172         REGISTER_CURL_CONSTANT(CURLOPT_GSSAPI_DELEGATION);
1173         REGISTER_CURL_CONSTANT(CURL_VERSION_NTLM_WB);
1174 #endif
1175
1176 #if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
1177         REGISTER_CURL_CONSTANT(CURLOPT_ACCEPTTIMEOUT_MS);
1178         REGISTER_CURL_CONSTANT(CURLOPT_DNS_SERVERS);
1179 #endif
1180
1181 #if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
1182         REGISTER_CURL_CONSTANT(CURLOPT_MAIL_AUTH);
1183         REGISTER_CURL_CONSTANT(CURLOPT_SSL_OPTIONS);
1184         REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPALIVE);
1185         REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPIDLE);
1186         REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPINTVL);
1187         REGISTER_CURL_CONSTANT(CURLSSLOPT_ALLOW_BEAST);
1188 #endif
1189
1190 #if LIBCURL_VERSION_NUM >= 0x071901 /* Available since 7.25.1 */
1191         REGISTER_CURL_CONSTANT(CURL_REDIR_POST_303);
1192 #endif
1193
1194 #if LIBCURL_VERSION_NUM >= 0x071c00 /* Available since 7.28.0 */
1195         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_AGENT);
1196 #endif
1197
1198 #if LIBCURL_VERSION_NUM >= 0x071e00 /* Available since 7.30.0 */
1199         REGISTER_CURL_CONSTANT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE);
1200         REGISTER_CURL_CONSTANT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE);
1201         REGISTER_CURL_CONSTANT(CURLMOPT_MAX_HOST_CONNECTIONS);
1202         REGISTER_CURL_CONSTANT(CURLMOPT_MAX_PIPELINE_LENGTH);
1203         REGISTER_CURL_CONSTANT(CURLMOPT_MAX_TOTAL_CONNECTIONS);
1204 #endif
1205
1206 #if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */
1207         REGISTER_CURL_CONSTANT(CURLOPT_SASL_IR);
1208 #endif
1209
1210 #if LIBCURL_VERSION_NUM >= 0x072100 /* Available since 7.33.0 */
1211         REGISTER_CURL_CONSTANT(CURLOPT_DNS_INTERFACE);
1212         REGISTER_CURL_CONSTANT(CURLOPT_DNS_LOCAL_IP4);
1213         REGISTER_CURL_CONSTANT(CURLOPT_DNS_LOCAL_IP6);
1214         REGISTER_CURL_CONSTANT(CURLOPT_XOAUTH2_BEARER);
1215
1216         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2_0);
1217         REGISTER_CURL_CONSTANT(CURL_VERSION_HTTP2);
1218 #endif
1219
1220 #if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */
1221         REGISTER_CURL_CONSTANT(CURLOPT_LOGIN_OPTIONS);
1222
1223         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_0);
1224         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_1);
1225         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_2);
1226 #endif
1227
1228 #if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */
1229         REGISTER_CURL_CONSTANT(CURLOPT_EXPECT_100_TIMEOUT_MS);
1230         REGISTER_CURL_CONSTANT(CURLOPT_SSL_ENABLE_ALPN);
1231         REGISTER_CURL_CONSTANT(CURLOPT_SSL_ENABLE_NPN);
1232 #endif
1233
1234 #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
1235         REGISTER_CURL_CONSTANT(CURLHEADER_SEPARATE);
1236         REGISTER_CURL_CONSTANT(CURLHEADER_UNIFIED);
1237         REGISTER_CURL_CONSTANT(CURLOPT_HEADEROPT);
1238         REGISTER_CURL_CONSTANT(CURLOPT_PROXYHEADER);
1239 #endif
1240
1241 #if LIBCURL_VERSION_NUM >= 0x072600 /* Available since 7.38.0 */
1242         REGISTER_CURL_CONSTANT(CURLAUTH_NEGOTIATE);
1243         REGISTER_CURL_CONSTANT(CURL_VERSION_GSSAPI);
1244 #endif
1245
1246 #if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
1247         REGISTER_CURL_CONSTANT(CURLOPT_PINNEDPUBLICKEY);
1248 #endif
1249
1250 #if LIBCURL_VERSION_NUM >= 0x072800 /* Available since 7.40.0 */
1251         REGISTER_CURL_CONSTANT(CURLOPT_UNIX_SOCKET_PATH);
1252         REGISTER_CURL_CONSTANT(CURLPROTO_SMB);
1253         REGISTER_CURL_CONSTANT(CURLPROTO_SMBS);
1254         REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS5);
1255         REGISTER_CURL_CONSTANT(CURL_VERSION_UNIX_SOCKETS);
1256 #endif
1257
1258 #if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */
1259         REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYSTATUS);
1260 #endif
1261
1262 #if LIBCURL_VERSION_NUM >= 0x072a00 /* Available since 7.42.0 */
1263         REGISTER_CURL_CONSTANT(CURLOPT_PATH_AS_IS);
1264         REGISTER_CURL_CONSTANT(CURLOPT_SSL_FALSESTART);
1265 #endif
1266
1267 #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
1268         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2);
1269
1270         REGISTER_CURL_CONSTANT(CURLOPT_PIPEWAIT);
1271         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SERVICE_NAME);
1272         REGISTER_CURL_CONSTANT(CURLOPT_SERVICE_NAME);
1273
1274         REGISTER_CURL_CONSTANT(CURLPIPE_NOTHING);
1275         REGISTER_CURL_CONSTANT(CURLPIPE_HTTP1);
1276         REGISTER_CURL_CONSTANT(CURLPIPE_MULTIPLEX);
1277 #endif
1278
1279 #if LIBCURL_VERSION_NUM >= 0x072c00 /* Available since 7.44.0 */
1280         REGISTER_CURL_CONSTANT(CURLSSLOPT_NO_REVOKE);
1281 #endif
1282
1283 #if LIBCURL_VERSION_NUM >= 0x072d00 /* Available since 7.45.0 */
1284         REGISTER_CURL_CONSTANT(CURLOPT_DEFAULT_PROTOCOL);
1285 #endif
1286
1287 #if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */
1288         REGISTER_CURL_CONSTANT(CURLOPT_STREAM_WEIGHT);
1289         REGISTER_CURL_CONSTANT(CURLMOPT_PUSHFUNCTION);
1290         REGISTER_CURL_CONSTANT(CURL_PUSH_OK);
1291         REGISTER_CURL_CONSTANT(CURL_PUSH_DENY);
1292 #endif
1293
1294 #if LIBCURL_VERSION_NUM >= 0x072f00 /* Available since 7.47.0 */
1295         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2TLS);
1296         REGISTER_CURL_CONSTANT(CURL_VERSION_PSL);
1297 #endif
1298
1299 #if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */
1300         REGISTER_CURL_CONSTANT(CURLOPT_TFTP_NO_OPTIONS);
1301 #endif
1302
1303 #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
1304         REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
1305         REGISTER_CURL_CONSTANT(CURLOPT_CONNECT_TO);
1306         REGISTER_CURL_CONSTANT(CURLOPT_TCP_FASTOPEN);
1307 #endif
1308
1309 #if LIBCURL_VERSION_NUM >= 0x073200 /* Available since 7.50.0 */
1310         REGISTER_CURL_CONSTANT(CURLINFO_HTTP_VERSION);
1311 #endif
1312
1313 #if LIBCURL_VERSION_NUM >= 0x073300 /* Available since 7.51.0 */
1314         REGISTER_CURL_CONSTANT(CURLE_WEIRD_SERVER_REPLY);
1315         REGISTER_CURL_CONSTANT(CURLOPT_KEEP_SENDING_ON_ERROR);
1316 #endif
1317
1318 #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
1319         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_3);
1320         REGISTER_CURL_CONSTANT(CURL_VERSION_HTTPS_PROXY);
1321         REGISTER_CURL_CONSTANT(CURLINFO_PROTOCOL);
1322         REGISTER_CURL_CONSTANT(CURLINFO_PROXY_SSL_VERIFYRESULT);
1323         REGISTER_CURL_CONSTANT(CURLINFO_SCHEME);
1324         REGISTER_CURL_CONSTANT(CURLOPT_PRE_PROXY);
1325         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CAINFO);
1326         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CAPATH);
1327         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CRLFILE);
1328         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_KEYPASSWD);
1329         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_PINNEDPUBLICKEY);
1330         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_CIPHER_LIST);
1331         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_OPTIONS);
1332         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_VERIFYHOST);
1333         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_VERIFYPEER);
1334         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLCERT);
1335         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLCERTTYPE);
1336         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLKEY);
1337         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLKEYTYPE);
1338         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLVERSION);
1339         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_PASSWORD);
1340         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_TYPE);
1341         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_USERNAME);
1342         REGISTER_CURL_CONSTANT(CURLPROXY_HTTPS);
1343 #endif
1344
1345 #if LIBCURL_VERSION_NUM >= 0x073500 /* Available since 7.53.0 */
1346         REGISTER_CURL_CONSTANT(CURL_MAX_READ_SIZE);
1347         REGISTER_CURL_CONSTANT(CURLOPT_ABSTRACT_UNIX_SOCKET);
1348 #endif
1349
1350 #if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */
1351         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_DEFAULT);
1352         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_NONE);
1353         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_0);
1354         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_1);
1355         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_2);
1356         REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_3);
1357         REGISTER_CURL_CONSTANT(CURLOPT_SUPPRESS_CONNECT_HEADERS);
1358 #endif
1359
1360 #if LIBCURL_VERSION_NUM >= 0x073601 /* Available since 7.54.1 */
1361         REGISTER_CURL_CONSTANT(CURLAUTH_GSSAPI);
1362 #endif
1363
1364 #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
1365         REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD_T);
1366         REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD_T);
1367         REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD_T);
1368         REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD_T);
1369         REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD_T);
1370         REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD_T);
1371         REGISTER_CURL_CONSTANT(CURLOPT_REQUEST_TARGET);
1372         REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_AUTH);
1373 #endif
1374
1375 #if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */
1376         REGISTER_CURL_CONSTANT(CURLOPT_SSH_COMPRESSION);
1377         REGISTER_CURL_CONSTANT(CURL_VERSION_MULTI_SSL);
1378 #endif
1379
1380 #if LIBCURL_VERSION_NUM >= 0x073900 /* Available since 7.57.0 */
1381         REGISTER_CURL_CONSTANT(CURL_VERSION_BROTLI);
1382         REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_CONNECT);
1383 #endif
1384
1385 #if LIBCURL_VERSION_NUM >= 0x073a00 /* Available since 7.58.0 */
1386         REGISTER_CURL_CONSTANT(CURLSSH_AUTH_GSSAPI);
1387 #endif
1388
1389 #if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
1390         REGISTER_CURL_CONSTANT(CURLINFO_FILETIME_T);
1391         REGISTER_CURL_CONSTANT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS);
1392         REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE_LARGE);
1393 #endif
1394
1395 #if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */
1396         REGISTER_CURL_CONSTANT(CURLOPT_DNS_SHUFFLE_ADDRESSES);
1397         REGISTER_CURL_CONSTANT(CURLOPT_HAPROXYPROTOCOL);
1398 #endif
1399
1400 #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
1401         REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_PSL);
1402         REGISTER_CURL_CONSTANT(CURLAUTH_BEARER);
1403         REGISTER_CURL_CONSTANT(CURLINFO_APPCONNECT_TIME_T);
1404         REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME_T);
1405         REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME_T);
1406         REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME_T);
1407         REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME_T);
1408         REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME_T);
1409         REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME_T);
1410         REGISTER_CURL_CONSTANT(CURLOPT_DISALLOW_USERNAME_IN_URL);
1411         REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLS13_CIPHERS);
1412         REGISTER_CURL_CONSTANT(CURLOPT_TLS13_CIPHERS);
1413 #endif
1414
1415 #if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
1416         REGISTER_CURL_CONSTANT(CURL_VERSION_ALTSVC);
1417 #endif
1418
1419         REGISTER_CURL_CONSTANT(CURLOPT_SAFE_UPLOAD);
1420
1421 #ifdef PHP_CURL_NEED_OPENSSL_TSL
1422         if (!CRYPTO_get_id_callback()) {
1423                 int i, c = CRYPTO_num_locks();
1424
1425                 php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
1426                 if (!php_curl_openssl_tsl) {
1427                         return FAILURE;
1428                 }
1429
1430                 for (i = 0; i < c; ++i) {
1431                         php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
1432                 }
1433
1434                 CRYPTO_set_id_callback(php_curl_ssl_id);
1435                 CRYPTO_set_locking_callback(php_curl_ssl_lock);
1436         }
1437 #endif
1438
1439         if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
1440                 return FAILURE;
1441         }
1442
1443         curlfile_register_class();
1444
1445         return SUCCESS;
1446 }
1447 /* }}} */
1448
1449 /* {{{ PHP_MSHUTDOWN_FUNCTION
1450  */
1451 PHP_MSHUTDOWN_FUNCTION(curl)
1452 {
1453         curl_global_cleanup();
1454 #ifdef PHP_CURL_NEED_OPENSSL_TSL
1455         if (php_curl_openssl_tsl) {
1456                 int i, c = CRYPTO_num_locks();
1457
1458                 CRYPTO_set_id_callback(NULL);
1459                 CRYPTO_set_locking_callback(NULL);
1460
1461                 for (i = 0; i < c; ++i) {
1462                         tsrm_mutex_free(php_curl_openssl_tsl[i]);
1463                 }
1464
1465                 free(php_curl_openssl_tsl);
1466                 php_curl_openssl_tsl = NULL;
1467         }
1468 #endif
1469         UNREGISTER_INI_ENTRIES();
1470         return SUCCESS;
1471 }
1472 /* }}} */
1473
1474 /* {{{ curl_write_nothing
1475  * Used as a work around. See _php_curl_close_ex
1476  */
1477 static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx)
1478 {
1479         return size * nmemb;
1480 }
1481 /* }}} */
1482
1483 /* {{{ curl_write
1484  */
1485 static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
1486 {
1487         php_curl *ch = (php_curl *) ctx;
1488         php_curl_write *t = ch->handlers->write;
1489         size_t length = size * nmemb;
1490
1491 #if PHP_CURL_DEBUG
1492         fprintf(stderr, "curl_write() called\n");
1493         fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
1494 #endif
1495
1496         switch (t->method) {
1497                 case PHP_CURL_STDOUT:
1498                         PHPWRITE(data, length);
1499                         break;
1500                 case PHP_CURL_FILE:
1501                         return fwrite(data, size, nmemb, t->fp);
1502                 case PHP_CURL_RETURN:
1503                         if (length > 0) {
1504                                 smart_str_appendl(&t->buf, data, (int) length);
1505                         }
1506                         break;
1507                 case PHP_CURL_USER: {
1508                         zval argv[2];
1509                         zval retval;
1510                         int  error;
1511                         zend_fcall_info fci;
1512
1513                         GC_ADDREF(ch->res);
1514                         ZVAL_RES(&argv[0], ch->res);
1515                         ZVAL_STRINGL(&argv[1], data, length);
1516
1517                         fci.size = sizeof(fci);
1518                         fci.object = NULL;
1519                         ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1520                         fci.retval = &retval;
1521                         fci.param_count = 2;
1522                         fci.params = argv;
1523                         fci.no_separation = 0;
1524
1525                         ch->in_callback = 1;
1526                         error = zend_call_function(&fci, &t->fci_cache);
1527                         ch->in_callback = 0;
1528                         if (error == FAILURE) {
1529                                 php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
1530                                 length = -1;
1531                         } else if (!Z_ISUNDEF(retval)) {
1532                                 _php_curl_verify_handlers(ch, 1);
1533                                 length = zval_get_long(&retval);
1534                         }
1535
1536                         zval_ptr_dtor(&argv[0]);
1537                         zval_ptr_dtor(&argv[1]);
1538                         break;
1539                 }
1540         }
1541
1542         return length;
1543 }
1544 /* }}} */
1545
1546 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1547 /* {{{ curl_fnmatch
1548  */
1549 static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
1550 {
1551         php_curl *ch = (php_curl *) ctx;
1552         php_curl_fnmatch *t = ch->handlers->fnmatch;
1553         int rval = CURL_FNMATCHFUNC_FAIL;
1554         switch (t->method) {
1555                 case PHP_CURL_USER: {
1556                         zval argv[3];
1557                         zval retval;
1558                         int  error;
1559                         zend_fcall_info fci;
1560
1561                         GC_ADDREF(ch->res);
1562                         ZVAL_RES(&argv[0], ch->res);
1563                         ZVAL_STRING(&argv[1], pattern);
1564                         ZVAL_STRING(&argv[2], string);
1565
1566                         fci.size = sizeof(fci);
1567                         ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1568                         fci.object = NULL;
1569                         fci.retval = &retval;
1570                         fci.param_count = 3;
1571                         fci.params = argv;
1572                         fci.no_separation = 0;
1573
1574                         ch->in_callback = 1;
1575                         error = zend_call_function(&fci, &t->fci_cache);
1576                         ch->in_callback = 0;
1577                         if (error == FAILURE) {
1578                                 php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION");
1579                         } else if (!Z_ISUNDEF(retval)) {
1580                                 _php_curl_verify_handlers(ch, 1);
1581                                 rval = zval_get_long(&retval);
1582                         }
1583                         zval_ptr_dtor(&argv[0]);
1584                         zval_ptr_dtor(&argv[1]);
1585                         zval_ptr_dtor(&argv[2]);
1586                         break;
1587                 }
1588         }
1589         return rval;
1590 }
1591 /* }}} */
1592 #endif
1593
1594 /* {{{ curl_progress
1595  */
1596 static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
1597 {
1598         php_curl *ch = (php_curl *)clientp;
1599         php_curl_progress *t = ch->handlers->progress;
1600         size_t  rval = 0;
1601
1602 #if PHP_CURL_DEBUG
1603         fprintf(stderr, "curl_progress() called\n");
1604         fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
1605 #endif
1606
1607         switch (t->method) {
1608                 case PHP_CURL_USER: {
1609                         zval argv[5];
1610                         zval retval;
1611                         int  error;
1612                         zend_fcall_info fci;
1613
1614                         GC_ADDREF(ch->res);
1615                         ZVAL_RES(&argv[0], ch->res);
1616                         ZVAL_LONG(&argv[1], (zend_long)dltotal);
1617                         ZVAL_LONG(&argv[2], (zend_long)dlnow);
1618                         ZVAL_LONG(&argv[3], (zend_long)ultotal);
1619                         ZVAL_LONG(&argv[4], (zend_long)ulnow);
1620
1621                         fci.size = sizeof(fci);
1622                         ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1623                         fci.object = NULL;
1624                         fci.retval = &retval;
1625                         fci.param_count = 5;
1626                         fci.params = argv;
1627                         fci.no_separation = 0;
1628
1629                         ch->in_callback = 1;
1630                         error = zend_call_function(&fci, &t->fci_cache);
1631                         ch->in_callback = 0;
1632                         if (error == FAILURE) {
1633                                 php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
1634                         } else if (!Z_ISUNDEF(retval)) {
1635                                 _php_curl_verify_handlers(ch, 1);
1636                                 if (0 != zval_get_long(&retval)) {
1637                                         rval = 1;
1638                                 }
1639                         }
1640                         zval_ptr_dtor(&argv[0]);
1641                         break;
1642                 }
1643         }
1644         return rval;
1645 }
1646 /* }}} */
1647
1648 /* {{{ curl_read
1649  */
1650 static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
1651 {
1652         php_curl *ch = (php_curl *)ctx;
1653         php_curl_read *t = ch->handlers->read;
1654         int length = 0;
1655
1656         switch (t->method) {
1657                 case PHP_CURL_DIRECT:
1658                         if (t->fp) {
1659                                 length = fread(data, size, nmemb, t->fp);
1660                         }
1661                         break;
1662                 case PHP_CURL_USER: {
1663                         zval argv[3];
1664                         zval retval;
1665                         int  error;
1666                         zend_fcall_info fci;
1667
1668                         GC_ADDREF(ch->res);
1669                         ZVAL_RES(&argv[0], ch->res);
1670                         if (t->res) {
1671                                 GC_ADDREF(t->res);
1672                                 ZVAL_RES(&argv[1], t->res);
1673                         } else {
1674                                 ZVAL_NULL(&argv[1]);
1675                         }
1676                         ZVAL_LONG(&argv[2], (int)size * nmemb);
1677
1678                         fci.size = sizeof(fci);
1679                         ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1680                         fci.object = NULL;
1681                         fci.retval = &retval;
1682                         fci.param_count = 3;
1683                         fci.params = argv;
1684                         fci.no_separation = 0;
1685
1686                         ch->in_callback = 1;
1687                         error = zend_call_function(&fci, &t->fci_cache);
1688                         ch->in_callback = 0;
1689                         if (error == FAILURE) {
1690                                 php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
1691                                 length = CURL_READFUNC_ABORT;
1692                         } else if (!Z_ISUNDEF(retval)) {
1693                                 _php_curl_verify_handlers(ch, 1);
1694                                 if (Z_TYPE(retval) == IS_STRING) {
1695                                         length = MIN((int) (size * nmemb), Z_STRLEN(retval));
1696                                         memcpy(data, Z_STRVAL(retval), length);
1697                                 }
1698                                 zval_ptr_dtor(&retval);
1699                         }
1700
1701                         zval_ptr_dtor(&argv[0]);
1702                         zval_ptr_dtor(&argv[1]);
1703                         break;
1704                 }
1705         }
1706
1707         return length;
1708 }
1709 /* }}} */
1710
1711 /* {{{ curl_write_header
1712  */
1713 static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
1714 {
1715         php_curl *ch = (php_curl *) ctx;
1716         php_curl_write *t = ch->handlers->write_header;
1717         size_t length = size * nmemb;
1718
1719         switch (t->method) {
1720                 case PHP_CURL_STDOUT:
1721                         /* Handle special case write when we're returning the entire transfer
1722                          */
1723                         if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
1724                                 smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
1725                         } else {
1726                                 PHPWRITE(data, length);
1727                         }
1728                         break;
1729                 case PHP_CURL_FILE:
1730                         return fwrite(data, size, nmemb, t->fp);
1731                 case PHP_CURL_USER: {
1732                         zval argv[2];
1733                         zval retval;
1734                         int  error;
1735                         zend_fcall_info fci;
1736
1737                         GC_ADDREF(ch->res);
1738                         ZVAL_RES(&argv[0], ch->res);
1739                         ZVAL_STRINGL(&argv[1], data, length);
1740
1741                         fci.size = sizeof(fci);
1742                         ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1743                         fci.object = NULL;
1744                         fci.retval = &retval;
1745                         fci.param_count = 2;
1746                         fci.params = argv;
1747                         fci.no_separation = 0;
1748
1749                         ch->in_callback = 1;
1750                         error = zend_call_function(&fci, &t->fci_cache);
1751                         ch->in_callback = 0;
1752                         if (error == FAILURE) {
1753                                 php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
1754                                 length = -1;
1755                         } else if (!Z_ISUNDEF(retval)) {
1756                                 _php_curl_verify_handlers(ch, 1);
1757                                 length = zval_get_long(&retval);
1758                         }
1759                         zval_ptr_dtor(&argv[0]);
1760                         zval_ptr_dtor(&argv[1]);
1761                         break;
1762                 }
1763
1764                 case PHP_CURL_IGNORE:
1765                         return length;
1766
1767                 default:
1768                         return -1;
1769         }
1770
1771         return length;
1772 }
1773 /* }}} */
1774
1775 static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
1776 {
1777         php_curl *ch = (php_curl *)ctx;
1778
1779         if (type == CURLINFO_HEADER_OUT) {
1780                 if (ch->header.str) {
1781                         zend_string_release_ex(ch->header.str, 0);
1782                 }
1783                 if (buf_len > 0) {
1784                         ch->header.str = zend_string_init(buf, buf_len, 0);
1785                 }
1786         }
1787
1788         return 0;
1789 }
1790 /* }}} */
1791
1792 /* {{{ curl_free_string
1793  */
1794 static void curl_free_string(void **string)
1795 {
1796         efree((char *)*string);
1797 }
1798 /* }}} */
1799
1800 /* {{{ curl_free_post
1801  */
1802 static void curl_free_post(void **post)
1803 {
1804 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
1805         curl_mime_free((curl_mime *)*post);
1806 #else
1807         curl_formfree((struct HttpPost *)*post);
1808 #endif
1809 }
1810 /* }}} */
1811
1812 /* {{{ curl_free_stream
1813  */
1814 static void curl_free_stream(void **post)
1815 {
1816         php_stream_close((php_stream *)*post);
1817 }
1818 /* }}} */
1819
1820 /* {{{ curl_free_slist
1821  */
1822 static void curl_free_slist(zval *el)
1823 {
1824         curl_slist_free_all(((struct curl_slist *)Z_PTR_P(el)));
1825 }
1826 /* }}} */
1827
1828 /* {{{ proto array curl_version([int version])
1829    Return cURL version information. */
1830 PHP_FUNCTION(curl_version)
1831 {
1832         curl_version_info_data *d;
1833         zend_long uversion = CURLVERSION_NOW;
1834
1835         ZEND_PARSE_PARAMETERS_START(0, 1)
1836                 Z_PARAM_OPTIONAL
1837                 Z_PARAM_LONG(uversion)
1838         ZEND_PARSE_PARAMETERS_END();
1839
1840         d = curl_version_info(uversion);
1841         if (d == NULL) {
1842                 RETURN_FALSE;
1843         }
1844
1845         array_init(return_value);
1846
1847         CAAL("version_number", d->version_num);
1848         CAAL("age", d->age);
1849         CAAL("features", d->features);
1850         CAAL("ssl_version_number", d->ssl_version_num);
1851         CAAS("version", d->version);
1852         CAAS("host", d->host);
1853         CAAS("ssl_version", d->ssl_version);
1854         CAAS("libz_version", d->libz_version);
1855         /* Add an array of protocols */
1856         {
1857                 char **p = (char **) d->protocols;
1858                 zval protocol_list;
1859
1860                 array_init(&protocol_list);
1861
1862                 while (*p != NULL) {
1863                         add_next_index_string(&protocol_list, *p);
1864                         p++;
1865                 }
1866                 CAAZ("protocols", &protocol_list);
1867         }
1868         if (d->age >= 1) {
1869                 CAAS("ares", d->ares);
1870                 CAAL("ares_num", d->ares_num);
1871         }
1872         if (d->age >= 2) {
1873                 CAAS("libidn", d->libidn);
1874         }
1875 #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
1876         if (d->age >= 3) {
1877                 CAAL("iconv_ver_num", d->iconv_ver_num);
1878                 CAAS("libssh_version", d->libssh_version);
1879         }
1880 #endif
1881 #if LIBCURL_VERSION_NUM >= 0x073900 /* Available since 7.57.0 */
1882         if (d->age >= 4) {
1883                 CAAL("brotli_ver_num", d->brotli_ver_num);
1884                 CAAS("brotli_version", d->brotli_version);
1885         }
1886 #endif
1887 }
1888 /* }}} */
1889
1890 /* {{{ alloc_curl_handle
1891  */
1892 php_curl *alloc_curl_handle()
1893 {
1894         php_curl *ch               = ecalloc(1, sizeof(php_curl));
1895         ch->to_free                = ecalloc(1, sizeof(struct _php_curl_free));
1896         ch->handlers               = ecalloc(1, sizeof(php_curl_handlers));
1897         ch->handlers->write        = ecalloc(1, sizeof(php_curl_write));
1898         ch->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
1899         ch->handlers->read         = ecalloc(1, sizeof(php_curl_read));
1900         ch->handlers->progress     = NULL;
1901 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1902         ch->handlers->fnmatch      = NULL;
1903 #endif
1904         ch->clone                                  = emalloc(sizeof(uint32_t));
1905         *ch->clone                 = 1;
1906
1907         memset(&ch->err, 0, sizeof(struct _php_curl_error));
1908
1909         zend_llist_init(&ch->to_free->str,   sizeof(char *),          (llist_dtor_func_t)curl_free_string, 0);
1910         zend_llist_init(&ch->to_free->post,  sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post,   0);
1911         zend_llist_init(&ch->to_free->stream, sizeof(php_stream *),   (llist_dtor_func_t)curl_free_stream, 0);
1912
1913         ch->to_free->slist = emalloc(sizeof(HashTable));
1914         zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0);
1915
1916         return ch;
1917 }
1918 /* }}} */
1919
1920 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
1921 /* {{{ create_certinfo
1922  */
1923 static void create_certinfo(struct curl_certinfo *ci, zval *listcode)
1924 {
1925         int i;
1926
1927         if (ci) {
1928                 zval certhash;
1929
1930                 for (i=0; i<ci->num_of_certs; i++) {
1931                         struct curl_slist *slist;
1932
1933                         array_init(&certhash);
1934                         for (slist = ci->certinfo[i]; slist; slist = slist->next) {
1935                                 int len;
1936                                 char s[64];
1937                                 char *tmp;
1938                                 strncpy(s, slist->data, sizeof(s));
1939                                 s[sizeof(s)-1] = '\0';
1940                                 tmp = memchr(s, ':', sizeof(s));
1941                                 if(tmp) {
1942                                         *tmp = '\0';
1943                                         len = strlen(s);
1944                                         add_assoc_string(&certhash, s, &slist->data[len+1]);
1945                                 } else {
1946                                         php_error_docref(NULL, E_WARNING, "Could not extract hash key from certificate info");
1947                                 }
1948                         }
1949                         add_next_index_zval(listcode, &certhash);
1950                 }
1951         }
1952 }
1953 /* }}} */
1954 #endif
1955
1956 /* {{{ _php_curl_set_default_options()
1957    Set default options for a handle */
1958 static void _php_curl_set_default_options(php_curl *ch)
1959 {
1960         char *cainfo;
1961
1962         curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS,        1);
1963         curl_easy_setopt(ch->cp, CURLOPT_VERBOSE,           0);
1964         curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
1965         curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION,     curl_write);
1966         curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
1967         curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION,      curl_read);
1968         curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
1969         curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION,    curl_write_header);
1970         curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
1971 #if !defined(ZTS)
1972         curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
1973 #endif
1974         curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
1975         curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
1976
1977         cainfo = INI_STR("openssl.cafile");
1978         if (!(cainfo && cainfo[0] != '\0')) {
1979                 cainfo = INI_STR("curl.cainfo");
1980         }
1981         if (cainfo && cainfo[0] != '\0') {
1982                 curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
1983         }
1984
1985 #if defined(ZTS)
1986         curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
1987 #endif
1988 }
1989 /* }}} */
1990
1991 /* {{{ proto resource curl_init([string url])
1992    Initialize a cURL session */
1993 PHP_FUNCTION(curl_init)
1994 {
1995         php_curl *ch;
1996         CURL     *cp;
1997         zend_string *url = NULL;
1998
1999         ZEND_PARSE_PARAMETERS_START(0,1)
2000                 Z_PARAM_OPTIONAL
2001                 Z_PARAM_STR(url)
2002         ZEND_PARSE_PARAMETERS_END();
2003
2004         cp = curl_easy_init();
2005         if (!cp) {
2006                 php_error_docref(NULL, E_WARNING, "Could not initialize a new cURL handle");
2007                 RETURN_FALSE;
2008         }
2009
2010         ch = alloc_curl_handle();
2011
2012         ch->cp = cp;
2013
2014         ch->handlers->write->method = PHP_CURL_STDOUT;
2015         ch->handlers->read->method  = PHP_CURL_DIRECT;
2016         ch->handlers->write_header->method = PHP_CURL_IGNORE;
2017
2018         _php_curl_set_default_options(ch);
2019
2020         if (url) {
2021                 if (php_curl_option_url(ch, ZSTR_VAL(url), ZSTR_LEN(url)) == FAILURE) {
2022                         _php_curl_close_ex(ch);
2023                         RETURN_FALSE;
2024                 }
2025         }
2026
2027         ZVAL_RES(return_value, zend_register_resource(ch, le_curl));
2028         ch->res = Z_RES_P(return_value);
2029 }
2030 /* }}} */
2031
2032 void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
2033 {
2034         if (!Z_ISUNDEF(source->handlers->write->stream)) {
2035                 Z_ADDREF(source->handlers->write->stream);
2036         }
2037         ch->handlers->write->stream = source->handlers->write->stream;
2038         ch->handlers->write->method = source->handlers->write->method;
2039         if (!Z_ISUNDEF(source->handlers->read->stream)) {
2040                 Z_ADDREF(source->handlers->read->stream);
2041         }
2042         ch->handlers->read->stream  = source->handlers->read->stream;
2043         ch->handlers->read->method  = source->handlers->read->method;
2044         ch->handlers->write_header->method = source->handlers->write_header->method;
2045         if (!Z_ISUNDEF(source->handlers->write_header->stream)) {
2046                 Z_ADDREF(source->handlers->write_header->stream);
2047         }
2048         ch->handlers->write_header->stream = source->handlers->write_header->stream;
2049
2050         ch->handlers->write->fp = source->handlers->write->fp;
2051         ch->handlers->write_header->fp = source->handlers->write_header->fp;
2052         ch->handlers->read->fp = source->handlers->read->fp;
2053         ch->handlers->read->res = source->handlers->read->res;
2054 #if CURLOPT_PASSWDDATA != 0
2055         if (!Z_ISUNDEF(source->handlers->passwd)) {
2056                 ZVAL_COPY(&ch->handlers->passwd, &source->handlers->passwd);
2057                 curl_easy_setopt(source->cp, CURLOPT_PASSWDDATA, (void *) ch);
2058         }
2059 #endif
2060         if (!Z_ISUNDEF(source->handlers->write->func_name)) {
2061                 ZVAL_COPY(&ch->handlers->write->func_name, &source->handlers->write->func_name);
2062         }
2063         if (!Z_ISUNDEF(source->handlers->read->func_name)) {
2064                 ZVAL_COPY(&ch->handlers->read->func_name, &source->handlers->read->func_name);
2065         }
2066         if (!Z_ISUNDEF(source->handlers->write_header->func_name)) {
2067                 ZVAL_COPY(&ch->handlers->write_header->func_name, &source->handlers->write_header->func_name);
2068         }
2069
2070         curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
2071         curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
2072         curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
2073         curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
2074
2075         if (source->handlers->progress) {
2076                 ch->handlers->progress = ecalloc(1, sizeof(php_curl_progress));
2077                 if (!Z_ISUNDEF(source->handlers->progress->func_name)) {
2078                         ZVAL_COPY(&ch->handlers->progress->func_name, &source->handlers->progress->func_name);
2079                 }
2080                 ch->handlers->progress->method = source->handlers->progress->method;
2081                 curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, (void *) ch);
2082         }
2083
2084 #if LIBCURL_VERSION_NUM >= 0x071500
2085         if (source->handlers->fnmatch) {
2086                 ch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch));
2087                 if (!Z_ISUNDEF(source->handlers->fnmatch->func_name)) {
2088                         ZVAL_COPY(&ch->handlers->fnmatch->func_name, &source->handlers->fnmatch->func_name);
2089                 }
2090                 ch->handlers->fnmatch->method = source->handlers->fnmatch->method;
2091                 curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, (void *) ch);
2092         }
2093 #endif
2094
2095         efree(ch->to_free->slist);
2096         efree(ch->to_free);
2097         ch->to_free = source->to_free;
2098         efree(ch->clone);
2099         ch->clone = source->clone;
2100
2101         /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
2102         (*source->clone)++;
2103 }
2104
2105 /* {{{ proto resource curl_copy_handle(resource ch)
2106    Copy a cURL handle along with all of it's preferences */
2107 PHP_FUNCTION(curl_copy_handle)
2108 {
2109         CURL            *cp;
2110         zval            *zid;
2111         php_curl        *ch, *dupch;
2112
2113         ZEND_PARSE_PARAMETERS_START(1,1)
2114                 Z_PARAM_RESOURCE(zid)
2115         ZEND_PARSE_PARAMETERS_END();
2116
2117         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
2118                 RETURN_FALSE;
2119         }
2120
2121         cp = curl_easy_duphandle(ch->cp);
2122         if (!cp) {
2123                 php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle");
2124                 RETURN_FALSE;
2125         }
2126
2127         dupch = alloc_curl_handle();
2128         dupch->cp = cp;
2129
2130         _php_setup_easy_copy_handlers(dupch, ch);
2131
2132         Z_ADDREF_P(zid);
2133
2134         ZVAL_RES(return_value, zend_register_resource(dupch, le_curl));
2135         dupch->res = Z_RES_P(return_value);
2136 }
2137 /* }}} */
2138
2139 #if LIBCURL_VERSION_NUM >= 0x073800
2140 static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */
2141 {
2142         php_stream *stream = (php_stream *) arg;
2143         size_t numread = php_stream_read(stream, buffer, nitems * size);
2144
2145         if (numread == (size_t)-1) {
2146                 return CURL_READFUNC_ABORT;
2147         }
2148         return numread;
2149 }
2150 /* }}} */
2151
2152 static int seek_cb(void *arg, curl_off_t offset, int origin) /* {{{ */
2153 {
2154         php_stream *stream = (php_stream *) arg;
2155         int res = php_stream_seek(stream, offset, origin);
2156
2157         if (res) {
2158                 return CURL_SEEKFUNC_CANTSEEK;
2159         }
2160         return CURL_SEEKFUNC_OK;
2161 }
2162 /* }}} */
2163 #endif
2164
2165 static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ */
2166 {
2167         CURLcode error = CURLE_OK;
2168         zend_long lval;
2169
2170         switch (option) {
2171                 /* Long options */
2172                 case CURLOPT_SSL_VERIFYHOST:
2173                         lval = zval_get_long(zvalue);
2174                         if (lval == 1) {
2175 #if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */
2176                                 php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl 7.28.1. It is recommended to use value 2 instead");
2177 #else
2178                                 php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead");
2179                                 error = curl_easy_setopt(ch->cp, option, 2);
2180                                 break;
2181 #endif
2182                         }
2183                 case CURLOPT_AUTOREFERER:
2184                 case CURLOPT_BUFFERSIZE:
2185                 case CURLOPT_CONNECTTIMEOUT:
2186                 case CURLOPT_COOKIESESSION:
2187                 case CURLOPT_CRLF:
2188                 case CURLOPT_DNS_CACHE_TIMEOUT:
2189                 case CURLOPT_DNS_USE_GLOBAL_CACHE:
2190                 case CURLOPT_FAILONERROR:
2191                 case CURLOPT_FILETIME:
2192                 case CURLOPT_FORBID_REUSE:
2193                 case CURLOPT_FRESH_CONNECT:
2194                 case CURLOPT_FTP_USE_EPRT:
2195                 case CURLOPT_FTP_USE_EPSV:
2196                 case CURLOPT_HEADER:
2197                 case CURLOPT_HTTPGET:
2198                 case CURLOPT_HTTPPROXYTUNNEL:
2199                 case CURLOPT_HTTP_VERSION:
2200                 case CURLOPT_INFILESIZE:
2201                 case CURLOPT_LOW_SPEED_LIMIT:
2202                 case CURLOPT_LOW_SPEED_TIME:
2203                 case CURLOPT_MAXCONNECTS:
2204                 case CURLOPT_MAXREDIRS:
2205                 case CURLOPT_NETRC:
2206                 case CURLOPT_NOBODY:
2207                 case CURLOPT_NOPROGRESS:
2208                 case CURLOPT_NOSIGNAL:
2209                 case CURLOPT_PORT:
2210                 case CURLOPT_POST:
2211                 case CURLOPT_PROXYPORT:
2212                 case CURLOPT_PROXYTYPE:
2213                 case CURLOPT_PUT:
2214                 case CURLOPT_RESUME_FROM:
2215                 case CURLOPT_SSLVERSION:
2216                 case CURLOPT_SSL_VERIFYPEER:
2217                 case CURLOPT_TIMECONDITION:
2218                 case CURLOPT_TIMEOUT:
2219                 case CURLOPT_TIMEVALUE:
2220                 case CURLOPT_TRANSFERTEXT:
2221                 case CURLOPT_UNRESTRICTED_AUTH:
2222                 case CURLOPT_UPLOAD:
2223                 case CURLOPT_VERBOSE:
2224                 case CURLOPT_HTTPAUTH:
2225                 case CURLOPT_FTP_CREATE_MISSING_DIRS:
2226                 case CURLOPT_PROXYAUTH:
2227                 case CURLOPT_FTP_RESPONSE_TIMEOUT:
2228                 case CURLOPT_IPRESOLVE:
2229                 case CURLOPT_MAXFILESIZE:
2230                 case CURLOPT_TCP_NODELAY:
2231                 case CURLOPT_FTPSSLAUTH:
2232                 case CURLOPT_IGNORE_CONTENT_LENGTH:
2233                 case CURLOPT_FTP_SKIP_PASV_IP:
2234                 case CURLOPT_FTP_FILEMETHOD:
2235                 case CURLOPT_CONNECT_ONLY:
2236                 case CURLOPT_LOCALPORT:
2237                 case CURLOPT_LOCALPORTRANGE:
2238 #if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */
2239                 case CURLOPT_SSL_SESSIONID_CACHE:
2240 #endif
2241 #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
2242                 case CURLOPT_FTP_SSL_CCC:
2243                 case CURLOPT_SSH_AUTH_TYPES:
2244 #endif
2245 #if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */
2246                 case CURLOPT_CONNECTTIMEOUT_MS:
2247                 case CURLOPT_HTTP_CONTENT_DECODING:
2248                 case CURLOPT_HTTP_TRANSFER_DECODING:
2249                 case CURLOPT_TIMEOUT_MS:
2250 #endif
2251 #if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
2252                 case CURLOPT_NEW_DIRECTORY_PERMS:
2253                 case CURLOPT_NEW_FILE_PERMS:
2254 #endif
2255 #if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */
2256                 case CURLOPT_USE_SSL:
2257                 case CURLOPT_APPEND:
2258                 case CURLOPT_DIRLISTONLY:
2259 #else
2260                 case CURLOPT_FTP_SSL:
2261                 case CURLOPT_FTPAPPEND:
2262                 case CURLOPT_FTPLISTONLY:
2263 #endif
2264 #if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
2265                 case CURLOPT_PROXY_TRANSFER_MODE:
2266 #endif
2267 #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
2268                 case CURLOPT_ADDRESS_SCOPE:
2269 #endif
2270 #if LIBCURL_VERSION_NUM >  0x071301 /* Available since 7.19.1 */
2271                 case CURLOPT_CERTINFO:
2272 #endif
2273 #if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
2274                 case CURLOPT_PROTOCOLS:
2275                 case CURLOPT_REDIR_PROTOCOLS:
2276                 case CURLOPT_SOCKS5_GSSAPI_NEC:
2277                 case CURLOPT_TFTP_BLKSIZE:
2278 #endif
2279 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2280                 case CURLOPT_FTP_USE_PRET:
2281                 case CURLOPT_RTSP_CLIENT_CSEQ:
2282                 case CURLOPT_RTSP_REQUEST:
2283                 case CURLOPT_RTSP_SERVER_CSEQ:
2284 #endif
2285 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
2286                 case CURLOPT_WILDCARDMATCH:
2287 #endif
2288 #if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
2289                 case CURLOPT_TLSAUTH_TYPE:
2290 #endif
2291 #if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */
2292                 case CURLOPT_GSSAPI_DELEGATION:
2293 #endif
2294 #if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
2295                 case CURLOPT_ACCEPTTIMEOUT_MS:
2296 #endif
2297 #if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
2298                 case CURLOPT_SSL_OPTIONS:
2299                 case CURLOPT_TCP_KEEPALIVE:
2300                 case CURLOPT_TCP_KEEPIDLE:
2301                 case CURLOPT_TCP_KEEPINTVL:
2302 #endif
2303 #if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */
2304                 case CURLOPT_SASL_IR:
2305 #endif
2306 #if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */
2307                 case CURLOPT_EXPECT_100_TIMEOUT_MS:
2308                 case CURLOPT_SSL_ENABLE_ALPN:
2309                 case CURLOPT_SSL_ENABLE_NPN:
2310 #endif
2311 #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2312                 case CURLOPT_HEADEROPT:
2313 #endif
2314 #if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */
2315                 case CURLOPT_SSL_VERIFYSTATUS:
2316 #endif
2317 #if LIBCURL_VERSION_NUM >= 0x072a00 /* Available since 7.42.0 */
2318                 case CURLOPT_PATH_AS_IS:
2319                 case CURLOPT_SSL_FALSESTART:
2320 #endif
2321 #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
2322                 case CURLOPT_PIPEWAIT:
2323 #endif
2324 #if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */
2325                 case CURLOPT_STREAM_WEIGHT:
2326 #endif
2327 #if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */
2328                 case CURLOPT_TFTP_NO_OPTIONS:
2329 #endif
2330 #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2331                 case CURLOPT_TCP_FASTOPEN:
2332 #endif
2333 #if LIBCURL_VERSION_NUM >= 0x073300 /* Available since 7.51.0 */
2334                 case CURLOPT_KEEP_SENDING_ON_ERROR:
2335 #endif
2336 #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
2337                 case CURLOPT_PROXY_SSL_OPTIONS:
2338                 case CURLOPT_PROXY_SSL_VERIFYHOST:
2339                 case CURLOPT_PROXY_SSL_VERIFYPEER:
2340                 case CURLOPT_PROXY_SSLVERSION:
2341 #endif
2342 #if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */
2343                 case CURLOPT_SUPPRESS_CONNECT_HEADERS:
2344 #endif
2345 #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
2346                 case CURLOPT_SOCKS5_AUTH:
2347 #endif
2348 #if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */
2349                 case CURLOPT_SSH_COMPRESSION:
2350 #endif
2351 #if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
2352                 case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
2353 #endif
2354 #if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */
2355                 case CURLOPT_DNS_SHUFFLE_ADDRESSES:
2356                 case CURLOPT_HAPROXYPROTOCOL:
2357 #endif
2358 #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
2359                 case CURLOPT_DISALLOW_USERNAME_IN_URL:
2360 #endif
2361                         lval = zval_get_long(zvalue);
2362 #if LIBCURL_VERSION_NUM >= 0x071304
2363                         if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
2364                                 (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) {
2365                                         php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set");
2366                                         return 1;
2367                         }
2368 #endif
2369 # if defined(ZTS)
2370                         if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) {
2371                                 php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled");
2372                                 return 1;
2373                         }
2374 # endif
2375                         error = curl_easy_setopt(ch->cp, option, lval);
2376                         break;
2377                 case CURLOPT_SAFE_UPLOAD:
2378                         if (!zend_is_true(zvalue)) {
2379                                 php_error_docref(NULL, E_WARNING, "Disabling safe uploads is no longer supported");
2380                                 return FAILURE;
2381                         }
2382                         break;
2383
2384                 /* String options */
2385                 case CURLOPT_CAINFO:
2386                 case CURLOPT_CAPATH:
2387                 case CURLOPT_COOKIE:
2388                 case CURLOPT_EGDSOCKET:
2389                 case CURLOPT_INTERFACE:
2390                 case CURLOPT_PROXY:
2391                 case CURLOPT_PROXYUSERPWD:
2392                 case CURLOPT_REFERER:
2393                 case CURLOPT_SSLCERTTYPE:
2394                 case CURLOPT_SSLENGINE:
2395                 case CURLOPT_SSLENGINE_DEFAULT:
2396                 case CURLOPT_SSLKEY:
2397                 case CURLOPT_SSLKEYPASSWD:
2398                 case CURLOPT_SSLKEYTYPE:
2399                 case CURLOPT_SSL_CIPHER_LIST:
2400                 case CURLOPT_USERAGENT:
2401                 case CURLOPT_USERPWD:
2402                 case CURLOPT_COOKIELIST:
2403                 case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2404 #if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */
2405                 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2406 #endif
2407 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
2408                 case CURLOPT_PASSWORD:
2409                 case CURLOPT_PROXYPASSWORD:
2410                 case CURLOPT_PROXYUSERNAME:
2411                 case CURLOPT_USERNAME:
2412 #endif
2413 #if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
2414                 case CURLOPT_NOPROXY:
2415                 case CURLOPT_SOCKS5_GSSAPI_SERVICE:
2416 #endif
2417 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2418                 case CURLOPT_MAIL_FROM:
2419                 case CURLOPT_RTSP_STREAM_URI:
2420                 case CURLOPT_RTSP_TRANSPORT:
2421 #endif
2422 #if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
2423                 case CURLOPT_TLSAUTH_PASSWORD:
2424                 case CURLOPT_TLSAUTH_USERNAME:
2425 #endif
2426 #if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */
2427                 case CURLOPT_ACCEPT_ENCODING:
2428                 case CURLOPT_TRANSFER_ENCODING:
2429 #else
2430                 case CURLOPT_ENCODING:
2431 #endif
2432 #if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
2433                 case CURLOPT_DNS_SERVERS:
2434 #endif
2435 #if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
2436                 case CURLOPT_MAIL_AUTH:
2437 #endif
2438 #if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */
2439                 case CURLOPT_LOGIN_OPTIONS:
2440 #endif
2441 #if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
2442                 case CURLOPT_PINNEDPUBLICKEY:
2443 #endif
2444 #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
2445                 case CURLOPT_PROXY_SERVICE_NAME:
2446                 case CURLOPT_SERVICE_NAME:
2447 #endif
2448 #if LIBCURL_VERSION_NUM >= 0x072d00 /* Available since 7.45.0 */
2449                 case CURLOPT_DEFAULT_PROTOCOL:
2450 #endif
2451 #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
2452                 case CURLOPT_PRE_PROXY:
2453                 case CURLOPT_PROXY_CAINFO:
2454                 case CURLOPT_PROXY_CAPATH:
2455                 case CURLOPT_PROXY_CRLFILE:
2456                 case CURLOPT_PROXY_KEYPASSWD:
2457                 case CURLOPT_PROXY_PINNEDPUBLICKEY:
2458                 case CURLOPT_PROXY_SSL_CIPHER_LIST:
2459                 case CURLOPT_PROXY_SSLCERT:
2460                 case CURLOPT_PROXY_SSLCERTTYPE:
2461                 case CURLOPT_PROXY_SSLKEY:
2462                 case CURLOPT_PROXY_SSLKEYTYPE:
2463                 case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2464                 case CURLOPT_PROXY_TLSAUTH_TYPE:
2465                 case CURLOPT_PROXY_TLSAUTH_USERNAME:
2466 #endif
2467 #if LIBCURL_VERSION_NUM >= 0x073500 /* Available since 7.53.0 */
2468                 case CURLOPT_ABSTRACT_UNIX_SOCKET:
2469 #endif
2470 #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
2471                 case CURLOPT_REQUEST_TARGET:
2472 #endif
2473 #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
2474                 case CURLOPT_PROXY_TLS13_CIPHERS:
2475                 case CURLOPT_TLS13_CIPHERS:
2476 #endif
2477                 {
2478                         zend_string *tmp_str;
2479                         zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2480                         int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2481                         zend_tmp_string_release(tmp_str);
2482                         return ret;
2483                 }
2484
2485                 /* Curl nullable string options */
2486                 case CURLOPT_CUSTOMREQUEST:
2487                 case CURLOPT_FTPPORT:
2488                 case CURLOPT_RANGE:
2489                 case CURLOPT_FTP_ACCOUNT:
2490 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2491                 case CURLOPT_RTSP_SESSION_ID:
2492 #endif
2493 #if LIBCURL_VERSION_NUM >= 0x072100 /* Available since 7.33.0 */
2494                 case CURLOPT_DNS_INTERFACE:
2495                 case CURLOPT_DNS_LOCAL_IP4:
2496                 case CURLOPT_DNS_LOCAL_IP6:
2497                 case CURLOPT_XOAUTH2_BEARER:
2498 #endif
2499 #if LIBCURL_VERSION_NUM >= 0x072800 /* Available since 7.40.0 */
2500                 case CURLOPT_UNIX_SOCKET_PATH:
2501 #endif
2502 #if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
2503                 case CURLOPT_KRBLEVEL:
2504 #else
2505                 case CURLOPT_KRB4LEVEL:
2506 #endif
2507                 {
2508                         if (Z_ISNULL_P(zvalue)) {
2509                                 error = curl_easy_setopt(ch->cp, option, NULL);
2510                         } else {
2511                                 zend_string *tmp_str;
2512                                 zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2513                                 int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2514                                 zend_tmp_string_release(tmp_str);
2515                                 return ret;
2516                         }
2517                         break;
2518                 }
2519
2520                 /* Curl private option */
2521                 case CURLOPT_PRIVATE:
2522                 {
2523                         zend_string *tmp_str;
2524                         zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2525                         int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1);
2526                         zend_tmp_string_release(tmp_str);
2527                         return ret;
2528                 }
2529
2530                 /* Curl url option */
2531                 case CURLOPT_URL:
2532                 {
2533                         zend_string *tmp_str;
2534                         zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2535                         int ret = php_curl_option_url(ch, ZSTR_VAL(str), ZSTR_LEN(str));
2536                         zend_tmp_string_release(tmp_str);
2537                         return ret;
2538                 }
2539
2540                 /* Curl file handle options */
2541                 case CURLOPT_FILE:
2542                 case CURLOPT_INFILE:
2543                 case CURLOPT_STDERR:
2544                 case CURLOPT_WRITEHEADER: {
2545                         FILE *fp = NULL;
2546                         php_stream *what = NULL;
2547
2548                         if (Z_TYPE_P(zvalue) != IS_NULL) {
2549                                 what = (php_stream *)zend_fetch_resource2_ex(zvalue, "File-Handle", php_file_le_stream(), php_file_le_pstream());
2550                                 if (!what) {
2551                                         return FAILURE;
2552                                 }
2553
2554                                 if (FAILURE == php_stream_cast(what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
2555                                         return FAILURE;
2556                                 }
2557
2558                                 if (!fp) {
2559                                         return FAILURE;
2560                                 }
2561                         }
2562
2563                         error = CURLE_OK;
2564                         switch (option) {
2565                                 case CURLOPT_FILE:
2566                                         if (!what) {
2567                                                 if (!Z_ISUNDEF(ch->handlers->write->stream)) {
2568                                                         zval_ptr_dtor(&ch->handlers->write->stream);
2569                                                         ZVAL_UNDEF(&ch->handlers->write->stream);
2570                                                 }
2571                                                 ch->handlers->write->fp = NULL;
2572                                                 ch->handlers->write->method = PHP_CURL_STDOUT;
2573                                         } else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2574                                                 zval_ptr_dtor(&ch->handlers->write->stream);
2575                                                 ch->handlers->write->fp = fp;
2576                                                 ch->handlers->write->method = PHP_CURL_FILE;
2577                                                 ZVAL_COPY(&ch->handlers->write->stream, zvalue);
2578                                         } else {
2579                                                 php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2580                                                 return FAILURE;
2581                                         }
2582                                         break;
2583                                 case CURLOPT_WRITEHEADER:
2584                                         if (!what) {
2585                                                 if (!Z_ISUNDEF(ch->handlers->write_header->stream)) {
2586                                                         zval_ptr_dtor(&ch->handlers->write_header->stream);
2587                                                         ZVAL_UNDEF(&ch->handlers->write_header->stream);
2588                                                 }
2589                                                 ch->handlers->write_header->fp = NULL;
2590                                                 ch->handlers->write_header->method = PHP_CURL_IGNORE;
2591                                         } else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2592                                                 zval_ptr_dtor(&ch->handlers->write_header->stream);
2593                                                 ch->handlers->write_header->fp = fp;
2594                                                 ch->handlers->write_header->method = PHP_CURL_FILE;
2595                                                 ZVAL_COPY(&ch->handlers->write_header->stream, zvalue);
2596                                         } else {
2597                                                 php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2598                                                 return FAILURE;
2599                                         }
2600                                         break;
2601                                 case CURLOPT_INFILE:
2602                                         if (!what) {
2603                                                 if (!Z_ISUNDEF(ch->handlers->read->stream)) {
2604                                                         zval_ptr_dtor(&ch->handlers->read->stream);
2605                                                         ZVAL_UNDEF(&ch->handlers->read->stream);
2606                                                 }
2607                                                 ch->handlers->read->fp = NULL;
2608                                                 ch->handlers->read->res = NULL;
2609                                         } else {
2610                                                 zval_ptr_dtor(&ch->handlers->read->stream);
2611                                                 ch->handlers->read->fp = fp;
2612                                                 ch->handlers->read->res = Z_RES_P(zvalue);
2613                                                 ZVAL_COPY(&ch->handlers->read->stream, zvalue);
2614                                         }
2615                                         break;
2616                                 case CURLOPT_STDERR:
2617                                         if (!what) {
2618                                                 if (!Z_ISUNDEF(ch->handlers->std_err)) {
2619                                                         zval_ptr_dtor(&ch->handlers->std_err);
2620                                                         ZVAL_UNDEF(&ch->handlers->std_err);
2621                                                 }
2622                                         } else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2623                                                 zval_ptr_dtor(&ch->handlers->std_err);
2624                                                 ZVAL_COPY(&ch->handlers->std_err, zvalue);
2625                                         } else {
2626                                                 php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2627                                                 return FAILURE;
2628                                         }
2629                                         /* break omitted intentionally */
2630                                 default:
2631                                         error = curl_easy_setopt(ch->cp, option, fp);
2632                                         break;
2633                         }
2634                         break;
2635                 }
2636
2637                 /* Curl linked list options */
2638                 case CURLOPT_HTTP200ALIASES:
2639                 case CURLOPT_HTTPHEADER:
2640                 case CURLOPT_POSTQUOTE:
2641                 case CURLOPT_PREQUOTE:
2642                 case CURLOPT_QUOTE:
2643                 case CURLOPT_TELNETOPTIONS:
2644 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2645                 case CURLOPT_MAIL_RCPT:
2646 #endif
2647 #if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
2648                 case CURLOPT_RESOLVE:
2649 #endif
2650 #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2651                 case CURLOPT_PROXYHEADER:
2652 #endif
2653 #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2654                 case CURLOPT_CONNECT_TO:
2655 #endif
2656                 {
2657                         zval *current;
2658                         HashTable *ph;
2659                         zend_string *val, *tmp_val;
2660                         struct curl_slist *slist = NULL;
2661
2662                         ph = HASH_OF(zvalue);
2663                         if (!ph) {
2664                                 char *name = NULL;
2665                                 switch (option) {
2666                                         case CURLOPT_HTTPHEADER:
2667                                                 name = "CURLOPT_HTTPHEADER";
2668                                                 break;
2669                                         case CURLOPT_QUOTE:
2670                                                 name = "CURLOPT_QUOTE";
2671                                                 break;
2672                                         case CURLOPT_HTTP200ALIASES:
2673                                                 name = "CURLOPT_HTTP200ALIASES";
2674                                                 break;
2675                                         case CURLOPT_POSTQUOTE:
2676                                                 name = "CURLOPT_POSTQUOTE";
2677                                                 break;
2678                                         case CURLOPT_PREQUOTE:
2679                                                 name = "CURLOPT_PREQUOTE";
2680                                                 break;
2681                                         case CURLOPT_TELNETOPTIONS:
2682                                                 name = "CURLOPT_TELNETOPTIONS";
2683                                                 break;
2684 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2685                                         case CURLOPT_MAIL_RCPT:
2686                                                 name = "CURLOPT_MAIL_RCPT";
2687                                                 break;
2688 #endif
2689 #if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
2690                                         case CURLOPT_RESOLVE:
2691                                                 name = "CURLOPT_RESOLVE";
2692                                                 break;
2693 #endif
2694 #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2695                                         case CURLOPT_PROXYHEADER:
2696                                                 name = "CURLOPT_PROXYHEADER";
2697                                                 break;
2698 #endif
2699 #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2700                                         case CURLOPT_CONNECT_TO:
2701                                                 name = "CURLOPT_CONNECT_TO";
2702                                                 break;
2703 #endif
2704                                 }
2705                                 php_error_docref(NULL, E_WARNING, "You must pass either an object or an array with the %s argument", name);
2706                                 return FAILURE;
2707                         }
2708
2709                         ZEND_HASH_FOREACH_VAL(ph, current) {
2710                                 ZVAL_DEREF(current);
2711                                 val = zval_get_tmp_string(current, &tmp_val);
2712                                 slist = curl_slist_append(slist, ZSTR_VAL(val));
2713                                 zend_tmp_string_release(tmp_val);
2714                                 if (!slist) {
2715                                         php_error_docref(NULL, E_WARNING, "Could not build curl_slist");
2716                                         return 1;
2717                                 }
2718                         } ZEND_HASH_FOREACH_END();
2719
2720                         if (slist) {
2721                                 if ((*ch->clone) == 1) {
2722                                         zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
2723                                 } else {
2724                                         zend_hash_next_index_insert_ptr(ch->to_free->slist, slist);
2725                                 }
2726                         }
2727
2728                         error = curl_easy_setopt(ch->cp, option, slist);
2729
2730                         break;
2731                 }
2732
2733                 case CURLOPT_BINARYTRANSFER:
2734                         /* Do nothing, just backward compatibility */
2735                         break;
2736
2737                 case CURLOPT_FOLLOWLOCATION:
2738                         lval = zend_is_true(zvalue);
2739 #if LIBCURL_VERSION_NUM < 0x071304
2740                         if (lval && PG(open_basedir) && *PG(open_basedir)) {
2741                                 php_error_docref(NULL, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set");
2742                                 return FAILURE;
2743                         }
2744 #endif
2745                         error = curl_easy_setopt(ch->cp, option, lval);
2746                         break;
2747
2748                 case CURLOPT_HEADERFUNCTION:
2749                         if (!Z_ISUNDEF(ch->handlers->write_header->func_name)) {
2750                                 zval_ptr_dtor(&ch->handlers->write_header->func_name);
2751                                 ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
2752                         }
2753                         ZVAL_COPY(&ch->handlers->write_header->func_name, zvalue);
2754                         ch->handlers->write_header->method = PHP_CURL_USER;
2755                         break;
2756
2757                 case CURLOPT_POSTFIELDS:
2758                         if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) {
2759                                 zval *current;
2760                                 HashTable *postfields;
2761                                 zend_string *string_key;
2762                                 zend_ulong  num_key;
2763 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2764                                 curl_mime *mime;
2765                                 curl_mimepart *part;
2766                                 CURLcode form_error;
2767 #else
2768                                 struct HttpPost *first = NULL;
2769                                 struct HttpPost *last  = NULL;
2770                                 CURLFORMcode form_error;
2771 #endif
2772                                 postfields = HASH_OF(zvalue);
2773                                 if (!postfields) {
2774                                         php_error_docref(NULL, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
2775                                         return FAILURE;
2776                                 }
2777
2778 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2779                                 mime = curl_mime_init(ch->cp);
2780                                 if (mime == NULL) {
2781                                         return FAILURE;
2782                                 }
2783 #endif
2784
2785                                 ZEND_HASH_FOREACH_KEY_VAL(postfields, num_key, string_key, current) {
2786                                         zend_string *postval, *tmp_postval;
2787                                         /* Pretend we have a string_key here */
2788                                         if (!string_key) {
2789                                                 string_key = zend_long_to_str(num_key);
2790                                         } else {
2791                                                 zend_string_addref(string_key);
2792                                         }
2793
2794                                         ZVAL_DEREF(current);
2795                                         if (Z_TYPE_P(current) == IS_OBJECT &&
2796                                                         instanceof_function(Z_OBJCE_P(current), curl_CURLFile_class)) {
2797                                                 /* new-style file upload */
2798                                                 zval *prop, rv;
2799                                                 char *type = NULL, *filename = NULL;
2800 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2801                                                 php_stream *stream;
2802 #endif
2803
2804                                                 prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv);
2805                                                 if (Z_TYPE_P(prop) != IS_STRING) {
2806                                                         php_error_docref(NULL, E_WARNING, "Invalid filename for key %s", ZSTR_VAL(string_key));
2807                                                 } else {
2808                                                         postval = Z_STR_P(prop);
2809
2810                                                         if (php_check_open_basedir(ZSTR_VAL(postval))) {
2811                                                                 return 1;
2812                                                         }
2813
2814                                                         prop = zend_read_property(curl_CURLFile_class, current, "mime", sizeof("mime")-1, 0, &rv);
2815                                                         if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
2816                                                                 type = Z_STRVAL_P(prop);
2817                                                         }
2818                                                         prop = zend_read_property(curl_CURLFile_class, current, "postname", sizeof("postname")-1, 0, &rv);
2819                                                         if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
2820                                                                 filename = Z_STRVAL_P(prop);
2821                                                         }
2822
2823 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2824                                                         if (!(stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", IGNORE_PATH, NULL))) {
2825                                                                 zend_string_release_ex(string_key, 0);
2826                                                                 return FAILURE;
2827                                                         }
2828                                                         part = curl_mime_addpart(mime);
2829                                                         if (part == NULL) {
2830                                                                 php_stream_close(stream);
2831                                                                 zend_string_release_ex(string_key, 0);
2832                                                                 return FAILURE;
2833                                                         }
2834                                                         if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK
2835                                                                 || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, NULL, stream)) != CURLE_OK
2836                                                                 || (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK
2837                                                                 || (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) {
2838                                                                 php_stream_close(stream);
2839                                                                 error = form_error;
2840                                                         }
2841                                                         zend_llist_add_element(&ch->to_free->stream, &stream);
2842 #else
2843                                                         form_error = curl_formadd(&first, &last,
2844                                                                                         CURLFORM_COPYNAME, ZSTR_VAL(string_key),
2845                                                                                         CURLFORM_NAMELENGTH, ZSTR_LEN(string_key),
2846                                                                                         CURLFORM_FILENAME, filename ? filename : ZSTR_VAL(postval),
2847                                                                                         CURLFORM_CONTENTTYPE, type ? type : "application/octet-stream",
2848                                                                                         CURLFORM_FILE, ZSTR_VAL(postval),
2849                                                                                         CURLFORM_END);
2850                                                         if (form_error != CURL_FORMADD_OK) {
2851                                                                 /* Not nice to convert between enums but we only have place for one error type */
2852                                                                 error = (CURLcode)form_error;
2853                                                         }
2854 #endif
2855                                                 }
2856
2857                                                 zend_string_release_ex(string_key, 0);
2858                                                 continue;
2859                                         }
2860
2861                                         postval = zval_get_tmp_string(current, &tmp_postval);
2862
2863 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2864                                         part = curl_mime_addpart(mime);
2865                                         if (part == NULL) {
2866                                                 zend_tmp_string_release(tmp_postval);
2867                                                 zend_string_release_ex(string_key, 0);
2868                                                 return FAILURE;
2869                                         }
2870                                         if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK
2871                                                 || (form_error = curl_mime_data(part, ZSTR_VAL(postval), ZSTR_LEN(postval))) != CURLE_OK) {
2872                                                 error = form_error;
2873                                         }
2874 #else
2875                                         /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
2876                                          * must be explicitly cast to long in curl_formadd
2877                                          * use since curl needs a long not an int. */
2878                                         form_error = curl_formadd(&first, &last,
2879                                                                                  CURLFORM_COPYNAME, ZSTR_VAL(string_key),
2880                                                                                  CURLFORM_NAMELENGTH, ZSTR_LEN(string_key),
2881                                                                                  CURLFORM_COPYCONTENTS, ZSTR_VAL(postval),
2882                                                                                  CURLFORM_CONTENTSLENGTH, ZSTR_LEN(postval),
2883                                                                                  CURLFORM_END);
2884
2885                                         if (form_error != CURL_FORMADD_OK) {
2886                                                 /* Not nice to convert between enums but we only have place for one error type */
2887                                                 error = (CURLcode)form_error;
2888                                         }
2889 #endif
2890                                         zend_tmp_string_release(tmp_postval);
2891                                         zend_string_release_ex(string_key, 0);
2892                                 } ZEND_HASH_FOREACH_END();
2893
2894                                 SAVE_CURL_ERROR(ch, error);
2895                                 if (error != CURLE_OK) {
2896                                         return FAILURE;
2897                                 }
2898
2899                                 if ((*ch->clone) == 1) {
2900                                         zend_llist_clean(&ch->to_free->post);
2901                                 }
2902 #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2903                                 zend_llist_add_element(&ch->to_free->post, &mime);
2904                                 error = curl_easy_setopt(ch->cp, CURLOPT_MIMEPOST, mime);
2905 #else
2906                                 zend_llist_add_element(&ch->to_free->post, &first);
2907                                 error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
2908 #endif
2909                         } else {
2910 #if LIBCURL_VERSION_NUM >= 0x071101
2911                                 zend_string *tmp_str;
2912                                 zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2913                                 /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
2914                                 error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str));
2915                                 error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, ZSTR_VAL(str));
2916                                 zend_tmp_string_release(tmp_str);
2917 #else
2918                                 char *post = NULL;
2919                                 zend_string *tmp_str;
2920                                 zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2921
2922                                 post = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
2923                                 zend_llist_add_element(&ch->to_free->str, &post);
2924
2925                                 curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
2926                                 error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str));
2927                                 zend_tmp_string_release(tmp_str);
2928 #endif
2929                         }
2930                         break;
2931
2932                 case CURLOPT_PROGRESSFUNCTION:
2933                         curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION,      curl_progress);
2934                         curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
2935                         if (ch->handlers->progress == NULL) {
2936                                 ch->handlers->progress = ecalloc(1, sizeof(php_curl_progress));
2937                         } else if (!Z_ISUNDEF(ch->handlers->progress->func_name)) {
2938                                 zval_ptr_dtor(&ch->handlers->progress->func_name);
2939                                 ch->handlers->progress->fci_cache = empty_fcall_info_cache;
2940                         }
2941                         ZVAL_COPY(&ch->handlers->progress->func_name, zvalue);
2942                         ch->handlers->progress->method = PHP_CURL_USER;
2943                         break;
2944
2945                 case CURLOPT_READFUNCTION:
2946                         if (!Z_ISUNDEF(ch->handlers->read->func_name)) {
2947                                 zval_ptr_dtor(&ch->handlers->read->func_name);
2948                                 ch->handlers->read->fci_cache = empty_fcall_info_cache;
2949                         }
2950                         ZVAL_COPY(&ch->handlers->read->func_name, zvalue);
2951                         ch->handlers->read->method = PHP_CURL_USER;
2952                         break;
2953
2954                 case CURLOPT_RETURNTRANSFER:
2955                         if (zend_is_true(zvalue)) {
2956                                 ch->handlers->write->method = PHP_CURL_RETURN;
2957                         } else {
2958                                 ch->handlers->write->method = PHP_CURL_STDOUT;
2959                         }
2960                         break;
2961
2962                 case CURLOPT_WRITEFUNCTION:
2963                         if (!Z_ISUNDEF(ch->handlers->write->func_name)) {
2964                                 zval_ptr_dtor(&ch->handlers->write->func_name);
2965                                 ch->handlers->write->fci_cache = empty_fcall_info_cache;
2966                         }
2967                         ZVAL_COPY(&ch->handlers->write->func_name, zvalue);
2968                         ch->handlers->write->method = PHP_CURL_USER;
2969                         break;
2970
2971                 /* Curl off_t options */
2972                 case CURLOPT_MAX_RECV_SPEED_LARGE:
2973                 case CURLOPT_MAX_SEND_SPEED_LARGE:
2974 #if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
2975                 case CURLOPT_TIMEVALUE_LARGE:
2976 #endif
2977                         lval = zval_get_long(zvalue);
2978                         error = curl_easy_setopt(ch->cp, option, (curl_off_t)lval);
2979                         break;
2980
2981 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
2982                 case CURLOPT_POSTREDIR:
2983                         lval = zval_get_long(zvalue);
2984                         error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL);
2985                         break;
2986 #endif
2987
2988                 /* the following options deal with files, therefore the open_basedir check
2989                  * is required.
2990                  */
2991                 case CURLOPT_COOKIEFILE:
2992                 case CURLOPT_COOKIEJAR:
2993                 case CURLOPT_RANDOM_FILE:
2994                 case CURLOPT_SSLCERT:
2995                 case CURLOPT_NETRC_FILE:
2996 #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
2997                 case CURLOPT_SSH_PRIVATE_KEYFILE:
2998                 case CURLOPT_SSH_PUBLIC_KEYFILE:
2999 #endif
3000 #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
3001                 case CURLOPT_CRLFILE:
3002                 case CURLOPT_ISSUERCERT:
3003 #endif
3004 #if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */
3005                 case CURLOPT_SSH_KNOWNHOSTS:
3006 #endif
3007                 {
3008                     zend_string *tmp_str;
3009                         zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
3010                         int ret;
3011
3012                         if (ZSTR_LEN(str) && php_check_open_basedir(ZSTR_VAL(str))) {
3013                                 zend_tmp_string_release(tmp_str);
3014                                 return FAILURE;
3015                         }
3016
3017                         ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
3018                         zend_tmp_string_release(tmp_str);
3019                         return ret;
3020                 }
3021
3022                 case CURLINFO_HEADER_OUT:
3023                         if (zend_is_true(zvalue)) {
3024                                 curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
3025                                 curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
3026                                 curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
3027                         } else {
3028                                 curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
3029                                 curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
3030                                 curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
3031                         }
3032                         break;
3033
3034                 case CURLOPT_SHARE:
3035                         {
3036                                 php_curlsh *sh;
3037                                 if ((sh = (php_curlsh *)zend_fetch_resource_ex(zvalue, le_curl_share_handle_name, le_curl_share_handle))) {
3038                                         curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share);
3039                                 }
3040                         }
3041                         break;
3042
3043 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3044                 case CURLOPT_FNMATCH_FUNCTION:
3045                         curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_FUNCTION, curl_fnmatch);
3046                         curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, ch);
3047                         if (ch->handlers->fnmatch == NULL) {
3048                                 ch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch));
3049                         } else if (!Z_ISUNDEF(ch->handlers->fnmatch->func_name)) {
3050                                 zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3051                                 ch->handlers->fnmatch->fci_cache = empty_fcall_info_cache;
3052                         }
3053                         ZVAL_COPY(&ch->handlers->fnmatch->func_name, zvalue);
3054                         ch->handlers->fnmatch->method = PHP_CURL_USER;
3055                         break;
3056 #endif
3057
3058         }
3059
3060         SAVE_CURL_ERROR(ch, error);
3061         if (error != CURLE_OK) {
3062                 return FAILURE;
3063         } else {
3064                 return SUCCESS;
3065         }
3066 }
3067 /* }}} */
3068
3069 /* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
3070    Set an option for a cURL transfer */
3071 PHP_FUNCTION(curl_setopt)
3072 {
3073         zval       *zid, *zvalue;
3074         zend_long        options;
3075         php_curl   *ch;
3076
3077         ZEND_PARSE_PARAMETERS_START(3, 3)
3078                 Z_PARAM_RESOURCE(zid)
3079                 Z_PARAM_LONG(options)
3080                 Z_PARAM_ZVAL(zvalue)
3081         ZEND_PARSE_PARAMETERS_END();
3082
3083         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3084                 RETURN_FALSE;
3085         }
3086
3087         if (options <= 0 && options != CURLOPT_SAFE_UPLOAD) {
3088                 php_error_docref(NULL, E_WARNING, "Invalid curl configuration option");
3089                 RETURN_FALSE;
3090         }
3091
3092         if (_php_curl_setopt(ch, options, zvalue) == SUCCESS) {
3093                 RETURN_TRUE;
3094         } else {
3095                 RETURN_FALSE;
3096         }
3097 }
3098 /* }}} */
3099
3100 /* {{{ proto bool curl_setopt_array(resource ch, array options)
3101    Set an array of option for a cURL transfer */
3102 PHP_FUNCTION(curl_setopt_array)
3103 {
3104         zval            *zid, *arr, *entry;
3105         php_curl        *ch;
3106         zend_ulong      option;
3107         zend_string     *string_key;
3108
3109         ZEND_PARSE_PARAMETERS_START(2, 2)
3110                 Z_PARAM_RESOURCE(zid)
3111                 Z_PARAM_ARRAY(arr)
3112         ZEND_PARSE_PARAMETERS_END();
3113
3114         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3115                 RETURN_FALSE;
3116         }
3117
3118         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(arr), option, string_key, entry) {
3119                 if (string_key) {
3120                         php_error_docref(NULL, E_WARNING,
3121                                         "Array keys must be CURLOPT constants or equivalent integer values");
3122                         RETURN_FALSE;
3123                 }
3124                 ZVAL_DEREF(entry);
3125                 if (_php_curl_setopt(ch, (zend_long) option, entry) == FAILURE) {
3126                         RETURN_FALSE;
3127                 }
3128         } ZEND_HASH_FOREACH_END();
3129
3130         RETURN_TRUE;
3131 }
3132 /* }}} */
3133
3134 /* {{{ _php_curl_cleanup_handle(ch)
3135    Cleanup an execution phase */
3136 void _php_curl_cleanup_handle(php_curl *ch)
3137 {
3138         smart_str_free(&ch->handlers->write->buf);
3139         if (ch->header.str) {
3140                 zend_string_release_ex(ch->header.str, 0);
3141                 ch->header.str = NULL;
3142         }
3143
3144         memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
3145         ch->err.no = 0;
3146 }
3147 /* }}} */
3148
3149 /* {{{ proto bool curl_exec(resource ch)
3150    Perform a cURL session */
3151 PHP_FUNCTION(curl_exec)
3152 {
3153         CURLcode        error;
3154         zval            *zid;
3155         php_curl        *ch;
3156
3157         ZEND_PARSE_PARAMETERS_START(1, 1)
3158                 Z_PARAM_RESOURCE(zid)
3159         ZEND_PARSE_PARAMETERS_END();
3160
3161         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3162                 RETURN_FALSE;
3163         }
3164
3165         _php_curl_verify_handlers(ch, 1);
3166
3167         _php_curl_cleanup_handle(ch);
3168
3169         error = curl_easy_perform(ch->cp);
3170         SAVE_CURL_ERROR(ch, error);
3171
3172         if (error != CURLE_OK) {
3173                 smart_str_free(&ch->handlers->write->buf);
3174                 RETURN_FALSE;
3175         }
3176
3177         if (!Z_ISUNDEF(ch->handlers->std_err)) {
3178                 php_stream  *stream;
3179                 stream = (php_stream*)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream());
3180                 if (stream) {
3181                         php_stream_flush(stream);
3182                 }
3183         }
3184
3185         if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.s) {
3186                 smart_str_0(&ch->handlers->write->buf);
3187                 RETURN_STR_COPY(ch->handlers->write->buf.s);
3188         }
3189
3190         /* flush the file handle, so any remaining data is synched to disk */
3191         if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
3192                 fflush(ch->handlers->write->fp);
3193         }
3194         if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
3195                 fflush(ch->handlers->write_header->fp);
3196         }
3197
3198         if (ch->handlers->write->method == PHP_CURL_RETURN) {
3199                 RETURN_EMPTY_STRING();
3200         } else {
3201                 RETURN_TRUE;
3202         }
3203 }
3204 /* }}} */
3205
3206 /* {{{ proto mixed curl_getinfo(resource ch [, int option])
3207    Get information regarding a specific transfer */
3208 PHP_FUNCTION(curl_getinfo)
3209 {
3210         zval            *zid;
3211         php_curl        *ch;
3212         zend_long       option = 0;
3213
3214         ZEND_PARSE_PARAMETERS_START(1, 2)
3215                 Z_PARAM_RESOURCE(zid)
3216                 Z_PARAM_OPTIONAL
3217                 Z_PARAM_LONG(option)
3218         ZEND_PARSE_PARAMETERS_END();
3219
3220         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3221                 RETURN_FALSE;
3222         }
3223
3224         if (ZEND_NUM_ARGS() < 2) {
3225                 char *s_code;
3226                 /* libcurl expects long datatype. So far no cases are known where
3227                    it would be an issue. Using zend_long would truncate a 64-bit
3228                    var on Win64, so the exact long datatype fits everywhere, as
3229                    long as there's no 32-bit int overflow. */
3230                 long l_code;
3231                 double d_code;
3232 #if LIBCURL_VERSION_NUM > 0x071301 /* 7.19.1 */
3233                 struct curl_certinfo *ci = NULL;
3234                 zval listcode;
3235 #endif
3236 #if LIBCURL_VERSION_NUM >= 0x073d00 /* 7.61.0 */
3237                 curl_off_t co;
3238 #endif
3239
3240                 array_init(return_value);
3241
3242                 if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
3243                         CAAS("url", s_code);
3244                 }
3245                 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
3246                         if (s_code != NULL) {
3247                                 CAAS("content_type", s_code);
3248                         } else {
3249                                 zval retnull;
3250                                 ZVAL_NULL(&retnull);
3251                                 CAAZ("content_type", &retnull);
3252                         }
3253                 }
3254                 if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
3255                         CAAL("http_code", l_code);
3256                 }
3257                 if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
3258                         CAAL("header_size", l_code);
3259                 }
3260                 if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
3261                         CAAL("request_size", l_code);
3262                 }
3263                 if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
3264                         CAAL("filetime", l_code);
3265                 }
3266                 if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
3267                         CAAL("ssl_verify_result", l_code);
3268                 }
3269                 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
3270                         CAAL("redirect_count", l_code);
3271                 }
3272                 if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
3273                         CAAD("total_time", d_code);
3274                 }
3275                 if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
3276                         CAAD("namelookup_time", d_code);
3277                 }
3278                 if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
3279                         CAAD("connect_time", d_code);
3280                 }
3281                 if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
3282                         CAAD("pretransfer_time", d_code);
3283                 }
3284                 if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
3285                         CAAD("size_upload", d_code);
3286                 }
3287                 if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
3288                         CAAD("size_download", d_code);
3289                 }
3290                 if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
3291                         CAAD("speed_download", d_code);
3292                 }
3293                 if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
3294                         CAAD("speed_upload", d_code);
3295                 }
3296                 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
3297                         CAAD("download_content_length", d_code);
3298                 }
3299                 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
3300                         CAAD("upload_content_length", d_code);
3301                 }
3302                 if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
3303                         CAAD("starttransfer_time", d_code);
3304                 }
3305                 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
3306                         CAAD("redirect_time", d_code);
3307                 }
3308 #if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */
3309                 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
3310                         CAAS("redirect_url", s_code);
3311                 }
3312 #endif
3313 #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
3314                 if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) {
3315                         CAAS("primary_ip", s_code);
3316                 }
3317 #endif
3318 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
3319                 if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
3320                         array_init(&listcode);
3321                         create_certinfo(ci, &listcode);
3322                         CAAZ("certinfo", &listcode);
3323                 }
3324 #endif
3325 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3326                 if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) {
3327                         CAAL("primary_port", l_code);
3328                 }
3329                 if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) {
3330                         CAAS("local_ip", s_code);
3331                 }
3332                 if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) {
3333                         CAAL("local_port", l_code);
3334                 }
3335 #endif
3336 #if LIBCURL_VERSION_NUM >= 0x073200 /* Available since 7.50.0 */
3337                 if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_VERSION, &l_code) == CURLE_OK) {
3338                         CAAL("http_version", l_code);
3339                 }
3340 #endif
3341 #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
3342                 if (curl_easy_getinfo(ch->cp, CURLINFO_PROTOCOL, &l_code) == CURLE_OK) {
3343                         CAAL("protocol", l_code);
3344                 }
3345                 if (curl_easy_getinfo(ch->cp, CURLINFO_PROXY_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
3346                         CAAL("ssl_verifyresult", l_code);
3347                 }
3348                 if (curl_easy_getinfo(ch->cp, CURLINFO_SCHEME, &s_code) == CURLE_OK) {
3349                         CAAS("scheme", s_code);
3350                 }
3351 #endif
3352 #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
3353                 if (curl_easy_getinfo(ch->cp, CURLINFO_APPCONNECT_TIME_T, &co) == CURLE_OK) {
3354                         CAAL("appconnect_time_us", co);
3355                 }
3356                 if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME_T, &co) == CURLE_OK) {
3357                         CAAL("connect_time_us", co);
3358                 }
3359                 if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME_T, &co) == CURLE_OK) {
3360                         CAAL("namelookup_time_us", co);
3361                 }
3362                 if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME_T, &co) == CURLE_OK) {
3363                         CAAL("pretransfer_time_us", co);
3364                 }
3365                 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME_T, &co) == CURLE_OK) {
3366                         CAAL("redirect_time_us", co);
3367                 }
3368                 if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME_T, &co) == CURLE_OK) {
3369                         CAAL("starttransfer_time_us", co);
3370                 }
3371                 if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME_T, &co) == CURLE_OK) {
3372                         CAAL("total_time_us", co);
3373                 }
3374 #endif
3375                 if (ch->header.str) {
3376                         CAASTR("request_header", ch->header.str);
3377                 }
3378         } else {
3379                 switch (option) {
3380                         case CURLINFO_HEADER_OUT:
3381                                 if (ch->header.str) {
3382                                         RETURN_STR_COPY(ch->header.str);
3383                                 } else {
3384                                         RETURN_FALSE;
3385                                 }
3386 #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
3387                         case CURLINFO_CERTINFO: {
3388                                 struct curl_certinfo *ci = NULL;
3389
3390                                 array_init(return_value);
3391
3392                                 if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
3393                                         create_certinfo(ci, return_value);
3394                                 } else {
3395                                         RETURN_FALSE;
3396                                 }
3397                                 break;
3398                         }
3399 #endif
3400                         default: {
3401                                 int type = CURLINFO_TYPEMASK & option;
3402                                 switch (type) {
3403                                         case CURLINFO_STRING:
3404                                         {
3405                                                 char *s_code = NULL;
3406
3407                                                 if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
3408                                                         RETURN_STRING(s_code);
3409                                                 } else {
3410                                                         RETURN_FALSE;
3411                                                 }
3412                                                 break;
3413                                         }
3414                                         case CURLINFO_LONG:
3415                                         {
3416                                                 zend_long code = 0;
3417
3418                                                 if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
3419                                                         RETURN_LONG(code);
3420                                                 } else {
3421                                                         RETURN_FALSE;
3422                                                 }
3423                                                 break;
3424                                         }
3425                                         case CURLINFO_DOUBLE:
3426                                         {
3427                                                 double code = 0.0;
3428
3429                                                 if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
3430                                                         RETURN_DOUBLE(code);
3431                                                 } else {
3432                                                         RETURN_FALSE;
3433                                                 }
3434                                                 break;
3435                                         }
3436                                         case CURLINFO_SLIST:
3437                                         {
3438                                                 struct curl_slist *slist;
3439                                                 array_init(return_value);
3440                                                 if (curl_easy_getinfo(ch->cp, option, &slist) == CURLE_OK) {
3441                                                         while (slist) {
3442                                                                 add_next_index_string(return_value, slist->data);
3443                                                                 slist = slist->next;
3444                                                         }
3445                                                         curl_slist_free_all(slist);
3446                                                 } else {
3447                                                         RETURN_FALSE;
3448                                                 }
3449                                                 break;
3450                                         }
3451 #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
3452                                         case CURLINFO_OFF_T:
3453                                         {
3454                                                 curl_off_t c_off;
3455                                                 if (curl_easy_getinfo(ch->cp, option, &c_off) == CURLE_OK) {
3456                                                         RETURN_LONG((long) c_off);
3457                                                 } else {
3458                                                         RETURN_FALSE;
3459                                                 }
3460                                                 break;
3461                                         }
3462 #endif
3463                                         default:
3464                                                 RETURN_FALSE;
3465                                 }
3466                         }
3467                 }
3468         }
3469 }
3470 /* }}} */
3471
3472 /* {{{ proto string curl_error(resource ch)
3473    Return a string contain the last error for the current session */
3474 PHP_FUNCTION(curl_error)
3475 {
3476         zval            *zid;
3477         php_curl        *ch;
3478
3479         ZEND_PARSE_PARAMETERS_START(1, 1)
3480                 Z_PARAM_RESOURCE(zid)
3481         ZEND_PARSE_PARAMETERS_END();
3482
3483         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3484                 RETURN_FALSE;
3485         }
3486
3487         if (ch->err.no) {
3488                 ch->err.str[CURL_ERROR_SIZE] = 0;
3489                 RETURN_STRING(ch->err.str);
3490         } else {
3491                 RETURN_EMPTY_STRING();
3492         }
3493 }
3494 /* }}} */
3495
3496 /* {{{ proto int curl_errno(resource ch)
3497    Return an integer containing the last error number */
3498 PHP_FUNCTION(curl_errno)
3499 {
3500         zval            *zid;
3501         php_curl        *ch;
3502
3503         ZEND_PARSE_PARAMETERS_START(1,1)
3504                 Z_PARAM_RESOURCE(zid)
3505         ZEND_PARSE_PARAMETERS_END();
3506
3507         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3508                 RETURN_FALSE;
3509         }
3510
3511         RETURN_LONG(ch->err.no);
3512 }
3513 /* }}} */
3514
3515 /* {{{ proto void curl_close(resource ch)
3516    Close a cURL session */
3517 PHP_FUNCTION(curl_close)
3518 {
3519         zval            *zid;
3520         php_curl        *ch;
3521
3522         ZEND_PARSE_PARAMETERS_START(1, 1)
3523                 Z_PARAM_RESOURCE(zid)
3524         ZEND_PARSE_PARAMETERS_END();
3525
3526         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3527                 RETURN_FALSE;
3528         }
3529
3530         if (ch->in_callback) {
3531                 php_error_docref(NULL, E_WARNING, "Attempt to close cURL handle from a callback");
3532                 return;
3533         }
3534
3535         zend_list_close(Z_RES_P(zid));
3536 }
3537 /* }}} */
3538
3539 /* {{{ _php_curl_close_ex()
3540    List destructor for curl handles */
3541 static void _php_curl_close_ex(php_curl *ch)
3542 {
3543 #if PHP_CURL_DEBUG
3544         fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
3545 #endif
3546
3547         _php_curl_verify_handlers(ch, 0);
3548
3549         /*
3550          * Libcurl is doing connection caching. When easy handle is cleaned up,
3551          * if the handle was previously used by the curl_multi_api, the connection
3552          * remains open un the curl multi handle is cleaned up. Some protocols are
3553          * sending content like the FTP one, and libcurl try to use the
3554          * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those
3555          * callback are freed, we need to use an other callback to which avoid
3556          * segfaults.
3557          *
3558          * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2
3559          */
3560         if (ch->cp != NULL) {
3561                 curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing);
3562                 curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing);
3563
3564                 curl_easy_cleanup(ch->cp);
3565         }
3566
3567         /* cURL destructors should be invoked only by last curl handle */
3568         if (--(*ch->clone) == 0) {
3569                 zend_llist_clean(&ch->to_free->str);
3570                 zend_llist_clean(&ch->to_free->post);
3571                 zend_llist_clean(&ch->to_free->stream);
3572                 zend_hash_destroy(ch->to_free->slist);
3573                 efree(ch->to_free->slist);
3574                 efree(ch->to_free);
3575                 efree(ch->clone);
3576         }
3577
3578         smart_str_free(&ch->handlers->write->buf);
3579         zval_ptr_dtor(&ch->handlers->write->func_name);
3580         zval_ptr_dtor(&ch->handlers->read->func_name);
3581         zval_ptr_dtor(&ch->handlers->write_header->func_name);
3582         zval_ptr_dtor(&ch->handlers->std_err);
3583         if (ch->header.str) {
3584                 zend_string_release_ex(ch->header.str, 0);
3585         }
3586
3587         zval_ptr_dtor(&ch->handlers->write_header->stream);
3588         zval_ptr_dtor(&ch->handlers->write->stream);
3589         zval_ptr_dtor(&ch->handlers->read->stream);
3590
3591         efree(ch->handlers->write);
3592         efree(ch->handlers->write_header);
3593         efree(ch->handlers->read);
3594
3595         if (ch->handlers->progress) {
3596                 zval_ptr_dtor(&ch->handlers->progress->func_name);
3597                 efree(ch->handlers->progress);
3598         }
3599
3600 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3601         if (ch->handlers->fnmatch) {
3602                 zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3603                 efree(ch->handlers->fnmatch);
3604         }
3605 #endif
3606
3607         efree(ch->handlers);
3608         efree(ch);
3609 }
3610 /* }}} */
3611
3612 /* {{{ _php_curl_close()
3613    List destructor for curl handles */
3614 static void _php_curl_close(zend_resource *rsrc)
3615 {
3616         php_curl *ch = (php_curl *) rsrc->ptr;
3617         _php_curl_close_ex(ch);
3618 }
3619 /* }}} */
3620
3621 /* {{{ proto bool curl_strerror(int code)
3622       return string describing error code */
3623 PHP_FUNCTION(curl_strerror)
3624 {
3625         zend_long code;
3626         const char *str;
3627
3628         ZEND_PARSE_PARAMETERS_START(1, 1)
3629                 Z_PARAM_LONG(code)
3630         ZEND_PARSE_PARAMETERS_END();
3631
3632         str = curl_easy_strerror(code);
3633         if (str) {
3634                 RETURN_STRING(str);
3635         } else {
3636                 RETURN_NULL();
3637         }
3638 }
3639 /* }}} */
3640
3641 /* {{{ _php_curl_reset_handlers()
3642    Reset all handlers of a given php_curl */
3643 static void _php_curl_reset_handlers(php_curl *ch)
3644 {
3645         if (!Z_ISUNDEF(ch->handlers->write->stream)) {
3646                 zval_ptr_dtor(&ch->handlers->write->stream);
3647                 ZVAL_UNDEF(&ch->handlers->write->stream);
3648         }
3649         ch->handlers->write->fp = NULL;
3650         ch->handlers->write->method = PHP_CURL_STDOUT;
3651
3652         if (!Z_ISUNDEF(ch->handlers->write_header->stream)) {
3653                 zval_ptr_dtor(&ch->handlers->write_header->stream);
3654                 ZVAL_UNDEF(&ch->handlers->write_header->stream);
3655         }
3656         ch->handlers->write_header->fp = NULL;
3657         ch->handlers->write_header->method = PHP_CURL_IGNORE;
3658
3659         if (!Z_ISUNDEF(ch->handlers->read->stream)) {
3660                 zval_ptr_dtor(&ch->handlers->read->stream);
3661                 ZVAL_UNDEF(&ch->handlers->read->stream);
3662         }
3663         ch->handlers->read->fp = NULL;
3664         ch->handlers->read->res = NULL;
3665         ch->handlers->read->method  = PHP_CURL_DIRECT;
3666
3667         if (!Z_ISUNDEF(ch->handlers->std_err)) {
3668                 zval_ptr_dtor(&ch->handlers->std_err);
3669                 ZVAL_UNDEF(&ch->handlers->std_err);
3670         }
3671
3672         if (ch->handlers->progress) {
3673                 zval_ptr_dtor(&ch->handlers->progress->func_name);
3674                 efree(ch->handlers->progress);
3675                 ch->handlers->progress = NULL;
3676         }
3677
3678 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3679         if (ch->handlers->fnmatch) {
3680                 zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3681                 efree(ch->handlers->fnmatch);
3682                 ch->handlers->fnmatch = NULL;
3683         }
3684 #endif
3685
3686 }
3687 /* }}} */
3688
3689 /* {{{ proto void curl_reset(resource ch)
3690    Reset all options of a libcurl session handle */
3691 PHP_FUNCTION(curl_reset)
3692 {
3693         zval       *zid;
3694         php_curl   *ch;
3695
3696         ZEND_PARSE_PARAMETERS_START(1, 1)
3697                 Z_PARAM_RESOURCE(zid)
3698         ZEND_PARSE_PARAMETERS_END();
3699
3700         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3701                 RETURN_FALSE;
3702         }
3703
3704         if (ch->in_callback) {
3705                 php_error_docref(NULL, E_WARNING, "Attempt to reset cURL handle from a callback");
3706                 return;
3707         }
3708
3709         curl_easy_reset(ch->cp);
3710         _php_curl_reset_handlers(ch);
3711         _php_curl_set_default_options(ch);
3712 }
3713 /* }}} */
3714
3715 /* {{{ proto void curl_escape(resource ch, string str)
3716    URL encodes the given string */
3717 PHP_FUNCTION(curl_escape)
3718 {
3719         zend_string *str;
3720         char        *res;
3721         zval        *zid;
3722         php_curl    *ch;
3723
3724         ZEND_PARSE_PARAMETERS_START(2,2)
3725                 Z_PARAM_RESOURCE(zid)
3726                 Z_PARAM_STR(str)
3727         ZEND_PARSE_PARAMETERS_END();
3728
3729         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3730                 RETURN_FALSE;
3731         }
3732
3733         if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) {
3734                 RETURN_FALSE;
3735         }
3736
3737         if ((res = curl_easy_escape(ch->cp, ZSTR_VAL(str), ZSTR_LEN(str)))) {
3738                 RETVAL_STRING(res);
3739                 curl_free(res);
3740         } else {
3741                 RETURN_FALSE;
3742         }
3743 }
3744 /* }}} */
3745
3746 /* {{{ proto void curl_unescape(resource ch, string str)
3747    URL decodes the given string */
3748 PHP_FUNCTION(curl_unescape)
3749 {
3750         char        *out = NULL;
3751         int          out_len;
3752         zval        *zid;
3753         zend_string *str;
3754         php_curl    *ch;
3755
3756         ZEND_PARSE_PARAMETERS_START(2,2)
3757                 Z_PARAM_RESOURCE(zid)
3758                 Z_PARAM_STR(str)
3759         ZEND_PARSE_PARAMETERS_END();
3760
3761         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3762                 RETURN_FALSE;
3763         }
3764
3765         if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) {
3766                 RETURN_FALSE;
3767         }
3768
3769         if ((out = curl_easy_unescape(ch->cp, ZSTR_VAL(str), ZSTR_LEN(str), &out_len))) {
3770                 RETVAL_STRINGL(out, out_len);
3771                 curl_free(out);
3772         } else {
3773                 RETURN_FALSE;
3774         }
3775 }
3776 /* }}} */
3777
3778 #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
3779 /* {{{ proto void curl_pause(resource ch, int bitmask)
3780        pause and unpause a connection */
3781 PHP_FUNCTION(curl_pause)
3782 {
3783         zend_long       bitmask;
3784         zval       *zid;
3785         php_curl   *ch;
3786
3787         ZEND_PARSE_PARAMETERS_START(2,2)
3788                 Z_PARAM_RESOURCE(zid)
3789                 Z_PARAM_LONG(bitmask)
3790         ZEND_PARSE_PARAMETERS_END();
3791
3792         if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3793                 RETURN_FALSE;
3794         }
3795
3796         RETURN_LONG(curl_easy_pause(ch->cp, bitmask));
3797 }
3798 /* }}} */
3799 #endif
3800
3801 #endif /* HAVE_CURL */