1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

- 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.
This commit is contained in:
Daniel Stenberg 2010-01-01 14:44:44 +00:00
parent 42d365f199
commit 605bbfc4c0
15 changed files with 186 additions and 5 deletions

14
CHANGES
View File

@ -6,6 +6,20 @@
Changelog Changelog
Daniel Stenberg (1 Jan 2010)
- 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.
I added test cases 1107 and 1108 to verify the functionality.
The PRET command is documented at
http://www.drftpd.org/index.php/Distributed_PASV
Yang Tse (30 Dec 2009) Yang Tse (30 Dec 2009)
- Steven M. Schweda improved VMS build system, and Craig A. Berry helped - Steven M. Schweda improved VMS build system, and Craig A. Berry helped
with the patch and testing. with the patch and testing.

View File

@ -1,8 +1,8 @@
Curl and libcurl 7.20.0 Curl and libcurl 7.20.0
Public curl releases: 114 Public curl releases: 114
Command line options: 134 Command line options: 135
curl_easy_setopt() options: 165 curl_easy_setopt() options: 166
Public functions in libcurl: 58 Public functions in libcurl: 58
Known libcurl bindings: 39 Known libcurl bindings: 39
Contributors: 761 Contributors: 761
@ -16,6 +16,7 @@ This release includes the following changes:
o added support for IMAP, POP3 and SMTP transfers o added support for IMAP, POP3 and SMTP transfers
o added --mail-from and --mail-rcpt for SMTP o added --mail-from and --mail-rcpt for SMTP
o VMS build system enhancements o VMS build system enhancements
o added support for the PRET ftp command
This release includes the following bugfixes: This release includes the following bugfixes:
@ -50,6 +51,6 @@ advice from friends like these:
Marco Maggi, Camille Moncelier, Claes Jakobsson, Kevin Baughman, Marco Maggi, Camille Moncelier, Claes Jakobsson, Kevin Baughman,
Marc Kleine-Budde, Jad Chamcham, Bjorn Augustsson, David Byron, Marc Kleine-Budde, Jad Chamcham, Bjorn Augustsson, David Byron,
Markus Koetter, Chad Monroe, Martin Storsjo, Siegfried Gyuricsko, Markus Koetter, Chad Monroe, Martin Storsjo, Siegfried Gyuricsko,
Jon Nelson, Julien Chaffraix, Renato Botelho, Peter Pentchev Jon Nelson, Julien Chaffraix, Renato Botelho, Peter Pentchev, Ingmar Runge
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@ -461,6 +461,11 @@ will re-use the same IP address it already uses for the control
connection. (Added in 7.14.2) connection. (Added in 7.14.2)
This option has no effect if PORT, EPRT or EPSV is used instead of PASV. This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
.IP "--ftp-pret"
(FTP) Tell curl to send a PRET command before PASV (and EPSV). Certain
FTP servers, mainly drftpd, require this non-standard command for
directory listings as well as up and downloads in PASV mode.
(Added in 7.20.x)
.IP "--ftp-ssl" .IP "--ftp-ssl"
(FTP) Try to use SSL/TLS for the FTP connection. Reverts to a non-secure (FTP) Try to use SSL/TLS for the FTP connection. Reverts to a non-secure
connection if the server doesn't support SSL/TLS. See also connection if the server doesn't support SSL/TLS. See also

View File

@ -1160,6 +1160,12 @@ means that it will first attempt to use EPSV before using PASV, but if you
pass zero to this option, it will not try using EPSV, only plain PASV. pass zero to this option, it will not try using EPSV, only plain PASV.
If the server is an IPv6 host, this option will have no effect as of 7.12.3. If the server is an IPv6 host, this option will have no effect as of 7.12.3.
.IP CURLOPT_FTP_USE_PRET
Pass a long. If the value is 1, it tells curl to send a PRET command
before PASV (and EPSV). Certain FTP servers, mainly drftpd, require this
non-standard command for directory listings as well as up and downloads in
PASV mode. Has no effect when using the active FTP transfers mode.
(Added in 7.20.x)
.IP CURLOPT_FTP_CREATE_MISSING_DIRS .IP CURLOPT_FTP_CREATE_MISSING_DIRS
Pass a long. If the value is 1, curl will attempt to create any remote Pass a long. If the value is 1, curl will attempt to create any remote
directory that it fails to CWD into. CWD is the command that changes working directory that it fails to CWD into. CWD is the command that changes working

View File

@ -70,6 +70,10 @@ either a PASV or a EPSV command. The server is flawed.
.IP "CURLE_FTP_WEIRD_227_FORMAT (14)" .IP "CURLE_FTP_WEIRD_227_FORMAT (14)"
FTP servers return a 227-line as a response to a PASV command. If libcurl FTP servers return a 227-line as a response to a PASV command. If libcurl
fails to parse that line, this return code is passed back. fails to parse that line, this return code is passed back.
.IP "CURLE_FTP_PRET_FAILED (84)"
The FTP server does not understand the PRET command at all or does not
support the given argument. Be careful when using \fICURLOPT_CUSTOMREQUEST\fP,
a custom LIST command will be sent with PRET CMD before PASV as well.
.IP "CURLE_FTP_CANT_GET_HOST (15)" .IP "CURLE_FTP_CANT_GET_HOST (15)"
An internal failure to lookup the host used for the new connection. An internal failure to lookup the host used for the new connection.
.IP "CURLE_FTP_COULDNT_SET_TYPE (17)" .IP "CURLE_FTP_COULDNT_SET_TYPE (17)"

View File

@ -413,6 +413,7 @@ typedef enum {
wrong format (Added in 7.19.0) */ wrong format (Added in 7.19.0) */
CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
7.19.0) */ 7.19.0) */
CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
@ -1291,6 +1292,9 @@ typedef enum {
/* set the SMTP mail receiver(s) */ /* set the SMTP mail receiver(s) */
CINIT(MAIL_RCPT, OBJECTPOINT, 187), CINIT(MAIL_RCPT, OBJECTPOINT, 187),
/* FTP: send PRET before PASV */
CINIT(FTP_USE_PRET, LONG, 188),
CURLOPT_LASTENTRY /* the last unused */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;

View File

@ -565,6 +565,7 @@ static void state(struct connectdata *conn,
"REST", "REST",
"RETR_REST", "RETR_REST",
"PORT", "PORT",
"PRET",
"PASV", "PASV",
"LIST", "LIST",
"RETR", "RETR",
@ -1090,7 +1091,25 @@ static CURLcode ftp_state_post_rest(struct connectdata *conn)
} }
else { else {
/* We have chosen (this is default) to use the PASV (or similar) command */ /* 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; return result;
} }
@ -2710,6 +2729,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
break; 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: case FTP_PASV:
result = ftp_state_pasv_resp(conn, ftpcode); result = ftp_state_pasv_resp(conn, ftpcode);
break; break;

View File

@ -79,6 +79,7 @@ typedef enum {
FTP_REST, /* when used to check if the server supports it in head-like */ 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_RETR_REST, /* when asking for "resume" in for RETR */
FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ 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_PASV, /* generic state for PASV and EPSV, check count1 */
FTP_LIST, /* generic state for LIST, NLST or a custom list command */ FTP_LIST, /* generic state for LIST, NLST or a custom list command */
FTP_RETR, FTP_RETR,

View File

@ -81,6 +81,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_REMOTE_ACCESS_DENIED: case CURLE_REMOTE_ACCESS_DENIED:
return "Access denied to remote resource"; 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: case CURLE_FTP_WEIRD_PASS_REPLY:
return "FTP: unknown PASS reply"; return "FTP: unknown PASS reply";

View File

@ -701,6 +701,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->httpreq = HTTPREQ_GET; /* Default HTTP request */ set->httpreq = HTTPREQ_GET; /* Default HTTP request */
set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT 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->ftp_filemethod = FTPFILE_MULTICWD;
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ 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)); data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
break; break;
case CURLOPT_FTP_USE_PRET:
data->set.ftp_use_pret = (bool)(0 != va_arg(param, long));
break;
case CURLOPT_FTP_SSL_CCC: case CURLOPT_FTP_SSL_CCC:
data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long); data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
break; break;

View File

@ -1308,6 +1308,7 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */ 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_epsv; /* if EPSV is to be attempted or not */
bool ftp_use_eprt; /* if EPRT 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 curl_usessl ftp_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! */ IMAP or POP3 or others! */

View File

@ -477,6 +477,7 @@ struct Configurable {
bool resume_from_current; bool resume_from_current;
bool disable_epsv; bool disable_epsv;
bool disable_eprt; bool disable_eprt;
bool ftp_pret;
curl_off_t resume_from; curl_off_t resume_from;
char *postfields; char *postfields;
curl_off_t postfieldsize; curl_off_t postfieldsize;
@ -794,6 +795,7 @@ static void help(void)
" --ftp-pasv Use PASV/EPSV instead of PORT (F)", " --ftp-pasv Use PASV/EPSV instead of PORT (F)",
" -P/--ftp-port <address> Use PORT with address instead of PASV (F)", " -P/--ftp-port <address> Use PORT with address instead of PASV (F)",
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n" " --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
" --ftp-pret Send PRET before PASV (for drftpd) (F)",
" --ftp-ssl Try SSL/TLS for ftp transfer (F)", " --ftp-ssl Try SSL/TLS for ftp transfer (F)",
" --ftp-ssl-ccc Send CCC after authenticating (F)", " --ftp-ssl-ccc Send CCC after authenticating (F)",
" --ftp-ssl-ccc-mode [active/passive] Set CCC mode (F)", " --ftp-ssl-ccc-mode [active/passive] Set CCC mode (F)",
@ -1746,6 +1748,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$9", "tftp-blksize", TRUE}, {"$9", "tftp-blksize", TRUE},
{"$A", "mail-from", TRUE}, {"$A", "mail-from", TRUE},
{"$B", "mail-rcpt", TRUE}, {"$B", "mail-rcpt", TRUE},
{"$C", "ftp-pret", FALSE},
{"0", "http1.0", FALSE}, {"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE}, {"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE}, {"2", "sslv2", FALSE},
@ -2284,6 +2287,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
if(err) if(err)
return err; return err;
break; break;
case 'C': /* --ftp-pret */
config->ftp_pret = toggle;
break;
} }
break; break;
case '#': /* --progress-bar */ case '#': /* --progress-bar */
@ -5032,6 +5038,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
if(config->mail_rcpt) if(config->mail_rcpt)
my_setopt_str(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt); my_setopt_str(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
/* curl 7.20.x */
if(config->ftp_pret)
my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
retry_numretries = config->req_retry; retry_numretries = config->req_retry;
retrystart = cutil_tvnow(); retrystart = cutil_tvnow();

View File

@ -63,7 +63,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test1089 test1090 test1091 test1092 test1093 test1094 test1095 test1096 \ test1089 test1090 test1091 test1092 test1093 test1094 test1095 test1096 \
test1097 test560 test561 test1098 test1099 test562 test563 test1100 \ test1097 test560 test561 test1098 test1099 test562 test563 test1100 \
test564 test1101 test1102 test1103 test1104 test299 test310 test311 \ test564 test1101 test1102 test1103 test1104 test299 test310 test311 \
test312 test1105 test565 test800 test1106 test801 test566 test802 test803 test312 test1105 test565 test800 test1106 test801 test566 test802 test803 \
test1107 test1108
filecheck: filecheck:
@mkdir test-place; \ @mkdir test-place; \

53
tests/data/test1107 Normal file
View File

@ -0,0 +1,53 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
PRET
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
<servercmd>
REPLY PRET 200 fine
</servercmd>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP RETR PASV with PRET
</name>
<command>
ftp://%HOSTIP:%FTPPORT/1107 --ftp-pret
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
PRET RETR 1107
EPSV
TYPE I
SIZE 1107
RETR 1107
QUIT
</protocol>
</verify>
</testcase>

45
tests/data/test1108 Normal file
View File

@ -0,0 +1,45 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
PRET
</keywords>
</info>
# Server-side
<reply>
<servercmd>
REPLY PRET 550 unkown command
</servercmd>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP RETR PASV with PRET not supported
</name>
<command>
ftp://%HOSTIP:%FTPPORT/1108 --ftp-pret
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
PRET RETR 1108
</protocol>
# we expect that the server doesn't understand PRET
<errorcode>
84
</errorcode>
</verify>
</testcase>