diff options
author | Alexander Moskalev <irker@irker.net> | 2020-11-26 10:30:02 +0300 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-02-16 10:24:22 +0100 |
commit | e727919b97c4baeca93cb7700d4adf2e35a3530f (patch) | |
tree | 81ef04e6048481ad94c22a4316c7346d2484380e /ext/curl/interface.c | |
parent | d16341dabe30f03149d78a03dad734b9d32907b2 (diff) | |
download | php-git-e727919b97c4baeca93cb7700d4adf2e35a3530f.tar.gz |
cURL: make possible to send file from buffer string
Add CURLStringFile class which works similarly to CURLFile, but
uploads a file from a string rather than a file. This avoids the
need to create a temporary file, or use of a data:// stream.
Basic usage:
$file = new CURLStringFile($data, 'filename.txt', 'text/plain');
curl_setopt($curl, CURLOPT_POSTFIELDS, ['file' => $file]);
Closes GH-6456.
Diffstat (limited to 'ext/curl/interface.c')
-rw-r--r-- | ext/curl/interface.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/ext/curl/interface.c b/ext/curl/interface.c index d96334cd07..0827bdfd8b 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1654,6 +1654,15 @@ static void curl_free_cb_arg(void **cb_arg_p) } /* }}} */ +#if LIBCURL_VERSION_NUM < 0x073800 /* 7.56.0 */ +/* {{{ curl_free_buffers */ +static void curl_free_buffers(void **buffer) +{ + zend_string_release((zend_string *) *buffer); +} +/* }}} */ +#endif + /* {{{ curl_free_slist */ static void curl_free_slist(zval *el) { @@ -1744,6 +1753,10 @@ void init_curl_handle(php_curl *ch) zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0); zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t)curl_free_cb_arg, 0); +#if LIBCURL_VERSION_NUM < 0x073800 /* 7.56.0 */ + zend_llist_init(&ch->to_free->buffers, sizeof(zend_string *), (llist_dtor_func_t)curl_free_buffers, 0); +#endif + ch->to_free->slist = emalloc(sizeof(HashTable)); zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); ZVAL_UNDEF(&ch->postfields); @@ -2086,6 +2099,78 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields continue; } + if (Z_TYPE_P(current) == IS_OBJECT && instanceof_function(Z_OBJCE_P(current), curl_CURLStringFile_class)) { + /* new-style file upload from string */ + zval *prop, rv; + char *type = NULL, *filename = NULL; + + prop = zend_read_property(curl_CURLStringFile_class, Z_OBJ_P(current), "postname", sizeof("postname")-1, 0, &rv); + if (EG(exception)) { + zend_string_release_ex(string_key, 0); + return FAILURE; + } + ZVAL_DEREF(prop); + ZEND_ASSERT(Z_TYPE_P(prop) == IS_STRING); + + filename = Z_STRVAL_P(prop); + + prop = zend_read_property(curl_CURLStringFile_class, Z_OBJ_P(current), "mime", sizeof("mime")-1, 0, &rv); + if (EG(exception)) { + zend_string_release_ex(string_key, 0); + return FAILURE; + } + ZVAL_DEREF(prop); + ZEND_ASSERT(Z_TYPE_P(prop) == IS_STRING); + + type = Z_STRVAL_P(prop); + + prop = zend_read_property(curl_CURLStringFile_class, Z_OBJ_P(current), "data", sizeof("data")-1, 0, &rv); + if (EG(exception)) { + zend_string_release_ex(string_key, 0); + return FAILURE; + } + ZVAL_DEREF(prop); + ZEND_ASSERT(Z_TYPE_P(prop) == IS_STRING); + + postval = Z_STR_P(prop); + +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ + zval_ptr_dtor(&ch->postfields); + ZVAL_COPY(&ch->postfields, zpostfields); + + part = curl_mime_addpart(mime); + if (part == NULL) { + zend_string_release_ex(string_key, 0); + return FAILURE; + } + if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK + || (form_error = curl_mime_data(part, ZSTR_VAL(postval), ZSTR_LEN(postval))) != CURLE_OK + || (form_error = curl_mime_filename(part, filename)) != CURLE_OK + || (form_error = curl_mime_type(part, type)) != CURLE_OK) { + error = form_error; + } +#else + postval = zend_string_copy(postval); + zend_llist_add_element(&ch->to_free->buffers, &postval); + + form_error = curl_formadd(&first, &last, + CURLFORM_COPYNAME, ZSTR_VAL(string_key), + CURLFORM_NAMELENGTH, ZSTR_LEN(string_key), + CURLFORM_BUFFER, filename, + CURLFORM_CONTENTTYPE, type, + CURLFORM_BUFFERPTR, ZSTR_VAL(postval), + CURLFORM_BUFFERLENGTH, ZSTR_LEN(postval), + CURLFORM_END); + if (form_error != CURL_FORMADD_OK) { + /* Not nice to convert between enums but we only have place for one error type */ + error = (CURLcode)form_error; + } +#endif + + zend_string_release_ex(string_key, 0); + continue; + } + postval = zval_get_tmp_string(current, &tmp_postval); #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ @@ -3330,6 +3415,11 @@ static void curl_free_obj(zend_object *object) if (--(*ch->clone) == 0) { zend_llist_clean(&ch->to_free->post); zend_llist_clean(&ch->to_free->stream); + +#if LIBCURL_VERSION_NUM < 0x073800 /* 7.56.0 */ + zend_llist_clean(&ch->to_free->buffers); +#endif + zend_hash_destroy(ch->to_free->slist); efree(ch->to_free->slist); efree(ch->to_free); |