summaryrefslogtreecommitdiff
path: root/lib/libfetch/http.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2000-07-21 11:02:43 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2000-07-21 11:02:43 +0000
commitc78f1cc912c84fd5aacdafea557bb94b7bd7e9aa (patch)
treeed5ae7750eaa324c5641e700f59b9f28c8f6b9ed /lib/libfetch/http.c
parente0a9ca38aa9340d06065069b1c77dc57d9caa536 (diff)
Notes
Diffstat (limited to 'lib/libfetch/http.c')
-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 06dad22ade4a..090114283286 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) {