- From: Richard Atterer <richard@list03.atterer.net>
- Date: Thu, 13 Feb 2003 16:47:48 +0100
- To: www-lib@w3.org
On Wed, Feb 12, 2003 at 06:34:29PM +0100, Richard Atterer wrote:
> The bad news first: AFAICT libwww doesn't support FTP resumes (REST
> command) at all. :-( Maybe I'll come up with a patch.
Yes, here it is! Again, to apply it, pipe this mail into
patch -d somepath/w3c-libwww-5.4.0/Library/src
It will apply with or without the previous patch, although there may be a
few "Hunk succeeded at offset -10 lines" messages.
Jose/anybody, please apply this, I consider it a quite important feature!
Cheers,
Richard
--
__ _
|_) /| Richard Atterer | CS student at the Technische | GnuPG key:
| \/¯| http://atterer.net | Universität München, Germany | 0x888354F7
¯ '` ¯
--- HTFTP.h.orig 2003-01-13 18:12:46.000000000 +0100
+++ HTFTP.h 2003-02-13 16:33:53.000000000 +0100
@@ -24,6 +24,13 @@
a part of the W3C
Sample Code Library.
+The module supports partial downloads by using the FTP "REST" command. To
+initiate such a partial request, proceed the same way as with an HTTP
+request; use something like HTRequest_addRange(request, "bytes", "12345-").
+HTFTP only supports ranges without an end offset, a range like "12345-20000"
+will be ignored. If the "REST" command was successful, an appropriate range
+entry is added to the request's response object.
+
*/
#ifndef HTFTP_H
--- HTFTP.c.orig 2003-02-12 17:39:04.000000000 +0100
+++ HTFTP.c 2003-02-13 00:23:46.000000000 +0100
@@ -55,6 +55,7 @@
** Jan 2000 JB Joe Bester - Fixed the protocol bug that appeared after
** after the CERT advisory warning on wu. Added code
** to do an incremental streaming of FTP data.
+** Feb 2003 Richard Atterer - added REST support
**
** Notes:
** Portions Copyright 1994 Trustees of Dartmouth College
@@ -1093,6 +1094,7 @@
NEED_SELECT = 0,
NEED_CONNECT,
NEED_ACCEPT,
+ NEED_REST,
NEED_ACTION,
NEED_CWD,
NEED_SEGMENT,
@@ -1105,7 +1107,7 @@
switch ((state) ctrl->substate) {
case NEED_SELECT:
HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_SELECT\n");
- ctrl->substate = data->pasv ? NEED_CONNECT : NEED_ACTION;
+ ctrl->substate = data->pasv ? NEED_CONNECT : NEED_REST;
break;
case NEED_CONNECT:
@@ -1116,7 +1118,7 @@
else if (status == HT_OK) {
HTTRACE(PROT_TRACE, "FTP Get Data Active data socket %d\n" _
HTNet_socket(dnet));
- ctrl->substate = NEED_ACTION;
+ ctrl->substate = NEED_REST;
} else { /* Swap to PORT on the fly */
NETCLOSE(HTNet_socket(dnet));
HTNet_setSocket(dnet, INVSOC);
@@ -1140,6 +1142,67 @@
ctrl->substate = SUB_ERROR;
break;
+ case NEED_REST:
+ HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_REST\n");
+ if (!ctrl->sent) {
+ ctrl->substate = NEED_ACTION;
+ /* If the user added a Range header to the request and that
+ header is a single "from offset x to the end", transform
+ that into a REST command. */
+ HTAssocList* ranges = HTRequest_range(request);
+ HTAssoc* r1, * r2;
+ const char* rangeVal, * s;
+ int len = 0;
+ char* chunkData;
+ HTStream* input;
+
+ /* Do nothing unless exactly one range item present. */
+ if (ranges == 0) break;
+ r1 = HTAssocList_nextObject(ranges);
+ if (r1 == 0) break;
+ r2 = HTAssocList_nextObject(ranges);
+ if (r2 != 0) break;
+ /* Do nothing unless assoc reads: "bytes" => "12345-" */
+ if (strcmp(HTAssoc_name(r1), "bytes") != 0) break;
+ rangeVal = HTAssoc_value(r1);
+ s = rangeVal;
+ if (*s < '0' || *s > '9') break;
+ while (*++s >= '0' && *s <= '9') len += *s - '0';
+ if (*s != '-' || s[1] != '\0' || len == 0) break;
+
+ /* send: "REST 12345" */
+ len = 4 + 1 + (s - rangeVal) + 2;
+ HTChunk_setSize(ctrl->cmd, len + 1);
+ chunkData = HTChunk_data(ctrl->cmd);
+ sprintf(chunkData, "REST %s%c", rangeVal, LF);
+ chunkData[len - 2] = CR; /* Overwrite '-' */
+ input = HTRequest_inputStream(request);
+ HTTRACE(PROT_TRACE, "FTP Get Data Tx...... %s" _ chunkData);
+ status = (*input->isa->put_block)(input, chunkData, len);
+ if (status == HT_WOULD_BLOCK)
+ return HT_WOULD_BLOCK;
+ else if (status == HT_ERROR)
+ ctrl->substate = SUB_ERROR;
+ ctrl->sent = YES;
+ ctrl->substate = NEED_REST; /* Wait for reply */
+ } else {
+ status = HTHost_read(HTNet_host(cnet), cnet);
+ if (status == HT_WOULD_BLOCK) {
+ return HT_WOULD_BLOCK;
+ } else if (status == HT_LOADED && ctrl->repcode == 350) {
+ /* Add appropriate range header to response object */
+ HTResponse* resp = HTRequest_response(request);
+ HTAssocList* ranges = HTRequest_range(request);
+ HTAssoc* r1 = HTAssocList_nextObject(ranges);
+ HTResponse_addRange(resp, "bytes", HTAssoc_value(r1));
+ ctrl->substate = NEED_ACTION;
+ } else {
+ ctrl->substate = SUB_ERROR;
+ }
+ ctrl->sent = NO;
+ }
+ break;
+
case NEED_ACTION:
HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_ACTION\n");
if (!ctrl->sent) {
@@ -1202,7 +1265,7 @@
HTCleanTelnetString(segment);
ctrl->substate = NEED_CWD;
} else
- ctrl->substate = NEED_ACTION;
+ ctrl->substate = NEED_REST;
}
}
break;
Received on Thursday, 13 February 2003 14:46:07 UTC