aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/http.c82
-rw-r--r--lib/http.h2
-rw-r--r--lib/transfer.c85
3 files changed, 90 insertions, 79 deletions
diff --git a/lib/http.c b/lib/http.c
index c65b0cf1f..0da7156e3 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -181,6 +181,60 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader)
}
/*
+ * 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)
* for HTTP Basic authentication.
*
@@ -668,6 +722,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
/* if exactly this is wanted, go */
int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
if(neg == 0) {
+ DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
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
redirected request is being out on thin ice. Except if the host name
is the same as the first one! */
- char *start = ptr+strlen("Host:");
- while(*start && ISSPACE(*start ))
- 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;
+ char *cookiehost = Curl_copy_header_value(ptr);
+ if (!cookiehost)
+ return CURLE_OUT_OF_MEMORY;
+ if (!*cookiehost)
+ /* 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 = malloc(len+1);
- if(!conn->allocptr.cookiehost)
- return CURLE_OUT_OF_MEMORY;
- memcpy(conn->allocptr.cookiehost, start, len);
- conn->allocptr.cookiehost[len]=0;
+ conn->allocptr.cookiehost = cookiehost;
}
#endif
diff --git a/lib/http.h b/lib/http.h
index f41ebb6e8..5a04f8c43 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -35,6 +35,8 @@ bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */
+char *Curl_copy_header_value(const char *h);
+
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
int tunnelsocket,
diff --git a/lib/transfer.c b/lib/transfer.c
index 4201ad18a..7f59be876 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -109,6 +109,7 @@
#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */
+
/*
* This function will call the read callback to fill our buffer with data
* to upload.
@@ -927,42 +928,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
", 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)) {
- char *start;
- char *end;
- 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 */
+ char *contenttype = Curl_copy_header_value(k->p);
+ if (!contenttype)
+ return CURLE_OUT_OF_MEMORY;
+ if (!*contenttype)
+ /* ignore empty data */
+ free(contenttype);
+ else {
Curl_safefree(data->info.contenttype);
-
- data->info.contenttype = malloc(len + 1);
- if(NULL == data->info.contenttype)
- return CURLE_OUT_OF_MEMORY;
-
- /* copy the content-type string */
- memcpy(data->info.contenttype, start, len);
- data->info.contenttype[len] = 0; /* zero terminate */
+ data->info.contenttype = contenttype;
}
}
#ifndef CURL_DISABLE_HTTP
@@ -1123,36 +1099,19 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
else if((k->httpcode >= 300 && k->httpcode < 400) &&
checkprefix("Location:", k->p)) {
- /* this is the URL that the server advices us to use instead */
- char *ptr;
- char *start=k->p;
- 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;
+ /* this is the URL that the server advises us to use instead */
+ char *location = Curl_copy_header_value(k->p);
+ if (!location)
+ 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) {
+ DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->req.location); /* clone */
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;