C# 解析种子文件(bt文件)

来源:互联网 发布:神玥软件招聘 编辑:程序博客网 时间:2024/05/02 04:34

原文地址:http://blog.csdn.net/love_beibei/article/details/7460565

[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Collections;  
  6.   
  7. namespace XunleiHelper  
  8. {  
  9.     public class Torrent  
  10.     {  
  11.         #region 私有字段  
  12.           
  13.         private string _openError = "";  
  14.         private bool _openFile = false;  
  15.   
  16.         private string _announce = "";  
  17.         private IList<string> _announceList = new List<string>();  
  18.         private DateTime _createTime = new DateTime(1970, 1, 1, 0, 0, 0);  
  19.         private long _codePage = 0;  
  20.         private string _comment = "";  
  21.         private string _createdBy = "";  
  22.         private string _encoding = "";  
  23.         private string _commentUTF8 = "";  
  24.         private IList<FileInfo> _fileList = new List<FileInfo>();  
  25.         private string _name = "";  
  26.         private string _nameUTF8 = "";  
  27.         private long _pieceLength = 0;  
  28.         private byte[] _pieces;  
  29.         private string _publisher = "";  
  30.         private string _publisherUTF8 = "";  
  31.         private string _publisherUrl = "";  
  32.         private string _publisherUrlUTF8 = "";  
  33.         private IList<string> _notes = new List<string>();  
  34.         private long _totalLength;  
  35.  
  36.         #endregion  
  37.  
  38.         #region 属性  
  39.           
  40.         /// <summary>  
  41.         /// 错误信息  
  42.         /// </summary>  
  43.         public string OpenError { set { _openError = value; } get { return _openError; } }  
  44.           
  45.         /// <summary>  
  46.         /// 是否正常打开文件  
  47.         /// </summary>  
  48.         public bool OpenFile { set { _openFile = value; } get { return _openFile; } }  
  49.           
  50.         /// <summary>  
  51.         /// 服务器的URL(字符串)  
  52.         /// </summary>  
  53.         public string Announce { set { _announce = value; } get { return _announce; } }  
  54.           
  55.         /// <summary>  
  56.         /// 备用tracker服务器列表(列表)  
  57.         /// </summary>  
  58.         public IList<string> AnnounceList { set { _announceList = value; } get { return _announceList; } }  
  59.           
  60.         /// <summary>  
  61.         /// 种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)  
  62.         /// </summary>  
  63.         public DateTime CreateTime { set { _createTime = value; } get { return _createTime; } }  
  64.           
  65.         /// <summary>  
  66.         /// 未知数字CodePage  
  67.         /// </summary>  
  68.         public long CodePage { set { _codePage = value; } get { return _codePage; } }  
  69.           
  70.         /// <summary>  
  71.         /// 种子描述  
  72.         /// </summary>  
  73.         public string Comment { set { _comment = value; } get { return _comment; } }  
  74.           
  75.         /// <summary>  
  76.         /// 编码方式  
  77.         /// </summary>  
  78.         public string CommentUTF8 { set { _commentUTF8 = value; } get { return _commentUTF8; } }  
  79.           
  80.         /// <summary>  
  81.         /// 创建人  
  82.         /// </summary>  
  83.         public string CreatedBy { set { _createdBy = value; } get { return _createdBy; } }  
  84.           
  85.         /// <summary>  
  86.         /// 编码方式  
  87.         /// </summary>  
  88.         public string Encoding { set { _encoding = value; } get { return _encoding; } }  
  89.         /// <summary>  
  90.         /// 文件信息  
  91.         /// </summary>  
  92.         public IList<FileInfo> FileList { set { _fileList = value; } get { return _fileList; } }  
  93.           
  94.         /// <summary>  
  95.         /// 种子名  
  96.         /// </summary>  
  97.         public string Name { set { _name = value; } get { return _name; } }  
  98.         /// <summary>  
  99.         /// 种子名UTF8  
  100.         /// </summary>  
  101.         public string NameUTF8 { set { _nameUTF8 = value; } get { return _nameUTF8; } }  
  102.           
  103.         /// <summary>  
  104.         /// 每个块的大小,单位字节(整数)  
  105.         /// </summary>  
  106.         public long PieceLength { set { _pieceLength = value; } get { return _pieceLength; } }  
  107.           
  108.         /// <summary>  
  109.         /// 每个块的20个字节的SHA1 Hash的值(二进制格式)  
  110.         /// </summary>  
  111.         private byte[] Pieces { set { _pieces = value; } get { return _pieces; } }  
  112.           
  113.         /// <summary>  
  114.         /// 出版  
  115.         /// </summary>  
  116.         public string Publisher { set { _publisher = value; } get { return _publisher; } }  
  117.           
  118.         /// <summary>  
  119.         /// 出版UTF8  
  120.         /// </summary>  
  121.         public string PublisherUTF8 { set { _publisherUTF8 = value; } get { return _publisherUTF8; } }  
  122.           
  123.         /// <summary>  
  124.         /// 出版地址  
  125.         /// </summary>  
  126.         public string PublisherUrl { set { _publisherUrl = value; } get { return _publisherUrl; } }  
  127.       
  128.         /// <summary>  
  129.         /// 出版地址  
  130.         /// </summary>  
  131.         public string PublisherUrlUTF8 { set { _publisherUrlUTF8 = value; } get { return _publisherUrlUTF8; } }  
  132.           
  133.         /// <summary>  
  134.         /// NODES  
  135.         /// </summary>  
  136.         public IList<string> Notes { set { _notes = value; } get { return _notes; } }  
  137.   
  138.         /// <summary>  
  139.         /// 包含文件的总长度  
  140.         /// </summary>  
  141.         public long TotalLength  
  142.         {  
  143.             get  
  144.             {  
  145.                 return _totalLength;  
  146.             }  
  147.         }  
  148.  
  149.         #endregion  
  150.   
  151.         public Torrent(string fileName)  
  152.         {  
  153.             System.IO.FileStream torrentFile = new System.IO.FileStream(fileName, System.IO.FileMode.Open);  
  154.             byte[] buffer = new byte[torrentFile.Length];  
  155.             torrentFile.Read(buffer, 0, buffer.Length);  
  156.             torrentFile.Close();  
  157.   
  158.             if ((char)buffer[0] != 'd')  
  159.             {  
  160.                 if (OpenError.Length == 0) OpenError = "错误的Torrent文件,开头第1字节不是100";  
  161.                 return;  
  162.             }  
  163.             GetTorrentData(buffer);  
  164.         }  
  165.  
  166.         #region 开始读数据  
  167.   
  168.         /// <summary>  
  169.         /// 开始读取  
  170.         /// </summary>  
  171.         /// <param name="buffer"></param>  
  172.         private void GetTorrentData(byte[] buffer)  
  173.         {  
  174.             int startIndex = 1;  
  175.             while (true)  
  176.             {  
  177.                 object Keys = GetKeyText(buffer, ref startIndex);  
  178.                 if (Keys == null)  
  179.                 {  
  180.                     if (startIndex >= buffer.Length) OpenFile = true;  
  181.                     break;  
  182.                 }  
  183.   
  184.                 if (GetValueText(buffer, ref startIndex, Keys.ToString().ToUpper()) == falsebreak;  
  185.             }  
  186.         }  
  187.  
  188.         #endregion  
  189.   
  190.         /// <summary>  
  191.         /// 读取结构  
  192.         /// </summary>  
  193.         /// <param name="buffer"></param>  
  194.         /// <param name="starIndex"></param>  
  195.         /// <param name="key"></param>  
  196.         /// <returns></returns>  
  197.         private bool GetValueText(byte[] buffer, ref int starIndex, string key)  
  198.         {  
  199.             switch (key)  
  200.             {  
  201.                 case "ANNOUNCE":  
  202.                     Announce = GetKeyText(buffer, ref starIndex).ToString();  
  203.                     break;  
  204.                 case "ANNOUNCE-LIST":  
  205.                     int listCount = 0;  
  206.                     ArrayList _tempList = GetKeyData(buffer, ref starIndex, ref listCount);  
  207.                     for (int i = 0; i != _tempList.Count; i++)  
  208.                     {  
  209.                         AnnounceList.Add(_tempList[i].ToString());  
  210.                     }  
  211.                     break;  
  212.                 case "CREATION DATE":  
  213.                     object date = GetKeyNumb(buffer, ref starIndex).ToString();  
  214.                     if (date == null)  
  215.                     {  
  216.                         if (OpenError.Length == 0) OpenError = "CREATION DATE 返回不是数字类型";  
  217.                         return false;  
  218.                     }  
  219.                     CreateTime = CreateTime.AddTicks(long.Parse(date.ToString()));  
  220.                     break;  
  221.                 case "CODEPAGE":  
  222.                     object codePageNumb = GetKeyNumb(buffer, ref starIndex);  
  223.                     if (codePageNumb == null)  
  224.                     {  
  225.                         if (OpenError.Length == 0) OpenError = "CODEPAGE 返回不是数字类型";  
  226.                         return false;  
  227.                     }  
  228.                     CodePage = long.Parse(codePageNumb.ToString());  
  229.                     break;  
  230.                 case "ENCODING":  
  231.                     Encoding = GetKeyText(buffer, ref starIndex).ToString();  
  232.                     break;  
  233.                 case "CREATED BY":  
  234.                     CreatedBy = GetKeyText(buffer, ref starIndex).ToString();  
  235.                     break;  
  236.                 case "COMMENT":  
  237.                     Comment = GetKeyText(buffer, ref starIndex).ToString();  
  238.                     break;  
  239.                 case "COMMENT.UTF-8":  
  240.                     CommentUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  241.                     break;  
  242.                 case "INFO":  
  243.                     int fileListCount = 0;  
  244.                     GetFileInfo(buffer, ref starIndex, ref fileListCount);  
  245.                     break;  
  246.                 case "NAME":  
  247.                     Name = GetKeyText(buffer, ref starIndex).ToString();  
  248.                     break;  
  249.                 case "NAME.UTF-8":  
  250.                     NameUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  251.                     break;  
  252.                 case "PIECE LENGTH":  
  253.                     object pieceLengthNumb = GetKeyNumb(buffer, ref starIndex);  
  254.                     if (pieceLengthNumb == null)  
  255.                     {  
  256.                         if (OpenError.Length == 0) OpenError = "PIECE LENGTH 返回不是数字类型";  
  257.                         return false;  
  258.                     }  
  259.                     PieceLength = long.Parse(pieceLengthNumb.ToString());  
  260.                     break;  
  261.                 case "PIECES":  
  262.                     Pieces = GetKeyByte(buffer, ref starIndex);  
  263.                     break;  
  264.                 case "PUBLISHER":  
  265.                     Publisher = GetKeyText(buffer, ref starIndex).ToString();  
  266.                     break;  
  267.                 case "PUBLISHER.UTF-8":  
  268.                     PublisherUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  269.                     break;  
  270.                 case "PUBLISHER-URL":  
  271.                     PublisherUrl = GetKeyText(buffer, ref starIndex).ToString();  
  272.                     break;  
  273.                 case "PUBLISHER-URL.UTF-8":  
  274.                     PublisherUrlUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  275.                     break;  
  276.                 case "NODES":  
  277.                     int nodesCount = 0;  
  278.                     ArrayList _nodesList = GetKeyData(buffer, ref starIndex, ref nodesCount);  
  279.                     int ipCount = _nodesList.Count / 2;  
  280.                     for (int i = 0; i != ipCount; i++)  
  281.                     {  
  282.                         Notes.Add(_nodesList[i * 2] + ":" + _nodesList[(i * 2) + 1]);  
  283.                     }  
  284.                     break;  
  285.   
  286.                 default:  
  287.                     return false;  
  288.             }  
  289.             return true;  
  290.         }  
  291.  
  292.         #region 获取数据  
  293.           
  294.         /// <summary>  
  295.         /// 获取列表方式 "I1:Xe"="X" 会调用GetKeyText  
  296.         /// </summary>  
  297.         /// <param name="buffer"></param>  
  298.         /// <param name="starIndex"></param>  
  299.         /// <param name="listCount"></param>  
  300.         private ArrayList GetKeyData(byte[] buffer, ref int starIndex, ref int listCount)  
  301.         {  
  302.             ArrayList _tempList = new ArrayList();  
  303.             while (true)  
  304.             {  
  305.                 string textStar = System.Text.Encoding.UTF8.GetString(buffer, starIndex, 1);  
  306.                 switch (textStar)  
  307.                 {  
  308.                     case "l":  
  309.                         starIndex++;  
  310.                         listCount++;  
  311.                         break;  
  312.                     case "e":  
  313.                         listCount--;  
  314.                         starIndex++;  
  315.                         if (listCount == 0) return _tempList;  
  316.                         break;  
  317.                     case "i":  
  318.                         _tempList.Add(GetKeyNumb(buffer, ref starIndex).ToString());  
  319.                         break;  
  320.                     default:  
  321.                         object listText = GetKeyText(buffer, ref starIndex);  
  322.                         if (listText != null)  
  323.                         {  
  324.                             _tempList.Add(listText.ToString());  
  325.                         }  
  326.                         else  
  327.                         {  
  328.                             if (OpenError.Length == 0)  
  329.                             {  
  330.                                 OpenError = "错误的Torrent文件,ANNOUNCE-LIST错误";  
  331.                                 return _tempList;  
  332.                             }  
  333.                         }  
  334.                         break;  
  335.                 }  
  336.             }  
  337.         }  
  338.           
  339.         /// <summary>  
  340.         /// 获取字符串  
  341.         /// </summary>  
  342.         /// <param name="buffer"></param>  
  343.         /// <param name="startIndex"></param>  
  344.         /// <returns></returns>  
  345.         private object GetKeyText(byte[] buffer, ref int startIndex)  
  346.         {  
  347.             int numb = 0;  
  348.             int leftNumb = 0;  
  349.             for (int i = startIndex; i != buffer.Length; i++)  
  350.             {  
  351.                 if ((char)buffer[i] == ':'break;  
  352.                 if ((char)buffer[i] == 'e')  
  353.                 {  
  354.                     leftNumb++;  
  355.                     continue;  
  356.                 }  
  357.                 numb++;  
  358.             }  
  359.   
  360.             startIndex += leftNumb;  
  361.             string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);  
  362.             try  
  363.             {  
  364.                 int readNumb = Int32.Parse(textNumb);  
  365.                 startIndex = startIndex + numb + 1;  
  366.                 object keyText = System.Text.Encoding.UTF8.GetString(buffer, startIndex, readNumb);  
  367.                 startIndex += readNumb;  
  368.                 return keyText;  
  369.             }  
  370.             catch  
  371.             {  
  372.                 return null;  
  373.             }  
  374.   
  375.         }  
  376.   
  377.         /// <summary>  
  378.         /// 获取数字  
  379.         /// </summary>  
  380.         /// <param name="buffer"></param>  
  381.         /// <param name="startIndex"></param>  
  382.         private object GetKeyNumb(byte[] buffer, ref int startIndex)  
  383.         {  
  384.             if (System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1) == "i")  
  385.             {  
  386.                 int numb = 0;  
  387.                 for (int i = startIndex; i != buffer.Length; i++)  
  388.                 {  
  389.                     if ((char)buffer[i] == 'e'break;  
  390.                     numb++;  
  391.                 }  
  392.                 startIndex++;  
  393.                 long retNumb = 0;  
  394.                 try  
  395.                 {  
  396.                     retNumb = long.Parse(System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb - 1));  
  397.                     startIndex += numb;  
  398.                     return retNumb;  
  399.                 }  
  400.                 catch  
  401.                 {  
  402.                     return null;  
  403.                 }  
  404.             }  
  405.             else  
  406.             {  
  407.                 return null;  
  408.             }  
  409.   
  410.         }  
  411.   
  412.         /// <summary>  
  413.         /// 获取BYTE数据  
  414.         /// </summary>  
  415.         /// <param name="buffer"></param>  
  416.         /// <param name="startIndex"></param>  
  417.         /// <returns></returns>  
  418.         private byte[] GetKeyByte(byte[] buffer, ref int startIndex)  
  419.         {  
  420.             int numb = 0;  
  421.             for (int i = startIndex; i != buffer.Length; i++)  
  422.             {  
  423.                 if ((char)buffer[i] == ':'break;  
  424.                 numb++;  
  425.             }  
  426.             string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);  
  427.   
  428.             try  
  429.             {  
  430.                 int readNumb = Int32.Parse(textNumb);  
  431.                 startIndex = startIndex + numb + 1;  
  432.                 System.IO.MemoryStream keyMemory = new System.IO.MemoryStream(buffer, startIndex, readNumb);  
  433.                 byte[] keyBytes = new byte[readNumb];  
  434.                 keyMemory.Read(keyBytes, 0, readNumb);  
  435.                 keyMemory.Close();  
  436.                 startIndex += readNumb;  
  437.                 return keyBytes;  
  438.             }  
  439.             catch  
  440.             {  
  441.                 return null;  
  442.             }  
  443.         }  
  444.   
  445.         /// <summary>  
  446.         /// 对付INFO的结构  
  447.         /// </summary>  
  448.         /// <param name="buffer"></param>  
  449.         /// <param name="startIndex"></param>  
  450.         /// <param name="listCount"></param>  
  451.         private void GetFileInfo(byte[] buffer, ref int startIndex, ref int listCount)  
  452.         {  
  453.             if ((char)buffer[startIndex] != 'd'return;  
  454.             startIndex++;  
  455.   
  456.             if (GetKeyText(buffer, ref startIndex).ToString().ToUpper() == "FILES")  
  457.             {  
  458.                 FileInfo info = new FileInfo();  
  459.   
  460.                 while (true)  
  461.                 {  
  462.                     string TextStar = System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1);  
  463.   
  464.                     switch (TextStar)  
  465.                     {  
  466.                         case "l":  
  467.                             startIndex++;  
  468.                             listCount++;  
  469.                             break;  
  470.                         case "e":  
  471.                             listCount--;  
  472.                             startIndex++;  
  473.                             if (listCount == 1) FileList.Add(info);  
  474.                             if (listCount == 0) return;  
  475.                             break;  
  476.                         case "d":  
  477.                             info = new FileInfo();  
  478.                             listCount++;  
  479.                             startIndex++;  
  480.                             break;  
  481.   
  482.                         default:  
  483.                             object listText = GetKeyText(buffer, ref startIndex);  
  484.                             if (listText == nullreturn;  
  485.                             switch (listText.ToString().ToUpper())   //转换为大写  
  486.                             {  
  487.                                 case "ED2K":  
  488.                                     info.De2K = GetKeyText(buffer, ref startIndex).ToString();  
  489.                                     break;  
  490.                                 case "FILEHASH":  
  491.                                     info.FileHash = GetKeyText(buffer, ref startIndex).ToString();  
  492.                                     break;  
  493.   
  494.                                 case "LENGTH":  
  495.                                     info.Length = Convert.ToInt64(GetKeyNumb(buffer, ref startIndex));  
  496.                                     _totalLength += info.Length;  
  497.                                     break;  
  498.                                 case "PATH":  
  499.                                     int PathCount = 0;  
  500.                                     ArrayList PathList = GetKeyData(buffer, ref startIndex, ref PathCount);  
  501.                                     string Temp = "";  
  502.                                     for (int i = 0; i != PathList.Count; i++)  
  503.                                     {  
  504.                                         if (i < PathList.Count && i != 0)  
  505.                                             Temp += "\\";  
  506.                                         Temp += PathList[i].ToString();  
  507.                                     }  
  508.                                     info.Path = Temp;  
  509.                                     break;  
  510.                                 case "PATH.UTF-8":  
  511.                                     int pathUtf8Count = 0;  
  512.                                     ArrayList pathutf8List = GetKeyData(buffer, ref startIndex, ref pathUtf8Count);  
  513.                                     string utfTemp = "";  
  514.                                     for (int i = 0; i != pathutf8List.Count; i++)  
  515.                                     {  
  516.                                         utfTemp += pathutf8List[i].ToString();  
  517.                                     }  
  518.                                     info.PathUTF8 = utfTemp;  
  519.                                     break;  
  520.                             }  
  521.                             break;  
  522.                     }  
  523.   
  524.                 }  
  525.   
  526.             }  
  527.         }  
  528.  
  529.         #endregion  
  530.   
  531.         /// <summary>  
  532.         /// 对应结构 INFO 多个文件时  
  533.         /// </summary>  
  534.         public class FileInfo  
  535.         {  
  536.             private string path = "";  
  537.             private string pathutf8 = "";  
  538.             private long length = 0;  
  539.             private string md5sum = "";  
  540.             private string de2k = "";  
  541.             private string filehash = "";  
  542.   
  543.             /// <summary>  
  544.             /// 文件路径  
  545.             /// </summary>  
  546.             public string Path { get { return path; } set { path = value; } }  
  547.           
  548.             /// <summary>  
  549.             /// UTF8的名称  
  550.             /// </summary>  
  551.             public string PathUTF8 { get { return pathutf8; } set { pathutf8 = value; } }  
  552.               
  553.             /// <summary>  
  554.             /// 文件大小  
  555.             /// </summary>  
  556.             public long Length { get { return length; } set { length = value; } }  
  557.               
  558.             /// <summary>  
  559.             /// MD5验效 (可选)  
  560.             /// </summary>  
  561.             public string MD5Sum { get { return md5sum; } set { md5sum = value; } }  
  562.               
  563.             /// <summary>  
  564.             /// ED2K 未知  
  565.             /// </summary>  
  566.             public string De2K { get { return de2k; } set { de2k = value; } }  
  567.               
  568.             /// <summary>  
  569.             /// FileHash 未知  
  570.             /// </summary>  
  571.             public string FileHash { get { return filehash; } set { filehash = value; } }  
  572.         }  
  573.     }  
  574. }  

[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Collections;  
  6.   
  7. namespace XunleiHelper  
  8. {  
  9.     public class Torrent  
  10.     {  
  11.         #region 私有字段  
  12.           
  13.         private string _openError = "";  
  14.         private bool _openFile = false;  
  15.   
  16.         private string _announce = "";  
  17.         private IList<string> _announceList = new List<string>();  
  18.         private DateTime _createTime = new DateTime(1970, 1, 1, 0, 0, 0);  
  19.         private long _codePage = 0;  
  20.         private string _comment = "";  
  21.         private string _createdBy = "";  
  22.         private string _encoding = "";  
  23.         private string _commentUTF8 = "";  
  24.         private IList<FileInfo> _fileList = new List<FileInfo>();  
  25.         private string _name = "";  
  26.         private string _nameUTF8 = "";  
  27.         private long _pieceLength = 0;  
  28.         private byte[] _pieces;  
  29.         private string _publisher = "";  
  30.         private string _publisherUTF8 = "";  
  31.         private string _publisherUrl = "";  
  32.         private string _publisherUrlUTF8 = "";  
  33.         private IList<string> _notes = new List<string>();  
  34.         private long _totalLength;  
  35.  
  36.         #endregion  
  37.  
  38.         #region 属性  
  39.           
  40.         /// <summary>  
  41.         /// 错误信息  
  42.         /// </summary>  
  43.         public string OpenError { set { _openError = value; } get { return _openError; } }  
  44.           
  45.         /// <summary>  
  46.         /// 是否正常打开文件  
  47.         /// </summary>  
  48.         public bool OpenFile { set { _openFile = value; } get { return _openFile; } }  
  49.           
  50.         /// <summary>  
  51.         /// 服务器的URL(字符串)  
  52.         /// </summary>  
  53.         public string Announce { set { _announce = value; } get { return _announce; } }  
  54.           
  55.         /// <summary>  
  56.         /// 备用tracker服务器列表(列表)  
  57.         /// </summary>  
  58.         public IList<string> AnnounceList { set { _announceList = value; } get { return _announceList; } }  
  59.           
  60.         /// <summary>  
  61.         /// 种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)  
  62.         /// </summary>  
  63.         public DateTime CreateTime { set { _createTime = value; } get { return _createTime; } }  
  64.           
  65.         /// <summary>  
  66.         /// 未知数字CodePage  
  67.         /// </summary>  
  68.         public long CodePage { set { _codePage = value; } get { return _codePage; } }  
  69.           
  70.         /// <summary>  
  71.         /// 种子描述  
  72.         /// </summary>  
  73.         public string Comment { set { _comment = value; } get { return _comment; } }  
  74.           
  75.         /// <summary>  
  76.         /// 编码方式  
  77.         /// </summary>  
  78.         public string CommentUTF8 { set { _commentUTF8 = value; } get { return _commentUTF8; } }  
  79.           
  80.         /// <summary>  
  81.         /// 创建人  
  82.         /// </summary>  
  83.         public string CreatedBy { set { _createdBy = value; } get { return _createdBy; } }  
  84.           
  85.         /// <summary>  
  86.         /// 编码方式  
  87.         /// </summary>  
  88.         public string Encoding { set { _encoding = value; } get { return _encoding; } }  
  89.         /// <summary>  
  90.         /// 文件信息  
  91.         /// </summary>  
  92.         public IList<FileInfo> FileList { set { _fileList = value; } get { return _fileList; } }  
  93.           
  94.         /// <summary>  
  95.         /// 种子名  
  96.         /// </summary>  
  97.         public string Name { set { _name = value; } get { return _name; } }  
  98.         /// <summary>  
  99.         /// 种子名UTF8  
  100.         /// </summary>  
  101.         public string NameUTF8 { set { _nameUTF8 = value; } get { return _nameUTF8; } }  
  102.           
  103.         /// <summary>  
  104.         /// 每个块的大小,单位字节(整数)  
  105.         /// </summary>  
  106.         public long PieceLength { set { _pieceLength = value; } get { return _pieceLength; } }  
  107.           
  108.         /// <summary>  
  109.         /// 每个块的20个字节的SHA1 Hash的值(二进制格式)  
  110.         /// </summary>  
  111.         private byte[] Pieces { set { _pieces = value; } get { return _pieces; } }  
  112.           
  113.         /// <summary>  
  114.         /// 出版  
  115.         /// </summary>  
  116.         public string Publisher { set { _publisher = value; } get { return _publisher; } }  
  117.           
  118.         /// <summary>  
  119.         /// 出版UTF8  
  120.         /// </summary>  
  121.         public string PublisherUTF8 { set { _publisherUTF8 = value; } get { return _publisherUTF8; } }  
  122.           
  123.         /// <summary>  
  124.         /// 出版地址  
  125.         /// </summary>  
  126.         public string PublisherUrl { set { _publisherUrl = value; } get { return _publisherUrl; } }  
  127.       
  128.         /// <summary>  
  129.         /// 出版地址  
  130.         /// </summary>  
  131.         public string PublisherUrlUTF8 { set { _publisherUrlUTF8 = value; } get { return _publisherUrlUTF8; } }  
  132.           
  133.         /// <summary>  
  134.         /// NODES  
  135.         /// </summary>  
  136.         public IList<string> Notes { set { _notes = value; } get { return _notes; } }  
  137.   
  138.         /// <summary>  
  139.         /// 包含文件的总长度  
  140.         /// </summary>  
  141.         public long TotalLength  
  142.         {  
  143.             get  
  144.             {  
  145.                 return _totalLength;  
  146.             }  
  147.         }  
  148.  
  149.         #endregion  
  150.   
  151.         public Torrent(string fileName)  
  152.         {  
  153.             System.IO.FileStream torrentFile = new System.IO.FileStream(fileName, System.IO.FileMode.Open);  
  154.             byte[] buffer = new byte[torrentFile.Length];  
  155.             torrentFile.Read(buffer, 0, buffer.Length);  
  156.             torrentFile.Close();  
  157.   
  158.             if ((char)buffer[0] != 'd')  
  159.             {  
  160.                 if (OpenError.Length == 0) OpenError = "错误的Torrent文件,开头第1字节不是100";  
  161.                 return;  
  162.             }  
  163.             GetTorrentData(buffer);  
  164.         }  
  165.  
  166.         #region 开始读数据  
  167.   
  168.         /// <summary>  
  169.         /// 开始读取  
  170.         /// </summary>  
  171.         /// <param name="buffer"></param>  
  172.         private void GetTorrentData(byte[] buffer)  
  173.         {  
  174.             int startIndex = 1;  
  175.             while (true)  
  176.             {  
  177.                 object Keys = GetKeyText(buffer, ref startIndex);  
  178.                 if (Keys == null)  
  179.                 {  
  180.                     if (startIndex >= buffer.Length) OpenFile = true;  
  181.                     break;  
  182.                 }  
  183.   
  184.                 if (GetValueText(buffer, ref startIndex, Keys.ToString().ToUpper()) == falsebreak;  
  185.             }  
  186.         }  
  187.  
  188.         #endregion  
  189.   
  190.         /// <summary>  
  191.         /// 读取结构  
  192.         /// </summary>  
  193.         /// <param name="buffer"></param>  
  194.         /// <param name="starIndex"></param>  
  195.         /// <param name="key"></param>  
  196.         /// <returns></returns>  
  197.         private bool GetValueText(byte[] buffer, ref int starIndex, string key)  
  198.         {  
  199.             switch (key)  
  200.             {  
  201.                 case "ANNOUNCE":  
  202.                     Announce = GetKeyText(buffer, ref starIndex).ToString();  
  203.                     break;  
  204.                 case "ANNOUNCE-LIST":  
  205.                     int listCount = 0;  
  206.                     ArrayList _tempList = GetKeyData(buffer, ref starIndex, ref listCount);  
  207.                     for (int i = 0; i != _tempList.Count; i++)  
  208.                     {  
  209.                         AnnounceList.Add(_tempList[i].ToString());  
  210.                     }  
  211.                     break;  
  212.                 case "CREATION DATE":  
  213.                     object date = GetKeyNumb(buffer, ref starIndex).ToString();  
  214.                     if (date == null)  
  215.                     {  
  216.                         if (OpenError.Length == 0) OpenError = "CREATION DATE 返回不是数字类型";  
  217.                         return false;  
  218.                     }  
  219.                     CreateTime = CreateTime.AddTicks(long.Parse(date.ToString()));  
  220.                     break;  
  221.                 case "CODEPAGE":  
  222.                     object codePageNumb = GetKeyNumb(buffer, ref starIndex);  
  223.                     if (codePageNumb == null)  
  224.                     {  
  225.                         if (OpenError.Length == 0) OpenError = "CODEPAGE 返回不是数字类型";  
  226.                         return false;  
  227.                     }  
  228.                     CodePage = long.Parse(codePageNumb.ToString());  
  229.                     break;  
  230.                 case "ENCODING":  
  231.                     Encoding = GetKeyText(buffer, ref starIndex).ToString();  
  232.                     break;  
  233.                 case "CREATED BY":  
  234.                     CreatedBy = GetKeyText(buffer, ref starIndex).ToString();  
  235.                     break;  
  236.                 case "COMMENT":  
  237.                     Comment = GetKeyText(buffer, ref starIndex).ToString();  
  238.                     break;  
  239.                 case "COMMENT.UTF-8":  
  240.                     CommentUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  241.                     break;  
  242.                 case "INFO":  
  243.                     int fileListCount = 0;  
  244.                     GetFileInfo(buffer, ref starIndex, ref fileListCount);  
  245.                     break;  
  246.                 case "NAME":  
  247.                     Name = GetKeyText(buffer, ref starIndex).ToString();  
  248.                     break;  
  249.                 case "NAME.UTF-8":  
  250.                     NameUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  251.                     break;  
  252.                 case "PIECE LENGTH":  
  253.                     object pieceLengthNumb = GetKeyNumb(buffer, ref starIndex);  
  254.                     if (pieceLengthNumb == null)  
  255.                     {  
  256.                         if (OpenError.Length == 0) OpenError = "PIECE LENGTH 返回不是数字类型";  
  257.                         return false;  
  258.                     }  
  259.                     PieceLength = long.Parse(pieceLengthNumb.ToString());  
  260.                     break;  
  261.                 case "PIECES":  
  262.                     Pieces = GetKeyByte(buffer, ref starIndex);  
  263.                     break;  
  264.                 case "PUBLISHER":  
  265.                     Publisher = GetKeyText(buffer, ref starIndex).ToString();  
  266.                     break;  
  267.                 case "PUBLISHER.UTF-8":  
  268.                     PublisherUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  269.                     break;  
  270.                 case "PUBLISHER-URL":  
  271.                     PublisherUrl = GetKeyText(buffer, ref starIndex).ToString();  
  272.                     break;  
  273.                 case "PUBLISHER-URL.UTF-8":  
  274.                     PublisherUrlUTF8 = GetKeyText(buffer, ref starIndex).ToString();  
  275.                     break;  
  276.                 case "NODES":  
  277.                     int nodesCount = 0;  
  278.                     ArrayList _nodesList = GetKeyData(buffer, ref starIndex, ref nodesCount);  
  279.                     int ipCount = _nodesList.Count / 2;  
  280.                     for (int i = 0; i != ipCount; i++)  
  281.                     {  
  282.                         Notes.Add(_nodesList[i * 2] + ":" + _nodesList[(i * 2) + 1]);  
  283.                     }  
  284.                     break;  
  285.   
  286.                 default:  
  287.                     return false;  
  288.             }  
  289.             return true;  
  290.         }  
  291.  
  292.         #region 获取数据  
  293.           
  294.         /// <summary>  
  295.         /// 获取列表方式 "I1:Xe"="X" 会调用GetKeyText  
  296.         /// </summary>  
  297.         /// <param name="buffer"></param>  
  298.         /// <param name="starIndex"></param>  
  299.         /// <param name="listCount"></param>  
  300.         private ArrayList GetKeyData(byte[] buffer, ref int starIndex, ref int listCount)  
  301.         {  
  302.             ArrayList _tempList = new ArrayList();  
  303.             while (true)  
  304.             {  
  305.                 string textStar = System.Text.Encoding.UTF8.GetString(buffer, starIndex, 1);  
  306.                 switch (textStar)  
  307.                 {  
  308.                     case "l":  
  309.                         starIndex++;  
  310.                         listCount++;  
  311.                         break;  
  312.                     case "e":  
  313.                         listCount--;  
  314.                         starIndex++;  
  315.                         if (listCount == 0) return _tempList;  
  316.                         break;  
  317.                     case "i":  
  318.                         _tempList.Add(GetKeyNumb(buffer, ref starIndex).ToString());  
  319.                         break;  
  320.                     default:  
  321.                         object listText = GetKeyText(buffer, ref starIndex);  
  322.                         if (listText != null)  
  323.                         {  
  324.                             _tempList.Add(listText.ToString());  
  325.                         }  
  326.                         else  
  327.                         {  
  328.                             if (OpenError.Length == 0)  
  329.                             {  
  330.                                 OpenError = "错误的Torrent文件,ANNOUNCE-LIST错误";  
  331.                                 return _tempList;  
  332.                             }  
  333.                         }  
  334.                         break;  
  335.                 }  
  336.             }  
  337.         }  
  338.           
  339.         /// <summary>  
  340.         /// 获取字符串  
  341.         /// </summary>  
  342.         /// <param name="buffer"></param>  
  343.         /// <param name="startIndex"></param>  
  344.         /// <returns></returns>  
  345.         private object GetKeyText(byte[] buffer, ref int startIndex)  
  346.         {  
  347.             int numb = 0;  
  348.             int leftNumb = 0;  
  349.             for (int i = startIndex; i != buffer.Length; i++)  
  350.             {  
  351.                 if ((char)buffer[i] == ':'break;  
  352.                 if ((char)buffer[i] == 'e')  
  353.                 {  
  354.                     leftNumb++;  
  355.                     continue;  
  356.                 }  
  357.                 numb++;  
  358.             }  
  359.   
  360.             startIndex += leftNumb;  
  361.             string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);  
  362.             try  
  363.             {  
  364.                 int readNumb = Int32.Parse(textNumb);  
  365.                 startIndex = startIndex + numb + 1;  
  366.                 object keyText = System.Text.Encoding.UTF8.GetString(buffer, startIndex, readNumb);  
  367.                 startIndex += readNumb;  
  368.                 return keyText;  
  369.             }  
  370.             catch  
  371.             {  
  372.                 return null;  
  373.             }  
  374.   
  375.         }  
  376.   
  377.         /// <summary>  
  378.         /// 获取数字  
  379.         /// </summary>  
  380.         /// <param name="buffer"></param>  
  381.         /// <param name="startIndex"></param>  
  382.         private object GetKeyNumb(byte[] buffer, ref int startIndex)  
  383.         {  
  384.             if (System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1) == "i")  
  385.             {  
  386.                 int numb = 0;  
  387.                 for (int i = startIndex; i != buffer.Length; i++)  
  388.                 {  
  389.                     if ((char)buffer[i] == 'e'break;  
  390.                     numb++;  
  391.                 }  
  392.                 startIndex++;  
  393.                 long retNumb = 0;  
  394.                 try  
  395.                 {  
  396.                     retNumb = long.Parse(System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb - 1));  
  397.                     startIndex += numb;  
  398.                     return retNumb;  
  399.                 }  
  400.                 catch  
  401.                 {  
  402.                     return null;  
  403.                 }  
  404.             }  
  405.             else  
  406.             {  
  407.                 return null;  
  408.             }  
  409.   
  410.         }  
  411.   
  412.         /// <summary>  
  413.         /// 获取BYTE数据  
  414.         /// </summary>  
  415.         /// <param name="buffer"></param>  
  416.         /// <param name="startIndex"></param>  
  417.         /// <returns></returns>  
  418.         private byte[] GetKeyByte(byte[] buffer, ref int startIndex)  
  419.         {  
  420.             int numb = 0;  
  421.             for (int i = startIndex; i != buffer.Length; i++)  
  422.             {  
  423.                 if ((char)buffer[i] == ':'break;  
  424.                 numb++;  
  425.             }  
  426.             string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);  
  427.   
  428.             try  
  429.             {  
  430.                 int readNumb = Int32.Parse(textNumb);  
  431.                 startIndex = startIndex + numb + 1;  
  432.                 System.IO.MemoryStream keyMemory = new System.IO.MemoryStream(buffer, startIndex, readNumb);  
  433.                 byte[] keyBytes = new byte[readNumb];  
  434.                 keyMemory.Read(keyBytes, 0, readNumb);  
  435.                 keyMemory.Close();  
  436.                 startIndex += readNumb;  
  437.                 return keyBytes;  
  438.             }  
  439.             catch  
  440.             {  
  441.                 return null;  
  442.             }  
  443.         }  
  444.   
  445.         /// <summary>  
  446.         /// 对付INFO的结构  
  447.         /// </summary>  
  448.         /// <param name="buffer"></param>  
  449.         /// <param name="startIndex"></param>  
  450.         /// <param name="listCount"></param>  
  451.         private void GetFileInfo(byte[] buffer, ref int startIndex, ref int listCount)  
  452.         {  
  453.             if ((char)buffer[startIndex] != 'd'return;  
  454.             startIndex++;  
  455.   
  456.             if (GetKeyText(buffer, ref startIndex).ToString().ToUpper() == "FILES")  
  457.             {  
  458.                 FileInfo info = new FileInfo();  
  459.   
  460.                 while (true)  
  461.                 {  
  462.                     string TextStar = System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1);  
  463.   
  464.                     switch (TextStar)  
  465.                     {  
  466.                         case "l":  
  467.                             startIndex++;  
  468.                             listCount++;  
  469.                             break;  
  470.                         case "e":  
  471.                             listCount--;  
  472.                             startIndex++;  
  473.                             if (listCount == 1) FileList.Add(info);  
  474.                             if (listCount == 0) return;  
  475.                             break;  
  476.                         case "d":  
  477.                             info = new FileInfo();  
  478.                             listCount++;  
  479.                             startIndex++;  
  480.                             break;  
  481.   
  482.                         default:  
  483.                             object listText = GetKeyText(buffer, ref startIndex);  
  484.                             if (listText == nullreturn;  
  485.                             switch (listText.ToString().ToUpper())   //转换为大写  
  486.                             {  
  487.                                 case "ED2K":  
  488.                                     info.De2K = GetKeyText(buffer, ref startIndex).ToString();  
  489.                                     break;  
  490.                                 case "FILEHASH":  
  491.                                     info.FileHash = GetKeyText(buffer, ref startIndex).ToString();  
  492.                                     break;  
  493.   
  494.                                 case "LENGTH":  
  495.                                     info.Length = Convert.ToInt64(GetKeyNumb(buffer, ref startIndex));  
  496.                                     _totalLength += info.Length;  
  497.                                     break;  
  498.                                 case "PATH":  
  499.                                     int PathCount = 0;  
  500.                                     ArrayList PathList = GetKeyData(buffer, ref startIndex, ref PathCount);  
  501.                                     string Temp = "";  
  502.                                     for (int i = 0; i != PathList.Count; i++)  
  503.                                     {  
  504.                                         if (i < PathList.Count && i != 0)  
  505.                                             Temp += "\\";  
  506.                                         Temp += PathList[i].ToString();  
  507.                                     }  
  508.                                     info.Path = Temp;  
  509.                                     break;  
  510.                                 case "PATH.UTF-8":  
  511.                                     int pathUtf8Count = 0;  
  512.                                     ArrayList pathutf8List = GetKeyData(buffer, ref startIndex, ref pathUtf8Count);  
  513.                                     string utfTemp = "";  
  514.                                     for (int i = 0; i != pathutf8List.Count; i++)  
  515.                                     {  
  516.                                         utfTemp += pathutf8List[i].ToString();  
  517.                                     }  
  518.                                     info.PathUTF8 = utfTemp;  
  519.                                     break;  
  520.                             }  
  521.                             break;  
  522.                     }  
  523.   
  524.                 }  
  525.   
  526.             }  
  527.         }  
  528.  
  529.         #endregion  
  530.   
  531.         /// <summary>  
  532.         /// 对应结构 INFO 多个文件时  
  533.         /// </summary>  
  534.         public class FileInfo  
  535.         {  
  536.             private string path = "";  
  537.             private string pathutf8 = "";  
  538.             private long length = 0;  
  539.             private string md5sum = "";  
  540.             private string de2k = "";  
  541.             private string filehash = "";  
  542.   
  543.             /// <summary>  
  544.             /// 文件路径  
  545.             /// </summary>  
  546.             public string Path { get { return path; } set { path = value; } }  
  547.           
  548.             /// <summary>  
  549.             /// UTF8的名称  
  550.             /// </summary>  
  551.             public string PathUTF8 { get { return pathutf8; } set { pathutf8 = value; } }  
  552.               
  553.             /// <summary>  
  554.             /// 文件大小  
  555.             /// </summary>  
  556.             public long Length { get { return length; } set { length = value; } }  
  557.               
  558.             /// <summary>  
  559.             /// MD5验效 (可选)  
  560.             /// </summary>  
  561.             public string MD5Sum { get { return md5sum; } set { md5sum = value; } }  
  562.               
  563.             /// <summary>  
  564.             /// ED2K 未知  
  565.             /// </summary>  
  566.             public string De2K { get { return de2k; } set { de2k = value; } }  
  567.               
  568.             /// <summary>  
  569.             /// FileHash 未知  
  570.             /// </summary>  
  571.             public string FileHash { get { return filehash; } set { filehash = value; } }  
  572.         }  
  573.     }  
  574. }  
0 0
原创粉丝点击