summaryrefslogtreecommitdiffstats
path: root/lib/libfetch
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2000-07-21 11:02:43 +0000
committerdes <des@FreeBSD.org>2000-07-21 11:02:43 +0000
commitaccb02b55adca56cf39b820f13f7c5fe5c836912 (patch)
tree04cddae5d5b0930e6c6206b7e572dea2b99724ab /lib/libfetch
parentef0d473b84b8fccbcfffec18f6171fa502ae0492 (diff)
downloadFreeBSD-src-accb02b55adca56cf39b820f13f7c5fe5c836912.zip
FreeBSD-src-accb02b55adca56cf39b820f13f7c5fe5c836912.tar.gz
Ignore environment variables that are set but empty.
Sort out the size / length confusion. Always try to report the *real* file size in the url_stat structure, no matter how much of it is actually being sent, and try to detect inconsistencies between sizes. Rearrange the request loop to avoid having to add meaningless code just to silence compiler warnings. Switch to a more sensible and consistent interface for the _http_parse*() functions.
Diffstat (limited to 'lib/libfetch')
-rw-r--r--lib/libfetch/http.c121
1 files changed, 81 insertions, 40 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 06dad22..0901142 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -419,54 +419,70 @@ _http_next_header(int fd, char **p)
/*
* Parse a last-modified header
*/
-static time_t
-_http_parse_mtime(char *p)
+static int
+_http_parse_mtime(char *p, time_t *mtime)
{
- char locale[64];
+ char locale[64], *r;
struct tm tm;
strncpy(locale, setlocale(LC_TIME, NULL), sizeof locale);
setlocale(LC_TIME, "C");
- strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm);
+ r = strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm);
/* XXX should add support for date-2 and date-3 */
setlocale(LC_TIME, locale);
+ if (r == NULL)
+ return -1;
DEBUG(fprintf(stderr, "last modified: [\033[1m%04d-%02d-%02d "
"%02d:%02d:%02d\033[m]\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec));
- return timegm(&tm);
+ *mtime = timegm(&tm);
+ return 0;
}
/*
* Parse a content-length header
*/
-static off_t
-_http_parse_length(char *p)
+static int
+_http_parse_length(char *p, size_t *length)
{
- off_t len;
+ size_t len;
for (len = 0; *p && isdigit(*p); ++p)
len = len * 10 + (*p - '0');
- DEBUG(fprintf(stderr, "content length: [\033[1m%lld\033[m]\n", len));
- return len;
+ DEBUG(fprintf(stderr, "content length: [\033[1m%d\033[m]\n", len));
+ *length = len;
+ return 0;
}
/*
* Parse a content-range header
*/
-static off_t
-_http_parse_range(char *p)
+static int
+_http_parse_range(char *p, off_t *offset, size_t *length, size_t *size)
{
- off_t off;
-
+ int first, last, len;
+
if (strncasecmp(p, "bytes ", 6) != 0)
return -1;
- for (p += 6, off = 0; *p && isdigit(*p); ++p)
- off = off * 10 + *p - '0';
+ for (first = 0, p += 6; *p && isdigit(*p); ++p)
+ first = first * 10 + *p - '0';
if (*p != '-')
return -1;
- DEBUG(fprintf(stderr, "content range: [\033[1m%lld-\033[m]\n", off));
- return off;
+ for (last = 0, ++p; *p && isdigit(*p); ++p)
+ last = last * 10 + *p - '0';
+ if (first > last || *p != '/')
+ return -1;
+ for (len = 0, ++p; *p && isdigit(*p); ++p)
+ len = len * 10 + *p - '0';
+ if (len < last - first + 1)
+ return -1;
+ DEBUG(fprintf(stderr, "content range: [\033[1m%d-%d/%d\033[m]\n",
+ first, last, len));
+ *offset = first;
+ *length = last - first + 1;
+ *size = len;
+ return 0;
}
@@ -715,7 +731,7 @@ _http_connect(struct url *URL, int *proxy, char *flags)
URL->port = 80;
}
- if (!direct && (p = getenv("HTTP_PROXY")) != NULL) {
+ if (!direct && (p = getenv("HTTP_PROXY")) != NULL && *p != '\0') {
/* attempt to connect to proxy server */
if ((fd = _http_proxy_connect(p, af, verbose)) == -1)
return -1;
@@ -751,6 +767,8 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
int chunked, need_auth, noredirect, proxy, verbose;
int code, fd, i, n;
off_t offset;
+ size_t clength, length, size;
+ time_t mtime;
char *p;
FILE *f;
hdr h;
@@ -762,23 +780,22 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
noredirect = (flags && strchr(flags, 'A'));
verbose = (flags && strchr(flags, 'v'));
+ /* try the provided URL first */
+ url = URL;
+
+ /* if the A flag is set, we only get one try */
n = noredirect ? 1 : MAX_REDIRECT;
+ i = 0;
- /* just to appease compiler warnings */
- code = HTTP_PROTOCOL_ERROR;
- chunked = 0;
- offset = 0;
- fd = -1;
-
- for (url = URL, i = 0; i < n; ++i) {
+ do {
new = NULL;
- if (us) {
- us->size = -1;
- us->atime = us->mtime = 0;
- }
chunked = 0;
need_auth = 0;
offset = 0;
+ clength = -1;
+ length = -1;
+ size = -1;
+ mtime = 0;
retry:
/* connect to server or proxy */
if ((fd = _http_connect(url, &proxy, flags)) == -1)
@@ -805,7 +822,7 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
}
/* proxy authorization */
- if (proxy && (p = getenv("HTTP_PROXY_AUTH")) != NULL)
+ if (proxy && (p = getenv("HTTP_PROXY_AUTH")) != NULL && *p != '\0')
_http_authorize(fd, "Proxy-Authorization", p);
/* server authorization */
@@ -814,7 +831,7 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
_http_basic_auth(fd, "Authorization",
url->user ? url->user : "",
url->pwd ? url->pwd : "");
- else if ((p = getenv("HTTP_AUTH")) != NULL)
+ else if ((p = getenv("HTTP_AUTH")) != NULL && *p != '\0')
_http_authorize(fd, "Authorization", p);
else {
_http_seterr(HTTP_NEED_AUTH);
@@ -885,15 +902,13 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
_http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
case hdr_content_length:
- if (us)
- us->size = _http_parse_length(p);
+ _http_parse_length(p, &clength);
break;
case hdr_content_range:
- offset = _http_parse_range(p);
+ _http_parse_range(p, &offset, &length, &size);
break;
case hdr_last_modified:
- if (us)
- us->atime = us->mtime = _http_parse_mtime(p);
+ _http_parse_mtime(p, &mtime);
break;
case hdr_location:
if (!HTTP_REDIRECT(code))
@@ -942,7 +957,7 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
if (url != URL)
fetchFreeURL(url);
url = new;
- }
+ } while (++i < n);
/* no success */
if (fd == -1) {
@@ -950,14 +965,40 @@ _http_request(struct url *URL, char *op, struct url_stat *us, char *flags)
goto ouch;
}
+ DEBUG(fprintf(stderr, "offset: %lld, length: %d, size: %d, clength: %d\n",
+ offset, length, size, clength));
+
+ /* check for inconsistencies */
+ if (clength != -1 && length != -1 && clength != length) {
+ _http_seterr(HTTP_PROTOCOL_ERROR);
+ goto ouch;
+ }
+ if (clength == -1)
+ clength = length;
+ if (clength != -1)
+ length = offset + clength;
+ if (length != -1 && size != -1 && length != size) {
+ _http_seterr(HTTP_PROTOCOL_ERROR);
+ goto ouch;
+ }
+ if (size == -1)
+ size = length;
+
+ /* fill in stats */
+ if (us) {
+ us->size = size;
+ us->atime = us->mtime = mtime;
+ }
+
/* too far? */
- if (offset > url->offset) {
+ if (offset > URL->offset) {
_http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
}
- /* report back real offset */
+ /* report back real offset and size */
URL->offset = offset;
+ URL->length = clength;
/* wrap it up in a FILE */
if ((f = chunked ? _http_funopen(fd) : fdopen(fd, "r")) == NULL) {
OpenPOWER on IntegriCloud