summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-02-08 15:56:10 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-02-09 14:06:28 +0100
commit115c9e27f53809a254fba44b023bea92f4d4dcd0 (patch)
tree148e355a72b3cbf932fd3e7bbfb48aeb4c30288a
parent0829909ebd8ded89189d2cae699231512962f31c (diff)
downloadcurl-115c9e27f53809a254fba44b023bea92f4d4dcd0.tar.gz
ftp: add 'prefer_ascii' to the transfer state struct
... and make sure the code never updates 'set.prefer_ascii' as it breaks handle reuse which should use the setting as the user specified it. Added test 1569 to verify: it first makes an FTP transfer with ';type=A' and then another without type on the same handle and the second should then use binary. Previously, curl failed this. Closes #6578
-rw-r--r--lib/ftp.c19
-rw-r--r--lib/http.c4
-rw-r--r--lib/tftp.c6
-rw-r--r--lib/transfer.c11
-rw-r--r--lib/urldata.h1
-rw-r--r--tests/data/Makefile.inc2
-rw-r--r--tests/data/test156973
-rw-r--r--tests/libtest/Makefile.inc5
-rw-r--r--tests/libtest/lib1569.c46
9 files changed, 146 insertions, 21 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index c888b7858..05bed5464 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -1525,7 +1525,7 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
information. Which in FTP can't be much more than the file size and
date. */
if(data->set.opt_no_body && ftpc->file &&
- ftp_need_type(conn, data->set.prefer_ascii)) {
+ ftp_need_type(conn, data->state.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
@@ -1535,7 +1535,7 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
/* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */
- result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE);
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
if(result)
return result;
}
@@ -1747,7 +1747,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
result = ftp_state_retr(data, ftpc->known_filesize);
}
else {
- if(data->set.ignorecl || data->set.prefer_ascii) {
+ if(data->set.ignorecl || data->state.prefer_ascii) {
/* 'ignorecl' is used to support download of growing files. It
prevents the state machine from requesting the file size from
the server. With an unknown file size the download continues
@@ -2454,7 +2454,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
*/
if((instate != FTP_LIST) &&
- !data->set.prefer_ascii &&
+ !data->state.prefer_ascii &&
(ftp->downloadsize < 1)) {
/*
* It seems directory listings either don't show the size or very
@@ -2493,7 +2493,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(size > data->req.maxdownload && data->req.maxdownload > 0)
size = data->req.size = data->req.maxdownload;
- else if((instate != FTP_LIST) && (data->set.prefer_ascii))
+ else if((instate != FTP_LIST) && (data->state.prefer_ascii))
size = -1; /* kludge for servers that understate ASCII mode file size */
infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
@@ -3626,7 +3626,8 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
}
}
else if(data->set.upload) {
- result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii,
+ FTP_STOR_TYPE);
if(result)
return result;
@@ -3661,7 +3662,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
/* otherwise just fall through */
}
else {
- result = ftp_nb_type(data, conn, data->set.prefer_ascii,
+ result = ftp_nb_type(data, conn, data->state.prefer_ascii,
FTP_RETR_TYPE);
if(result)
return result;
@@ -4351,7 +4352,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
switch(command) {
case 'A': /* ASCII mode */
- data->set.prefer_ascii = TRUE;
+ data->state.prefer_ascii = TRUE;
break;
case 'D': /* directory mode */
@@ -4361,7 +4362,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
case 'I': /* binary mode */
default:
/* switch off ASCII */
- data->set.prefer_ascii = FALSE;
+ data->state.prefer_ascii = FALSE;
break;
}
}
diff --git a/lib/http.c b/lib/http.c
index 806f639dc..1141102f6 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1702,7 +1702,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
if(
#ifdef CURL_DO_LINEEND_CONV
- (handle->set.prefer_ascii) ||
+ (handle->state.prefer_ascii) ||
#endif
(handle->set.crlf)) {
/* \n will become \r\n later on */
@@ -2209,7 +2209,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
}
if(!type) {
result = Curl_dyn_addf(r, ";type=%c",
- data->set.prefer_ascii ? 'a' : 'i');
+ data->state.prefer_ascii ? 'a' : 'i');
if(result)
return result;
}
diff --git a/lib/tftp.c b/lib/tftp.c
index 3f1d1b51b..defc9105e 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -460,7 +460,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
CURLcode result = CURLE_OK;
/* Set ascii mode if -B flag was used */
- if(data->set.prefer_ascii)
+ if(data->state.prefer_ascii)
mode = "netascii";
switch(event) {
@@ -1420,14 +1420,14 @@ static CURLcode tftp_setup_connection(struct Curl_easy *data,
switch(command) {
case 'A': /* ASCII mode */
case 'N': /* NETASCII mode */
- data->set.prefer_ascii = TRUE;
+ data->state.prefer_ascii = TRUE;
break;
case 'O': /* octet mode */
case 'I': /* binary mode */
default:
/* switch off ASCII */
- data->set.prefer_ascii = FALSE;
+ data->state.prefer_ascii = FALSE;
break;
}
}
diff --git a/lib/transfer.c b/lib/transfer.c
index 59f759600..e63ad7133 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -286,7 +286,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
* <DATA> CRLF
*/
/* On non-ASCII platforms the <DATA> may or may not be
- translated based on set.prefer_ascii while the protocol
+ translated based on state.prefer_ascii while the protocol
portion must always be translated to the network encoding.
To further complicate matters, line end conversion might be
done later on, so we need to prevent CRLFs from becoming
@@ -301,7 +301,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
if(
#ifdef CURL_DO_LINEEND_CONV
- (data->set.prefer_ascii) ||
+ (data->state.prefer_ascii) ||
#endif
(data->set.crlf)) {
/* \n will become \r\n later on */
@@ -348,7 +348,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
{
CURLcode result;
size_t length;
- if(data->set.prefer_ascii)
+ if(data->state.prefer_ascii)
/* translate the protocol and data */
length = nread;
else
@@ -389,7 +389,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
nread += strlen(endofline_network); /* for the added end of line */
}
#ifdef CURL_DOES_CONVERSIONS
- else if((data->set.prefer_ascii) && (!sending_http_headers)) {
+ else if((data->state.prefer_ascii) && (!sending_http_headers)) {
CURLcode result;
result = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -1028,7 +1028,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
if((!sending_http_headers) && (
#ifdef CURL_DO_LINEEND_CONV
/* always convert if we're FTPing in ASCII mode */
- (data->set.prefer_ascii) ||
+ (data->state.prefer_ascii) ||
#endif
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
@@ -1415,6 +1415,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
}
+ data->state.prefer_ascii = data->set.prefer_ascii;
data->state.httpreq = data->set.method;
data->change.url = data->set.str[STRING_SET_URL];
diff --git a/lib/urldata.h b/lib/urldata.h
index 4d7ccd59e..00c7d407f 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1467,6 +1467,7 @@ struct UrlState {
BIT(stream_depends_e); /* set or don't set the Exclusive bit */
BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
BIT(cookie_engine);
+ BIT(prefer_ascii); /* ASCII rather than binary */
};
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 6762c8dcc..228e93d80 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -187,7 +187,7 @@ test1540 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
-test1566 test1567 test1568 \
+test1566 test1567 test1568 test1569 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
\
diff --git a/tests/data/test1569 b/tests/data/test1569
new file mode 100644
index 000000000..78f1dea26
--- /dev/null
+++ b/tests/data/test1569
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+RETR
+</keywords>
+</info>
+# Server-side
+<reply>
+<data nocheck="yes">
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</data>
+<servercmd>
+REPLY EPSV 500 no such command
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP first type=A then regular URL
+ </name>
+<tool>
+lib1569
+</tool>
+<command>
+"ftp://%HOSTIP:%FTPPORT/1569;type=A" ftp://%HOSTIP:%FTPPORT/1569
+</command>
+
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+EPSV
+PASV
+TYPE A
+RETR 1569
+PASV
+TYPE I
+SIZE 1569
+RETR 1569
+QUIT
+</protocol>
+</verify>
+<stdout>
+data
+ to
+ see
+that FTP
+works
+ so does it?
+data
+ to
+ see
+that FTP
+works
+ so does it?
+</stdout>
+
+</testcase>
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 561895200..9f2ba8a91 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -57,7 +57,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
lib1540 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
- lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 \
+ lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
lib1591 lib1592 lib1593 lib1594 lib1596 \
lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
lib1915 lib1916 lib1917 lib1918 lib1933 lib1934 lib1935 lib1936 \
@@ -608,6 +608,9 @@ lib1567_CPPFLAGS = $(AM_CPPFLAGS)
lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
lib1568_CPPFLAGS = $(AM_CPPFLAGS)
+lib1569_SOURCES = lib1569.c $(SUPPORTFILES)
+lib1569_CPPFLAGS = $(AM_CPPFLAGS)
+
lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591
diff --git a/tests/libtest/lib1569.c b/tests/libtest/lib1569.c
new file mode 100644
index 000000000..0aaba3973
--- /dev/null
+++ b/tests/libtest/lib1569.c
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testtrace.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURLcode ret;
+ CURL *hnd;
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ hnd = curl_easy_init();
+ curl_easy_setopt(hnd, CURLOPT_URL, URL);
+ curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
+
+ ret = curl_easy_perform(hnd);
+
+ curl_easy_setopt(hnd, CURLOPT_URL, libtest_arg2);
+ ret = curl_easy_perform(hnd);
+ curl_easy_cleanup(hnd);
+
+ curl_global_cleanup();
+ return (int)ret;
+}