]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
FTP REST support
authorwessels <>
Wed, 20 Jan 1999 04:40:39 +0000 (04:40 +0000)
committerwessels <>
Wed, 20 Jan 1999 04:40:39 +0000 (04:40 +0000)
src/HttpHdrRange.cc
src/ftp.cc
src/protos.h

index b9472a0aef9b1d1ff992e741f0c490703d8b5faa..0ee9f847c3cdac34ad14487f4548163a757d6635 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHdrRange.cc,v 1.17 1998/12/05 00:54:10 wessels Exp $
+ * $Id: HttpHdrRange.cc,v 1.18 1999/01/19 21:40:39 wessels Exp $
  *
  * DEBUG: section 64    HTTP Range Header
  * AUTHOR: Alex Rousskov
@@ -409,21 +409,49 @@ httpHdrRangeWillBeComplex(const HttpHdrRange * range)
     return 0;
 }
 
-/* hack: returns offset of first range spec */
+/* Returns lowest known offset in range spec(s), or range_spec_unknown */
+/* this is used for size limiting */
 size_t
 httpHdrRangeFirstOffset(const HttpHdrRange * range)
 {
+    size_t offset = range_spec_unknown;
     HttpHdrRangePos pos = HttpHdrRangeInitPos;
     const HttpHdrRangeSpec *spec;
     assert(range);
     while ((spec = httpHdrRangeGetSpec(range, &pos))) {
-       if (!known_spec(spec->offset))  /* ignore unknowns */
-           continue;
-       return spec->offset;
+       if (spec->offset < offset || !known_spec(offset))
+           offset = spec->offset;
     }
-    return 0;
+    return offset;
 }
 
+/* Returns lowest offset in range spec(s), 0 if unknown */
+/* This is used for finding out where we need to start if all
+ * ranges are combined into one, for example FTP REST.
+ * Use 0 for size if unknown
+ */
+size_t
+httpHdrRangeLowestOffset(const HttpHdrRange * range, size_t size)
+{
+    size_t offset = range_spec_unknown;
+    size_t current;
+    HttpHdrRangePos pos = HttpHdrRangeInitPos;
+    const HttpHdrRangeSpec *spec;
+    assert(range);
+    while ((spec = httpHdrRangeGetSpec(range, &pos))) {
+       current = spec->offset;
+       if (!known_spec(current)) {
+           if (spec->length > size || !known_spec(spec->length))
+               return 0; /* Unknown. Assume start of file */
+           current = size - spec->length;
+       }
+       if (current < offset || !known_spec(offset))
+           offset = current;
+    }
+    return known_spec(offset) ? offset : 0;
+}
+
+
 /* generates a "unique" boundary string for multipart responses
  * the caller is responsible for cleaning the string */
 String
index 5328985f4af07f64e52d495506dfb9b60823f259..806c6a95b23b099ce173f491d0fac8e216470c27 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.cc,v 1.267 1999/01/19 02:24:25 wessels Exp $
+ * $Id: ftp.cc,v 1.268 1999/01/19 21:40:40 wessels Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -50,9 +50,7 @@ typedef enum {
     SENT_CWD,
     SENT_LIST,
     SENT_NLST,
-#if RESTART_UNSUPPORTED
     SENT_REST,
-#endif
     SENT_RETR,
     SENT_STOR,
     SENT_QUIT,
@@ -97,9 +95,8 @@ typedef struct _Ftpdata {
     int size;
     wordlist *pathcomps;
     char *filepath;
-#if RESTART_UNSUPPORTED
     int restart_offset;
-#endif
+    int restarted_offset;
     int rest_att;
     char *proxy_host;
     size_t list_width;
@@ -155,6 +152,7 @@ static PF ftpReadControlReply;
 static CWCB ftpWriteCommandCallback;
 static void ftpLoginParser(const char *, FtpStateData *, int escaped);
 static wordlist *ftpParseControlReply(char *, size_t, int *, int *);
+static int ftpRestartable(FtpStateData * ftpState);
 static void ftpAppendSuccessHeader(FtpStateData * ftpState);
 static void ftpAuthRequired(HttpReply * reply, request_t * request, const char *realm);
 static void ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState);
@@ -193,10 +191,8 @@ static FTPSM ftpReadCwd;
 static FTPSM ftpSendList;
 static FTPSM ftpSendNlst;
 static FTPSM ftpReadList;
-#if RESTART_UNSUPPORTED
 static FTPSM ftpSendRest;
 static FTPSM ftpReadRest;
-#endif
 static FTPSM ftpSendRetr;
 static FTPSM ftpReadRetr;
 static FTPSM ftpReadTransferDone;
@@ -248,9 +244,7 @@ FTPSM *FTP_SM_FUNCS[] =
     ftpReadCwd,
     ftpReadList,               /* SENT_LIST */
     ftpReadList,               /* SENT_NLST */
-#if RESTART_UNSUPPORTED
     ftpReadRest,
-#endif
     ftpReadRetr,
     ftpReadStor,
     ftpReadQuit,
@@ -1395,6 +1389,8 @@ ftpSendType(FtpStateData * ftpState)
     }
     if (mode == 'I')
        ftpState->flags.binary = 1;
+    else
+       ftpState->flags.binary = 0;
     snprintf(cbuf, 1024, "TYPE %c\r\n", mode);
     ftpWriteCommand(cbuf, ftpState);
     ftpState->state = SENT_TYPE;
@@ -1860,10 +1856,8 @@ ftpRestOrList(FtpStateData * ftpState)
        ftpState->flags.use_base = 1;
     } else if (ftpState->flags.isdir)
        ftpSendList(ftpState);
-#if RESTART_UNSUPPORTED
-    else if (ftpState->restart_offset > 0)
+    else if (ftpRestartable(ftpState))
        ftpSendRest(ftpState);
-#endif
     else
        ftpSendRetr(ftpState);
 }
@@ -1903,7 +1897,6 @@ ftpReadStor(FtpStateData * ftpState)
     }
 }
 
-#if RESTART_UNSUPPORTED
 static void
 ftpSendRest(FtpStateData * ftpState)
 {
@@ -1912,6 +1905,24 @@ ftpSendRest(FtpStateData * ftpState)
     ftpState->state = SENT_REST;
 }
 
+static int
+ftpRestartable(FtpStateData * ftpState)
+{
+    if (ftpState->restart_offset > 0)
+       return 1;
+    if (!ftpState->request->range)
+       return 0;
+    if (!ftpState->flags.binary)
+       return 0;
+    if (ftpState->size <= 0)
+       return 0;
+
+    ftpState->restart_offset = httpHdrRangeLowestOffset(ftpState->request->range, (size_t) ftpState->size);
+    if (ftpState->restart_offset <= 0)
+       return 0;
+    return 1;
+}
+
 static void
 ftpReadRest(FtpStateData * ftpState)
 {
@@ -1919,6 +1930,7 @@ ftpReadRest(FtpStateData * ftpState)
     debug(9, 3) ("This is ftpReadRest\n");
     assert(ftpState->restart_offset > 0);
     if (code == 350) {
+       ftpState->restarted_offset = ftpState->restart_offset;
        ftpSendRetr(ftpState);
     } else if (code > 0) {
        debug(9, 3) ("ftpReadRest: REST not supported\n");
@@ -1927,7 +1939,6 @@ ftpReadRest(FtpStateData * ftpState)
        ftpFail(ftpState);
     }
 }
-#endif
 
 static void
 ftpSendList(FtpStateData * ftpState)
@@ -2302,8 +2313,21 @@ ftpAppendSuccessHeader(FtpStateData * ftpState)
     storeBuffer(e);
     httpReplyReset(reply);
     /* set standard stuff */
-    httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying",
-       mime_type, ftpState->size, ftpState->mdtm, -2);
+    if (ftpState->restarted_offset) {
+       /* Partial reply */
+       HttpHdrRangeSpec range_spec =
+       {
+           ftpState->restarted_offset,
+           ftpState->size - ftpState->restarted_offset
+       };
+       httpReplySetHeaders(reply, 1.0, HTTP_PARTIAL_CONTENT, "Gatewaying",
+           mime_type, ftpState->size - ftpState->restarted_offset, ftpState->mdtm, -2);
+       httpHeaderAddContRange(&reply->header, range_spec, ftpState->size);
+    } else {
+       /* Full reply */
+       httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying",
+           mime_type, ftpState->size, ftpState->mdtm, -2);
+    }
     /* additional info */
     if (mime_enc)
        httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc);
@@ -2320,7 +2344,7 @@ ftpAppendSuccessHeader(FtpStateData * ftpState)
        if (pe)
            storeRelease(pe);
        storeRelease(e);
-    } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
+    } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) {
        storeSetPublicKey(e);
     } else {
        storeRelease(e);
index c1b6990edfb8f6cc34d826074dab3bf5013ead3a..c9d776fa9e3db663a652852710d28ac6f2336ff7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.306 1999/01/19 17:41:03 wessels Exp $
+ * $Id: protos.h,v 1.307 1999/01/19 21:40:42 wessels Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -332,6 +332,7 @@ extern String httpHdrRangeBoundaryStr(clientHttpRequest * http);
 extern int httpHdrRangeIsComplex(const HttpHdrRange * range);
 extern int httpHdrRangeWillBeComplex(const HttpHdrRange * range);
 extern size_t httpHdrRangeFirstOffset(const HttpHdrRange * range);
+extern size_t httpHdrRangeLowestOffset(const HttpHdrRange * range, size_t size);
 
 
 /* Http Content Range Header Field */