aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2018-03-05 23:38:16 +0100
committerDaniel Stenberg <daniel@haxx.se>2018-03-11 11:46:10 +0100
commit8123560d4496992baecc0c7a05e56ce48e6b6273 (patch)
tree5597389e87043f3fd82d84334a61d690784d8c53 /lib
parent019aa722aa82e8642254f3e835992bc425ed3e19 (diff)
HTTP: allow "header;" to replace an internal header with a blank one
Reported-by: Michael Kaufmann Fixes #2357 Closes #2362
Diffstat (limited to 'lib')
-rw-r--r--lib/http.c134
-rw-r--r--lib/http_proxy.c8
-rw-r--r--lib/rtsp.c26
-rw-r--r--lib/transfer.c7
-rw-r--r--lib/transfer.h3
5 files changed, 93 insertions, 85 deletions
diff --git a/lib/http.c b/lib/http.c
index c1c7b3908..841f6cc0b 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -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
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply
- * to know if this is a proxy request or not, as it then might check a
- * different header list.
+ * It takes a connectdata struct as input instead of the Curl_easy simply to
+ * know if this is a proxy request or not, as it then might check a different
+ * header list. Provide the header prefix without colon!.
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
@@ -191,7 +191,8 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : 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;
}
@@ -614,9 +615,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
if((proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic";
result = http_output_basic(conn, proxy);
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
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1598,7 +1599,32 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
headers = h[i];
while(headers) {
+ char *semicolonp = NULL;
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) {
/* 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))
ptr++;
- if(*ptr) {
- /* only send this if the contents was non-blank */
+ if(*ptr || semicolonp) {
+ /* only send this if the contents was non-blank or done special */
+ CURLcode result = CURLE_OK;
if(conn->allocptr.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)))
;
else {
- CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
- 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;
- }
+ result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
}
+ if(semicolonp)
+ *semicolonp = ';'; /* put back the semicolon */
+ if(result)
+ return result;
}
}
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
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:")) {
+ if(Curl_checkheaders(conn, "User-Agent")) {
free(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
@@ -1890,7 +1889,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->bits.authneg = FALSE;
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);
if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY;
@@ -1899,11 +1898,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref = NULL;
#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];
#endif
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
@@ -1919,22 +1918,29 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBZ
/* 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) {
/* 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
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
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"
Curl_safefree(conn->allocptr.te);
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
/* Create the (updated) Connection: header */
- conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
- strdup("Connection: TE\r\n" TE_HEADER);
+ conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+ free(cptr);
if(!conn->allocptr.te)
return CURLE_OUT_OF_MEMORY;
}
@@ -1958,7 +1964,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+ const char *cthdr = Curl_checkheaders(conn, "Content-Type");
/* Read and seek 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);
}
- ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
@@ -2016,7 +2022,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_safefree(conn->allocptr.host);
- ptr = Curl_checkheaders(conn, "Host:");
+ ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
@@ -2055,7 +2061,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#endif
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)
return CURLE_OUT_OF_MEMORY;
}
@@ -2164,7 +2170,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#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) &&
data->state.resume_from) {
@@ -2245,14 +2251,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* ones if any such are specified.
*/
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 */
free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
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 */
free(conn->allocptr.rangeline);
@@ -2354,7 +2360,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy &&
!conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
@@ -2455,7 +2461,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize = data->state.infilesize;
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 */
result = Curl_add_bufferf(req_buffer,
"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
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
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,
although it isn't very wise to actually set your own */
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
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
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
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
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,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@@ -2606,7 +2612,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/"
"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
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 7f5040543..c1eb177dd 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -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
* 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;
}
- if(!Curl_checkProxyheaders(conn, "Host:")) {
+ if(!Curl_checkProxyheaders(conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
@@ -260,10 +260,10 @@ static CURLcode CONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
diff --git a/lib/rtsp.c b/lib/rtsp.c
index c60697290..194bc949e 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -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
* 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 */
- p_transport = Curl_checkheaders(conn, "Transport:");
+ p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
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 */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept:")?
+ p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(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
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
@@ -421,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
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);
else
conn->allocptr.ref = NULL;
@@ -438,7 +438,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* 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);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
@@ -448,11 +448,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* 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.");
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.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -542,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* 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,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
@@ -552,7 +552,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -561,7 +561,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
diff --git a/lib/transfer.c b/lib/transfer.c
index e27792c10..c46ac25f4 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -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
* you should have received as part of this distribution. The terms
@@ -85,7 +85,7 @@
!defined(CURL_DISABLE_IMAP)
/*
* 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.
*/
@@ -97,7 +97,8 @@ char *Curl_checkheaders(const struct connectdata *conn,
struct Curl_easy *data = conn->data;
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;
}
diff --git a/lib/transfer.h b/lib/transfer.h
index 72526a834..9ba398d27 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -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
* 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,
const char *thisheader);