aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ftp.c30
-rw-r--r--lib/ftp.h1
-rw-r--r--lib/strerror.c3
-rw-r--r--lib/url.c5
-rw-r--r--lib/urldata.h1
5 files changed, 39 insertions, 1 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index c5be2361f..64e29ceab 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -565,6 +565,7 @@ static void state(struct connectdata *conn,
"REST",
"RETR_REST",
"PORT",
+ "PRET",
"PASV",
"LIST",
"RETR",
@@ -1090,7 +1091,25 @@ static CURLcode ftp_state_post_rest(struct connectdata *conn)
}
else {
/* We have chosen (this is default) to use the PASV (or similar) command */
- result = ftp_state_use_pasv(conn);
+ if(data->set.ftp_use_pret) {
+ /* The user has requested that we send a PRET command
+ to prepare the server for the upcoming PASV */
+ if(!conn->proto.ftpc.file) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET %s", data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"));
+ }
+ else if(data->set.upload) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
+ }
+ else {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
+ }
+ state(conn, FTP_PRET);
+ }
+ else {
+ result = ftp_state_use_pasv(conn);
+ }
}
return result;
}
@@ -2710,6 +2729,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
break;
+ case FTP_PRET:
+ if(ftpcode != 200) {
+ /* there only is this one standard OK return code. */
+ failf(data, "PRET command not accepted: %03d", ftpcode);
+ return CURLE_FTP_PRET_FAILED;
+ }
+ result = ftp_state_use_pasv(conn);
+ break;
+
case FTP_PASV:
result = ftp_state_pasv_resp(conn, ftpcode);
break;
diff --git a/lib/ftp.h b/lib/ftp.h
index 93581bfc9..11dd65bae 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -79,6 +79,7 @@ typedef enum {
FTP_REST, /* when used to check if the server supports it in head-like */
FTP_RETR_REST, /* when asking for "resume" in for RETR */
FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */
+ FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */
FTP_PASV, /* generic state for PASV and EPSV, check count1 */
FTP_LIST, /* generic state for LIST, NLST or a custom list command */
FTP_RETR,
diff --git a/lib/strerror.c b/lib/strerror.c
index 75067a7d0..da223f58d 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -81,6 +81,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_REMOTE_ACCESS_DENIED:
return "Access denied to remote resource";
+ case CURLE_FTP_PRET_FAILED:
+ return "FTP: The server did not accept the PRET command.";
+
case CURLE_FTP_WEIRD_PASS_REPLY:
return "FTP: unknown PASS reply";
diff --git a/lib/url.c b/lib/url.c
index 3f2f1cd72..19283c290 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -701,6 +701,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->httpreq = HTTPREQ_GET; /* Default HTTP request */
set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
+ set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
set->ftp_filemethod = FTPFILE_MULTICWD;
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
@@ -1563,6 +1564,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
break;
+ case CURLOPT_FTP_USE_PRET:
+ data->set.ftp_use_pret = (bool)(0 != va_arg(param, long));
+ break;
+
case CURLOPT_FTP_SSL_CCC:
data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
break;
diff --git a/lib/urldata.h b/lib/urldata.h
index 4bcb5bf6f..d7b8be6af 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1308,6 +1308,7 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
bool ftp_use_eprt; /* if EPRT is to be attempted or not */
+ bool ftp_use_pret; /* if PRET is to be used before PASV or not */
curl_usessl ftp_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! */