http.c (4cee73c80f52cef57f3e95357ada6ea352be14e2) http.c (38c7e4a631ce968b02e4a08944aabad9b57844e8)
1/*-
2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 286 unchanged lines hidden (view full) ---

295 hdr_last_modified,
296 hdr_location,
297 hdr_transfer_encoding
298} hdr;
299
300/* Names of interesting headers */
301static struct {
302 hdr num;
1/*-
2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 286 unchanged lines hidden (view full) ---

295 hdr_last_modified,
296 hdr_location,
297 hdr_transfer_encoding
298} hdr;
299
300/* Names of interesting headers */
301static struct {
302 hdr num;
303 char *name;
303 const char *name;
304} hdr_names[] = {
305 { hdr_content_length, "Content-Length" },
306 { hdr_content_range, "Content-Range" },
307 { hdr_last_modified, "Last-Modified" },
308 { hdr_location, "Location" },
309 { hdr_transfer_encoding, "Transfer-Encoding" },
310 { hdr_unknown, NULL },
311};
312
313static char *reply_buf;
314static size_t reply_size;
315static size_t reply_length;
316
317/*
318 * Send a formatted line; optionally echo to terminal
319 */
320static int
304} hdr_names[] = {
305 { hdr_content_length, "Content-Length" },
306 { hdr_content_range, "Content-Range" },
307 { hdr_last_modified, "Last-Modified" },
308 { hdr_location, "Location" },
309 { hdr_transfer_encoding, "Transfer-Encoding" },
310 { hdr_unknown, NULL },
311};
312
313static char *reply_buf;
314static size_t reply_size;
315static size_t reply_length;
316
317/*
318 * Send a formatted line; optionally echo to terminal
319 */
320static int
321_http_cmd(int fd, char *fmt, ...)
321_http_cmd(int fd, const char *fmt, ...)
322{
323 va_list ap;
324 size_t len;
325 char *msg;
326 int r;
327
328 va_start(ap, fmt);
329 len = vasprintf(&msg, fmt, ap);

--- 51 unchanged lines hidden (view full) ---

381
382 return ((p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0'));
383}
384
385/*
386 * Check a header; if the type matches the given string, return a
387 * pointer to the beginning of the value.
388 */
322{
323 va_list ap;
324 size_t len;
325 char *msg;
326 int r;
327
328 va_start(ap, fmt);
329 len = vasprintf(&msg, fmt, ap);

--- 51 unchanged lines hidden (view full) ---

381
382 return ((p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0'));
383}
384
385/*
386 * Check a header; if the type matches the given string, return a
387 * pointer to the beginning of the value.
388 */
389static char *
390_http_match(char *str, char *hdr)
389static const char *
390_http_match(const char *str, const char *hdr)
391{
392 while (*str && *hdr && tolower(*str++) == tolower(*hdr++))
393 /* nothing */;
394 if (*str || *hdr != ':')
395 return NULL;
396 while (*hdr && isspace(*++hdr))
397 /* nothing */;
398 return hdr;
399}
400
401/*
402 * Get the next header and return the appropriate symbolic code.
403 */
404static hdr
391{
392 while (*str && *hdr && tolower(*str++) == tolower(*hdr++))
393 /* nothing */;
394 if (*str || *hdr != ':')
395 return NULL;
396 while (*hdr && isspace(*++hdr))
397 /* nothing */;
398 return hdr;
399}
400
401/*
402 * Get the next header and return the appropriate symbolic code.
403 */
404static hdr
405_http_next_header(int fd, char **p)
405_http_next_header(int fd, const char **p)
406{
407 int i;
408
409 if (_fetch_getln(fd, &reply_buf, &reply_size, &reply_length) == -1)
410 return hdr_syserror;
411 while (reply_length && isspace(reply_buf[reply_length-1]))
412 reply_length--;
413 reply_buf[reply_length] = 0;

--- 10 unchanged lines hidden (view full) ---

424 return hdr_names[i].num;
425 return hdr_unknown;
426}
427
428/*
429 * Parse a last-modified header
430 */
431static int
406{
407 int i;
408
409 if (_fetch_getln(fd, &reply_buf, &reply_size, &reply_length) == -1)
410 return hdr_syserror;
411 while (reply_length && isspace(reply_buf[reply_length-1]))
412 reply_length--;
413 reply_buf[reply_length] = 0;

--- 10 unchanged lines hidden (view full) ---

424 return hdr_names[i].num;
425 return hdr_unknown;
426}
427
428/*
429 * Parse a last-modified header
430 */
431static int
432_http_parse_mtime(char *p, time_t *mtime)
432_http_parse_mtime(const char *p, time_t *mtime)
433{
434 char locale[64], *r;
435 struct tm tm;
436
437 strncpy(locale, setlocale(LC_TIME, NULL), sizeof locale);
438 setlocale(LC_TIME, "C");
439 r = strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm);
440 /* XXX should add support for date-2 and date-3 */

--- 7 unchanged lines hidden (view full) ---

448 *mtime = timegm(&tm);
449 return 0;
450}
451
452/*
453 * Parse a content-length header
454 */
455static int
433{
434 char locale[64], *r;
435 struct tm tm;
436
437 strncpy(locale, setlocale(LC_TIME, NULL), sizeof locale);
438 setlocale(LC_TIME, "C");
439 r = strptime(p, "%a, %d %b %Y %H:%M:%S GMT", &tm);
440 /* XXX should add support for date-2 and date-3 */

--- 7 unchanged lines hidden (view full) ---

448 *mtime = timegm(&tm);
449 return 0;
450}
451
452/*
453 * Parse a content-length header
454 */
455static int
456_http_parse_length(char *p, off_t *length)
456_http_parse_length(const char *p, off_t *length)
457{
458 off_t len;
459
460 for (len = 0; *p && isdigit(*p); ++p)
461 len = len * 10 + (*p - '0');
462 DEBUG(fprintf(stderr, "content length: [\033[1m%lld\033[m]\n", len));
463 *length = len;
464 return 0;
465}
466
467/*
468 * Parse a content-range header
469 */
470static int
457{
458 off_t len;
459
460 for (len = 0; *p && isdigit(*p); ++p)
461 len = len * 10 + (*p - '0');
462 DEBUG(fprintf(stderr, "content length: [\033[1m%lld\033[m]\n", len));
463 *length = len;
464 return 0;
465}
466
467/*
468 * Parse a content-range header
469 */
470static int
471_http_parse_range(char *p, off_t *offset, off_t *length, off_t *size)
471_http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
472{
473 int first, last, len;
474
475 if (strncasecmp(p, "bytes ", 6) != 0)
476 return -1;
477 for (first = 0, p += 6; *p && isdigit(*p); ++p)
478 first = first * 10 + *p - '0';
479 if (*p != '-')

--- 74 unchanged lines hidden (view full) ---

554 *dst = 0;
555 return str;
556}
557
558/*
559 * Encode username and password
560 */
561static int
472{
473 int first, last, len;
474
475 if (strncasecmp(p, "bytes ", 6) != 0)
476 return -1;
477 for (first = 0, p += 6; *p && isdigit(*p); ++p)
478 first = first * 10 + *p - '0';
479 if (*p != '-')

--- 74 unchanged lines hidden (view full) ---

554 *dst = 0;
555 return str;
556}
557
558/*
559 * Encode username and password
560 */
561static int
562_http_basic_auth(int fd, char *hdr, char *usr, char *pwd)
562_http_basic_auth(int fd, const char *hdr, const char *usr, const char *pwd)
563{
564 char *upw, *auth;
565 int r;
566
567 if (asprintf(&upw, "%s:%s", usr, pwd) == -1)
568 return -1;
569 auth = _http_base64(upw);
570 free(upw);
571 if (auth == NULL)
572 return -1;
573 r = _http_cmd(fd, "%s: Basic %s", hdr, auth);
574 free(auth);
575 return r;
576}
577
578/*
579 * Send an authorization header
580 */
581static int
563{
564 char *upw, *auth;
565 int r;
566
567 if (asprintf(&upw, "%s:%s", usr, pwd) == -1)
568 return -1;
569 auth = _http_base64(upw);
570 free(upw);
571 if (auth == NULL)
572 return -1;
573 r = _http_cmd(fd, "%s: Basic %s", hdr, auth);
574 free(auth);
575 return r;
576}
577
578/*
579 * Send an authorization header
580 */
581static int
582_http_authorize(int fd, char *hdr, char *p)
582_http_authorize(int fd, const char *hdr, const char *p)
583{
584 /* basic authorization */
585 if (strncasecmp(p, "basic:", 6) == 0) {
586 char *user, *pwd, *str;
587 int r;
588
589 /* skip realm */
590 for (p += 6; *p && *p != ':'; ++p)

--- 16 unchanged lines hidden (view full) ---

607/*****************************************************************************
608 * Helper functions for connecting to a server or proxy
609 */
610
611/*
612 * Connect to the correct HTTP server or proxy.
613 */
614static int
583{
584 /* basic authorization */
585 if (strncasecmp(p, "basic:", 6) == 0) {
586 char *user, *pwd, *str;
587 int r;
588
589 /* skip realm */
590 for (p += 6; *p && *p != ':'; ++p)

--- 16 unchanged lines hidden (view full) ---

607/*****************************************************************************
608 * Helper functions for connecting to a server or proxy
609 */
610
611/*
612 * Connect to the correct HTTP server or proxy.
613 */
614static int
615_http_connect(struct url *URL, struct url *purl, char *flags)
615_http_connect(struct url *URL, struct url *purl, const char *flags)
616{
617 int verbose;
618 int af, fd;
619
620#ifdef INET6
621 af = AF_UNSPEC;
622#else
623 af = AF_INET;

--- 17 unchanged lines hidden (view full) ---

641
642 if ((fd = _fetch_connect(URL->host, URL->port, af, verbose)) == -1)
643 /* _fetch_connect() has already set an error code */
644 return -1;
645 return fd;
646}
647
648static struct url *
616{
617 int verbose;
618 int af, fd;
619
620#ifdef INET6
621 af = AF_UNSPEC;
622#else
623 af = AF_INET;

--- 17 unchanged lines hidden (view full) ---

641
642 if ((fd = _fetch_connect(URL->host, URL->port, af, verbose)) == -1)
643 /* _fetch_connect() has already set an error code */
644 return -1;
645 return fd;
646}
647
648static struct url *
649_http_get_proxy()
649_http_get_proxy(void)
650{
651 struct url *purl;
652 char *p;
653
654 if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
655 (purl = fetchParseURL(p))) {
656 if (!*purl->scheme)
657 strcpy(purl->scheme, SCHEME_HTTP);

--- 10 unchanged lines hidden (view full) ---

668/*****************************************************************************
669 * Core
670 */
671
672/*
673 * Send a request and process the reply
674 */
675FILE *
650{
651 struct url *purl;
652 char *p;
653
654 if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
655 (purl = fetchParseURL(p))) {
656 if (!*purl->scheme)
657 strcpy(purl->scheme, SCHEME_HTTP);

--- 10 unchanged lines hidden (view full) ---

668/*****************************************************************************
669 * Core
670 */
671
672/*
673 * Send a request and process the reply
674 */
675FILE *
676_http_request(struct url *URL, char *op, struct url_stat *us,
677 struct url *purl, char *flags)
676_http_request(struct url *URL, const char *op, struct url_stat *us,
677 struct url *purl, const char *flags)
678{
679 struct url *url, *new;
680 int chunked, direct, need_auth, noredirect, verbose;
681 int code, fd, i, n;
682 off_t offset, clength, length, size;
683 time_t mtime;
678{
679 struct url *url, *new;
680 int chunked, direct, need_auth, noredirect, verbose;
681 int code, fd, i, n;
682 off_t offset, clength, length, size;
683 time_t mtime;
684 char *p;
684 const char *p;
685 FILE *f;
686 hdr h;
687 char *host;
688#ifdef INET6
689 char hbuf[MAXHOSTNAMELEN + 1];
690#endif
691
692 direct = CHECK_FLAG('d');

--- 262 unchanged lines hidden (view full) ---

955/*****************************************************************************
956 * Entry points
957 */
958
959/*
960 * Retrieve and stat a file by HTTP
961 */
962FILE *
685 FILE *f;
686 hdr h;
687 char *host;
688#ifdef INET6
689 char hbuf[MAXHOSTNAMELEN + 1];
690#endif
691
692 direct = CHECK_FLAG('d');

--- 262 unchanged lines hidden (view full) ---

955/*****************************************************************************
956 * Entry points
957 */
958
959/*
960 * Retrieve and stat a file by HTTP
961 */
962FILE *
963fetchXGetHTTP(struct url *URL, struct url_stat *us, char *flags)
963fetchXGetHTTP(struct url *URL, struct url_stat *us, const char *flags)
964{
965 return _http_request(URL, "GET", us, _http_get_proxy(), flags);
966}
967
968/*
969 * Retrieve a file by HTTP
970 */
971FILE *
964{
965 return _http_request(URL, "GET", us, _http_get_proxy(), flags);
966}
967
968/*
969 * Retrieve a file by HTTP
970 */
971FILE *
972fetchGetHTTP(struct url *URL, char *flags)
972fetchGetHTTP(struct url *URL, const char *flags)
973{
974 return fetchXGetHTTP(URL, NULL, flags);
975}
976
977/*
978 * Store a file by HTTP
979 */
980FILE *
973{
974 return fetchXGetHTTP(URL, NULL, flags);
975}
976
977/*
978 * Store a file by HTTP
979 */
980FILE *
981fetchPutHTTP(struct url *URL, char *flags)
981fetchPutHTTP(struct url *URL, const char *flags)
982{
983 warnx("fetchPutHTTP(): not implemented");
984 return NULL;
985}
986
987/*
988 * Get an HTTP document's metadata
989 */
990int
982{
983 warnx("fetchPutHTTP(): not implemented");
984 return NULL;
985}
986
987/*
988 * Get an HTTP document's metadata
989 */
990int
991fetchStatHTTP(struct url *URL, struct url_stat *us, char *flags)
991fetchStatHTTP(struct url *URL, struct url_stat *us, const char *flags)
992{
993 FILE *f;
994
995 if ((f = _http_request(URL, "HEAD", us, _http_get_proxy(), flags)) == NULL)
996 return -1;
997 fclose(f);
998 return 0;
999}
1000
1001/*
1002 * List a directory
1003 */
1004struct url_ent *
992{
993 FILE *f;
994
995 if ((f = _http_request(URL, "HEAD", us, _http_get_proxy(), flags)) == NULL)
996 return -1;
997 fclose(f);
998 return 0;
999}
1000
1001/*
1002 * List a directory
1003 */
1004struct url_ent *
1005fetchListHTTP(struct url *url, char *flags)
1005fetchListHTTP(struct url *url, const char *flags)
1006{
1007 warnx("fetchListHTTP(): not implemented");
1008 return NULL;
1009}
1006{
1007 warnx("fetchListHTTP(): not implemented");
1008 return NULL;
1009}