root/ext/curl/interface.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_curl_ssl_lock
  2. php_curl_ssl_id
  3. php_curl_ssl_mutex_create
  4. php_curl_ssl_mutex_destroy
  5. php_curl_ssl_mutex_lock
  6. php_curl_ssl_mutex_unlock
  7. php_curl_option_str
  8. php_curl_option_url
  9. _php_curl_verify_handlers
  10. ZEND_GET_MODULE
  11. PHP_MINIT_FUNCTION
  12. PHP_MSHUTDOWN_FUNCTION
  13. curl_write_nothing
  14. curl_write
  15. curl_fnmatch
  16. curl_progress
  17. curl_read
  18. curl_write_header
  19. curl_debug
  20. curl_passwd
  21. curl_free_string
  22. curl_free_post
  23. curl_free_slist
  24. PHP_FUNCTION
  25. alloc_curl_handle
  26. split_certinfo
  27. create_certinfo
  28. _php_curl_set_default_options
  29. PHP_FUNCTION
  30. PHP_FUNCTION
  31. _php_curl_setopt
  32. PHP_FUNCTION
  33. PHP_FUNCTION
  34. _php_curl_cleanup_handle
  35. PHP_FUNCTION
  36. PHP_FUNCTION
  37. PHP_FUNCTION
  38. PHP_FUNCTION
  39. PHP_FUNCTION
  40. _php_curl_close_ex
  41. _php_curl_close
  42. PHP_FUNCTION
  43. _php_curl_reset_handlers
  44. PHP_FUNCTION
  45. PHP_FUNCTION
  46. PHP_FUNCTION
  47. PHP_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */