From a1fd524f8f7862047fa96a47c016fc19edc0d231 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 28 Feb 2020 11:08:15 +0100 Subject: [PATCH] Fix #79013: Content-Length missing when posting a curlFile with curl Unfortunately, some Webservers (e.g. IIS) do not implement the (F)CGI specifications correctly wrt. chunked uploads (i.e. Transfer-encoding: chunked), but instead pass `-1` as CONTENT_LENGTH to the CGI application. However, our (F)CFI SAPIs (i.e. cgi and cgi-fcgi) do not support this. Therefore we do no longer do chunked uploads unless ext/curl has been compiled with `CURL_FILE_AS_STREAM` for best interoperability. We only make minimal modifications to the code for simplicity, and also because we consider this commit a mere work-around for broken (F)CGI servers/ applications which have to deal with HTTP/1.1 requests (HTTP/2 and later do no longer support Transfer-encoding: chunked, anyway). Users who are sure that they upload CURLFiles to servers which support chunked uploads are encouraged to build with `CURL_FILE_AS_STREAM`; we introduce the PHP constant `CURL_FILE_AS_STREAM` to be able to retrieve this information during run-time. --- ext/curl/interface.c | 12 +++++++++++- ext/curl/tests/bug77711.phpt | 5 ++++- ext/curl/tests/curl_copy_handle_variation3.phpt | 5 ++++- ext/curl/tests/curl_copy_handle_variation4.phpt | 5 ++++- ext/curl/tests/curl_file_upload_stream.phpt | 5 +++-- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 668f7a71d9353..fc252b875ed4b 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1404,6 +1404,12 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLOPT_SAFE_UPLOAD); +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ && defined(CURL_FILE_AS_STREAM) + REGISTER_BOOL_CONSTANT("CURL_FILE_AS_STREAM", 1, CONST_CS | CONST_PERSISTENT); +#else + REGISTER_BOOL_CONSTANT("CURL_FILE_AS_STREAM", 0, CONST_CS | CONST_PERSISTENT); +#endif + #ifdef PHP_CURL_NEED_OPENSSL_TSL if (!CRYPTO_get_id_callback()) { int i, c = CRYPTO_num_locks(); @@ -2105,7 +2111,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) (*source->clone)++; } -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ && defined(CURL_FILE_AS_STREAM) static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */ { struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg; @@ -2235,7 +2241,11 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields return FAILURE; } if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK +#ifdef CURL_FILE_AS_STREAM || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, free_cb, cb_arg)) != CURLE_OK +#else + || (form_error = curl_mime_filedata(part, ZSTR_VAL(postval))) != CURLE_OK +#endif || (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK || (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) { error = form_error; diff --git a/ext/curl/tests/bug77711.phpt b/ext/curl/tests/bug77711.phpt index 8ef5e48891943..02e922cdbe469 100644 --- a/ext/curl/tests/bug77711.phpt +++ b/ext/curl/tests/bug77711.phpt @@ -1,7 +1,10 @@ --TEST-- FR #77711 (CURLFile should support UNICODE filenames) --SKIPIF-- - + --FILE-- + --FILE-- + --FILE-- = 7.56.0'); +include 'skipif.inc'; +if (!CURL_FILE_AS_STREAM) die('skip CURLFile does not support streams'); +?> --FILE--