- 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