summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/http.c')
-rw-r--r--Utilities/cmcurl/lib/http.c175
1 files changed, 99 insertions, 76 deletions
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index cb585e7..faa486c 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -88,6 +88,7 @@
#include "hsts.h"
#include "ws.h"
#include "c-hyper.h"
+#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -233,15 +234,12 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
Curl_mime_initpart(&http->form);
data->req.p.http = http;
+ connkeep(conn, "HTTP default");
- if((data->state.httpwant == CURL_HTTP_VERSION_3)
- || (data->state.httpwant == CURL_HTTP_VERSION_3ONLY)) {
+ if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
CURLcode result = Curl_conn_may_http3(data, conn);
if(result)
return result;
-
- /* TODO: HTTP lower version eyeballing */
- conn->transport = TRNSPRT_QUIC;
}
return CURLE_OK;
@@ -2342,7 +2340,16 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
- if(http->postsize) {
+ /* For really small puts we don't use Expect: headers at all, and for
+ the somewhat bigger ones we allow the app to disable it. Just make
+ sure that the expect100header is always set to the preferred value
+ here. */
+ ptr = Curl_checkheaders(data, STRCONST("Expect"));
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
+ }
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
result = expect100(data, conn, r);
if(result)
return result;
@@ -4155,11 +4162,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(!k->headerline++) {
/* This is the first header, it MUST be the error code line
or else we consider this to be the body right away! */
- int httpversion_major;
- int rtspversion_major;
- int nc = 0;
-#define HEADER1 headp /* no conversion needed, just use headp */
-
+ bool fine_statusline = FALSE;
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
/*
* https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
@@ -4168,39 +4171,60 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* says. We allow any three-digit number here, but we cannot make
* guarantees on future behaviors since it isn't within the protocol.
*/
- char separator;
- char twoorthree[2];
int httpversion = 0;
- char digit4 = 0;
- nc = sscanf(HEADER1,
- " HTTP/%1d.%1d%c%3d%c",
- &httpversion_major,
- &httpversion,
- &separator,
- &k->httpcode,
- &digit4);
-
- if(nc == 1 && httpversion_major >= 2 &&
- 2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
- conn->httpversion = 0;
- nc = 4;
- separator = ' ';
- }
-
- /* There can only be a 4th response code digit stored in 'digit4' if
- all the other fields were parsed and stored first, so nc is 5 when
- digit4 a digit.
-
- The sscanf() line above will also allow zero-prefixed and negative
- numbers, so we check for that too here.
- */
- else if(ISDIGIT(digit4) || (nc >= 4 && k->httpcode < 100)) {
- failf(data, "Unsupported response code in HTTP response");
- return CURLE_UNSUPPORTED_PROTOCOL;
+ char *p = headp;
+
+ while(*p && ISBLANK(*p))
+ p++;
+ if(!strncmp(p, "HTTP/", 5)) {
+ p += 5;
+ switch(*p) {
+ case '1':
+ p++;
+ if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
+ if(ISBLANK(p[2])) {
+ httpversion = 10 + (p[1] - '0');
+ p += 3;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(ISSPACE(*p))
+ fine_statusline = TRUE;
+ }
+ }
+ }
+ if(!fine_statusline) {
+ failf(data, "Unsupported HTTP/1 subversion in response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ break;
+ case '2':
+ case '3':
+ if(!ISBLANK(p[1]))
+ break;
+ httpversion = (*p - '0') * 10;
+ p += 2;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(!ISSPACE(*p))
+ break;
+ fine_statusline = TRUE;
+ }
+ break;
+ default: /* unsupported */
+ failf(data, "Unsupported HTTP version in response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
}
- if((nc >= 4) && (' ' == separator)) {
- httpversion += 10 * httpversion_major;
+ if(fine_statusline) {
+ if(k->httpcode < 100) {
+ failf(data, "Unsupported response code in HTTP response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
switch(httpversion) {
case 10:
case 11:
@@ -4227,51 +4251,50 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
}
}
- else if(!nc) {
- /* this is the real world, not a Nirvana
- NCSA 1.5.x returns this crap when asked for HTTP/1.1
- */
- nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
- conn->httpversion = 10;
-
+ else {
/* If user has set option HTTP200ALIASES,
compare header line against list of aliases
*/
- if(!nc) {
- statusline check =
- checkhttpprefix(data,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
- if(check == STATUS_DONE) {
- nc = 1;
- k->httpcode = 200;
- conn->httpversion = 10;
- }
+ statusline check =
+ checkhttpprefix(data,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ if(check == STATUS_DONE) {
+ fine_statusline = TRUE;
+ k->httpcode = 200;
+ conn->httpversion = 10;
}
}
- else {
- failf(data, "Unsupported HTTP version in response");
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
}
else if(conn->handler->protocol & CURLPROTO_RTSP) {
- char separator;
- int rtspversion;
- nc = sscanf(HEADER1,
- " RTSP/%1d.%1d%c%3d",
- &rtspversion_major,
- &rtspversion,
- &separator,
- &k->httpcode);
- if((nc == 4) && (' ' == separator)) {
- conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
- }
- else {
- nc = 0;
+ char *p = headp;
+ while(*p && ISBLANK(*p))
+ p++;
+ if(!strncmp(p, "RTSP/", 5)) {
+ p += 5;
+ if(ISDIGIT(*p)) {
+ p++;
+ if((p[0] == '.') && ISDIGIT(p[1])) {
+ if(ISBLANK(p[2])) {
+ p += 3;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(ISSPACE(*p)) {
+ fine_statusline = TRUE;
+ conn->httpversion = 11; /* RTSP acts like HTTP 1.1 */
+ }
+ }
+ }
+ }
+ }
+ if(!fine_statusline)
+ return CURLE_WEIRD_SERVER_REPLY;
}
}
- if(nc) {
+ if(fine_statusline) {
result = Curl_http_statusline(data, conn);
if(result)
return result;