1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

Factored out Curl_copy_header_value

This commit is contained in:
Dan Fandrich 2008-07-30 20:11:51 +00:00
parent f3bc16f4f5
commit cc0285da7f
3 changed files with 89 additions and 78 deletions

View File

@ -180,6 +180,60 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader)
return NULL; return NULL;
} }
/*
* Strip off leading and trailing whitespace from the value in the
* given HTTP header line and return a strdupped copy. Returns NULL in
* case of allocation failure. Returns an empty string if the header value
* consists entirely of whitespace.
*/
char *Curl_copy_header_value(const char *h)
{
const char *start;
const char *end;
char *value;
size_t len;
DEBUGASSERT(h);
/* Find the end of the header name */
while (*h && (*h != ':'))
++h;
if (*h)
/* Skip over colon */
++h;
/* Find the first non-space letter */
for(start=h;
*start && ISSPACE(*start);
start++)
; /* empty loop */
/* data is in the host encoding so
use '\r' and '\n' instead of 0x0d and 0x0a */
end = strchr(start, '\r');
if(!end)
end = strchr(start, '\n');
if(!end)
end = strchr(start, '\0');
/* skip all trailing space letters */
for(; ISSPACE(*end) && (end > start); end--)
; /* empty loop */
/* get length of the type */
len = end-start+1;
value = malloc(len + 1);
if(!value)
return NULL;
memcpy(value, start, len);
value[len] = 0; /* zero terminate */
return value;
}
/* /*
* http_output_basic() sets up an Authorization: header (or the proxy version) * http_output_basic() sets up an Authorization: header (or the proxy version)
* for HTTP Basic authentication. * for HTTP Basic authentication.
@ -668,6 +722,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
/* if exactly this is wanted, go */ /* if exactly this is wanted, go */
int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
if(neg == 0) { if(neg == 0) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url); data->req.newurl = strdup(data->change.url);
data->state.authproblem = (data->req.newurl == NULL); data->state.authproblem = (data->req.newurl == NULL);
} }
@ -2094,23 +2149,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
custom Host: header if this is NOT a redirect, as setting Host: in the custom Host: header if this is NOT a redirect, as setting Host: in the
redirected request is being out on thin ice. Except if the host name redirected request is being out on thin ice. Except if the host name
is the same as the first one! */ is the same as the first one! */
char *start = ptr+strlen("Host:"); char *cookiehost = Curl_copy_header_value(ptr);
while(*start && ISSPACE(*start )) if (!cookiehost)
start++;
ptr = start; /* start host-scanning here */
/* scan through the string to find the end (space or colon) */
while(*ptr && !ISSPACE(*ptr) && !(':'==*ptr))
ptr++;
if(ptr != start) {
size_t len=ptr-start;
Curl_safefree(conn->allocptr.cookiehost);
conn->allocptr.cookiehost = malloc(len+1);
if(!conn->allocptr.cookiehost)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
memcpy(conn->allocptr.cookiehost, start, len); if (!*cookiehost)
conn->allocptr.cookiehost[len]=0; /* ignore empty data */
free(cookiehost);
else {
char *colon = strchr(cookiehost, ':');
if (colon)
*colon = 0; /* The host must not include an embedded port number */
Curl_safefree(conn->allocptr.cookiehost);
conn->allocptr.cookiehost = cookiehost;
} }
#endif #endif

View File

@ -35,6 +35,8 @@ bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */ const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */ const char *content); /* content string to find */
char *Curl_copy_header_value(const char *h);
/* ftp can use this as well */ /* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct connectdata *conn, CURLcode Curl_proxyCONNECT(struct connectdata *conn,
int tunnelsocket, int tunnelsocket,

View File

@ -109,6 +109,7 @@
#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */ #define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */
/* /*
* This function will call the read callback to fill our buffer with data * This function will call the read callback to fill our buffer with data
* to upload. * to upload.
@ -927,42 +928,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
", closing after transfer\n", contentlength); ", closing after transfer\n", contentlength);
} }
} }
/* check for Content-Type: header lines to get the mime-type */ /* check for Content-Type: header lines to get the MIME-type */
else if(checkprefix("Content-Type:", k->p)) { else if(checkprefix("Content-Type:", k->p)) {
char *start; char *contenttype = Curl_copy_header_value(k->p);
char *end; if (!contenttype)
size_t len;
/* Find the first non-space letter */
for(start=k->p+13;
*start && ISSPACE(*start);
start++)
; /* empty loop */
/* data is now in the host encoding so
use '\r' and '\n' instead of 0x0d and 0x0a */
end = strchr(start, '\r');
if(!end)
end = strchr(start, '\n');
if(end) {
/* skip all trailing space letters */
for(; ISSPACE(*end) && (end > start); end--)
; /* empty loop */
/* get length of the type */
len = end-start+1;
/* allocate memory of a cloned copy */
Curl_safefree(data->info.contenttype);
data->info.contenttype = malloc(len + 1);
if(NULL == data->info.contenttype)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if (!*contenttype)
/* copy the content-type string */ /* ignore empty data */
memcpy(data->info.contenttype, start, len); free(contenttype);
data->info.contenttype[len] = 0; /* zero terminate */ else {
Curl_safefree(data->info.contenttype);
data->info.contenttype = contenttype;
} }
} }
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
@ -1123,36 +1099,19 @@ CURLcode Curl_readwrite(struct connectdata *conn,
} }
else if((k->httpcode >= 300 && k->httpcode < 400) && else if((k->httpcode >= 300 && k->httpcode < 400) &&
checkprefix("Location:", k->p)) { checkprefix("Location:", k->p)) {
/* this is the URL that the server advices us to use instead */ /* this is the URL that the server advises us to use instead */
char *ptr; char *location = Curl_copy_header_value(k->p);
char *start=k->p; if (!location)
char backup;
start += 9; /* pass "Location:" */
/* Skip spaces and tabs. We do this to support multiple
white spaces after the "Location:" keyword. */
while(*start && ISSPACE(*start ))
start++;
/* Scan through the string from the end to find the last
non-space. k->end_ptr points to the actual terminating zero
letter, move pointer one letter back and start from
there. This logic strips off trailing whitespace, but keeps
any embedded whitespace. */
ptr = k->end_ptr-1;
while((ptr>=start) && ISSPACE(*ptr))
ptr--;
ptr++;
backup = *ptr; /* store the ending letter */
if(ptr != start) {
*ptr = '\0'; /* zero terminate */
data->req.location = strdup(start); /* clone string */
*ptr = backup; /* restore ending letter */
if(!data->req.location)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if (!*location)
/* ignore empty data */
free(location);
else {
DEBUGASSERT(!data->req.location);
data->req.location = location;
if(data->set.http_follow_location) { if(data->set.http_follow_location) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->req.location); /* clone */ data->req.newurl = strdup(data->req.location); /* clone */
if(!data->req.newurl) if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;