Commit 21d5aead authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Alexander Krasnostavsky made the CURLOPT_FTP_CREATE_MISSING_DIRS option work

fine even for third party transfers.
parent f40c9b83
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
                                  Changelog

Daniel (16 October 2004)
- Alexander Krasnostavsky made the CURLOPT_FTP_CREATE_MISSING_DIRS option work
  fine even for third party transfers.

- runekl at opoint.com found out (and provided a fix) that libcurl leaked
  memory for cookies with the "max-age" field set.

+85 −33
Original line number Diff line number Diff line
@@ -122,6 +122,8 @@ static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
static CURLcode ftp_quit(struct connectdata *conn);
static CURLcode ftp_3rdparty_pretransfer(struct connectdata *conn);
static CURLcode ftp_3rdparty_transfer(struct connectdata *conn);
static CURLcode ftp_parse_url_path(struct connectdata *conn);
static CURLcode ftp_cwd_and_create_path(struct connectdata *conn);
static CURLcode ftp_regular_transfer(struct connectdata *conn);
static CURLcode ftp_3rdparty(struct connectdata *conn);

@@ -2109,23 +2111,9 @@ CURLcode ftp_perform(struct connectdata *conn,
      return result;
  }

  /* This is a re-used connection. Since we change directory to where the
     transfer is taking place, we must now get back to the original dir
     where we ended up after login: */
  if (conn->bits.reuse && ftp->entrypath) {
    if ((result = ftp_cwd_and_mkd(conn, ftp->entrypath)) != CURLE_OK)
      return result;
  }

  {
    int i; /* counter for loop */
    for (i=0; i < ftp->dirdepth; i++) {
      /* RFC 1738 says empty components should be respected too, but
         that is plain stupid since CWD can't be used with an empty argument */
      if ((result = ftp_cwd_and_mkd(conn, ftp->dirs[i])) != CURLE_OK)
  result = ftp_cwd_and_create_path(conn);
  if (result)
    return result;
    }
  }

  /* Requested time of file or time-depended transfer? */
  if((data->set.get_filetime || data->set.timecondition) &&
@@ -2268,6 +2256,10 @@ CURLcode Curl_ftp(struct connectdata *conn)
{
  CURLcode retcode = CURLE_OK;

  retcode = ftp_parse_url_path(conn);
  if (retcode)
    return retcode;

  if (conn->sec_conn) /* 3rd party transfer */
    retcode = ftp_3rdparty(conn);
  else
@@ -2546,6 +2538,10 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
    port_conn = conn;
  }

  result = ftp_cwd_and_create_path(conn);
  if (result)
    return result;

  /* sets the passive mode */
  FTPSENDF(pasv_conn, "%s", "PASV");
  result = Curl_GetFTPResponse(&nread, pasv_conn, &ftpcode);
@@ -2640,35 +2636,25 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)

/***********************************************************************
 *
 * ftp_regular_transfer()
 * ftp_parse_url_path()
 *
 * The input argument is already checked for validity.
 * Performs a regular transfer between local and remote hosts.
 * Parse the URL path into separate path components.
 *
 * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
 * Curl_ftp_done() function without finding any major problem.
 */
static
CURLcode ftp_regular_transfer(struct connectdata *conn)
CURLcode ftp_parse_url_path(struct connectdata *conn)
{
  CURLcode retcode = CURLE_OK;
  bool connected=0;
  struct SessionHandle *data = conn->data;
  struct FTP *ftp;

  char *slash_pos;  /* position of the first '/' char in curpos */
  char *cur_pos=conn->path; /* current position in ppath. point at the begin
  char *cur_pos = conn->path; /* current position in path. point at the begin
                                 of next path component */

  /* the ftp struct is already inited in ftp_connect() */
  ftp = conn->proto.ftp;
  ftp->ctl_valid = FALSE;
  conn->size = -1; /* make sure this is unknown at this point */

  Curl_pgrsSetUploadCounter(data, 0);
  Curl_pgrsSetDownloadCounter(data, 0);
  Curl_pgrsSetUploadSize(data, 0);
  Curl_pgrsSetDownloadSize(data, 0);

  ftp->dirdepth = 0;
  ftp->diralloc = 5; /* default dir depth to allocate */
@@ -2731,6 +2717,72 @@ CURLcode ftp_regular_transfer(struct connectdata *conn)
    ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
                       pointer */

  return retcode;
}



/***********************************************************************
 *
 * ftp_cwd_and_create_path()
 *
 * Creates full path on remote target host.
 *
 */
static
CURLcode ftp_cwd_and_create_path(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  /* the ftp struct is already inited in Curl_ftp_connect() */
  struct FTP *ftp = conn->proto.ftp;
  int i;

  /* This is a re-used connection. Since we change directory to where the
     transfer is taking place, we must now get back to the original dir
     where we ended up after login: */
  if (conn->bits.reuse && ftp->entrypath) {
    if ((result = ftp_cwd_and_mkd(conn, ftp->entrypath)) != CURLE_OK)
      return result;
  }

  for (i=0; i < ftp->dirdepth; i++) {
    /* RFC 1738 says empty components should be respected too, but
       that is plain stupid since CWD can't be used with an empty argument */
    if ((result = ftp_cwd_and_mkd(conn, ftp->dirs[i])) != CURLE_OK)
      return result;
  }

  return result;
}


/***********************************************************************
 *
 * ftp_regular_transfer()
 *
 * The input argument is already checked for validity.
 * Performs a regular transfer between local and remote hosts.
 *
 * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
 * Curl_ftp_done() function without finding any major problem.
 */
static
CURLcode ftp_regular_transfer(struct connectdata *conn)
{
  CURLcode retcode=CURLE_OK;
  bool connected=0;
  struct SessionHandle *data = conn->data;
  struct FTP *ftp;

  /* the ftp struct is already inited in ftp_connect() */
  ftp = conn->proto.ftp;
  conn->size = -1; /* make sure this is unknown at this point */

  Curl_pgrsSetUploadCounter(data, 0);
  Curl_pgrsSetDownloadCounter(data, 0);
  Curl_pgrsSetUploadSize(data, 0);
  Curl_pgrsSetDownloadSize(data, 0);

  retcode = ftp_perform(conn, &connected);

  if(CURLE_OK == retcode) {