mirror of
https://github.com/curl/curl.git
synced 2026-07-23 14:57:19 +03:00
http: restore header folding behavior
Folded header lines will now get passed through like before. The headers API is adapted and will provide the content unfolded. Added test 1274 and extended test 1940 to verify. Reported-by: Petr Pisar Fixes #8844 Closes #8899
This commit is contained in:
parent
16a58e9f93
commit
c9b60f0053
8 changed files with 139 additions and 9 deletions
|
|
@ -216,6 +216,54 @@ static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode append_value(struct Curl_easy *data, const char *value,
|
||||
size_t vlen) /* length of the incoming header */
|
||||
{
|
||||
struct Curl_header_store *hs;
|
||||
struct Curl_header_store *newhs;
|
||||
size_t olen; /* length of the old value */
|
||||
size_t offset;
|
||||
DEBUGASSERT(data->state.prevhead);
|
||||
hs = data->state.prevhead;
|
||||
olen = strlen(hs->value);
|
||||
offset = hs->value - hs->buffer;
|
||||
|
||||
/* skip all trailing space letters */
|
||||
while(vlen && ISSPACE(value[vlen - 1]))
|
||||
vlen--;
|
||||
|
||||
/* save only one leading space */
|
||||
while((vlen > 1) && ISSPACE(value[0]) && ISSPACE(value[1])) {
|
||||
vlen--;
|
||||
value++;
|
||||
}
|
||||
|
||||
/* since this header block might move in the realloc below, it needs to
|
||||
first be unlinked from the list and then re-added again after the
|
||||
realloc */
|
||||
Curl_llist_remove(&data->state.httphdrs, &hs->node, NULL);
|
||||
|
||||
newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + olen + 1);
|
||||
if(!newhs)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
/* ->name' and ->value point into ->buffer (to keep the header allocation
|
||||
in a single memory block), which now potentially have moved. Adjust
|
||||
them. */
|
||||
newhs->name = newhs->buffer;
|
||||
newhs->value = &newhs->buffer[offset];
|
||||
|
||||
/* put the data at the end of the previous data, not the newline */
|
||||
memcpy(&newhs->value[olen], value, vlen);
|
||||
newhs->value[olen + vlen] = 0; /* zero terminate at newline */
|
||||
|
||||
/* insert this node into the list of headers */
|
||||
Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
|
||||
newhs, &newhs->node);
|
||||
data->state.prevhead = newhs;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_headers_push() gets passed a full HTTP header to store. It gets called
|
||||
* immediately before the header callback. The header is CRLF terminated.
|
||||
|
|
@ -242,6 +290,10 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
|
|||
}
|
||||
hlen = end - header + 1;
|
||||
|
||||
if((header[0] == ' ') || (header[0] == '\t'))
|
||||
/* line folding, append value to the previous header's value */
|
||||
return append_value(data, header, hlen);
|
||||
|
||||
hs = calloc(1, sizeof(*hs) + hlen);
|
||||
if(!hs)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
|
@ -260,7 +312,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
|
|||
/* insert this node into the list of headers */
|
||||
Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
|
||||
hs, &hs->node);
|
||||
|
||||
data->state.prevhead = hs;
|
||||
return CURLE_OK;
|
||||
fail:
|
||||
free(hs);
|
||||
|
|
|
|||
15
lib/http.c
15
lib/http.c
|
|
@ -3799,11 +3799,16 @@ static CURLcode verify_header(struct Curl_easy *data)
|
|||
if(k->headerline < 2)
|
||||
/* the first "header" is the status-line and it has no colon */
|
||||
return CURLE_OK;
|
||||
ptr = memchr(header, ':', hlen);
|
||||
if(!ptr) {
|
||||
/* this is bad, bail out */
|
||||
failf(data, "Header without colon");
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
if(((header[0] == ' ') || (header[0] == '\t')) && k->headerline > 2)
|
||||
/* line folding, can't happen on line 2 */
|
||||
;
|
||||
else {
|
||||
ptr = memchr(header, ':', hlen);
|
||||
if(!ptr) {
|
||||
/* this is bad, bail out */
|
||||
failf(data, "Header without colon");
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1423,6 +1423,7 @@ struct UrlState {
|
|||
headers */
|
||||
struct Curl_llist httphdrs; /* received headers */
|
||||
struct curl_header headerout; /* for external purposes */
|
||||
struct Curl_header_store *prevhead; /* the latest added header */
|
||||
#endif
|
||||
trailers_state trailers_state; /* whether we are sending trailers
|
||||
and what stage are we at */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue