--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/013.24793845-ignoreascii.patch Wed Nov 23 00:29:59 2016 -0800
@@ -0,0 +1,263 @@
+This patch is a backport of proftpd Bug#4159 from 1.3.6.rc2 to 1.3.5b. It should
+be removed as soon as we sync with stable 1.3.6 release.
+
+This patch is hand crafted combination of following two commits. No test files
+are included.
+
+Fix regression, caused by change for Bug#4159 with the ASCII translation handling of LIST/NLST output
+https://github.com/proftpd/proftpd/commit/3892250b429661dd8d166a55230f9a0da923a26b
+
+Bug#4159: Support ability to disable ASCII translation transparently to FTP clients.
+https://github.com/proftpd/proftpd/commit/68229c0bc839260a43ac1c9b9f7ed68e39aa0f1a
+
+http://bugs.proftpd.org/show_bug.cgi?id=4159
+
+diff --git a/doc/modules/mod_xfer.html b/doc/modules/mod_xfer.html
+index 19179fa..52b02c0 100644
+--- a/doc/modules/mod_xfer.html
++++ b/doc/modules/mod_xfer.html
+@@ -33,6 +33,7 @@ file transfers.
+ <li><a href="#StoreUniquePrefix">StoreUniquePrefix</a>
+ <li><a href="#TimeoutNoTransfer">TimeoutNoTransfer</a>
+ <li><a href="#TimeoutStalled">TimeoutStalled</a>
++ <li><a href="#TransferOptions">TransferOptions</a>
+ <li><a href="#TransferPriority">TransferPriority</a>
+ <li><a href="#TransferRate">TransferRate</a>
+ <li><a href="#UseSendfile">UseSendfile</a>
+@@ -330,6 +331,36 @@ The maximum allowed <em>seconds</em> value is 65535 (108 minutes).
+
+ <p>
+ <hr>
++<h2><a name="TransferOptions">TransferOptions</a></h2>
++<strong>Syntax:</strong> TransferOptions <em>opt1 ...</em><br>
++<strong>Default:</strong> None<br>
++<strong>Context:</strong> server config, <code><VirtualHost></code>, <code><Global></code><br>
++<strong>Module:</strong> mod_xfer<br>
++<strong>Compatibility:</strong> 1.3.5b and later
++
++<p>
++The <code>TransferOptions</code> directive to configure various optional data
++transfer behaviors.
++
++<p>
++The currently implemented options are:
++<ul>
++ <li><code>IgnoreASCII</code><br>
++ <p>
++ This option causes proftpd to silently ignore any client requests to
++ perform ASCII translations via the <code>TYPE</code> command. That is,
++ FTP clients can request ASCII translations, and proftpd will respond
++ as the client expects, but will <b>not</b> actually perform the translation
++ for either uploads <i>or</i> downloads. This behavior can be useful in
++ circumstances involving older/mainframe clients and EBCDIC files.
++
++ <p>
++ <b>Note</b> that this option first appeared in
++ <code>proftpd-1.3.5b</code>.
++</ul>
++
++<p>
++<hr>
+ <h2><a name="TransferPriority">TransferPriority</a></h2>
+ <strong>Syntax:</strong> TransferPriority <em>cmd-list "low"|"medium"|"high"|number</em><br>
+ <strong>Default:</strong> None<br>
+diff --git a/include/data.h b/include/data.h
+index 4eaf5d9..fd5f9d9 100644
+--- a/include/data.h
++++ b/include/data.h
+@@ -31,6 +31,11 @@
+ #ifndef PR_DATACONN_H
+ #define PR_DATACONN_H
+
++/* Toggles whether to actually perform ASCII translation during the data
++ * transfer.
++ */
++int pr_data_ignore_ascii(int);
++
+ void pr_data_init(char *, int);
+ void pr_data_cleanup(void);
+ int pr_data_open(char *, char *, int, off_t);
+@@ -40,6 +45,7 @@ int pr_data_xfer(char *, size_t);
+ void pr_data_reset(void);
+ void pr_data_set_linger(long);
+
++
+ /* Clear the session.xfer.p pool, if present, and reset any associated
+ * state.
+ */
+diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c
+index de5c52a..4b75034 100644
+--- a/modules/mod_xfer.c
++++ b/modules/mod_xfer.c
+@@ -61,6 +61,7 @@ static int xfer_check_limit(cmd_rec *);
+
+ /* TransferOptions */
+ #define PR_XFER_OPT_HANDLE_ALLO 0x0001
++#define PR_XFER_OPT_IGNORE_ASCII 0x0002
+ static unsigned long xfer_opts = PR_XFER_OPT_HANDLE_ALLO;
+
+ /* Transfer priority */
+@@ -1923,7 +1924,8 @@ MODRET xfer_rest(cmd_rec *cmd) {
+ * clients.
+ */
+ if ((session.sf_flags & SF_ASCII) &&
+- pos != 0) {
++ pos != 0 &&
++ !(xfer_opts & PR_XFER_OPT_IGNORE_ASCII)) {
+ pr_log_debug(DEBUG5, "%s not allowed in ASCII mode", cmd->argv[0]);
+ pr_response_add_err(R_501,
+ _("%s: Resuming transfers not allowed in ASCII mode"), cmd->argv[0]);
+@@ -2587,6 +2589,26 @@ MODRET xfer_post_pass(cmd_rec *cmd) {
+ */
+ }
+
++ /*
++ * Check for TransferOptions
++ */
++ c = find_config(main_server->conf, CONF_PARAM, "TransferOptions", FALSE);
++ while (c != NULL) {
++ unsigned long opts = 0;
++
++ pr_signals_handle();
++
++ opts = *((unsigned long *) c->argv[0]);
++ xfer_opts |= opts;
++
++ c = find_config_next(c, c->next, CONF_PARAM, "TransferOptions", FALSE);
++ }
++
++ if (xfer_opts & PR_XFER_OPT_IGNORE_ASCII) {
++ pr_log_debug(DEBUG8, "Ignoring ASCII translation for this session");
++ pr_data_ignore_ascii(TRUE);
++ }
++
+ /* Check for TransferPriority. */
+ c = find_config(TOPLEVEL_CONF, CONF_PARAM, "TransferPriority", FALSE);
+ if (c) {
+@@ -2999,6 +3021,36 @@ MODRET set_timeoutstalled(cmd_rec *cmd) {
+ return PR_HANDLED(cmd);
+ }
+
++/* usage: TransferOptions opt1 opt2 ... */
++MODRET set_transferoptions(cmd_rec *cmd) {
++ config_rec *c = NULL;
++ register unsigned int i = 0;
++ unsigned long opts = 0UL;
++
++ if (cmd->argc-1 == 0) {
++ CONF_ERROR(cmd, "wrong number of parameters");
++ }
++
++ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
++
++ c = add_config_param(cmd->argv[0], 1, NULL);
++
++ for (i = 1; i < cmd->argc; i++) {
++ if (strcasecmp(cmd->argv[i], "IgnoreASCII") == 0) {
++ opts |= PR_XFER_OPT_IGNORE_ASCII;
++
++ } else {
++ CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown TransferOption '",
++ cmd->argv[i], "'", NULL));
++ }
++ }
++
++ c->argv[0] = pcalloc(c->pool, sizeof(unsigned long));
++ *((unsigned long *) c->argv[0]) = opts;
++
++ return PR_HANDLED(cmd);
++}
++
+ /* usage: TransferPriority cmds "low"|"medium"|"high"|number
+ */
+ MODRET set_transferpriority(cmd_rec *cmd) {
+@@ -3459,6 +3511,7 @@ static conftable xfer_conftab[] = {
+ { "StoreUniquePrefix", set_storeuniqueprefix, NULL },
+ { "TimeoutNoTransfer", set_timeoutnoxfer, NULL },
+ { "TimeoutStalled", set_timeoutstalled, NULL },
++ { "TransferOptions", set_transferoptions, NULL },
+ { "TransferPriority", set_transferpriority, NULL },
+ { "TransferRate", set_transferrate, NULL },
+ { "UseSendfile", set_usesendfile, NULL },
+diff --git a/src/data.c b/src/data.c
+index 5136f5f..0c45c77 100644
+--- a/src/data.c
++++ b/src/data.c
+@@ -40,6 +40,9 @@
+
+ static const char *trace_channel = "data";
+
++#define PR_DATA_OPT_IGNORE_ASCII 0x0001
++static unsigned long data_opts = 0UL;
++
+ /* local macro */
+
+ #define MODE_STRING (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE) ? \
+@@ -580,6 +583,33 @@ void pr_data_reset(void) {
+ session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE|SF_EPSV_ALL));
+ }
+
++int pr_data_ignore_ascii(int ignore_ascii) {
++ int res;
++
++ if (ignore_ascii != TRUE &&
++ ignore_ascii != FALSE) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ if (data_opts & PR_DATA_OPT_IGNORE_ASCII) {
++ if (!ignore_ascii) {
++ data_opts &= ~PR_DATA_OPT_IGNORE_ASCII;
++ }
++
++ res = TRUE;
++
++ } else {
++ if (ignore_ascii) {
++ data_opts |= PR_DATA_OPT_IGNORE_ASCII;
++ }
++
++ res = FALSE;
++ }
++
++ return res;
++}
++
+ void pr_data_init(char *filename, int direction) {
+ if (session.xfer.p == NULL) {
+ data_new_xfer(filename, direction);
+@@ -1155,7 +1185,15 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) {
+ char *buf = session.xfer.buf;
+ pr_buffer_t *pbuf;
+
+- if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) {
++ /* We use ASCII translation if:
++ *
++ * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST)
++ * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
++ */
++ if ((session.sf_flags & SF_ASCII_OVERRIDE) ||
++ ((session.sf_flags & SF_ASCII) &&
++ !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
++
+ int adjlen, buflen;
+
+ do {
+@@ -1330,8 +1368,14 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) {
+
+ /* Fill up our internal buffer. */
+ memcpy(session.xfer.buf, cl_buf, buflen);
+-
+- if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) {
++ /* We use ASCII translation if:
++ *
++ * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST)
++ * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
++ */
++ if ((session.sf_flags & SF_ASCII_OVERRIDE) ||
++ ((session.sf_flags & SF_ASCII) &&
++ !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
+ /* Scan the internal buffer, looking for LFs with no preceding CRs.
+ * Add CRs (and expand the internal buffer) as necessary. xferbuflen
+ * will be adjusted so that it contains the length of data in