Commit 0fd282b0 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

new experimental "ftp method" code

parent cdf4afbe
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -909,6 +909,9 @@ typedef enum {
     control connection. */
  CINIT(FTP_SKIP_PASV_IP, LONG, 137),

  /* Select "file method" to use when doing FTP */
  CINIT(FTP_FILEMETHOD, LONG, 138),

  CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

+70 −43
Original line number Diff line number Diff line
@@ -3642,8 +3642,6 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
  return CURLE_OK;
}



/***********************************************************************
 *
 * ftp_parse_url_path()
@@ -3667,6 +3665,34 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
  ftp = conn->proto.ftp;
  ftp->ctl_valid = FALSE;

  switch(data->set.ftp_filemethod) {
  case FTPFILE_NOCWD:
    /* fastest, but less standard-compliant */
    ftp->file = conn->path;  /* this is a full file path */
    break;

  case FTPFILE_SINGLECWD:
    /* get the last slash */
    slash_pos=strrchr(cur_pos, '/');
    if(slash_pos) {
      ftp->dirdepth = 1; /* we consider it to be a single dir */
      ftp->dirs = (char **)calloc(1, sizeof(ftp->dirs[0]));
      if(!ftp->dirs)
        return CURLE_OUT_OF_MEMORY;

      ftp->dirs[0] = curl_unescape(cur_pos, slash_pos-cur_pos);
      if(!ftp->dirs[0]) {
        free(ftp->dirs);
        return CURLE_OUT_OF_MEMORY;
      }
      ftp->file = slash_pos+1;  /* the rest is the file name */
    }
    else
      ftp->file = cur_pos;  /* this is a file name only */
    break;

  default: /* allow pretty much anything */
  case FTPFILE_MULTICWD:
    ftp->dirdepth = 0;
    ftp->diralloc = 5; /* default dir depth to allocate */
    ftp->dirs = (char **)calloc(ftp->diralloc, sizeof(ftp->dirs[0]));
@@ -3719,6 +3745,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
    }

    ftp->file = cur_pos;  /* the rest is the file name */
  }

  if(*ftp->file) {
    ftp->file = curl_unescape(ftp->file, 0);
+7 −1
Original line number Diff line number Diff line
@@ -327,7 +327,7 @@ CURLcode Curl_open(struct SessionHandle **curl)
    data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
    data->set.ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
    data->set.ftp_use_lprt = TRUE;   /* FTP defaults to EPRT operations */

    data->set.ftp_filemethod = FTPFILE_MULTICWD;
    data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */

    /* make libcurl quiet by default: */
@@ -557,6 +557,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
     */
    data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
    break;
  case CURLOPT_FTP_FILEMETHOD:
    /*
     * How do access files over FTP.
     */
    data->set.ftp_filemethod = va_arg(param, long);
    break;
  case CURLOPT_NETRC:
    /*
     * Parse the $HOME/.netrc file
+11 −3
Original line number Diff line number Diff line
@@ -310,6 +310,12 @@ typedef enum {
  FTP_LAST  /* never used */
} ftpstate;

typedef enum {
  FTPFILE_MULTICWD  = 1, /* as defined by RFC1738 */
  FTPFILE_NOCWD     = 2, /* use SIZE / RETR / STOR on the full path */
  FTPFILE_SINGLECWD = 3  /* make one CWD, then SIZE / RETR / STOR on the file */
} curl_ftpfile;

struct FTP {
  curl_off_t *bytecountp;
  char *user;    /* user name string */
@@ -1035,6 +1041,8 @@ struct UserDefined {
  char *source_url;     /* for 3rd party transfer */
  char *source_userpwd;  /* for 3rd party transfer */

  curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used  */

/* Here follows boolean settings that define how to behave during
   this session. They are STATIC, set by libcurl users or at least initially
   and they don't change during operations. */
+21 −2
Original line number Diff line number Diff line
@@ -357,6 +357,7 @@ struct Configurable {
  struct curl_slist *tp_postquote;
  struct curl_slist *tp_prequote;
  char *ftp_account; /* for ACCT */
  int ftp_filemethod;

  bool ignorecl; /* --ignore-content-length */
};
@@ -1244,6 +1245,18 @@ static ParameterError add2list(struct curl_slist **list,
  return PARAM_OK;
}

static int ftpfilemethod(struct Configurable *config, char *str)
{
  if(strequal("singlecwd", str))
    return 3;
  if(strequal("nocwd", str))
    return 2;
  if(strequal("multicwd", str))
    return 1;
  warnf(config, "unrecognized ftp file method '%s', using default\n", str);
  return 1;
}

static ParameterError getparameter(char *flag, /* f or -long-flag */
                                   char *nextarg, /* NULL if unset */
                                   bool *usedarg, /* set to TRUE if the arg
@@ -1316,6 +1329,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
    {"$o", "trace-time", FALSE},
    {"$p", "ignore-content-length", FALSE},
    {"$q", "ftp-skip-pasv-ip", FALSE},
    {"$r", "ftp-method", TRUE},

    {"0", "http1.0",     FALSE},
    {"1", "tlsv1",       FALSE},
@@ -1726,6 +1740,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
      case 'q': /* --ftp-skip-pasv-ip */
        config->ftp_skip_ip ^= TRUE;
        break;
      case 'r': /* --ftp-method (undocumented at this point) */
        config->ftp_filemethod = ftpfilemethod(config, nextarg);
        break;
      }
      break;
    case '#': /* --progress-bar */
@@ -3944,8 +3961,10 @@ operate(struct Configurable *config, int argc, char *argv[])
        curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);

        /* curl 7.14.2 */
        curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP,
                         config->ftp_skip_ip);
        curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);

        /* curl 7.15.1 */
        curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);

        retry_numretries = config->req_retry;