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:
parent
f3bc16f4f5
commit
cc0285da7f
82
lib/http.c
82
lib/http.c
@ -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
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user