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
This commit is contained in:
Daniel Stenberg 2021-02-08 15:56:10 +01:00
parent 0829909ebd
commit 115c9e27f5
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
9 changed files with 146 additions and 21 deletions

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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];

View file

@ -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 */
};