qt5集成libcurl实现tftp和ftp的方法之三:搭建FTP时,当ftpServer端默认登录的目录不是根目录/时,有一个bug会产生的解决办法

来源:互联网 发布:php ext文件夹 编辑:程序博客网 时间:2024/05/17 06:41

最近在使用curl时遇到一个问题,老出现下面的错误提示:

< 550 Failed to change directory.* Server denied you to change to the given directory* Connection #0 to host 192.168.2.223 left intact* Access denied to remote resource
在网上找了很长时间,发现真正有价值的博客非常少,只有两个:

http://blog.dou.li/curl-9-server-denied-you-to-change-to-the-given-directory.html和

http://blog.csdn.net/langeldep/article/details/6166218,不过少比没有好,第二个博客的方法确实能解决问题,所以,我将解决该问题的方法稍作整理。

解决该问题的方法有三种:

第一种是上面链接1,通过严格地设置文件的路径,但是我测试发现不好使。

第二种方法是上面链接2,通过修改代码实现。测试发现确实能解决问题。

第三种方法,没必要修改源码,这不是BUG,只要添加下面的语句设置好参数就行了,不过这种方法我没测试,不知道好不好用。
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_NOCWD);

第二种方法的详细解释和操作过程为: 

CURL 库在使用FTP传输文件时, 正常情况下, ftp的server端都会默认进入根目录 /,   但是当ftp的server端设置了一个子目录,比如 ftp的server设置了  /data/movies 为第一次默认进入的目录, 则curl的FTP将会无法传输文件, 错误的原因是 :
ftp的下载地址为  ftp://root:123456@192.168.2.223/data/movies/vbr.ts
而第一次进入的目录为 /data/movies  , 而curl库的FTP解析ftp地址得出 要进入 data 和movies 目录后才能找到下载的文件,
就会去执行  CWD data   和  CWD movies , 而在 /data/movies 这个目录去进入  data 目录, 目录肯定是不存在的,
所以出错。

具体的错误现象如下:

* About to connect() to 192.168.2.223 port 21 (#0)*   Trying 192.168.2.223... Leave Lock = Resume Download File* connected* Connected to 192.168.2.223 (192.168.2.223) port 21 (#0)< 220 (vsFTPd 2.0.5)> USER root< 331 Please specify the password.> PASS 123456< 230 Login successful.> PWD< 257 "/data/movies"* Entry path is '/data/movies'> CWD data< 550 Failed to change directory.* Server denied you to change to the given directory* Connection #0 to host 192.168.2.223 left intact* Access denied to remote resource> QUIT< 221 Goodbye.* Closing connection #0
修改方法是  修改 curl库目录下面 lib文件夹下面的 ftp.c 文件,在函数 static CURLcode ftp_parse_url_path(struct connectdata *conn) 中 添加如下代码

if (ftpc->dirdepth == 0)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>ftpc->dirs[0] = strdup("/");<span style="white-space:pre"></span>ftpc->dirdepth++;<span style="white-space:pre"></span>}
意思就是 让ftp客户端从 根目录开始一级一级的进入到文件所在的目录。添加的位置如下 :

  default: /* allow pretty much anything */  case FTPFILE_MULTICWD:    ftpc->dirdepth = 0;    ftpc->diralloc = 5; /* default dir depth to allocate */    ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));    if(!ftpc->dirs)      return CURLE_OUT_OF_MEMORY;    /* we have a special case for listing the root dir only */    if(strequal(path_to_use, "/")) {      cur_pos++; /* make it point to the zero byte */      ftpc->dirs[0] = strdup("/");      ftpc->dirdepth++;    }    else {      /* parse the URL path into separate path components */      while((slash_pos = strchr(cur_pos, '/')) != NULL)   {        /* 1 or 0 pointer offset to indicate absolute directory */        ssize_t absolute_dir = ((cur_pos - data->state.path > 0) && (ftpc->dirdepth == 0))?1:0;<span style="color:#ff0000;">if (ftpc->dirdepth == 0){ftpc->dirs[0] = strdup("/");ftpc->dirdepth++;}</span>        /* seek out the next path component */        if(slash_pos-cur_pos) {          /* we skip empty path components, like "x//y" since the FTP command             CWD requires a parameter and a non-existant parameter a) doesn't             work on many servers and b) has no effect on the others. */          int len = (int)(slash_pos - cur_pos + absolute_dir);          ftpc->dirs[ftpc->dirdepth] = curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);          if(!ftpc->dirs[ftpc->dirdepth])  { /* run out of memory ... */            failf(data, "no memory");            freedirs(ftpc);            return CURLE_OUT_OF_MEMORY;          }          if(isBadFtpString(ftpc->dirs[ftpc->dirdepth]))   {            free(ftpc->dirs[ftpc->dirdepth]);            freedirs(ftpc);            return CURLE_URL_MALFORMAT;          }        }        else {          cur_pos = slash_pos + 1; /* jump to the rest of the string */          continue;        }        cur_pos = slash_pos + 1; /* jump to the rest of the string */        if(++ftpc->dirdepth >= ftpc->diralloc) {          /* enlarge array */          char *bigger;          ftpc->diralloc *= 2; /* double the size each time */          bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));          if(!bigger)   {            freedirs(ftpc);            return CURLE_OUT_OF_MEMORY;          }          ftpc->dirs = (char **)bigger;        }      }    }    filename = cur_pos;  /* the rest is the file name */    break;  } /* switch */

然后按照前一篇博客http://blog.csdn.net/xueyushenzhou/article/details/51702672的说明,重新编译出共享库,再将原来的都替换掉就行啦。

0 0
原创粉丝点击