C# 解析bt种子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
     
namespace XunleiHelper
{
public class Torrent
{
#region 私有字段
private string _openError = "";
private bool _openFile = false;
     
private string _announce = "";
private IList<string> _announceList = new List<string>();
private DateTime _createTime = new DateTime(1970, 1, 1, 0, 0, 0);
private long _codePage = 0;
private string _comment = "";
private string _createdBy = "";
private string _encoding = "";
private string _commentUTF8 = "";
private IList<FileInfo> _fileList = new List<FileInfo>();
private string _name = "";
private string _nameUTF8 = "";
private long _pieceLength = 0;
private byte[] _pieces;
private string _publisher = "";
private string _publisherUTF8 = "";
private string _publisherUrl = "";
private string _publisherUrlUTF8 = "";
private IList<string> _notes = new List<string>();
private long _totalLength;
     
#endregion
     
#region 属性
/// <summary>
/// 错误信息
/// </summary>
public string OpenError { set { _openError = value; } get { return _openError; } }
/// <summary>
/// 是否正常打开文件
/// </summary>
public bool OpenFile { set { _openFile = value; } get { return _openFile; } }
/// <summary>
/// 服务器的URL(字符串)
/// </summary>
public string Announce { set { _announce = value; } get { return _announce; } }
/// <summary>
/// 备用tracker服务器列表(列表)
/// </summary>
public IList<string> AnnounceList { set { _announceList = value; } get { return _announceList; } }
/// <summary>
/// 种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)
/// </summary>
public DateTime CreateTime { set { _createTime = value; } get { return _createTime; } }
/// <summary>
/// 未知数字CodePage
/// </summary>
public long CodePage { set { _codePage = value; } get { return _codePage; } }
/// <summary>
/// 种子描述
/// </summary>
public string Comment { set { _comment = value; } get { return _comment; } }
/// <summary>
/// 编码方式
/// </summary>
public string CommentUTF8 { set { _commentUTF8 = value; } get { return _commentUTF8; } }
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { set { _createdBy = value; } get { return _createdBy; } }
/// <summary>
/// 编码方式
/// </summary>
public string Encoding { set { _encoding = value; } get { return _encoding; } }
/// <summary>
/// 文件信息
/// </summary>
public IList<FileInfo> FileList { set { _fileList = value; } get { return _fileList; } }
/// <summary>
/// 种子名
/// </summary>
public string Name { set { _name = value; } get { return _name; } }
/// <summary>
/// 种子名UTF8
/// </summary>
public string NameUTF8 { set { _nameUTF8 = value; } get { return _nameUTF8; } }
/// <summary>
/// 每个块的大小,单位字节(整数)
/// </summary>
public long PieceLength { set { _pieceLength = value; } get { return _pieceLength; } }
/// <summary>
/// 每个块的20个字节的SHA1 Hash的值(二进制格式)
/// </summary>
private byte[] Pieces { set { _pieces = value; } get { return _pieces; } }
/// <summary>
/// 出版
/// </summary>
public string Publisher { set { _publisher = value; } get { return _publisher; } }
/// <summary>
/// 出版UTF8
/// </summary>
public string PublisherUTF8 { set { _publisherUTF8 = value; } get { return _publisherUTF8; } }
/// <summary>
/// 出版地址
/// </summary>
public string PublisherUrl { set { _publisherUrl = value; } get { return _publisherUrl; } }
/// <summary>
/// 出版地址
/// </summary>
public string PublisherUrlUTF8 { set { _publisherUrlUTF8 = value; } get { return _publisherUrlUTF8; } }
/// <summary>
/// NODES
/// </summary>
public IList<string> Notes { set { _notes = value; } get { return _notes; } }
     
/// <summary>
/// 包含文件的总长度
/// </summary>
public long TotalLength
{
get
{
return _totalLength;
}
}
     
#endregion
     
public Torrent(string fileName)
{
System.IO.FileStream torrentFile = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
byte[] buffer = new byte[torrentFile.Length];
torrentFile.Read(buffer, 0, buffer.Length);
torrentFile.Close();
     
if ((char)buffer[0] != 'd')
{
if (OpenError.Length == 0) OpenError = "错误的Torrent文件,开头第1字节不是100";
return;
}
GetTorrentData(buffer);
}
     
#region 开始读数据
     
/// <summary>
/// 开始读取
/// </summary>
/// <param name="buffer"></param>
private void GetTorrentData(byte[] buffer)
{
int startIndex = 1;
while (true)
{
object Keys = GetKeyText(buffer, ref startIndex);
if (Keys == null)
{
if (startIndex >= buffer.Length) OpenFile = true;
break;
}
     
if (GetValueText(buffer, ref startIndex, Keys.ToString().ToUpper()) == false) break;
}
}
     
#endregion
     
/// <summary>
/// 读取结构
/// </summary>
/// <param name="buffer"></param>
/// <param name="starIndex"></param>
/// <param name="key"></param>
/// <returns></returns>
private bool GetValueText(byte[] buffer, ref int starIndex, string key)
{
switch (key)
{
case "ANNOUNCE":
Announce = GetKeyText(buffer, ref starIndex).ToString();
break;
case "ANNOUNCE-LIST":
int listCount = 0;
ArrayList _tempList = GetKeyData(buffer, ref starIndex, ref listCount);
for (int i = 0; i != _tempList.Count; i++)
{
AnnounceList.Add(_tempList[i].ToString());
}
break;
case "CREATION DATE":
object date = GetKeyNumb(buffer, ref starIndex).ToString();
if (date == null)
{
if (OpenError.Length == 0) OpenError = "CREATION DATE 返回不是数字类型";
return false;
}
CreateTime = CreateTime.AddTicks(long.Parse(date.ToString()));
break;
case "CODEPAGE":
object codePageNumb = GetKeyNumb(buffer, ref starIndex);
if (codePageNumb == null)
{
if (OpenError.Length == 0) OpenError = "CODEPAGE 返回不是数字类型";
return false;
}
CodePage = long.Parse(codePageNumb.ToString());
break;
case "ENCODING":
Encoding = GetKeyText(buffer, ref starIndex).ToString();
break;
case "CREATED BY":
CreatedBy = GetKeyText(buffer, ref starIndex).ToString();
break;
case "COMMENT":
Comment = GetKeyText(buffer, ref starIndex).ToString();
break;
case "COMMENT.UTF-8":
CommentUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "INFO":
int fileListCount = 0;
GetFileInfo(buffer, ref starIndex, ref fileListCount);
break;
case "NAME":
Name = GetKeyText(buffer, ref starIndex).ToString();
break;
case "NAME.UTF-8":
NameUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PIECE LENGTH":
object pieceLengthNumb = GetKeyNumb(buffer, ref starIndex);
if (pieceLengthNumb == null)
{
if (OpenError.Length == 0) OpenError = "PIECE LENGTH 返回不是数字类型";
return false;
}
PieceLength = long.Parse(pieceLengthNumb.ToString());
break;
case "PIECES":
Pieces = GetKeyByte(buffer, ref starIndex);
break;
case "PUBLISHER":
Publisher = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER.UTF-8":
PublisherUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER-URL":
PublisherUrl = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER-URL.UTF-8":
PublisherUrlUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "NODES":
int nodesCount = 0;
ArrayList _nodesList = GetKeyData(buffer, ref starIndex, ref nodesCount);
int ipCount = _nodesList.Count / 2;
for (int i = 0; i != ipCount; i++)
{
Notes.Add(_nodesList[i * 2] + ":" + _nodesList[(i * 2) + 1]);
}
break;
     
default:
return false;
}
return true;
}
     
#region 获取数据
/// <summary>
/// 获取列表方式 "I1:Xe"="X" 会调用GetKeyText
/// </summary>
/// <param name="buffer"></param>
/// <param name="starIndex"></param>
/// <param name="listCount"></param>
private ArrayList GetKeyData(byte[] buffer, ref int starIndex, ref int listCount)
{
ArrayList _tempList = new ArrayList();
while (true)
{
string textStar = System.Text.Encoding.UTF8.GetString(buffer, starIndex, 1);
switch (textStar)
{
case "l":
starIndex++;
listCount++;
break;
case "e":
listCount--;
starIndex++;
if (listCount == 0) return _tempList;
break;
case "i":
_tempList.Add(GetKeyNumb(buffer, ref starIndex).ToString());
break;
default:
object listText = GetKeyText(buffer, ref starIndex);
if (listText != null)
{
_tempList.Add(listText.ToString());
}
else
{
if (OpenError.Length == 0)
{
OpenError = "错误的Torrent文件,ANNOUNCE-LIST错误";
return _tempList;
}
}
break;
}
}
}
/// <summary>
/// 获取字符串
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
private object GetKeyText(byte[] buffer, ref int startIndex)
{
int numb = 0;
int leftNumb = 0;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == ':') break;
if ((char)buffer[i] == 'e')
{
leftNumb++;
continue;
}
numb++;
}
     
startIndex += leftNumb;
string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);
try
{
int readNumb = Int32.Parse(textNumb);
startIndex = startIndex + numb + 1;
object keyText = System.Text.Encoding.UTF8.GetString(buffer, startIndex, readNumb);
startIndex += readNumb;
return keyText;
}
catch
{
return null;
}
     
}
     
/// <summary>
/// 获取数字
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
private object GetKeyNumb(byte[] buffer, ref int startIndex)
{
if (System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1) == "i")
{
int numb = 0;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == 'e') break;
numb++;
}
startIndex++;
long retNumb = 0;
try
{
retNumb = long.Parse(System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb - 1));
startIndex += numb;
return retNumb;
}
catch
{
return null;
}
}
else
{
return null;
}
     
}
     
/// <summary>
/// 获取BYTE数据
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
private byte[] GetKeyByte(byte[] buffer, ref int startIndex)
{
int numb = 0;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == ':') break;
numb++;
}
string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);
     
try
{
int readNumb = Int32.Parse(textNumb);
startIndex = startIndex + numb + 1;
System.IO.MemoryStream keyMemory = new System.IO.MemoryStream(buffer, startIndex, readNumb);
byte[] keyBytes = new byte[readNumb];
keyMemory.Read(keyBytes, 0, readNumb);
keyMemory.Close();
startIndex += readNumb;
return keyBytes;
}
catch
{
return null;
}
}
     
/// <summary>
/// 对付INFO的结构
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <param name="listCount"></param>
private void GetFileInfo(byte[] buffer, ref int startIndex, ref int listCount)
{
if ((char)buffer[startIndex] != 'd') return;
startIndex++;
     
if (GetKeyText(buffer, ref startIndex).ToString().ToUpper() == "FILES")
{
FileInfo info = new FileInfo();
     
while (true)
{
string TextStar = System.Text.Encoding.UTF8.GetString(buffer, startIndex, 1);
     
switch (TextStar)
{
case "l":
startIndex++;
listCount++;
break;
case "e":
listCount--;
startIndex++;
if (listCount == 1) FileList.Add(info);
if (listCount == 0) return;
break;
case "d":
info = new FileInfo();
listCount++;
startIndex++;
break;
     
default:
object listText = GetKeyText(buffer, ref startIndex);
if (listText == null) return;
switch (listText.ToString().ToUpper())   //转换为大写
{
case "ED2K":
info.De2K = GetKeyText(buffer, ref startIndex).ToString();
break;
case "FILEHASH":
info.FileHash = GetKeyText(buffer, ref startIndex).ToString();
break;
     
case "LENGTH":
info.Length = Convert.ToInt64(GetKeyNumb(buffer, ref startIndex));
_totalLength += info.Length;
break;
case "PATH":
int PathCount = 0;
ArrayList PathList = GetKeyData(buffer, ref startIndex, ref PathCount);
string Temp = "";
for (int i = 0; i != PathList.Count; i++)
{
if (i < PathList.Count && i != 0)
Temp += "\\";
Temp += PathList[i].ToString();
}
info.Path = Temp;
break;
case "PATH.UTF-8":
int pathUtf8Count = 0;
ArrayList pathutf8List = GetKeyData(buffer, ref startIndex, ref pathUtf8Count);
string utfTemp = "";
for (int i = 0; i != pathutf8List.Count; i++)
{
utfTemp += pathutf8List[i].ToString();
}
info.PathUTF8 = utfTemp;
break;
}
break;
}
     
}
     
}
}
     
#endregion
     
/// <summary>
/// 对应结构 INFO 多个文件时
/// </summary>
public class FileInfo
{
private string path = "";
private string pathutf8 = "";
private long length = 0;
private string md5sum = "";
private string de2k = "";
private string filehash = "";
     
/// <summary>
/// 文件路径
/// </summary>
public string Path { get { return path; } set { path = value; } }
/// <summary>
/// UTF8的名称
/// </summary>
public string PathUTF8 { get { return pathutf8; } set { pathutf8 = value; } }
/// <summary>
/// 文件大小
/// </summary>
public long Length { get { return length; } set { length = value; } }
/// <summary>
/// MD5验效 (可选)
/// </summary>
public string MD5Sum { get { return md5sum; } set { md5sum = value; } }
/// <summary>
/// ED2K 未知
/// </summary>
public string De2K { get { return de2k; } set { de2k = value; } }
/// <summary>
/// FileHash 未知
/// </summary>
public string FileHash { get { return filehash; } set { filehash = value; } }
}
}
}

 

扩展阅读:b编码级种子文件的解析
En解释+API:http://wiki.theory.org/BitTorrentSpecification  (推荐LordMike所写的库:下载)

原文:http://hi.baidu.com/kongfl888/item/6c97d4cb14a35b42a8ba94f8

转载于:https://www.cnblogs.com/kongfl888/p/3351737.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值