设为首页收藏本站

SKY外语、计算机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 7307|回复: 11

[C++] 字符串解析--BT种子文件信息解析

[复制链接]

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-15 11:39:24 |显示全部楼层
一楼拜大神

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-15 11:43:57 |显示全部楼层
作者:猫鱼 日期:2013-10-15 原文地址:http://www.skywj.com/thread-9201-1-1.html

这个东西主要涉及字符操作,没有啥高深的技术。难度的话大专学生水平。

种子文件的编码方式为B编码,可百度B编码了解详细信息。B编码内容略多,不在此发出。

注释我敲得很多了。如果不明白的回复我尽量回答。

代码涉及小部分linux函数,很简单的函数,不懂可回帖或者百度。
回复

使用道具 评分 举报

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-15 11:55:11 |显示全部楼层
本帖最后由 猫/db鱼 于 2013-10-15 18:18 编辑

代码设计思路 ---希望以定义类对象A,A.info()的形式获得种子文件的信息
1.定义一个数据结构存放种子文件相关信息!
2.将文件解析操作函数封装到一个类中,并提供一个公有调用接口,该接口执行后返回1步骤定义的数据类型,其中保存指定的种子文件的相关信息。
封装不足之处:公有调用接口返回的数据是定义在类中的私有成员变量的地址,封装的隐蔽不足。但鉴于该代码在项目中只调用一次, 本人以容忍的态度忽略这个问题。若各位有更好的想法,如果可以,希望能回复一下。
回复

使用道具 评分 举报

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-15 11:57:47 |显示全部楼层
本帖最后由 猫/db鱼 于 2013-10-15 12:06 编辑

-------------头文件---------------------权限不够,不能回帖了,=会我在发上源文件
  1. /*****************************************************************************
  2. **        文件名:                ResovlerMetafile.h
  3. **        文件职能:                声明bt种子文件解析类,
  4. **        创建日期:                2013-08-06
  5. **        创建人:                        tmfish
  6. ******************************************************************************/

  7. #ifndef                 RESOLVERMETAFILE_H_
  8. #define                 RESOLVERMETAFILE_H_

  9. #define DEBUG

  10. #include <iostream>
  11. #include <cstdio>
  12. #include <vector>
  13. #include <string>
  14. #include <cstring>
  15. #include <cstdlib>
  16. #include <fstream>
  17. #include <cctype>
  18. #include "sha1.h"
  19. using namespace std;


  20. typedef        int         FILETYPE;                                //文件类型

  21. /*状态标识*/
  22. typedef        int          STATE;                                //状态
  23. const        int                NOFILE      = 2;                //文件为空
  24. const        int                OK                        = 0;                //成功标识
  25. const        int         ERROR                = -1;                //错误标识

  26. /*文件类型标识*/
  27. const        int                ISSIMPLE        =1;                        //单文件标识
  28. const        int                ISMULTIPLE        =2;                        //多文件标识

  29. struct Files                                        //多文件中的多个文件
  30. {
  31.         int                length;                                //单个文件的长度
  32.         char*        path;                                //单个文件的路径及文件名
  33. };        

  34. /****************************************************************************************************************
  35. **        种子文件信息结构体
  36. **        用于存储种子文件的主要信息
  37. **        成员说明
  38.         flagFileType        标识文件是单文件还是多文件,
  39.                                         当其值为ISSIMPLE的时候表示单文件,所有的多文件特有属性(m_name,files,)失效
  40.                                         当其值为ISMULTIPLE的时候表示多文件,多有单文件特有属性失效(s_name,length)
  41.         pieceLen                指定piece的大小 通常为256KB、亦有128kb或512kb 单位为字节
  42.         pieces                        每个piece对应hash值
  43.         file_name                单文件的文件名
  44.         fileLength                文件的总文件长度
  45.         dir_name                多文件存放所有文件的目录名称
  46.         multi_files                多文件中包含的所有文件的信息
  47.         tracker_list        tracker地址列表,其类型为一个string类型的vector数组
  48.                                         第一个元素是主tracker地址
  49.         info_hash                根据info关键字的值计算的哈希值,固定为20字节
  50. *****************************************************************************************************************/
  51. typedef struct MetafileInfo
  52. {
  53.         /*标识文件属性*/
  54.         int                        fileType;
  55.         /*单文件、多文件共有属性*/
  56.         long                 pieceLen;                                //每个piece的长度
  57.         char*                pieces;                                        //每个piece对应的hash值
  58.         long long         fileLength;                                //文件总大小
  59.         vector<const char*>        trackerList;                //tracker地址列表
  60.         /*单文件特有属性*/
  61.         char*                fileName;                                //文件名
  62.         /*多文件特有属性*/
  63.         char*                 dirName;                                //存放所有文件的文件夹名
  64.         vector<Files>        multiFiles;                        //多文件中所有文件信息
  65.         unsigned char        info_hash[20];                        //根据info关键字的值计算的哈希值。
  66. }* pMetaInfo;


  67. /*种子文件解析类*/
  68. class ResolverMetafile
  69. {
  70. public:
  71.         /*构造及析构函数*/
  72.         ResolverMetafile(string MetafilePath);
  73.         ~ResolverMetafile();

  74.         /********************************************************************
  75.         *功能:获取共享文件信息
  76.         *返回:函数返回存储种子文件信息的m_metaInfo结构体对象
  77.         *参数:st_info是一个MetafileInfo类型的常引用,用于接收种子文件信息
  78.                    存放点地址
  79.         *附注:该函数是文件解析类对外提供的主要接口
  80.         *********************************************************************/
  81.         MetafileInfo GetMetafileInfo(pMetaInfo*const ppst_info);
  82.         /*
  83.          * 功能:向tracker列表添加一个tracker服务器地址
  84.          * 返回:成功添加tracker返回1,tracker已经存在返回0
  85.          *                  函数成功执行失败返回-1
  86.          * 参数:url指定添加的tracker地址,如果该地址存在与tracker
  87.          *                  列表中,则函数退出
  88.          * 附注:当连接某些tarcker地址的时候,服务器会返回一个重定向地址,函数用于
  89.          *                  添加该类地址,当调用该函数后,调用者应该重新调用GetMetafileInfo获取数据
  90.          */
  91.         STATE AddTracker(const char* url);
  92. protected:
  93.         /*
  94.          * 功能:更具info关键字的值计算其对应的哈希值,将其填充与m_metaInfo.info_hash内
  95.          * 返回:成功返回0,失败返回-1
  96.          * 附注:info关键字对应的值为一个字典。
  97.          */
  98.          STATE CalcInfoHash();

  99.         /*
  100.          * 功能:读取m_metafilePath指定的种子文件,将文件内容保存到m_metafile中
  101.          * 返回:函数成功执行返回1,m_metafilePath为空返回2,失败返回-1
  102.          * 附注:文件读取方式为二进制读取
  103.         */
  104.         STATE        ReadMetafile();

  105.         /*
  106.          * 功能:判断种子文件类型
  107.          * 返回:单文件返回ISSIMPLE,多文件返回ISMULTIPLE,m_metafile为空返回2
  108.          * 附注:ISSIMPLE值为1,ISMULTIPLE值为2
  109.         */
  110.         FILETYPE        FileType();

  111.         /*
  112.          *功能:在m_metafile中查找指定关键字
  113.          *返回:函数查找到指定的关键字返回1,没有找到返回0,函数执行出错返回-1
  114.          *参数:word为需要查找的指定关键字,index为查找到的字符串的起始下标
  115.         */
  116.         STATE        FindWord(const char* word, long long& index);

  117.         /*
  118.          * 功能:解析种子文件的tracker服务器列表,将其放入m_metaInfo.trackerList
  119.          * 返回:函数成功执行返回0,失败返回-1
  120.          * 附注:m_metaInfo.trackerList第一个值为主tracker服务器
  121.         */
  122.         STATE        ResTracker();

  123.         /*
  124.          * 功能:解析piece快大小,将其放入m_metaInfo.pieceLen
  125.          * 返回:成功执行返回0,失败返回-1,m_metafile为空返回2
  126.         */
  127.          STATE        ResPieceLen();

  128.         /*
  129.          * 功能:解析每个块对应的hash值字符串,将其放入m_metaInfo.pieces
  130.          * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  131.          */
  132.          STATE        ResPieces();

  133.          /*
  134.          * 功能:解析文件名,对于多文件而言解析目录名,
  135.          *       若解析单文件,放入m_metaInfo.filename,若解析多文件,放入dirName
  136.          * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  137.          */
  138.          STATE        ResFileName();

  139.         /*
  140.          * 功能:解析总文件大小,填充m_metaInfo.fileLength
  141.          * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  142.          */
  143.          STATE ResFileLength();

  144.         /*
  145.          * 功能:解析文件大小和路径,仅对多文件有效,填充m_metaInfo.multiFiles结构体
  146.          * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  147.          */
  148.          STATE        ResFilePathLen();

  149.          /*
  150.          * 功能:释放类资源
  151.          */
  152.          void ReleaseMem();
  153. protected:
  154.         /*种子文件信息*/
  155.         MetafileInfo        m_metaInfo;
  156.          /*存储种子文件路径*/
  157.          string        m_metafilePath;
  158.          /*存储种子文件的内容*/
  159.          unsigned char*  m_metafile;
  160.          /*种子文件大小*/
  161.         long long int m_metafileLen;

  162. #ifdef DEBUG
  163. public:
  164.         /*测试函数*/
  165.         void Test();
  166. #endif
  167. };

  168. #endif
复制代码

回复

使用道具 评分 举报

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-15 15:03:20 |显示全部楼层
源代码

  1. /*
  2. * resolvermetafile.cpp
  3. * 对resolverMetafile类的具体实现
  4. *  Created on: 2013-8-6
  5. *      Author: tmfish
  6. */
  7. #include "resolverMetafile.h"

  8. #ifdef DEBUG
  9. //测试函数
  10. void ResolverMetafile::Test()
  11. {
  12.         cout << "测试函数" << endl;
  13.         //合格测试
  14.         //*successful
  15.         cout << "filetype:  "        << m_metaInfo.fileType         << endl;
  16.         cout << "piecelen:        "        << m_metaInfo.pieceLen         << endl;
  17.         if (ISSIMPLE == m_metaInfo.fileType)
  18.         {
  19.                 cout << "filename:        "        << m_metaInfo.fileName        << endl;
  20.         }else if (ISMULTIPLE == m_metaInfo.fileType)
  21.         {
  22.                 cout << "dirname:        "        << m_metaInfo.dirName        << endl;
  23.         }

  24.         cout << "multiple files number: " << m_metaInfo.multiFiles.size() << endl;
  25.         for (int i=0; i<int(m_metaInfo.multiFiles.size()); i++)
  26.         {
  27.                 cout << "path:           " << m_metaInfo.multiFiles[i].path << endl;
  28.                 cout << "length:         " << m_metaInfo.multiFiles[i].length << endl;
  29.         }

  30.         cout << "fileLen:        "        << m_metaInfo.fileLength<< endl;
  31.         for(int i=0; i<int(m_metaInfo.trackerList.size()); i++)
  32.         {
  33.                 cout << "trackerList" << i << ": " << m_metaInfo.trackerList[i] << endl;
  34.         }
  35.         cout << "test for add " << endl;
  36.         char url[] = "一个URL地址,随意填";
  37.         AddTracker(url);
  38.         for(int i=0; i<int(m_metaInfo.trackerList.size()); i++)
  39.         {
  40.                 cout << "trackerList" << i << ": " << m_metaInfo.trackerList[i] << endl;
  41.         }
  42. }
  43. #endif

  44. //构造函数
  45. ResolverMetafile::ResolverMetafile(string path)
  46. {
  47.         memset(&m_metaInfo, 0, sizeof(m_metaInfo));
  48.         m_metafile                = NULL;
  49.         m_metafilePath         = path;
  50.         m_metafileLen         = 0;
  51.         ReadMetafile();
  52.         FileType();
  53.         ResTracker();
  54.         ResPieceLen();
  55.         ResPieces();
  56.         ResFileName();
  57.         ResFilePathLen();
  58.         ResFileLength();
  59.         CalcInfoHash();
  60. }

  61. //析构函数
  62. ResolverMetafile::~ResolverMetafile()
  63. {
  64.         /*某些释放*/
  65.         ReleaseMem();
  66. }

  67. /********************************************************************
  68. *功能:获取共享文件信息
  69. *返回:函数返回存储种子文件信息的m_metaInfo结构体对象
  70. *参数:pst_info是一个MetafileInfo类型的指针的指针,用于接收种子文件信息
  71.            存放点地址
  72. *********************************************************************/
  73. MetafileInfo ResolverMetafile::GetMetafileInfo(pMetaInfo*const ppst_info)
  74. {
  75.         *ppst_info = &m_metaInfo;

  76.         return m_metaInfo;
  77. }

  78. /*
  79. * 功能:向tracker列表添加一个tracker服务器地址
  80. * 返回:成功添加tracker返回1,tracker已经存在返回0
  81. *                  函数成功执行失败返回-1
  82. * 参数:strTracker指定添加的tracker地址,如果该地址存在与tracker
  83. *                  列表中,则函数退出
  84. * 附注:当连接某些tarcker地址的时候,服务器会返回一个重定向地址,函数用于
  85. *                  添加该类地址
  86. */
  87. STATE ResolverMetafile::AddTracker(const char* url)
  88. {
  89.         char* bufTmp = new char[strlen(url)+1];
  90.         memcpy(bufTmp,url,strlen(url)+1);
  91.         int size = m_metaInfo.trackerList.size();
  92.         //若地址存在,则无需添加
  93.         for (int i=0; i<size; i++)
  94.         {
  95.                 if (0 == strcmp(m_metaInfo.trackerList.at(i),url))
  96.                 {
  97.                         return OK;
  98.                 }
  99.         }
  100.         //于末尾追加元素
  101.         m_metaInfo.trackerList.push_back(bufTmp);
  102.         return OK;
  103. }

  104. /*
  105. * 功能:判断种子文件类型
  106. * 返回:单文件返回ISSIMPLE,多文件返回ISMULTIPLE,m_metafile为空返回2
  107. * 附注:ISSIMPLE值为1,ISMULTIPLE值为2
  108. */
  109. FILETYPE ResolverMetafile::FileType()
  110. {
  111. //        cout << m_metafile << endl;
  112.         long long  index;
  113.          //种子文件中files代表多文件
  114.         if (1 == FindWord("5:files",index))
  115.         {
  116.                 m_metaInfo.fileType = ISMULTIPLE;
  117.                 return ISMULTIPLE;
  118.         }else
  119.         {
  120.                 m_metaInfo.fileType = ISSIMPLE;
  121.                 return ISSIMPLE;
  122.         }
  123.         return ERROR;
  124. }

  125. /*
  126. * 功能:读取m_metafilePath指定的种子文件,将文件内容保存到m_metafile中
  127. * 返回:函数成功执行返回0,m_metafilePath为空返回2,失败返回-1
  128. * 附注:文件读取方式为二进制读取
  129. */
  130. STATE ResolverMetafile::ReadMetafile()
  131. {
  132.         if (m_metafilePath.empty())
  133.         {
  134.                 cerr << "文件路径为空!" << endl;
  135.                 return ERROR;
  136.         }
  137.         /*
  138.         ifstream fin(m_metafilePath.c_str(), ios_base::in | ios_base::binary);
  139. //        fin.open("in");
  140.         if (!fin.is_open())
  141.         {
  142.                 cerr<< "文件打开失败!" << endl;
  143.                 return ERROR;
  144.         }
  145.         //获取种子文件长度
  146.         fin.seekg(0,ios::end);
  147.         m_metafileLen = fin.tellg();
  148.         m_metafile = new char[m_metafileLen+1];
  149. //        fin.read(m_metafile, m_metafileLen);]
  150.         fin >> m_metafile;
  151.         if (NULL == m_metafile)
  152.         {
  153.                 cerr << "文件读取失败" << endl;
  154.                 return ERROR;
  155.         }
  156.         m_metafile[m_metafileLen] = '\0';
  157.         cout << m_metafile[3] << endl;
  158.         fin.close();
  159.         */

  160.         //以二进制、只读方式打开文件
  161.         FILE* fp = fopen(m_metafilePath.c_str(), "rb");
  162.         if (NULL == fp)
  163.         {
  164.                 cout << "文件打开失败" << endl;
  165.                 return -1;
  166.         }

  167.         //获取种子文件的长度,
  168.         fseek(fp, 0, SEEK_END);
  169.         m_metafileLen        = ftell(fp);
  170.         if (-1 == m_metafileLen)
  171.         {
  172.                 cout << "文件长度错误" << endl;
  173.                 return -1;
  174.         }
  175.         m_metafile = new unsigned char[m_metafileLen+1];
  176.         if (NULL == m_metafile)
  177.         {
  178.                 cout << "内存分配失败" << endl;
  179.                 return -1;
  180.         }

  181.         //读取种子文件的内容到m_metafile
  182.         fseek(fp, 0, SEEK_SET);
  183.         long i;
  184.         for ( i=0; i<m_metafileLen; i++)
  185.         {
  186.                 m_metafile[i] = fgetc(fp);
  187.         }
  188.         m_metafile[i] = '\0';

  189.         fclose(fp);

  190.         return OK;
  191. }

  192. /*
  193. *功能:在m_metafile中查找指定关键字
  194. *返回:函数查找到指定的关键字返回1,没有找到返回0,函数执行出错返回-1
  195. *参数:word为需要查找的指定关键字,index为查找到的字符串的起始下标的引用
  196. */
  197. STATE ResolverMetafile::FindWord(const char* word, long long& index)
  198. {
  199.         if (NULL == m_metafile)
  200.         {
  201.                 cerr << "种子内容为空" << endl;
  202.                 return ERROR;
  203.         }
  204.         for (long long  int i=0; i<(m_metafileLen-long(strlen(word))); i++)
  205.         {
  206.                 if (0 == memcmp(&m_metafile[i], word, strlen(word)))
  207.                 {
  208.                         index = i;
  209.                         return 1;
  210.                 }
  211.         }
  212.         //未找到
  213.         return 0;
  214. }

  215. /*
  216. * 功能:解析种子文件的tracker服务器列表,将其放入m_metaInfo.trackerList
  217. * 返回:函数成功执行返回0,失败返回-1
  218. * 附注:m_metaInfo.trackerList第一个值为主tracker服务器
  219. */
  220. STATE ResolverMetafile::ResTracker()
  221. {
  222.         if (NULL == m_metafile)
  223.         {
  224.                 cerr << "种子内容为空" << endl;
  225.                 return ERROR;
  226.         }
  227.         long long index = 0;


  228.         if (0 == FindWord("13:announce-list",index)) //单文件处理
  229.         {
  230.                 if (1 == FindWord("8:annouce",index))
  231.                 {
  232.                         int len  = 0;         //tracker长度
  233.                         index = index + strlen("8:announce"); //跳过"8:announce"
  234.                         while (isdigit(m_metafile[index]))
  235.                         {
  236.                                 len = len*10 + (m_metafile[index] - '0');
  237.                                 index++;
  238.                         }
  239.                         index ++; //跳过':'
  240.                         //填充m_metaInfo.trackerList数据成员
  241.                         char* tmpBuf  = new char[len+1];
  242.                         memcpy(tmpBuf, &m_metafile[index], len);
  243.                         tmpBuf[len] = '\0';
  244.                         if(!m_metaInfo.trackerList.empty())
  245.                         {
  246.                                 m_metaInfo.trackerList.clear();
  247.                         }
  248.                         m_metaInfo.trackerList.push_back(tmpBuf);
  249.                 }//end if

  250.         }else   //如果有“13:announce-list”关键字,则不用处理"8:annoucne"关键字
  251.         {
  252.                 index+=strlen("13:announce-list"); //跳过"13:announce-list"
  253.                 index++;//跳过'l'
  254.                 index++;//跳过'l'
  255.                 int len = 0;

  256.                 while('e' != m_metafile[index])
  257.                 {
  258.                         while(isdigit(m_metafile[index]))
  259.                         {
  260.                                 len = len*10 + (m_metafile[index]-'0');
  261.                                 index++;
  262.                         }
  263.                         index++;//跳过':'
  264.                         //提取tracker 放入m_metafile.trackerList容器
  265.                         //只处理"http"开头的地址
  266.                         if (0 == memcmp(&m_metafile[index],"http",4))
  267.                         {
  268.                                 char* tmpBuf  = new char[len+1];
  269.                                 memcpy(tmpBuf, &m_metafile[index], len);
  270.                                 tmpBuf[len] = '\0';
  271.                                 m_metaInfo.trackerList.push_back(tmpBuf);
  272.                         }
  273.                         //准备读取下一个tracker地址
  274.                         index = index + len;
  275.                         len =0;
  276.                 } //end while 1
  277.         }  //end if else
  278.         return OK;
  279. }

  280. /*
  281. * 功能:解析piece快大小,将其放入m_metaInfo.pieceLen
  282. * 返回:成功执行返回0,失败返回-1,m_metafile为空返回2
  283. */
  284. STATE ResolverMetafile::ResPieceLen()
  285. {
  286.         if (NULL == m_metafile)
  287.         {
  288.                 cerr << "种子内容为空" << endl;
  289.                 return ERROR;
  290.         }
  291.         m_metaInfo.pieceLen = 0;
  292.         long long index  =0;
  293.         if (1 == FindWord("12:piece length", index))
  294.         {
  295.                 index += strlen("12:piece length"); //跳过"12:piece length"
  296.                 index ++;                                                        //跳过':'
  297.                 //填充m_metaInfo.pieceLen
  298.                 while(isdigit(m_metafile[index]))
  299.                 {
  300.                         m_metaInfo.pieceLen = 10*(m_metaInfo.pieceLen) + (m_metafile[index]-'0');
  301.                         index++;
  302.                 }
  303.         }else
  304.         {
  305.                 return ERROR;
  306.         }
  307.         return OK;
  308. }

  309. /*
  310. * 功能:解析每个块对应的hash值字符串,将其放入m_metaInfo.pieces
  311. * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  312. */
  313. STATE ResolverMetafile::ResPieces()
  314. {
  315.         if (NULL == m_metafile)
  316.         {
  317.                 cerr << "种子内容为空" << endl;
  318.                 return ERROR;
  319.         }
  320.         long long index = 0;
  321.         if (1 == FindWord("6:pieces", index))
  322.         {
  323.                 index += strlen("6:pieces");
  324.                 long len = 0;
  325.                 while (isdigit(m_metafile[index]))
  326.                 {
  327.                         len = len*10 + (m_metafile[index]-'0');
  328.                         index++;
  329.                 }
  330.                 //填充m_metaInfo.pieces
  331.                 index++;//跳过':'
  332.                 m_metaInfo.pieces = new char[len+1];
  333.                 memcpy(m_metaInfo.pieces, &m_metafile[index], len);
  334.                 m_metaInfo.pieces[len] = '\0';
  335.         }else
  336.         {
  337.                 return ERROR;
  338.         }
  339.         return OK;
  340. }

  341. /*
  342. * 功能:解析文件名,对于多文件而言解析目录名,
  343. *       若解析单文件,放入m_metaInfo.filename,若解析多文件,放入dirName
  344. * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  345. */
  346. STATE ResolverMetafile::ResFileName()
  347. {
  348.         if (NULL == m_metafile)
  349.         {
  350.                 cerr << "种子内容为空" << endl;
  351.                 return ERROR;
  352.         }
  353.         long long  index;
  354.         int count = 0;
  355.         if (1 == FindWord("4:name", index))
  356.         {
  357.                 index = index + 6;        //跳过'4:name'
  358.                 while (':' != m_metafile[index] )
  359.                 {
  360.                         count = count*10+(m_metafile[index]-'0');
  361.                         index++;
  362.                 }
  363.                 index++;//跳过':'
  364.                 if (ISSIMPLE == m_metaInfo.fileType)
  365.                 {
  366.                         m_metaInfo.fileName  = new char[count+1];
  367.                         memcpy(m_metaInfo.fileName,&m_metafile[index], count);
  368.                         m_metaInfo.fileName[count] ='\0';
  369.                 }else if(ISMULTIPLE == m_metaInfo.fileType)
  370.                 {
  371.                         m_metaInfo.dirName  = new char[count+1];
  372.                         memcpy(m_metaInfo.dirName,&m_metafile[index], count);
  373.                         m_metaInfo.dirName[count] ='\0';

  374.                 }
  375.         }else
  376.         {
  377.                 return ERROR;
  378.         }
  379.         return OK;
  380. }

  381. /*
  382. * 功能:解析总文件大小,填充m_metaInfo.fileLength
  383. * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  384. */
  385. STATE ResolverMetafile::ResFileLength()
  386. {
  387.         if (NULL == m_metafile)
  388.         {
  389.                 cerr << "种子内容为空" << endl;
  390.                 return ERROR;
  391.         }
  392.         long long index = 0;
  393.         long long size = 0;
  394.         if (ISSIMPLE == m_metaInfo.fileType )
  395.         {
  396.                 cout << "enter simple file process " << endl;
  397.                 if (1 == FindWord("6:length",index)) //单文件
  398.                 {
  399.                         index = index+strlen("6:length"); //跳过"6:length"
  400.                         index ++ ;        //跳过'i'
  401.                         while(isdigit(m_metafile[index]))
  402.                         {
  403.                                 size = size*10 + (m_metafile[index]-'0');
  404.                                 index++;
  405.                         }
  406.                         m_metaInfo.fileLength = size;
  407.                 } //end if
  408.         }else if(ISMULTIPLE == m_metaInfo.fileType)
  409.         {
  410.                 for(int i=0; i<int(m_metaInfo.multiFiles.size()); i++)
  411.                 {
  412.                         m_metaInfo.fileLength = m_metaInfo.fileLength +
  413.                                                                         m_metaInfo.multiFiles[i].length;
  414.                 }
  415.         }else
  416.         {
  417.                 return ERROR;
  418.         }
  419.         return OK;
  420. }

  421. /*
  422. * 功能:解析文件大小和路径,仅对多文件有效,填充m_metaInfo.multiFiles结构体
  423. *                  并将files填充,代表多文件的文件个数
  424. * 返回:函数成功执行返回0,失败返回-1,m_metafile为空返回2
  425. */
  426. STATE ResolverMetafile::ResFilePathLen()
  427. {
  428.         if (NULL == m_metafile)
  429.         {
  430.                 cerr << "种子内容为空" << endl;
  431.                 return NOFILE;
  432.         }
  433.         //不是多文件该函数无效
  434.         if (ISMULTIPLE != m_metaInfo.fileType)
  435.         {
  436.                 return ERROR;
  437.         }

  438.         int         length          = 0;
  439. //        char*         path          = NULL;
  440.         int         pathSize = 0;
  441.         Files   mfBuf         ;
  442.         memset(&mfBuf, 0, sizeof(mfBuf));

  443.         for(long i=0; i<(m_metafileLen-8); i++) //-8预留空间,防内存溢出
  444.         {
  445.                 //获取多文件中各个文件的大小
  446.                 if (0 == memcmp(&m_metafile[i], "6:length", 8))
  447.                 {
  448.                         i+=8;        //跳过"6:length"
  449.                         i++;        //跳过'i'
  450.                         length = 0;
  451.                         while('e' != m_metafile[i])
  452.                         {
  453.                                 length = length*10 + (m_metafile[i]-'0');
  454.                                 i++;
  455.                         }
  456.                         mfBuf.length = length;
  457.                         //填充m_metaInfo.multiFiles成员,于末尾追加
  458.                         m_metaInfo.multiFiles.push_back(mfBuf);

  459.                 }//end if

  460.                 //获取多文件中文件路径
  461.                 if (0 == memcmp(&m_metafile[i], "4:path", 4))
  462.                 {
  463.                         i+=6; //跳过"4:path"
  464.                         i++;  //跳过 'l'
  465.                         pathSize = 0;
  466.                         while(':' != m_metafile[i])
  467.                         {
  468.                                 pathSize = pathSize*10 + (m_metafile[i] - '0');
  469.                                 i++;
  470.                         }
  471.                         i++; //跳过':'
  472.                         //填充m_metaInfo.multiFiles成员,于末尾追加
  473.                         int end = m_metaInfo.multiFiles.size();
  474.                         (m_metaInfo.multiFiles[end-1]).path = new char[pathSize+1];
  475.                         memcpy((m_metaInfo.multiFiles[end-1]).path, &m_metafile[i], pathSize);
  476.                         (m_metaInfo.multiFiles[end-1]).path[pathSize]  = '\0';
  477.                 }//end if
  478.         } //end for
  479.         return OK;
  480. }

  481. /*
  482. * 功能:更具info关键字的值计算其对应的哈希值,将其填充与m_metaInfo.info_hash内
  483. * 返回:成功返回0,失败返回-1
  484. * 附注:info关键字对应的值为一个字典。
  485. */
  486. STATE ResolverMetafile::CalcInfoHash()
  487. {
  488.         if (NULL == m_metafile)
  489.         {
  490.                 cerr << "种子内容为空" << endl;
  491.                 return NOFILE;
  492.         }
  493.         //begin 为info关键字值开始下标,end为结束
  494.         int push_pop = 0;
  495.         long long index=0,begin=0,end=0;

  496.         if (1 == FindWord("4:info", index))
  497.         {
  498.                 begin = index+6;
  499.         }else
  500.         {
  501.                 return ERROR;
  502.         }
  503.         index +=6; //跳过"4:info"
  504.         /*
  505.          * 核心算法: 遍历info关键字后的值,当遇到d,l时push_pop++,
  506.          *                           如果遇到e,则push_pop--当push_pop为0的时候,
  507.          *                           则证明info关键字后的字典结束,遇见i则直接遍历
  508.          *                           i的内容,遇见数字则直接计算其后字串内容
  509.          */
  510.         for (;index<m_metafileLen;)
  511.         {
  512.                 if ('d' == m_metafile[index])
  513.                 {
  514.                         push_pop++;
  515.                         index++;
  516.                 }else if ('l' == m_metafile[index])
  517.                 {
  518.                         push_pop++;
  519.                         index++;
  520.                 }else if ('i' == m_metafile[index])
  521.                 {
  522.                         index++;//跳过'i'
  523.                         if (index > m_metafileLen)
  524.                         {
  525.                                 return ERROR;
  526.                         }
  527.                         while ('e' != m_metafile[index])
  528.                         {
  529.                                 if (index+1 == m_metafileLen)
  530.                                 {
  531.                                         return ERROR;
  532.                                 }else
  533.                                 {
  534.                                         index ++;
  535.                                 }
  536.                         }//end while
  537.                         index ++; //跳过'e'
  538.                 }else if(('0'<=m_metafile[index]) && (m_metafile[index] <= '9'))
  539.                 {
  540.                         int len =0;
  541.                         while (isdigit(m_metafile[index]))
  542.                         {
  543.                                 len = len*10 + (m_metafile[index]-'0');
  544.                                 index++;
  545.                         }
  546.                         index++;        //跳过':'
  547.                         index+=len;
  548.                 }else if ('e' == m_metafile[index])
  549.                 {
  550.                         push_pop --;
  551.                         if (0 == push_pop)
  552.                         {
  553.                                 end = index; break;
  554.                         }
  555.                         index++;
  556.                 }else
  557.                 {
  558.                         return ERROR;
  559.                 }
  560.         }//end for

  561.         //计算hash值
  562.         SHA1_CTX context;
  563.         SHA1Init(&context);
  564.         SHA1Update(&context,&m_metafile[begin], end-begin+1);
  565.         SHA1Final(m_metaInfo.info_hash,&context);
  566.         cout << endl;
  567.         return OK;
  568. }

  569. /*
  570. * 功能:释放类资源
  571. */
  572. void ResolverMetafile::ReleaseMem()
  573. {
  574.         if (NULL != m_metafile)
  575.         {
  576.                 delete[] m_metafile;
  577.                 m_metafile = NULL;
  578.         }
  579.         if (NULL != m_metaInfo.pieces)
  580.         {
  581.                 delete[] m_metaInfo.pieces;
  582.         }

  583.         if (!m_metaInfo.trackerList.empty())
  584.         {
  585.                 for (int i=0; i< int(m_metaInfo.trackerList.size()); i++)
  586.                 {
  587.                         delete[] m_metaInfo.trackerList.at(i);
  588.                         m_metaInfo.trackerList.at(i) = NULL;
  589.                 }
  590.         }
  591.         m_metaInfo.trackerList.clear();
  592.         if (!m_metaInfo.multiFiles.empty())
  593.         {
  594.                 for (int i=0; i<int(m_metaInfo.multiFiles.size()); i++)
  595.                 {
  596.                         if (NULL != (m_metaInfo.multiFiles.at(i).path))
  597.                         delete[] m_metaInfo.multiFiles.at(i).path;
  598.                         m_metaInfo.multiFiles.at(i).path = NULL;
  599.                 }
  600.         }
  601.         m_metaInfo.multiFiles.clear();

  602.         memset(&m_metaInfo, 0, sizeof(m_metaInfo));
  603. }
复制代码
回复

使用道具 评分 举报

150

主题

6

好友

1179

积分

管理员

Rank: 9Rank: 9Rank: 9

性别
保密

最佳新人 活跃会员 推广达人 宣传达人 突出贡献 优秀版主 论坛元老

发表于 2013-10-16 13:19:22 |显示全部楼层
谢谢猫鱼的优秀技术贴!
回复

使用道具 评分 举报

11

主题

11

好友

597

积分

版主

吉祥物

Rank: 7Rank: 7Rank: 7

自我介绍
努力减肥的胖兔子,以及微博已长草!
性别

最佳新人 活跃会员 灌水之王

发表于 2013-10-16 13:28:16 |显示全部楼层
喵呜~好评。虽然我看不懂。。。
喜欢坐在窗台看。。。天空。。是那么的耀眼。。。。
回复

使用道具 评分 举报

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-16 15:12:24 |显示全部楼层
Kill 发表于 2013-10-16 13:19
谢谢猫鱼的优秀技术贴!

kill老师客气了,我入行软件开发4350给了我蛮大的帮助,这个是我该做的。
回复

使用道具 评分 举报

5

主题

0

好友

74

积分

注册会员

Rank: 2

性别
保密
发表于 2013-10-16 15:13:17 |显示全部楼层
SKY流氓兔 发表于 2013-10-16 13:28
喵呜~好评。虽然我看不懂。。。

感谢对我的认可!
回复

使用道具 评分 举报

11

主题

11

好友

597

积分

版主

吉祥物

Rank: 7Rank: 7Rank: 7

自我介绍
努力减肥的胖兔子,以及微博已长草!
性别

最佳新人 活跃会员 灌水之王

发表于 2013-10-16 17:22:31 |显示全部楼层
猫/db鱼 发表于 2013-10-16 15:13
感谢对我的认可!

不客气。你乖乖来歪歪被调戏就好。。
回复

使用道具 评分 举报

您需要登录后才可以回帖 登录 | 立即注册


手机版|SKY外语、计算机论坛 ( 粤ICP备12031577 )    

GMT+8, 2019-10-22 06:24 , Processed in 0.261719 second(s), 29 queries .

回顶部