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:
Daniel Stenberg 2001-09-28 08:58:18 +00:00
Родитель 4d13b2cc64
Коммит 8333644c84
1 изменённых файлов: 555 добавлений и 499 удалений

320
lib/ftp.c
Просмотреть файл

@ -92,8 +92,8 @@
#endif
/* Local API functions */
static CURLcode _ftp_sendquote(struct connectdata *conn, struct curl_slist *quote);
static CURLcode _ftp_cwd(struct connectdata *conn, char *path);
static CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote);
static CURLcode ftp_cwd(struct connectdata *conn, char *path);
/* easy-to-use macro: */
#define ftpsendf Curl_ftpsendf
@ -590,7 +590,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
/* Send any post-transfer QUOTE strings? */
if(data->set.postquote) {
CURLcode result = _ftp_sendquote(conn, data->set.postquote);
CURLcode result = ftp_sendquote(conn, data->set.postquote);
return result;
}
@ -599,7 +599,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
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;
ssize_t nread;
@ -628,7 +628,7 @@ CURLcode _ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
}
static
CURLcode _ftp_cwd(struct connectdata *conn, char *path)
CURLcode ftp_cwd(struct connectdata *conn, char *path)
{
ssize_t nread;
int ftpcode;
@ -648,7 +648,7 @@ CURLcode _ftp_cwd(struct connectdata *conn, char *path)
}
static
CURLcode _ftp_getfiletime(struct connectdata *conn, char *file)
CURLcode ftp_getfiletime(struct connectdata *conn, char *file)
{
CURLcode result=CURLE_OK;
int ftpcode; /* for ftp status */
@ -683,7 +683,7 @@ CURLcode _ftp_getfiletime(struct connectdata *conn, char *file)
return result;
}
static CURLcode _ftp_transfertype(struct connectdata *conn,
static CURLcode ftp_transfertype(struct connectdata *conn,
bool ascii)
{
struct SessionHandle *data = conn->data;
@ -707,7 +707,7 @@ static CURLcode _ftp_transfertype(struct connectdata *conn,
}
static
CURLcode _ftp_getsize(struct connectdata *conn, char *file,
CURLcode ftp_getsize(struct connectdata *conn, char *file,
ssize_t *size)
{
struct SessionHandle *data = conn->data;
@ -741,12 +741,9 @@ CURLcode _ftp_getsize(struct connectdata *conn, char *file,
*/
static void
ftp_pasv_verbose(struct connectdata *conn,
#ifdef ENABLE_IPV6
struct addrinfo *newhost
#else
char *newhost /* ipv4 */
#endif
)
Curl_addrinfo *addr,
char *newhost, /* ascii version */
int port)
{
#ifndef ENABLE_IPV6
/*****************************************************************
@ -757,11 +754,10 @@ ftp_pasv_verbose(struct connectdata *conn,
struct in_addr in;
struct hostent * answer;
#if defined (HAVE_INET_NTOA_R)
#ifdef HAVE_INET_NTOA_R
char ntoa_buf[64];
#endif
#ifndef ENABLE_IPV6
struct sockaddr_in serv_addr;
char hostent_buf[8192];
#endif
@ -817,11 +813,11 @@ ftp_pasv_verbose(struct connectdata *conn,
infof(conn->data, "Connecting to %s (%s) port %u\n",
answer?answer->h_name:newhost,
#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
ip_addr = inet_ntoa(in),
inet_ntoa(in),
#endif
connectport);
port);
#else
/*****************************************************************
@ -836,13 +832,13 @@ ftp_pasv_verbose(struct connectdata *conn,
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
if (getnameinfo(newhost->ai_addr, newhost->ai_addrlen,
if (getnameinfo(addr->ai_addr, addr->ai_addrlen,
nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) {
snprintf(nbuf, sizeof(nbuf), "?");
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)) {
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);
}
#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
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;
char *buf = data->state.buffer; /* this is our buffer */
/* for the ftp PORT mode */
int portsock=-1;
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = conn->proto.ftp;
ssize_t nread;
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
/******************************************************************
*
* Here's a piece of IPv6-specific code coming up
*
*/
struct addrinfo hints, *res, *ai;
struct sockaddr_storage ss;
socklen_t sslen;
@ -1076,7 +998,8 @@ CURLcode _ftp(struct connectdata *conn)
portmsgbuf[0] = '\0';
if (strcmp(*modep, "LPRT") == 0) {
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;
}
}
@ -1087,7 +1010,8 @@ CURLcode _ftp(struct connectdata *conn)
else
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
sizeof(portmsgbuf)) {
continue;
}
}
@ -1102,7 +1026,8 @@ CURLcode _ftp(struct connectdata *conn)
for (i = 0; i < plen; 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;
}
}
@ -1117,7 +1042,8 @@ CURLcode _ftp(struct connectdata *conn)
if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
continue;
} else
}
else
break;
}
@ -1132,6 +1058,11 @@ CURLcode _ftp(struct connectdata *conn)
conn->secondarysocket = portsock;
#else
/******************************************************************
*
* Here's a piece of IPv4-specific code coming up
*
*/
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr=NULL;
@ -1212,10 +1143,13 @@ CURLcode _ftp(struct connectdata *conn)
return CURLE_FTP_PORT_FAILED;
}
{
#ifdef HAVE_INET_NTOA_R
char ntoa_buf[64];
#endif
struct in_addr in;
unsigned short ip[5];
(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
char * depending on system */
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!");
return CURLE_FTP_PORT_FAILED;
}
#endif /* ENABLE_IPV6 */
#endif /* end of ipv4-specific code */
return CURLE_OK;
}
else { /* we use the PASV command */
/**********
* 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
/* no support for IPv6 passive mode yet */
char *mode[] = { "EPSV", "LPSV", "PASV", NULL };
@ -1276,10 +1227,10 @@ CURLcode _ftp(struct connectdata *conn)
Curl_addrinfo *addr;
char *hostdataptr=NULL;
#ifndef ENABLE_IPV6
char *ip_addr;
#else
#ifdef ENABLE_IPV6
struct addrinfo *ai;
#else
struct sockaddr_in serv_addr;
#endif
char *str=buf;
@ -1349,7 +1300,7 @@ CURLcode _ftp(struct connectdata *conn)
if(data->set.verbose)
/* 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;
}
@ -1369,7 +1320,7 @@ CURLcode _ftp(struct connectdata *conn)
if(data->set.verbose)
/* this just dumps information about this second connection */
ftp_pasv_verbose(conn, newhost);
ftp_pasv_verbose(conn, addr, newhost, connectport);
if(hostdataptr)
free(hostdataptr);
@ -1403,17 +1354,122 @@ CURLcode _ftp(struct connectdata *conn)
if(CURLE_OK != result)
return result;
}
} else {
}
else
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;
}
/* we have the (new) data connection ready */
/* 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;
}
/* 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");
if(data->set.upload) {
/* 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)
return result;
@ -1435,7 +1491,7 @@ CURLcode _ftp(struct connectdata *conn)
/* we could've got a specified offset from the command line,
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");
return CURLE_FTP_COULDNT_GET_SIZE;
}
@ -1510,7 +1566,7 @@ CURLcode _ftp(struct connectdata *conn)
if(data->set.ftp_use_port) {
/* 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 )
return result;
}
@ -1578,7 +1634,7 @@ CURLcode _ftp(struct connectdata *conn)
dirlist = TRUE;
/* Set type to ASCII */
result = _ftp_transfertype(conn, TRUE /* ASCII enforced */);
result = ftp_transfertype(conn, TRUE /* ASCII enforced */);
if(result)
return result;
@ -1592,7 +1648,7 @@ CURLcode _ftp(struct connectdata *conn)
}
else {
/* 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)
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. */
int foundsize=-1;
result = _ftp_getsize(conn, ftp->file, &foundsize);
result = ftp_getsize(conn, ftp->file, &foundsize);
if(CURLE_OK != result) {
infof(data, "ftp server doesn't support SIZE\n");
@ -1736,7 +1792,7 @@ CURLcode _ftp(struct connectdata *conn)
size = downloadsize;
if(data->set.ftp_use_port) {
result = AllowServerConnect(data, conn, portsock);
result = AllowServerConnect(data, conn, conn->secondarysocket);
if( result )
return result;
}
@ -1813,7 +1869,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
else
ftp->dir = NULL;
retcode = _ftp(conn);
retcode = ftp_perform(conn);
/* clean up here, success or error doesn't matter */
if(ftp->file)