#include "squid.h"
#include "comm.h"
#include "comm/ListenStateData.h"
+#include "compat/strtoll.h"
#include "ConnectionDetail.h"
#include "errorpage.h"
#include "fde.h"
#include "HttpRequest.h"
#include "HttpReply.h"
#include "MemBuf.h"
+#include "rfc1738.h"
#include "Server.h"
+#include "SquidString.h"
#include "SquidTime.h"
#include "Store.h"
#include "URLScheme.h"
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_started;
+ bool listing;
bool completed_forwarding;
};
int64_t restart_offset;
char *proxy_host;
size_t list_width;
- wordlist *cwd_message;
+ String 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
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 completedListing(void);
void dataComplete();
void dataRead(const CommIoCbParams &io);
int checkAuth(const HttpHeader * req_hdr);
if (ctrl.message)
wordlistDestroy(&ctrl.message);
- if (cwd_message)
- wordlistDestroy(&cwd_message);
+ cwd_message.clean();
safe_free(ctrl.last_reply);
/* failed() closes ctrl.fd and frees ftpState */
}
-void
-FtpStateData::listingStart()
-{
- debugs(9,3, HERE);
- wordlist *w;
- char *dirup;
- int i, j, k;
- const char *title = title_url.termedBuf();
- flags.listing_started = true;
- printfReplyBody("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
- printfReplyBody("<!-- HTML listing generated by Squid %s -->\n",
- version_string);
- printfReplyBody("<!-- %s -->\n", mkrfc1123(squid_curtime));
- printfReplyBody("<HTML><HEAD><TITLE>\n");
- {
- char *t = xstrdup(title);
- rfc1738_unescape(t);
- printfReplyBody("FTP Directory: %s\n", html_quote(t));
- xfree(t);
- }
-
- printfReplyBody("</TITLE>\n");
- printfReplyBody("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
-
- if (flags.need_base_href)
- printfReplyBody("<BASE HREF=\"%s\">\n",
- html_quote(base_href.termedBuf()));
-
- printfReplyBody("</HEAD><BODY>\n");
-
- if (cwd_message) {
- printfReplyBody("<PRE>\n");
-
- for (w = cwd_message; w; w = w->next)
- printfReplyBody("%s\n", html_quote(w->key));
-
- printfReplyBody("</PRE>\n");
-
- printfReplyBody("<HR noshade size=\"1px\">\n");
-
- wordlistDestroy(&cwd_message);
- }
-
- printfReplyBody("<H2>\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("<A HREF=\"");
- i += strcspn(&title[i], "/");
-
- if (i > 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("</A>");
- }
-
- 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("</H2>\n");
- printfReplyBody("<PRE>\n");
- dirup = htmlifyListEntry("<internal-dirup>");
- writeReplyBody(dirup, strlen(dirup));
- flags.html_header_sent = 1;
-}
-
+#if DEAD_CODE // obsoleted by ERR_DIR_LISTING
void
FtpStateData::listingFinish()
{
- debugs(9,3,HERE);
- entry->buffer();
- printfReplyBody("</PRE>\n");
+ // TODO: figure out what this means and how to show it ...
if (flags.listformat_unknown && !flags.tried_nlst) {
- printfReplyBody("<A HREF=\"%s/;type=d\">[As plain directory]</A>\n",
+ printfReplyBody("<a href=\"%s/;type=d\">[As plain directory]</a>\n",
flags.dir_slash ? rfc1738_escape_part(old_filepath) : ".");
} else if (typecode == 'D') {
const char *path = flags.dir_slash ? filepath : ".";
- printfReplyBody("<A HREF=\"%s/\">[As extended directory]</A>\n", rfc1738_escape_part(path));
+ printfReplyBody("<a href=\"%s/\">[As extended directory]</a>\n", rfc1738_escape_part(path));
}
-
- printfReplyBody("<HR noshade size=\"1px\">\n");
- printfReplyBody("<ADDRESS>\n");
- printfReplyBody("Generated %s by %s (%s)\n",
- mkrfc1123(squid_curtime),
- getMyHostname(),
- visible_appname_string);
- printfReplyBody("</ADDRESS></BODY></HTML>\n");
}
+#endif /* DEAD_CODE */
/// \ingroup ServerProtocolFTPInternal
static const char *Month[] = {
p->type = 0;
while (ct && *ct) {
- time_t t;
+ time_t tm;
int l = strcspn(ct, ",");
char *tmp;
break;
case 'm':
- t = (time_t) strtol(ct + 1, &tmp, 0);
+ tm = (time_t) strtol(ct + 1, &tmp, 0);
if (tmp != ct + 1)
break; /* not a valid integer */
- p->date = xstrdup(ctime(&t));
+ p->date = xstrdup(ctime(&tm));
*(strstr(p->date, "\n")) = '\0';
return p;
}
-/// \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 *
+MemBuf *
FtpStateData::htmlifyListEntry(const char *line)
{
- 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;
+ 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];
ftpListParts *parts;
- *icon = *href = *text = *size = *chdir = *view = *download = *link = *html = '\0';
+ *icon = *href = *text = *size = *chdir = *view = *download = *link = '\0';
+
+ debugs(9, 7, HERE << " line ={" << line << "}");
- if ((int) strlen(line) > 1024) {
- snprintf(html, 8192, "%s\n", line);
+ if (strlen(line) > 1024) {
+ html = new MemBuf();
+ html->init();
+ html->Printf("<tr><td colspan=\"5\">%s</td></tr>\n", line);
return html;
}
else
prefix[0] = '\0';
- /* Handle builtin <dirup> */
- if (strcmp(line, "<internal-dirup>") == 0) {
- /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> {link} */
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-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, "(<A HREF=\"%s\">%s</A>)",
- "%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.termedBuf();
- 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, "(<A HREF=\"%s\">%s</A>)", url, "Back");
- safe_free(url);
- } else { /* NO_DOTDOT && ROOT_DIR */
- /* "UNIX Root" directory */
- strcpy(href, "/");
- strcpy(text, "Home Directory");
- }
-
- snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A> %s\n",
- href, icon, href, text, link);
- return html;
- }
-
if ((parts = ftpListParseParts(line, flags)) == NULL) {
const char *p;
- snprintf(html, 8192, "%s\n", line);
+
+ html = new MemBuf();
+ html->init();
+ html->Printf("<tr class=\"entry\"><td colspan=\"5\">%s</td></tr>\n", line);
for (p = line; *p && xisspace(*p); p++);
if (*p && !xisspace(*p))
}
if (!strcmp(parts->name, ".") || !strcmp(parts->name, "..")) {
- *html = '\0';
ftpListPartsFree(&parts);
- return html;
+ return NULL;
}
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);
switch (parts->type) {
case 'd':
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ snprintf(icon, 2048, "<img border=\"0\" src=\"%s\" alt=\"%-6s\">",
mimeGetIconURL("internal-dir"),
"[DIR]");
strcat(href, "/"); /* margin is allocated above */
break;
case 'l':
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ snprintf(icon, 2048, "<img border=\"0\" src=\"%s\" alt=\"%-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, " -> <A HREF=\"%s%s\">%s</A>",
+ snprintf(link, 2048, " -> <a href=\"%s%s\">%s</a>",
*link2 != '/' ? prefix : "", link2,
html_quote(parts->link));
safe_free(link2);
break;
case '\0':
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ snprintf(icon, 2048, "<img border=\"0\" src=\"%s\" alt=\"%-6s\">",
mimeGetIconURL(parts->name),
"[UNKNOWN]");
- snprintf(chdir, 2048, " <A HREF=\"%s/;type=d\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[DIR]\"></A>",
+ snprintf(chdir, 2048, "<a href=\"%s/;type=d\"><img border=\"0\" src=\"%s\" "
+ "alt=\"[DIR]\"></a>",
rfc1738_escape_part(parts->name),
mimeGetIconURL("internal-dir"));
break;
case '-':
default:
- snprintf(icon, 2048, "<IMG border=\"0\" SRC=\"%s\" ALT=\"%-6s\">",
+ snprintf(icon, 2048, "<img border=\"0\" src=\"%s\" alt=\"%-6s\">",
mimeGetIconURL(parts->name),
"[FILE]");
snprintf(size, 2048, " %6"PRId64"k", parts->size);
if (parts->type != 'd') {
if (mimeGetViewOption(parts->name)) {
- snprintf(view, 2048, " <A HREF=\"%s%s;type=a\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[VIEW]\"></A>",
+ snprintf(view, 2048, "<a href=\"%s%s;type=a\"><img border=\"0\" src=\"%s\" "
+ "alt=\"[VIEW]\"></a>",
prefix, href, mimeGetIconURL("internal-view"));
}
if (mimeGetDownloadOption(parts->name)) {
- snprintf(download, 2048, " <A HREF=\"%s%s;type=i\"><IMG border=\"0\" SRC=\"%s\" "
- "ALT=\"[DOWNLOAD]\"></A>",
+ snprintf(download, 2048, "<a href=\"%s%s;type=i\"><img border=\"0\" src=\"%s\" "
+ "alt=\"[DOWNLOAD]\"></a>",
prefix, href, mimeGetIconURL("internal-download"));
}
}
- /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> . . . {date}{size}{chdir}{view}{download}{link}\n */
- if (parts->type != '\0') {
- snprintf(html, 8192, "<A HREF=\"%s%s\">%s</A> <A HREF=\"%s%s\">%s</A>%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, "<A HREF=\"%s%s\">%s</A> <A HREF=\"%s%s\">%s</A>%s "
- "%s%s%s%s\n",
- prefix, href, icon, prefix, href, html_quote(text), dots_fill(strlen(text)),
+ /* construct the table row from parts. */
+ html = new MemBuf();
+ html->init();
+ html->Printf("<tr class=\"entry\">"
+ "<td class=\"icon\"><a href=\"%s%s\">%s</a></td>"
+ "<td class=\"filename\"><a href=\"%s%s\">%s</a></td>"
+ "<td class=\"date\">%s</td>"
+ "<td class=\"size\">%s</td>"
+ "<td class=\"actions\">%s%s%s%s</td>"
+ "</tr>\n",
+ prefix, href, icon,
+ prefix, href, html_quote(text),
+ parts->date,
+ size,
chdir, view, download, link);
- }
ftpListPartsFree(&parts);
return html;
char *end;
char *line;
char *s;
- char *t;
+ MemBuf *t;
size_t linelen;
size_t usable;
- StoreEntry *e = entry;
size_t len = data.readBuf->contentSize();
if (!len) {
- debugs(9, 3, HERE << "no content to parse for " << e->url() );
+ debugs(9, 3, HERE << "no content to parse for " << entry->url() );
return;
}
debugs(9, 3, HERE << "usable = " << usable);
if (usable == 0) {
- debugs(9, 3, HERE << "didn't find end for " << e->url() );
+ debugs(9, 3, HERE << "didn't find end for " << entry->url() );
xfree(sbuf);
return;
}
line = (char *)memAllocate(MEM_4K_BUF);
end++;
- e->buffer(); /* released when done processing current data payload */
s = sbuf;
s += strspn(s, crlf);
t = htmlifyListEntry(line);
- assert(t != NULL);
-
- writeReplyBody(t, strlen(t));
+ if ( t != NULL) {
+ debugs(9, 7, HERE << "listing append: t = {" << t->contentSize() << ", '" << t->content() << "'}");
+ listing.append(t->content(), t->contentSize());
+//leak? delete t;
+ }
}
+ debugs(9, 7, HERE << "Done.");
data.readBuf->consume(usable);
memFree(line, MEM_4K_BUF);
xfree(sbuf);
maybeReadVirginBody();
} else {
- if (!flags.http_header_sent && !fwd->ftpPasvFailed() && flags.pasv_supported) {
+ if (!flags.http_header_sent && !fwd->ftpPasvFailed() && flags.pasv_supported && !flags.listing) {
fwd->dontRetry(false); /* this is a retryable error */
fwd->ftpPasvFailed(true);
}
return;
}
- if (!flags.http_header_sent && data.readBuf->contentSize() >= 0)
+ /* Directory listings are special. They write ther own headers via the error objects */
+ if (!flags.http_header_sent && data.readBuf->contentSize() >= 0 && !flags.isdir)
appendSuccessHeader();
if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
#endif
- if (flags.isdir && !flags.listing_started)
- listingStart();
-
if (flags.isdir) {
+ if (!flags.listing) {
+ flags.listing = 1;
+ listing.reset();
+ }
parseListing();
+ maybeReadVirginBody();
+ return;
} else if (const int csize = data.readBuf->contentSize()) {
writeReplyBody(data.readBuf->content(), csize);
debugs(9, 5, HERE << "consuming " << csize << " bytes of readBuf");
/* Copy the rest of the message to cwd_message to be printed in
* error messages
*/
- wordlistAddWl(&cwd_message, ctrl.message);
+ if (ctrl.message) {
+ for (wordlist *w = ctrl.message; w; w = w->next) {
+ cwd_message.append('\n');
+ cwd_message.append(w->key);
+ }
+ }
debugs(9, 3, HERE << "state=" << state << ", code=" << ctrl.replycode);
if (code >= 200 && code < 300) {
/* CWD OK */
ftpState->unhack();
- /* Reset cwd_message to only include the last message */
-
- if (ftpState->cwd_message)
- wordlistDestroy(&ftpState->cwd_message);
-
- ftpState->cwd_message = ftpState->ctrl.message;
+ /* 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);
+ }
ftpState->ctrl.message = NULL;
/* Continue to traverse the path */
char h1, h2, h3, h4;
int n;
u_short port;
- IpAddress ipa_remote;
+ Ip::Address ipa_remote;
int fd = ftpState->data.fd;
char *buf;
debugs(9, 3, HERE);
static void
ftpSendPassive(FtpStateData * ftpState)
{
- IpAddress addr;
+ Ip::Address addr;
struct addrinfo *AI = NULL;
/** Checks the server control channel is still available before running. */
int p1, p2;
int n;
u_short port;
- IpAddress ipa_remote;
+ Ip::Address ipa_remote;
int fd = ftpState->data.fd;
char *buf;
LOCAL_ARRAY(char, ipaddr, 1024);
ftpOpenListenSocket(FtpStateData * ftpState, int fallback)
{
int fd;
-
- IpAddress addr;
+ Ip::Address addr;
struct addrinfo *AI = NULL;
int on = 1;
int x = 0;
ftpSendPORT(FtpStateData * ftpState)
{
int fd;
-
- IpAddress ipa;
+ Ip::Address ipa;
struct addrinfo *AI = NULL;
unsigned char *addrptr;
unsigned char *portptr;
ftpSendEPRT(FtpStateData * ftpState)
{
int fd;
- IpAddress addr;
+ Ip::Address addr;
struct addrinfo *AI = NULL;
char buf[MAX_IPSTRLEN];
ftpState->flags.pasv_supported = 0;
fd = ftpOpenListenSocket(ftpState, 0);
- addr.InitAddrInfo(AI);
+ Ip::Address::InitAddrInfo(AI);
if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen)) {
- addr.FreeAddrInfo(AI);
+ Ip::Address::FreeAddrInfo(AI);
debugs(9, DBG_CRITICAL, HERE << "getsockname(" << fd << ",..): " << xstrerror());
/* XXX Need to set error message */
ftpState->writeCommand(cbuf);
ftpState->state = SENT_EPRT;
- addr.FreeAddrInfo(AI);
+ Ip::Address::FreeAddrInfo(AI);
}
static void
}
}
+/**
+ * Generate the HTTP headers and template fluff around an FTP
+ * directory listing display.
+ */
+void
+FtpStateData::completedListing()
+{
+ assert(entry);
+ entry->lock();
+ ErrorState *ferr = errorCon(ERR_DIR_LISTING, HTTP_OK, request);
+ ferr->ftp.listing = &listing;
+ ferr->ftp.cwd_msg = xstrdup(cwd_message.termedBuf());
+ ferr->ftp.server_msg = ctrl.message;
+ ctrl.message = NULL;
+ entry->replaceHttpReply( ferr->BuildHttpReply() );
+ errorStateFree(ferr);
+ EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+ entry->flush();
+ entry->unlock();
+}
+
+
/// \ingroup ServerProtocolFTPInternal
static void
ftpReadTransferDone(FtpStateData * ftpState)
if (code == 226 || code == 250) {
/* Connection closed; retrieval done. */
-
- if (ftpState->flags.html_header_sent)
- ftpState->listingFinish();
-
+ if (ftpState->flags.listing) {
+ ftpState->completedListing();
+ /* QUIT operation handles sending the reply to client */
+ }
ftpSendQuit(ftpState);
} else { /* != 226 */
debugs(9, DBG_IMPORTANT, HERE << "Got code " << code << " after reading data");
ftpState->state = SENT_QUIT;
}
-/// \ingroup ServerProtocolFTPInternal
+/**
+ * \ingroup ServerProtocolFTPInternal
+ *
+ * This completes a client FTP operation with success or other page
+ * generated and stored in the entry field by the code issuing QUIT.
+ */
static void
ftpReadQuit(FtpStateData * ftpState)
{
- /** \todo XXX should this just be a case of abortTransaction? */
ftpState->serverComplete();
}
void
FtpStateData::failedErrorMessage(err_type error, int xerrno)
{
- ErrorState *err;
+ ErrorState *ftperr;
const char *command, *reply;
+
/* Translate FTP errors into HTTP errors */
- err = NULL;
+ ftperr = NULL;
switch (error) {
if (ctrl.replycode > 500)
if (password_url)
- err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN, fwd->request);
+ ftperr = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN, fwd->request);
else
- err = errorCon(ERR_FTP_FORBIDDEN, HTTP_UNAUTHORIZED, fwd->request);
+ ftperr = errorCon(ERR_FTP_FORBIDDEN, HTTP_UNAUTHORIZED, fwd->request);
else if (ctrl.replycode == 421)
- err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE, fwd->request);
+ ftperr = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE, fwd->request);
break;
case SENT_RETR:
if (ctrl.replycode == 550)
- err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND, fwd->request);
+ ftperr = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND, fwd->request);
break;
break;
case ERR_READ_TIMEOUT:
- err = errorCon(error, HTTP_GATEWAY_TIMEOUT, fwd->request);
+ ftperr = errorCon(error, HTTP_GATEWAY_TIMEOUT, fwd->request);
break;
default:
- err = errorCon(error, HTTP_BAD_GATEWAY, fwd->request);
+ ftperr = errorCon(error, HTTP_BAD_GATEWAY, fwd->request);
break;
}
- if (err == NULL)
- err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY, fwd->request);
-
- err->xerrno = xerrno;
+ if (ftperr == NULL)
+ ftperr = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY, fwd->request);
- err->ftp.server_msg = ctrl.message;
+ ftperr->xerrno = xerrno;
+ ftperr->ftp.server_msg = ctrl.message;
ctrl.message = NULL;
if (old_request)
reply = ctrl.last_reply;
if (command)
- err->ftp.request = xstrdup(command);
+ ftperr->ftp.request = xstrdup(command);
if (reply)
- err->ftp.reply = xstrdup(reply);
+ ftperr->ftp.reply = xstrdup(reply);
- fwd->fail(err);
+ entry->replaceHttpReply( ftperr->BuildHttpReply() );
+ errorStateFree(ftperr);
}
/// \ingroup ServerProtocolFTPInternal
else
err->ftp.reply = xstrdup("");
- errorAppendEntry(ftpState->entry, err);
+ ftpState->entry->replaceHttpReply( err->BuildHttpReply() );
+ errorStateFree(err);
ftpSendQuit(ftpState);
}
String urlpath = request->urlpath;
const char *filename = NULL;
const char *t = NULL;
- StoreEntry *e = entry;
debugs(9, 3, HERE);
flags.http_header_sent = 1;
- assert(e->isEmpty());
+ assert(entry->isEmpty());
- EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT);
+ EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
- e->buffer(); /* released when done processing current data payload */
+ entry->buffer(); /* released when done processing current data payload */
filename = (t = urlpath.rpos('/')) ? t + 1 : urlpath.termedBuf();
/* set standard stuff */
- HttpVersion version(1, 0);
if (0 == getCurrentOffset()) {
/* Full reply */
- reply->setHeaders(version, HTTP_OK, "Gatewaying",
- mime_type, theSize, mdtm, -2);
+ reply->setHeaders(HTTP_OK, "Gatewaying", mime_type, theSize, mdtm, -2);
} else if (theSize < getCurrentOffset()) {
/*
* DPW 2007-05-04
" current offset=" << getCurrentOffset() <<
", but theSize=" << theSize <<
". assuming full content response");
- reply->setHeaders(version, HTTP_OK, "Gatewaying",
- mime_type, theSize, mdtm, -2);
+ reply->setHeaders(HTTP_OK, "Gatewaying", mime_type, theSize, mdtm, -2);
} else {
/* Partial reply */
HttpHdrRangeSpec range_spec;
range_spec.offset = getCurrentOffset();
range_spec.length = theSize - getCurrentOffset();
- reply->setHeaders(version, HTTP_PARTIAL_CONTENT, "Gatewaying",
- mime_type, theSize - getCurrentOffset(), mdtm, -2);
+ reply->setHeaders(HTTP_PARTIAL_CONTENT, "Gatewaying", mime_type, theSize - getCurrentOffset(), mdtm, -2);
httpHeaderAddContRange(&reply->header, range_spec, theSize);
}
* which should be sent to either StoreEntry, or to ICAP...
*/
void
-FtpStateData::writeReplyBody(const char *data, size_t len)
+FtpStateData::writeReplyBody(const char *dataToWrite, size_t dataLength)
{
- debugs(9, 5, HERE << "writing " << len << " bytes to the reply");
- addVirginReplyBody(data, len);
+ debugs(9, 5, HERE << "writing " << dataLength << " bytes to the reply");
+ addVirginReplyBody(dataToWrite, dataLength);
}
/**
comm_remove_close_handler(fd, closer);
closer = NULL;
fd = -1;
- }
- else if (fd >= 0) {
+ } else if (fd >= 0) {
comm_remove_close_handler(fd, closer);
closer = NULL;
comm_close(fd); // we do not expect to be called back