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

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

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