diff --git a/lib/http.c b/lib/http.c index aea19d5167..6b1538a737 100644 --- a/lib/http.c +++ b/lib/http.c @@ -519,6 +519,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, /* We decided to abort the ongoing transfer */ streamclose(conn, "Mid-auth HTTP and much data left to send"); data->req.size = 0; /* do not download any more than 0 bytes */ + data->req.http_bodyless = TRUE; } return CURLE_OK; } @@ -3118,32 +3119,50 @@ static CURLcode http_header_c(struct Curl_easy *data, struct SingleRequest *k = &data->req; const char *v; - /* Check for Content-Length: header lines to get size */ + /* Check for Content-Length: header lines to get size. Browsers insist we + should accept multiple Content-Length headers and that a comma separated + list also is fine and then we should accept them all as long as they are + the same value. Different values trigger error. + */ v = (!k->http_bodyless && !data->set.ignorecl) ? HD_VAL(hd, hdlen, "Content-Length:") : NULL; if(v) { - curl_off_t contentlength; - int offt = curlx_str_numblanks(&v, &contentlength); + do { + curl_off_t contentlength; + int offt = curlx_str_numblanks(&v, &contentlength); - if(offt == STRE_OK) { - k->size = contentlength; - k->maxdownload = k->size; - } - else if(offt == STRE_OVERFLOW) { - /* out of range */ - if(data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; + if(offt == STRE_OVERFLOW) { + /* out of range */ + if(data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + streamclose(conn, "overflow content-length"); + infof(data, "Overflow Content-Length: value"); + return CURLE_OK; } - streamclose(conn, "overflow content-length"); - infof(data, "Overflow Content-Length: value"); - } - else { - /* negative or just rubbish - bad HTTP */ - failf(data, "Invalid Content-Length: value"); - return CURLE_WEIRD_SERVER_REPLY; - } - return CURLE_OK; + else { + if((offt == STRE_OK) && + ((k->size == -1) || /* not set to something before */ + (k->size == contentlength))) { /* or the same value */ + + k->size = contentlength; + curlx_str_passblanks(&v); + + /* on a comma, loop and get the next instead */ + if(!curlx_str_single(&v, ',')) + continue; + + if(!curlx_str_newline(&v)) { + k->maxdownload = k->size; + return CURLE_OK; + } + } + /* negative, different value or just rubbish - bad HTTP */ + failf(data, "Invalid Content-Length: value"); + return CURLE_WEIRD_SERVER_REPLY; + } + } while(1); } v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ? HD_VAL(hd, hdlen, "Content-Encoding:") : NULL; diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 0d2d47c99a..11d9fb7cff 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -109,7 +109,7 @@ test727 test728 test729 test730 test731 test732 test733 test734 test735 \ test736 test737 test738 test739 test740 test741 test742 test743 test744 \ test745 test746 test747 test748 test749 test750 test751 test752 test753 \ test754 test755 test756 test757 test758 test759 test760 test761 test762 \ -test763 test764 test765 test766 \ +test763 test764 test765 test766 test767 test768 test769 test770 test771 \ \ test780 test781 test782 test783 test784 test785 test786 test787 test788 \ test789 test790 test791 test792 test793 test794 test796 test797 \ diff --git a/tests/data/test767 b/tests/data/test767 new file mode 100644 index 0000000000..0927be4f1b --- /dev/null +++ b/tests/data/test767 @@ -0,0 +1,58 @@ + + + +HTTP +HTTP GET + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with two Content-Length response header fields same size + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +Allocations: 135 +Maximum allocated: 136000 + + + diff --git a/tests/data/test768 b/tests/data/test768 new file mode 100644 index 0000000000..ced4353c30 --- /dev/null +++ b/tests/data/test768 @@ -0,0 +1,57 @@ + + + +HTTP +HTTP GET + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6badness +Content-Length: 44 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with letters after the number in Content-Length + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +8 + + + diff --git a/tests/data/test769 b/tests/data/test769 new file mode 100644 index 0000000000..773d741e3f --- /dev/null +++ b/tests/data/test769 @@ -0,0 +1,53 @@ + + + +HTTP +HTTP GET + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with space after Content-Length number + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + + diff --git a/tests/data/test770 b/tests/data/test770 new file mode 100644 index 0000000000..98e3850c4c --- /dev/null +++ b/tests/data/test770 @@ -0,0 +1,58 @@ + + + +HTTP +HTTP GET + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6,06,6 +Content-Length: 6, 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with Content-Length headers using comma separated list + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +Allocations: 135 +Maximum allocated: 136000 + + + diff --git a/tests/data/test771 b/tests/data/test771 new file mode 100644 index 0000000000..b57c87c88b --- /dev/null +++ b/tests/data/test771 @@ -0,0 +1,57 @@ + + + +HTTP +HTTP GET + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 44 +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with two Content-Length headers using different sizes + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +8 + + +