forked from php/php-src
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bug #46439 - better handling of CURL file uploads
- Loading branch information
Showing
6 changed files
with
285 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* | ||
+----------------------------------------------------------------------+ | ||
| PHP Version 5 | | ||
+----------------------------------------------------------------------+ | ||
| 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 | | ||
| available through the world-wide-web at the following url: | | ||
| 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. | | ||
+----------------------------------------------------------------------+ | ||
| Author: Stanislav Malyshev <stas@php.net> | | ||
+----------------------------------------------------------------------+ | ||
*/ | ||
|
||
/* $Id$ */ | ||
|
||
#ifdef HAVE_CONFIG_H | ||
# include "config.h" | ||
#endif | ||
|
||
#include "php.h" | ||
#if HAVE_CURL | ||
|
||
PHPAPI zend_class_entry *curl_CURLFile_class; | ||
|
||
/* {{{ proto string CURLFile::__construct(string $name, [string $mimetype [, string $postfilename]]) | ||
Create the CURLFile object */ | ||
ZEND_METHOD(CURLFile, __construct) | ||
{ | ||
char *fname = NULL, *mime = NULL, *postname = NULL; | ||
int fname_len, mime_len, postname_len; | ||
zval *cf = getThis(); | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", &fname, &fname_len, &mime, &mime_len, &postname, &postname_len) == FAILURE) { | ||
return; | ||
} | ||
|
||
if (fname) { | ||
zend_update_property_string(curl_CURLFile_class, cf, "name", sizeof("name")-1, fname TSRMLS_CC); | ||
} | ||
|
||
if (mime) { | ||
zend_update_property_string(curl_CURLFile_class, cf, "mime", sizeof("mime")-1, mime TSRMLS_CC); | ||
} | ||
|
||
if (postname) { | ||
zend_update_property_string(curl_CURLFile_class, cf, "postname", sizeof("postname")-1, postname TSRMLS_CC); | ||
} | ||
} | ||
|
||
/* }}} */ | ||
|
||
static void curlfile_get_property(char *name, INTERNAL_FUNCTION_PARAMETERS) | ||
{ | ||
zval *res; | ||
if (zend_parse_parameters_none() == FAILURE) { | ||
return; | ||
} | ||
res = zend_read_property(curl_CURLFile_class, getThis(), name, strlen(name), 1 TSRMLS_CC); | ||
*return_value = *res; | ||
zval_copy_ctor(return_value); | ||
INIT_PZVAL(return_value); | ||
} | ||
|
||
static void curlfile_set_property(char *name, INTERNAL_FUNCTION_PARAMETERS) | ||
{ | ||
char *arg = NULL; | ||
int arg_len; | ||
|
||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { | ||
return; | ||
} | ||
zend_update_property_string(curl_CURLFile_class, getThis(), name, strlen(name), arg); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
} | ||
|
||
/* {{{ proto string CURLFile::getFilename() | ||
Get file name */ | ||
ZEND_METHOD(CURLFile, getFilename) | ||
{ | ||
curlfile_get_property("name", INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ proto string CURLFile::getMimeType() | ||
Get MIME type */ | ||
ZEND_METHOD(CURLFile, getMimeType) | ||
{ | ||
curlfile_get_property("mime", INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ proto string CURLFile::getPostFilename() | ||
Get file name for POST */ | ||
ZEND_METHOD(CURLFile, getPostFilename) | ||
{ | ||
curlfile_get_property("postname", INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ proto string CURLFile::setMimeType(string $mime) | ||
Set MIME type */ | ||
ZEND_METHOD(CURLFile, setMimeType) | ||
{ | ||
curlfile_set_property("mime", INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ proto string CURLFile::setPostFilename(string $name) | ||
Set file name for POST */ | ||
ZEND_METHOD(CURLFile, setPostFilename) | ||
{ | ||
curlfile_set_property("postname", INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
} | ||
/* }}} */ | ||
|
||
ZEND_BEGIN_ARG_INFO_EX(arginfo_curlfile_create, 0, 0, 1) | ||
ZEND_ARG_INFO(0, filename) | ||
ZEND_ARG_INFO(0, mimetype) | ||
ZEND_ARG_INFO(0, postname) | ||
ZEND_END_ARG_INFO() | ||
|
||
ZEND_BEGIN_ARG_INFO(arginfo_curlfile_name, 0) | ||
ZEND_ARG_INFO(0, name) | ||
ZEND_END_ARG_INFO() | ||
|
||
|
||
static const zend_function_entry curlfile_funcs[] = { | ||
PHP_ME(CURLFile, __construct, arginfo_curlfile_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) | ||
PHP_ME(CURLFile, getFilename, NULL, ZEND_ACC_PUBLIC) | ||
PHP_ME(CURLFile, getMimeType, NULL, ZEND_ACC_PUBLIC) | ||
PHP_ME(CURLFile, setMimeType, arginfo_curlfile_name, ZEND_ACC_PUBLIC) | ||
PHP_ME(CURLFile, getPostFilename, NULL, ZEND_ACC_PUBLIC) | ||
PHP_ME(CURLFile, setPostFilename, arginfo_curlfile_name, ZEND_ACC_PUBLIC) | ||
PHP_FE_END | ||
}; | ||
|
||
void curlfile_register_class(TSRMLS_D) | ||
{ | ||
zend_class_entry ce; | ||
INIT_CLASS_ENTRY( ce, "CURLFile", curlfile_funcs ); | ||
curl_CURLFile_class = zend_register_internal_class(&ce TSRMLS_CC); | ||
zend_declare_property_string(curl_CURLFile_class, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); | ||
zend_declare_property_string(curl_CURLFile_class, "mime", sizeof("mime")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); | ||
zend_declare_property_string(curl_CURLFile_class, "postname", sizeof("postname")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1229,6 +1229,8 @@ PHP_MINIT_FUNCTION(curl) | |
} | ||
#endif | ||
|
||
curlfile_register_class(TSRMLS_C); | ||
|
||
return SUCCESS; | ||
} | ||
/* }}} */ | ||
|
@@ -1275,7 +1277,7 @@ 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) | ||
static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) | ||
{ | ||
return size * nmemb; | ||
} | ||
|
@@ -1853,13 +1855,13 @@ static void split_certinfo(char *string, zval *hash) | |
static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC) | ||
{ | ||
int i; | ||
|
||
if(ci) { | ||
zval *certhash = NULL; | ||
|
||
for(i=0; i<ci->num_of_certs; i++) { | ||
struct curl_slist *slist; | ||
|
||
MAKE_STD_ZVAL(certhash); | ||
array_init(certhash); | ||
for(slist = ci->certinfo[i]; slist; slist = slist->next) { | ||
|
@@ -1876,14 +1878,14 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC) | |
|
||
MAKE_STD_ZVAL(hash); | ||
array_init(hash); | ||
|
||
split_certinfo(&slist->data[len+1], hash); | ||
add_assoc_zval(certhash, s, hash); | ||
} else { | ||
add_assoc_string(certhash, s, &slist->data[len+1], 1); | ||
} | ||
} else { | ||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info"); | ||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info"); | ||
} | ||
} | ||
add_next_index_zval(listcode, certhash); | ||
|
@@ -2342,8 +2344,8 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu | |
#if LIBCURL_VERSION_NUM >= 0x071100 | ||
/* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */ | ||
error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue)); | ||
#else | ||
goto string_copy; | ||
#else | ||
goto string_copy; | ||
#endif | ||
} | ||
} | ||
|
@@ -2563,9 +2565,6 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu | |
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 */ | ||
|
@@ -2577,6 +2576,48 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu | |
numeric_key = 0; | ||
} | ||
|
||
if(Z_TYPE_PP(current) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(current), curl_CURLFile_class TSRMLS_CC)) { | ||
/* new-style file upload */ | ||
zval *prop; | ||
char *type = NULL, *filename = NULL; | ||
|
||
prop = zend_read_property(curl_CURLFile_class, *current, "name", sizeof("name")-1, 0 TSRMLS_CC); | ||
if(Z_TYPE_P(prop) != IS_STRING) { | ||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid filename for key %s", string_key); | ||
} else { | ||
postval = Z_STRVAL_P(prop); | ||
|
||
if (php_check_open_basedir(postval TSRMLS_CC)) { | ||
RETVAL_FALSE; | ||
return 1; | ||
} | ||
|
||
prop = zend_read_property(curl_CURLFile_class, *current, "mime", sizeof("mime")-1, 0 TSRMLS_CC); | ||
if(Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { | ||
type = Z_STRVAL_P(prop); | ||
} | ||
prop = zend_read_property(curl_CURLFile_class, *current, "postname", sizeof("postname")-1, 0 TSRMLS_CC); | ||
if(Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { | ||
filename = Z_STRVAL_P(prop); | ||
} | ||
error = curl_formadd(&first, &last, | ||
CURLFORM_COPYNAME, string_key, | ||
CURLFORM_NAMELENGTH, (long)string_key_len - 1, | ||
CURLFORM_FILENAME, filename ? filename : postval, | ||
CURLFORM_CONTENTTYPE, type ? type : "application/octet-stream", | ||
CURLFORM_FILE, postval, | ||
CURLFORM_END); | ||
} | ||
|
||
if (numeric_key) { | ||
efree(string_key); | ||
} | ||
continue; | ||
} | ||
|
||
SEPARATE_ZVAL(current); | ||
convert_to_string_ex(current); | ||
|
||
postval = Z_STRVAL_PP(current); | ||
|
||
/* The arguments after _NAMELENGTH and _CONTENTSLENGTH | ||
|
@@ -2586,6 +2627,8 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu | |
char *type, *filename; | ||
++postval; | ||
|
||
php_error_docref("curl.curlfile" TSRMLS_CC, E_DEPRECATED, "Usage of @filename API for file uploading is deprecated. Please use CURLFile parameter instead"); | ||
This comment has been minimized.
Sorry, something went wrong.
mj
|
||
|
||
if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) { | ||
*type = '\0'; | ||
} | ||
|
@@ -3088,7 +3131,7 @@ PHP_FUNCTION(curl_getinfo) | |
struct curl_certinfo *ci = NULL; | ||
|
||
array_init(return_value); | ||
|
||
if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) { | ||
create_certinfo(ci, return_value TSRMLS_CC); | ||
} else { | ||
|
@@ -3228,16 +3271,16 @@ static void _php_curl_close_ex(php_curl *ch TSRMLS_DC) | |
|
||
_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 | ||
* 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 | ||
* 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 | ||
* 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); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
TSRMLS_CC missing here