summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/ftp.c')
-rw-r--r--libs/libcurl/src/ftp.c420
1 files changed, 180 insertions, 240 deletions
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index 9fadac5138..11031da6fb 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -59,7 +59,7 @@
#include "fileinfo.h"
#include "ftplistparser.h"
#include "curl_range.h"
-#include "curl_sec.h"
+#include "curl_krb5.h"
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
@@ -137,14 +137,10 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
static CURLcode ftp_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode ftp_setup_connection(struct connectdata *conn);
-
static CURLcode init_wc_data(struct connectdata *conn);
static CURLcode wc_statemach(struct connectdata *conn);
-
static void wc_data_dtor(void *ptr);
-
static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
-
static CURLcode ftp_readresp(curl_socket_t sockfd,
struct pingpong *pp,
int *ftpcode,
@@ -152,12 +148,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
static CURLcode ftp_dophase_done(struct connectdata *conn,
bool connected);
-/* easy-to-use macro: */
-#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \
- if(result) \
- return result
-
-
/*
* FTP protocol handler.
*/
@@ -180,6 +170,7 @@ const struct Curl_handler Curl_handler_ftp = {
ZERO_NULL, /* connection_check */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
PROTOPT_WILDCARD /* flags */
@@ -209,6 +200,7 @@ const struct Curl_handler Curl_handler_ftps = {
ZERO_NULL, /* connection_check */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
};
@@ -775,25 +767,22 @@ static void _state(struct connectdata *conn,
static CURLcode ftp_state_user(struct connectdata *conn)
{
- CURLcode result;
- /* send USER */
- PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:"");
-
- state(conn, FTP_USER);
- conn->data->state.ftp_trying_alternative = FALSE;
-
- return CURLE_OK;
+ CURLcode result = Curl_pp_sendf(&conn->proto.ftpc.pp, "USER %s",
+ conn->user?conn->user:"");
+ if(!result) {
+ state(conn, FTP_USER);
+ conn->data->state.ftp_trying_alternative = FALSE;
+ }
+ return result;
}
static CURLcode ftp_state_pwd(struct connectdata *conn)
{
- CURLcode result;
-
- /* send PWD to discover our entry point */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
- state(conn, FTP_PWD);
+ CURLcode result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PWD");
+ if(!result)
+ state(conn, FTP_PWD);
- return CURLE_OK;
+ return result;
}
/* For the FTP "protocol connect" and "doing" phases only */
@@ -881,16 +870,19 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
where we ended up after login: */
ftpc->cwdcount = 0; /* we count this as the first path, then we add one
for all upcoming ones in the ftp->dirs[] array */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(&ftpc->pp, "CWD %s", ftpc->entrypath);
+ if(!result)
+ state(conn, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
ftpc->cwdcount = 1;
/* issue the first CWD, the rest is sent when the CWD responses are
received... */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount -1]);
+ if(!result)
+ state(conn, FTP_CWD);
}
else {
/* No CWD necessary */
@@ -1326,12 +1318,12 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
modeoff = conn->bits.ftp_use_epsv?0:1;
- PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
-
- ftpc->count1 = modeoff;
- state(conn, FTP_PASV);
- infof(conn->data, "Connect data stream passively\n");
-
+ result = Curl_pp_sendf(&ftpc->pp, "%s", mode[modeoff]);
+ if(!result) {
+ ftpc->count1 = modeoff;
+ state(conn, FTP_PASV);
+ infof(conn->data, "Connect data stream passively\n");
+ }
return result;
}
@@ -1364,23 +1356,23 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *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);
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ if(!conn->proto.ftpc.file)
+ result = Curl_pp_sendf(&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)
+ result = Curl_pp_sendf(&ftpc->pp, "PRET STOR %s",
+ conn->proto.ftpc.file);
+ else
+ result = Curl_pp_sendf(&ftpc->pp, "PRET RETR %s",
+ conn->proto.ftpc.file);
+ if(!result)
+ state(conn, FTP_PRET);
}
- else {
+ else
result = ftp_state_use_pasv(conn);
- }
}
return result;
}
@@ -1396,9 +1388,9 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
/* Determine if server can respond to REST command and therefore
whether it supports range */
- PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
-
- state(conn, FTP_REST);
+ result = Curl_pp_sendf(&ftpc->pp, "REST %d", 0);
+ if(!result)
+ state(conn, FTP_REST);
}
else
result = ftp_state_prepare_transfer(conn);
@@ -1416,9 +1408,9 @@ static CURLcode ftp_state_size(struct connectdata *conn)
/* if a "head"-like request is being made (on a file) */
/* we know ftpc->file is a valid pointer to a file name */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
-
- state(conn, FTP_SIZE);
+ result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_SIZE);
}
else
result = ftp_state_rest(conn);
@@ -1485,10 +1477,8 @@ static CURLcode ftp_state_list(struct connectdata *conn)
result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
free(cmd);
- if(result)
- return result;
-
- state(conn, FTP_LIST);
+ if(!result)
+ state(conn, FTP_LIST);
return result;
}
@@ -1549,9 +1539,10 @@ static CURLcode ftp_state_mdtm(struct connectdata *conn)
/* we have requested to get the modified-time of the file, this is a white
spot as the MDTM is not mentioned in RFC959 */
- PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
+ result = Curl_pp_sendf(&ftpc->pp, "MDTM %s", ftpc->file);
- state(conn, FTP_MDTM);
+ if(!result)
+ state(conn, FTP_MDTM);
}
else
result = ftp_state_type(conn);
@@ -1587,8 +1578,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
if(data->state.resume_from < 0) {
/* Got no given size to start from, figure it out */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_STOR_SIZE);
+ result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_STOR_SIZE);
return result;
}
@@ -1650,10 +1642,10 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* we've passed, proceed as normal */
} /* resume_from */
- PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
- ftpc->file);
-
- state(conn, FTP_STOR);
+ result = Curl_pp_sendf(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
+ if(!result)
+ state(conn, FTP_STOR);
return result;
}
@@ -1711,7 +1703,9 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
else
ftpc->count2 = 0; /* failure means cancel operation */
- PPSENDF(&ftpc->pp, "%s", cmd);
+ result = Curl_pp_sendf(&ftpc->pp, "%s", cmd);
+ if(result)
+ return result;
state(conn, instate);
quote = TRUE;
}
@@ -1740,12 +1734,14 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
the server terminates it, otherwise the client stops if the
received byte count exceeds the reported file size. Set option
CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_RETR);
}
else {
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_RETR_SIZE);
+ result = Curl_pp_sendf(&ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_RETR_SIZE);
}
}
}
@@ -1782,10 +1778,12 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
conn->bits.ftp_use_epsv = FALSE;
conn->data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
- conn->proto.ftpc.count1++;
- /* remain in/go to the FTP_PASV state */
- state(conn, FTP_PASV);
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "PASV");
+ if(!result) {
+ conn->proto.ftpc.count1++;
+ /* remain in/go to the FTP_PASV state */
+ state(conn, FTP_PASV);
+ }
return result;
}
@@ -1864,8 +1862,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
else if((ftpc->count1 == 1) &&
(ftpcode == 227)) {
/* positive PASV response */
- unsigned int ip[4];
- unsigned int port[2];
+ unsigned int ip[4] = {0, 0, 0, 0};
+ unsigned int port[2] = {0, 0};
/*
* Scan for a sequence of six comma-separated numbers and use them as
@@ -2092,7 +2090,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
break;
case 550: /* "No such file or directory" */
failf(data, "Given file does not exist");
- result = CURLE_FTP_COULDNT_RETR_FILE;
+ result = CURLE_REMOTE_FILE_NOT_FOUND;
break;
}
@@ -2229,15 +2227,16 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
infof(data, "Instructs server to resume from offset %"
CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
- PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
- data->state.resume_from);
-
- state(conn, FTP_RETR_REST);
+ result = Curl_pp_sendf(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
+ data->state.resume_from);
+ if(!result)
+ state(conn, FTP_RETR_REST);
}
else {
/* no resume */
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_RETR);
}
return result;
@@ -2272,6 +2271,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
(void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
}
+ else if(ftpcode == 550) { /* "No such file or directory" */
+ failf(data, "The file does not exist");
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2326,8 +2329,9 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
result = CURLE_FTP_COULDNT_USE_REST;
}
else {
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(&ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(conn, FTP_RETR);
}
break;
}
@@ -2504,7 +2508,7 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- if(conn->ssl[FIRSTSOCKET].use) {
+ if(conn->bits.ftp_use_control_ssl) {
/* PBSZ = PROTECTION BUFFER SIZE.
The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
@@ -2519,8 +2523,9 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
parameter of '0' to indicate that no buffering is taking place
and the data connection should not be encapsulated.
*/
- PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
- state(conn, FTP_PBSZ);
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "PBSZ %d", 0);
+ if(!result)
+ state(conn, FTP_PBSZ);
}
else {
result = ftp_state_pwd(conn);
@@ -2542,8 +2547,9 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
- PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
- state(conn, FTP_PASS);
+ result = Curl_pp_sendf(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
+ if(!result)
+ state(conn, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
@@ -2552,8 +2558,10 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
}
else if(ftpcode == 332) {
if(data->set.str[STRING_FTP_ACCOUNT]) {
- PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
- state(conn, FTP_ACCT);
+ result = Curl_pp_sendf(&ftpc->pp, "ACCT %s",
+ data->set.str[STRING_FTP_ACCOUNT]);
+ if(!result)
+ state(conn, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2569,11 +2577,13 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
!conn->data->state.ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
- PPSENDF(&conn->proto.ftpc.pp, "%s",
- conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
- conn->data->state.ftp_trying_alternative = TRUE;
- state(conn, FTP_USER);
- result = CURLE_OK;
+ result =
+ Curl_pp_sendf(&ftpc->pp, "%s",
+ conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ if(!result) {
+ conn->data->state.ftp_trying_alternative = TRUE;
+ state(conn, FTP_USER);
+ }
}
else {
failf(data, "Access denied: %03d", ftpcode);
@@ -2649,14 +2659,8 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
#endif
- if(data->set.use_ssl &&
- (!conn->ssl[FIRSTSOCKET].use
-#ifndef CURL_DISABLE_PROXY
- || (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
- !conn->proxy_ssl[FIRSTSOCKET].use)
-#endif
- )) {
- /* We don't have a SSL/TLS connection yet, but FTPS is
+ if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
+ /* We don't have a SSL/TLS control connection yet, but FTPS is
requested. Try a FTPS connection now */
ftpc->count3 = 0;
@@ -2675,15 +2679,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
(int)data->set.ftpsslauth);
return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
}
- PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
- state(conn, FTP_AUTH);
+ result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ if(!result)
+ state(conn, FTP_AUTH);
}
- else {
+ else
result = ftp_state_user(conn);
- if(result)
- return result;
- }
-
break;
case FTP_AUTH:
@@ -2701,6 +2702,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
+ conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
result = ftp_state_user(conn);
}
}
@@ -2718,9 +2720,6 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* ignore the failure and continue */
result = ftp_state_user(conn);
}
-
- if(result)
- return result;
break;
case FTP_USER:
@@ -2733,10 +2732,11 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
break;
case FTP_PBSZ:
- PPSENDF(&ftpc->pp, "PROT %c",
- data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
- state(conn, FTP_PROT);
-
+ result =
+ Curl_pp_sendf(&ftpc->pp, "PROT %c",
+ data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ if(!result)
+ state(conn, FTP_PROT);
break;
case FTP_PROT:
@@ -2753,14 +2753,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(data->set.ftp_ccc) {
/* CCC - Clear Command Channel
*/
- PPSENDF(&ftpc->pp, "%s", "CCC");
- state(conn, FTP_CCC);
+ result = Curl_pp_sendf(&ftpc->pp, "%s", "CCC");
+ if(!result)
+ state(conn, FTP_CCC);
}
- else {
+ else
result = ftp_state_pwd(conn);
- if(result)
- return result;
- }
break;
case FTP_CCC:
@@ -2768,16 +2766,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* First shut down the SSL layer (note: this call will block) */
result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
- if(result) {
+ if(result)
failf(conn->data, "Failed to clear the command channel (CCC)");
- return result;
- }
}
-
- /* Then continue as normal */
- result = ftp_state_pwd(conn);
- if(result)
- return result;
+ if(!result)
+ /* Then continue as normal */
+ result = ftp_state_pwd(conn);
break;
case FTP_PWD:
@@ -2843,7 +2837,6 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
systems. */
if(!ftpc->server_os && dir[0] != '/') {
-
result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
if(result) {
free(dir);
@@ -2939,12 +2932,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode >= 400) && !ftpc->count2) {
/* failure response code, and not allowed to fail */
failf(conn->data, "QUOT command failed with %03d", ftpcode);
- return CURLE_QUOTE_ERROR;
+ result = CURLE_QUOTE_ERROR;
}
- result = ftp_state_quote(conn, FALSE, ftpc->state);
- if(result)
- return result;
-
+ else
+ result = ftp_state_quote(conn, FALSE, ftpc->state);
break;
case FTP_CWD:
@@ -2954,29 +2945,28 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
ftpc->cwdcount && !ftpc->count2) {
/* try making it */
ftpc->count2++; /* counter to prevent CWD-MKD loops */
- PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- state(conn, FTP_MKD);
+ result = Curl_pp_sendf(&ftpc->pp, "MKD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ if(!result)
+ state(conn, FTP_MKD);
}
else {
/* return failure */
failf(data, "Server denied you to change to the given directory");
ftpc->cwdfail = TRUE; /* don't remember this path as we failed
to enter it */
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
}
}
else {
/* success */
ftpc->count2 = 0;
- if(++ftpc->cwdcount <= ftpc->dirdepth) {
+ if(++ftpc->cwdcount <= ftpc->dirdepth)
/* send next CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- }
- else {
+ result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ else
result = ftp_state_mdtm(conn);
- if(result)
- return result;
- }
}
break;
@@ -2984,11 +2974,14 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode/100 != 2) && !ftpc->count3--) {
/* failure to MKD the dir */
failf(data, "Failed to MKD dir: %03d", ftpcode);
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else {
+ state(conn, FTP_CWD);
+ /* send CWD */
+ result = Curl_pp_sendf(&ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
}
- state(conn, FTP_CWD);
- /* send CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
break;
case FTP_MDTM:
@@ -3091,7 +3084,7 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
*
*/
static CURLcode ftp_connect(struct connectdata *conn,
- bool *done) /* see description above */
+ bool *done) /* see description above */
{
CURLcode result;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -3112,8 +3105,10 @@ static CURLcode ftp_connect(struct connectdata *conn,
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result)
return result;
+ conn->bits.ftp_use_control_ssl = TRUE;
}
+ Curl_pp_setup(pp); /* once per transfer */
Curl_pp_init(pp); /* init the generic pingpong data */
/* When we connect, we start in the state where we await the 220
@@ -3297,9 +3292,18 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(!ftpc->dont_check) {
/* 226 Transfer complete, 250 Requested file action okay, completed. */
- if((ftpcode != 226) && (ftpcode != 250)) {
+ switch(ftpcode) {
+ case 226:
+ case 250:
+ break;
+ case 552:
+ failf(data, "Exceeded storage allocation");
+ result = CURLE_REMOTE_DISK_FULL;
+ break;
+ default:
failf(data, "server did not report OK, got %d", ftpcode);
result = CURLE_PARTIAL_FILE;
+ break;
}
}
}
@@ -3368,17 +3372,17 @@ static
CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
{
struct curl_slist *item;
- ssize_t nread;
- int ftpcode;
- CURLcode result;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
item = quote;
while(item) {
if(item->data) {
+ ssize_t nread;
char *cmd = item->data;
bool acceptfail = FALSE;
+ CURLcode result;
+ int ftpcode = 0;
/* if a command starts with an asterisk, which a legal FTP command never
can, the command will be allowed to fail without it causing any
@@ -3390,11 +3394,11 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
acceptfail = TRUE;
}
- PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
-
- pp->response = Curl_now(); /* timeout relative now */
-
- result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ result = Curl_pp_sendf(&ftpc->pp, "%s", cmd);
+ if(!result) {
+ pp->response = Curl_now(); /* timeout relative now */
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ }
if(result)
return result;
@@ -3442,12 +3446,14 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
return ftp_state_type_resp(conn, 200, newstate);
}
- PPSENDF(&ftpc->pp, "TYPE %c", want);
- state(conn, newstate);
+ result = Curl_pp_sendf(&ftpc->pp, "TYPE %c", want);
+ if(!result) {
+ state(conn, newstate);
- /* keep track of our current transfer type */
- ftpc->transfertype = want;
- return CURLE_OK;
+ /* keep track of our current transfer type */
+ ftpc->transfertype = want;
+ }
+ return result;
}
/***************************************************************************
@@ -3947,64 +3953,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
return result;
}
-
-CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
-{
- ssize_t bytes_written;
-#define SBUF_SIZE 1024
- char s[SBUF_SIZE];
- size_t write_len;
- char *sptr = s;
- CURLcode result = CURLE_OK;
-#ifdef HAVE_GSSAPI
- enum protection_level data_sec = conn->data_prot;
-#endif
-
- if(!cmd)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- write_len = strlen(cmd);
- if(!write_len || write_len > (sizeof(s) -3))
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- memcpy(&s, cmd, write_len);
- strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
- write_len += 2;
- bytes_written = 0;
-
- result = Curl_convert_to_network(conn->data, s, write_len);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(result)
- return result;
-
- for(;;) {
-#ifdef HAVE_GSSAPI
- conn->data_prot = PROT_CMD;
-#endif
- result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
- &bytes_written);
-#ifdef HAVE_GSSAPI
- DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
- conn->data_prot = data_sec;
-#endif
-
- if(result)
- break;
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
-
- if(bytes_written != (ssize_t)write_len) {
- write_len -= bytes_written;
- sptr += bytes_written;
- }
- else
- break;
- }
-
- return result;
-}
-
/***********************************************************************
*
* ftp_quit()
@@ -4068,22 +4016,14 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
data->state.most_recent_ftp_entrypath = NULL;
}
- free(ftpc->entrypath);
- ftpc->entrypath = NULL;
+ Curl_safefree(ftpc->entrypath);
}
freedirs(ftpc);
- free(ftpc->prevpath);
- ftpc->prevpath = NULL;
- free(ftpc->server_os);
- ftpc->server_os = NULL;
-
+ Curl_safefree(ftpc->prevpath);
+ Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
-
-#ifdef HAVE_GSSAPI
Curl_sec_end(conn);
-#endif
-
return CURLE_OK;
}