Skip to content

Commit fc8b3ab

Browse files
committed
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()`.
1 parent a037702 commit fc8b3ab

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ PHP NEWS
2222

2323
- CURL:
2424
. Fixed bug #79019 (Copied cURL handles upload empty file). (cmb)
25+
. Fixed bug #79013 (Content-Length missing when posting a curlFile with
26+
curl). (cmb)
2527

2628
- DOM:
2729
. Fixed bug #77569: (Write Access Violation in DomImplementation). (Nikita,

ext/curl/interface.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,10 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
22002200
char *type = NULL, *filename = NULL;
22012201
#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
22022202
struct mime_data_cb_arg *cb_arg;
2203+
php_stream *stream;
2204+
php_stream_statbuf ssb;
2205+
size_t filesize = -1;
2206+
curl_seek_callback seekfunc = seek_cb;
22032207
#endif
22042208

22052209
prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv);
@@ -2225,17 +2229,25 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
22252229
zval_ptr_dtor(&ch->postfields);
22262230
ZVAL_COPY(&ch->postfields, zpostfields);
22272231

2232+
if ((stream = php_stream_open_wrapper(ZSTR_VAL(postval), "rb", STREAM_MUST_SEEK, NULL))) {
2233+
if (!stream->readfilters.head && !php_stream_stat(stream, &ssb)) {
2234+
filesize = ssb.sb.st_size;
2235+
}
2236+
} else {
2237+
seekfunc = NULL;
2238+
}
2239+
22282240
cb_arg = emalloc(sizeof *cb_arg);
22292241
cb_arg->filename = zend_string_copy(postval);
2230-
cb_arg->stream = NULL;
2242+
cb_arg->stream = stream;
22312243

22322244
part = curl_mime_addpart(mime);
22332245
if (part == NULL) {
22342246
zend_string_release_ex(string_key, 0);
22352247
return FAILURE;
22362248
}
22372249
if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK
2238-
|| (form_error = curl_mime_data_cb(part, -1, read_cb, seek_cb, free_cb, cb_arg)) != CURLE_OK
2250+
|| (form_error = curl_mime_data_cb(part, filesize, read_cb, seekfunc, free_cb, cb_arg)) != CURLE_OK
22392251
|| (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK
22402252
|| (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) {
22412253
error = form_error;

0 commit comments

Comments
 (0)