summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2010-01-01 14:44:44 +0000
committerDaniel Stenberg <daniel@haxx.se>2010-01-01 14:44:44 +0000
commit605bbfc4c0fa838f50bf9d18e69e417168f524c0 (patch)
tree405fa3f29adea6bacbaad6b1edf8ad8f9e5b718a /lib
parent42d365f199f9637820de4ecdee21bc7d4668f138 (diff)
downloadcurl-605bbfc4c0fa838f50bf9d18e69e417168f524c0.tar.gz
- Ingmar Runge enhanced libcurl's FTP engine to support the PRET command. This
command is a special "hack" used by the drftpd server, but even though it is a custom extension I've deemed it fine to add to libcurl since this server seems to survive and people keep using it and want libcurl to support it. The new libcurl option is named CURLOPT_FTP_USE_PRET, and it is also usable from the curl tool with --ftp-pret. Using this option on a server that doesn't support this command will make libcurl fail.
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! */