Newer
Older
/* We need a file name when uploading. Return error! */
failf(data, "Uploading to a URL without a file name!");
return CURLE_URL_MALFORMAT;
}
ftpc->cwddone = FALSE; /* default to not done */
if(ftpc->prevpath) {
Daniel Stenberg
committed
/* prevpath is "raw" so we convert the input path before we compare the
strings */
Daniel Stenberg
committed
char *path = curl_easy_unescape(conn->data, data->state.path, 0, NULL);
Daniel Stenberg
committed
freedirs(ftpc);
Daniel Stenberg
committed
return CURLE_OUT_OF_MEMORY;
Daniel Stenberg
committed
dlen = strlen(path) - (ftpc->file?strlen(ftpc->file):0);
if((dlen == strlen(ftpc->prevpath)) &&
curl_strnequal(path, ftpc->prevpath, dlen)) {
infof(data, "Request has same path as previous transfer\n");
ftpc->cwddone = TRUE;
Daniel Stenberg
committed
free(path);
Daniel Stenberg
committed
}
/* call this when the DO phase has completed */
static CURLcode ftp_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
Daniel Stenberg
committed
struct FTP *ftp = conn->data->state.proto.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(connected)
result = ftp_nextconnect(conn);
if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) {
/* Failure detected, close the second socket if it was created already */
sclose(conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
}
if(ftp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else if(!connected)
/* since we didn't connect now, we want do_more to get called */
conn->bits.do_more = TRUE;
ftpc->ctl_valid = TRUE; /* seems good */
return result;
}
/* called from multi.c while DOing */
static CURLcode ftp_doing(struct connectdata *conn,
Patrick Monnerat
committed
bool *dophase_done)
{
CURLcode result;
result = ftp_multi_statemach(conn, dophase_done);
if(*dophase_done) {
result = ftp_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
return result;
}
Daniel Stenberg
committed
/***********************************************************************
*
* ftp_regular_transfer()
*
* The input argument is already checked for validity.
*
* Performs all commands done before a regular transfer between a local and a
* remote host.
Daniel Stenberg
committed
*
* ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
* ftp_done() function without finding any major problem.
Daniel Stenberg
committed
*/
static
CURLcode ftp_regular_transfer(struct connectdata *conn,
bool *dophase_done)
Daniel Stenberg
committed
{
CURLcode result=CURLE_OK;
Daniel Stenberg
committed
bool connected=0;
struct SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
Daniel Stenberg
committed
data->req.size = -1; /* make sure this is unknown at this point */
Daniel Stenberg
committed
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0);
ftpc->ctl_valid = TRUE; /* starts good */
result = ftp_perform(conn,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
if(CURLE_OK == result) {
if(!*dophase_done)
/* the DO phase has not completed yet */
return CURLE_OK;
result = ftp_dophase_done(conn, connected);
if(result)
return result;
}
else
Daniel Stenberg
committed
freedirs(ftpc);
return result;
}
static CURLcode ftp_setup_connection(struct connectdata * conn)
Patrick Monnerat
committed
{
struct SessionHandle *data = conn->data;
char * type;
char command;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel ftp operations through the proxy, we
switch and use HTTP operations only */
#ifndef CURL_DISABLE_HTTP
Daniel Stenberg
committed
if(conn->handler == &Curl_handler_ftp)
conn->handler = &Curl_handler_ftp_proxy;
else {
#ifdef USE_SSL
conn->handler = &Curl_handler_ftps_proxy;
#else
failf(data, "FTPS not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
Patrick Monnerat
committed
#else
failf(data, "FTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
Daniel Stenberg
committed
data->state.path++; /* don't include the initial slash */
Patrick Monnerat
committed
/* FTP URLs support an extension like ";type=<typecode>" that
* we'll try to get now! */
Daniel Stenberg
committed
type = strstr(data->state.path, ";type=");
Patrick Monnerat
committed
Daniel Stenberg
committed
if(!type)
Patrick Monnerat
committed
type = strstr(conn->host.rawalloc, ";type=");
Daniel Stenberg
committed
if(type) {
Patrick Monnerat
committed
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
*type = 0; /* it was in the middle of the hostname */
command = (char) toupper((int) type[6]);
switch (command) {
case 'A': /* ASCII mode */
data->set.prefer_ascii = TRUE;
break;
case 'D': /* directory mode */
data->set.ftp_list_only = TRUE;
break;
case 'I': /* binary mode */
default:
/* switch off ASCII */
data->set.prefer_ascii = FALSE;
break;
}
}
return CURLE_OK;
}
#ifdef USE_SSL
static CURLcode ftps_setup_connection(struct connectdata * conn)
Patrick Monnerat
committed
{
struct SessionHandle *data = conn->data;
conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLUSESSL_CONTROL;
return ftp_setup_connection(conn);
Patrick Monnerat
committed
}
#endif
#endif /* CURL_DISABLE_FTP */