aboutsummaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c436
1 files changed, 269 insertions, 167 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 4af86fb48..0844cc78a 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -149,7 +149,7 @@ void curl_slist_free_all(struct curl_slist *list)
}
-static UrgError AllowServerConnect(struct UrlData *data,
+static CURLcode AllowServerConnect(struct UrlData *data,
int sock)
{
fd_set rdset;
@@ -167,11 +167,11 @@ static UrgError AllowServerConnect(struct UrlData *data,
case -1: /* error */
/* let's die here */
failf(data, "Error while waiting for server connect");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
case 0: /* timeout */
/* let's die here */
failf(data, "Timeout while waiting for server connect");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
default:
/* we have received data here */
{
@@ -185,7 +185,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
if( -1 == s) {
/* DIE! */
failf(data, "Error accept()ing server connect");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
infof(data, "Connection accepted from server\n");
@@ -193,7 +193,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
}
break;
}
- return URG_OK;
+ return CURLE_OK;
}
@@ -202,7 +202,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3]))
-static int GetLastResponse(int sockfd, char *buf,
+int GetLastResponse(int sockfd, char *buf,
struct UrlData *data)
{
int nread;
@@ -230,7 +230,7 @@ static int GetLastResponse(int sockfd, char *buf,
}
*ptr=0; /* zero terminate */
- if(data->conf & CONF_VERBOSE) {
+ if(data->bits.verbose) {
fputs("< ", data->err);
fwrite(buf, 1, nread, data->err);
fputs("\n", data->err);
@@ -310,32 +310,37 @@ static char *URLfix(char *string)
}
#endif
-static
-UrgError _ftp(struct UrlData *data,
- long *bytecountp,
- char *ftpuser,
- char *ftppasswd,
- char *ppath)
+/* ftp_connect() should do everything that is to be considered a part
+ of the connection phase. */
+CURLcode ftp_connect(struct connectdata *conn)
{
/* this is FTP and no proxy */
size_t nread;
- UrgError result;
+ struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */
- /* for the ftp PORT mode */
- int portsock=-1;
- struct sockaddr_in serv_addr;
+ struct FTP *ftp;
- struct curl_slist *qitem; /* QUOTE item */
+ ftp = (struct FTP *)malloc(sizeof(struct FTP));
+ if(!ftp)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(ftp, 0, sizeof(struct FTP));
+ data->proto.ftp = ftp;
+
+ /* get some initial data into the ftp struct */
+ ftp->bytecountp = &conn->bytecount;
+ ftp->user = data->user;
+ ftp->passwd = data->passwd;
/* The first thing we do is wait for the "220*" line: */
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "220", 3)) {
failf(data, "This doesn't seem like a nice ftp-server response");
- return URG_FTP_WEIRD_SERVER_REPLY;
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
}
/* send USER */
- sendf(data->firstsocket, data, "USER %s\r\n", ftpuser);
+ sendf(data->firstsocket, data, "USER %s\r\n", ftp->user);
/* wait for feedback */
nread = GetLastResponse(data->firstsocket, buf, data);
@@ -344,19 +349,19 @@ UrgError _ftp(struct UrlData *data,
/* 530 User ... access denied
(the server denies to log the specified user) */
failf(data, "Access denied: %s", &buf[4]);
- return URG_FTP_ACCESS_DENIED;
+ return CURLE_FTP_ACCESS_DENIED;
}
else if(!strncmp(buf, "331", 3)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
- sendf(data->firstsocket, data, "PASS %s\r\n", ftppasswd);
+ sendf(data->firstsocket, data, "PASS %s\r\n", ftp->passwd);
nread = GetLastResponse(data->firstsocket, buf, data);
if(!strncmp(buf, "530", 3)) {
/* 530 Login incorrect.
(the username and/or the password are incorrect) */
failf(data, "the username and/or the password are incorrect");
- return URG_FTP_USER_PASSWORD_INCORRECT;
+ return CURLE_FTP_USER_PASSWORD_INCORRECT;
}
else if(!strncmp(buf, "230", 3)) {
/* 230 User ... logged in.
@@ -366,7 +371,7 @@ UrgError _ftp(struct UrlData *data,
}
else {
failf(data, "Odd return code after PASS");
- return URG_FTP_WEIRD_PASS_REPLY;
+ return CURLE_FTP_WEIRD_PASS_REPLY;
}
}
else if(! strncmp(buf, "230", 3)) {
@@ -376,9 +381,105 @@ UrgError _ftp(struct UrlData *data,
}
else {
failf(data, "Odd return code after USER");
- return URG_FTP_WEIRD_USER_REPLY;
+ return CURLE_FTP_WEIRD_USER_REPLY;
+ }
+
+ return CURLE_OK;
+}
+
+
+/* argument is already checked for validity */
+CURLcode ftp_done(struct connectdata *conn)
+{
+ struct UrlData *data = conn->data;
+ struct FTP *ftp = data->proto.ftp;
+ size_t nread;
+ char *buf = data->buffer; /* this is our buffer */
+ struct curl_slist *qitem; /* QUOTE item */
+
+ if(data->bits.upload) {
+ if((-1 != data->infilesize) && (data->infilesize != *ftp->bytecountp)) {
+ failf(data, "Wrote only partial file (%d out of %d bytes)",
+ *ftp->bytecountp, data->infilesize);
+ return CURLE_PARTIAL_FILE;
+ }
+ }
+ else {
+ if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
+ (data->maxdownload != *ftp->bytecountp)) {
+ failf(data, "Received only partial file");
+ return CURLE_PARTIAL_FILE;
+ }
+ else if(0 == *ftp->bytecountp) {
+ failf(data, "No data was received!");
+ return CURLE_FTP_COULDNT_RETR_FILE;
+ }
+ }
+ /* shut down the socket to inform the server we're done */
+ sclose(data->secondarysocket);
+ data->secondarysocket = -1;
+
+ /* now let's see what the server says about the transfer we
+ just performed: */
+ nread = GetLastResponse(data->firstsocket, buf, data);
+
+ /* 226 Transfer complete */
+ if(strncmp(buf, "226", 3)) {
+ failf(data, "%s", buf+4);
+ return CURLE_FTP_WRITE_ERROR;
+ }
+
+ /* Send any post-transfer QUOTE strings? */
+ if(data->postquote) {
+ qitem = data->postquote;
+ /* Send all QUOTE strings in same order as on command-line */
+ while (qitem) {
+ /* Send string */
+ if (qitem->data) {
+ sendf(data->firstsocket, data, "%s\r\n", qitem->data);
+
+ nread = GetLastResponse(data->firstsocket, buf, data);
+
+ if (buf[0] != '2') {
+ failf(data, "QUOT string not accepted: %s",
+ qitem->data);
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+ }
+ qitem = qitem->next;
+ }
}
+ if(ftp->file)
+ free(ftp->file);
+ if(ftp->dir)
+ free(ftp->dir);
+
+ /* TBD: the ftp struct is still allocated here */
+
+ return CURLE_OK;
+}
+
+
+
+static
+CURLcode _ftp(struct connectdata *conn)
+{
+ /* this is FTP and no proxy */
+ size_t nread;
+ CURLcode result;
+ struct UrlData *data=conn->data;
+ char *buf = data->buffer; /* this is our buffer */
+ /* for the ftp PORT mode */
+ int portsock=-1;
+ struct sockaddr_in serv_addr;
+
+ struct curl_slist *qitem; /* QUOTE item */
+ /* the ftp struct is already inited in ftp_connect() */
+ struct FTP *ftp = data->proto.ftp;
+
+ long *bytecountp = ftp->bytecountp;
+
/* Send any QUOTE strings? */
if(data->quote) {
qitem = data->quote;
@@ -393,7 +494,7 @@ UrgError _ftp(struct UrlData *data,
if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s",
qitem->data);
- return URG_FTP_QUOTE_ERROR;
+ return CURLE_FTP_QUOTE_ERROR;
}
}
qitem = qitem->next;
@@ -402,18 +503,18 @@ UrgError _ftp(struct UrlData *data,
/* 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->conf & CONF_NOBODY) {
+ if(data->bits.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! */
int filesize;
- sendf(data->firstsocket, data, "SIZE %s\r\n", ppath);
+ sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4);
- return URG_FTP_COULDNT_GET_SIZE;
+ return CURLE_FTP_COULDNT_GET_SIZE;
}
/* get the size from the ascii string: */
filesize = atoi(buf+4);
@@ -422,21 +523,21 @@ UrgError _ftp(struct UrlData *data,
if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) {
failf (data, "Failed writing output");
- return URG_WRITE_ERROR;
+ return CURLE_WRITE_ERROR;
}
if(data->writeheader) {
/* the header is requested to be written to this file */
if(strlen(buf) != data->fwrite (buf, 1, strlen(buf),
data->writeheader)) {
failf (data, "Failed writing output");
- return URG_WRITE_ERROR;
+ return CURLE_WRITE_ERROR;
}
}
- return URG_OK;
+ return CURLE_OK;
}
/* We have chosen to use the PORT command */
- if(data->conf & CONF_FTPPORT) {
+ if(data->bits.ftp_use_port) {
struct sockaddr_in sa;
struct hostent *h=NULL;
size_t size;
@@ -481,28 +582,28 @@ UrgError _ftp(struct UrlData *data,
if(getsockname(portsock, (struct sockaddr *) &add,
(int *)&size)<0) {
failf(data, "getsockname() failed");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
porttouse = ntohs(add.sin_port);
if ( listen(portsock, 1) < 0 ) {
failf(data, "listen(2) failed on socket");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
}
else {
failf(data, "bind(2) failed on socket");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
}
else {
failf(data, "socket(2) failed (%s)");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
}
else {
failf(data, "could't find my own IP address (%s)", myhost);
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
{
struct in_addr in;
@@ -520,7 +621,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) {
failf(data, "Server does not grok PORT, try without it!");
- return URG_FTP_PORT_FAILED;
+ return CURLE_FTP_PORT_FAILED;
}
}
else { /* we use the PASV command */
@@ -531,7 +632,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "227", 3)) {
failf(data, "Odd return code after PASV");
- return URG_FTP_WEIRD_PASV_REPLY;
+ return CURLE_FTP_WEIRD_PASV_REPLY;
}
else {
int ip[4];
@@ -561,13 +662,13 @@ UrgError _ftp(struct UrlData *data,
}
if(!*str) {
failf(data, "Couldn't interpret this 227-reply: %s", buf);
- return URG_FTP_WEIRD_227_FORMAT;
+ return CURLE_FTP_WEIRD_227_FORMAT;
}
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
he = GetHost(data, newhost);
if(!he) {
failf(data, "Can't resolve new host %s", newhost);
- return URG_FTP_CANT_GET_HOST;
+ return CURLE_FTP_CANT_GET_HOST;
}
@@ -579,7 +680,7 @@ UrgError _ftp(struct UrlData *data,
serv_addr.sin_family = he->h_addrtype;
serv_addr.sin_port = htons(newport);
- if(data->conf & CONF_VERBOSE) {
+ if(data->bits.verbose) {
struct in_addr in;
#if 1
struct hostent * answer;
@@ -620,26 +721,38 @@ UrgError _ftp(struct UrlData *data,
failf(data, "Can't connect to ftp server");
break;
}
- return URG_FTP_CANT_RECONNECT;
+ return CURLE_FTP_CANT_RECONNECT;
}
}
}
/* we have the (new) data connection ready */
- if(data->conf & CONF_UPLOAD) {
+ /* change directory first */
+
+ if(ftp->dir && ftp->dir[0]) {
+ sendf(data->firstsocket, data, "CWD %s\r\n", ftp->dir);
+ nread = GetLastResponse(data->firstsocket, buf, data);
+
+ if(strncmp(buf, "250", 3)) {
+ failf(data, "Couldn't change to directory %s", ftp->dir);
+ return CURLE_FTP_ACCESS_DENIED;
+ }
+ }
+
+ if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n",
- (data->conf&CONF_FTPASCII)?"A":"I");
+ (data->bits.ftp_ascii)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode",
- (data->conf&CONF_FTPASCII)?"ASCII":"binary");
- return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII:
- URG_FTP_COULDNT_SET_BINARY;
+ (data->bits.ftp_ascii)?"ASCII":"binary");
+ return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
+ CURLE_FTP_COULDNT_SET_BINARY;
}
if(data->resume_from) {
@@ -660,13 +773,13 @@ UrgError _ftp(struct UrlData *data,
/* we could've got a specified offset from the command line,
but now we know we didn't */
- sendf(data->firstsocket, data, "SIZE %s\r\n", ppath);
+ sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4);
- return URG_FTP_COULDNT_GET_SIZE;
+ return CURLE_FTP_COULDNT_GET_SIZE;
}
/* get the size from the ascii string: */
@@ -687,11 +800,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4);
- return URG_FTP_COULDNT_USE_REST;
+ return CURLE_FTP_COULDNT_USE_REST;
}
#else
/* enable append instead */
- data->conf |= CONF_FTPAPPEND;
+ data->bits.ftp_append = 1;
#endif
/* Now, let's read off the proper amount of bytes from the
input. If we knew it was a proper file we could've just
@@ -710,7 +823,7 @@ UrgError _ftp(struct UrlData *data,
if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n",
passed);
- return URG_FTP_COULDNT_USE_REST;
+ return CURLE_FTP_COULDNT_USE_REST;
}
}
while(passed != data->resume_from);
@@ -721,7 +834,7 @@ UrgError _ftp(struct UrlData *data,
if(data->infilesize <= 0) {
infof(data, "File already completely uploaded\n");
- return URG_OK;
+ return CURLE_OK;
}
}
/* we've passed, proceed as normal */
@@ -729,21 +842,21 @@ UrgError _ftp(struct UrlData *data,
}
/* Send everything on data->in to the socket */
- if(data->conf & CONF_FTPAPPEND)
+ if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */
- sendf(data->firstsocket, data, "APPE %s\r\n", ppath);
+ sendf(data->firstsocket, data, "APPE %s\r\n", ftp->file);
else
- sendf(data->firstsocket, data, "STOR %s\r\n", ppath);
+ sendf(data->firstsocket, data, "STOR %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data);
if(atoi(buf)>=400) {
failf(data, "Failed FTP upload:%s", buf+3);
/* oops, we never close the sockets! */
- return URG_FTP_COULDNT_STOR_FILE;
+ return CURLE_FTP_COULDNT_STOR_FILE;
}
- if(data->conf & CONF_FTPPORT) {
+ if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
if( result )
return result;
@@ -758,24 +871,19 @@ UrgError _ftp(struct UrlData *data,
#if 0
ProgressInit(data, data->infilesize);
#endif
- result = Transfer(data, -1, -1, FALSE, NULL, /* no download */
+ result = Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp);
if(result)
return result;
- if((-1 != data->infilesize) && (data->infilesize != *bytecountp)) {
- failf(data, "Wrote only partial file (%d out of %d bytes)",
- *bytecountp, data->infilesize);
- return URG_PARTIAL_FILE;
- }
}
else {
/* Retrieve file or directory */
bool dirlist=FALSE;
long downloadsize=-1;
- if(data->conf&CONF_RANGE && data->range) {
- int from, to;
+ if(data->bits.set_range && data->range) {
+ long from, to;
int totalsize=-1;
char *ptr;
char *ptr2;
@@ -788,32 +896,34 @@ UrgError _ftp(struct UrlData *data,
/* we didn't get any digit */
to=-1;
}
- if(-1 == to) {
+ if((-1 == to) && (from>=0)) {
/* X - */
data->resume_from = from;
+ infof(data, "FTP RANGE %d to end of file\n", from);
}
else if(from < 0) {
/* -Y */
- from = 0;
- to = -from;
- totalsize = to-from;
- data->maxdownload = totalsize;
+ totalsize = -from;
+ data->maxdownload = -from;
+ data->resume_from = from;
+ infof(data, "FTP RANGE the last %d bytes\n", totalsize);
}
else {
- /* X- */
+ /* X-Y */
totalsize = to-from;
- data->maxdownload = totalsize;
+ data->maxdownload = totalsize+1; /* include the last mentioned byte */
+ data->resume_from = from;
+ infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->maxdownload);
}
infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize);
}
-
+#if 0
if(!ppath[0])
/* make sure this becomes a valid name */
ppath="./";
-
- if((data->conf & CONF_FTPLISTONLY) ||
- ('/' == ppath[strlen(ppath)-1] )) {
+#endif
+ if((data->bits.ftp_list_only) || !ftp->file) {
/* The specified path ends with a slash, and therefore we think this
is a directory that is requested, use LIST. But before that we
need to set ASCII transfer mode. */
@@ -826,30 +936,29 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set ascii mode");
- return URG_FTP_COULDNT_SET_ASCII;
+ return CURLE_FTP_COULDNT_SET_ASCII;
}
/* if this output is to be machine-parsed, the NLST command will be
better used since the LIST command output is not specified or
standard in any way */
- sendf(data->firstsocket, data, "%s %s\r\n",
+ sendf(data->firstsocket, data, "%s\r\n",
data->customrequest?data->customrequest:
- (data->conf&CONF_FTPLISTONLY?"NLST":"LIST"),
- ppath);
+ (data->bits.ftp_list_only?"NLST":"LIST"));
}
else {
/* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n",
- (data->conf&CONF_FTPASCII)?"A":"I");
+ (data->bits.ftp_list_only)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode",
- (data->conf&CONF_FTPASCII)?"ASCII":"binary");
- return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII:
- URG_FTP_COULDNT_SET_BINARY;
+ (data->bits.ftp_ascii)?"ASCII":"binary");
+ return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
+ CURLE_FTP_COULDNT_SET_BINARY;
}
if(data->resume_from) {
@@ -860,7 +969,7 @@ UrgError _ftp(struct UrlData *data,
* of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */
- sendf(data->firstsocket, data, "SIZE %s\r\n", ppath);
+ sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data);
@@ -875,13 +984,27 @@ UrgError _ftp(struct UrlData *data,
int foundsize=atoi(buf+4);
/* We got a file size report, so we check that there actually is a
part of the file left to get, or else we go home. */
- if(foundsize <= data->resume_from) {
- failf(data, "Offset (%d) was beyond file size (%d)",
- data->resume_from, foundsize);
- return URG_FTP_BAD_DOWNLOAD_RESUME;
+ if(data->resume_from< 0) {
+ /* We're supposed to download the last abs(from) bytes */
+ if(foundsize < -data->resume_from) {
+ failf(data, "Offset (%d) was beyond file size (%d)",
+ data->resume_from, foundsize);
+ return CURLE_FTP_BAD_DOWNLOAD_RESUME;
+ }
+ /* convert to size to download */
+ downloadsize = -data->resume_from;
+ /* download from where? */
+ data->resume_from = foundsize - downloadsize;
+ }
+ else {
+ if(foundsize <= data->resume_from) {
+ failf(data, "Offset (%d) was beyond file size (%d)",
+ data->resume_from, foundsize);
+ return CURLE_FTP_BAD_DOWNLOAD_RESUME;
+ }
+ /* Now store the number of bytes we are expected to download */
+ downloadsize = foundsize-data->resume_from;
}
- /* Now store the number of bytes we are expected to download */
- downloadsize = foundsize-data->resume_from;
}
/* Set resume file transfer offset */
@@ -894,11 +1017,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4);
- return URG_FTP_COULDNT_USE_REST;
+ return CURLE_FTP_COULDNT_USE_REST;
}
}
- sendf(data->firstsocket, data, "RETR %s\r\n", ppath);
+ sendf(data->firstsocket, data, "RETR %s\r\n", ftp->file);
}
nread = GetLastResponse(data->firstsocket, buf, data);
@@ -968,12 +1091,12 @@ UrgError _ftp(struct UrlData *data,
if(size <= 0) {
failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, data->resume_from+size);
- return URG_PARTIAL_FILE;
+ return CURLE_PARTIAL_FILE;
}
}
#endif
- if(data->conf & CONF_FTPPORT) {
+ if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
if( result )
return result;
@@ -982,95 +1105,74 @@ UrgError _ftp(struct UrlData *data,
infof(data, "Getting file with size: %d\n", size);
/* FTP download: */
- result=Transfer(data, data->secondarysocket, size, FALSE,
+ result=Transfer(conn, data->secondarysocket, size, FALSE,
bytecountp,
-1, NULL); /* no upload here */
if(result)
return result;
-
- if((-1 != size) && (size != *bytecountp)) {
- failf(data, "Received only partial file");
- return URG_PARTIAL_FILE;
- }
- else if(0 == *bytecountp) {
- failf(data, "No data was received!");
- return URG_FTP_COULDNT_RETR_FILE;
- }
}
else {
failf(data, "%s", buf+4);
- return URG_FTP_COULDNT_RETR_FILE;
+ return CURLE_FTP_COULDNT_RETR_FILE;
}
}
/* end of transfer */
-#if 0
- ProgressEnd(data);
-#endif
- pgrsDone(data);
-
- /* shut down the socket to inform the server we're done */
- sclose(data->secondarysocket);
- data->secondarysocket = -1;
-
- /* now let's see what the server says about the transfer we
- just performed: */
- nread = GetLastResponse(data->firstsocket, buf, data);
-
- /* 226 Transfer complete */
- if(strncmp(buf, "226", 3)) {
- failf(data, "%s", buf+4);
- return URG_FTP_WRITE_ERROR;
- }
-
- /* Send any post-transfer QUOTE strings? */
- if(data->postquote) {
- qitem = data->postquote;
- /* Send all QUOTE strings in same order as on command-line */
- while (qitem) {
- /* Send string */
- if (qitem->data) {
- sendf(data->firstsocket, data, "%s\r\n", qitem->data);
-
- nread = GetLastResponse(data->firstsocket, buf, data);
-
- if (buf[0] != '2') {
- failf(data, "QUOT string not accepted: %s",
- qitem->data);
- return URG_FTP_QUOTE_ERROR;
- }
- }
- qitem = qitem->next;
- }
- }
-
- return URG_OK;
+ return CURLE_OK;
}
/* -- deal with the ftp server! -- */
-UrgError ftp(struct UrlData *data,
- long *bytecountp,
- char *ftpuser,
- char *ftppasswd,
- char *urlpath)
+/* argument is already checked for validity */
+CURLcode ftp(struct connectdata *conn)
{
- char *realpath;
- UrgError retcode;
+ CURLcode retcode;
-#if 0
- realpath = URLfix(urlpath);
-#else
- realpath = curl_unescape(urlpath);
-#endif
- if(realpath) {
- retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, realpath);
- free(realpath);
+ struct UrlData *data = conn->data;
+ struct FTP *ftp;
+ int dirlength=0; /* 0 forces strlen() */
+
+ /* the ftp struct is already inited in ftp_connect() */
+ ftp = data->proto.ftp;
+
+ /* We split the path into dir and file parts *before* we URLdecode
+ it */
+ ftp->file = strrchr(conn->ppath, '/');
+ if(ftp->file) {
+ ftp->file++; /* point to the first letter in the file name part or
+ remain NULL */
+ }
+ else {
+ ftp->file = conn->ppath; /* there's only a file part */
+ }
+ dirlength=ftp->file-conn->ppath;
+
+ if(*ftp->file) {
+ ftp->file = curl_unescape(ftp->file, 0);
+ if(NULL == ftp->file) {
+ failf(data, "no memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
}
else
- /* then we try the original path */
- retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, urlpath);
+ ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
+ pointer */
+
+ ftp->urlpath = conn->ppath;
+ if(dirlength) {
+ ftp->dir = curl_unescape(ftp->urlpath, dirlength);
+ if(NULL == ftp->dir) {
+ if(ftp->file)
+ free(ftp->file);
+ failf(data, "no memory");
+ return CURLE_OUT_OF_MEMORY; /* failure */
+ }
+ }
+ else
+ ftp->dir = NULL;
+
+ retcode = _ftp(conn);
return retcode;
}