summaryrefslogtreecommitdiff
path: root/ext/curl/interface.c
diff options
context:
space:
mode:
authorAlexander Moskalev <irker@irker.net>2020-11-26 10:30:02 +0300
committerNikita Popov <nikita.ppv@gmail.com>2021-02-16 10:24:22 +0100
commite727919b97c4baeca93cb7700d4adf2e35a3530f (patch)
tree81ef04e6048481ad94c22a4316c7346d2484380e /ext/curl/interface.c
parentd16341dabe30f03149d78a03dad734b9d32907b2 (diff)
downloadphp-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.c90
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);