设为首页 收藏本站
查看: 1279|回复: 0

[经验分享] FTP服务的LIST指令获取的文件列表信息的解析

[复制链接]

尚未签到

发表于 2016-6-11 04:07:59 | 显示全部楼层 |阅读模式
  客户端使用LIST命令指定获取服务器端FTP共享目录(或者下面的子目录),服务器端将通过数据端口将该指定目录下的文件列表(包括子目录)信息发送给客户端。本文对该文件列表信息进行分析和解析。
  文件列表信息分为UNIX格式和DOS格式两种。笔者是比照了Serv-U和微软自带的FTP服务器写出本文的,也许别的服务器另有新的方式或者格式也说不定,欢迎大家补充。
  首先不妨来看一下UNIX格式和DOS格式下的文件列表信息都是怎么样的:
  //MS-DOS文件列表格式解析
//02-23-05 09:24AM 2245 readme.ESn
//05-25-04 08:56AM 19041660 VC.ESn

  
UNIX文件列表格式解析
UNIX文件格式:
Serv-U:
-rwxrw-r-- 1 user group 3014 Nov 12 14:57 cwinvnc337.ESn
-rwxrw-r-- 1 user group 20480 Mar 3 11:25 inmcsvr更新说明.ESn
-rwxrw-r-- 1 user group 450 Apr 13 11:39 对话框中加入工具条.ESn
Windows自带FTP:
-rwxrwxrwx 1 owner group 19041660 May 25 2004 VC.ESn
-rwxrwxrwx 1 owner group 450 Apr 6 15:04 对话框中加入工具条.ESn

  注:由于未发现Serv-U支持DOS格式,因此DOS格式只列了微软自带的。
  下面我们对以上的格式进行分析:
  首先,文件列表信息中,每个文件的信息之间用回车换行符(/r/n)分隔。因此分解时第一步就是用/r/n进行截取。然后是对每一个文件信息的解析。
  每一个文件信息中,分为多个信息段,各个信息段之间用一个空格符间隔。UNIX格式和DOS格式的信息段的数量的顺序是不同的。下面将分别分析。
  先看看DOS格式,拿出一条文件信息来讲:02-23-05 09:24AM 2245 readme.ESn
  
第一段为05-25-04,一个空格后,为第二段08:56AM,一个空格后,为 19041660,由于文件长度不一定,预留的位置比较长,因此前面用空格填充了。
解析的时候,逐段用空格截取,记住,截取完第一段后,剩下的内容先用TrimLeft去除左侧的空格,然后继续截取就可以了。
因此,DOS格式共分四段,其中第一段为日期,第二段为时间,第三段为文件长度,第四段为文件名称。
  对了,如果只需要获取文件名称,你也不能从后面截取,因为文件名称是允许带空格的。:》
另外,如果列举的是个目录,那么,第三段就不是文件长度了,而是固定为:<DIR>
  
再看UNIX格式,也拿出一条文件信息来讲:
-rwxrw-r-- 1 user group 3014 Nov 12 14:57 cwinvnc337.ESn
unix我不熟,每一段的意义不太清楚。但以上的格式分解为:第一段为-rwxrw-r--,第二段为1,第三段为user,第四段为group,第五段为文件长度,第六段为月,第七段为日,第八段为时间,第九段为文件名称。
需要注意的是:如果格式串的第一个字符为d,表示为一个目录信息,比如drwxrw-r--
另外,第八段有可能不是时间,而是年份,比如2005,从上面的例子中你可以发现。
  
对于不同的FTP服务器,LIST获取的信息不尽相同,但段的顺序和意义是不变的。只是表示文件的长度的段的长度有所不同。
以下是笔者在实际项目中的解析函数,做的不是很好,但希望对大家有所帮助吧。
  /***************************************************
Function:CRecvFileMan::PraseFileList_MSDOS
Description:解析MSDOS风格的文件列表
Table Accessed:
Table Updated:
Parameter:CString sFileList - MSDOS风格文件列表
Return:无返回值
Others:
***************************************************/
void CRecvFileMan::PraseFileList_MSDOS(CString sFileList)
{
CString sLen;
CString sFile;
CString sOneFile;
int nIdx = 0;
while(1)
{
nIdx = sFileList.Find("/r/n");
if(nIdx == -1)
break;
sOneFile = sFileList.Left(nIdx);
sFileList = sFileList.Mid(nIdx + 2);
sLen = GetSegmentInfo(sOneFile,2);
if(sLen == "<DIR>")
{
continue;
}
sFile = GetSegmentInfo(sOneFile,0);
//根据解析的文件信息,形成下载文件类对象
CRecvFile *pFile = new CRecvFile(sFile,atoi(sLen));
m_arTransFile.Add(pFile);
};
}
  /***************************************************
Function:CRecvFileMan::PraseFileList_UNIX
Description:解析UNIX风格的文件列表
Table Accessed:
Table Updated:
Parameter:CString sFileList - UNIX风格文件列表,以回车换行分隔
Return:无返回值
Others:
***************************************************/
void CRecvFileMan::PraseFileList_UNIX(CString sFileList)
{
CString sLen;
CString sFile;
CString sOneFile;
int nIdx = 0;
while(1)
{
nIdx = sFileList.Find("/r/n");
if(nIdx == -1)
break;
sOneFile = sFileList.Left(nIdx);
sFileList = sFileList.Mid(nIdx + 2);
if(sOneFile.GetAt(0) == 'd')//第一个字母是d,表示是目录,忽略
continue;
sLen = GetSegmentInfo(sOneFile,4);
sFile = GetSegmentInfo(sOneFile,3);
//根据解析的文件信息,形成下载文件类对象
CRecvFile *pFile = new CRecvFile(sFile,atoi(sLen));
m_arTransFile.Add(pFile);
};
}
  /***************************************************
Function:CRecvFileMan::GetSegmentInfo
Description:得到文件列表中某个文件描述的指定段的信息
Table Accessed:
Table Updated:
Parameter:CString &sFileInfo - 指定的文件描述信息。即是传入,也是传出参数
将获取段号信息后剩余的信息返回,以便进一步截取其它信息
int nSegment - 指定的段号,从0开始
Return:CString - 指定段号的信息
Others:
***************************************************/
CString CRecvFileMan::GetSegmentInfo(CString &sFileInfo,int nSegment)
{
int nIdx = -1;
int nSeg = 0;
CString sInfo = "";
sFileInfo.TrimLeft();
while(nSeg < nSegment + 1)//逐段切隔
{
nIdx = sFileInfo.Find(" ");//以空格为切隔
if(nIdx < 0)//如果已没有空格,即最后一段信息
{
if(nSeg == nSegment)//如果最后一段正好是需要的段
{
sInfo = sFileInfo;//返回剩余信息
}
else
sInfo = "";
break;
}
else
{
sInfo = sFileInfo.Left(nIdx);//得到段信息
sFileInfo = sFileInfo.Mid(nIdx+1);//切隔信息
sFileInfo.TrimLeft();//过滤左侧的空格符
}
nSeg++;
}
return sInfo;
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-228758-1-1.html 上篇帖子: 在vsftpd中限制ftp用户对主目录以外的目录访问[转] 下篇帖子: 在VB中用winsock实现ftp的上传下载 web组件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表