From 6d7fa438a7dc33b20de746e31b5e8078c53c4d05 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 10 Apr 2001 18:17:05 +0000 Subject: [PATCH] This patch from Laurence Anderson fixes wget HTTP 1.1 support and addes chunked encoding so bb wget is now fully RFC compliant. --- Changelog | 20 +++++++++++--------- docs/busybox.pod | 3 ++- networking/wget.c | 47 ++++++++++++++++++++++++++++++----------------- wget.c | 47 ++++++++++++++++++++++++++++++----------------- 4 files changed, 73 insertions(+), 44 deletions(-) diff --git a/Changelog b/Changelog index 4adc7746c..296106d49 100644 --- a/Changelog +++ b/Changelog @@ -22,6 +22,8 @@ * Erik Andersen -- Cleanups for libc5, glibc, and uClibc. * Erik Andersen and Matt Kraai -- Cleanups for the human-readable output from ls, du, and df. + * Laurence Anderson -- Fixed wget HTTP 1.1 + support and added chunked encoding so it is now RFC compliant. * John Beppu -- The busybox.pod documentation is now automagically generated from the source code. This makes it _much_ simpler. Now to update the docs, just update the usage message... @@ -51,6 +53,7 @@ * Vladimir Oleynik -- More cmdedit updates * Vladimir Oleynik -- Fixed `du' applet so it continues running after permission errors. + * Vladimir Oleynik -- Reduced stack usage in recursive_action() * Pierre Peiffer -- made find_pid_by_name() cope with swapped out processes. * Jari Ruusu -- updates so that setting @@ -58,13 +61,12 @@ * Anthony Towns -- fixed a bug with sed address range handling * Dmitry Zakharov -- a number of updates - to wget: support for ftp downloads, basic HTTP basic auth, - handling of http redirects, protocol changed to 1.0 to stop - servers from requesting chunked encoding, when attempting to - continue an aborted download but server doesn't support restarts - then reopen output file in write mode, bugfix: when content-length - not given, wget didn't download anything, if -c is not specified, - it no longer default to restarting an aborted download. + to wget: support for ftp downloads, basic HTTP basic auth, handling + of http redirects, when attempting to continue an aborted download + but server doesn't support restarts then reopen output file in + write mode, bugfix: when content-length not given, wget didn't + download anything, if -c is not specified, it no longer default to + restarting an aborted download. -Erik Andersen, not yet released @@ -76,8 +78,8 @@ * Erik Andersen -- lash environment variable expansion rewritten, with lots of help/fixes/testing from Larry Doolittle. * Erik Andersen -- Fix use of busybox with dmalloc debugging lib - * Erik Andersen -- fixed ls behavior for broken or very narrow terminals. - * Erik Andersen -- stub umount2 and pivot_root if they are not available. + * Erik Andersen -- fixed ls behavior for broken or very narrow terminals + * Erik Andersen -- stub umount2 and pivot_root if they are not available * Erik Andersen -- libc5 fixes * Erik Andersen -- make init work with devfsd * Erik Andersen -- fixed df for nfs and dos where blksize = 512 diff --git a/docs/busybox.pod b/docs/busybox.pod index ca3ce97b5..8e8a5492d 100644 --- a/docs/busybox.pod +++ b/docs/busybox.pod @@ -770,6 +770,7 @@ Options: -H prefix output lines with filename where match was found -h suppress the prefixing filename on output -i ignore case distinctions + -l list names of files that match -n print line number with output lines -q be quiet. Returns 0 if result was found, 1 otherwise -v select non-matching lines @@ -2536,4 +2537,4 @@ Enrique Zanardi =cut -# $Id: busybox.pod,v 1.99 2001/04/10 00:00:05 kraai Exp $ +# $Id: busybox.pod,v 1.100 2001/04/10 18:17:05 andersen Exp $ diff --git a/networking/wget.c b/networking/wget.c index 5bec0ddd5..79f7e61cf 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -4,14 +4,6 @@ * * Chip Rosenthal Covad Communications * - * Note: According to RFC2616 section 3.6.1, "All HTTP/1.1 applications MUST be - * able to receive and decode the "chunked" transfer-coding, and MUST ignore - * chunk-extension extensions they do not understand." - * - * This prevents this particular wget app from completely RFC compliant, and as - * such, prevents it from being used as a general purpose web browser... This - * is a design decision, since it makes the code smaller. - * */ #include @@ -63,6 +55,7 @@ static void progressmeter(int flag); /* Globals (can be accessed from signal handlers */ static off_t filesize = 0; /* content-length of the file */ +static int chunked = 0; /* chunked transfer encoding */ #ifdef BB_FEATURE_WGET_STATUSBAR static char *curfile; /* Name of current file being transferred. */ static struct timeval start; /* Time a transfer started. */ @@ -231,11 +224,11 @@ int wget_main(int argc, char **argv) * Send HTTP request. */ if (proxy) { - fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.0\r\n", + fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.1\r\n", target.is_ftp ? "f" : "ht", target.host, target.port, target.path); } else { - fprintf(sfp, "GET /%s HTTP/1.0\r\n", target.path); + fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path); } fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host); @@ -258,7 +251,7 @@ int wget_main(int argc, char **argv) /* * Retrieve HTTP response line and check for "200" status code. */ - if (fgets(buf, sizeof(buf), sfp) == NULL) +read_response: if (fgets(buf, sizeof(buf), sfp) == NULL) close_delete_and_die("no response from server"); for (s = buf ; *s != '\0' && !isspace(*s) ; ++s) @@ -267,6 +260,9 @@ int wget_main(int argc, char **argv) ; switch (status = atoi(s)) { case 0: + case 100: + while (gethdr(buf, sizeof(buf), sfp, &n) != NULL); + goto read_response; case 200: if (do_continue && output != stdout) output = freopen(fname_out, "w", output); @@ -295,9 +291,13 @@ int wget_main(int argc, char **argv) got_clen = 1; continue; } - if (strcasecmp(buf, "transfer-encoding") == 0) + if (strcasecmp(buf, "transfer-encoding") == 0) { + if (strcasecmp(s, "chunked") == 0) { + chunked = got_clen = 1; + } else { close_delete_and_die("server wants to do %s transfer encoding", s); - + } + } if (strcasecmp(buf, "location") == 0) { if (s[0] == '/') target.path = xstrdup(s+1); @@ -386,12 +386,17 @@ int wget_main(int argc, char **argv) /* * Retrieve file */ + if (chunked) { + fgets(buf, sizeof(buf), dfp); + filesize = strtol(buf, (char **) NULL, 16); + } + do { #ifdef BB_FEATURE_WGET_STATUSBAR statbytes=0; if (quiet_flag==FALSE) progressmeter(-1); #endif - while ((filesize > 0 || !got_clen) && (n = fread(buf, 1, sizeof(buf), dfp)) > 0) { + while ((filesize > 0 || !got_clen) && (n = fread(buf, 1, chunked ? (filesize > sizeof(buf) ? sizeof(buf) : filesize) : sizeof(buf), dfp)) > 0) { fwrite(buf, 1, n, output); #ifdef BB_FEATURE_WGET_STATUSBAR statbytes+=n; @@ -402,8 +407,16 @@ int wget_main(int argc, char **argv) filesize -= n; } + if (chunked) { + fgets(buf, sizeof(buf), dfp); /* This is a newline */ + fgets(buf, sizeof(buf), dfp); + filesize = strtol(buf, (char **) NULL, 16); + if (filesize==0) chunked = 0; /* all done! */ + } + if (n == 0 && ferror(dfp)) perror_msg_and_die("network read error"); + } while (chunked); if (!proxy && target.is_ftp) { fclose(dfp); @@ -411,7 +424,7 @@ int wget_main(int argc, char **argv) error_msg_and_die("ftp error: %s", buf+4); ftpcmd("QUIT", NULL, sfp, buf); } - + printf("\n"); exit(EXIT_SUCCESS); } @@ -608,7 +621,7 @@ progressmeter(int flag) (void) gettimeofday(&now, (struct timezone *) 0); cursize = statbytes; - if (filesize != 0) { + if (filesize != 0 && !chunked) { ratio = 100.0 * cursize / filesize; ratio = MAX(ratio, 0); ratio = MIN(ratio, 100); @@ -719,7 +732,7 @@ progressmeter(int flag) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: wget.c,v 1.31 2001/04/05 21:45:53 andersen Exp $ + * $Id: wget.c,v 1.32 2001/04/10 18:17:05 andersen Exp $ */ diff --git a/wget.c b/wget.c index 5bec0ddd5..79f7e61cf 100644 --- a/wget.c +++ b/wget.c @@ -4,14 +4,6 @@ * * Chip Rosenthal Covad Communications * - * Note: According to RFC2616 section 3.6.1, "All HTTP/1.1 applications MUST be - * able to receive and decode the "chunked" transfer-coding, and MUST ignore - * chunk-extension extensions they do not understand." - * - * This prevents this particular wget app from completely RFC compliant, and as - * such, prevents it from being used as a general purpose web browser... This - * is a design decision, since it makes the code smaller. - * */ #include @@ -63,6 +55,7 @@ static void progressmeter(int flag); /* Globals (can be accessed from signal handlers */ static off_t filesize = 0; /* content-length of the file */ +static int chunked = 0; /* chunked transfer encoding */ #ifdef BB_FEATURE_WGET_STATUSBAR static char *curfile; /* Name of current file being transferred. */ static struct timeval start; /* Time a transfer started. */ @@ -231,11 +224,11 @@ int wget_main(int argc, char **argv) * Send HTTP request. */ if (proxy) { - fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.0\r\n", + fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.1\r\n", target.is_ftp ? "f" : "ht", target.host, target.port, target.path); } else { - fprintf(sfp, "GET /%s HTTP/1.0\r\n", target.path); + fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path); } fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host); @@ -258,7 +251,7 @@ int wget_main(int argc, char **argv) /* * Retrieve HTTP response line and check for "200" status code. */ - if (fgets(buf, sizeof(buf), sfp) == NULL) +read_response: if (fgets(buf, sizeof(buf), sfp) == NULL) close_delete_and_die("no response from server"); for (s = buf ; *s != '\0' && !isspace(*s) ; ++s) @@ -267,6 +260,9 @@ int wget_main(int argc, char **argv) ; switch (status = atoi(s)) { case 0: + case 100: + while (gethdr(buf, sizeof(buf), sfp, &n) != NULL); + goto read_response; case 200: if (do_continue && output != stdout) output = freopen(fname_out, "w", output); @@ -295,9 +291,13 @@ int wget_main(int argc, char **argv) got_clen = 1; continue; } - if (strcasecmp(buf, "transfer-encoding") == 0) + if (strcasecmp(buf, "transfer-encoding") == 0) { + if (strcasecmp(s, "chunked") == 0) { + chunked = got_clen = 1; + } else { close_delete_and_die("server wants to do %s transfer encoding", s); - + } + } if (strcasecmp(buf, "location") == 0) { if (s[0] == '/') target.path = xstrdup(s+1); @@ -386,12 +386,17 @@ int wget_main(int argc, char **argv) /* * Retrieve file */ + if (chunked) { + fgets(buf, sizeof(buf), dfp); + filesize = strtol(buf, (char **) NULL, 16); + } + do { #ifdef BB_FEATURE_WGET_STATUSBAR statbytes=0; if (quiet_flag==FALSE) progressmeter(-1); #endif - while ((filesize > 0 || !got_clen) && (n = fread(buf, 1, sizeof(buf), dfp)) > 0) { + while ((filesize > 0 || !got_clen) && (n = fread(buf, 1, chunked ? (filesize > sizeof(buf) ? sizeof(buf) : filesize) : sizeof(buf), dfp)) > 0) { fwrite(buf, 1, n, output); #ifdef BB_FEATURE_WGET_STATUSBAR statbytes+=n; @@ -402,8 +407,16 @@ int wget_main(int argc, char **argv) filesize -= n; } + if (chunked) { + fgets(buf, sizeof(buf), dfp); /* This is a newline */ + fgets(buf, sizeof(buf), dfp); + filesize = strtol(buf, (char **) NULL, 16); + if (filesize==0) chunked = 0; /* all done! */ + } + if (n == 0 && ferror(dfp)) perror_msg_and_die("network read error"); + } while (chunked); if (!proxy && target.is_ftp) { fclose(dfp); @@ -411,7 +424,7 @@ int wget_main(int argc, char **argv) error_msg_and_die("ftp error: %s", buf+4); ftpcmd("QUIT", NULL, sfp, buf); } - + printf("\n"); exit(EXIT_SUCCESS); } @@ -608,7 +621,7 @@ progressmeter(int flag) (void) gettimeofday(&now, (struct timezone *) 0); cursize = statbytes; - if (filesize != 0) { + if (filesize != 0 && !chunked) { ratio = 100.0 * cursize / filesize; ratio = MAX(ratio, 0); ratio = MIN(ratio, 100); @@ -719,7 +732,7 @@ progressmeter(int flag) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: wget.c,v 1.31 2001/04/05 21:45:53 andersen Exp $ + * $Id: wget.c,v 1.32 2001/04/10 18:17:05 andersen Exp $ */