summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-03-02 18:45:12 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-03-02 19:11:33 +0100
commitfc8b3ab7cbb4f5e77584babeaf25b9bf16f524cd (patch)
tree95c01fc4473ead1707bc27b17cc33c9f71ace6ff
parenta0377021c5640cd6e6ad719a76dd38f91f7c367b (diff)
downloadphp-git-fc8b3ab7cbb4f5e77584babeaf25b9bf16f524cd.tar.gz
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 try to retrieve the stream size in advance and pass it to `curl_mime_data_cb()` to prevent libcurl from doing chunked uploads. This is basically the same approach that `curl_mime_filedata()` implements, except that we are keeping already opened streams open for the `read_cb()`.
-rw-r--r--NEWS2
-rw-r--r--ext/curl/interface.c16
2 files changed, 16 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 16802c2ea8..7902b67522 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,8 @@ PHP NEWS
- CURL:
. Fixed bug #79019 (Copied cURL handles upload empty file). (cmb)
+ . Fixed bug #79013 (Content-Length missing when posting a curlFile with
+ curl). (cmb)
- DOM:
. Fixed bug #77569: (Write Access Violation in DomImplementation). (Nikita,
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 668f7a71d9..45e41ba49e 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -2200,6 +2200,10 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
char *type = NULL, *filename = NULL;
#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
struct mime_data_cb_arg *cb_arg;
+ php_stream *stream;
+ php_stream_statbuf ssb;
+ size_t filesize = -1;
+ curl_seek_callback seekfunc = seek_cb;
#endif
prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv);
@@ -2225,9 +2229,17 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
zval_ptr_dtor(&ch->postfields);
ZVAL_COPY(&ch->postfields, zpostfields);
+ if ((stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", STREAM_MUST_SEEK, NULL))) {
+ if (!stream->readfilters.head && !php_stream_stat(stream, &ssb)) {
+ filesize = ssb.sb.st_size;
+ }
+ } else {
+ seekfunc = NULL;
+ }
+
cb_arg = emalloc(sizeof *cb_arg);
cb_arg->filename = zend_string_copy(postval);
- cb_arg->stream = NULL;
+ cb_arg->stream = stream;
part = curl_mime_addpart(mime);
if (part == NULL) {
@@ -2235,7 +2247,7 @@ 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
- || (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, free_cb, cb_arg)) != CURLE_OK
+ || (form_error = curl_mime_data_cb(part, filesize, read_cb, seekfunc, free_cb, cb_arg)) != CURLE_OK
|| (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;