--- embedaddon/php/ext/curl/interface.c 2012/02/21 23:47:53 1.1.1.1 +++ embedaddon/php/ext/curl/interface.c 2013/07/22 01:31:38 1.1.1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2012 The PHP Group | + | Copyright (c) 1997-2013 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -10,13 +10,13 @@ | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | + | license@php.net so we can mail you 6 copy immediately. | +----------------------------------------------------------------------+ | Author: Sterling Hughes | +----------------------------------------------------------------------+ */ -/* $Id: interface.c,v 1.1.1.1 2012/02/21 23:47:53 misho Exp $ */ +/* $Id: interface.c,v 1.1.1.3 2013/07/22 01:31:38 misho Exp $ */ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS @@ -164,16 +164,14 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc # define php_curl_ret(__ret) RETVAL_FALSE; return; #endif -static int php_curl_option_url(php_curl *ch, const char *url, const int len) /* {{{ */ +static int php_curl_option_url(php_curl *ch, const char *url, const int len TSRMLS_DC) /* {{{ */ { CURLcode error = CURLE_OK; #if LIBCURL_VERSION_NUM < 0x071100 char *copystr = NULL; #endif - TSRMLS_FETCH(); - - /* Disable file:// if open_basedir or safe_mode are used */ - if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) { + /* Disable file:// if open_basedir are used */ + if (PG(open_basedir) && *PG(open_basedir)) { #if LIBCURL_VERSION_NUM >= 0x071304 error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE); #else @@ -715,6 +713,14 @@ PHP_MINIT_FUNCTION(curl) #if LIBCURL_VERSION_NUM >= 0x071202 REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL); #endif +#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */ + REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP); +#endif +#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */ + REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT); + REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP); + REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT); +#endif /* cURL protocol constants (curl_version) */ @@ -971,6 +977,15 @@ PHP_MSHUTDOWN_FUNCTION(curl) } /* }}} */ +/* {{{ curl_write_nothing + * Used as a work around. See _php_curl_close_ex + */ +static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) +{ + return size * nmemb; +} +/* }}} */ + /* {{{ curl_write */ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) @@ -1547,8 +1562,6 @@ PHP_FUNCTION(curl_init) MAKE_STD_ZVAL(clone); ch->clone = clone; - - curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); @@ -1572,7 +1585,7 @@ PHP_FUNCTION(curl_init) #endif if (url) { - if (!php_curl_option_url(ch, url, url_len)) { + if (!php_curl_option_url(ch, url, url_len TSRMLS_CC)) { _php_curl_close_ex(ch TSRMLS_CC); RETURN_FALSE; } @@ -1610,9 +1623,9 @@ PHP_FUNCTION(curl_copy_handle) dupch->uses = 0; ch->uses++; if (ch->handlers->write->stream) { - Z_ADDREF_P(dupch->handlers->write->stream); - dupch->handlers->write->stream = ch->handlers->write->stream; + Z_ADDREF_P(ch->handlers->write->stream); } + dupch->handlers->write->stream = ch->handlers->write->stream; dupch->handlers->write->method = ch->handlers->write->method; dupch->handlers->write->type = ch->handlers->write->type; if (ch->handlers->read->stream) { @@ -1679,6 +1692,17 @@ static int _php_curl_setopt(php_curl *ch, long option, CURLcode error=CURLE_OK; switch (option) { + /* Long options */ + case CURLOPT_SSL_VERIFYHOST: + if(Z_BVAL_PP(zvalue) == 1) { +#if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */ + 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"); +#else + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); + error = curl_easy_setopt(ch->cp, option, 2); + break; +#endif + } case CURLOPT_INFILESIZE: case CURLOPT_VERBOSE: case CURLOPT_HEADER: @@ -1717,7 +1741,6 @@ static int _php_curl_setopt(php_curl *ch, long option, #if LIBCURL_VERSION_NUM > 0x071002 case CURLOPT_CONNECTTIMEOUT_MS: #endif - case CURLOPT_SSL_VERIFYHOST: case CURLOPT_SSL_VERIFYPEER: case CURLOPT_DNS_USE_GLOBAL_CACHE: case CURLOPT_NOSIGNAL: @@ -1767,8 +1790,8 @@ static int _php_curl_setopt(php_curl *ch, long option, convert_to_long_ex(zvalue); #if LIBCURL_VERSION_NUM >= 0x71304 if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && - ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when in safe_mode or an open_basedir is set"); + (PG(open_basedir) && *PG(open_basedir)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); RETVAL_FALSE; return 1; } @@ -1784,9 +1807,9 @@ static int _php_curl_setopt(php_curl *ch, long option, #endif case CURLOPT_FOLLOWLOCATION: convert_to_long_ex(zvalue); - if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) { + if (PG(open_basedir) && *PG(open_basedir)) { if (Z_LVAL_PP(zvalue) != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set"); RETVAL_FALSE; return 1; } @@ -1828,24 +1851,20 @@ static int _php_curl_setopt(php_curl *ch, long option, case CURLOPT_SSH_PRIVATE_KEYFILE: #endif { -#if LIBCURL_VERSION_NUM < 0x071100 - char *copystr = NULL; -#endif - convert_to_string_ex(zvalue); #if LIBCURL_VERSION_NUM >= 0x071300 if ( option == CURLOPT_SSH_PUBLIC_KEYFILE || option == CURLOPT_SSH_PRIVATE_KEYFILE ) { - if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) { + if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) { RETVAL_FALSE; return 1; } } #endif if (option == CURLOPT_URL) { - if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue))) { + if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue) TSRMLS_CC)) { RETVAL_FALSE; return 1; } @@ -2027,10 +2046,6 @@ string_copy: HashTable *postfields; struct HttpPost *first = NULL; struct HttpPost *last = NULL; - char *postval; - char *string_key = NULL; - ulong num_key; - uint string_key_len; postfields = HASH_OF(*zvalue); if (!postfields) { @@ -2043,12 +2058,26 @@ string_copy: zend_hash_get_current_data(postfields, (void **) ¤t) == SUCCESS; zend_hash_move_forward(postfields) ) { + char *postval; + char *string_key = NULL; + uint string_key_len; + ulong num_key; + int numeric_key; SEPARATE_ZVAL(current); convert_to_string_ex(current); zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL); + /* Pretend we have a string_key here */ + if(!string_key) { + spprintf(&string_key, 0, "%ld", num_key); + string_key_len = strlen(string_key)+1; + numeric_key = 1; + } else { + numeric_key = 0; + } + postval = Z_STRVAL_PP(current); /* The arguments after _NAMELENGTH and _CONTENTSLENGTH @@ -2064,8 +2093,8 @@ string_copy: if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) { *filename = '\0'; } - /* safe_mode / open_basedir check */ - if (php_check_open_basedir(postval TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(postval, "rb+", CHECKUID_CHECK_MODE_PARAM))) { + /* open_basedir check */ + if (php_check_open_basedir(postval TSRMLS_CC)) { RETVAL_FALSE; return 1; } @@ -2090,6 +2119,10 @@ string_copy: CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current), CURLFORM_END); } + + if (numeric_key) { + efree(string_key); + } } SAVE_CURL_ERROR(ch, error); @@ -2098,6 +2131,9 @@ string_copy: return 1; } + if (Z_REFCOUNT_P(ch->clone) <= 1) { + zend_llist_clean(&ch->to_free->post); + } zend_llist_add_element(&ch->to_free->post, &first); error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first); @@ -2154,8 +2190,8 @@ string_copy: break; } - /* the following options deal with files, therefor safe_mode & open_basedir checks - * are required. + /* the following options deal with files, therefore the open_basedir check + * is required. */ case CURLOPT_COOKIEJAR: case CURLOPT_SSLCERT: @@ -2167,7 +2203,7 @@ string_copy: convert_to_string_ex(zvalue); - if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) { + if (Z_STRLEN_PP(zvalue) && php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) { RETVAL_FALSE; return 1; } @@ -2438,6 +2474,22 @@ PHP_FUNCTION(curl_getinfo) CAAZ("certinfo", listcode); } #endif +#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */ + if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) { + CAAS("primary_ip", s_code); + } +#endif +#if LIBCURL_VERSION_NUM > 0x071500 + if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) { + CAAL("primary_port", l_code); + } + if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) { + CAAS("local_ip", s_code); + } + if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) { + CAAL("local_port", l_code); + } +#endif #if LIBCURL_VERSION_NUM >= 0x071202 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) { CAAS("redirect_url", s_code); @@ -2448,6 +2500,13 @@ PHP_FUNCTION(curl_getinfo) } } else { switch (option) { + /* string variable types */ +#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */ + case CURLINFO_PRIMARY_IP: +#endif +#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */ + case CURLINFO_LOCAL_IP: +#endif case CURLINFO_PRIVATE: case CURLINFO_EFFECTIVE_URL: case CURLINFO_CONTENT_TYPE: @@ -2464,6 +2523,11 @@ PHP_FUNCTION(curl_getinfo) } break; } + /* Long variable types */ +#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */ + case CURLINFO_PRIMARY_PORT: + case CURLINFO_LOCAL_PORT: +#endif case CURLINFO_HTTP_CODE: case CURLINFO_HEADER_SIZE: case CURLINFO_REQUEST_SIZE: @@ -2479,6 +2543,7 @@ PHP_FUNCTION(curl_getinfo) } break; } + /* Double variable types */ case CURLINFO_TOTAL_TIME: case CURLINFO_NAMELOOKUP_TIME: case CURLINFO_CONNECT_TIME: @@ -2595,6 +2660,21 @@ static void _php_curl_close_ex(php_curl *ch TSRMLS_DC) #endif _php_curl_verify_handlers(ch, 0 TSRMLS_CC); + + /* + * Libcurl is doing connection caching. When easy handle is cleaned up, + * if the handle was previously used by the curl_multi_api, the connection + * remains open un the curl multi handle is cleaned up. Some protocols are + * sending content like the FTP one, and libcurl try to use the + * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those + * callback are freed, we need to use an other callback to which avoid + * segfaults. + * + * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 + */ + curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); + curl_easy_cleanup(ch->cp); /* cURL destructors should be invoked only by last curl handle */