new experimental "ftp method" code

This commit is contained in:
Daniel Stenberg 2005-11-28 23:06:00 +00:00
parent cdf4afbe50
commit 0fd282b078
5 changed files with 111 additions and 48 deletions

View File

@ -909,6 +909,9 @@ typedef enum {
control connection. */ control connection. */
CINIT(FTP_SKIP_PASV_IP, LONG, 137), 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 */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;

View File

@ -3642,8 +3642,6 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/*********************************************************************** /***********************************************************************
* *
* ftp_parse_url_path() * ftp_parse_url_path()
@ -3667,6 +3665,34 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
ftp = conn->proto.ftp; ftp = conn->proto.ftp;
ftp->ctl_valid = FALSE; 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->dirdepth = 0;
ftp->diralloc = 5; /* default dir depth to allocate */ ftp->diralloc = 5; /* default dir depth to allocate */
ftp->dirs = (char **)calloc(ftp->diralloc, sizeof(ftp->dirs[0])); 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 */ ftp->file = cur_pos; /* the rest is the file name */
}
if(*ftp->file) { if(*ftp->file) {
ftp->file = curl_unescape(ftp->file, 0); ftp->file = curl_unescape(ftp->file, 0);

View File

@ -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_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT 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_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 */ data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* make libcurl quiet 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; data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
break; break;
case CURLOPT_FTP_FILEMETHOD:
/*
* How do access files over FTP.
*/
data->set.ftp_filemethod = va_arg(param, long);
break;
case CURLOPT_NETRC: case CURLOPT_NETRC:
/* /*
* Parse the $HOME/.netrc file * Parse the $HOME/.netrc file

View File

@ -310,6 +310,12 @@ typedef enum {
FTP_LAST /* never used */ FTP_LAST /* never used */
} ftpstate; } 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 { struct FTP {
curl_off_t *bytecountp; curl_off_t *bytecountp;
char *user; /* user name string */ char *user; /* user name string */
@ -1035,6 +1041,8 @@ struct UserDefined {
char *source_url; /* for 3rd party transfer */ char *source_url; /* for 3rd party transfer */
char *source_userpwd; /* 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 /* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */ and they don't change during operations. */

View File

@ -357,6 +357,7 @@ struct Configurable {
struct curl_slist *tp_postquote; struct curl_slist *tp_postquote;
struct curl_slist *tp_prequote; struct curl_slist *tp_prequote;
char *ftp_account; /* for ACCT */ char *ftp_account; /* for ACCT */
int ftp_filemethod;
bool ignorecl; /* --ignore-content-length */ bool ignorecl; /* --ignore-content-length */
}; };
@ -1244,6 +1245,18 @@ static ParameterError add2list(struct curl_slist **list,
return PARAM_OK; 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 */ static ParameterError getparameter(char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */ char *nextarg, /* NULL if unset */
bool *usedarg, /* set to TRUE if the arg 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}, {"$o", "trace-time", FALSE},
{"$p", "ignore-content-length", FALSE}, {"$p", "ignore-content-length", FALSE},
{"$q", "ftp-skip-pasv-ip", FALSE}, {"$q", "ftp-skip-pasv-ip", FALSE},
{"$r", "ftp-method", TRUE},
{"0", "http1.0", FALSE}, {"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE}, {"1", "tlsv1", FALSE},
@ -1726,6 +1740,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'q': /* --ftp-skip-pasv-ip */ case 'q': /* --ftp-skip-pasv-ip */
config->ftp_skip_ip ^= TRUE; config->ftp_skip_ip ^= TRUE;
break; break;
case 'r': /* --ftp-method (undocumented at this point) */
config->ftp_filemethod = ftpfilemethod(config, nextarg);
break;
} }
break; break;
case '#': /* --progress-bar */ 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_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
/* curl 7.14.2 */ /* curl 7.14.2 */
curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
config->ftp_skip_ip);
/* curl 7.15.1 */
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
retry_numretries = config->req_retry; retry_numretries = config->req_retry;