Skip to content

curl_easy_reset() does not reset text/binary option for FTP transfer #6577

Description

@bodob

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

  1. Transfer (upload) uses ASCII mode by using FTP command "TYPE A" via CURLOPT_PREQUOTE.
  2. curl_easy_reset() to reset all options
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions