Advertisement
RieqyNS13

interface.c

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