aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ftp.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 25806a45f..aa96871cb 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -1967,10 +1967,13 @@ CURLcode ftp_perform(struct connectdata *conn,
return result;
}
- /* change directory first! */
- if(ftp->dir && ftp->dir[0]) {
- if ((result = ftp_cwd(conn, ftp->dir)) != CURLE_OK)
+ {
+ int i; /* counter for loop */
+ for (i=0; ftp->dirs[i]; i++) {
+ /* RFC 1738 says empty components should be respected too */
+ if ((result = ftp_cwd(conn, ftp->dirs[i])) != CURLE_OK)
return result;
+ }
}
/* Requested time of file or time-depended transfer? */
@@ -2091,34 +2094,64 @@ CURLcode ftp_perform(struct connectdata *conn,
*/
CURLcode Curl_ftp(struct connectdata *conn)
{
- CURLcode retcode;
+ CURLcode retcode=CURLE_OK;
bool connected=0;
struct SessionHandle *data = conn->data;
struct FTP *ftp;
- int dirlength=0; /* 0 forces strlen() */
+
+ char *slash_pos; /* position of the first '/' char in curpos */
+ char *cur_pos=conn->ppath; /* current position in ppath. point at the begin
+ of next path component */
+ int path_part=0;/* current path component */
/* the ftp struct is already inited in ftp_connect() */
ftp = conn->proto.ftp;
conn->size = -1; /* make sure this is unknown at this point */
- /* We split the path into dir and file parts *before* we URLdecode
- it */
- ftp->file = strrchr(conn->ppath, '/');
- if(ftp->file) {
- if(ftp->file != conn->ppath)
- dirlength=ftp->file-conn->ppath; /* don't count the traling slash */
+ /* fixed : initialize ftp->dirs[xxx] to NULL !
+ is done in Curl_ftp_connect() */
- 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 */
+ /* parse the URL path into separate path components */
+ while((slash_pos=strchr(cur_pos, '/'))) {
+ /* seek out the next path component */
+ if (0 == slash_pos-cur_pos) /* empty path component, like "x//y" */
+ ftp->dirs[path_part] = strdup(""); /* empty string */
+ else
+ ftp->dirs[path_part] = curl_unescape(cur_pos,slash_pos-cur_pos);
+
+ if (!ftp->dirs[path_part]) { /* run out of memory ... */
+ failf(data, "no memory");
+ retcode = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ cur_pos = slash_pos + 1; /* jump to the rest of the string */
+ if(++path_part >= CURL_MAX_FTP_DIRDEPTH) {
+ /* too deep */
+ failf(data, "too deep dir hierarchy");
+ retcode = CURLE_URL_MALFORMAT;
+ }
+ }
+ if (retcode) {
+ int i;
+ for (i=0;i<path_part;i++) { /* free previous parts */
+ free(ftp->dirs[i]);
+ ftp->dirs[i]=NULL;
+ }
+ return retcode; /* failure */
+ }
}
+ ftp->file = cur_pos; /* the rest is the file name */
+
if(*ftp->file) {
ftp->file = curl_unescape(ftp->file, 0);
if(NULL == ftp->file) {
+ int i;
+ for (i=0;i<path_part;i++){
+ free(ftp->dirs[i]);
+ ftp->dirs[i]=NULL;
+ }
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY;
}
@@ -2126,20 +2159,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
else
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_perform(conn, &connected);
if(CURLE_OK == retcode) {
@@ -2219,6 +2239,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
{
struct FTP *ftp= conn->proto.ftp;
+ int i;
/* The FTP session may or may not have been allocated/setup at this point! */
if(ftp) {
@@ -2228,10 +2249,12 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
free(ftp->cache);
if(ftp->file)
free(ftp->file);
- if(ftp->dir)
- free(ftp->dir);
+ for (i=0;ftp->dirs[i];i++){
+ free(ftp->dirs[i]);
+ ftp->dirs[i]=NULL;
+ }
- ftp->file = ftp->dir = NULL; /* zero */
+ ftp->file = NULL; /* zero */
}
return CURLE_OK;
}