From: Amos Jeffries Date: Sun, 18 Jan 2009 04:59:55 +0000 (+1300) Subject: Remove FTP listing experiment. Will continue in other branch X-Git-Tag: SQUID_3_2_0_1~1255^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=581aba778c3b49f3a45538496c75e6e7fd5501e0;p=thirdparty%2Fsquid.git Remove FTP listing experiment. Will continue in other branch --- diff --git a/src/MemBuf.h b/src/MemBuf.h index 2fff10579e..4da921b3a8 100644 --- a/src/MemBuf.h +++ b/src/MemBuf.h @@ -72,8 +72,8 @@ public: /** * Whether the buffer contains any data space available. - \retval true if data can be added to the buffer - \retval false if the buffer is full + \retval true if data can be added to teh buffer + \retval false if teh buffer is full */ bool hasSpace() const { return size+1 < capacity; } diff --git a/src/cache_cf.cc b/src/cache_cf.cc index ba81de5aa9..c48cceaf2c 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -2475,13 +2475,11 @@ free_time_t(time_t * var) *var = 0; } -#if UNUSED_CODE static void dump_size_t(StoreEntry * entry, const char *name, size_t var) { storeAppendPrintf(entry, "%s %d\n", name, (int) var); } -#endif static void dump_b_size_t(StoreEntry * entry, const char *name, size_t var) @@ -2509,7 +2507,6 @@ dump_kb_int64_t(StoreEntry * entry, const char *name, int64_t var) storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_KBYTES_STR); } -#if UNUSED_CODE static void parse_size_t(size_t * var) { @@ -2517,7 +2514,6 @@ parse_size_t(size_t * var) i = GetInteger(); *var = (size_t) i; } -#endif static void parse_b_size_t(size_t * var) diff --git a/src/cf.data.pre b/src/cf.data.pre index 472a30e9e8..9c55908b85 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2630,6 +2630,16 @@ DOC_START (for example perl.com). DOC_END +NAME: ftp_list_width +TYPE: size_t +DEFAULT: 32 +LOC: Config.Ftp.list_width +DOC_START + Sets the width of ftp listings. This should be set to fit in + the width of a standard browser. Setting this too small + can cut off long filenames when browsing ftp sites. +DOC_END + NAME: ftp_passive TYPE: onoff DEFAULT: on diff --git a/src/enums.h b/src/enums.h index 4e453ecf33..559c0ee8c4 100644 --- a/src/enums.h +++ b/src/enums.h @@ -98,7 +98,6 @@ typedef enum { ERR_ESI, /* Failure to perform ESI processing */ ERR_INVALID_RESP, ERR_ICAP_FAILURE, - ERR_FTP_LISTING, /* Display of FTP remote directory */ ERR_MAX } err_type; diff --git a/src/errorpage.cc b/src/errorpage.cc index 0dfb16520c..848c60042a 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -655,10 +655,7 @@ ErrorState::Convert(char token) case 'g': /* FTP SERVER MESSAGE */ - if(ftp.server_msg) - wordlistCat(ftp.server_msg, &mb); - else if(ftp.listing) - mb.append(ftp.listing->content(), ftp.listing->contentSize()); + wordlistCat(ftp.server_msg, &mb); break; @@ -809,8 +806,6 @@ ErrorState::Convert(char token) case 'z': if (dnsserver_msg) p = dnsserver_msg; - else if (ftp.cwd_msg) - p = ftp.cwd_msg; else p = "[unknown]"; diff --git a/src/errorpage.h b/src/errorpage.h index b1340e7e26..b73564124f 100644 --- a/src/errorpage.h +++ b/src/errorpage.h @@ -136,8 +136,6 @@ public: wordlist *server_msg; char *request; char *reply; - char *cwd_msg; - MemBuf *listing; } ftp; char *request_hdrs; diff --git a/src/ftp.cc b/src/ftp.cc index 9cf90d8946..9ca5faaa12 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -53,7 +53,6 @@ #include "wordlist.h" #include "SquidTime.h" #include "URLScheme.h" -#include "SquidString.h" /** \defgroup ServerProtocolFTPInternal Server-Side FTP Internals @@ -107,12 +106,13 @@ struct _ftp_flags { bool dir_slash; bool root_dir; bool no_dotdot; + bool html_header_sent; bool binary; bool try_slash_hack; bool put; bool put_mkdir; bool listformat_unknown; - bool listing; + bool listing_started; bool completed_forwarding; }; @@ -171,12 +171,11 @@ public: int64_t restarted_offset; char *proxy_host; size_t list_width; - String cwd_message; + wordlist *cwd_message; char *old_request; char *old_reply; char *old_filepath; char typecode; - MemBuf listing; ///< FTP directory listing in HTML format. // \todo: optimize ctrl and data structs member order, to minimize size /// FTP control channel info; the channel is opened once per transaction @@ -213,11 +212,13 @@ public: void failed(err_type, int xerrno); void failedErrorMessage(err_type, int xerrno); void unhack(); + void listingStart(); + void listingFinish(); void scheduleReadControlReply(int); void handleControlReply(); void readStor(); + char *htmlifyListEntry(const char *line); void parseListing(); - MemBuf *htmlifyListEntry(const char *line); void dataComplete(); void dataRead(const CommIoCbParams &io); int checkAuth(const HttpHeader * req_hdr); @@ -489,7 +490,8 @@ FtpStateData::~FtpStateData() if (ctrl.message) wordlistDestroy(&ctrl.message); - cwd_message.clean(); + if (cwd_message) + wordlistDestroy(&cwd_message); safe_free(ctrl.last_reply); @@ -558,12 +560,98 @@ FtpStateData::ftpTimeout(const CommTimeoutCbParams &io) /* failed() closes ctrl.fd and frees ftpState */ } -#if DEAD_CODE // obsoleted by ERR_FTP_LISTING template. void -FtpStateData::listingFinish() +FtpStateData::listingStart() { + debugs(9,3, HERE); + wordlist *w; + char *dirup; + int i, j, k; + const char *title = title_url.buf(); + flags.listing_started = true; + printfReplyBody("\n"); + printfReplyBody("\n", + version_string); + printfReplyBody("\n", mkrfc1123(squid_curtime)); + printfReplyBody("\n"); + { + char *t = xstrdup(title); + rfc1738_unescape(t); + printfReplyBody("FTP Directory: %s\n", html_quote(t)); + xfree(t); + } + + printfReplyBody("\n"); + printfReplyBody("\n"); + + if (flags.need_base_href) + printfReplyBody("\n", + html_quote(base_href.buf())); + + printfReplyBody("\n"); + + if (cwd_message) { + printfReplyBody("
\n");
+
+        for (w = cwd_message; w; w = w->next)
+            printfReplyBody("%s\n", html_quote(w->key));
+
+        printfReplyBody("
\n"); + + printfReplyBody("
\n"); + + wordlistDestroy(&cwd_message); + } + + printfReplyBody("

\n"); + printfReplyBody("FTP Directory: "); + /* "ftp://" == 6 characters */ + assert(title_url.size() >= 6); + k = 6 + strcspn(&title[6], "/"); + + for (i = 6, j = 0; title[i]; j = i) { + printfReplyBody(" j) { + char *url = xstrdup(title); + url[i] = '\0'; + printfReplyBody("%s", html_quote(url + k)); + printfReplyBody("/"); + printfReplyBody("\">"); + rfc1738_unescape(url + j); + printfReplyBody("%s", html_quote(url + j)); + safe_free(url); + printfReplyBody(""); + } -// TODO: figure out what this means and how to show it ... + printfReplyBody("/"); + + if (title[i] == '/') + i++; + + if (i == j) { + /* Error guard, or "assert" */ + printfReplyBody("ERROR: Failed to parse URL: %s\n", + html_quote(title)); + debugs(9, DBG_CRITICAL, "Failed to parse URL: " << title); + break; + } + } + + printfReplyBody("

\n"); + printfReplyBody("
\n");
+    dirup = htmlifyListEntry("");
+    writeReplyBody(dirup, strlen(dirup));
+    flags.html_header_sent = 1;
+}
+
+void
+FtpStateData::listingFinish()
+{
+    debugs(9,3,HERE);
+    entry->buffer();
+    printfReplyBody("
\n"); if (flags.listformat_unknown && !flags.tried_nlst) { printfReplyBody("[As plain directory]\n", @@ -572,8 +660,15 @@ FtpStateData::listingFinish() const char *path = flags.dir_slash ? filepath : "."; printfReplyBody("[As extended directory]\n", rfc1738_escape_part(path)); } + + printfReplyBody("
\n"); + printfReplyBody("
\n"); + printfReplyBody("Generated %s by %s (%s)\n", + mkrfc1123(squid_curtime), + getMyHostname(), + visible_appname_string); + printfReplyBody("
\n"); } -#endif /* DEAD_CODE */ /// \ingroup ServerProtocolFTPInternal static const char *Month[] = { @@ -837,25 +932,47 @@ found: return p; } -MemBuf * +/// \ingroup ServerProtocolFTPInternal +static const char * +dots_fill(size_t len) +{ + static char buf[256]; + size_t i = 0; + + if (len > Config.Ftp.list_width) { + memset(buf, ' ', 256); + buf[0] = '\n'; + buf[Config.Ftp.list_width + 4] = '\0'; + return buf; + } + + for (i = len; i < Config.Ftp.list_width; i++) + buf[i - len] = (i % 2) ? '.' : ' '; + + buf[i - len] = '\0'; + + return buf; +} + +char * FtpStateData::htmlifyListEntry(const char *line) { - char icon[2048]; - char href[2048 + 40]; - char text[ 2048]; - char size[ 2048]; - char chdir[ 2048 + 40]; - char view[ 2048 + 40]; - char download[ 2048 + 40]; - char link[ 2048 + 40]; - MemBuf *html; - char prefix[2048]; + LOCAL_ARRAY(char, icon, 2048); + LOCAL_ARRAY(char, href, 2048 + 40); + LOCAL_ARRAY(char, text, 2048); + LOCAL_ARRAY(char, size, 2048); + LOCAL_ARRAY(char, chdir, 2048 + 40); + LOCAL_ARRAY(char, view, 2048 + 40); + LOCAL_ARRAY(char, download, 2048 + 40); + LOCAL_ARRAY(char, link, 2048 + 40); + LOCAL_ARRAY(char, html, 8192); + LOCAL_ARRAY(char, prefix, 2048); + size_t width = Config.Ftp.list_width; ftpListParts *parts; - *icon = *href = *text = *size = *chdir = *view = *download = *link = '\0'; + *icon = *href = *text = *size = *chdir = *view = *download = *link = *html = '\0'; - if (strlen(line) > 1024) { - html = new MemBuf(); - html->Printf("%s\n", line); + if ((int) strlen(line) > 1024) { + snprintf(html, 8192, "%s\n", line); return html; } @@ -864,10 +981,64 @@ FtpStateData::htmlifyListEntry(const char *line) else prefix[0] = '\0'; + /* Handle builtin */ + if (strcmp(line, "") == 0) { + /* {icon} {text} {link} */ + snprintf(icon, 2048, "\"%-6s\"", + mimeGetIconURL("internal-dirup"), + "[DIRUP]"); + + if (!flags.no_dotdot && !flags.root_dir) { + /* Normal directory */ + + if (!flags.dir_slash) + strcpy(href, "../"); + else + strcpy(href, "./"); + + strcpy(text, "Parent Directory"); + } else if (!flags.no_dotdot && flags.root_dir) { + /* "Top level" directory */ + strcpy(href, "%2e%2e/"); + strcpy(text, "Parent Directory"); + snprintf(link, 2048, "(%s)", + "%2f/", + "Root Directory"); + } else if (flags.no_dotdot && !flags.root_dir) { + char *url; + /* Normal directory where last component is / or .. */ + strcpy(href, "%2e%2e/"); + strcpy(text, "Parent Directory"); + + if (flags.dir_slash) { + url = xstrdup("./"); + } else { + const char *title = title_url.buf(); + int k = 6 + strcspn(&title[6], "/"); + char *t; + url = xstrdup(title + k); + t = url + strlen(url) - 2; + + while (t > url && *t != '/') + *t-- = '\0'; + } + + snprintf(link, 2048, "(%s)", url, "Back"); + safe_free(url); + } else { /* NO_DOTDOT && ROOT_DIR */ + /* "UNIX Root" directory */ + strcpy(href, "/"); + strcpy(text, "Home Directory"); + } + + snprintf(html, 8192, "%s %s %s\n", + href, icon, href, text, link); + return html; + } + if ((parts = ftpListParseParts(line, flags)) == NULL) { const char *p; - html = new MemBuf(); - html->Printf("%s\n", line); + snprintf(html, 8192, "%s\n", line); for (p = line; *p && xisspace(*p); p++); if (*p && !xisspace(*p)) @@ -877,14 +1048,22 @@ FtpStateData::htmlifyListEntry(const char *line) } if (!strcmp(parts->name, ".") || !strcmp(parts->name, "..")) { + *html = '\0'; ftpListPartsFree(&parts); - return NULL; + return html; } parts->size += 1023; parts->size >>= 10; parts->showname = xstrdup(parts->name); + if (!Config.Ftp.list_wrap) { + if (strlen(parts->showname) > width - 1) { + *(parts->showname + width - 1) = '>'; + *(parts->showname + width - 0) = '\0'; + } + } + /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n */ xstrncpy(href, rfc1738_escape_part(parts->name), 2048); @@ -893,21 +1072,21 @@ FtpStateData::htmlifyListEntry(const char *line) switch (parts->type) { case 'd': - snprintf(icon, 2048, "\"%-6s\"", + snprintf(icon, 2048, "\"%-6s\"", mimeGetIconURL("internal-dir"), "[DIR]"); strcat(href, "/"); /* margin is allocated above */ break; case 'l': - snprintf(icon, 2048, "\"%-6s\"", + snprintf(icon, 2048, "\"%-6s\"", mimeGetIconURL("internal-link"), "[LINK]"); /* sometimes there is an 'l' flag, but no "->" link */ if (parts->link) { char *link2 = xstrdup(html_quote(rfc1738_escape(parts->link))); - snprintf(link, 2048, " -> %s", + snprintf(link, 2048, " -> %s", *link2 != '/' ? prefix : "", link2, html_quote(parts->link)); safe_free(link2); @@ -916,11 +1095,11 @@ FtpStateData::htmlifyListEntry(const char *line) break; case '\0': - snprintf(icon, 2048, "\"%-6s\"", + snprintf(icon, 2048, "\"%-6s\"", mimeGetIconURL(parts->name), "[UNKNOWN]"); - snprintf(chdir, 2048, "", + snprintf(chdir, 2048, " ", rfc1738_escape_part(parts->name), mimeGetIconURL("internal-dir")); break; @@ -928,7 +1107,7 @@ FtpStateData::htmlifyListEntry(const char *line) case '-': default: - snprintf(icon, 2048, "\"%-6s\"", + snprintf(icon, 2048, "\"%-6s\"", mimeGetIconURL(parts->name), "[FILE]"); snprintf(size, 2048, " %6"PRId64"k", parts->size); @@ -937,32 +1116,31 @@ FtpStateData::htmlifyListEntry(const char *line) if (parts->type != 'd') { if (mimeGetViewOption(parts->name)) { - snprintf(view, 2048, "", + snprintf(view, 2048, " ", prefix, href, mimeGetIconURL("internal-view")); } if (mimeGetDownloadOption(parts->name)) { - snprintf(download, 2048, "", + snprintf(download, 2048, " ", prefix, href, mimeGetIconURL("internal-download")); } } - /* construct the table row from parts. */ - html = new MemBuf(); - html->Printf("" - "%s" - "%s" - "%s" - "%s" - "%s%s%s%s" - "\n", - prefix, href, icon, - prefix, href, html_quote(text), - parts->date, - size, - chdir, view, download, link); + /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n */ + if (parts->type != '\0') { + snprintf(html, 8192, "%s %s%s " + "%s%8s%s%s%s%s\n", + prefix, href, icon, prefix, href, html_quote(text), dots_fill(strlen(text)), + parts->date, size, chdir, view, download, link); + } else { + /* Plain listing. {icon} {text} ... {chdir}{view}{download} */ + snprintf(html, 8192, "%s %s%s " + "%s%s%s%s\n", + prefix, href, icon, prefix, href, html_quote(text), dots_fill(strlen(text)), + chdir, view, download, link); + } ftpListPartsFree(&parts); return html; @@ -976,7 +1154,7 @@ FtpStateData::parseListing() char *end; char *line; char *s; - MemBuf *t; + char *t; size_t linelen; size_t usable; StoreEntry *e = entry; @@ -1034,9 +1212,9 @@ FtpStateData::parseListing() t = htmlifyListEntry(line); - if( t != NULL) { - listing.append(t->content(), t->contentSize()); - } + assert(t != NULL); + + writeReplyBody(t, strlen(t)); } data.readBuf->consume(usable); @@ -1171,7 +1349,7 @@ FtpStateData::dataRead(const CommIoCbParams &io) maybeReadVirginBody(); } else { - if (!flags.http_header_sent && !fwd->ftpPasvFailed() && flags.pasv_supported && !flags.listing) { + if (!flags.http_header_sent && !fwd->ftpPasvFailed() && flags.pasv_supported) { fwd->dontRetry(false); /* this is a retryable error */ fwd->ftpPasvFailed(true); } @@ -1229,16 +1407,17 @@ FtpStateData::processReplyBody() #endif + if (flags.isdir && !flags.listing_started) + listingStart(); + if (flags.isdir) { - flags.listing = 1; - listing.reset(); parseListing(); - return; - } else if (const int csize = data.readBuf->contentSize()) { - writeReplyBody(data.readBuf->content(), csize); - debugs(9, 5, HERE << "consuming " << csize << " bytes of readBuf"); - data.readBuf->consume(csize); - } + } else + if (const int csize = data.readBuf->contentSize()) { + writeReplyBody(data.readBuf->content(), csize); + debugs(9, 5, HERE << "consuming " << csize << " bytes of readBuf"); + data.readBuf->consume(csize); + } entry->flush(); @@ -1710,11 +1889,7 @@ FtpStateData::handleControlReply() /* Copy the rest of the message to cwd_message to be printed in * error messages */ - cwd_message.append('\n'); - for (wordlist *w = ctrl.message; w; w = w->next) { - cwd_message.append(' '); - cwd_message.append(w->key); - } + wordlistAddWl(&cwd_message, ctrl.message); debugs(9, 3, HERE << "state=" << state << ", code=" << ctrl.replycode); @@ -1983,13 +2158,13 @@ ftpReadCwd(FtpStateData * ftpState) if (code >= 200 && code < 300) { /* CWD OK */ ftpState->unhack(); - /* Reset cwd_message to only include the last message */ - ftpState->cwd_message.reset(""); - for (wordlist *w = ftpState->ctrl.message; w; w = w->next) { - ftpState->cwd_message.append(' '); - ftpState->cwd_message.append(w->key); - } + + if (ftpState->cwd_message) + wordlistDestroy(&ftpState->cwd_message); + + ftpState->cwd_message = ftpState->ctrl.message; + ftpState->ctrl.message = NULL; /* Continue to traverse the path */ @@ -3135,8 +3310,9 @@ ftpReadTransferDone(FtpStateData * ftpState) if (code == 226 || code == 250) { /* Connection closed; retrieval done. */ - if (ftpState->flags.listing) - ftpState->failed(ERR_FTP_LISTING, 0); + if (ftpState->flags.html_header_sent) + ftpState->listingFinish(); + ftpSendQuit(ftpState); } else { /* != 226 */ debugs(9, DBG_IMPORTANT, HERE << "Got code " << code << " after reading data"); @@ -3369,14 +3545,9 @@ FtpStateData::failedErrorMessage(err_type error, int xerrno) err->xerrno = xerrno; - if(error == ERR_FTP_LISTING) { - err->ftp.listing = &listing; - err->ftp.cwd_msg = xstrdup(html_quote(cwd_message.buf())); - } - else { - err->ftp.server_msg = ctrl.message; - ctrl.message = NULL; - } + err->ftp.server_msg = ctrl.message; + + ctrl.message = NULL; if (old_request) command = old_request;