1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

HTTP: allow "header;" to replace an internal header with a blank one

Reported-by: Michael Kaufmann
Fixes #2357
Closes #2362
This commit is contained in:
Daniel Stenberg 2018-03-05 23:38:16 +01:00
parent 019aa722aa
commit 8123560d44
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
9 changed files with 286 additions and 87 deletions

View File

@ -177,9 +177,9 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header * if proxy headers are not available, then it will lookup into http header
* link list * link list
* *
* It takes a connectdata struct as input instead of the Curl_easy simply * It takes a connectdata struct as input instead of the Curl_easy simply to
* to know if this is a proxy request or not, as it then might check a * know if this is a proxy request or not, as it then might check a different
* different header list. * header list. Provide the header prefix without colon!.
*/ */
char *Curl_checkProxyheaders(const struct connectdata *conn, char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader) const char *thisheader)
@ -191,7 +191,8 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ? for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers; data->set.proxyheaders : data->set.headers;
head; head = head->next) { head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen)) if(strncasecompare(head->data, thisheader, thislen) &&
Curl_headersep(head->data[thislen]))
return head->data; return head->data;
} }
@ -614,9 +615,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BASIC) { if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */ /* Basic */
if((proxy && conn->bits.proxy_user_passwd && if((proxy && conn->bits.proxy_user_passwd &&
!Curl_checkProxyheaders(conn, "Proxy-authorization:")) || !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
(!proxy && conn->bits.user_passwd && (!proxy && conn->bits.user_passwd &&
!Curl_checkheaders(conn, "Authorization:"))) { !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic"; auth = "Basic";
result = http_output_basic(conn, proxy); result = http_output_basic(conn, proxy);
if(result) if(result)
@ -1533,7 +1534,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */ operations (as there is one packet coming back from the web server) */
ptr = Curl_checkheaders(conn, "Expect:"); ptr = Curl_checkheaders(conn, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
@ -1598,7 +1599,32 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
headers = h[i]; headers = h[i];
while(headers) { while(headers) {
char *semicolonp = NULL;
ptr = strchr(headers->data, ':'); ptr = strchr(headers->data, ':');
if(!ptr) {
char *optr;
/* no colon, semicolon? */
ptr = strchr(headers->data, ';');
if(ptr) {
optr = ptr;
ptr++; /* pass the semicolon */
while(*ptr && ISSPACE(*ptr))
ptr++;
if(*ptr) {
/* this may be used for something else in the future */
optr = NULL;
}
else {
if(*(--ptr) == ';') {
/* send no-value custom header if terminated by semicolon */
*ptr = ':';
semicolonp = ptr;
}
}
ptr = optr;
}
}
if(ptr) { if(ptr) {
/* we require a colon for this to be a true header */ /* we require a colon for this to be a true header */
@ -1606,8 +1632,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
while(*ptr && ISSPACE(*ptr)) while(*ptr && ISSPACE(*ptr))
ptr++; ptr++;
if(*ptr) { if(*ptr || semicolonp) {
/* only send this if the contents was non-blank */ /* only send this if the contents was non-blank or done special */
CURLcode result = CURLE_OK;
if(conn->allocptr.host && if(conn->allocptr.host &&
/* a Host: header was sent already, don't pass on any custom Host: /* a Host: header was sent already, don't pass on any custom Host:
@ -1645,40 +1672,12 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name))) !strcasecompare(data->state.first_host, conn->host.name)))
; ;
else { else {
CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
headers->data);
if(result)
return result;
}
}
}
else {
ptr = strchr(headers->data, ';');
if(ptr) {
ptr++; /* pass the semicolon */
while(*ptr && ISSPACE(*ptr))
ptr++;
if(*ptr) {
/* this may be used for something else in the future */
}
else {
if(*(--ptr) == ';') {
CURLcode result;
/* send no-value custom header if terminated by semicolon */
*ptr = ':';
result = Curl_add_bufferf(req_buffer, "%s\r\n",
headers->data);
/* restore the previous value */
*ptr = ';';
if(result)
return result;
}
} }
if(semicolonp)
*semicolonp = ';'; /* put back the semicolon */
if(result)
return result;
} }
} }
headers = headers->next; headers = headers->next;
@ -1869,7 +1868,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string with the user-agent string specified, we erase the previously made string
here. */ here. */
if(Curl_checkheaders(conn, "User-Agent:")) { if(Curl_checkheaders(conn, "User-Agent")) {
free(conn->allocptr.uagent); free(conn->allocptr.uagent);
conn->allocptr.uagent = NULL; conn->allocptr.uagent = NULL;
} }
@ -1890,7 +1889,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->bits.authneg = FALSE; conn->bits.authneg = FALSE;
Curl_safefree(conn->allocptr.ref); Curl_safefree(conn->allocptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) { if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!conn->allocptr.ref) if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -1899,11 +1898,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref = NULL; conn->allocptr.ref = NULL;
#if !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_COOKIES)
if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:")) if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
addcookies = data->set.str[STRING_COOKIE]; addcookies = data->set.str[STRING_COOKIE];
#endif #endif
if(!Curl_checkheaders(conn, "Accept-Encoding:") && if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) { data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding); Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding = conn->allocptr.accept_encoding =
@ -1919,22 +1918,29 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */ /* we only consider transfer-encoding magic if libz support is built-in */
if(!Curl_checkheaders(conn, "TE:") && if(!Curl_checkheaders(conn, "TE") &&
data->set.http_transfer_encoding) { data->set.http_transfer_encoding) {
/* When we are to insert a TE: header in the request, we must also insert /* When we are to insert a TE: header in the request, we must also insert
TE in a Connection: header, so we need to merge the custom provided TE in a Connection: header, so we need to merge the custom provided
Connection: header and prevent the original to get sent. Note that if Connection: header and prevent the original to get sent. Note that if
the user has inserted his/hers own TE: header we don't do this magic the user has inserted his/hers own TE: header we don't do this magic
but then assume that the user will handle it all! */ but then assume that the user will handle it all! */
char *cptr = Curl_checkheaders(conn, "Connection:"); char *cptr = Curl_checkheaders(conn, "Connection");
#define TE_HEADER "TE: gzip\r\n" #define TE_HEADER "TE: gzip\r\n"
Curl_safefree(conn->allocptr.te); Curl_safefree(conn->allocptr.te);
/* Create the (updated) Connection: header */ if(cptr) {
conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr): cptr = Curl_copy_header_value(cptr);
strdup("Connection: TE\r\n" TE_HEADER); if(!cptr)
return CURLE_OUT_OF_MEMORY;
}
/* Create the (updated) Connection: header */
conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
free(cptr);
if(!conn->allocptr.te) if(!conn->allocptr.te)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -1958,7 +1964,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
if(http->sendit) { if(http->sendit) {
const char *cthdr = Curl_checkheaders(conn, "Content-Type:"); const char *cthdr = Curl_checkheaders(conn, "Content-Type");
/* Read and seek body only. */ /* Read and seek body only. */
http->sendit->flags |= MIME_BODY_ONLY; http->sendit->flags |= MIME_BODY_ONLY;
@ -1982,7 +1988,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->postsize = Curl_mime_size(http->sendit); http->postsize = Curl_mime_size(http->sendit);
} }
ptr = Curl_checkheaders(conn, "Transfer-Encoding:"); ptr = Curl_checkheaders(conn, "Transfer-Encoding");
if(ptr) { if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */ /* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky = data->req.upload_chunky =
@ -2016,7 +2022,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_safefree(conn->allocptr.host); Curl_safefree(conn->allocptr.host);
ptr = Curl_checkheaders(conn, "Host:"); ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow || if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) { strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_COOKIES)
@ -2055,7 +2061,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#endif #endif
if(strcmp("Host:", ptr)) { if(strcmp("Host:", ptr)) {
conn->allocptr.host = aprintf("%s\r\n", ptr); conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
if(!conn->allocptr.host) if(!conn->allocptr.host)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -2164,7 +2170,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
} }
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */
http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n"; http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
data->state.resume_from) { data->state.resume_from) {
@ -2245,14 +2251,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* ones if any such are specified. * ones if any such are specified.
*/ */
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
!Curl_checkheaders(conn, "Range:")) { !Curl_checkheaders(conn, "Range")) {
/* if a line like this was already allocated, free the previous one */ /* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline); free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range); data->state.range);
} }
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
!Curl_checkheaders(conn, "Content-Range:")) { !Curl_checkheaders(conn, "Content-Range")) {
/* if a line like this was already allocated, free the previous one */ /* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline); free(conn->allocptr.rangeline);
@ -2354,7 +2360,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref:"" /* Referer: <data> */, conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy && (conn->bits.httpproxy &&
!conn->bits.tunnel_proxy && !conn->bits.tunnel_proxy &&
!Curl_checkProxyheaders(conn, "Proxy-Connection:"))? !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"", "Proxy-Connection: Keep-Alive\r\n":"",
te te
); );
@ -2455,7 +2461,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize = data->state.infilesize; postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky && if((postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */ /* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "Content-Length: %" CURL_FORMAT_CURL_OFF_T
@ -2517,7 +2523,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(postsize != -1 && !data->req.upload_chunky && if(postsize != -1 && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
@ -2542,7 +2548,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value sure that the expect100header is always set to the preferred value
here. */ here. */
ptr = Curl_checkheaders(conn, "Expect:"); ptr = Curl_checkheaders(conn, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");
@ -2596,7 +2602,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((postsize != -1) && !data->req.upload_chunky && if((postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation, /* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */ although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
@ -2606,7 +2612,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result; return result;
} }
if(!Curl_checkheaders(conn, "Content-Type:")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
"Content-Type: application/" "Content-Type: application/"
"x-www-form-urlencoded\r\n"); "x-www-form-urlencoded\r\n");
@ -2618,7 +2624,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value sure that the expect100header is always set to the preferred value
here. */ here. */
ptr = Curl_checkheaders(conn, "Expect:"); ptr = Curl_checkheaders(conn, "Expect");
if(ptr) { if(ptr) {
data->state.expect100header = data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue"); Curl_compareheader(ptr, "Expect:", "100-continue");

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -252,7 +252,7 @@ static CURLcode CONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(!Curl_checkProxyheaders(conn, "Host:")) { if(!Curl_checkProxyheaders(conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader); host = aprintf("Host: %s\r\n", hostheader);
if(!host) { if(!host) {
free(hostheader); free(hostheader);
@ -260,10 +260,10 @@ static CURLcode CONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
if(!Curl_checkProxyheaders(conn, "Proxy-Connection:")) if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n"; proxyconn = "Proxy-Connection: Keep-Alive\r\n";
if(!Curl_checkProxyheaders(conn, "User-Agent:") && if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent; useragent = conn->allocptr.uagent;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -357,7 +357,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
} }
/* Transport Header for SETUP requests */ /* Transport Header for SETUP requests */
p_transport = Curl_checkheaders(conn, "Transport:"); p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) { if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */ /* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) { if(data->set.str[STRING_RTSP_TRANSPORT]) {
@ -381,11 +381,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */ /* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) { if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */ /* Accept Header */
p_accept = Curl_checkheaders(conn, "Accept:")? p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n"; NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */ /* Accept-Encoding header */
if(!Curl_checkheaders(conn, "Accept-Encoding:") && if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) { data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding); Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding = conn->allocptr.accept_encoding =
@ -402,11 +402,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string with the user-agent string specified, we erase the previously made string
here. */ here. */
if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) { if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent); Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL; conn->allocptr.uagent = NULL;
} }
else if(!Curl_checkheaders(conn, "User-Agent:") && else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) { data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent; p_uagent = conn->allocptr.uagent;
} }
@ -421,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */ /* Referrer */
Curl_safefree(conn->allocptr.ref); Curl_safefree(conn->allocptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else else
conn->allocptr.ref = NULL; conn->allocptr.ref = NULL;
@ -438,7 +438,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */ /* Check to see if there is a range set in the custom headers */
if(!Curl_checkheaders(conn, "Range:") && data->state.range) { if(!Curl_checkheaders(conn, "Range") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline); Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline; p_range = conn->allocptr.rangeline;
@ -448,11 +448,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* /*
* Sanity check the custom headers * Sanity check the custom headers
*/ */
if(Curl_checkheaders(conn, "CSeq:")) { if(Curl_checkheaders(conn, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header."); failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR; return CURLE_RTSP_CSEQ_ERROR;
} }
if(Curl_checkheaders(conn, "Session:")) { if(Curl_checkheaders(conn, "Session")) {
failf(data, "Session ID cannot be set as a custom header."); failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
@ -542,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) { if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to /* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */ * actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(conn, "Content-Length:")) { if(!Curl_checkheaders(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize)); (data->set.upload ? putsize : postsize));
@ -552,7 +552,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER || if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) { rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type:")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n"); "Content-Type: text/parameters\r\n");
if(result) if(result)
@ -561,7 +561,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
} }
if(rtspreq == RTSPREQ_ANNOUNCE) { if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type:")) { if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer, result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n"); "Content-Type: application/sdp\r\n");
if(result) if(result)

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -85,7 +85,7 @@
!defined(CURL_DISABLE_IMAP) !defined(CURL_DISABLE_IMAP)
/* /*
* checkheaders() checks the linked list of custom headers for a * checkheaders() checks the linked list of custom headers for a
* particular header (prefix). * particular header (prefix). Provide the prefix without colon!
* *
* Returns a pointer to the first matching header or NULL if none matched. * Returns a pointer to the first matching header or NULL if none matched.
*/ */
@ -97,7 +97,8 @@ char *Curl_checkheaders(const struct connectdata *conn,
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) { for(head = data->set.headers; head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen)) if(strncasecompare(head->data, thisheader, thislen) &&
Curl_headersep(head->data[thislen]) )
return head->data; return head->data;
} }

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -22,6 +22,7 @@
* *
***************************************************************************/ ***************************************************************************/
#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn, char *Curl_checkheaders(const struct connectdata *conn,
const char *thisheader); const char *thisheader);

View File

@ -127,6 +127,7 @@ test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 \ test1152 test1153 test1154 \
\ \
test1160 test1161 test1162 test1163 \ test1160 test1161 test1162 test1163 \
test1170 test1171 \
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \ test1216 test1217 test1218 test1219 \
@ -138,7 +139,7 @@ test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 \
test1260 test1261 test1262 test1263 test1264 test1265 \ test1260 test1261 test1262 test1263 test1264 test1265 \
\ \
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \ test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 \ test1288 test1289 test1290 test1291 test1292 \
test1298 test1299 \ test1298 test1299 \
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \ test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \ test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \

70
tests/data/test1170 Normal file
View File

@ -0,0 +1,70 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
compressed
Transfer-Encoding
</keywords>
</info>
#
# Server-side
<reply>
<data base64="yes">
SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDI5IE5vdiAyMDA0IDIxOjU2OjUzIEdNVA0KU2Vy
dmVyOiBBcGFjaGUvMS4zLjMxIChEZWJpYW4gR05VL0xpbnV4KSBtb2RfZ3ppcC8xLjMuMjYuMWEg
UEhQLzQuMy45LTEgbW9kX3NzbC8yLjguMjAgT3BlblNTTC8wLjkuN2QgbW9kX3BlcmwvMS4yOQ0K
VmFyeTogQWNjZXB0LUVuY29kaW5nDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1J
U08tODg1OS0xDQpUcmFuc2Zlci1FbmNvZGluZzogZ3ppcA0KQ29udGVudC1MZW5ndGg6IDQ0DQoN
Ch+LCAh5nqtBAANsYWxhbGEAy8nMS1Uw5FLIAdFGXAoQhjEXAAoCcWAYAAAA
</data>
<datacheck>
HTTP/1.1 200 OK
Date: Mon, 29 Nov 2004 21:56:53 GMT
Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29
Vary: Accept-Encoding
Content-Type: text/html; charset=ISO-8859-1
Transfer-Encoding: gzip
Content-Length: 44
line 1
line 2
line 3
</datacheck>
</reply>
#
# Client-side
<client>
<features>
libz
</features>
<server>
http
</server>
<name>
HTTP GET transfer-encoding with removed Connection:
</name>
<command>
http://%HOSTIP:%HTTPPORT/1170 --tr-encoding -H "Connection:"
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1170 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Connection: TE
TE: gzip
</protocol>
</verify>
</testcase>

70
tests/data/test1171 Normal file
View File

@ -0,0 +1,70 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
compressed
Transfer-Encoding
</keywords>
</info>
#
# Server-side
<reply>
<data base64="yes">
SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDI5IE5vdiAyMDA0IDIxOjU2OjUzIEdNVA0KU2Vy
dmVyOiBBcGFjaGUvMS4zLjMxIChEZWJpYW4gR05VL0xpbnV4KSBtb2RfZ3ppcC8xLjMuMjYuMWEg
UEhQLzQuMy45LTEgbW9kX3NzbC8yLjguMjAgT3BlblNTTC8wLjkuN2QgbW9kX3BlcmwvMS4yOQ0K
VmFyeTogQWNjZXB0LUVuY29kaW5nDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1J
U08tODg1OS0xDQpUcmFuc2Zlci1FbmNvZGluZzogZ3ppcA0KQ29udGVudC1MZW5ndGg6IDQ0DQoN
Ch+LCAh5nqtBAANsYWxhbGEAy8nMS1Uw5FLIAdFGXAoQhjEXAAoCcWAYAAAA
</data>
<datacheck>
HTTP/1.1 200 OK
Date: Mon, 29 Nov 2004 21:56:53 GMT
Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29
Vary: Accept-Encoding
Content-Type: text/html; charset=ISO-8859-1
Transfer-Encoding: gzip
Content-Length: 44
line 1
line 2
line 3
</datacheck>
</reply>
#
# Client-side
<client>
<features>
libz
</features>
<server>
http
</server>
<name>
HTTP GET transfer-encoding with blanked Connection:
</name>
<command>
http://%HOSTIP:%HTTPPORT/1171 --tr-encoding -H "Connection;"
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1171 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Connection: TE
TE: gzip
</protocol>
</verify>
</testcase>

50
tests/data/test1292 Normal file
View File

@ -0,0 +1,50 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP added headers
HTTP replaced headers
</keywords>
</info>
#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake swsclose
Content-Type: text/html
Funny-head: yesyes
</data>
</reply>
#
# Client-side
<client>
<server>
http
</server>
<name>
Replaced internal headers with a blank one
</name>
<command>
-H "Host;" -H "Accept;" http://%HOSTIP:%HTTPPORT/1292
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1292 HTTP/1.1
Host:
Accept:
</protocol>
</verify>
</testcase>