diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ftp.c | 30 | ||||
-rw-r--r-- | lib/ftp.h | 1 | ||||
-rw-r--r-- | lib/strerror.c | 3 | ||||
-rw-r--r-- | lib/url.c | 5 | ||||
-rw-r--r-- | lib/urldata.h | 1 |
5 files changed, 39 insertions, 1 deletions
@@ -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; @@ -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"; @@ -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! */ |