mirror of https://github.com/moparisthebest/curl
moved the PORT and PASV code into separate smaller functions for readability
renamed all static ^_ftp_* functions to ^ftp_, prefixing with underscore is not nice
This commit is contained in:
parent
4d13b2cc64
commit
8333644c84
322
lib/ftp.c
322
lib/ftp.c
|
@ -92,8 +92,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Local API functions */
|
/* Local API functions */
|
||||||
static CURLcode _ftp_sendquote(struct connectdata *conn, struct curl_slist *quote);
|
static CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote);
|
||||||
static CURLcode _ftp_cwd(struct connectdata *conn, char *path);
|
static CURLcode ftp_cwd(struct connectdata *conn, char *path);
|
||||||
|
|
||||||
/* easy-to-use macro: */
|
/* easy-to-use macro: */
|
||||||
#define ftpsendf Curl_ftpsendf
|
#define ftpsendf Curl_ftpsendf
|
||||||
|
@ -590,7 +590,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
||||||
|
|
||||||
/* Send any post-transfer QUOTE strings? */
|
/* Send any post-transfer QUOTE strings? */
|
||||||
if(data->set.postquote) {
|
if(data->set.postquote) {
|
||||||
CURLcode result = _ftp_sendquote(conn, data->set.postquote);
|
CURLcode result = ftp_sendquote(conn, data->set.postquote);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +599,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
CURLcode _ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
|
CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
|
||||||
{
|
{
|
||||||
struct curl_slist *item;
|
struct curl_slist *item;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
@ -628,7 +628,7 @@ CURLcode _ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
CURLcode _ftp_cwd(struct connectdata *conn, char *path)
|
CURLcode ftp_cwd(struct connectdata *conn, char *path)
|
||||||
{
|
{
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int ftpcode;
|
int ftpcode;
|
||||||
|
@ -648,7 +648,7 @@ CURLcode _ftp_cwd(struct connectdata *conn, char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
CURLcode _ftp_getfiletime(struct connectdata *conn, char *file)
|
CURLcode ftp_getfiletime(struct connectdata *conn, char *file)
|
||||||
{
|
{
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
int ftpcode; /* for ftp status */
|
int ftpcode; /* for ftp status */
|
||||||
|
@ -683,7 +683,7 @@ CURLcode _ftp_getfiletime(struct connectdata *conn, char *file)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode _ftp_transfertype(struct connectdata *conn,
|
static CURLcode ftp_transfertype(struct connectdata *conn,
|
||||||
bool ascii)
|
bool ascii)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
@ -707,7 +707,7 @@ static CURLcode _ftp_transfertype(struct connectdata *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
CURLcode _ftp_getsize(struct connectdata *conn, char *file,
|
CURLcode ftp_getsize(struct connectdata *conn, char *file,
|
||||||
ssize_t *size)
|
ssize_t *size)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
@ -741,12 +741,9 @@ CURLcode _ftp_getsize(struct connectdata *conn, char *file,
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ftp_pasv_verbose(struct connectdata *conn,
|
ftp_pasv_verbose(struct connectdata *conn,
|
||||||
#ifdef ENABLE_IPV6
|
Curl_addrinfo *addr,
|
||||||
struct addrinfo *newhost
|
char *newhost, /* ascii version */
|
||||||
#else
|
int port)
|
||||||
char *newhost /* ipv4 */
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
#ifndef ENABLE_IPV6
|
#ifndef ENABLE_IPV6
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
|
@ -757,11 +754,10 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
struct hostent * answer;
|
struct hostent * answer;
|
||||||
|
|
||||||
#if defined (HAVE_INET_NTOA_R)
|
#ifdef HAVE_INET_NTOA_R
|
||||||
char ntoa_buf[64];
|
char ntoa_buf[64];
|
||||||
#endif
|
#endif
|
||||||
#ifndef ENABLE_IPV6
|
#ifndef ENABLE_IPV6
|
||||||
struct sockaddr_in serv_addr;
|
|
||||||
char hostent_buf[8192];
|
char hostent_buf[8192];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -817,11 +813,11 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||||
infof(conn->data, "Connecting to %s (%s) port %u\n",
|
infof(conn->data, "Connecting to %s (%s) port %u\n",
|
||||||
answer?answer->h_name:newhost,
|
answer?answer->h_name:newhost,
|
||||||
#if defined(HAVE_INET_NTOA_R)
|
#if defined(HAVE_INET_NTOA_R)
|
||||||
inet_ntoa_r(in, ip_addr=ntoa_buf, sizeof(ntoa_buf)),
|
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)),
|
||||||
#else
|
#else
|
||||||
ip_addr = inet_ntoa(in),
|
inet_ntoa(in),
|
||||||
#endif
|
#endif
|
||||||
connectport);
|
port);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
|
@ -836,13 +832,13 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||||
#else
|
#else
|
||||||
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
|
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
|
||||||
#endif
|
#endif
|
||||||
if (getnameinfo(newhost->ai_addr, newhost->ai_addrlen,
|
if (getnameinfo(addr->ai_addr, addr->ai_addrlen,
|
||||||
nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) {
|
nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) {
|
||||||
snprintf(nbuf, sizeof(nbuf), "?");
|
snprintf(nbuf, sizeof(nbuf), "?");
|
||||||
snprintf(sbuf, sizeof(sbuf), "?");
|
snprintf(sbuf, sizeof(sbuf), "?");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getnameinfo(newhost->ai_addr, newhost->ai_addrlen,
|
if (getnameinfo(addr->ai_addr, addr->ai_addrlen,
|
||||||
hbuf, sizeof(hbuf), NULL, 0, 0)) {
|
hbuf, sizeof(hbuf), NULL, 0, 0)) {
|
||||||
infof(conn->data, "Connecting to %s port %s\n", nbuf, sbuf);
|
infof(conn->data, "Connecting to %s port %s\n", nbuf, sbuf);
|
||||||
}
|
}
|
||||||
|
@ -850,104 +846,30 @@ ftp_pasv_verbose(struct connectdata *conn,
|
||||||
infof(conn->data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf);
|
infof(conn->data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* PORT is the ftp client's way of telling the server that *WE* open a port
|
||||||
|
* that we listen on an awaits the server to connect to. This is the opposite
|
||||||
|
* of PASV.
|
||||||
|
*/
|
||||||
|
|
||||||
static
|
static
|
||||||
CURLcode _ftp(struct connectdata *conn)
|
CURLcode ftp_use_port(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
/* this is FTP and no proxy */
|
|
||||||
ssize_t nread;
|
|
||||||
CURLcode result;
|
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
char *buf = data->state.buffer; /* this is our buffer */
|
|
||||||
/* for the ftp PORT mode */
|
|
||||||
int portsock=-1;
|
int portsock=-1;
|
||||||
/* the ftp struct is already inited in ftp_connect() */
|
ssize_t nread;
|
||||||
struct FTP *ftp = conn->proto.ftp;
|
char *buf = data->state.buffer; /* this is our buffer */
|
||||||
|
int ftpcode; /* receive FTP response codes in this */
|
||||||
|
|
||||||
long *bytecountp = ftp->bytecountp;
|
|
||||||
int ftpcode; /* for ftp status */
|
|
||||||
|
|
||||||
/* Send any QUOTE strings? */
|
|
||||||
if(data->set.quote) {
|
|
||||||
if ((result = _ftp_sendquote(conn, data->set.quote)) != CURLE_OK)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a re-used connection. Since we change directory to where the
|
|
||||||
transfer is taking place, we must now get back to the original dir
|
|
||||||
where we ended up after login: */
|
|
||||||
if (conn->bits.reuse) {
|
|
||||||
if ((result = _ftp_cwd(conn, ftp->entrypath)) != CURLE_OK)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* change directory first! */
|
|
||||||
if(ftp->dir && ftp->dir[0]) {
|
|
||||||
if ((result = _ftp_cwd(conn, ftp->dir)) != CURLE_OK)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Requested time of file? */
|
|
||||||
if(data->set.get_filetime && ftp->file) {
|
|
||||||
result = _ftp_getfiletime(conn, ftp->file);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have selected NOBODY, it means that we only want file information.
|
|
||||||
Which in FTP can't be much more than the file size! */
|
|
||||||
if(data->set.no_body) {
|
|
||||||
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers
|
|
||||||
may not support it! It is however the only way we have to get a file's
|
|
||||||
size! */
|
|
||||||
ssize_t filesize;
|
|
||||||
|
|
||||||
/* Some servers return different sizes for different modes, and thus we
|
|
||||||
must set the proper type before we check the size */
|
|
||||||
result = _ftp_transfertype(conn, data->set.ftp_ascii);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/* failing to get size is not a serious error */
|
|
||||||
result = _ftp_getsize(conn, ftp->file, &filesize);
|
|
||||||
|
|
||||||
if(CURLE_OK == result) {
|
|
||||||
sprintf(buf, "Content-Length: %d\r\n", filesize);
|
|
||||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we asked for a time of the file and we actually got one as
|
|
||||||
well, we "emulate" a HTTP-style header in our output. */
|
|
||||||
|
|
||||||
#ifdef HAVE_STRFTIME
|
|
||||||
if(data->set.get_filetime && data->info.filetime) {
|
|
||||||
struct tm *tm;
|
|
||||||
#ifdef HAVE_LOCALTIME_R
|
|
||||||
struct tm buffer;
|
|
||||||
tm = (struct tm *)localtime_r(&data->info.filetime, &buffer);
|
|
||||||
#else
|
|
||||||
tm = localtime(&data->info.filetime);
|
|
||||||
#endif
|
|
||||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
|
||||||
strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n",
|
|
||||||
tm);
|
|
||||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have chosen to use the PORT command */
|
|
||||||
if(data->set.ftp_use_port) {
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
|
/******************************************************************
|
||||||
|
*
|
||||||
|
* Here's a piece of IPv6-specific code coming up
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
struct addrinfo hints, *res, *ai;
|
struct addrinfo hints, *res, *ai;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
socklen_t sslen;
|
socklen_t sslen;
|
||||||
|
@ -1076,7 +998,8 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
portmsgbuf[0] = '\0';
|
portmsgbuf[0] = '\0';
|
||||||
if (strcmp(*modep, "LPRT") == 0) {
|
if (strcmp(*modep, "LPRT") == 0) {
|
||||||
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
|
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
|
||||||
|
sizeof(portmsgbuf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1087,7 +1010,8 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
else
|
else
|
||||||
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
|
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
|
||||||
|
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
|
||||||
|
sizeof(portmsgbuf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1026,8 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
for (i = 0; i < plen; i++) {
|
for (i = 0; i < plen; i++) {
|
||||||
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
|
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
|
||||||
|
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
|
||||||
|
sizeof(portmsgbuf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1117,7 +1042,8 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
if (ftpcode != 200) {
|
if (ftpcode != 200) {
|
||||||
failf(data, "Server does not grok %s", *modep);
|
failf(data, "Server does not grok %s", *modep);
|
||||||
continue;
|
continue;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,6 +1058,11 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
conn->secondarysocket = portsock;
|
conn->secondarysocket = portsock;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/******************************************************************
|
||||||
|
*
|
||||||
|
* Here's a piece of IPv4-specific code coming up
|
||||||
|
*
|
||||||
|
*/
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
struct hostent *h=NULL;
|
struct hostent *h=NULL;
|
||||||
char *hostdataptr=NULL;
|
char *hostdataptr=NULL;
|
||||||
|
@ -1212,10 +1143,13 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_INET_NTOA_R
|
||||||
|
char ntoa_buf[64];
|
||||||
|
#endif
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
unsigned short ip[5];
|
unsigned short ip[5];
|
||||||
(void) memcpy(&in.s_addr, *h->h_addr_list, sizeof (in.s_addr));
|
(void) memcpy(&in.s_addr, *h->h_addr_list, sizeof (in.s_addr));
|
||||||
#if defined (HAVE_INET_NTOA_R)
|
#ifdef HAVE_INET_NTOA_R
|
||||||
/* ignore the return code from inet_ntoa_r() as it is int or
|
/* ignore the return code from inet_ntoa_r() as it is int or
|
||||||
char * depending on system */
|
char * depending on system */
|
||||||
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf));
|
inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf));
|
||||||
|
@ -1239,9 +1173,26 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
failf(data, "Server does not grok PORT, try without it!");
|
failf(data, "Server does not grok PORT, try without it!");
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_IPV6 */
|
#endif /* end of ipv4-specific code */
|
||||||
}
|
|
||||||
else { /* we use the PASV command */
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* PASV is the ftp client's way of asking the server to open a second port
|
||||||
|
* that we can connect to (for the data transfer). This is the opposite of
|
||||||
|
* PORT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static
|
||||||
|
CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
ssize_t nread;
|
||||||
|
char *buf = data->state.buffer; /* this is our buffer */
|
||||||
|
int ftpcode; /* receive FTP response codes in this */
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* no support for IPv6 passive mode yet */
|
/* no support for IPv6 passive mode yet */
|
||||||
char *mode[] = { "EPSV", "LPSV", "PASV", NULL };
|
char *mode[] = { "EPSV", "LPSV", "PASV", NULL };
|
||||||
|
@ -1276,10 +1227,10 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
Curl_addrinfo *addr;
|
Curl_addrinfo *addr;
|
||||||
char *hostdataptr=NULL;
|
char *hostdataptr=NULL;
|
||||||
|
|
||||||
#ifndef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
char *ip_addr;
|
|
||||||
#else
|
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
|
#else
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
#endif
|
#endif
|
||||||
char *str=buf;
|
char *str=buf;
|
||||||
|
|
||||||
|
@ -1349,7 +1300,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
|
|
||||||
if(data->set.verbose)
|
if(data->set.verbose)
|
||||||
/* this just dumps information about this second connection */
|
/* this just dumps information about this second connection */
|
||||||
ftp_pasv_verbose(conn, ai);
|
ftp_pasv_verbose(conn, ai, newhost, 0 /* port not really known */);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1369,7 +1320,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
|
|
||||||
if(data->set.verbose)
|
if(data->set.verbose)
|
||||||
/* this just dumps information about this second connection */
|
/* this just dumps information about this second connection */
|
||||||
ftp_pasv_verbose(conn, newhost);
|
ftp_pasv_verbose(conn, addr, newhost, connectport);
|
||||||
|
|
||||||
if(hostdataptr)
|
if(hostdataptr)
|
||||||
free(hostdataptr);
|
free(hostdataptr);
|
||||||
|
@ -1403,17 +1354,122 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
if(CURLE_OK != result)
|
if(CURLE_OK != result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
return CURLE_FTP_CANT_RECONNECT;
|
return CURLE_FTP_CANT_RECONNECT;
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
CURLcode ftp_perform(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
/* this is FTP and no proxy */
|
||||||
|
ssize_t nread;
|
||||||
|
CURLcode result;
|
||||||
|
struct SessionHandle *data=conn->data;
|
||||||
|
char *buf = data->state.buffer; /* this is our buffer */
|
||||||
|
|
||||||
|
/* the ftp struct is already inited in ftp_connect() */
|
||||||
|
struct FTP *ftp = conn->proto.ftp;
|
||||||
|
|
||||||
|
long *bytecountp = ftp->bytecountp;
|
||||||
|
int ftpcode; /* for ftp status */
|
||||||
|
|
||||||
|
/* Send any QUOTE strings? */
|
||||||
|
if(data->set.quote) {
|
||||||
|
if ((result = ftp_sendquote(conn, data->set.quote)) != CURLE_OK)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is a re-used connection. Since we change directory to where the
|
||||||
|
transfer is taking place, we must now get back to the original dir
|
||||||
|
where we ended up after login: */
|
||||||
|
if (conn->bits.reuse) {
|
||||||
|
if ((result = ftp_cwd(conn, ftp->entrypath)) != CURLE_OK)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
/* we have the (new) data connection ready */
|
|
||||||
|
/* change directory first! */
|
||||||
|
if(ftp->dir && ftp->dir[0]) {
|
||||||
|
if ((result = ftp_cwd(conn, ftp->dir)) != CURLE_OK)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Requested time of file? */
|
||||||
|
if(data->set.get_filetime && ftp->file) {
|
||||||
|
result = ftp_getfiletime(conn, ftp->file);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have selected NOBODY, it means that we only want file information.
|
||||||
|
Which in FTP can't be much more than the file size! */
|
||||||
|
if(data->set.no_body) {
|
||||||
|
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers
|
||||||
|
may not support it! It is however the only way we have to get a file's
|
||||||
|
size! */
|
||||||
|
ssize_t filesize;
|
||||||
|
|
||||||
|
/* Some servers return different sizes for different modes, and thus we
|
||||||
|
must set the proper type before we check the size */
|
||||||
|
result = ftp_transfertype(conn, data->set.ftp_ascii);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* failing to get size is not a serious error */
|
||||||
|
result = ftp_getsize(conn, ftp->file, &filesize);
|
||||||
|
|
||||||
|
if(CURLE_OK == result) {
|
||||||
|
sprintf(buf, "Content-Length: %d\r\n", filesize);
|
||||||
|
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we asked for a time of the file and we actually got one as
|
||||||
|
well, we "emulate" a HTTP-style header in our output. */
|
||||||
|
|
||||||
|
#ifdef HAVE_STRFTIME
|
||||||
|
if(data->set.get_filetime && data->info.filetime) {
|
||||||
|
struct tm *tm;
|
||||||
|
#ifdef HAVE_LOCALTIME_R
|
||||||
|
struct tm buffer;
|
||||||
|
tm = (struct tm *)localtime_r(&data->info.filetime, &buffer);
|
||||||
|
#else
|
||||||
|
tm = localtime(&data->info.filetime);
|
||||||
|
#endif
|
||||||
|
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||||
|
strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n",
|
||||||
|
tm);
|
||||||
|
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get us a second connection up and connected */
|
||||||
|
if(data->set.ftp_use_port)
|
||||||
|
/* We have chosen to use the PORT command */
|
||||||
|
result = ftp_use_port(conn);
|
||||||
|
else
|
||||||
|
/* We have chosen (this is default) to use the PASV command */
|
||||||
|
result = ftp_use_pasv(conn);
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* we have the data connection ready */
|
||||||
infof(data, "Connected the data stream!\n");
|
infof(data, "Connected the data stream!\n");
|
||||||
|
|
||||||
if(data->set.upload) {
|
if(data->set.upload) {
|
||||||
|
|
||||||
/* Set type to binary (unless specified ASCII) */
|
/* Set type to binary (unless specified ASCII) */
|
||||||
result = _ftp_transfertype(conn, data->set.ftp_ascii);
|
result = ftp_transfertype(conn, data->set.ftp_ascii);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -1435,7 +1491,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
/* we could've got a specified offset from the command line,
|
/* we could've got a specified offset from the command line,
|
||||||
but now we know we didn't */
|
but now we know we didn't */
|
||||||
|
|
||||||
if(CURLE_OK != _ftp_getsize(conn, ftp->file, &conn->resume_from)) {
|
if(CURLE_OK != ftp_getsize(conn, ftp->file, &conn->resume_from)) {
|
||||||
failf(data, "Couldn't get remote file size");
|
failf(data, "Couldn't get remote file size");
|
||||||
return CURLE_FTP_COULDNT_GET_SIZE;
|
return CURLE_FTP_COULDNT_GET_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -1510,7 +1566,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
|
|
||||||
if(data->set.ftp_use_port) {
|
if(data->set.ftp_use_port) {
|
||||||
/* PORT means we are now awaiting the server to connect to us. */
|
/* PORT means we are now awaiting the server to connect to us. */
|
||||||
result = AllowServerConnect(data, conn, portsock);
|
result = AllowServerConnect(data, conn, conn->secondarysocket);
|
||||||
if( result )
|
if( result )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1578,7 +1634,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
dirlist = TRUE;
|
dirlist = TRUE;
|
||||||
|
|
||||||
/* Set type to ASCII */
|
/* Set type to ASCII */
|
||||||
result = _ftp_transfertype(conn, TRUE /* ASCII enforced */);
|
result = ftp_transfertype(conn, TRUE /* ASCII enforced */);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -1592,7 +1648,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Set type to binary (unless specified ASCII) */
|
/* Set type to binary (unless specified ASCII) */
|
||||||
result = _ftp_transfertype(conn, data->set.ftp_ascii);
|
result = ftp_transfertype(conn, data->set.ftp_ascii);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -1605,7 +1661,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
* the best way to know if we're trying to resume beyond the EOF. */
|
* the best way to know if we're trying to resume beyond the EOF. */
|
||||||
int foundsize=-1;
|
int foundsize=-1;
|
||||||
|
|
||||||
result = _ftp_getsize(conn, ftp->file, &foundsize);
|
result = ftp_getsize(conn, ftp->file, &foundsize);
|
||||||
|
|
||||||
if(CURLE_OK != result) {
|
if(CURLE_OK != result) {
|
||||||
infof(data, "ftp server doesn't support SIZE\n");
|
infof(data, "ftp server doesn't support SIZE\n");
|
||||||
|
@ -1736,7 +1792,7 @@ CURLcode _ftp(struct connectdata *conn)
|
||||||
size = downloadsize;
|
size = downloadsize;
|
||||||
|
|
||||||
if(data->set.ftp_use_port) {
|
if(data->set.ftp_use_port) {
|
||||||
result = AllowServerConnect(data, conn, portsock);
|
result = AllowServerConnect(data, conn, conn->secondarysocket);
|
||||||
if( result )
|
if( result )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1813,7 +1869,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
|
||||||
else
|
else
|
||||||
ftp->dir = NULL;
|
ftp->dir = NULL;
|
||||||
|
|
||||||
retcode = _ftp(conn);
|
retcode = ftp_perform(conn);
|
||||||
|
|
||||||
/* clean up here, success or error doesn't matter */
|
/* clean up here, success or error doesn't matter */
|
||||||
if(ftp->file)
|
if(ftp->file)
|
||||||
|
|
Loading…
Reference in New Issue