Back to index

php5  5.3.10
interface.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Sterling Hughes <sterling@php.net>                           |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: interface.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #include "php.h"
00028 
00029 #if HAVE_CURL
00030 
00031 #include <stdio.h>
00032 #include <string.h>
00033 
00034 #ifdef PHP_WIN32
00035 #include <winsock2.h>
00036 #include <sys/types.h>
00037 #endif
00038 
00039 #include <curl/curl.h>
00040 #include <curl/easy.h>
00041 
00042 /* As of curl 7.11.1 this is no longer defined inside curl.h */
00043 #ifndef HttpPost
00044 #define HttpPost curl_httppost
00045 #endif
00046 
00047 /* {{{ cruft for thread safe SSL crypto locks */
00048 #if defined(ZTS) && defined(HAVE_CURL_SSL)
00049 # ifdef PHP_WIN32
00050 #  define PHP_CURL_NEED_OPENSSL_TSL
00051 #  include <openssl/crypto.h>
00052 # else /* !PHP_WIN32 */
00053 #  if defined(HAVE_CURL_OPENSSL)
00054 #   if defined(HAVE_OPENSSL_CRYPTO_H)
00055 #    define PHP_CURL_NEED_OPENSSL_TSL
00056 #    include <openssl/crypto.h>
00057 #   else
00058 #    warning \
00059        "libcurl was compiled with OpenSSL support, but configure could not find " \
00060        "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
00061        "cause random crashes on SSL requests"
00062 #   endif
00063 #  elif defined(HAVE_CURL_GNUTLS)
00064 #   if defined(HAVE_GCRYPT_H)
00065 #    define PHP_CURL_NEED_GNUTLS_TSL
00066 #    include <gcrypt.h>
00067 #   else
00068 #    warning \
00069        "libcurl was compiled with GnuTLS support, but configure could not find " \
00070        "gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \
00071        "cause random crashes on SSL requests"
00072 #   endif
00073 #  else
00074 #   warning \
00075        "libcurl was compiled with SSL support, but configure could not determine which" \
00076        "library was used; thus no SSL crypto locking callbacks will be set, which may " \
00077        "cause random crashes on SSL requests"
00078 #  endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
00079 # endif /* PHP_WIN32 */
00080 #endif /* ZTS && HAVE_CURL_SSL */
00081 /* }}} */
00082 
00083 #define SMART_STR_PREALLOC 4096
00084 
00085 #include "ext/standard/php_smart_str.h"
00086 #include "ext/standard/info.h"
00087 #include "ext/standard/file.h"
00088 #include "ext/standard/url.h"
00089 #include "php_curl.h"
00090 
00091 int  le_curl;
00092 int  le_curl_multi_handle;
00093 
00094 #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
00095 static MUTEX_T *php_curl_openssl_tsl = NULL;
00096 
00097 static void php_curl_ssl_lock(int mode, int n, const char * file, int line)
00098 {
00099        if (mode & CRYPTO_LOCK) {
00100               tsrm_mutex_lock(php_curl_openssl_tsl[n]);
00101        } else {
00102               tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
00103        }
00104 }
00105 
00106 static unsigned long php_curl_ssl_id(void)
00107 {
00108        return (unsigned long) tsrm_thread_id();
00109 }
00110 #endif
00111 /* }}} */
00112 
00113 #ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */
00114 static int php_curl_ssl_mutex_create(void **m)
00115 {
00116        if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
00117               return SUCCESS;
00118        } else {
00119               return FAILURE;
00120        }
00121 }
00122 
00123 static int php_curl_ssl_mutex_destroy(void **m)
00124 {
00125        tsrm_mutex_free(*((MUTEX_T *) m));
00126        return SUCCESS;
00127 }
00128 
00129 static int php_curl_ssl_mutex_lock(void **m)
00130 {
00131        return tsrm_mutex_lock(*((MUTEX_T *) m));
00132 }
00133 
00134 static int php_curl_ssl_mutex_unlock(void **m)
00135 {
00136        return tsrm_mutex_unlock(*((MUTEX_T *) m));
00137 }
00138 
00139 static struct gcry_thread_cbs php_curl_gnutls_tsl = {
00140        GCRY_THREAD_OPTION_USER,
00141        NULL,
00142        php_curl_ssl_mutex_create,
00143        php_curl_ssl_mutex_destroy,
00144        php_curl_ssl_mutex_lock,
00145        php_curl_ssl_mutex_unlock
00146 };
00147 #endif
00148 /* }}} */
00149 
00150 static void _php_curl_close_ex(php_curl *ch TSRMLS_DC);
00151 static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
00152 
00153 
00154 #define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
00155 
00156 #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s), (long) v);
00157 #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s), (double) v);
00158 #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) (v ? v : ""), 1);
00159 #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v);
00160 
00161 #if defined(PHP_WIN32) || defined(__GNUC__)
00162 # define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
00163 #else
00164 # define php_curl_ret(__ret) RETVAL_FALSE; return;
00165 #endif
00166 
00167 static int php_curl_option_url(php_curl *ch, const char *url, const int len) /* {{{ */
00168 {
00169        CURLcode error = CURLE_OK;
00170 #if LIBCURL_VERSION_NUM < 0x071100
00171        char *copystr = NULL;
00172 #endif
00173        TSRMLS_FETCH();
00174 
00175        /* Disable file:// if open_basedir or safe_mode are used */
00176        if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
00177 #if LIBCURL_VERSION_NUM >= 0x071304
00178               error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
00179 #else
00180               php_url *uri;
00181 
00182               if (!(uri = php_url_parse_ex(url, len))) {
00183                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL '%s'", url);
00184                      return 0;
00185               }
00186 
00187               if (uri->scheme && !strncasecmp("file", uri->scheme, sizeof("file"))) {
00188                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol 'file' disabled in cURL");
00189                      php_url_free(uri);
00190                      return 0;
00191               }
00192               php_url_free(uri);
00193 #endif
00194        }
00195        /* Strings passed to libcurl as 'char *' arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
00196 #if LIBCURL_VERSION_NUM >= 0x071100
00197        error = curl_easy_setopt(ch->cp, CURLOPT_URL, url);
00198 #else
00199        copystr = estrndup(url, len);
00200        error = curl_easy_setopt(ch->cp, CURLOPT_URL, copystr);
00201        zend_llist_add_element(&ch->to_free->str, &copystr);
00202 #endif
00203 
00204        return (error == CURLE_OK ? 1 : 0);
00205 }
00206 /* }}} */
00207 
00208 int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
00209 {
00210        php_stream *stream;
00211        if (!ch || !ch->handlers) {
00212               return 0;
00213        }
00214 
00215        if (ch->handlers->std_err) {
00216               stream = (php_stream *) zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
00217               if (stream == NULL) {
00218                      if (reporterror) {
00219                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr");
00220                      }
00221                      zval_ptr_dtor(&ch->handlers->std_err);
00222                      ch->handlers->std_err = NULL;
00223 
00224                      curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
00225               }
00226        }
00227        if (ch->handlers->read && ch->handlers->read->stream) {
00228               stream = (php_stream *) zend_fetch_resource(&ch->handlers->read->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
00229               if (stream == NULL) {
00230                      if (reporterror) {
00231                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default");
00232                      }
00233                      zval_ptr_dtor(&ch->handlers->read->stream);
00234                      ch->handlers->read->fd = 0;
00235                      ch->handlers->read->fp = 0;
00236                      ch->handlers->read->stream = NULL;
00237 
00238                      curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
00239               }
00240        }
00241        if (ch->handlers->write_header && ch->handlers->write_header->stream) {
00242               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());
00243               if (stream == NULL) {
00244                      if (reporterror) {
00245                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default");
00246                      }
00247                      zval_ptr_dtor(&ch->handlers->write_header->stream);
00248                      ch->handlers->write_header->fp = 0;
00249                      ch->handlers->write_header->stream = NULL;
00250 
00251                      ch->handlers->write_header->method = PHP_CURL_IGNORE;
00252                      curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
00253               }
00254        }
00255        if (ch->handlers->write && ch->handlers->write->stream) {
00256               stream = (php_stream *) zend_fetch_resource(&ch->handlers->write->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
00257               if (stream == NULL) {
00258                      if (reporterror) {
00259                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default");
00260                      }
00261                      zval_ptr_dtor(&ch->handlers->write->stream);
00262                      ch->handlers->write->fp = 0;
00263                      ch->handlers->write->stream = NULL;
00264 
00265                      ch->handlers->write->method = PHP_CURL_STDOUT;
00266                      ch->handlers->write->type   = PHP_CURL_ASCII;
00267                      curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
00268               }
00269        }
00270        return 1;
00271 }
00272 /* }}} */
00273 
00274 /* {{{ arginfo */
00275 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
00276        ZEND_ARG_INFO(0, version)
00277 ZEND_END_ARG_INFO()
00278 
00279 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
00280        ZEND_ARG_INFO(0, url)
00281 ZEND_END_ARG_INFO()
00282 
00283 ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
00284        ZEND_ARG_INFO(0, ch)
00285 ZEND_END_ARG_INFO()
00286 
00287 ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
00288        ZEND_ARG_INFO(0, ch)
00289        ZEND_ARG_INFO(0, option)
00290        ZEND_ARG_INFO(0, value)
00291 ZEND_END_ARG_INFO()
00292 
00293 ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
00294        ZEND_ARG_INFO(0, ch)
00295        ZEND_ARG_ARRAY_INFO(0, options, 0)
00296 ZEND_END_ARG_INFO()
00297 
00298 ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
00299        ZEND_ARG_INFO(0, ch)
00300 ZEND_END_ARG_INFO()
00301 
00302 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
00303        ZEND_ARG_INFO(0, ch)
00304        ZEND_ARG_INFO(0, option)
00305 ZEND_END_ARG_INFO()
00306 
00307 ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
00308        ZEND_ARG_INFO(0, ch)
00309 ZEND_END_ARG_INFO()
00310 
00311 ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
00312        ZEND_ARG_INFO(0, ch)
00313 ZEND_END_ARG_INFO()
00314 
00315 ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
00316        ZEND_ARG_INFO(0, ch)
00317 ZEND_END_ARG_INFO()
00318 
00319 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
00320 ZEND_END_ARG_INFO()
00321 
00322 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
00323        ZEND_ARG_INFO(0, mh)
00324        ZEND_ARG_INFO(0, ch)
00325 ZEND_END_ARG_INFO()
00326 
00327 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
00328        ZEND_ARG_INFO(0, mh)
00329        ZEND_ARG_INFO(0, ch)
00330 ZEND_END_ARG_INFO()
00331 
00332 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
00333        ZEND_ARG_INFO(0, mh)
00334        ZEND_ARG_INFO(0, timeout)
00335 ZEND_END_ARG_INFO()
00336 
00337 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
00338        ZEND_ARG_INFO(0, mh)
00339        ZEND_ARG_INFO(1, still_running)
00340 ZEND_END_ARG_INFO()
00341 
00342 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
00343        ZEND_ARG_INFO(0, ch)
00344 ZEND_END_ARG_INFO()
00345 
00346 ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
00347        ZEND_ARG_INFO(0, mh)
00348        ZEND_ARG_INFO(1, msgs_in_queue)
00349 ZEND_END_ARG_INFO()
00350 
00351 ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
00352        ZEND_ARG_INFO(0, mh)
00353 ZEND_END_ARG_INFO()
00354 /* }}} */
00355 
00356 /* {{{ curl_functions[]
00357  */
00358 const zend_function_entry curl_functions[] = {
00359        PHP_FE(curl_init,                arginfo_curl_init)
00360        PHP_FE(curl_copy_handle,         arginfo_curl_copy_handle)
00361        PHP_FE(curl_version,             arginfo_curl_version)
00362        PHP_FE(curl_setopt,              arginfo_curl_setopt)
00363        PHP_FE(curl_setopt_array,        arginfo_curl_setopt_array)
00364        PHP_FE(curl_exec,                arginfo_curl_exec)
00365        PHP_FE(curl_getinfo,             arginfo_curl_getinfo)
00366        PHP_FE(curl_error,               arginfo_curl_error)
00367        PHP_FE(curl_errno,               arginfo_curl_errno)
00368        PHP_FE(curl_close,               arginfo_curl_close)
00369        PHP_FE(curl_multi_init,          arginfo_curl_multi_init)
00370        PHP_FE(curl_multi_add_handle,    arginfo_curl_multi_add_handle)
00371        PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
00372        PHP_FE(curl_multi_select,        arginfo_curl_multi_select)
00373        PHP_FE(curl_multi_exec,          arginfo_curl_multi_exec)
00374        PHP_FE(curl_multi_getcontent,    arginfo_curl_multi_getcontent)
00375        PHP_FE(curl_multi_info_read,     arginfo_curl_multi_info_read)
00376        PHP_FE(curl_multi_close,         arginfo_curl_multi_close)
00377        PHP_FE_END
00378 };
00379 /* }}} */
00380 
00381 /* {{{ curl_module_entry
00382  */
00383 zend_module_entry curl_module_entry = {
00384        STANDARD_MODULE_HEADER,
00385        "curl",
00386        curl_functions,
00387        PHP_MINIT(curl),
00388        PHP_MSHUTDOWN(curl),
00389        NULL,
00390        NULL,
00391        PHP_MINFO(curl),
00392        NO_VERSION_YET,
00393        STANDARD_MODULE_PROPERTIES
00394 };
00395 /* }}} */
00396 
00397 #ifdef COMPILE_DL_CURL
00398 ZEND_GET_MODULE (curl)
00399 #endif
00400 
00401 /* {{{ PHP_INI_BEGIN */
00402 PHP_INI_BEGIN()
00403        PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
00404 PHP_INI_END()
00405 /* }}} */
00406 
00407 /* {{{ PHP_MINFO_FUNCTION
00408  */
00409 PHP_MINFO_FUNCTION(curl)
00410 {
00411        curl_version_info_data *d;
00412        char **p;
00413        char str[1024];
00414        size_t n = 0;
00415 
00416        d = curl_version_info(CURLVERSION_NOW);
00417        php_info_print_table_start();
00418        php_info_print_table_row(2, "cURL support",    "enabled");
00419        php_info_print_table_row(2, "cURL Information", d->version);
00420        sprintf(str, "%d", d->age);
00421        php_info_print_table_row(2, "Age", str);
00422 
00423        /* To update on each new cURL release using src/main.c in cURL sources */
00424        if (d->features) {
00425               struct feat {
00426                      const char *name;
00427                      int bitmask;
00428               };
00429 
00430               unsigned int i;
00431 
00432               static const struct feat feats[] = {
00433 #if LIBCURL_VERSION_NUM > 0x070a06 /* 7.10.7 */
00434                      {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
00435 #endif
00436 #if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
00437                      {"Debug", CURL_VERSION_DEBUG},
00438                      {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
00439 #endif
00440 #if LIBCURL_VERSION_NUM > 0x070b02 /* 7.12.0 */
00441                      {"IDN", CURL_VERSION_IDN},
00442 #endif
00443 #ifdef CURL_VERSION_IPV6
00444                      {"IPv6", CURL_VERSION_IPV6},
00445 #endif
00446 #if LIBCURL_VERSION_NUM > 0x070b00 /* 7.11.1 */
00447                      {"Largefile", CURL_VERSION_LARGEFILE},
00448 #endif
00449 #if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
00450                      {"NTLM", CURL_VERSION_NTLM},
00451 #endif
00452 #if LIBCURL_VERSION_NUM > 0x070a07 /* 7.10.8 */
00453                      {"SPNEGO", CURL_VERSION_SPNEGO},
00454 #endif
00455 #ifdef CURL_VERSION_SSL
00456                      {"SSL",  CURL_VERSION_SSL},
00457 #endif
00458 #if LIBCURL_VERSION_NUM > 0x070d01 /* 7.13.2 */
00459                      {"SSPI",  CURL_VERSION_SSPI},
00460 #endif
00461 #ifdef CURL_VERSION_KERBEROS4
00462                      {"krb4", CURL_VERSION_KERBEROS4},
00463 #endif
00464 #ifdef CURL_VERSION_LIBZ
00465                      {"libz", CURL_VERSION_LIBZ},
00466 #endif
00467 #if LIBCURL_VERSION_NUM > 0x070f03 /* 7.15.4 */
00468                      {"CharConv", CURL_VERSION_CONV},
00469 #endif
00470                      {NULL, 0}
00471               };
00472 
00473               php_info_print_table_row(1, "Features");
00474               for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
00475                      if (feats[i].name) {
00476                             php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
00477                      }
00478               }
00479        }
00480 
00481        n = 0;
00482        p = (char **) d->protocols;
00483        while (*p != NULL) {
00484                      n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : "");
00485                      p++;
00486        }
00487        php_info_print_table_row(2, "Protocols", str);
00488 
00489        php_info_print_table_row(2, "Host", d->host);
00490 
00491        if (d->ssl_version) {
00492               php_info_print_table_row(2, "SSL Version", d->ssl_version);
00493        }
00494 
00495        if (d->libz_version) {
00496               php_info_print_table_row(2, "ZLib Version", d->libz_version);
00497        }
00498 
00499 #if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND
00500        if (d->ares) {
00501               php_info_print_table_row(2, "ZLib Version", d->ares);
00502        }
00503 #endif
00504 
00505 #if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD
00506        if (d->libidn) {
00507               php_info_print_table_row(2, "libIDN Version", d->libidn);
00508        }
00509 #endif
00510 
00511 #if LIBCURL_VERSION_NUM >= 0x071300
00512 
00513        if (d->iconv_ver_num) {
00514               php_info_print_table_row(2, "IconV Version", d->iconv_ver_num);
00515        }
00516 
00517        if (d->libssh_version) {
00518               php_info_print_table_row(2, "libSSH Version", d->libssh_version);
00519        }
00520 #endif
00521        php_info_print_table_end();
00522 }
00523 /* }}} */
00524 
00525 #define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
00526 
00527 /* {{{ PHP_MINIT_FUNCTION
00528  */
00529 PHP_MINIT_FUNCTION(curl)
00530 {
00531        le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
00532        le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
00533 
00534        REGISTER_INI_ENTRIES();
00535 
00536        /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
00537           or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
00538           of options and which version they were introduced */
00539 
00540        /* Constants for curl_setopt() */
00541 #if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
00542        REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE);
00543        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER);
00544        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4);
00545        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6);
00546 #endif
00547        REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
00548        REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
00549        REGISTER_CURL_CONSTANT(CURLOPT_PORT);
00550        REGISTER_CURL_CONSTANT(CURLOPT_FILE);
00551        REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
00552        REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
00553        REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
00554        REGISTER_CURL_CONSTANT(CURLOPT_URL);
00555        REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
00556        REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
00557        REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
00558        REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
00559        REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
00560        REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION);
00561        REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
00562        REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
00563        REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
00564        REGISTER_CURL_CONSTANT(CURLOPT_POST);
00565        REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
00566        REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
00567        REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
00568        REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
00569 #if CURLOPT_FTPASCII != 0
00570        REGISTER_CURL_CONSTANT(CURLOPT_FTPASCII);
00571 #endif
00572        REGISTER_CURL_CONSTANT(CURLOPT_PUT);
00573 #if CURLOPT_MUTE != 0
00574        REGISTER_CURL_CONSTANT(CURLOPT_MUTE);
00575 #endif
00576        REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
00577        REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
00578        REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
00579        REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
00580 #if LIBCURL_VERSION_NUM > 0x071002
00581        REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
00582 #endif
00583        REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
00584        REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
00585        REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
00586        REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
00587        REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
00588        REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
00589        REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
00590        REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
00591        REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
00592        REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
00593        REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
00594        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
00595        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
00596        REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
00597        REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
00598        REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
00599        REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
00600        REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
00601        REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
00602        REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
00603        REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
00604        REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
00605        REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
00606        REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
00607        REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
00608        REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
00609        REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
00610        REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
00611        REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
00612        REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
00613        REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
00614 #if CURLOPT_PASSWDFUNCTION != 0
00615        REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION);
00616 #endif
00617        REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
00618        REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
00619        REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
00620        REGISTER_CURL_CONSTANT(CURLOPT_CLOSEPOLICY);
00621        REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
00622        REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
00623        REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
00624        REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
00625        REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
00626 #if LIBCURL_VERSION_NUM > 0x071002
00627        REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
00628 #endif
00629        REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
00630        REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
00631        REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
00632        REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
00633        REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
00634        REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
00635        REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
00636        REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
00637        REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
00638        REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
00639        REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
00640        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
00641        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
00642        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
00643        REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
00644        REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
00645        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
00646        REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
00647        REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
00648        REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
00649        REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
00650        REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
00651 #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
00652        REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
00653 #endif
00654        REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
00655        REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
00656        REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
00657        REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
00658 
00659 #if LIBCURL_VERSION_NUM > 0x070f04 /* CURLOPT_MAX_RECV_SPEED_LARGE & CURLOPT_MAX_SEND_SPEED_LARGE  are available since curl 7.15.5 */
00660        REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE);
00661        REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE);
00662 #endif 
00663 
00664 #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
00665        REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
00666        /* http authentication options */
00667        REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
00668        REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
00669        REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
00670        REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
00671        REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
00672        REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
00673 #endif
00674 
00675 #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
00676        REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
00677        REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
00678 #endif
00679 
00680        REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
00681 
00682        /* Constants effecting the way CURLOPT_CLOSEPOLICY works */
00683        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
00684        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC);
00685        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_SLOWEST);
00686        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_CALLBACK);
00687        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_OLDEST);
00688 
00689        /* Info constants */
00690        REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
00691        REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
00692        REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
00693        REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
00694        REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
00695        REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
00696        REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
00697        REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
00698        REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
00699        REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
00700        REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
00701        REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
00702        REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
00703        REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
00704        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
00705        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
00706        REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
00707        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
00708        REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
00709        REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
00710        REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
00711        REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
00712 #if LIBCURL_VERSION_NUM >  0x071301
00713        REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO);
00714 #endif
00715 #if LIBCURL_VERSION_NUM >= 0x071202
00716     REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
00717 #endif
00718 
00719 
00720        /* cURL protocol constants (curl_version) */
00721        REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
00722        REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
00723        REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
00724        REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
00725 
00726        /* version constants */
00727        REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
00728 
00729        /* Error Constants */
00730        REGISTER_CURL_CONSTANT(CURLE_OK);
00731        REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
00732        REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
00733        REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
00734        REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
00735        REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
00736        REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
00737        REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
00738        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
00739        REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
00740        REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
00741        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
00742        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
00743        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
00744        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
00745        REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
00746        REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
00747        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
00748        REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
00749        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
00750        REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
00751        REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
00752        REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
00753        REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
00754        REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
00755        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
00756        REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
00757        REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
00758        REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
00759        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
00760        REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
00761        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
00762        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
00763        REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
00764        REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
00765        REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
00766        REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
00767        REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
00768        REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
00769        REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
00770        REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
00771        REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
00772        REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
00773        REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
00774        REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
00775        REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
00776        REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
00777        REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
00778        REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
00779        REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
00780        REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
00781        REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
00782        REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
00783        REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
00784        REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
00785        REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
00786        REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
00787        REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
00788        REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
00789        REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
00790        REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
00791        REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
00792 #if LIBCURL_VERSION_NUM >= 0x070a08
00793        REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
00794        REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
00795 #endif
00796 #if LIBCURL_VERSION_NUM >= 0x070b00
00797        REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
00798 #endif
00799        REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
00800        REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
00801        REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
00802 
00803        REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
00804        REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
00805        REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
00806 
00807        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
00808        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
00809        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
00810 
00811        REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
00812        REGISTER_CURL_CONSTANT(CURLM_OK);
00813        REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
00814        REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
00815        REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
00816        REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
00817 
00818        REGISTER_CURL_CONSTANT(CURLMSG_DONE);
00819 
00820 #if LIBCURL_VERSION_NUM >= 0x070c02
00821        REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
00822        REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
00823        REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
00824        REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
00825 #endif
00826 
00827 #if LIBCURL_VERSION_NUM >  0x070b00
00828        REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
00829        REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
00830        REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
00831        REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
00832        REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
00833 #endif
00834 
00835 #if LIBCURL_VERSION_NUM > 0x071301
00836        REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO);
00837        REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR);
00838 #endif
00839 
00840 /* SSH support works in 7.19.0+ using libssh2 */
00841 #if LIBCURL_VERSION_NUM >= 0x071300
00842        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE);
00843        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY);
00844        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD);
00845        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST);
00846        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD);
00847        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT);
00848        REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES);
00849        REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD);
00850        REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE);
00851        REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE);
00852        REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
00853        REGISTER_CURL_CONSTANT(CURLE_SSH);
00854 #endif
00855 
00856 #if LIBCURL_VERSION_NUM >= 0x071304
00857        REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
00858        REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
00859        REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
00860        REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
00861        REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
00862        REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
00863        REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
00864        REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
00865        REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
00866        REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
00867        REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
00868        REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
00869        REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
00870        REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
00871        REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
00872 #endif
00873 
00874 #if LIBCURL_VERSION_NUM >= 0x070f01
00875        REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD);
00876        REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP);
00877 #endif
00878 
00879 #if LIBCURL_VERSION_NUM >= 0x071001
00880        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD);
00881        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD);
00882        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD);
00883 #endif
00884 
00885 #ifdef PHP_CURL_NEED_OPENSSL_TSL
00886        if (!CRYPTO_get_id_callback()) {
00887               int i, c = CRYPTO_num_locks();
00888 
00889               php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
00890               if (!php_curl_openssl_tsl) {
00891                      return FAILURE;
00892               }
00893 
00894               for (i = 0; i < c; ++i) {
00895                      php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
00896               }
00897 
00898               CRYPTO_set_id_callback(php_curl_ssl_id);
00899               CRYPTO_set_locking_callback(php_curl_ssl_lock);
00900        }
00901 #endif
00902 #ifdef PHP_CURL_NEED_GNUTLS_TSL
00903        gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
00904 #endif
00905 
00906        if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
00907               return FAILURE;
00908        }
00909 
00910 #ifdef PHP_CURL_URL_WRAPPERS
00911 # if HAVE_CURL_VERSION_INFO
00912        {
00913               curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
00914               char **p = (char **)info->protocols;
00915 
00916               while (*p != NULL) {
00917                      /* Do not enable cURL "file" protocol and make sure cURL is always used when --with-curlwrappers is enabled */
00918                      if (strncasecmp(*p, "file", sizeof("file")-1) != 0) {
00919                             php_unregister_url_stream_wrapper(*p TSRMLS_CC);
00920                             php_register_url_stream_wrapper(*p, &php_curl_wrapper TSRMLS_CC);
00921                      }
00922                      (void) *p++;
00923               }
00924        }
00925 # else
00926        php_unregister_url_stream_wrapper("http");
00927        php_register_url_stream_wrapper("http", &php_curl_wrapper TSRMLS_CC);
00928        php_unregister_url_stream_wrapper("https");
00929        php_register_url_stream_wrapper("https", &php_curl_wrapper TSRMLS_CC);
00930        php_unregister_url_stream_wrapper("ftp");
00931        php_register_url_stream_wrapper("ftp", &php_curl_wrapper TSRMLS_CC);
00932        php_unregister_url_stream_wrapper("ftps");
00933        php_register_url_stream_wrapper("ftps", &php_curl_wrapper TSRMLS_CC);
00934        php_unregister_url_stream_wrapper("ldap");
00935        php_register_url_stream_wrapper("ldap", &php_curl_wrapper TSRMLS_CC);
00936 # endif
00937 #endif
00938 
00939        return SUCCESS;
00940 }
00941 /* }}} */
00942 
00943 /* {{{ PHP_MSHUTDOWN_FUNCTION
00944  */
00945 PHP_MSHUTDOWN_FUNCTION(curl)
00946 {
00947 #ifdef PHP_CURL_URL_WRAPPERS
00948        php_unregister_url_stream_wrapper("http" TSRMLS_CC);
00949        php_unregister_url_stream_wrapper("https" TSRMLS_CC);
00950        php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
00951        php_unregister_url_stream_wrapper("ldap" TSRMLS_CC);
00952 #endif
00953        curl_global_cleanup();
00954 #ifdef PHP_CURL_NEED_OPENSSL_TSL
00955        if (php_curl_openssl_tsl) {
00956               int i, c = CRYPTO_num_locks();
00957 
00958               CRYPTO_set_id_callback(NULL);
00959               CRYPTO_set_locking_callback(NULL);
00960 
00961               for (i = 0; i < c; ++i) {
00962                      tsrm_mutex_free(php_curl_openssl_tsl[i]);
00963               }
00964 
00965               free(php_curl_openssl_tsl);
00966               php_curl_openssl_tsl = NULL;
00967        }
00968 #endif
00969        UNREGISTER_INI_ENTRIES();
00970        return SUCCESS;
00971 }
00972 /* }}} */
00973 
00974 /* {{{ curl_write
00975  */
00976 static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
00977 {
00978        php_curl       *ch     = (php_curl *) ctx;
00979        php_curl_write *t      = ch->handlers->write;
00980        size_t          length = size * nmemb;
00981        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
00982 
00983 #if PHP_CURL_DEBUG
00984        fprintf(stderr, "curl_write() called\n");
00985        fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
00986 #endif
00987 
00988        switch (t->method) {
00989               case PHP_CURL_STDOUT:
00990                      PHPWRITE(data, length);
00991                      break;
00992               case PHP_CURL_FILE:
00993                      return fwrite(data, size, nmemb, t->fp);
00994               case PHP_CURL_RETURN:
00995                      if (length > 0) {
00996                             smart_str_appendl(&t->buf, data, (int) length);
00997                      }
00998                      break;
00999               case PHP_CURL_USER: {
01000                      zval **argv[2];
01001                      zval *retval_ptr = NULL;
01002                      zval *handle = NULL;
01003                      zval *zdata = NULL;
01004                      int   error;
01005                      zend_fcall_info fci;
01006 
01007                      MAKE_STD_ZVAL(handle);
01008                      ZVAL_RESOURCE(handle, ch->id);
01009                      zend_list_addref(ch->id);
01010                      argv[0] = &handle;
01011 
01012                      MAKE_STD_ZVAL(zdata);
01013                      ZVAL_STRINGL(zdata, data, length, 1);
01014                      argv[1] = &zdata;
01015 
01016                      fci.size = sizeof(fci);
01017                      fci.function_table = EG(function_table);
01018                      fci.object_ptr = NULL;
01019                      fci.function_name = t->func_name;
01020                      fci.retval_ptr_ptr = &retval_ptr;
01021                      fci.param_count = 2;
01022                      fci.params = argv;
01023                      fci.no_separation = 0;
01024                      fci.symbol_table = NULL;
01025 
01026                      ch->in_callback = 1;
01027                      error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
01028                      ch->in_callback = 0;
01029                      if (error == FAILURE) {
01030                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
01031                             length = -1;
01032                      } else if (retval_ptr) {
01033                             if (Z_TYPE_P(retval_ptr) != IS_LONG) {
01034                                    convert_to_long_ex(&retval_ptr);
01035                             }
01036                             length = Z_LVAL_P(retval_ptr);
01037                             zval_ptr_dtor(&retval_ptr);
01038                      }
01039 
01040                      zval_ptr_dtor(argv[0]);
01041                      zval_ptr_dtor(argv[1]);
01042                      break;
01043               }
01044        }
01045 
01046        return length;
01047 }
01048 /* }}} */
01049 
01050 /* {{{ curl_progress
01051  */
01052 static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
01053 {
01054        php_curl       *ch = (php_curl *) clientp;
01055        php_curl_progress  *t  = ch->handlers->progress;
01056        int             length = -1;
01057        size_t rval = 0;
01058 
01059 #if PHP_CURL_DEBUG
01060        fprintf(stderr, "curl_progress() called\n");
01061        fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
01062 #endif
01063 
01064        switch (t->method) {
01065               case PHP_CURL_USER: {
01066                      zval **argv[4];
01067                      zval  *zdltotal = NULL;
01068                      zval  *zdlnow = NULL;
01069                      zval  *zultotal = NULL;
01070                      zval  *zulnow = NULL;
01071                      zval  *retval_ptr;
01072                      int   error;
01073                      zend_fcall_info fci;
01074                      TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
01075 
01076                      MAKE_STD_ZVAL(zdltotal);
01077                      MAKE_STD_ZVAL(zdlnow);
01078                      MAKE_STD_ZVAL(zultotal);
01079                      MAKE_STD_ZVAL(zulnow);
01080 
01081                      ZVAL_LONG(zdltotal, (long) dltotal);
01082                      ZVAL_LONG(zdlnow, (long) dlnow);
01083                      ZVAL_LONG(zultotal, (long) ultotal);
01084                      ZVAL_LONG(zulnow, (long) ulnow);
01085 
01086                      argv[0] = &zdltotal;
01087                      argv[1] = &zdlnow;
01088                      argv[2] = &zultotal;
01089                      argv[3] = &zulnow;
01090 
01091                      fci.size = sizeof(fci);
01092                      fci.function_table = EG(function_table);
01093                      fci.function_name = t->func_name;
01094                      fci.object_ptr = NULL;
01095                      fci.retval_ptr_ptr = &retval_ptr;
01096                      fci.param_count = 4;
01097                      fci.params = argv;
01098                      fci.no_separation = 0;
01099                      fci.symbol_table = NULL;
01100 
01101                      ch->in_callback = 1;
01102                      error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
01103                      ch->in_callback = 0;
01104                      if (error == FAILURE) {
01105                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
01106                             length = -1;
01107                      } else if (retval_ptr) {
01108                             if (Z_TYPE_P(retval_ptr) != IS_LONG) {
01109                                    convert_to_long_ex(&retval_ptr);
01110                             }
01111                             if (0 != Z_LVAL_P(retval_ptr)) {
01112                                    rval = 1;
01113                             }
01114                             zval_ptr_dtor(&retval_ptr);
01115                      }
01116                      zval_ptr_dtor(argv[0]);
01117                      zval_ptr_dtor(argv[1]);
01118                      zval_ptr_dtor(argv[2]);
01119                      zval_ptr_dtor(argv[3]);
01120                      break;
01121               }
01122        }
01123        return rval;
01124 }
01125 /* }}} */
01126 
01127 /* {{{ curl_read
01128  */
01129 static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
01130 {
01131        php_curl       *ch = (php_curl *) ctx;
01132        php_curl_read  *t  = ch->handlers->read;
01133        int             length = 0;
01134 
01135        switch (t->method) {
01136               case PHP_CURL_DIRECT:
01137                      if (t->fp) {
01138                             length = fread(data, size, nmemb, t->fp);
01139                      }
01140                      break;
01141               case PHP_CURL_USER: {
01142                      zval **argv[3];
01143                      zval  *handle = NULL;
01144                      zval  *zfd = NULL;
01145                      zval  *zlength = NULL;
01146                      zval  *retval_ptr;
01147                      int   error;
01148                      zend_fcall_info fci;
01149                      TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
01150 
01151                      MAKE_STD_ZVAL(handle);
01152                      MAKE_STD_ZVAL(zfd);
01153                      MAKE_STD_ZVAL(zlength);
01154 
01155                      ZVAL_RESOURCE(handle, ch->id);
01156                      zend_list_addref(ch->id);
01157                      ZVAL_RESOURCE(zfd, t->fd);
01158                      zend_list_addref(t->fd);
01159                      ZVAL_LONG(zlength, (int) size * nmemb);
01160 
01161                      argv[0] = &handle;
01162                      argv[1] = &zfd;
01163                      argv[2] = &zlength;
01164 
01165                      fci.size = sizeof(fci);
01166                      fci.function_table = EG(function_table);
01167                      fci.function_name = t->func_name;
01168                      fci.object_ptr = NULL;
01169                      fci.retval_ptr_ptr = &retval_ptr;
01170                      fci.param_count = 3;
01171                      fci.params = argv;
01172                      fci.no_separation = 0;
01173                      fci.symbol_table = NULL;
01174 
01175                      ch->in_callback = 1;
01176                      error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
01177                      ch->in_callback = 0;
01178                      if (error == FAILURE) {
01179                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
01180 #if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
01181                             length = CURL_READFUNC_ABORT;
01182 #endif
01183                      } else if (retval_ptr) {
01184                             if (Z_TYPE_P(retval_ptr) == IS_STRING) {
01185                                    length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr));
01186                                    memcpy(data, Z_STRVAL_P(retval_ptr), length);
01187                             }
01188                             zval_ptr_dtor(&retval_ptr);
01189                      }
01190 
01191                      zval_ptr_dtor(argv[0]);
01192                      zval_ptr_dtor(argv[1]);
01193                      zval_ptr_dtor(argv[2]);
01194                      break;
01195               }
01196        }
01197 
01198        return length;
01199 }
01200 /* }}} */
01201 
01202 /* {{{ curl_write_header
01203  */
01204 static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
01205 {
01206        php_curl       *ch  = (php_curl *) ctx;
01207        php_curl_write *t   = ch->handlers->write_header;
01208        size_t          length = size * nmemb;
01209        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
01210 
01211        switch (t->method) {
01212               case PHP_CURL_STDOUT:
01213                      /* Handle special case write when we're returning the entire transfer
01214                       */
01215                      if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
01216                             smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
01217                      } else {
01218                             PHPWRITE(data, length);
01219                      }
01220                      break;
01221               case PHP_CURL_FILE:
01222                      return fwrite(data, size, nmemb, t->fp);
01223               case PHP_CURL_USER: {
01224                      zval **argv[2];
01225                      zval  *handle = NULL;
01226                      zval  *zdata = NULL;
01227                      zval  *retval_ptr;
01228                      int   error;
01229                      zend_fcall_info fci;
01230 
01231                      MAKE_STD_ZVAL(handle);
01232                      MAKE_STD_ZVAL(zdata);
01233 
01234                      ZVAL_RESOURCE(handle, ch->id);
01235                      zend_list_addref(ch->id);
01236                      ZVAL_STRINGL(zdata, data, length, 1);
01237 
01238                      argv[0] = &handle;
01239                      argv[1] = &zdata;
01240 
01241                      fci.size = sizeof(fci);
01242                      fci.function_table = EG(function_table);
01243                      fci.function_name = t->func_name;
01244                      fci.symbol_table = NULL;
01245                      fci.object_ptr = NULL;
01246                      fci.retval_ptr_ptr = &retval_ptr;
01247                      fci.param_count = 2;
01248                      fci.params = argv;
01249                      fci.no_separation = 0;
01250 
01251                      ch->in_callback = 1;
01252                      error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
01253                      ch->in_callback = 0;
01254                      if (error == FAILURE) {
01255                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
01256                             length = -1;
01257                      } else if (retval_ptr) {
01258                             if (Z_TYPE_P(retval_ptr) != IS_LONG) {
01259                                    convert_to_long_ex(&retval_ptr);
01260                             }
01261                             length = Z_LVAL_P(retval_ptr);
01262                             zval_ptr_dtor(&retval_ptr);
01263                      }
01264                      zval_ptr_dtor(argv[0]);
01265                      zval_ptr_dtor(argv[1]);
01266                      break;
01267               }
01268 
01269               case PHP_CURL_IGNORE:
01270                      return length;
01271 
01272               default:
01273                      return -1;
01274        }
01275 
01276        return length;
01277 }
01278 /* }}} */
01279 
01280 static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
01281 {
01282        php_curl    *ch   = (php_curl *) ctx;
01283 
01284        if (type == CURLINFO_HEADER_OUT) {
01285               if (ch->header.str_len) {
01286                      efree(ch->header.str);
01287               }
01288               if (buf_len > 0) {
01289                      ch->header.str = estrndup(buf, buf_len);
01290                      ch->header.str_len = buf_len;
01291               }
01292        }
01293 
01294        return 0;
01295 }
01296 /* }}} */
01297 
01298 #if CURLOPT_PASSWDFUNCTION != 0
01299 /* {{{ curl_passwd
01300  */
01301 static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
01302 {
01303        php_curl    *ch   = (php_curl *) ctx;
01304        zval        *func = ch->handlers->passwd;
01305        zval        *argv[3];
01306        zval        *retval = NULL;
01307        int          error;
01308        int          ret = -1;
01309        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
01310 
01311        MAKE_STD_ZVAL(argv[0]);
01312        MAKE_STD_ZVAL(argv[1]);
01313        MAKE_STD_ZVAL(argv[2]);
01314 
01315        ZVAL_RESOURCE(argv[0], ch->id);
01316        zend_list_addref(ch->id);
01317        ZVAL_STRING(argv[1], prompt, 1);
01318        ZVAL_LONG(argv[2], buflen);
01319 
01320        error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC);
01321        if (error == FAILURE) {
01322               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_PASSWDFUNCTION");
01323        } else if (Z_TYPE_P(retval) == IS_STRING) {
01324               if (Z_STRLEN_P(retval) > buflen) {
01325                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Returned password is too long for libcurl to handle");
01326               } else {
01327                      strlcpy(buf, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
01328               }
01329        } else {
01330               php_error_docref(NULL TSRMLS_CC, E_WARNING, "User handler '%s' did not return a string", Z_STRVAL_P(func));
01331        }
01332 
01333        zval_ptr_dtor(&argv[0]);
01334        zval_ptr_dtor(&argv[1]);
01335        zval_ptr_dtor(&argv[2]);
01336        zval_ptr_dtor(&retval);
01337 
01338        return ret;
01339 }
01340 /* }}} */
01341 #endif
01342 
01343 /* {{{ curl_free_string
01344  */
01345 static void curl_free_string(void **string)
01346 {
01347        efree(*string);
01348 }
01349 /* }}} */
01350 
01351 /* {{{ curl_free_post
01352  */
01353 static void curl_free_post(void **post)
01354 {
01355        curl_formfree((struct HttpPost *) *post);
01356 }
01357 /* }}} */
01358 
01359 /* {{{ curl_free_slist
01360  */
01361 static void curl_free_slist(void **slist)
01362 {
01363        curl_slist_free_all((struct curl_slist *) *slist);
01364 }
01365 /* }}} */
01366 
01367 /* {{{ proto array curl_version([int version])
01368    Return cURL version information. */
01369 PHP_FUNCTION(curl_version)
01370 {
01371        curl_version_info_data *d;
01372        long uversion = CURLVERSION_NOW;
01373 
01374        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) {
01375               return;
01376        }
01377 
01378        d = curl_version_info(uversion);
01379        if (d == NULL) {
01380               RETURN_FALSE;
01381        }
01382 
01383        array_init(return_value);
01384 
01385        CAAL("version_number", d->version_num);
01386        CAAL("age", d->age);
01387        CAAL("features", d->features);
01388        CAAL("ssl_version_number", d->ssl_version_num);
01389        CAAS("version", d->version);
01390        CAAS("host", d->host);
01391        CAAS("ssl_version", d->ssl_version);
01392        CAAS("libz_version", d->libz_version);
01393        /* Add an array of protocols */
01394        {
01395               char **p = (char **) d->protocols;
01396               zval  *protocol_list = NULL;
01397 
01398               MAKE_STD_ZVAL(protocol_list);
01399               array_init(protocol_list);
01400 
01401               while (*p != NULL) {
01402                      add_next_index_string(protocol_list, *p, 1);
01403                      p++;
01404               }
01405               CAAZ("protocols", protocol_list);
01406        }
01407 }
01408 /* }}} */
01409 
01410 /* {{{ alloc_curl_handle
01411  */
01412 static void alloc_curl_handle(php_curl **ch)
01413 {
01414        *ch                           = emalloc(sizeof(php_curl));
01415        (*ch)->to_free                = ecalloc(1, sizeof(struct _php_curl_free));
01416        (*ch)->handlers               = ecalloc(1, sizeof(php_curl_handlers));
01417        (*ch)->handlers->write        = ecalloc(1, sizeof(php_curl_write));
01418        (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
01419        (*ch)->handlers->read         = ecalloc(1, sizeof(php_curl_read));
01420        (*ch)->handlers->progress     = ecalloc(1, sizeof(php_curl_progress));
01421 
01422        (*ch)->in_callback = 0;
01423        (*ch)->header.str_len = 0;
01424 
01425        memset(&(*ch)->err, 0, sizeof((*ch)->err));
01426        (*ch)->handlers->write->stream = NULL;
01427        (*ch)->handlers->write_header->stream = NULL;
01428        (*ch)->handlers->read->stream = NULL;
01429 
01430        zend_llist_init(&(*ch)->to_free->str,   sizeof(char *),            (llist_dtor_func_t) curl_free_string, 0);
01431        zend_llist_init(&(*ch)->to_free->slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist,  0);
01432        zend_llist_init(&(*ch)->to_free->post,  sizeof(struct HttpPost),   (llist_dtor_func_t) curl_free_post,   0);
01433 }
01434 /* }}} */
01435 
01436 #if LIBCURL_VERSION_NUM > 0x071301
01437 /* {{{ split_certinfo
01438  */
01439 static void split_certinfo(char *string, zval *hash)
01440 {
01441        char *org = estrdup(string);
01442        char *s = org;
01443        char *split;
01444 
01445        if(org) {
01446         do {
01447                      char *key;
01448                      char *val;
01449                      char *tmp;
01450 
01451             split = strstr(s, "; ");
01452             if(split)
01453                 *split = '\0';
01454                      
01455                      key = s;
01456                      tmp = memchr(key, '=', 64);
01457                      if(tmp) {
01458                             *tmp = '\0';
01459                             val = tmp+1;
01460                             add_assoc_string(hash, key, val, 1);
01461                      }
01462                      s = split+2;
01463               } while(split);
01464               efree(org);
01465        }
01466 }
01467 /* }}} */
01468 
01469 /* {{{ create_certinfo
01470  */
01471 static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC)
01472 {
01473        int i;
01474                      
01475        if(ci) {
01476               zval *certhash = NULL;
01477               
01478               for(i=0; i<ci->num_of_certs; i++) {
01479                      struct curl_slist *slist;
01480                      
01481                      MAKE_STD_ZVAL(certhash);
01482                      array_init(certhash);
01483                      for(slist = ci->certinfo[i]; slist; slist = slist->next) {
01484                             int len;
01485                             char s[64];
01486                             char *tmp;
01487                             strncpy(s, slist->data, 64);
01488                             tmp = memchr(s, ':', 64);
01489                             if(tmp) {
01490                                    *tmp = '\0';
01491                                    len = strlen(s);
01492                                    if(!strcmp(s, "Subject") || !strcmp(s, "Issuer")) {
01493                                           zval *hash;
01494 
01495                                           MAKE_STD_ZVAL(hash);
01496                                           array_init(hash);
01497                                           
01498                                           split_certinfo(&slist->data[len+1], hash);
01499                                           add_assoc_zval(certhash, s, hash);
01500                                    } else {
01501                                           add_assoc_string(certhash, s, &slist->data[len+1], 1);
01502                                    }
01503                             } else {
01504                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info"); 
01505                             }
01506                      }
01507                      add_next_index_zval(listcode, certhash);
01508               }
01509        }
01510 }
01511 /* }}} */
01512 #endif
01513 
01514 /* {{{ proto resource curl_init([string url])
01515    Initialize a cURL session */
01516 PHP_FUNCTION(curl_init)
01517 {
01518        php_curl      *ch;
01519        CURL          *cp;
01520        zval          *clone;
01521        char          *url = NULL;
01522        int           url_len = 0;
01523        char *cainfo;
01524 
01525        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &url, &url_len) == FAILURE) {
01526               return;
01527        }
01528 
01529        cp = curl_easy_init();
01530        if (!cp) {
01531               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle");
01532               RETURN_FALSE;
01533        }
01534 
01535        alloc_curl_handle(&ch);
01536        TSRMLS_SET_CTX(ch->thread_ctx);
01537 
01538        ch->cp = cp;
01539 
01540        ch->handlers->write->method = PHP_CURL_STDOUT;
01541        ch->handlers->write->type   = PHP_CURL_ASCII;
01542        ch->handlers->read->method  = PHP_CURL_DIRECT;
01543        ch->handlers->write_header->method = PHP_CURL_IGNORE;
01544 
01545        ch->uses = 0;
01546 
01547        MAKE_STD_ZVAL(clone);
01548        ch->clone = clone;
01549 
01550 
01551 
01552        curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS,        1);
01553        curl_easy_setopt(ch->cp, CURLOPT_VERBOSE,           0);
01554        curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
01555        curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION,     curl_write);
01556        curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
01557        curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION,      curl_read);
01558        curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
01559        curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION,    curl_write_header);
01560        curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
01561        curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
01562        curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
01563        curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
01564 
01565        cainfo = INI_STR("curl.cainfo");
01566        if (cainfo && strlen(cainfo) > 0) {
01567               curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
01568        }
01569 
01570 #if defined(ZTS)
01571        curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
01572 #endif
01573 
01574        if (url) {
01575               if (!php_curl_option_url(ch, url, url_len)) {
01576                      _php_curl_close_ex(ch TSRMLS_CC);
01577                      RETURN_FALSE;
01578               }
01579        }
01580 
01581        ZEND_REGISTER_RESOURCE(return_value, ch, le_curl);
01582        ch->id = Z_LVAL_P(return_value);
01583 }
01584 /* }}} */
01585 
01586 /* {{{ proto resource curl_copy_handle(resource ch)
01587    Copy a cURL handle along with all of it's preferences */
01588 PHP_FUNCTION(curl_copy_handle)
01589 {
01590        CURL          *cp;
01591        zval          *zid;
01592        php_curl      *ch, *dupch;
01593 
01594        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
01595               return;
01596        }
01597 
01598        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
01599 
01600        cp = curl_easy_duphandle(ch->cp);
01601        if (!cp) {
01602               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot duplicate cURL handle");
01603               RETURN_FALSE;
01604        }
01605 
01606        alloc_curl_handle(&dupch);
01607        TSRMLS_SET_CTX(dupch->thread_ctx);
01608 
01609        dupch->cp = cp;
01610        dupch->uses = 0;
01611        ch->uses++;
01612        if (ch->handlers->write->stream) {
01613               Z_ADDREF_P(dupch->handlers->write->stream);
01614               dupch->handlers->write->stream = ch->handlers->write->stream;
01615        }
01616        dupch->handlers->write->method = ch->handlers->write->method;
01617        dupch->handlers->write->type   = ch->handlers->write->type;
01618        if (ch->handlers->read->stream) {
01619               Z_ADDREF_P(ch->handlers->read->stream);
01620        }
01621        dupch->handlers->read->stream  = ch->handlers->read->stream;
01622        dupch->handlers->read->method  = ch->handlers->read->method;
01623        dupch->handlers->write_header->method = ch->handlers->write_header->method;
01624        if (ch->handlers->write_header->stream) {
01625               Z_ADDREF_P(ch->handlers->write_header->stream);
01626        }
01627        dupch->handlers->write_header->stream = ch->handlers->write_header->stream;
01628 
01629        dupch->handlers->write->fp = ch->handlers->write->fp;
01630        dupch->handlers->write_header->fp = ch->handlers->write_header->fp;
01631        dupch->handlers->read->fp = ch->handlers->read->fp;
01632        dupch->handlers->read->fd = ch->handlers->read->fd;
01633 #if CURLOPT_PASSWDDATA != 0
01634        if (ch->handlers->passwd) {
01635               zval_add_ref(&ch->handlers->passwd);
01636               dupch->handlers->passwd = ch->handlers->passwd;
01637               curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) dupch);
01638        }
01639 #endif
01640        if (ch->handlers->write->func_name) {
01641               zval_add_ref(&ch->handlers->write->func_name);
01642               dupch->handlers->write->func_name = ch->handlers->write->func_name;
01643        }
01644        if (ch->handlers->read->func_name) {
01645               zval_add_ref(&ch->handlers->read->func_name);
01646               dupch->handlers->read->func_name = ch->handlers->read->func_name;
01647        }
01648        if (ch->handlers->write_header->func_name) {
01649               zval_add_ref(&ch->handlers->write_header->func_name);
01650               dupch->handlers->write_header->func_name = ch->handlers->write_header->func_name;
01651        }
01652        
01653        if (ch->handlers->progress->func_name) {
01654               zval_add_ref(&ch->handlers->progress->func_name);
01655               dupch->handlers->progress->func_name = ch->handlers->progress->func_name;
01656        }
01657        dupch->handlers->progress->method = ch->handlers->progress->method;
01658 
01659        curl_easy_setopt(dupch->cp, CURLOPT_ERRORBUFFER,       dupch->err.str);
01660        curl_easy_setopt(dupch->cp, CURLOPT_FILE,              (void *) dupch);
01661        curl_easy_setopt(dupch->cp, CURLOPT_INFILE,            (void *) dupch);
01662        curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER,       (void *) dupch);
01663        curl_easy_setopt(dupch->cp, CURLOPT_PROGRESSDATA,      (void *) dupch); 
01664 
01665        efree(dupch->to_free);
01666        dupch->to_free = ch->to_free;
01667 
01668        /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
01669        Z_ADDREF_P(ch->clone);
01670        dupch->clone = ch->clone;
01671 
01672        ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl);
01673        dupch->id = Z_LVAL_P(return_value);
01674 }
01675 /* }}} */
01676 
01677 static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */
01678 {
01679        CURLcode     error=CURLE_OK;
01680 
01681        switch (option) {
01682               case CURLOPT_INFILESIZE:
01683               case CURLOPT_VERBOSE:
01684               case CURLOPT_HEADER:
01685               case CURLOPT_NOPROGRESS:
01686               case CURLOPT_NOBODY:
01687               case CURLOPT_FAILONERROR:
01688               case CURLOPT_UPLOAD:
01689               case CURLOPT_POST:
01690               case CURLOPT_FTPLISTONLY:
01691               case CURLOPT_FTPAPPEND:
01692               case CURLOPT_NETRC:
01693               case CURLOPT_PUT:
01694 #if CURLOPT_MUTE != 0
01695                case CURLOPT_MUTE:
01696 #endif
01697               case CURLOPT_TIMEOUT:
01698 #if LIBCURL_VERSION_NUM > 0x071002
01699               case CURLOPT_TIMEOUT_MS:
01700 #endif
01701               case CURLOPT_FTP_USE_EPSV:
01702               case CURLOPT_LOW_SPEED_LIMIT:
01703               case CURLOPT_SSLVERSION:
01704               case CURLOPT_LOW_SPEED_TIME:
01705               case CURLOPT_RESUME_FROM:
01706               case CURLOPT_TIMEVALUE:
01707               case CURLOPT_TIMECONDITION:
01708               case CURLOPT_TRANSFERTEXT:
01709               case CURLOPT_HTTPPROXYTUNNEL:
01710               case CURLOPT_FILETIME:
01711               case CURLOPT_MAXREDIRS:
01712               case CURLOPT_MAXCONNECTS:
01713               case CURLOPT_CLOSEPOLICY:
01714               case CURLOPT_FRESH_CONNECT:
01715               case CURLOPT_FORBID_REUSE:
01716               case CURLOPT_CONNECTTIMEOUT:
01717 #if LIBCURL_VERSION_NUM > 0x071002
01718               case CURLOPT_CONNECTTIMEOUT_MS:
01719 #endif
01720               case CURLOPT_SSL_VERIFYHOST:
01721               case CURLOPT_SSL_VERIFYPEER:
01722               case CURLOPT_DNS_USE_GLOBAL_CACHE:
01723               case CURLOPT_NOSIGNAL:
01724               case CURLOPT_PROXYTYPE:
01725               case CURLOPT_BUFFERSIZE:
01726               case CURLOPT_HTTPGET:
01727               case CURLOPT_HTTP_VERSION:
01728               case CURLOPT_CRLF:
01729               case CURLOPT_DNS_CACHE_TIMEOUT:
01730               case CURLOPT_PROXYPORT:
01731               case CURLOPT_FTP_USE_EPRT:
01732 #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
01733               case CURLOPT_HTTPAUTH:
01734 #endif
01735 #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
01736               case CURLOPT_PROXYAUTH:
01737               case CURLOPT_FTP_CREATE_MISSING_DIRS:
01738 #endif
01739 
01740 #if LIBCURL_VERSION_NUM >= 0x070c02
01741               case CURLOPT_FTPSSLAUTH:
01742 #endif
01743 #if LIBCURL_VERSION_NUM >  0x070b00
01744               case CURLOPT_FTP_SSL:
01745 #endif
01746               case CURLOPT_UNRESTRICTED_AUTH:
01747               case CURLOPT_PORT:
01748               case CURLOPT_AUTOREFERER:
01749               case CURLOPT_COOKIESESSION:
01750 #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
01751               case CURLOPT_TCP_NODELAY:
01752 #endif
01753 #if LIBCURL_VERSION_NUM >= 0x71304
01754               case CURLOPT_REDIR_PROTOCOLS:
01755               case CURLOPT_PROTOCOLS:
01756 #endif
01757 #if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
01758               case CURLOPT_IPRESOLVE:
01759 #endif
01760 #if LIBCURL_VERSION_NUM >= 0x070f01
01761               case CURLOPT_FTP_FILEMETHOD:
01762               case CURLOPT_FTP_SKIP_PASV_IP:
01763 #endif
01764 #if LIBCURL_VERSION_NUM >  0x071301
01765               case CURLOPT_CERTINFO:
01766 #endif
01767                      convert_to_long_ex(zvalue);
01768 #if LIBCURL_VERSION_NUM >= 0x71304
01769                      if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
01770                             ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
01771                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when in safe_mode or an open_basedir is set");
01772                                    RETVAL_FALSE;
01773                                    return 1;
01774                      }
01775 #endif
01776                      error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
01777                      break;
01778 #if LIBCURL_VERSION_NUM > 0x070f04
01779               case CURLOPT_MAX_RECV_SPEED_LARGE:
01780               case CURLOPT_MAX_SEND_SPEED_LARGE:
01781                      convert_to_long_ex(zvalue);
01782                      error = curl_easy_setopt(ch->cp, option, (curl_off_t)Z_LVAL_PP(zvalue));
01783                      break;
01784 #endif
01785               case CURLOPT_FOLLOWLOCATION:
01786                      convert_to_long_ex(zvalue);
01787                      if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
01788                             if (Z_LVAL_PP(zvalue) != 0) {
01789                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set");
01790                                    RETVAL_FALSE;
01791                                    return 1;
01792                             }
01793                      }
01794                      error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
01795                      break;
01796 #if LIBCURL_VERSION_NUM > 0x071301
01797               case CURLOPT_POSTREDIR:
01798                      convert_to_long_ex(zvalue);
01799                      error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, Z_LVAL_PP(zvalue) & CURL_REDIR_POST_ALL);
01800                      break;
01801 #endif
01802               case CURLOPT_PRIVATE:
01803               case CURLOPT_URL:
01804               case CURLOPT_PROXY:
01805               case CURLOPT_USERPWD:
01806               case CURLOPT_PROXYUSERPWD:
01807               case CURLOPT_RANGE:
01808               case CURLOPT_CUSTOMREQUEST:
01809               case CURLOPT_USERAGENT:
01810               case CURLOPT_FTPPORT:
01811               case CURLOPT_COOKIE:
01812               case CURLOPT_REFERER:
01813               case CURLOPT_INTERFACE:
01814               case CURLOPT_KRB4LEVEL:
01815               case CURLOPT_EGDSOCKET:
01816               case CURLOPT_CAINFO:
01817               case CURLOPT_CAPATH:
01818               case CURLOPT_SSL_CIPHER_LIST:
01819               case CURLOPT_SSLKEY:
01820               case CURLOPT_SSLKEYTYPE:
01821               case CURLOPT_SSLKEYPASSWD:
01822               case CURLOPT_SSLENGINE:
01823               case CURLOPT_SSLENGINE_DEFAULT:
01824               case CURLOPT_SSLCERTTYPE:
01825               case CURLOPT_ENCODING:
01826 #if LIBCURL_VERSION_NUM >= 0x071300
01827               case CURLOPT_SSH_PUBLIC_KEYFILE:
01828               case CURLOPT_SSH_PRIVATE_KEYFILE:
01829 #endif
01830               {
01831 #if LIBCURL_VERSION_NUM < 0x071100
01832                      char *copystr = NULL;
01833 #endif
01834 
01835                      convert_to_string_ex(zvalue);
01836 #if LIBCURL_VERSION_NUM >= 0x071300
01837                      if (
01838                             option == CURLOPT_SSH_PUBLIC_KEYFILE || option == CURLOPT_SSH_PRIVATE_KEYFILE
01839 
01840                      ) {
01841                             if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) {
01842                                    RETVAL_FALSE;
01843                                    return 1;
01844                             }
01845                      }
01846 #endif
01847                      if (option == CURLOPT_URL) {
01848                             if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue))) {
01849                                    RETVAL_FALSE;
01850                                    return 1;
01851                             }
01852                      } else {
01853                             if (option == CURLOPT_PRIVATE) {
01854                                    char *copystr;
01855 #if LIBCURL_VERSION_NUM < 0x071100
01856 string_copy:
01857 #endif
01858                                    copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
01859                                    error = curl_easy_setopt(ch->cp, option, copystr);
01860                                    zend_llist_add_element(&ch->to_free->str, &copystr);
01861                             } else {
01862 #if LIBCURL_VERSION_NUM >= 0x071100
01863                                    /* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
01864                                    error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
01865 #else                       
01866                                    goto string_copy;                  
01867 #endif
01868                             }
01869                      }
01870                      break;
01871               }
01872               case CURLOPT_FILE:
01873               case CURLOPT_INFILE:
01874               case CURLOPT_WRITEHEADER:
01875               case CURLOPT_STDERR: {
01876                      FILE *fp = NULL;
01877                      int type;
01878                      void * what;
01879 
01880                      what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream(), php_file_le_pstream());
01881                      if (!what) {
01882                             RETVAL_FALSE;
01883                             return 1;
01884                      }
01885 
01886                      if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
01887                             RETVAL_FALSE;
01888                             return 1;
01889                      }
01890 
01891                      if (!fp) {
01892                             RETVAL_FALSE;
01893                             return 1;
01894                      }
01895 
01896                      error = CURLE_OK;
01897                      switch (option) {
01898                             case CURLOPT_FILE:
01899                                    if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
01900                                           if (ch->handlers->write->stream) {
01901                                                  Z_DELREF_P(ch->handlers->write->stream);
01902                                           }
01903                                           Z_ADDREF_PP(zvalue);
01904                                           ch->handlers->write->fp = fp;
01905                                           ch->handlers->write->method = PHP_CURL_FILE;
01906                                           ch->handlers->write->stream = *zvalue;
01907                                    } else {
01908                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
01909                                           RETVAL_FALSE;
01910                                           return 1;
01911                                    }
01912                                    break;
01913                             case CURLOPT_WRITEHEADER:
01914                                    if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
01915                                           if (ch->handlers->write_header->stream) {
01916                                                  Z_DELREF_P(ch->handlers->write_header->stream);
01917                                           }
01918                                           Z_ADDREF_PP(zvalue);
01919                                           ch->handlers->write_header->fp = fp;
01920                                           ch->handlers->write_header->method = PHP_CURL_FILE;
01921                                           ch->handlers->write_header->stream = *zvalue;
01922                                    } else {
01923                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
01924                                           RETVAL_FALSE;
01925                                           return 1;
01926                                    }
01927                                    break;
01928                             case CURLOPT_INFILE:
01929                                    if (ch->handlers->read->stream) {
01930                                           Z_DELREF_P(ch->handlers->read->stream);
01931                                    }
01932                                    Z_ADDREF_PP(zvalue);
01933                                    ch->handlers->read->fp = fp;
01934                                    ch->handlers->read->fd = Z_LVAL_PP(zvalue);
01935                                    ch->handlers->read->stream = *zvalue;
01936                                    break;
01937                             case CURLOPT_STDERR:
01938                                    if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
01939                                           if (ch->handlers->std_err) {
01940                                                  zval_ptr_dtor(&ch->handlers->std_err);
01941                                           }
01942                                           zval_add_ref(zvalue);
01943                                           ch->handlers->std_err = *zvalue;
01944                                    } else {
01945                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
01946                                           RETVAL_FALSE;
01947                                           return 1;
01948                                    }
01949                                    /* break omitted intentionally */
01950                             default:
01951                                    error = curl_easy_setopt(ch->cp, option, fp);
01952                                    break;
01953                      }
01954 
01955                      break;
01956               }
01957               case CURLOPT_RETURNTRANSFER:
01958                      convert_to_long_ex(zvalue);
01959 
01960                      if (Z_LVAL_PP(zvalue)) {
01961                             ch->handlers->write->method = PHP_CURL_RETURN;
01962                      } else {
01963                             ch->handlers->write->method = PHP_CURL_STDOUT;
01964                      }
01965                      break;
01966               case CURLOPT_BINARYTRANSFER:
01967                      convert_to_long_ex(zvalue);
01968 
01969                      if (Z_LVAL_PP(zvalue)) {
01970                             ch->handlers->write->type = PHP_CURL_BINARY;
01971                      } else {
01972                             ch->handlers->write->type = PHP_CURL_ASCII;
01973                      }
01974                      break;
01975               case CURLOPT_WRITEFUNCTION:
01976                      if (ch->handlers->write->func_name) {
01977                             zval_ptr_dtor(&ch->handlers->write->func_name);
01978                             ch->handlers->write->fci_cache = empty_fcall_info_cache;
01979                      }
01980                      zval_add_ref(zvalue);
01981                      ch->handlers->write->func_name = *zvalue;
01982                      ch->handlers->write->method = PHP_CURL_USER;
01983                      break;
01984               case CURLOPT_READFUNCTION:
01985                      if (ch->handlers->read->func_name) {
01986                             zval_ptr_dtor(&ch->handlers->read->func_name);
01987                             ch->handlers->read->fci_cache = empty_fcall_info_cache;
01988                      }
01989                      zval_add_ref(zvalue);
01990                      ch->handlers->read->func_name = *zvalue;
01991                      ch->handlers->read->method = PHP_CURL_USER;
01992                      break;
01993               case CURLOPT_PROGRESSFUNCTION:
01994                      curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION,      curl_progress);
01995                      curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
01996                      if (ch->handlers->progress->func_name) {
01997                             zval_ptr_dtor(&ch->handlers->progress->func_name);
01998                             ch->handlers->progress->fci_cache = empty_fcall_info_cache;
01999                      }
02000                      zval_add_ref(zvalue);
02001                      ch->handlers->progress->func_name = *zvalue;
02002                      ch->handlers->progress->method = PHP_CURL_USER;
02003                      break;
02004               case CURLOPT_HEADERFUNCTION:
02005                      if (ch->handlers->write_header->func_name) {
02006                             zval_ptr_dtor(&ch->handlers->write_header->func_name);
02007                             ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
02008                      }
02009                      zval_add_ref(zvalue);
02010                      ch->handlers->write_header->func_name = *zvalue;
02011                      ch->handlers->write_header->method = PHP_CURL_USER;
02012                      break;
02013 #if CURLOPT_PASSWDFUNCTION != 0
02014               case CURLOPT_PASSWDFUNCTION:
02015                      if (ch->handlers->passwd) {
02016                             zval_ptr_dtor(&ch->handlers->passwd);
02017                      }
02018                      zval_add_ref(zvalue);
02019                      ch->handlers->passwd = *zvalue;
02020                      error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd);
02021                      error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA,     (void *) ch);
02022                      break;
02023 #endif
02024               case CURLOPT_POSTFIELDS:
02025                      if (Z_TYPE_PP(zvalue) == IS_ARRAY || Z_TYPE_PP(zvalue) == IS_OBJECT) {
02026                             zval            **current;
02027                             HashTable        *postfields;
02028                             struct HttpPost  *first = NULL;
02029                             struct HttpPost  *last  = NULL;
02030                             char             *postval;
02031                             char             *string_key = NULL;
02032                             ulong             num_key;
02033                             uint              string_key_len;
02034 
02035                             postfields = HASH_OF(*zvalue);
02036                             if (!postfields) {
02037                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
02038                                    RETVAL_FALSE;
02039                                    return 1;
02040                             }
02041 
02042                             for (zend_hash_internal_pointer_reset(postfields);
02043                                     zend_hash_get_current_data(postfields, (void **) &current) == SUCCESS;
02044                                     zend_hash_move_forward(postfields)
02045                             ) {
02046 
02047                                    SEPARATE_ZVAL(current);
02048                                    convert_to_string_ex(current);
02049 
02050                                    zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL);
02051 
02052                                    postval = Z_STRVAL_PP(current);
02053 
02054                                    /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
02055                                     * must be explicitly cast to long in curl_formadd
02056                                     * use since curl needs a long not an int. */
02057                                    if (*postval == '@') {
02058                                           char *type, *filename;
02059                                           ++postval;
02060 
02061                                           if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) {
02062                                                  *type = '\0';
02063                                           }
02064                                           if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) {
02065                                                  *filename = '\0';
02066                                           }
02067                                           /* safe_mode / open_basedir check */
02068                                           if (php_check_open_basedir(postval TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(postval, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
02069                                                  RETVAL_FALSE;
02070                                                  return 1;
02071                                           }
02072                                           error = curl_formadd(&first, &last,
02073                                                                       CURLFORM_COPYNAME, string_key,
02074                                                                       CURLFORM_NAMELENGTH, (long)string_key_len - 1,
02075                                                                       CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval,
02076                                                                       CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream",
02077                                                                       CURLFORM_FILE, postval,
02078                                                                       CURLFORM_END);
02079                                           if (type) {
02080                                                  *type = ';';
02081                                           }
02082                                           if (filename) {
02083                                                  *filename = ';';
02084                                           }
02085                                    } else {
02086                                           error = curl_formadd(&first, &last,
02087                                                                               CURLFORM_COPYNAME, string_key,
02088                                                                               CURLFORM_NAMELENGTH, (long)string_key_len - 1,
02089                                                                               CURLFORM_COPYCONTENTS, postval,
02090                                                                               CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current),
02091                                                                               CURLFORM_END);
02092                                    }
02093                             }
02094 
02095                             SAVE_CURL_ERROR(ch, error);
02096                             if (error != CURLE_OK) {
02097                                    RETVAL_FALSE;
02098                                    return 1;
02099                             }
02100 
02101                             zend_llist_add_element(&ch->to_free->post, &first);
02102                             error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
02103 
02104                      } else {
02105 #if LIBCURL_VERSION_NUM >= 0x071101
02106                             convert_to_string_ex(zvalue);
02107                             /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
02108                             error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
02109                             error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue));
02110 #else
02111                             char *post = NULL;
02112 
02113                             convert_to_string_ex(zvalue);
02114                             post = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
02115                             zend_llist_add_element(&ch->to_free->str, &post);
02116 
02117                             error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
02118                             error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
02119 #endif
02120                      }
02121                      break;
02122               case CURLOPT_HTTPHEADER:
02123               case CURLOPT_QUOTE:
02124               case CURLOPT_HTTP200ALIASES:
02125               case CURLOPT_POSTQUOTE: {
02126                      zval              **current;
02127                      HashTable          *ph;
02128                      struct curl_slist  *slist = NULL;
02129 
02130                      ph = HASH_OF(*zvalue);
02131                      if (!ph) {
02132                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must pass either an object or an array with the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE arguments");
02133                             RETVAL_FALSE;
02134                             return 1;
02135                      }
02136 
02137                      for (zend_hash_internal_pointer_reset(ph);
02138                              zend_hash_get_current_data(ph, (void **) &current) == SUCCESS;
02139                              zend_hash_move_forward(ph)
02140                      ) {
02141                             SEPARATE_ZVAL(current);
02142                             convert_to_string_ex(current);
02143 
02144                             slist = curl_slist_append(slist, Z_STRVAL_PP(current));
02145                             if (!slist) {
02146                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist");
02147                                    RETVAL_FALSE;
02148                                    return 1;
02149                             }
02150                      }
02151                      zend_llist_add_element(&ch->to_free->slist, &slist);
02152 
02153                      error = curl_easy_setopt(ch->cp, option, slist);
02154 
02155                      break;
02156               }
02157               /* the following options deal with files, therefor safe_mode & open_basedir checks
02158                * are required.
02159                */
02160               case CURLOPT_COOKIEJAR:
02161               case CURLOPT_SSLCERT:
02162               case CURLOPT_RANDOM_FILE:
02163               case CURLOPT_COOKIEFILE: {
02164 #if LIBCURL_VERSION_NUM < 0x071100
02165                      char *copystr = NULL;
02166 #endif
02167 
02168                      convert_to_string_ex(zvalue);
02169 
02170                      if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) {
02171                             RETVAL_FALSE;
02172                             return 1;
02173                      }
02174 
02175 #if LIBCURL_VERSION_NUM >= 0x071100
02176                      error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
02177 #else
02178                      copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
02179 
02180                      error = curl_easy_setopt(ch->cp, option, copystr);
02181                      zend_llist_add_element(&ch->to_free->str, &copystr);
02182 #endif
02183                      break;
02184               }
02185               case CURLINFO_HEADER_OUT:
02186                      convert_to_long_ex(zvalue);
02187                      if (Z_LVAL_PP(zvalue) == 1) {
02188                             curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
02189                             curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
02190                             curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
02191                      } else {
02192                             curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
02193                             curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
02194                             curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
02195                      }
02196                      break;
02197        }
02198 
02199        SAVE_CURL_ERROR(ch, error);
02200        if (error != CURLE_OK) {
02201               return 1;
02202        } else {
02203               return 0;
02204        }
02205 }
02206 /* }}} */
02207 
02208 /* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
02209    Set an option for a cURL transfer */
02210 PHP_FUNCTION(curl_setopt)
02211 {
02212        zval       *zid, **zvalue;
02213        long        options;
02214        php_curl   *ch;
02215 
02216        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &zid, &options, &zvalue) == FAILURE) {
02217               return;
02218        }
02219 
02220        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02221 
02222        if (options <= 0) {
02223               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid curl configuration option");
02224               RETURN_FALSE;
02225        }
02226 
02227        if (!_php_curl_setopt(ch, options, zvalue, return_value TSRMLS_CC)) {
02228               RETURN_TRUE;
02229        } else {
02230               RETURN_FALSE;
02231        }
02232 }
02233 /* }}} */
02234 
02235 /* {{{ proto bool curl_setopt_array(resource ch, array options)
02236    Set an array of option for a cURL transfer */
02237 PHP_FUNCTION(curl_setopt_array)
02238 {
02239        zval          *zid, *arr, **entry;
02240        php_curl      *ch;
02241        ulong         option;
02242        HashPosition  pos;
02243        char          *string_key;
02244        uint          str_key_len;
02245 
02246        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &zid, &arr) == FAILURE) {
02247               return;
02248        }
02249 
02250        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02251 
02252        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
02253        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
02254               if (zend_hash_get_current_key_ex(Z_ARRVAL_P(arr), &string_key, &str_key_len, &option, 0, &pos) != HASH_KEY_IS_LONG) {
02255                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values");
02256                      RETURN_FALSE;
02257               }
02258               if (_php_curl_setopt(ch, (long) option, entry, return_value TSRMLS_CC)) {
02259                      RETURN_FALSE;
02260               }
02261               zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
02262        }
02263        RETURN_TRUE;
02264 }
02265 /* }}} */
02266 
02267 /* {{{ _php_curl_cleanup_handle(ch)
02268    Cleanup an execution phase */
02269 void _php_curl_cleanup_handle(php_curl *ch)
02270 {
02271        if (ch->handlers->write->buf.len > 0) {
02272               smart_str_free(&ch->handlers->write->buf);
02273        }
02274        if (ch->header.str_len) {
02275               efree(ch->header.str);
02276               ch->header.str_len = 0;
02277        }
02278 
02279        memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
02280        ch->err.no = 0;
02281 }
02282 /* }}} */
02283 
02284 /* {{{ proto bool curl_exec(resource ch)
02285    Perform a cURL session */
02286 PHP_FUNCTION(curl_exec)
02287 {
02288        CURLcode      error;
02289        zval          *zid;
02290        php_curl      *ch;
02291 
02292        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
02293               return;
02294        }
02295 
02296        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02297 
02298        _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
02299 
02300        _php_curl_cleanup_handle(ch);
02301 
02302        error = curl_easy_perform(ch->cp);
02303        SAVE_CURL_ERROR(ch, error);
02304        /* CURLE_PARTIAL_FILE is returned by HEAD requests */
02305        if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) {
02306               if (ch->handlers->write->buf.len > 0) {
02307                      smart_str_free(&ch->handlers->write->buf);
02308               }
02309               RETURN_FALSE;
02310        }
02311 
02312        if (ch->handlers->std_err) {
02313               php_stream  *stream;
02314               stream = (php_stream*)zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
02315               if (stream) {
02316                      php_stream_flush(stream);
02317               }
02318        }
02319 
02320        if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
02321               smart_str_0(&ch->handlers->write->buf);
02322               RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
02323        }
02324 
02325        /* flush the file handle, so any remaining data is synched to disk */
02326        if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
02327               fflush(ch->handlers->write->fp);
02328        }
02329        if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
02330               fflush(ch->handlers->write_header->fp);
02331        }
02332 
02333        if (ch->handlers->write->method == PHP_CURL_RETURN) {
02334               RETURN_EMPTY_STRING();
02335        } else {
02336               RETURN_TRUE;
02337        }
02338 }
02339 /* }}} */
02340 
02341 /* {{{ proto mixed curl_getinfo(resource ch [, int option])
02342    Get information regarding a specific transfer */
02343 PHP_FUNCTION(curl_getinfo)
02344 {
02345        zval          *zid;
02346        php_curl      *ch;
02347        long          option = 0;
02348 
02349        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zid, &option) == FAILURE) {
02350               return;
02351        }
02352 
02353        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02354 
02355        if (ZEND_NUM_ARGS() < 2) {
02356               char   *s_code;
02357               long    l_code;
02358               double  d_code;
02359 #if LIBCURL_VERSION_NUM >  0x071301
02360               struct curl_certinfo *ci = NULL;
02361               zval *listcode;
02362 #endif
02363 
02364               array_init(return_value);
02365 
02366               if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
02367                      CAAS("url", s_code);
02368               }
02369               if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
02370                      if (s_code != NULL) {
02371                             CAAS("content_type", s_code);
02372                      } else {
02373                             zval *retnull;
02374                             MAKE_STD_ZVAL(retnull);
02375                             ZVAL_NULL(retnull);
02376                             CAAZ("content_type", retnull);
02377                      }
02378               }
02379               if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
02380                      CAAL("http_code", l_code);
02381               }
02382               if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
02383                      CAAL("header_size", l_code);
02384               }
02385               if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
02386                      CAAL("request_size", l_code);
02387               }
02388               if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
02389                      CAAL("filetime", l_code);
02390               }
02391               if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
02392                      CAAL("ssl_verify_result", l_code);
02393               }
02394               if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
02395                      CAAL("redirect_count", l_code);
02396               }
02397               if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
02398                      CAAD("total_time", d_code);
02399               }
02400               if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
02401                      CAAD("namelookup_time", d_code);
02402               }
02403               if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
02404                      CAAD("connect_time", d_code);
02405               }
02406               if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
02407                      CAAD("pretransfer_time", d_code);
02408               }
02409               if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
02410                      CAAD("size_upload", d_code);
02411               }
02412               if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
02413                      CAAD("size_download", d_code);
02414               }
02415               if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
02416                      CAAD("speed_download", d_code);
02417               }
02418               if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
02419                      CAAD("speed_upload", d_code);
02420               }
02421               if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
02422                      CAAD("download_content_length", d_code);
02423               }
02424               if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
02425                      CAAD("upload_content_length", d_code);
02426               }
02427               if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
02428                      CAAD("starttransfer_time", d_code);
02429               }
02430               if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
02431                      CAAD("redirect_time", d_code);
02432               }
02433 #if LIBCURL_VERSION_NUM > 0x071301
02434               if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
02435                      MAKE_STD_ZVAL(listcode);
02436                      array_init(listcode);
02437                      create_certinfo(ci, listcode TSRMLS_CC);
02438                      CAAZ("certinfo", listcode);
02439               }
02440 #endif
02441 #if LIBCURL_VERSION_NUM >= 0x071202
02442               if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
02443                      CAAS("redirect_url", s_code);
02444               }
02445 #endif
02446               if (ch->header.str_len > 0) {
02447                      CAAS("request_header", ch->header.str);
02448               }
02449        } else {
02450               switch (option) {
02451                      case CURLINFO_PRIVATE:
02452                      case CURLINFO_EFFECTIVE_URL:
02453                      case CURLINFO_CONTENT_TYPE:
02454 #if LIBCURL_VERSION_NUM >= 0x071202
02455                      case CURLINFO_REDIRECT_URL:
02456 #endif
02457                      {
02458                             char *s_code = NULL;
02459 
02460                             if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
02461                                    RETURN_STRING(s_code, 1);
02462                             } else {
02463                                    RETURN_FALSE;
02464                             }
02465                             break;
02466                      }
02467                      case CURLINFO_HTTP_CODE:
02468                      case CURLINFO_HEADER_SIZE:
02469                      case CURLINFO_REQUEST_SIZE:
02470                      case CURLINFO_FILETIME:
02471                      case CURLINFO_SSL_VERIFYRESULT:
02472                      case CURLINFO_REDIRECT_COUNT: {
02473                             long code = 0;
02474 
02475                             if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
02476                                    RETURN_LONG(code);
02477                             } else {
02478                                    RETURN_FALSE;
02479                             }
02480                             break;
02481                      }
02482                      case CURLINFO_TOTAL_TIME:
02483                      case CURLINFO_NAMELOOKUP_TIME:
02484                      case CURLINFO_CONNECT_TIME:
02485                      case CURLINFO_PRETRANSFER_TIME:
02486                      case CURLINFO_SIZE_UPLOAD:
02487                      case CURLINFO_SIZE_DOWNLOAD:
02488                      case CURLINFO_SPEED_DOWNLOAD:
02489                      case CURLINFO_SPEED_UPLOAD:
02490                      case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
02491                      case CURLINFO_CONTENT_LENGTH_UPLOAD:
02492                      case CURLINFO_STARTTRANSFER_TIME:
02493                      case CURLINFO_REDIRECT_TIME: {
02494                             double code = 0.0;
02495 
02496                             if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
02497                                    RETURN_DOUBLE(code);
02498                             } else {
02499                                    RETURN_FALSE;
02500                             }
02501                             break;
02502                      }
02503                      case CURLINFO_HEADER_OUT:
02504                             if (ch->header.str_len > 0) {
02505                                    RETURN_STRINGL(ch->header.str, ch->header.str_len, 1);
02506                             } else {
02507                                    RETURN_FALSE;
02508                             }
02509 #if LIBCURL_VERSION_NUM > 0x071301
02510                      case CURLINFO_CERTINFO: {
02511                             struct curl_certinfo *ci = NULL;
02512 
02513                             array_init(return_value);
02514                             
02515                             if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
02516                                    create_certinfo(ci, return_value TSRMLS_CC);
02517                             } else {
02518                                    RETURN_FALSE;
02519                             }
02520                             break;
02521                      }
02522 #endif
02523               }
02524        }
02525 }
02526 /* }}} */
02527 
02528 /* {{{ proto string curl_error(resource ch)
02529    Return a string contain the last error for the current session */
02530 PHP_FUNCTION(curl_error)
02531 {
02532        zval          *zid;
02533        php_curl      *ch;
02534 
02535        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
02536               return;
02537        }
02538 
02539        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02540 
02541        ch->err.str[CURL_ERROR_SIZE] = 0;
02542        RETURN_STRING(ch->err.str, 1);
02543 }
02544 /* }}} */
02545 
02546 /* {{{ proto int curl_errno(resource ch)
02547    Return an integer containing the last error number */
02548 PHP_FUNCTION(curl_errno)
02549 {
02550        zval          *zid;
02551        php_curl      *ch;
02552 
02553        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
02554               return;
02555        }
02556 
02557        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02558 
02559        RETURN_LONG(ch->err.no);
02560 }
02561 /* }}} */
02562 
02563 /* {{{ proto void curl_close(resource ch)
02564    Close a cURL session */
02565 PHP_FUNCTION(curl_close)
02566 {
02567        zval          *zid;
02568        php_curl      *ch;
02569 
02570        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
02571               return;
02572        }
02573 
02574        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
02575 
02576        if (ch->in_callback) {
02577               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close cURL handle from a callback");
02578               return;
02579        }
02580 
02581        if (ch->uses) {
02582               ch->uses--;
02583        } else {
02584               zend_list_delete(Z_LVAL_P(zid));
02585        }
02586 }
02587 /* }}} */
02588 
02589 /* {{{ _php_curl_close()
02590    List destructor for curl handles */
02591 static void _php_curl_close_ex(php_curl *ch TSRMLS_DC)
02592 {
02593 #if PHP_CURL_DEBUG
02594        fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
02595 #endif
02596 
02597        _php_curl_verify_handlers(ch, 0 TSRMLS_CC);
02598        curl_easy_cleanup(ch->cp);
02599 
02600        /* cURL destructors should be invoked only by last curl handle */
02601        if (Z_REFCOUNT_P(ch->clone) <= 1) {
02602               zend_llist_clean(&ch->to_free->str);
02603               zend_llist_clean(&ch->to_free->slist);
02604               zend_llist_clean(&ch->to_free->post);
02605               efree(ch->to_free);
02606               FREE_ZVAL(ch->clone);
02607        } else {
02608               Z_DELREF_P(ch->clone);
02609        }
02610 
02611        if (ch->handlers->write->buf.len > 0) {
02612               smart_str_free(&ch->handlers->write->buf);
02613        }
02614        if (ch->handlers->write->func_name) {
02615               zval_ptr_dtor(&ch->handlers->write->func_name);
02616        }
02617        if (ch->handlers->read->func_name) {
02618               zval_ptr_dtor(&ch->handlers->read->func_name);
02619        }
02620        if (ch->handlers->write_header->func_name) {
02621               zval_ptr_dtor(&ch->handlers->write_header->func_name);
02622        }
02623        if (ch->handlers->progress->func_name) {
02624               zval_ptr_dtor(&ch->handlers->progress->func_name);
02625        }
02626        if (ch->handlers->passwd) {
02627               zval_ptr_dtor(&ch->handlers->passwd);
02628        }
02629        if (ch->handlers->std_err) {
02630               zval_ptr_dtor(&ch->handlers->std_err);
02631        }
02632        if (ch->header.str_len > 0) {
02633               efree(ch->header.str);
02634        }
02635 
02636        if (ch->handlers->write_header->stream) {
02637               zval_ptr_dtor(&ch->handlers->write_header->stream);
02638        }
02639        if (ch->handlers->write->stream) {
02640               zval_ptr_dtor(&ch->handlers->write->stream);
02641        }
02642        if (ch->handlers->read->stream) {
02643               zval_ptr_dtor(&ch->handlers->read->stream);
02644        }
02645 
02646        efree(ch->handlers->write);
02647        efree(ch->handlers->write_header);
02648        efree(ch->handlers->read);
02649        efree(ch->handlers->progress);
02650        efree(ch->handlers);
02651        efree(ch);
02652 }
02653 /* }}} */
02654 
02655 /* {{{ _php_curl_close()
02656    List destructor for curl handles */
02657 static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
02658 {
02659        php_curl *ch = (php_curl *) rsrc->ptr;
02660        _php_curl_close_ex(ch TSRMLS_CC);
02661 }
02662 /* }}} */
02663 
02664 #endif /* HAVE_CURL */
02665 
02666 /*
02667  * Local variables:
02668  * tab-width: 4
02669  * c-basic-offset: 4
02670  * End:
02671  * vim600: fdm=marker
02672  * vim: noet sw=4 ts=4
02673  */