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} |