David Balazic's patch to make the FTP operations "do right" according to
RFC1738, which means it'll use one CWD for each pathpart.
This commit is contained in:
		
							
								
								
									
										89
									
								
								lib/ftp.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user