Transfer after curl_easy_reset() uses incorrect options, thus still happening in ASCII mode, even when explicitly setting CURLOPT_TRANSFERTEXT to 0.
In addition, this also causes '\r' (carriage returns) to be written to the output on Unix, which is wrong for both ASCII and binary mode.
To reproduce
- Transfer (upload) uses ASCII mode by using FTP command "TYPE A" via CURLOPT_PREQUOTE.
- curl_easy_reset() to reset all options
- Next transfer (download)
Example C code
#include <curl/curl.h>
int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd = NULL;
struct curl_slist *cmdlist = NULL;
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "ftp://ftpserver.example.com//tmp/myfile.txt");
curl_easy_setopt(hnd, CURLOPT_USERPWD, "anonymous:xyz");
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
// Using CURLOPT_TRANSFERTEXT=1 would be easier, but we want to use/test CURLOPT_PREQUOTE
cmdlist = curl_slist_append(cmdlist, "TYPE A"); // ASCII transfer
curl_easy_setopt(hnd, CURLOPT_PREQUOTE, cmdlist);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
ret = curl_easy_perform(hnd);
fprintf(stderr, "\nUpload done, now doing download\n\n.");
// Resetting all options before download
curl_easy_reset(hnd);
// Workaround (instead of the above call):
// curl_easy_cleanup(hnd);
// hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "ftp://ftpserver.example.com//tmp/myfile.txt");
curl_easy_setopt(hnd, CURLOPT_USERPWD, "anonymous:xyz");
curl_easy_setopt(hnd, CURLOPT_TRANSFERTEXT, 0L); // Trying explicitly set binary mode - does not work
// Note: Even CURLOPT_TRANSFERTEXT=1 did not correctly download the file - output still contains \r characters
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
return (int)ret;
}
Example usage
From bash (ftpdld is the name of the executable created from code above):
printf "Line1\nLine2" | ftpdld | od -cx
Workaround
Instead of curl_easy_reset() use a new curl handle for the download.
Expected output
Verbose output (stderr) should indicate binary mode (TYPE I) being used for download.
File downloaded only contains newline (no carriage return) as end-of-line characters.
Actual output
Verbose output (stderr) indicates that ASCII mode is used for download.
File downloaded contains carriage return + newline as end-of-line characters.
curl/libcurl version
libcurl/7.74.0
operating system
Linux xxxxx 3.10.0-1062.el7.x86_64 #1 SMP Thu Jul 18 20:25:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Transfer after curl_easy_reset() uses incorrect options, thus still happening in ASCII mode, even when explicitly setting CURLOPT_TRANSFERTEXT to 0.
In addition, this also causes '\r' (carriage returns) to be written to the output on Unix, which is wrong for both ASCII and binary mode.
To reproduce
Example C code
Example usage
From bash (ftpdld is the name of the executable created from code above):
printf "Line1\nLine2" | ftpdld | od -cxWorkaround
Instead of curl_easy_reset() use a new curl handle for the download.
Expected output
Verbose output (stderr) should indicate binary mode (TYPE I) being used for download.
File downloaded only contains newline (no carriage return) as end-of-line characters.
Actual output
Verbose output (stderr) indicates that ASCII mode is used for download.
File downloaded contains carriage return + newline as end-of-line characters.
curl/libcurl version
libcurl/7.74.0
operating system
Linux xxxxx 3.10.0-1062.el7.x86_64 #1 SMP Thu Jul 18 20:25:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux