Revised patch.

This version properly handles:

  ftp -C http://myfile.txt

* when the local file exists, and is zero length
* when the local file does not exist


Index: fetch.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.97
diff -u fetch.c
--- fetch.c     16 Oct 2009 12:28:04 -0000      1.97
+++ fetch.c     13 Jan 2010 00:17:43 -0000
@@ -552,7 +552,7 @@
 #endif /* !SMALL */

        if (verbose)
-               fprintf(ttyout, "Requesting %s", origline);
+               fprintf(ttyout, "Requesting %s%s", origline, debug ? "\n" : "");

        /*
         * Construct and send the request. Proxy requests don't want leading /.
@@ -590,11 +590,8 @@
                                restart_point = 0;
                }
 #endif /* !SMALL */
-               ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath,
-#ifndef SMALL
-                       restart_point ? "HTTP/1.1" :
-#endif /* !SMALL */
-                       "HTTP/1.0");
+               /* The "Host" header is only valid for HTTP 1.1 */
+               ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, "HTTP/1.1");
                if (strchr(host, ':')) {
                        char *h, *p;

@@ -627,6 +624,11 @@
                if (port && strcmp(port, "80") != 0)
                        ftp_printf(fin, ssl, ":%s", port);
 #endif /* !SMALL */
+               /* "Connection: close" is required by RFC2616.  It also
+                  prevents a 15 second delay whilst the client and the server
+                   both wait for the other to sever the connection (after the
+                   data has finished streaming.) */
+               ftp_printf(fin, ssl, "\r\nConnection: close");
                ftp_printf(fin, ssl, "\r\n%s%s\r\n\r\n",
                    buf ? buf : "", HTTP_USER_AGENT);
                if (verbose)
@@ -670,6 +672,17 @@

        switch (status) {
        case 200:       /* OK */
+               /* When we request a partial file, and we receive an HTTP 200
+                   it is a good indication that the httpd doesn't support
+ range requests, and is about to send us the entire file. + This is at least the case with Apache 1.3.29. + If the restart_point == 0, then we are not actually
+                   a partial file, and an HTTP 200 is appropriate.
+               */
+               if (resume && 0 != restart_point) {
+                       warnx("Server lacks file transfer continuation 
support.");
+                       goto cleanup_url_get;
+               }
 #ifndef SMALL
        case 206:       /* Partial Content */
 #endif /* !SMALL */
@@ -1317,13 +1330,16 @@

        va_start(ap, fmt);

-       if (fp != NULL)
+       if (fp != NULL) {
+               /* Show the HTTP request when in debug mode. */
+               if (debug)
+                       vprintf(fmt, ap);
                ret = vfprintf(fp, fmt, ap);
 #ifndef SMALL
-       else if (ssl != NULL)
+       } else if (ssl != NULL) {
                ret = SSL_vprintf((SSL*)ssl, fmt, ap);
 #endif /* !SMALL */
-       else
+       } else
                ret = 0;

        va_end(ap);




On Tue, 12 Jan 2010, Matthew Mulrooney wrote:


Hi,

Here's a patch for a couple of issues with ftp(1):

Servers that don't support content ranges ========================================= Currently, performing "ftp -C" against a server that doesn't support content ranges (which includes Apache 1.3), will redownload the entire file, and append the entire contents onto the existing file.

So, if we have "myfile.txt" that is 200 bytes long (on the server), and it already exists on the filesystem, but it is only 100 bytes long, performing:

 ftp -C http://localhost/myfile.txt

will result in a local file that is 300 bytes long.

HTTP 1.0 and the Host header
============================
The Host header didn't appear until the HTTP 1.1 spec, but we are using it with HTTP 1.0 requests: * I don't know if there are any httpds that actually care. * Wget uses HTTP 1.0 with Host headers.
* Curl uses HTTP 1.1 with Host headers (gets it right?)

Connection: close
=================
According to:

 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10

"HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message."


Thoughts?

---
Matthew Mulrooney
Teamify - Team Management Simplified - http://www.teamify.com
---



Index: fetch.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.97
diff -u fetch.c
--- fetch.c     16 Oct 2009 12:28:04 -0000      1.97
+++ fetch.c     12 Jan 2010 23:11:17 -0000
@@ -552,7 +552,7 @@
#endif /* !SMALL */

       if (verbose)
-               fprintf(ttyout, "Requesting %s", origline);
+ fprintf(ttyout, "Requesting %s%s", origline, debug ? "\n" : "");

       /*
* Construct and send the request. Proxy requests don't want leading /.
@@ -590,11 +590,8 @@
                               restart_point = 0;
               }
#endif /* !SMALL */
-               ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath,
-#ifndef SMALL
-                       restart_point ? "HTTP/1.1" :
-#endif /* !SMALL */
-                       "HTTP/1.0");
+               /* The "Host" header is only valid for HTTP 1.1 */
+ ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, "HTTP/1.1");
               if (strchr(host, ':')) {
                       char *h, *p;

@@ -627,6 +624,11 @@
               if (port && strcmp(port, "80") != 0)
                       ftp_printf(fin, ssl, ":%s", port);
#endif /* !SMALL */
+               /* "Connection: close" is required by RFC2616.  It also
+ prevents a 15 second delay whilst the client and the server + both wait for the other to sever the connection (after the
+                   data has finished streaming.) */
+               ftp_printf(fin, ssl, "\r\nConnection: close");
               ftp_printf(fin, ssl, "\r\n%s%s\r\n\r\n",
                   buf ? buf : "", HTTP_USER_AGENT);
               if (verbose)
@@ -670,6 +672,10 @@

       switch (status) {
       case 200:       /* OK */
+               if (resume) {
+ warnx("Server lacks file transfer continuation support.");
+                       goto cleanup_url_get;
+               }
#ifndef SMALL
       case 206:       /* Partial Content */
#endif /* !SMALL */
@@ -1317,13 +1323,16 @@

       va_start(ap, fmt);

-       if (fp != NULL)
+       if (fp != NULL) {
+               /* Show the HTTP request when in debug mode. */
+               if (debug)
+                       vprintf(fmt, ap);
               ret = vfprintf(fp, fmt, ap);
#ifndef SMALL
-       else if (ssl != NULL)
+       } else if (ssl != NULL) {
               ret = SSL_vprintf((SSL*)ssl, fmt, ap);
#endif /* !SMALL */
-       else
+       } else
               ret = 0;

       va_end(ap);









---
Matthew Mulrooney
Teamify - Team Management Simplified - http://www.teamify.com
---

Reply via email to