Annotation of embedaddon/php/ext/curl/interface.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Sterling Hughes <sterling@php.net>                           |
                     16:    +----------------------------------------------------------------------+
                     17: */
                     18: 
                     19: /* $Id: interface.c 321634 2012-01-01 13:15:04Z felipe $ */
                     20: 
                     21: #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
                     22: 
                     23: #ifdef HAVE_CONFIG_H
                     24: #include "config.h"
                     25: #endif
                     26: 
                     27: #include "php.h"
                     28: 
                     29: #if HAVE_CURL
                     30: 
                     31: #include <stdio.h>
                     32: #include <string.h>
                     33: 
                     34: #ifdef PHP_WIN32
                     35: #include <winsock2.h>
                     36: #include <sys/types.h>
                     37: #endif
                     38: 
                     39: #include <curl/curl.h>
                     40: #include <curl/easy.h>
                     41: 
                     42: /* As of curl 7.11.1 this is no longer defined inside curl.h */
                     43: #ifndef HttpPost
                     44: #define HttpPost curl_httppost
                     45: #endif
                     46: 
                     47: /* {{{ cruft for thread safe SSL crypto locks */
                     48: #if defined(ZTS) && defined(HAVE_CURL_SSL)
                     49: # ifdef PHP_WIN32
                     50: #  define PHP_CURL_NEED_OPENSSL_TSL
                     51: #  include <openssl/crypto.h>
                     52: # else /* !PHP_WIN32 */
                     53: #  if defined(HAVE_CURL_OPENSSL)
                     54: #   if defined(HAVE_OPENSSL_CRYPTO_H)
                     55: #    define PHP_CURL_NEED_OPENSSL_TSL
                     56: #    include <openssl/crypto.h>
                     57: #   else
                     58: #    warning \
                     59:        "libcurl was compiled with OpenSSL support, but configure could not find " \
                     60:        "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
                     61:        "cause random crashes on SSL requests"
                     62: #   endif
                     63: #  elif defined(HAVE_CURL_GNUTLS)
                     64: #   if defined(HAVE_GCRYPT_H)
                     65: #    define PHP_CURL_NEED_GNUTLS_TSL
                     66: #    include <gcrypt.h>
                     67: #   else
                     68: #    warning \
                     69:        "libcurl was compiled with GnuTLS support, but configure could not find " \
                     70:        "gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \
                     71:        "cause random crashes on SSL requests"
                     72: #   endif
                     73: #  else
                     74: #   warning \
                     75:        "libcurl was compiled with SSL support, but configure could not determine which" \
                     76:        "library was used; thus no SSL crypto locking callbacks will be set, which may " \
                     77:        "cause random crashes on SSL requests"
                     78: #  endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
                     79: # endif /* PHP_WIN32 */
                     80: #endif /* ZTS && HAVE_CURL_SSL */
                     81: /* }}} */
                     82: 
                     83: #define SMART_STR_PREALLOC 4096
                     84: 
                     85: #include "ext/standard/php_smart_str.h"
                     86: #include "ext/standard/info.h"
                     87: #include "ext/standard/file.h"
                     88: #include "ext/standard/url.h"
                     89: #include "php_curl.h"
                     90: 
                     91: int  le_curl;
                     92: int  le_curl_multi_handle;
                     93: 
                     94: #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
                     95: static MUTEX_T *php_curl_openssl_tsl = NULL;
                     96: 
                     97: static void php_curl_ssl_lock(int mode, int n, const char * file, int line)
                     98: {
                     99:        if (mode & CRYPTO_LOCK) {
                    100:                tsrm_mutex_lock(php_curl_openssl_tsl[n]);
                    101:        } else {
                    102:                tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
                    103:        }
                    104: }
                    105: 
                    106: static unsigned long php_curl_ssl_id(void)
                    107: {
                    108:        return (unsigned long) tsrm_thread_id();
                    109: }
                    110: #endif
                    111: /* }}} */
                    112: 
                    113: #ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */
                    114: static int php_curl_ssl_mutex_create(void **m)
                    115: {
                    116:        if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
                    117:                return SUCCESS;
                    118:        } else {
                    119:                return FAILURE;
                    120:        }
                    121: }
                    122: 
                    123: static int php_curl_ssl_mutex_destroy(void **m)
                    124: {
                    125:        tsrm_mutex_free(*((MUTEX_T *) m));
                    126:        return SUCCESS;
                    127: }
                    128: 
                    129: static int php_curl_ssl_mutex_lock(void **m)
                    130: {
                    131:        return tsrm_mutex_lock(*((MUTEX_T *) m));
                    132: }
                    133: 
                    134: static int php_curl_ssl_mutex_unlock(void **m)
                    135: {
                    136:        return tsrm_mutex_unlock(*((MUTEX_T *) m));
                    137: }
                    138: 
                    139: static struct gcry_thread_cbs php_curl_gnutls_tsl = {
                    140:        GCRY_THREAD_OPTION_USER,
                    141:        NULL,
                    142:        php_curl_ssl_mutex_create,
                    143:        php_curl_ssl_mutex_destroy,
                    144:        php_curl_ssl_mutex_lock,
                    145:        php_curl_ssl_mutex_unlock
                    146: };
                    147: #endif
                    148: /* }}} */
                    149: 
                    150: static void _php_curl_close_ex(php_curl *ch TSRMLS_DC);
                    151: static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
                    152: 
                    153: 
                    154: #define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
                    155: 
                    156: #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s), (long) v);
                    157: #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s), (double) v);
                    158: #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) (v ? v : ""), 1);
                    159: #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v);
                    160: 
                    161: #if defined(PHP_WIN32) || defined(__GNUC__)
                    162: # define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
                    163: #else
                    164: # define php_curl_ret(__ret) RETVAL_FALSE; return;
                    165: #endif
                    166: 
                    167: static int php_curl_option_url(php_curl *ch, const char *url, const int len) /* {{{ */
                    168: {
                    169:        CURLcode error = CURLE_OK;
                    170: #if LIBCURL_VERSION_NUM < 0x071100
                    171:        char *copystr = NULL;
                    172: #endif
                    173:        TSRMLS_FETCH();
                    174: 
                    175:        /* Disable file:// if open_basedir or safe_mode are used */
                    176:        if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
                    177: #if LIBCURL_VERSION_NUM >= 0x071304
                    178:                error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
                    179: #else
                    180:                php_url *uri;
                    181: 
                    182:                if (!(uri = php_url_parse_ex(url, len))) {
                    183:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL '%s'", url);
                    184:                        return 0;
                    185:                }
                    186: 
                    187:                if (uri->scheme && !strncasecmp("file", uri->scheme, sizeof("file"))) {
                    188:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol 'file' disabled in cURL");
                    189:                        php_url_free(uri);
                    190:                        return 0;
                    191:                }
                    192:                php_url_free(uri);
                    193: #endif
                    194:        }
                    195:        /* Strings passed to libcurl as 'char *' arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
                    196: #if LIBCURL_VERSION_NUM >= 0x071100
                    197:        error = curl_easy_setopt(ch->cp, CURLOPT_URL, url);
                    198: #else
                    199:        copystr = estrndup(url, len);
                    200:        error = curl_easy_setopt(ch->cp, CURLOPT_URL, copystr);
                    201:        zend_llist_add_element(&ch->to_free->str, &copystr);
                    202: #endif
                    203: 
                    204:        return (error == CURLE_OK ? 1 : 0);
                    205: }
                    206: /* }}} */
                    207: 
                    208: int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
                    209: {
                    210:        php_stream *stream;
                    211:        if (!ch || !ch->handlers) {
                    212:                return 0;
                    213:        }
                    214: 
                    215:        if (ch->handlers->std_err) {
                    216:                stream = (php_stream *) zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
                    217:                if (stream == NULL) {
                    218:                        if (reporterror) {
                    219:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr");
                    220:                        }
                    221:                        zval_ptr_dtor(&ch->handlers->std_err);
                    222:                        ch->handlers->std_err = NULL;
                    223: 
                    224:                        curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
                    225:                }
                    226:        }
                    227:        if (ch->handlers->read && ch->handlers->read->stream) {
                    228:                stream = (php_stream *) zend_fetch_resource(&ch->handlers->read->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
                    229:                if (stream == NULL) {
                    230:                        if (reporterror) {
                    231:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default");
                    232:                        }
                    233:                        zval_ptr_dtor(&ch->handlers->read->stream);
                    234:                        ch->handlers->read->fd = 0;
                    235:                        ch->handlers->read->fp = 0;
                    236:                        ch->handlers->read->stream = NULL;
                    237: 
                    238:                        curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
                    239:                }
                    240:        }
                    241:        if (ch->handlers->write_header && ch->handlers->write_header->stream) {
                    242:                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());
                    243:                if (stream == NULL) {
                    244:                        if (reporterror) {
                    245:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default");
                    246:                        }
                    247:                        zval_ptr_dtor(&ch->handlers->write_header->stream);
                    248:                        ch->handlers->write_header->fp = 0;
                    249:                        ch->handlers->write_header->stream = NULL;
                    250: 
                    251:                        ch->handlers->write_header->method = PHP_CURL_IGNORE;
                    252:                        curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
                    253:                }
                    254:        }
                    255:        if (ch->handlers->write && ch->handlers->write->stream) {
                    256:                stream = (php_stream *) zend_fetch_resource(&ch->handlers->write->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
                    257:                if (stream == NULL) {
                    258:                        if (reporterror) {
                    259:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default");
                    260:                        }
                    261:                        zval_ptr_dtor(&ch->handlers->write->stream);
                    262:                        ch->handlers->write->fp = 0;
                    263:                        ch->handlers->write->stream = NULL;
                    264: 
                    265:                        ch->handlers->write->method = PHP_CURL_STDOUT;
                    266:                        ch->handlers->write->type   = PHP_CURL_ASCII;
                    267:                        curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
                    268:                }
                    269:        }
                    270:        return 1;
                    271: }
                    272: /* }}} */
                    273: 
                    274: /* {{{ arginfo */
                    275: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
                    276:        ZEND_ARG_INFO(0, version)
                    277: ZEND_END_ARG_INFO()
                    278: 
                    279: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
                    280:        ZEND_ARG_INFO(0, url)
                    281: ZEND_END_ARG_INFO()
                    282: 
                    283: ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
                    284:        ZEND_ARG_INFO(0, ch)
                    285: ZEND_END_ARG_INFO()
                    286: 
                    287: ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
                    288:        ZEND_ARG_INFO(0, ch)
                    289:        ZEND_ARG_INFO(0, option)
                    290:        ZEND_ARG_INFO(0, value)
                    291: ZEND_END_ARG_INFO()
                    292: 
                    293: ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
                    294:        ZEND_ARG_INFO(0, ch)
                    295:        ZEND_ARG_ARRAY_INFO(0, options, 0)
                    296: ZEND_END_ARG_INFO()
                    297: 
                    298: ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
                    299:        ZEND_ARG_INFO(0, ch)
                    300: ZEND_END_ARG_INFO()
                    301: 
                    302: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
                    303:        ZEND_ARG_INFO(0, ch)
                    304:        ZEND_ARG_INFO(0, option)
                    305: ZEND_END_ARG_INFO()
                    306: 
                    307: ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
                    308:        ZEND_ARG_INFO(0, ch)
                    309: ZEND_END_ARG_INFO()
                    310: 
                    311: ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
                    312:        ZEND_ARG_INFO(0, ch)
                    313: ZEND_END_ARG_INFO()
                    314: 
                    315: ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
                    316:        ZEND_ARG_INFO(0, ch)
                    317: ZEND_END_ARG_INFO()
                    318: 
                    319: ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
                    320: ZEND_END_ARG_INFO()
                    321: 
                    322: ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
                    323:        ZEND_ARG_INFO(0, mh)
                    324:        ZEND_ARG_INFO(0, ch)
                    325: ZEND_END_ARG_INFO()
                    326: 
                    327: ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
                    328:        ZEND_ARG_INFO(0, mh)
                    329:        ZEND_ARG_INFO(0, ch)
                    330: ZEND_END_ARG_INFO()
                    331: 
                    332: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
                    333:        ZEND_ARG_INFO(0, mh)
                    334:        ZEND_ARG_INFO(0, timeout)
                    335: ZEND_END_ARG_INFO()
                    336: 
                    337: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
                    338:        ZEND_ARG_INFO(0, mh)
                    339:        ZEND_ARG_INFO(1, still_running)
                    340: ZEND_END_ARG_INFO()
                    341: 
                    342: ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
                    343:        ZEND_ARG_INFO(0, ch)
                    344: ZEND_END_ARG_INFO()
                    345: 
                    346: ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
                    347:        ZEND_ARG_INFO(0, mh)
                    348:        ZEND_ARG_INFO(1, msgs_in_queue)
                    349: ZEND_END_ARG_INFO()
                    350: 
                    351: ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
                    352:        ZEND_ARG_INFO(0, mh)
                    353: ZEND_END_ARG_INFO()
                    354: /* }}} */
                    355: 
                    356: /* {{{ curl_functions[]
                    357:  */
                    358: const zend_function_entry curl_functions[] = {
                    359:        PHP_FE(curl_init,                arginfo_curl_init)
                    360:        PHP_FE(curl_copy_handle,         arginfo_curl_copy_handle)
                    361:        PHP_FE(curl_version,             arginfo_curl_version)
                    362:        PHP_FE(curl_setopt,              arginfo_curl_setopt)
                    363:        PHP_FE(curl_setopt_array,        arginfo_curl_setopt_array)
                    364:        PHP_FE(curl_exec,                arginfo_curl_exec)
                    365:        PHP_FE(curl_getinfo,             arginfo_curl_getinfo)
                    366:        PHP_FE(curl_error,               arginfo_curl_error)
                    367:        PHP_FE(curl_errno,               arginfo_curl_errno)
                    368:        PHP_FE(curl_close,               arginfo_curl_close)
                    369:        PHP_FE(curl_multi_init,          arginfo_curl_multi_init)
                    370:        PHP_FE(curl_multi_add_handle,    arginfo_curl_multi_add_handle)
                    371:        PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
                    372:        PHP_FE(curl_multi_select,        arginfo_curl_multi_select)
                    373:        PHP_FE(curl_multi_exec,          arginfo_curl_multi_exec)
                    374:        PHP_FE(curl_multi_getcontent,    arginfo_curl_multi_getcontent)
                    375:        PHP_FE(curl_multi_info_read,     arginfo_curl_multi_info_read)
                    376:        PHP_FE(curl_multi_close,         arginfo_curl_multi_close)
                    377:        PHP_FE_END
                    378: };
                    379: /* }}} */
                    380: 
                    381: /* {{{ curl_module_entry
                    382:  */
                    383: zend_module_entry curl_module_entry = {
                    384:        STANDARD_MODULE_HEADER,
                    385:        "curl",
                    386:        curl_functions,
                    387:        PHP_MINIT(curl),
                    388:        PHP_MSHUTDOWN(curl),
                    389:        NULL,
                    390:        NULL,
                    391:        PHP_MINFO(curl),
                    392:        NO_VERSION_YET,
                    393:        STANDARD_MODULE_PROPERTIES
                    394: };
                    395: /* }}} */
                    396: 
                    397: #ifdef COMPILE_DL_CURL
                    398: ZEND_GET_MODULE (curl)
                    399: #endif
                    400: 
                    401: /* {{{ PHP_INI_BEGIN */
                    402: PHP_INI_BEGIN()
                    403:        PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
                    404: PHP_INI_END()
                    405: /* }}} */
                    406: 
                    407: /* {{{ PHP_MINFO_FUNCTION
                    408:  */
                    409: PHP_MINFO_FUNCTION(curl)
                    410: {
                    411:        curl_version_info_data *d;
                    412:        char **p;
                    413:        char str[1024];
                    414:        size_t n = 0;
                    415: 
                    416:        d = curl_version_info(CURLVERSION_NOW);
                    417:        php_info_print_table_start();
                    418:        php_info_print_table_row(2, "cURL support",    "enabled");
                    419:        php_info_print_table_row(2, "cURL Information", d->version);
                    420:        sprintf(str, "%d", d->age);
                    421:        php_info_print_table_row(2, "Age", str);
                    422: 
                    423:        /* To update on each new cURL release using src/main.c in cURL sources */
                    424:        if (d->features) {
                    425:                struct feat {
                    426:                        const char *name;
                    427:                        int bitmask;
                    428:                };
                    429: 
                    430:                unsigned int i;
                    431: 
                    432:                static const struct feat feats[] = {
                    433: #if LIBCURL_VERSION_NUM > 0x070a06 /* 7.10.7 */
                    434:                        {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
                    435: #endif
                    436: #if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
                    437:                        {"Debug", CURL_VERSION_DEBUG},
                    438:                        {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
                    439: #endif
                    440: #if LIBCURL_VERSION_NUM > 0x070b02 /* 7.12.0 */
                    441:                        {"IDN", CURL_VERSION_IDN},
                    442: #endif
                    443: #ifdef CURL_VERSION_IPV6
                    444:                        {"IPv6", CURL_VERSION_IPV6},
                    445: #endif
                    446: #if LIBCURL_VERSION_NUM > 0x070b00 /* 7.11.1 */
                    447:                        {"Largefile", CURL_VERSION_LARGEFILE},
                    448: #endif
                    449: #if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
                    450:                        {"NTLM", CURL_VERSION_NTLM},
                    451: #endif
                    452: #if LIBCURL_VERSION_NUM > 0x070a07 /* 7.10.8 */
                    453:                        {"SPNEGO", CURL_VERSION_SPNEGO},
                    454: #endif
                    455: #ifdef CURL_VERSION_SSL
                    456:                        {"SSL",  CURL_VERSION_SSL},
                    457: #endif
                    458: #if LIBCURL_VERSION_NUM > 0x070d01 /* 7.13.2 */
                    459:                        {"SSPI",  CURL_VERSION_SSPI},
                    460: #endif
                    461: #ifdef CURL_VERSION_KERBEROS4
                    462:                        {"krb4", CURL_VERSION_KERBEROS4},
                    463: #endif
                    464: #ifdef CURL_VERSION_LIBZ
                    465:                        {"libz", CURL_VERSION_LIBZ},
                    466: #endif
                    467: #if LIBCURL_VERSION_NUM > 0x070f03 /* 7.15.4 */
                    468:                        {"CharConv", CURL_VERSION_CONV},
                    469: #endif
                    470:                        {NULL, 0}
                    471:                };
                    472: 
                    473:                php_info_print_table_row(1, "Features");
                    474:                for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
                    475:                        if (feats[i].name) {
                    476:                                php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
                    477:                        }
                    478:                }
                    479:        }
                    480: 
                    481:        n = 0;
                    482:        p = (char **) d->protocols;
                    483:        while (*p != NULL) {
                    484:                        n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : "");
                    485:                        p++;
                    486:        }
                    487:        php_info_print_table_row(2, "Protocols", str);
                    488: 
                    489:        php_info_print_table_row(2, "Host", d->host);
                    490: 
                    491:        if (d->ssl_version) {
                    492:                php_info_print_table_row(2, "SSL Version", d->ssl_version);
                    493:        }
                    494: 
                    495:        if (d->libz_version) {
                    496:                php_info_print_table_row(2, "ZLib Version", d->libz_version);
                    497:        }
                    498: 
                    499: #if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND
                    500:        if (d->ares) {
                    501:                php_info_print_table_row(2, "ZLib Version", d->ares);
                    502:        }
                    503: #endif
                    504: 
                    505: #if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD
                    506:        if (d->libidn) {
                    507:                php_info_print_table_row(2, "libIDN Version", d->libidn);
                    508:        }
                    509: #endif
                    510: 
                    511: #if LIBCURL_VERSION_NUM >= 0x071300
                    512: 
                    513:        if (d->iconv_ver_num) {
                    514:                php_info_print_table_row(2, "IconV Version", d->iconv_ver_num);
                    515:        }
                    516: 
                    517:        if (d->libssh_version) {
                    518:                php_info_print_table_row(2, "libSSH Version", d->libssh_version);
                    519:        }
                    520: #endif
                    521:        php_info_print_table_end();
                    522: }
                    523: /* }}} */
                    524: 
                    525: #define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
                    526: 
                    527: /* {{{ PHP_MINIT_FUNCTION
                    528:  */
                    529: PHP_MINIT_FUNCTION(curl)
                    530: {
                    531:        le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
                    532:        le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
                    533: 
                    534:        REGISTER_INI_ENTRIES();
                    535: 
                    536:        /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
                    537:           or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
                    538:           of options and which version they were introduced */
                    539: 
                    540:        /* Constants for curl_setopt() */
                    541: #if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
                    542:        REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE);
                    543:        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER);
                    544:        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4);
                    545:        REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6);
                    546: #endif
                    547:        REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
                    548:        REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
                    549:        REGISTER_CURL_CONSTANT(CURLOPT_PORT);
                    550:        REGISTER_CURL_CONSTANT(CURLOPT_FILE);
                    551:        REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
                    552:        REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
                    553:        REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
                    554:        REGISTER_CURL_CONSTANT(CURLOPT_URL);
                    555:        REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
                    556:        REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
                    557:        REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
                    558:        REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
                    559:        REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
                    560:        REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION);
                    561:        REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
                    562:        REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
                    563:        REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
                    564:        REGISTER_CURL_CONSTANT(CURLOPT_POST);
                    565:        REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
                    566:        REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
                    567:        REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
                    568:        REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
                    569: #if CURLOPT_FTPASCII != 0
                    570:        REGISTER_CURL_CONSTANT(CURLOPT_FTPASCII);
                    571: #endif
                    572:        REGISTER_CURL_CONSTANT(CURLOPT_PUT);
                    573: #if CURLOPT_MUTE != 0
                    574:        REGISTER_CURL_CONSTANT(CURLOPT_MUTE);
                    575: #endif
                    576:        REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
                    577:        REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
                    578:        REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
                    579:        REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
                    580: #if LIBCURL_VERSION_NUM > 0x071002
                    581:        REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
                    582: #endif
                    583:        REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
                    584:        REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
                    585:        REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
                    586:        REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
                    587:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
                    588:        REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
                    589:        REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
                    590:        REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
                    591:        REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
                    592:        REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
                    593:        REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
                    594:        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
                    595:        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
                    596:        REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
                    597:        REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
                    598:        REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
                    599:        REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
                    600:        REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
                    601:        REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
                    602:        REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
                    603:        REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
                    604:        REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
                    605:        REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
                    606:        REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
                    607:        REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
                    608:        REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
                    609:        REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
                    610:        REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
                    611:        REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
                    612:        REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
                    613:        REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
                    614: #if CURLOPT_PASSWDFUNCTION != 0
                    615:        REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION);
                    616: #endif
                    617:        REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
                    618:        REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
                    619:        REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
                    620:        REGISTER_CURL_CONSTANT(CURLOPT_CLOSEPOLICY);
                    621:        REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
                    622:        REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
                    623:        REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
                    624:        REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
                    625:        REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
                    626: #if LIBCURL_VERSION_NUM > 0x071002
                    627:        REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
                    628: #endif
                    629:        REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
                    630:        REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
                    631:        REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
                    632:        REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
                    633:        REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
                    634:        REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
                    635:        REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
                    636:        REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
                    637:        REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
                    638:        REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
                    639:        REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
                    640:        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
                    641:        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
                    642:        REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
                    643:        REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
                    644:        REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
                    645:        REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
                    646:        REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
                    647:        REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
                    648:        REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
                    649:        REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
                    650:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
                    651: #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
                    652:        REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
                    653: #endif
                    654:        REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
                    655:        REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
                    656:        REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
                    657:        REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
                    658: 
                    659: #if LIBCURL_VERSION_NUM > 0x070f04 /* CURLOPT_MAX_RECV_SPEED_LARGE & CURLOPT_MAX_SEND_SPEED_LARGE  are available since curl 7.15.5 */
                    660:        REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE);
                    661:        REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE);
                    662: #endif 
                    663: 
                    664: #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
                    665:        REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
                    666:        /* http authentication options */
                    667:        REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
                    668:        REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
                    669:        REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
                    670:        REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
                    671:        REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
                    672:        REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
                    673: #endif
                    674: 
                    675: #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
                    676:        REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
                    677:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
                    678: #endif
                    679: 
                    680:        REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
                    681: 
                    682:        /* Constants effecting the way CURLOPT_CLOSEPOLICY works */
                    683:        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
                    684:        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC);
                    685:        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_SLOWEST);
                    686:        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_CALLBACK);
                    687:        REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_OLDEST);
                    688: 
                    689:        /* Info constants */
                    690:        REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
                    691:        REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
                    692:        REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
                    693:        REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
                    694:        REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
                    695:        REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
                    696:        REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
                    697:        REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
                    698:        REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
                    699:        REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
                    700:        REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
                    701:        REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
                    702:        REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
                    703:        REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
                    704:        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
                    705:        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
                    706:        REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
                    707:        REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
                    708:        REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
                    709:        REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
                    710:        REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
                    711:        REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
                    712: #if LIBCURL_VERSION_NUM >  0x071301
                    713:        REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO);
                    714: #endif
                    715: #if LIBCURL_VERSION_NUM >= 0x071202
                    716:     REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
                    717: #endif
                    718: 
                    719: 
                    720:        /* cURL protocol constants (curl_version) */
                    721:        REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
                    722:        REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
                    723:        REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
                    724:        REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
                    725: 
                    726:        /* version constants */
                    727:        REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
                    728: 
                    729:        /* Error Constants */
                    730:        REGISTER_CURL_CONSTANT(CURLE_OK);
                    731:        REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
                    732:        REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
                    733:        REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
                    734:        REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
                    735:        REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
                    736:        REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
                    737:        REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
                    738:        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
                    739:        REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
                    740:        REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
                    741:        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
                    742:        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
                    743:        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
                    744:        REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
                    745:        REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
                    746:        REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
                    747:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
                    748:        REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
                    749:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
                    750:        REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
                    751:        REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
                    752:        REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
                    753:        REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
                    754:        REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
                    755:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
                    756:        REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
                    757:        REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
                    758:        REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
                    759:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
                    760:        REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
                    761:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
                    762:        REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
                    763:        REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
                    764:        REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
                    765:        REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
                    766:        REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
                    767:        REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
                    768:        REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
                    769:        REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
                    770:        REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
                    771:        REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
                    772:        REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
                    773:        REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
                    774:        REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
                    775:        REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
                    776:        REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
                    777:        REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
                    778:        REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
                    779:        REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
                    780:        REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
                    781:        REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
                    782:        REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
                    783:        REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
                    784:        REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
                    785:        REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
                    786:        REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
                    787:        REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
                    788:        REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
                    789:        REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
                    790:        REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
                    791:        REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
                    792: #if LIBCURL_VERSION_NUM >= 0x070a08
                    793:        REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
                    794:        REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
                    795: #endif
                    796: #if LIBCURL_VERSION_NUM >= 0x070b00
                    797:        REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
                    798: #endif
                    799:        REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
                    800:        REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
                    801:        REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
                    802: 
                    803:        REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
                    804:        REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
                    805:        REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
                    806: 
                    807:        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
                    808:        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
                    809:        REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
                    810: 
                    811:        REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
                    812:        REGISTER_CURL_CONSTANT(CURLM_OK);
                    813:        REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
                    814:        REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
                    815:        REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
                    816:        REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
                    817: 
                    818:        REGISTER_CURL_CONSTANT(CURLMSG_DONE);
                    819: 
                    820: #if LIBCURL_VERSION_NUM >= 0x070c02
                    821:        REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
                    822:        REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
                    823:        REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
                    824:        REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
                    825: #endif
                    826: 
                    827: #if LIBCURL_VERSION_NUM >  0x070b00
                    828:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
                    829:        REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
                    830:        REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
                    831:        REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
                    832:        REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
                    833: #endif
                    834: 
                    835: #if LIBCURL_VERSION_NUM > 0x071301
                    836:        REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO);
                    837:        REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR);
                    838: #endif
                    839: 
                    840: /* SSH support works in 7.19.0+ using libssh2 */
                    841: #if LIBCURL_VERSION_NUM >= 0x071300
                    842:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE);
                    843:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY);
                    844:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD);
                    845:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST);
                    846:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD);
                    847:        REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT);
                    848:        REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES);
                    849:        REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD);
                    850:        REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE);
                    851:        REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE);
                    852:        REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
                    853:        REGISTER_CURL_CONSTANT(CURLE_SSH);
                    854: #endif
                    855: 
                    856: #if LIBCURL_VERSION_NUM >= 0x071304
                    857:        REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
                    858:        REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
                    859:        REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
                    860:        REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
                    861:        REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
                    862:        REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
                    863:        REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
                    864:        REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
                    865:        REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
                    866:        REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
                    867:        REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
                    868:        REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
                    869:        REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
                    870:        REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
                    871:        REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
                    872: #endif
                    873: 
                    874: #if LIBCURL_VERSION_NUM >= 0x070f01
                    875:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD);
                    876:        REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP);
                    877: #endif
                    878: 
                    879: #if LIBCURL_VERSION_NUM >= 0x071001
                    880:        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD);
                    881:        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD);
                    882:        REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD);
                    883: #endif
                    884: 
                    885: #ifdef PHP_CURL_NEED_OPENSSL_TSL
                    886:        if (!CRYPTO_get_id_callback()) {
                    887:                int i, c = CRYPTO_num_locks();
                    888: 
                    889:                php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
                    890:                if (!php_curl_openssl_tsl) {
                    891:                        return FAILURE;
                    892:                }
                    893: 
                    894:                for (i = 0; i < c; ++i) {
                    895:                        php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
                    896:                }
                    897: 
                    898:                CRYPTO_set_id_callback(php_curl_ssl_id);
                    899:                CRYPTO_set_locking_callback(php_curl_ssl_lock);
                    900:        }
                    901: #endif
                    902: #ifdef PHP_CURL_NEED_GNUTLS_TSL
                    903:        gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
                    904: #endif
                    905: 
                    906:        if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
                    907:                return FAILURE;
                    908:        }
                    909: 
                    910: #ifdef PHP_CURL_URL_WRAPPERS
                    911: # if HAVE_CURL_VERSION_INFO
                    912:        {
                    913:                curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
                    914:                char **p = (char **)info->protocols;
                    915: 
                    916:                while (*p != NULL) {
                    917:                        /* Do not enable cURL "file" protocol and make sure cURL is always used when --with-curlwrappers is enabled */
                    918:                        if (strncasecmp(*p, "file", sizeof("file")-1) != 0) {
                    919:                                php_unregister_url_stream_wrapper(*p TSRMLS_CC);
                    920:                                php_register_url_stream_wrapper(*p, &php_curl_wrapper TSRMLS_CC);
                    921:                        }
                    922:                        (void) *p++;
                    923:                }
                    924:        }
                    925: # else
                    926:        php_unregister_url_stream_wrapper("http");
                    927:        php_register_url_stream_wrapper("http", &php_curl_wrapper TSRMLS_CC);
                    928:        php_unregister_url_stream_wrapper("https");
                    929:        php_register_url_stream_wrapper("https", &php_curl_wrapper TSRMLS_CC);
                    930:        php_unregister_url_stream_wrapper("ftp");
                    931:        php_register_url_stream_wrapper("ftp", &php_curl_wrapper TSRMLS_CC);
                    932:        php_unregister_url_stream_wrapper("ftps");
                    933:        php_register_url_stream_wrapper("ftps", &php_curl_wrapper TSRMLS_CC);
                    934:        php_unregister_url_stream_wrapper("ldap");
                    935:        php_register_url_stream_wrapper("ldap", &php_curl_wrapper TSRMLS_CC);
                    936: # endif
                    937: #endif
                    938: 
                    939:        return SUCCESS;
                    940: }
                    941: /* }}} */
                    942: 
                    943: /* {{{ PHP_MSHUTDOWN_FUNCTION
                    944:  */
                    945: PHP_MSHUTDOWN_FUNCTION(curl)
                    946: {
                    947: #ifdef PHP_CURL_URL_WRAPPERS
                    948:        php_unregister_url_stream_wrapper("http" TSRMLS_CC);
                    949:        php_unregister_url_stream_wrapper("https" TSRMLS_CC);
                    950:        php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
                    951:        php_unregister_url_stream_wrapper("ldap" TSRMLS_CC);
                    952: #endif
                    953:        curl_global_cleanup();
                    954: #ifdef PHP_CURL_NEED_OPENSSL_TSL
                    955:        if (php_curl_openssl_tsl) {
                    956:                int i, c = CRYPTO_num_locks();
                    957: 
                    958:                CRYPTO_set_id_callback(NULL);
                    959:                CRYPTO_set_locking_callback(NULL);
                    960: 
                    961:                for (i = 0; i < c; ++i) {
                    962:                        tsrm_mutex_free(php_curl_openssl_tsl[i]);
                    963:                }
                    964: 
                    965:                free(php_curl_openssl_tsl);
                    966:                php_curl_openssl_tsl = NULL;
                    967:        }
                    968: #endif
                    969:        UNREGISTER_INI_ENTRIES();
                    970:        return SUCCESS;
                    971: }
                    972: /* }}} */
                    973: 
                    974: /* {{{ curl_write
                    975:  */
                    976: static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
                    977: {
                    978:        php_curl       *ch     = (php_curl *) ctx;
                    979:        php_curl_write *t      = ch->handlers->write;
                    980:        size_t          length = size * nmemb;
                    981:        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
                    982: 
                    983: #if PHP_CURL_DEBUG
                    984:        fprintf(stderr, "curl_write() called\n");
                    985:        fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
                    986: #endif
                    987: 
                    988:        switch (t->method) {
                    989:                case PHP_CURL_STDOUT:
                    990:                        PHPWRITE(data, length);
                    991:                        break;
                    992:                case PHP_CURL_FILE:
                    993:                        return fwrite(data, size, nmemb, t->fp);
                    994:                case PHP_CURL_RETURN:
                    995:                        if (length > 0) {
                    996:                                smart_str_appendl(&t->buf, data, (int) length);
                    997:                        }
                    998:                        break;
                    999:                case PHP_CURL_USER: {
                   1000:                        zval **argv[2];
                   1001:                        zval *retval_ptr = NULL;
                   1002:                        zval *handle = NULL;
                   1003:                        zval *zdata = NULL;
                   1004:                        int   error;
                   1005:                        zend_fcall_info fci;
                   1006: 
                   1007:                        MAKE_STD_ZVAL(handle);
                   1008:                        ZVAL_RESOURCE(handle, ch->id);
                   1009:                        zend_list_addref(ch->id);
                   1010:                        argv[0] = &handle;
                   1011: 
                   1012:                        MAKE_STD_ZVAL(zdata);
                   1013:                        ZVAL_STRINGL(zdata, data, length, 1);
                   1014:                        argv[1] = &zdata;
                   1015: 
                   1016:                        fci.size = sizeof(fci);
                   1017:                        fci.function_table = EG(function_table);
                   1018:                        fci.object_ptr = NULL;
                   1019:                        fci.function_name = t->func_name;
                   1020:                        fci.retval_ptr_ptr = &retval_ptr;
                   1021:                        fci.param_count = 2;
                   1022:                        fci.params = argv;
                   1023:                        fci.no_separation = 0;
                   1024:                        fci.symbol_table = NULL;
                   1025: 
                   1026:                        ch->in_callback = 1;
                   1027:                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
                   1028:                        ch->in_callback = 0;
                   1029:                        if (error == FAILURE) {
                   1030:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
                   1031:                                length = -1;
                   1032:                        } else if (retval_ptr) {
                   1033:                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                   1034:                                        convert_to_long_ex(&retval_ptr);
                   1035:                                }
                   1036:                                length = Z_LVAL_P(retval_ptr);
                   1037:                                zval_ptr_dtor(&retval_ptr);
                   1038:                        }
                   1039: 
                   1040:                        zval_ptr_dtor(argv[0]);
                   1041:                        zval_ptr_dtor(argv[1]);
                   1042:                        break;
                   1043:                }
                   1044:        }
                   1045: 
                   1046:        return length;
                   1047: }
                   1048: /* }}} */
                   1049: 
                   1050: /* {{{ curl_progress
                   1051:  */
                   1052: static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
                   1053: {
                   1054:        php_curl       *ch = (php_curl *) clientp;
                   1055:        php_curl_progress  *t  = ch->handlers->progress;
                   1056:        int             length = -1;
                   1057:        size_t  rval = 0;
                   1058: 
                   1059: #if PHP_CURL_DEBUG
                   1060:        fprintf(stderr, "curl_progress() called\n");
                   1061:        fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
                   1062: #endif
                   1063: 
                   1064:        switch (t->method) {
                   1065:                case PHP_CURL_USER: {
                   1066:                        zval **argv[4];
                   1067:                        zval  *zdltotal = NULL;
                   1068:                        zval  *zdlnow = NULL;
                   1069:                        zval  *zultotal = NULL;
                   1070:                        zval  *zulnow = NULL;
                   1071:                        zval  *retval_ptr;
                   1072:                        int   error;
                   1073:                        zend_fcall_info fci;
                   1074:                        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
                   1075: 
                   1076:                        MAKE_STD_ZVAL(zdltotal);
                   1077:                        MAKE_STD_ZVAL(zdlnow);
                   1078:                        MAKE_STD_ZVAL(zultotal);
                   1079:                        MAKE_STD_ZVAL(zulnow);
                   1080: 
                   1081:                        ZVAL_LONG(zdltotal, (long) dltotal);
                   1082:                        ZVAL_LONG(zdlnow, (long) dlnow);
                   1083:                        ZVAL_LONG(zultotal, (long) ultotal);
                   1084:                        ZVAL_LONG(zulnow, (long) ulnow);
                   1085: 
                   1086:                        argv[0] = &zdltotal;
                   1087:                        argv[1] = &zdlnow;
                   1088:                        argv[2] = &zultotal;
                   1089:                        argv[3] = &zulnow;
                   1090: 
                   1091:                        fci.size = sizeof(fci);
                   1092:                        fci.function_table = EG(function_table);
                   1093:                        fci.function_name = t->func_name;
                   1094:                        fci.object_ptr = NULL;
                   1095:                        fci.retval_ptr_ptr = &retval_ptr;
                   1096:                        fci.param_count = 4;
                   1097:                        fci.params = argv;
                   1098:                        fci.no_separation = 0;
                   1099:                        fci.symbol_table = NULL;
                   1100: 
                   1101:                        ch->in_callback = 1;
                   1102:                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
                   1103:                        ch->in_callback = 0;
                   1104:                        if (error == FAILURE) {
                   1105:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
                   1106:                                length = -1;
                   1107:                        } else if (retval_ptr) {
                   1108:                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                   1109:                                        convert_to_long_ex(&retval_ptr);
                   1110:                                }
                   1111:                                if (0 != Z_LVAL_P(retval_ptr)) {
                   1112:                                        rval = 1;
                   1113:                                }
                   1114:                                zval_ptr_dtor(&retval_ptr);
                   1115:                        }
                   1116:                        zval_ptr_dtor(argv[0]);
                   1117:                        zval_ptr_dtor(argv[1]);
                   1118:                        zval_ptr_dtor(argv[2]);
                   1119:                        zval_ptr_dtor(argv[3]);
                   1120:                        break;
                   1121:                }
                   1122:        }
                   1123:        return rval;
                   1124: }
                   1125: /* }}} */
                   1126: 
                   1127: /* {{{ curl_read
                   1128:  */
                   1129: static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
                   1130: {
                   1131:        php_curl       *ch = (php_curl *) ctx;
                   1132:        php_curl_read  *t  = ch->handlers->read;
                   1133:        int             length = 0;
                   1134: 
                   1135:        switch (t->method) {
                   1136:                case PHP_CURL_DIRECT:
                   1137:                        if (t->fp) {
                   1138:                                length = fread(data, size, nmemb, t->fp);
                   1139:                        }
                   1140:                        break;
                   1141:                case PHP_CURL_USER: {
                   1142:                        zval **argv[3];
                   1143:                        zval  *handle = NULL;
                   1144:                        zval  *zfd = NULL;
                   1145:                        zval  *zlength = NULL;
                   1146:                        zval  *retval_ptr;
                   1147:                        int   error;
                   1148:                        zend_fcall_info fci;
                   1149:                        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
                   1150: 
                   1151:                        MAKE_STD_ZVAL(handle);
                   1152:                        MAKE_STD_ZVAL(zfd);
                   1153:                        MAKE_STD_ZVAL(zlength);
                   1154: 
                   1155:                        ZVAL_RESOURCE(handle, ch->id);
                   1156:                        zend_list_addref(ch->id);
                   1157:                        ZVAL_RESOURCE(zfd, t->fd);
                   1158:                        zend_list_addref(t->fd);
                   1159:                        ZVAL_LONG(zlength, (int) size * nmemb);
                   1160: 
                   1161:                        argv[0] = &handle;
                   1162:                        argv[1] = &zfd;
                   1163:                        argv[2] = &zlength;
                   1164: 
                   1165:                        fci.size = sizeof(fci);
                   1166:                        fci.function_table = EG(function_table);
                   1167:                        fci.function_name = t->func_name;
                   1168:                        fci.object_ptr = NULL;
                   1169:                        fci.retval_ptr_ptr = &retval_ptr;
                   1170:                        fci.param_count = 3;
                   1171:                        fci.params = argv;
                   1172:                        fci.no_separation = 0;
                   1173:                        fci.symbol_table = NULL;
                   1174: 
                   1175:                        ch->in_callback = 1;
                   1176:                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
                   1177:                        ch->in_callback = 0;
                   1178:                        if (error == FAILURE) {
                   1179:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
                   1180: #if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
                   1181:                                length = CURL_READFUNC_ABORT;
                   1182: #endif
                   1183:                        } else if (retval_ptr) {
                   1184:                                if (Z_TYPE_P(retval_ptr) == IS_STRING) {
                   1185:                                        length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr));
                   1186:                                        memcpy(data, Z_STRVAL_P(retval_ptr), length);
                   1187:                                }
                   1188:                                zval_ptr_dtor(&retval_ptr);
                   1189:                        }
                   1190: 
                   1191:                        zval_ptr_dtor(argv[0]);
                   1192:                        zval_ptr_dtor(argv[1]);
                   1193:                        zval_ptr_dtor(argv[2]);
                   1194:                        break;
                   1195:                }
                   1196:        }
                   1197: 
                   1198:        return length;
                   1199: }
                   1200: /* }}} */
                   1201: 
                   1202: /* {{{ curl_write_header
                   1203:  */
                   1204: static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
                   1205: {
                   1206:        php_curl       *ch  = (php_curl *) ctx;
                   1207:        php_curl_write *t   = ch->handlers->write_header;
                   1208:        size_t          length = size * nmemb;
                   1209:        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
                   1210: 
                   1211:        switch (t->method) {
                   1212:                case PHP_CURL_STDOUT:
                   1213:                        /* Handle special case write when we're returning the entire transfer
                   1214:                         */
                   1215:                        if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
                   1216:                                smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
                   1217:                        } else {
                   1218:                                PHPWRITE(data, length);
                   1219:                        }
                   1220:                        break;
                   1221:                case PHP_CURL_FILE:
                   1222:                        return fwrite(data, size, nmemb, t->fp);
                   1223:                case PHP_CURL_USER: {
                   1224:                        zval **argv[2];
                   1225:                        zval  *handle = NULL;
                   1226:                        zval  *zdata = NULL;
                   1227:                        zval  *retval_ptr;
                   1228:                        int   error;
                   1229:                        zend_fcall_info fci;
                   1230: 
                   1231:                        MAKE_STD_ZVAL(handle);
                   1232:                        MAKE_STD_ZVAL(zdata);
                   1233: 
                   1234:                        ZVAL_RESOURCE(handle, ch->id);
                   1235:                        zend_list_addref(ch->id);
                   1236:                        ZVAL_STRINGL(zdata, data, length, 1);
                   1237: 
                   1238:                        argv[0] = &handle;
                   1239:                        argv[1] = &zdata;
                   1240: 
                   1241:                        fci.size = sizeof(fci);
                   1242:                        fci.function_table = EG(function_table);
                   1243:                        fci.function_name = t->func_name;
                   1244:                        fci.symbol_table = NULL;
                   1245:                        fci.object_ptr = NULL;
                   1246:                        fci.retval_ptr_ptr = &retval_ptr;
                   1247:                        fci.param_count = 2;
                   1248:                        fci.params = argv;
                   1249:                        fci.no_separation = 0;
                   1250: 
                   1251:                        ch->in_callback = 1;
                   1252:                        error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
                   1253:                        ch->in_callback = 0;
                   1254:                        if (error == FAILURE) {
                   1255:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
                   1256:                                length = -1;
                   1257:                        } else if (retval_ptr) {
                   1258:                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                   1259:                                        convert_to_long_ex(&retval_ptr);
                   1260:                                }
                   1261:                                length = Z_LVAL_P(retval_ptr);
                   1262:                                zval_ptr_dtor(&retval_ptr);
                   1263:                        }
                   1264:                        zval_ptr_dtor(argv[0]);
                   1265:                        zval_ptr_dtor(argv[1]);
                   1266:                        break;
                   1267:                }
                   1268: 
                   1269:                case PHP_CURL_IGNORE:
                   1270:                        return length;
                   1271: 
                   1272:                default:
                   1273:                        return -1;
                   1274:        }
                   1275: 
                   1276:        return length;
                   1277: }
                   1278: /* }}} */
                   1279: 
                   1280: static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
                   1281: {
                   1282:        php_curl    *ch   = (php_curl *) ctx;
                   1283: 
                   1284:        if (type == CURLINFO_HEADER_OUT) {
                   1285:                if (ch->header.str_len) {
                   1286:                        efree(ch->header.str);
                   1287:                }
                   1288:                if (buf_len > 0) {
                   1289:                        ch->header.str = estrndup(buf, buf_len);
                   1290:                        ch->header.str_len = buf_len;
                   1291:                }
                   1292:        }
                   1293: 
                   1294:        return 0;
                   1295: }
                   1296: /* }}} */
                   1297: 
                   1298: #if CURLOPT_PASSWDFUNCTION != 0
                   1299: /* {{{ curl_passwd
                   1300:  */
                   1301: static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
                   1302: {
                   1303:        php_curl    *ch   = (php_curl *) ctx;
                   1304:        zval        *func = ch->handlers->passwd;
                   1305:        zval        *argv[3];
                   1306:        zval        *retval = NULL;
                   1307:        int          error;
                   1308:        int          ret = -1;
                   1309:        TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
                   1310: 
                   1311:        MAKE_STD_ZVAL(argv[0]);
                   1312:        MAKE_STD_ZVAL(argv[1]);
                   1313:        MAKE_STD_ZVAL(argv[2]);
                   1314: 
                   1315:        ZVAL_RESOURCE(argv[0], ch->id);
                   1316:        zend_list_addref(ch->id);
                   1317:        ZVAL_STRING(argv[1], prompt, 1);
                   1318:        ZVAL_LONG(argv[2], buflen);
                   1319: 
                   1320:        error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC);
                   1321:        if (error == FAILURE) {
                   1322:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_PASSWDFUNCTION");
                   1323:        } else if (Z_TYPE_P(retval) == IS_STRING) {
                   1324:                if (Z_STRLEN_P(retval) > buflen) {
                   1325:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Returned password is too long for libcurl to handle");
                   1326:                } else {
                   1327:                        strlcpy(buf, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
                   1328:                }
                   1329:        } else {
                   1330:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "User handler '%s' did not return a string", Z_STRVAL_P(func));
                   1331:        }
                   1332: 
                   1333:        zval_ptr_dtor(&argv[0]);
                   1334:        zval_ptr_dtor(&argv[1]);
                   1335:        zval_ptr_dtor(&argv[2]);
                   1336:        zval_ptr_dtor(&retval);
                   1337: 
                   1338:        return ret;
                   1339: }
                   1340: /* }}} */
                   1341: #endif
                   1342: 
                   1343: /* {{{ curl_free_string
                   1344:  */
                   1345: static void curl_free_string(void **string)
                   1346: {
                   1347:        efree(*string);
                   1348: }
                   1349: /* }}} */
                   1350: 
                   1351: /* {{{ curl_free_post
                   1352:  */
                   1353: static void curl_free_post(void **post)
                   1354: {
                   1355:        curl_formfree((struct HttpPost *) *post);
                   1356: }
                   1357: /* }}} */
                   1358: 
                   1359: /* {{{ curl_free_slist
                   1360:  */
                   1361: static void curl_free_slist(void **slist)
                   1362: {
                   1363:        curl_slist_free_all((struct curl_slist *) *slist);
                   1364: }
                   1365: /* }}} */
                   1366: 
                   1367: /* {{{ proto array curl_version([int version])
                   1368:    Return cURL version information. */
                   1369: PHP_FUNCTION(curl_version)
                   1370: {
                   1371:        curl_version_info_data *d;
                   1372:        long uversion = CURLVERSION_NOW;
                   1373: 
                   1374:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) {
                   1375:                return;
                   1376:        }
                   1377: 
                   1378:        d = curl_version_info(uversion);
                   1379:        if (d == NULL) {
                   1380:                RETURN_FALSE;
                   1381:        }
                   1382: 
                   1383:        array_init(return_value);
                   1384: 
                   1385:        CAAL("version_number", d->version_num);
                   1386:        CAAL("age", d->age);
                   1387:        CAAL("features", d->features);
                   1388:        CAAL("ssl_version_number", d->ssl_version_num);
                   1389:        CAAS("version", d->version);
                   1390:        CAAS("host", d->host);
                   1391:        CAAS("ssl_version", d->ssl_version);
                   1392:        CAAS("libz_version", d->libz_version);
                   1393:        /* Add an array of protocols */
                   1394:        {
                   1395:                char **p = (char **) d->protocols;
                   1396:                zval  *protocol_list = NULL;
                   1397: 
                   1398:                MAKE_STD_ZVAL(protocol_list);
                   1399:                array_init(protocol_list);
                   1400: 
                   1401:                while (*p != NULL) {
                   1402:                        add_next_index_string(protocol_list, *p, 1);
                   1403:                        p++;
                   1404:                }
                   1405:                CAAZ("protocols", protocol_list);
                   1406:        }
                   1407: }
                   1408: /* }}} */
                   1409: 
                   1410: /* {{{ alloc_curl_handle
                   1411:  */
                   1412: static void alloc_curl_handle(php_curl **ch)
                   1413: {
                   1414:        *ch                           = emalloc(sizeof(php_curl));
                   1415:        (*ch)->to_free                = ecalloc(1, sizeof(struct _php_curl_free));
                   1416:        (*ch)->handlers               = ecalloc(1, sizeof(php_curl_handlers));
                   1417:        (*ch)->handlers->write        = ecalloc(1, sizeof(php_curl_write));
                   1418:        (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
                   1419:        (*ch)->handlers->read         = ecalloc(1, sizeof(php_curl_read));
                   1420:        (*ch)->handlers->progress     = ecalloc(1, sizeof(php_curl_progress));
                   1421: 
                   1422:        (*ch)->in_callback = 0;
                   1423:        (*ch)->header.str_len = 0;
                   1424: 
                   1425:        memset(&(*ch)->err, 0, sizeof((*ch)->err));
                   1426:        (*ch)->handlers->write->stream = NULL;
                   1427:        (*ch)->handlers->write_header->stream = NULL;
                   1428:        (*ch)->handlers->read->stream = NULL;
                   1429: 
                   1430:        zend_llist_init(&(*ch)->to_free->str,   sizeof(char *),            (llist_dtor_func_t) curl_free_string, 0);
                   1431:        zend_llist_init(&(*ch)->to_free->slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist,  0);
                   1432:        zend_llist_init(&(*ch)->to_free->post,  sizeof(struct HttpPost),   (llist_dtor_func_t) curl_free_post,   0);
                   1433: }
                   1434: /* }}} */
                   1435: 
                   1436: #if LIBCURL_VERSION_NUM > 0x071301
                   1437: /* {{{ split_certinfo
                   1438:  */
                   1439: static void split_certinfo(char *string, zval *hash)
                   1440: {
                   1441:        char *org = estrdup(string);
                   1442:        char *s = org;
                   1443:        char *split;
                   1444: 
                   1445:        if(org) {
                   1446:         do {
                   1447:                        char *key;
                   1448:                        char *val;
                   1449:                        char *tmp;
                   1450: 
                   1451:             split = strstr(s, "; ");
                   1452:             if(split)
                   1453:                 *split = '\0';
                   1454:                        
                   1455:                        key = s;
                   1456:                        tmp = memchr(key, '=', 64);
                   1457:                        if(tmp) {
                   1458:                                *tmp = '\0';
                   1459:                                val = tmp+1;
                   1460:                                add_assoc_string(hash, key, val, 1);
                   1461:                        }
                   1462:                        s = split+2;
                   1463:                } while(split);
                   1464:                efree(org);
                   1465:        }
                   1466: }
                   1467: /* }}} */
                   1468: 
                   1469: /* {{{ create_certinfo
                   1470:  */
                   1471: static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC)
                   1472: {
                   1473:        int i;
                   1474:                        
                   1475:        if(ci) {
                   1476:                zval *certhash = NULL;
                   1477:                
                   1478:                for(i=0; i<ci->num_of_certs; i++) {
                   1479:                        struct curl_slist *slist;
                   1480:                        
                   1481:                        MAKE_STD_ZVAL(certhash);
                   1482:                        array_init(certhash);
                   1483:                        for(slist = ci->certinfo[i]; slist; slist = slist->next) {
                   1484:                                int len;
                   1485:                                char s[64];
                   1486:                                char *tmp;
                   1487:                                strncpy(s, slist->data, 64);
                   1488:                                tmp = memchr(s, ':', 64);
                   1489:                                if(tmp) {
                   1490:                                        *tmp = '\0';
                   1491:                                        len = strlen(s);
                   1492:                                        if(!strcmp(s, "Subject") || !strcmp(s, "Issuer")) {
                   1493:                                                zval *hash;
                   1494: 
                   1495:                                                MAKE_STD_ZVAL(hash);
                   1496:                                                array_init(hash);
                   1497:                                                
                   1498:                                                split_certinfo(&slist->data[len+1], hash);
                   1499:                                                add_assoc_zval(certhash, s, hash);
                   1500:                                        } else {
                   1501:                                                add_assoc_string(certhash, s, &slist->data[len+1], 1);
                   1502:                                        }
                   1503:                                } else {
                   1504:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info"); 
                   1505:                                }
                   1506:                        }
                   1507:                        add_next_index_zval(listcode, certhash);
                   1508:                }
                   1509:        }
                   1510: }
                   1511: /* }}} */
                   1512: #endif
                   1513: 
                   1514: /* {{{ proto resource curl_init([string url])
                   1515:    Initialize a cURL session */
                   1516: PHP_FUNCTION(curl_init)
                   1517: {
                   1518:        php_curl        *ch;
                   1519:        CURL            *cp;
                   1520:        zval            *clone;
                   1521:        char            *url = NULL;
                   1522:        int             url_len = 0;
                   1523:        char *cainfo;
                   1524: 
                   1525:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &url, &url_len) == FAILURE) {
                   1526:                return;
                   1527:        }
                   1528: 
                   1529:        cp = curl_easy_init();
                   1530:        if (!cp) {
                   1531:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle");
                   1532:                RETURN_FALSE;
                   1533:        }
                   1534: 
                   1535:        alloc_curl_handle(&ch);
                   1536:        TSRMLS_SET_CTX(ch->thread_ctx);
                   1537: 
                   1538:        ch->cp = cp;
                   1539: 
                   1540:        ch->handlers->write->method = PHP_CURL_STDOUT;
                   1541:        ch->handlers->write->type   = PHP_CURL_ASCII;
                   1542:        ch->handlers->read->method  = PHP_CURL_DIRECT;
                   1543:        ch->handlers->write_header->method = PHP_CURL_IGNORE;
                   1544: 
                   1545:        ch->uses = 0;
                   1546: 
                   1547:        MAKE_STD_ZVAL(clone);
                   1548:        ch->clone = clone;
                   1549: 
                   1550: 
                   1551: 
                   1552:        curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS,        1);
                   1553:        curl_easy_setopt(ch->cp, CURLOPT_VERBOSE,           0);
                   1554:        curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
                   1555:        curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION,     curl_write);
                   1556:        curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
                   1557:        curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION,      curl_read);
                   1558:        curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
                   1559:        curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION,    curl_write_header);
                   1560:        curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
                   1561:        curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
                   1562:        curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
                   1563:        curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
                   1564: 
                   1565:        cainfo = INI_STR("curl.cainfo");
                   1566:        if (cainfo && strlen(cainfo) > 0) {
                   1567:                curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
                   1568:        }
                   1569: 
                   1570: #if defined(ZTS)
                   1571:        curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
                   1572: #endif
                   1573: 
                   1574:        if (url) {
                   1575:                if (!php_curl_option_url(ch, url, url_len)) {
                   1576:                        _php_curl_close_ex(ch TSRMLS_CC);
                   1577:                        RETURN_FALSE;
                   1578:                }
                   1579:        }
                   1580: 
                   1581:        ZEND_REGISTER_RESOURCE(return_value, ch, le_curl);
                   1582:        ch->id = Z_LVAL_P(return_value);
                   1583: }
                   1584: /* }}} */
                   1585: 
                   1586: /* {{{ proto resource curl_copy_handle(resource ch)
                   1587:    Copy a cURL handle along with all of it's preferences */
                   1588: PHP_FUNCTION(curl_copy_handle)
                   1589: {
                   1590:        CURL            *cp;
                   1591:        zval            *zid;
                   1592:        php_curl        *ch, *dupch;
                   1593: 
                   1594:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
                   1595:                return;
                   1596:        }
                   1597: 
                   1598:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   1599: 
                   1600:        cp = curl_easy_duphandle(ch->cp);
                   1601:        if (!cp) {
                   1602:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot duplicate cURL handle");
                   1603:                RETURN_FALSE;
                   1604:        }
                   1605: 
                   1606:        alloc_curl_handle(&dupch);
                   1607:        TSRMLS_SET_CTX(dupch->thread_ctx);
                   1608: 
                   1609:        dupch->cp = cp;
                   1610:        dupch->uses = 0;
                   1611:        ch->uses++;
                   1612:        if (ch->handlers->write->stream) {
                   1613:                Z_ADDREF_P(dupch->handlers->write->stream);
                   1614:                dupch->handlers->write->stream = ch->handlers->write->stream;
                   1615:        }
                   1616:        dupch->handlers->write->method = ch->handlers->write->method;
                   1617:        dupch->handlers->write->type   = ch->handlers->write->type;
                   1618:        if (ch->handlers->read->stream) {
                   1619:                Z_ADDREF_P(ch->handlers->read->stream);
                   1620:        }
                   1621:        dupch->handlers->read->stream  = ch->handlers->read->stream;
                   1622:        dupch->handlers->read->method  = ch->handlers->read->method;
                   1623:        dupch->handlers->write_header->method = ch->handlers->write_header->method;
                   1624:        if (ch->handlers->write_header->stream) {
                   1625:                Z_ADDREF_P(ch->handlers->write_header->stream);
                   1626:        }
                   1627:        dupch->handlers->write_header->stream = ch->handlers->write_header->stream;
                   1628: 
                   1629:        dupch->handlers->write->fp = ch->handlers->write->fp;
                   1630:        dupch->handlers->write_header->fp = ch->handlers->write_header->fp;
                   1631:        dupch->handlers->read->fp = ch->handlers->read->fp;
                   1632:        dupch->handlers->read->fd = ch->handlers->read->fd;
                   1633: #if CURLOPT_PASSWDDATA != 0
                   1634:        if (ch->handlers->passwd) {
                   1635:                zval_add_ref(&ch->handlers->passwd);
                   1636:                dupch->handlers->passwd = ch->handlers->passwd;
                   1637:                curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) dupch);
                   1638:        }
                   1639: #endif
                   1640:        if (ch->handlers->write->func_name) {
                   1641:                zval_add_ref(&ch->handlers->write->func_name);
                   1642:                dupch->handlers->write->func_name = ch->handlers->write->func_name;
                   1643:        }
                   1644:        if (ch->handlers->read->func_name) {
                   1645:                zval_add_ref(&ch->handlers->read->func_name);
                   1646:                dupch->handlers->read->func_name = ch->handlers->read->func_name;
                   1647:        }
                   1648:        if (ch->handlers->write_header->func_name) {
                   1649:                zval_add_ref(&ch->handlers->write_header->func_name);
                   1650:                dupch->handlers->write_header->func_name = ch->handlers->write_header->func_name;
                   1651:        }
                   1652:        
                   1653:        if (ch->handlers->progress->func_name) {
                   1654:                zval_add_ref(&ch->handlers->progress->func_name);
                   1655:                dupch->handlers->progress->func_name = ch->handlers->progress->func_name;
                   1656:        }
                   1657:        dupch->handlers->progress->method = ch->handlers->progress->method;
                   1658: 
                   1659:        curl_easy_setopt(dupch->cp, CURLOPT_ERRORBUFFER,       dupch->err.str);
                   1660:        curl_easy_setopt(dupch->cp, CURLOPT_FILE,              (void *) dupch);
                   1661:        curl_easy_setopt(dupch->cp, CURLOPT_INFILE,            (void *) dupch);
                   1662:        curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER,       (void *) dupch);
                   1663:        curl_easy_setopt(dupch->cp, CURLOPT_PROGRESSDATA,      (void *) dupch); 
                   1664: 
                   1665:        efree(dupch->to_free);
                   1666:        dupch->to_free = ch->to_free;
                   1667: 
                   1668:        /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
                   1669:        Z_ADDREF_P(ch->clone);
                   1670:        dupch->clone = ch->clone;
                   1671: 
                   1672:        ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl);
                   1673:        dupch->id = Z_LVAL_P(return_value);
                   1674: }
                   1675: /* }}} */
                   1676: 
                   1677: static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */
                   1678: {
                   1679:        CURLcode     error=CURLE_OK;
                   1680: 
                   1681:        switch (option) {
                   1682:                case CURLOPT_INFILESIZE:
                   1683:                case CURLOPT_VERBOSE:
                   1684:                case CURLOPT_HEADER:
                   1685:                case CURLOPT_NOPROGRESS:
                   1686:                case CURLOPT_NOBODY:
                   1687:                case CURLOPT_FAILONERROR:
                   1688:                case CURLOPT_UPLOAD:
                   1689:                case CURLOPT_POST:
                   1690:                case CURLOPT_FTPLISTONLY:
                   1691:                case CURLOPT_FTPAPPEND:
                   1692:                case CURLOPT_NETRC:
                   1693:                case CURLOPT_PUT:
                   1694: #if CURLOPT_MUTE != 0
                   1695:                 case CURLOPT_MUTE:
                   1696: #endif
                   1697:                case CURLOPT_TIMEOUT:
                   1698: #if LIBCURL_VERSION_NUM > 0x071002
                   1699:                case CURLOPT_TIMEOUT_MS:
                   1700: #endif
                   1701:                case CURLOPT_FTP_USE_EPSV:
                   1702:                case CURLOPT_LOW_SPEED_LIMIT:
                   1703:                case CURLOPT_SSLVERSION:
                   1704:                case CURLOPT_LOW_SPEED_TIME:
                   1705:                case CURLOPT_RESUME_FROM:
                   1706:                case CURLOPT_TIMEVALUE:
                   1707:                case CURLOPT_TIMECONDITION:
                   1708:                case CURLOPT_TRANSFERTEXT:
                   1709:                case CURLOPT_HTTPPROXYTUNNEL:
                   1710:                case CURLOPT_FILETIME:
                   1711:                case CURLOPT_MAXREDIRS:
                   1712:                case CURLOPT_MAXCONNECTS:
                   1713:                case CURLOPT_CLOSEPOLICY:
                   1714:                case CURLOPT_FRESH_CONNECT:
                   1715:                case CURLOPT_FORBID_REUSE:
                   1716:                case CURLOPT_CONNECTTIMEOUT:
                   1717: #if LIBCURL_VERSION_NUM > 0x071002
                   1718:                case CURLOPT_CONNECTTIMEOUT_MS:
                   1719: #endif
                   1720:                case CURLOPT_SSL_VERIFYHOST:
                   1721:                case CURLOPT_SSL_VERIFYPEER:
                   1722:                case CURLOPT_DNS_USE_GLOBAL_CACHE:
                   1723:                case CURLOPT_NOSIGNAL:
                   1724:                case CURLOPT_PROXYTYPE:
                   1725:                case CURLOPT_BUFFERSIZE:
                   1726:                case CURLOPT_HTTPGET:
                   1727:                case CURLOPT_HTTP_VERSION:
                   1728:                case CURLOPT_CRLF:
                   1729:                case CURLOPT_DNS_CACHE_TIMEOUT:
                   1730:                case CURLOPT_PROXYPORT:
                   1731:                case CURLOPT_FTP_USE_EPRT:
                   1732: #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
                   1733:                case CURLOPT_HTTPAUTH:
                   1734: #endif
                   1735: #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
                   1736:                case CURLOPT_PROXYAUTH:
                   1737:                case CURLOPT_FTP_CREATE_MISSING_DIRS:
                   1738: #endif
                   1739: 
                   1740: #if LIBCURL_VERSION_NUM >= 0x070c02
                   1741:                case CURLOPT_FTPSSLAUTH:
                   1742: #endif
                   1743: #if LIBCURL_VERSION_NUM >  0x070b00
                   1744:                case CURLOPT_FTP_SSL:
                   1745: #endif
                   1746:                case CURLOPT_UNRESTRICTED_AUTH:
                   1747:                case CURLOPT_PORT:
                   1748:                case CURLOPT_AUTOREFERER:
                   1749:                case CURLOPT_COOKIESESSION:
                   1750: #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
                   1751:                case CURLOPT_TCP_NODELAY:
                   1752: #endif
                   1753: #if LIBCURL_VERSION_NUM >= 0x71304
                   1754:                case CURLOPT_REDIR_PROTOCOLS:
                   1755:                case CURLOPT_PROTOCOLS:
                   1756: #endif
                   1757: #if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
                   1758:                case CURLOPT_IPRESOLVE:
                   1759: #endif
                   1760: #if LIBCURL_VERSION_NUM >= 0x070f01
                   1761:                case CURLOPT_FTP_FILEMETHOD:
                   1762:                case CURLOPT_FTP_SKIP_PASV_IP:
                   1763: #endif
                   1764: #if LIBCURL_VERSION_NUM >  0x071301
                   1765:                case CURLOPT_CERTINFO:
                   1766: #endif
                   1767:                        convert_to_long_ex(zvalue);
                   1768: #if LIBCURL_VERSION_NUM >= 0x71304
                   1769:                        if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
                   1770:                                ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
                   1771:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when in safe_mode or an open_basedir is set");
                   1772:                                        RETVAL_FALSE;
                   1773:                                        return 1;
                   1774:                        }
                   1775: #endif
                   1776:                        error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
                   1777:                        break;
                   1778: #if LIBCURL_VERSION_NUM > 0x070f04
                   1779:                case CURLOPT_MAX_RECV_SPEED_LARGE:
                   1780:                case CURLOPT_MAX_SEND_SPEED_LARGE:
                   1781:                        convert_to_long_ex(zvalue);
                   1782:                        error = curl_easy_setopt(ch->cp, option, (curl_off_t)Z_LVAL_PP(zvalue));
                   1783:                        break;
                   1784: #endif
                   1785:                case CURLOPT_FOLLOWLOCATION:
                   1786:                        convert_to_long_ex(zvalue);
                   1787:                        if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
                   1788:                                if (Z_LVAL_PP(zvalue) != 0) {
                   1789:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set");
                   1790:                                        RETVAL_FALSE;
                   1791:                                        return 1;
                   1792:                                }
                   1793:                        }
                   1794:                        error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
                   1795:                        break;
                   1796: #if LIBCURL_VERSION_NUM > 0x071301
                   1797:                case CURLOPT_POSTREDIR:
                   1798:                        convert_to_long_ex(zvalue);
                   1799:                        error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, Z_LVAL_PP(zvalue) & CURL_REDIR_POST_ALL);
                   1800:                        break;
                   1801: #endif
                   1802:                case CURLOPT_PRIVATE:
                   1803:                case CURLOPT_URL:
                   1804:                case CURLOPT_PROXY:
                   1805:                case CURLOPT_USERPWD:
                   1806:                case CURLOPT_PROXYUSERPWD:
                   1807:                case CURLOPT_RANGE:
                   1808:                case CURLOPT_CUSTOMREQUEST:
                   1809:                case CURLOPT_USERAGENT:
                   1810:                case CURLOPT_FTPPORT:
                   1811:                case CURLOPT_COOKIE:
                   1812:                case CURLOPT_REFERER:
                   1813:                case CURLOPT_INTERFACE:
                   1814:                case CURLOPT_KRB4LEVEL:
                   1815:                case CURLOPT_EGDSOCKET:
                   1816:                case CURLOPT_CAINFO:
                   1817:                case CURLOPT_CAPATH:
                   1818:                case CURLOPT_SSL_CIPHER_LIST:
                   1819:                case CURLOPT_SSLKEY:
                   1820:                case CURLOPT_SSLKEYTYPE:
                   1821:                case CURLOPT_SSLKEYPASSWD:
                   1822:                case CURLOPT_SSLENGINE:
                   1823:                case CURLOPT_SSLENGINE_DEFAULT:
                   1824:                case CURLOPT_SSLCERTTYPE:
                   1825:                case CURLOPT_ENCODING:
                   1826: #if LIBCURL_VERSION_NUM >= 0x071300
                   1827:                case CURLOPT_SSH_PUBLIC_KEYFILE:
                   1828:                case CURLOPT_SSH_PRIVATE_KEYFILE:
                   1829: #endif
                   1830:                {
                   1831: #if LIBCURL_VERSION_NUM < 0x071100
                   1832:                        char *copystr = NULL;
                   1833: #endif
                   1834: 
                   1835:                        convert_to_string_ex(zvalue);
                   1836: #if LIBCURL_VERSION_NUM >= 0x071300
                   1837:                        if (
                   1838:                                option == CURLOPT_SSH_PUBLIC_KEYFILE || option == CURLOPT_SSH_PRIVATE_KEYFILE
                   1839: 
                   1840:                        ) {
                   1841:                                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))) {
                   1842:                                        RETVAL_FALSE;
                   1843:                                        return 1;
                   1844:                                }
                   1845:                        }
                   1846: #endif
                   1847:                        if (option == CURLOPT_URL) {
                   1848:                                if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue))) {
                   1849:                                        RETVAL_FALSE;
                   1850:                                        return 1;
                   1851:                                }
                   1852:                        } else {
                   1853:                                if (option == CURLOPT_PRIVATE) {
                   1854:                                        char *copystr;
                   1855: #if LIBCURL_VERSION_NUM < 0x071100
                   1856: string_copy:
                   1857: #endif
                   1858:                                        copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
                   1859:                                        error = curl_easy_setopt(ch->cp, option, copystr);
                   1860:                                        zend_llist_add_element(&ch->to_free->str, &copystr);
                   1861:                                } else {
                   1862: #if LIBCURL_VERSION_NUM >= 0x071100
                   1863:                                        /* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
                   1864:                                        error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
                   1865: #else                          
                   1866:                                        goto string_copy;                       
                   1867: #endif
                   1868:                                }
                   1869:                        }
                   1870:                        break;
                   1871:                }
                   1872:                case CURLOPT_FILE:
                   1873:                case CURLOPT_INFILE:
                   1874:                case CURLOPT_WRITEHEADER:
                   1875:                case CURLOPT_STDERR: {
                   1876:                        FILE *fp = NULL;
                   1877:                        int type;
                   1878:                        void * what;
                   1879: 
                   1880:                        what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream(), php_file_le_pstream());
                   1881:                        if (!what) {
                   1882:                                RETVAL_FALSE;
                   1883:                                return 1;
                   1884:                        }
                   1885: 
                   1886:                        if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
                   1887:                                RETVAL_FALSE;
                   1888:                                return 1;
                   1889:                        }
                   1890: 
                   1891:                        if (!fp) {
                   1892:                                RETVAL_FALSE;
                   1893:                                return 1;
                   1894:                        }
                   1895: 
                   1896:                        error = CURLE_OK;
                   1897:                        switch (option) {
                   1898:                                case CURLOPT_FILE:
                   1899:                                        if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
                   1900:                                                if (ch->handlers->write->stream) {
                   1901:                                                        Z_DELREF_P(ch->handlers->write->stream);
                   1902:                                                }
                   1903:                                                Z_ADDREF_PP(zvalue);
                   1904:                                                ch->handlers->write->fp = fp;
                   1905:                                                ch->handlers->write->method = PHP_CURL_FILE;
                   1906:                                                ch->handlers->write->stream = *zvalue;
                   1907:                                        } else {
                   1908:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
                   1909:                                                RETVAL_FALSE;
                   1910:                                                return 1;
                   1911:                                        }
                   1912:                                        break;
                   1913:                                case CURLOPT_WRITEHEADER:
                   1914:                                        if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
                   1915:                                                if (ch->handlers->write_header->stream) {
                   1916:                                                        Z_DELREF_P(ch->handlers->write_header->stream);
                   1917:                                                }
                   1918:                                                Z_ADDREF_PP(zvalue);
                   1919:                                                ch->handlers->write_header->fp = fp;
                   1920:                                                ch->handlers->write_header->method = PHP_CURL_FILE;
                   1921:                                                ch->handlers->write_header->stream = *zvalue;
                   1922:                                        } else {
                   1923:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
                   1924:                                                RETVAL_FALSE;
                   1925:                                                return 1;
                   1926:                                        }
                   1927:                                        break;
                   1928:                                case CURLOPT_INFILE:
                   1929:                                        if (ch->handlers->read->stream) {
                   1930:                                                Z_DELREF_P(ch->handlers->read->stream);
                   1931:                                        }
                   1932:                                        Z_ADDREF_PP(zvalue);
                   1933:                                        ch->handlers->read->fp = fp;
                   1934:                                        ch->handlers->read->fd = Z_LVAL_PP(zvalue);
                   1935:                                        ch->handlers->read->stream = *zvalue;
                   1936:                                        break;
                   1937:                                case CURLOPT_STDERR:
                   1938:                                        if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
                   1939:                                                if (ch->handlers->std_err) {
                   1940:                                                        zval_ptr_dtor(&ch->handlers->std_err);
                   1941:                                                }
                   1942:                                                zval_add_ref(zvalue);
                   1943:                                                ch->handlers->std_err = *zvalue;
                   1944:                                        } else {
                   1945:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
                   1946:                                                RETVAL_FALSE;
                   1947:                                                return 1;
                   1948:                                        }
                   1949:                                        /* break omitted intentionally */
                   1950:                                default:
                   1951:                                        error = curl_easy_setopt(ch->cp, option, fp);
                   1952:                                        break;
                   1953:                        }
                   1954: 
                   1955:                        break;
                   1956:                }
                   1957:                case CURLOPT_RETURNTRANSFER:
                   1958:                        convert_to_long_ex(zvalue);
                   1959: 
                   1960:                        if (Z_LVAL_PP(zvalue)) {
                   1961:                                ch->handlers->write->method = PHP_CURL_RETURN;
                   1962:                        } else {
                   1963:                                ch->handlers->write->method = PHP_CURL_STDOUT;
                   1964:                        }
                   1965:                        break;
                   1966:                case CURLOPT_BINARYTRANSFER:
                   1967:                        convert_to_long_ex(zvalue);
                   1968: 
                   1969:                        if (Z_LVAL_PP(zvalue)) {
                   1970:                                ch->handlers->write->type = PHP_CURL_BINARY;
                   1971:                        } else {
                   1972:                                ch->handlers->write->type = PHP_CURL_ASCII;
                   1973:                        }
                   1974:                        break;
                   1975:                case CURLOPT_WRITEFUNCTION:
                   1976:                        if (ch->handlers->write->func_name) {
                   1977:                                zval_ptr_dtor(&ch->handlers->write->func_name);
                   1978:                                ch->handlers->write->fci_cache = empty_fcall_info_cache;
                   1979:                        }
                   1980:                        zval_add_ref(zvalue);
                   1981:                        ch->handlers->write->func_name = *zvalue;
                   1982:                        ch->handlers->write->method = PHP_CURL_USER;
                   1983:                        break;
                   1984:                case CURLOPT_READFUNCTION:
                   1985:                        if (ch->handlers->read->func_name) {
                   1986:                                zval_ptr_dtor(&ch->handlers->read->func_name);
                   1987:                                ch->handlers->read->fci_cache = empty_fcall_info_cache;
                   1988:                        }
                   1989:                        zval_add_ref(zvalue);
                   1990:                        ch->handlers->read->func_name = *zvalue;
                   1991:                        ch->handlers->read->method = PHP_CURL_USER;
                   1992:                        break;
                   1993:                case CURLOPT_PROGRESSFUNCTION:
                   1994:                        curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION,      curl_progress);
                   1995:                        curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
                   1996:                        if (ch->handlers->progress->func_name) {
                   1997:                                zval_ptr_dtor(&ch->handlers->progress->func_name);
                   1998:                                ch->handlers->progress->fci_cache = empty_fcall_info_cache;
                   1999:                        }
                   2000:                        zval_add_ref(zvalue);
                   2001:                        ch->handlers->progress->func_name = *zvalue;
                   2002:                        ch->handlers->progress->method = PHP_CURL_USER;
                   2003:                        break;
                   2004:                case CURLOPT_HEADERFUNCTION:
                   2005:                        if (ch->handlers->write_header->func_name) {
                   2006:                                zval_ptr_dtor(&ch->handlers->write_header->func_name);
                   2007:                                ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
                   2008:                        }
                   2009:                        zval_add_ref(zvalue);
                   2010:                        ch->handlers->write_header->func_name = *zvalue;
                   2011:                        ch->handlers->write_header->method = PHP_CURL_USER;
                   2012:                        break;
                   2013: #if CURLOPT_PASSWDFUNCTION != 0
                   2014:                case CURLOPT_PASSWDFUNCTION:
                   2015:                        if (ch->handlers->passwd) {
                   2016:                                zval_ptr_dtor(&ch->handlers->passwd);
                   2017:                        }
                   2018:                        zval_add_ref(zvalue);
                   2019:                        ch->handlers->passwd = *zvalue;
                   2020:                        error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd);
                   2021:                        error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA,     (void *) ch);
                   2022:                        break;
                   2023: #endif
                   2024:                case CURLOPT_POSTFIELDS:
                   2025:                        if (Z_TYPE_PP(zvalue) == IS_ARRAY || Z_TYPE_PP(zvalue) == IS_OBJECT) {
                   2026:                                zval            **current;
                   2027:                                HashTable        *postfields;
                   2028:                                struct HttpPost  *first = NULL;
                   2029:                                struct HttpPost  *last  = NULL;
                   2030:                                char             *postval;
                   2031:                                char             *string_key = NULL;
                   2032:                                ulong             num_key;
                   2033:                                uint              string_key_len;
                   2034: 
                   2035:                                postfields = HASH_OF(*zvalue);
                   2036:                                if (!postfields) {
                   2037:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
                   2038:                                        RETVAL_FALSE;
                   2039:                                        return 1;
                   2040:                                }
                   2041: 
                   2042:                                for (zend_hash_internal_pointer_reset(postfields);
                   2043:                                         zend_hash_get_current_data(postfields, (void **) &current) == SUCCESS;
                   2044:                                         zend_hash_move_forward(postfields)
                   2045:                                ) {
                   2046: 
                   2047:                                        SEPARATE_ZVAL(current);
                   2048:                                        convert_to_string_ex(current);
                   2049: 
                   2050:                                        zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL);
                   2051: 
                   2052:                                        postval = Z_STRVAL_PP(current);
                   2053: 
                   2054:                                        /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
                   2055:                                         * must be explicitly cast to long in curl_formadd
                   2056:                                         * use since curl needs a long not an int. */
                   2057:                                        if (*postval == '@') {
                   2058:                                                char *type, *filename;
                   2059:                                                ++postval;
                   2060: 
                   2061:                                                if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) {
                   2062:                                                        *type = '\0';
                   2063:                                                }
                   2064:                                                if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) {
                   2065:                                                        *filename = '\0';
                   2066:                                                }
                   2067:                                                /* safe_mode / open_basedir check */
                   2068:                                                if (php_check_open_basedir(postval TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(postval, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
                   2069:                                                        RETVAL_FALSE;
                   2070:                                                        return 1;
                   2071:                                                }
                   2072:                                                error = curl_formadd(&first, &last,
                   2073:                                                                                CURLFORM_COPYNAME, string_key,
                   2074:                                                                                CURLFORM_NAMELENGTH, (long)string_key_len - 1,
                   2075:                                                                                CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval,
                   2076:                                                                                CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream",
                   2077:                                                                                CURLFORM_FILE, postval,
                   2078:                                                                                CURLFORM_END);
                   2079:                                                if (type) {
                   2080:                                                        *type = ';';
                   2081:                                                }
                   2082:                                                if (filename) {
                   2083:                                                        *filename = ';';
                   2084:                                                }
                   2085:                                        } else {
                   2086:                                                error = curl_formadd(&first, &last,
                   2087:                                                                                         CURLFORM_COPYNAME, string_key,
                   2088:                                                                                         CURLFORM_NAMELENGTH, (long)string_key_len - 1,
                   2089:                                                                                         CURLFORM_COPYCONTENTS, postval,
                   2090:                                                                                         CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current),
                   2091:                                                                                         CURLFORM_END);
                   2092:                                        }
                   2093:                                }
                   2094: 
                   2095:                                SAVE_CURL_ERROR(ch, error);
                   2096:                                if (error != CURLE_OK) {
                   2097:                                        RETVAL_FALSE;
                   2098:                                        return 1;
                   2099:                                }
                   2100: 
                   2101:                                zend_llist_add_element(&ch->to_free->post, &first);
                   2102:                                error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
                   2103: 
                   2104:                        } else {
                   2105: #if LIBCURL_VERSION_NUM >= 0x071101
                   2106:                                convert_to_string_ex(zvalue);
                   2107:                                /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
                   2108:                                error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
                   2109:                                error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue));
                   2110: #else
                   2111:                                char *post = NULL;
                   2112: 
                   2113:                                convert_to_string_ex(zvalue);
                   2114:                                post = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
                   2115:                                zend_llist_add_element(&ch->to_free->str, &post);
                   2116: 
                   2117:                                error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
                   2118:                                error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
                   2119: #endif
                   2120:                        }
                   2121:                        break;
                   2122:                case CURLOPT_HTTPHEADER:
                   2123:                case CURLOPT_QUOTE:
                   2124:                case CURLOPT_HTTP200ALIASES:
                   2125:                case CURLOPT_POSTQUOTE: {
                   2126:                        zval              **current;
                   2127:                        HashTable          *ph;
                   2128:                        struct curl_slist  *slist = NULL;
                   2129: 
                   2130:                        ph = HASH_OF(*zvalue);
                   2131:                        if (!ph) {
                   2132:                                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");
                   2133:                                RETVAL_FALSE;
                   2134:                                return 1;
                   2135:                        }
                   2136: 
                   2137:                        for (zend_hash_internal_pointer_reset(ph);
                   2138:                                 zend_hash_get_current_data(ph, (void **) &current) == SUCCESS;
                   2139:                                 zend_hash_move_forward(ph)
                   2140:                        ) {
                   2141:                                SEPARATE_ZVAL(current);
                   2142:                                convert_to_string_ex(current);
                   2143: 
                   2144:                                slist = curl_slist_append(slist, Z_STRVAL_PP(current));
                   2145:                                if (!slist) {
                   2146:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist");
                   2147:                                        RETVAL_FALSE;
                   2148:                                        return 1;
                   2149:                                }
                   2150:                        }
                   2151:                        zend_llist_add_element(&ch->to_free->slist, &slist);
                   2152: 
                   2153:                        error = curl_easy_setopt(ch->cp, option, slist);
                   2154: 
                   2155:                        break;
                   2156:                }
                   2157:                /* the following options deal with files, therefor safe_mode & open_basedir checks
                   2158:                 * are required.
                   2159:                 */
                   2160:                case CURLOPT_COOKIEJAR:
                   2161:                case CURLOPT_SSLCERT:
                   2162:                case CURLOPT_RANDOM_FILE:
                   2163:                case CURLOPT_COOKIEFILE: {
                   2164: #if LIBCURL_VERSION_NUM < 0x071100
                   2165:                        char *copystr = NULL;
                   2166: #endif
                   2167: 
                   2168:                        convert_to_string_ex(zvalue);
                   2169: 
                   2170:                        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))) {
                   2171:                                RETVAL_FALSE;
                   2172:                                return 1;
                   2173:                        }
                   2174: 
                   2175: #if LIBCURL_VERSION_NUM >= 0x071100
                   2176:                        error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
                   2177: #else
                   2178:                        copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
                   2179: 
                   2180:                        error = curl_easy_setopt(ch->cp, option, copystr);
                   2181:                        zend_llist_add_element(&ch->to_free->str, &copystr);
                   2182: #endif
                   2183:                        break;
                   2184:                }
                   2185:                case CURLINFO_HEADER_OUT:
                   2186:                        convert_to_long_ex(zvalue);
                   2187:                        if (Z_LVAL_PP(zvalue) == 1) {
                   2188:                                curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
                   2189:                                curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
                   2190:                                curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
                   2191:                        } else {
                   2192:                                curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
                   2193:                                curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
                   2194:                                curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
                   2195:                        }
                   2196:                        break;
                   2197:        }
                   2198: 
                   2199:        SAVE_CURL_ERROR(ch, error);
                   2200:        if (error != CURLE_OK) {
                   2201:                return 1;
                   2202:        } else {
                   2203:                return 0;
                   2204:        }
                   2205: }
                   2206: /* }}} */
                   2207: 
                   2208: /* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
                   2209:    Set an option for a cURL transfer */
                   2210: PHP_FUNCTION(curl_setopt)
                   2211: {
                   2212:        zval       *zid, **zvalue;
                   2213:        long        options;
                   2214:        php_curl   *ch;
                   2215: 
                   2216:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &zid, &options, &zvalue) == FAILURE) {
                   2217:                return;
                   2218:        }
                   2219: 
                   2220:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2221: 
                   2222:        if (options <= 0) {
                   2223:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid curl configuration option");
                   2224:                RETURN_FALSE;
                   2225:        }
                   2226: 
                   2227:        if (!_php_curl_setopt(ch, options, zvalue, return_value TSRMLS_CC)) {
                   2228:                RETURN_TRUE;
                   2229:        } else {
                   2230:                RETURN_FALSE;
                   2231:        }
                   2232: }
                   2233: /* }}} */
                   2234: 
                   2235: /* {{{ proto bool curl_setopt_array(resource ch, array options)
                   2236:    Set an array of option for a cURL transfer */
                   2237: PHP_FUNCTION(curl_setopt_array)
                   2238: {
                   2239:        zval            *zid, *arr, **entry;
                   2240:        php_curl        *ch;
                   2241:        ulong           option;
                   2242:        HashPosition    pos;
                   2243:        char            *string_key;
                   2244:        uint            str_key_len;
                   2245: 
                   2246:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &zid, &arr) == FAILURE) {
                   2247:                return;
                   2248:        }
                   2249: 
                   2250:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2251: 
                   2252:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
                   2253:        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
                   2254:                if (zend_hash_get_current_key_ex(Z_ARRVAL_P(arr), &string_key, &str_key_len, &option, 0, &pos) != HASH_KEY_IS_LONG) {
                   2255:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values");
                   2256:                        RETURN_FALSE;
                   2257:                }
                   2258:                if (_php_curl_setopt(ch, (long) option, entry, return_value TSRMLS_CC)) {
                   2259:                        RETURN_FALSE;
                   2260:                }
                   2261:                zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
                   2262:        }
                   2263:        RETURN_TRUE;
                   2264: }
                   2265: /* }}} */
                   2266: 
                   2267: /* {{{ _php_curl_cleanup_handle(ch)
                   2268:    Cleanup an execution phase */
                   2269: void _php_curl_cleanup_handle(php_curl *ch)
                   2270: {
                   2271:        if (ch->handlers->write->buf.len > 0) {
                   2272:                smart_str_free(&ch->handlers->write->buf);
                   2273:        }
                   2274:        if (ch->header.str_len) {
                   2275:                efree(ch->header.str);
                   2276:                ch->header.str_len = 0;
                   2277:        }
                   2278: 
                   2279:        memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
                   2280:        ch->err.no = 0;
                   2281: }
                   2282: /* }}} */
                   2283: 
                   2284: /* {{{ proto bool curl_exec(resource ch)
                   2285:    Perform a cURL session */
                   2286: PHP_FUNCTION(curl_exec)
                   2287: {
                   2288:        CURLcode        error;
                   2289:        zval            *zid;
                   2290:        php_curl        *ch;
                   2291: 
                   2292:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
                   2293:                return;
                   2294:        }
                   2295: 
                   2296:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2297: 
                   2298:        _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
                   2299: 
                   2300:        _php_curl_cleanup_handle(ch);
                   2301: 
                   2302:        error = curl_easy_perform(ch->cp);
                   2303:        SAVE_CURL_ERROR(ch, error);
                   2304:        /* CURLE_PARTIAL_FILE is returned by HEAD requests */
                   2305:        if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) {
                   2306:                if (ch->handlers->write->buf.len > 0) {
                   2307:                        smart_str_free(&ch->handlers->write->buf);
                   2308:                }
                   2309:                RETURN_FALSE;
                   2310:        }
                   2311: 
                   2312:        if (ch->handlers->std_err) {
                   2313:                php_stream  *stream;
                   2314:                stream = (php_stream*)zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
                   2315:                if (stream) {
                   2316:                        php_stream_flush(stream);
                   2317:                }
                   2318:        }
                   2319: 
                   2320:        if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
                   2321:                smart_str_0(&ch->handlers->write->buf);
                   2322:                RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
                   2323:        }
                   2324: 
                   2325:        /* flush the file handle, so any remaining data is synched to disk */
                   2326:        if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
                   2327:                fflush(ch->handlers->write->fp);
                   2328:        }
                   2329:        if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
                   2330:                fflush(ch->handlers->write_header->fp);
                   2331:        }
                   2332: 
                   2333:        if (ch->handlers->write->method == PHP_CURL_RETURN) {
                   2334:                RETURN_EMPTY_STRING();
                   2335:        } else {
                   2336:                RETURN_TRUE;
                   2337:        }
                   2338: }
                   2339: /* }}} */
                   2340: 
                   2341: /* {{{ proto mixed curl_getinfo(resource ch [, int option])
                   2342:    Get information regarding a specific transfer */
                   2343: PHP_FUNCTION(curl_getinfo)
                   2344: {
                   2345:        zval            *zid;
                   2346:        php_curl        *ch;
                   2347:        long            option = 0;
                   2348: 
                   2349:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zid, &option) == FAILURE) {
                   2350:                return;
                   2351:        }
                   2352: 
                   2353:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2354: 
                   2355:        if (ZEND_NUM_ARGS() < 2) {
                   2356:                char   *s_code;
                   2357:                long    l_code;
                   2358:                double  d_code;
                   2359: #if LIBCURL_VERSION_NUM >  0x071301
                   2360:                struct curl_certinfo *ci = NULL;
                   2361:                zval *listcode;
                   2362: #endif
                   2363: 
                   2364:                array_init(return_value);
                   2365: 
                   2366:                if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
                   2367:                        CAAS("url", s_code);
                   2368:                }
                   2369:                if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
                   2370:                        if (s_code != NULL) {
                   2371:                                CAAS("content_type", s_code);
                   2372:                        } else {
                   2373:                                zval *retnull;
                   2374:                                MAKE_STD_ZVAL(retnull);
                   2375:                                ZVAL_NULL(retnull);
                   2376:                                CAAZ("content_type", retnull);
                   2377:                        }
                   2378:                }
                   2379:                if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
                   2380:                        CAAL("http_code", l_code);
                   2381:                }
                   2382:                if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
                   2383:                        CAAL("header_size", l_code);
                   2384:                }
                   2385:                if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
                   2386:                        CAAL("request_size", l_code);
                   2387:                }
                   2388:                if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
                   2389:                        CAAL("filetime", l_code);
                   2390:                }
                   2391:                if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
                   2392:                        CAAL("ssl_verify_result", l_code);
                   2393:                }
                   2394:                if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
                   2395:                        CAAL("redirect_count", l_code);
                   2396:                }
                   2397:                if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
                   2398:                        CAAD("total_time", d_code);
                   2399:                }
                   2400:                if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
                   2401:                        CAAD("namelookup_time", d_code);
                   2402:                }
                   2403:                if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
                   2404:                        CAAD("connect_time", d_code);
                   2405:                }
                   2406:                if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
                   2407:                        CAAD("pretransfer_time", d_code);
                   2408:                }
                   2409:                if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
                   2410:                        CAAD("size_upload", d_code);
                   2411:                }
                   2412:                if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
                   2413:                        CAAD("size_download", d_code);
                   2414:                }
                   2415:                if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
                   2416:                        CAAD("speed_download", d_code);
                   2417:                }
                   2418:                if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
                   2419:                        CAAD("speed_upload", d_code);
                   2420:                }
                   2421:                if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
                   2422:                        CAAD("download_content_length", d_code);
                   2423:                }
                   2424:                if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
                   2425:                        CAAD("upload_content_length", d_code);
                   2426:                }
                   2427:                if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
                   2428:                        CAAD("starttransfer_time", d_code);
                   2429:                }
                   2430:                if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
                   2431:                        CAAD("redirect_time", d_code);
                   2432:                }
                   2433: #if LIBCURL_VERSION_NUM > 0x071301
                   2434:                if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
                   2435:                        MAKE_STD_ZVAL(listcode);
                   2436:                        array_init(listcode);
                   2437:                        create_certinfo(ci, listcode TSRMLS_CC);
                   2438:                        CAAZ("certinfo", listcode);
                   2439:                }
                   2440: #endif
                   2441: #if LIBCURL_VERSION_NUM >= 0x071202
                   2442:                if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
                   2443:                        CAAS("redirect_url", s_code);
                   2444:                }
                   2445: #endif
                   2446:                if (ch->header.str_len > 0) {
                   2447:                        CAAS("request_header", ch->header.str);
                   2448:                }
                   2449:        } else {
                   2450:                switch (option) {
                   2451:                        case CURLINFO_PRIVATE:
                   2452:                        case CURLINFO_EFFECTIVE_URL:
                   2453:                        case CURLINFO_CONTENT_TYPE:
                   2454: #if LIBCURL_VERSION_NUM >= 0x071202
                   2455:                        case CURLINFO_REDIRECT_URL:
                   2456: #endif
                   2457:                        {
                   2458:                                char *s_code = NULL;
                   2459: 
                   2460:                                if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
                   2461:                                        RETURN_STRING(s_code, 1);
                   2462:                                } else {
                   2463:                                        RETURN_FALSE;
                   2464:                                }
                   2465:                                break;
                   2466:                        }
                   2467:                        case CURLINFO_HTTP_CODE:
                   2468:                        case CURLINFO_HEADER_SIZE:
                   2469:                        case CURLINFO_REQUEST_SIZE:
                   2470:                        case CURLINFO_FILETIME:
                   2471:                        case CURLINFO_SSL_VERIFYRESULT:
                   2472:                        case CURLINFO_REDIRECT_COUNT: {
                   2473:                                long code = 0;
                   2474: 
                   2475:                                if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
                   2476:                                        RETURN_LONG(code);
                   2477:                                } else {
                   2478:                                        RETURN_FALSE;
                   2479:                                }
                   2480:                                break;
                   2481:                        }
                   2482:                        case CURLINFO_TOTAL_TIME:
                   2483:                        case CURLINFO_NAMELOOKUP_TIME:
                   2484:                        case CURLINFO_CONNECT_TIME:
                   2485:                        case CURLINFO_PRETRANSFER_TIME:
                   2486:                        case CURLINFO_SIZE_UPLOAD:
                   2487:                        case CURLINFO_SIZE_DOWNLOAD:
                   2488:                        case CURLINFO_SPEED_DOWNLOAD:
                   2489:                        case CURLINFO_SPEED_UPLOAD:
                   2490:                        case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
                   2491:                        case CURLINFO_CONTENT_LENGTH_UPLOAD:
                   2492:                        case CURLINFO_STARTTRANSFER_TIME:
                   2493:                        case CURLINFO_REDIRECT_TIME: {
                   2494:                                double code = 0.0;
                   2495: 
                   2496:                                if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
                   2497:                                        RETURN_DOUBLE(code);
                   2498:                                } else {
                   2499:                                        RETURN_FALSE;
                   2500:                                }
                   2501:                                break;
                   2502:                        }
                   2503:                        case CURLINFO_HEADER_OUT:
                   2504:                                if (ch->header.str_len > 0) {
                   2505:                                        RETURN_STRINGL(ch->header.str, ch->header.str_len, 1);
                   2506:                                } else {
                   2507:                                        RETURN_FALSE;
                   2508:                                }
                   2509: #if LIBCURL_VERSION_NUM > 0x071301
                   2510:                        case CURLINFO_CERTINFO: {
                   2511:                                struct curl_certinfo *ci = NULL;
                   2512: 
                   2513:                                array_init(return_value);
                   2514:                                
                   2515:                                if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
                   2516:                                        create_certinfo(ci, return_value TSRMLS_CC);
                   2517:                                } else {
                   2518:                                        RETURN_FALSE;
                   2519:                                }
                   2520:                                break;
                   2521:                        }
                   2522: #endif
                   2523:                }
                   2524:        }
                   2525: }
                   2526: /* }}} */
                   2527: 
                   2528: /* {{{ proto string curl_error(resource ch)
                   2529:    Return a string contain the last error for the current session */
                   2530: PHP_FUNCTION(curl_error)
                   2531: {
                   2532:        zval            *zid;
                   2533:        php_curl        *ch;
                   2534: 
                   2535:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
                   2536:                return;
                   2537:        }
                   2538: 
                   2539:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2540: 
                   2541:        ch->err.str[CURL_ERROR_SIZE] = 0;
                   2542:        RETURN_STRING(ch->err.str, 1);
                   2543: }
                   2544: /* }}} */
                   2545: 
                   2546: /* {{{ proto int curl_errno(resource ch)
                   2547:    Return an integer containing the last error number */
                   2548: PHP_FUNCTION(curl_errno)
                   2549: {
                   2550:        zval            *zid;
                   2551:        php_curl        *ch;
                   2552: 
                   2553:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
                   2554:                return;
                   2555:        }
                   2556: 
                   2557:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2558: 
                   2559:        RETURN_LONG(ch->err.no);
                   2560: }
                   2561: /* }}} */
                   2562: 
                   2563: /* {{{ proto void curl_close(resource ch)
                   2564:    Close a cURL session */
                   2565: PHP_FUNCTION(curl_close)
                   2566: {
                   2567:        zval            *zid;
                   2568:        php_curl        *ch;
                   2569: 
                   2570:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
                   2571:                return;
                   2572:        }
                   2573: 
                   2574:        ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
                   2575: 
                   2576:        if (ch->in_callback) {
                   2577:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close cURL handle from a callback");
                   2578:                return;
                   2579:        }
                   2580: 
                   2581:        if (ch->uses) {
                   2582:                ch->uses--;
                   2583:        } else {
                   2584:                zend_list_delete(Z_LVAL_P(zid));
                   2585:        }
                   2586: }
                   2587: /* }}} */
                   2588: 
                   2589: /* {{{ _php_curl_close()
                   2590:    List destructor for curl handles */
                   2591: static void _php_curl_close_ex(php_curl *ch TSRMLS_DC)
                   2592: {
                   2593: #if PHP_CURL_DEBUG
                   2594:        fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
                   2595: #endif
                   2596: 
                   2597:        _php_curl_verify_handlers(ch, 0 TSRMLS_CC);
                   2598:        curl_easy_cleanup(ch->cp);
                   2599: 
                   2600:        /* cURL destructors should be invoked only by last curl handle */
                   2601:        if (Z_REFCOUNT_P(ch->clone) <= 1) {
                   2602:                zend_llist_clean(&ch->to_free->str);
                   2603:                zend_llist_clean(&ch->to_free->slist);
                   2604:                zend_llist_clean(&ch->to_free->post);
                   2605:                efree(ch->to_free);
                   2606:                FREE_ZVAL(ch->clone);
                   2607:        } else {
                   2608:                Z_DELREF_P(ch->clone);
                   2609:        }
                   2610: 
                   2611:        if (ch->handlers->write->buf.len > 0) {
                   2612:                smart_str_free(&ch->handlers->write->buf);
                   2613:        }
                   2614:        if (ch->handlers->write->func_name) {
                   2615:                zval_ptr_dtor(&ch->handlers->write->func_name);
                   2616:        }
                   2617:        if (ch->handlers->read->func_name) {
                   2618:                zval_ptr_dtor(&ch->handlers->read->func_name);
                   2619:        }
                   2620:        if (ch->handlers->write_header->func_name) {
                   2621:                zval_ptr_dtor(&ch->handlers->write_header->func_name);
                   2622:        }
                   2623:        if (ch->handlers->progress->func_name) {
                   2624:                zval_ptr_dtor(&ch->handlers->progress->func_name);
                   2625:        }
                   2626:        if (ch->handlers->passwd) {
                   2627:                zval_ptr_dtor(&ch->handlers->passwd);
                   2628:        }
                   2629:        if (ch->handlers->std_err) {
                   2630:                zval_ptr_dtor(&ch->handlers->std_err);
                   2631:        }
                   2632:        if (ch->header.str_len > 0) {
                   2633:                efree(ch->header.str);
                   2634:        }
                   2635: 
                   2636:        if (ch->handlers->write_header->stream) {
                   2637:                zval_ptr_dtor(&ch->handlers->write_header->stream);
                   2638:        }
                   2639:        if (ch->handlers->write->stream) {
                   2640:                zval_ptr_dtor(&ch->handlers->write->stream);
                   2641:        }
                   2642:        if (ch->handlers->read->stream) {
                   2643:                zval_ptr_dtor(&ch->handlers->read->stream);
                   2644:        }
                   2645: 
                   2646:        efree(ch->handlers->write);
                   2647:        efree(ch->handlers->write_header);
                   2648:        efree(ch->handlers->read);
                   2649:        efree(ch->handlers->progress);
                   2650:        efree(ch->handlers);
                   2651:        efree(ch);
                   2652: }
                   2653: /* }}} */
                   2654: 
                   2655: /* {{{ _php_curl_close()
                   2656:    List destructor for curl handles */
                   2657: static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                   2658: {
                   2659:        php_curl *ch = (php_curl *) rsrc->ptr;
                   2660:        _php_curl_close_ex(ch TSRMLS_CC);
                   2661: }
                   2662: /* }}} */
                   2663: 
                   2664: #endif /* HAVE_CURL */
                   2665: 
                   2666: /*
                   2667:  * Local variables:
                   2668:  * tab-width: 4
                   2669:  * c-basic-offset: 4
                   2670:  * End:
                   2671:  * vim600: fdm=marker
                   2672:  * vim: noet sw=4 ts=4
                   2673:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>