mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 15:48:49 -05:00
new experimental "ftp method" code
This commit is contained in:
parent
cdf4afbe50
commit
0fd282b078
@ -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;
|
||||||
|
|
||||||
|
111
lib/ftp.c
111
lib/ftp.c
@ -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,58 +3665,87 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|||||||
ftp = conn->proto.ftp;
|
ftp = conn->proto.ftp;
|
||||||
ftp->ctl_valid = FALSE;
|
ftp->ctl_valid = FALSE;
|
||||||
|
|
||||||
ftp->dirdepth = 0;
|
switch(data->set.ftp_filemethod) {
|
||||||
ftp->diralloc = 5; /* default dir depth to allocate */
|
case FTPFILE_NOCWD:
|
||||||
ftp->dirs = (char **)calloc(ftp->diralloc, sizeof(ftp->dirs[0]));
|
/* fastest, but less standard-compliant */
|
||||||
if(!ftp->dirs)
|
ftp->file = conn->path; /* this is a full file path */
|
||||||
return CURLE_OUT_OF_MEMORY;
|
break;
|
||||||
|
|
||||||
/* parse the URL path into separate path components */
|
case FTPFILE_SINGLECWD:
|
||||||
while((slash_pos=strchr(cur_pos, '/'))) {
|
/* get the last slash */
|
||||||
/* 1 or 0 to indicate absolute directory */
|
slash_pos=strrchr(cur_pos, '/');
|
||||||
bool absolute_dir = (cur_pos - conn->path > 0) && (ftp->dirdepth == 0);
|
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;
|
||||||
|
|
||||||
/* seek out the next path component */
|
ftp->dirs[0] = curl_unescape(cur_pos, slash_pos-cur_pos);
|
||||||
if (slash_pos-cur_pos) {
|
if(!ftp->dirs[0]) {
|
||||||
/* we skip empty path components, like "x//y" since the FTP command CWD
|
free(ftp->dirs);
|
||||||
requires a parameter and a non-existant parameter a) doesn't work on
|
|
||||||
many servers and b) has no effect on the others. */
|
|
||||||
int len = (int)(slash_pos - cur_pos + absolute_dir);
|
|
||||||
ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir, len);
|
|
||||||
|
|
||||||
if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */
|
|
||||||
failf(data, "no memory");
|
|
||||||
freedirs(ftp);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
if (isBadFtpString(ftp->dirs[ftp->dirdepth])) {
|
ftp->file = slash_pos+1; /* the rest is the file name */
|
||||||
freedirs(ftp);
|
|
||||||
return CURLE_URL_MALFORMAT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ftp->file = cur_pos; /* this is a file name only */
|
||||||
|
break;
|
||||||
|
|
||||||
if(!retcode) {
|
default: /* allow pretty much anything */
|
||||||
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
case FTPFILE_MULTICWD:
|
||||||
if(++ftp->dirdepth >= ftp->diralloc) {
|
ftp->dirdepth = 0;
|
||||||
/* enlarge array */
|
ftp->diralloc = 5; /* default dir depth to allocate */
|
||||||
char *bigger;
|
ftp->dirs = (char **)calloc(ftp->diralloc, sizeof(ftp->dirs[0]));
|
||||||
ftp->diralloc *= 2; /* double the size each time */
|
if(!ftp->dirs)
|
||||||
bigger = realloc(ftp->dirs, ftp->diralloc * sizeof(ftp->dirs[0]));
|
return CURLE_OUT_OF_MEMORY;
|
||||||
if(!bigger) {
|
|
||||||
ftp->dirdepth--;
|
/* parse the URL path into separate path components */
|
||||||
|
while((slash_pos=strchr(cur_pos, '/'))) {
|
||||||
|
/* 1 or 0 to indicate absolute directory */
|
||||||
|
bool absolute_dir = (cur_pos - conn->path > 0) && (ftp->dirdepth == 0);
|
||||||
|
|
||||||
|
/* seek out the next path component */
|
||||||
|
if (slash_pos-cur_pos) {
|
||||||
|
/* we skip empty path components, like "x//y" since the FTP command CWD
|
||||||
|
requires a parameter and a non-existant parameter a) doesn't work on
|
||||||
|
many servers and b) has no effect on the others. */
|
||||||
|
int len = (int)(slash_pos - cur_pos + absolute_dir);
|
||||||
|
ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir, len);
|
||||||
|
|
||||||
|
if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */
|
||||||
|
failf(data, "no memory");
|
||||||
freedirs(ftp);
|
freedirs(ftp);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
ftp->dirs = (char **)bigger;
|
if (isBadFtpString(ftp->dirs[ftp->dirdepth])) {
|
||||||
|
freedirs(ftp);
|
||||||
|
return CURLE_URL_MALFORMAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!retcode) {
|
||||||
|
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
||||||
|
if(++ftp->dirdepth >= ftp->diralloc) {
|
||||||
|
/* enlarge array */
|
||||||
|
char *bigger;
|
||||||
|
ftp->diralloc *= 2; /* double the size each time */
|
||||||
|
bigger = realloc(ftp->dirs, ftp->diralloc * sizeof(ftp->dirs[0]));
|
||||||
|
if(!bigger) {
|
||||||
|
ftp->dirdepth--;
|
||||||
|
freedirs(ftp);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
ftp->dirs = (char **)bigger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
@ -424,10 +430,10 @@ struct ConnectBits {
|
|||||||
LPRT doesn't work we disable it for the forthcoming
|
LPRT doesn't work we disable it for the forthcoming
|
||||||
requests */
|
requests */
|
||||||
bool netrc; /* name+password provided by netrc */
|
bool netrc; /* name+password provided by netrc */
|
||||||
|
|
||||||
bool trailerHdrPresent; /* Set when Trailer: header found in HTTP response.
|
bool trailerHdrPresent; /* Set when Trailer: header found in HTTP response.
|
||||||
Required to determine whether to look for trailers
|
Required to determine whether to look for trailers
|
||||||
in case of Transfer-Encoding: chunking */
|
in case of Transfer-Encoding: chunking */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hostname {
|
struct hostname {
|
||||||
@ -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. */
|
||||||
|
23
src/main.c
23
src/main.c
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user