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

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