⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 torrentfile.pas

📁 分析torrent的东西是拿别人的
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit TorrentFile;

interface

uses
  SysUtils, StrUtils, Contnrs, Hashes, Classes, BCode, MessageDigests, TSpyUtil;

type
  TProgressCallback = function(PieceNum: Integer): Boolean of object;
  TTorrentPiece = class(TObject)
  private
    _Hash: string;
    _Valid: Boolean;
  public
    property Hash: string read _Hash;
    property Valid: Boolean read _Valid write _Valid;
    constructor Create(Hash: string; Valid: Boolean);
  end;
  TTorrentSubFile = class(TObject)
  private
    _Name: string;
    _Path: string;
    _Length: Int64;
    _Offset: Int64;
    _Left: Int64;
    _MD5Sum: string;
    _MD4Sum: string;
    _SHA1Sum: string;
  public
    property Name: string read _Name;
    property Path: string read _Path;
    property Len: Int64 read _Length;
    property Offset: Int64 read _Offset;
    property Left: Int64 read _Left write _Left;
    property MD5Sum: string read _MD5Sum;
    property MD4Sum: string read _MD4Sum;
    property SHA1Sum: string read _SHA1Sum;
    constructor Create(Name: string; Path: string; Len: Int64; Offset: Int64; MD5Sum, SHA1Sum, MD4Sum: string);
  end;
  TTorrentFile = class(TObject)
  published
  private
    _Announce: string;
    _AnnounceList: TObjectList;
    _Name: string;
    _Length: Int64;
    _Count: Integer;
    _Files: TObjectList;
    _Err: TStringList;
    _Tree: TObjectHash;
    _SHA1Hash: string;
    _MD5Hash: string;
    _MD4Hash: string;
    _InfoHash: string;
    _PieceLength: Integer;
    _Multifile: Boolean;
    _BinaryHash: string;
    _Comment: string;
    _CreationDate: Int64;
    _CreationDateAsString: string;
    _CreatedBy: string;
    _PathDelim: string;
  public
    Pieces: array of TTorrentPiece;
    property Announce: string read _Announce write _Announce;
    property AnnounceList: TObjectList read _AnnounceList write _AnnounceList;
    property Name: string read _Name write _Name;
    property Len: Int64 read _Length;
    property Count: Integer read _Count;
    property Tree: TObjectHash read _Tree;
    property Errors: TStringList read _Err;
    property Hash: string read _InfoHash;
    property BinaryHash: string read _BinaryHash;
    property Files: TObjectList read _Files;
    property PieceLength: Integer read _PieceLength write _PieceLength;
    property Multifile: Boolean read _Multifile;
    property Comment: string read _Comment write _Comment;
    property CreationDate: Int64 read _CreationDate;
    property CreationDateAsString: string read _CreationDateAsString;
    property CreatedBy: string read _CreatedBy write _CreatedBy;
    property PathDelim: string read _PathDelim;
    procedure Clear();
    function Load(Stream: TStream): Boolean;
    function Save(Stream: TStream): Boolean;
    constructor Create();
    destructor Destroy(); override;
    function MakePieces(CallbackProc: TProgressCallback; FileList: TObjectList): Integer;
  end;

implementation

function SortFiles(A, B: Pointer): Integer;
begin
  Result := CompareStr(TTorrentSubFile(A).Path, TTorrentSubFile(B).Path);
end;

{ TTorrentSubFile }

constructor TTorrentSubFile.Create(Name, Path: string; Len: Int64; Offset: Int64; MD5Sum, SHA1Sum, MD4Sum: string);
begin
  _Name := Name;
  _Path := Path;
  _Length := Len;
  _Offset := Offset;
  _Left := Len;
  _MD5Sum := MD5Sum;
  _MD4Sum := MD4Sum;
  _SHA1Sum := SHA1Sum;
  inherited Create();
end;

{ TTorrentFile }

procedure TTorrentFile.Clear();
var
  i: Integer;
begin
  _Announce := '';
  _AnnounceList.Clear();
  _Name := '';
  _InfoHash := '';
  _SHA1Hash := '';
  _MD5Hash := '';
  _MD4Hash := '';
  _Length := 0;
  _Count := 0;
  _Files.Clear();
  _Tree.Clear();
  _Err.Clear();
  _BinaryHash := '';
  _Comment := '';
  _CreationDate := 0;
  _CreationDateAsString := '';
  _CreatedBy := '';
  for i := Low(Pieces) to High(Pieces) do FreeAndNil(Pieces[i]);
  SetLength(Pieces, 0);
  _Multifile := False;
end;

constructor TTorrentFile.Create();
begin
  _Files := TObjectList.Create();
  _Tree := TObjectHash.Create();
  _Err := TStringList.Create();
  _AnnounceList := TObjectList.Create();
  _PathDelim := (IncludeTrailingPathDelimiter('.'))[2];
  inherited Create();
end;

destructor TTorrentFile.Destroy();
begin
  Clear();
  FreeAndNil(_Files);
  FreeAndNil(_Tree);
  FreeAndNil(_Err);
  FreeAndNil(_AnnounceList);
  inherited;
end;

function TTorrentFile.Load(Stream: TStream): Boolean;
var
  info, thisfile: TObjectHash;
  files, path, announcelist, announcetier: TObjectList;
  thistier: TStringList;
  fp, fn, bh, md5sum, md4sum, sha1sum: string;
  i, j, pcount: Integer;
  sz, fs, fo: Int64;
  sha: TSHA1;
  r: Boolean;
  o: TObject;
  p: PChar;
begin
  Clear();
  r := False;
  sz := 0;
  try
    try
      o := bdecodeStream(Stream);
      if (Assigned(o)) then begin
        _Tree := o as TObjectHash;
        if (_Tree.Exists('announce')) then
          if _Tree['announce'] is TString then
            _Announce := (_Tree['announce'] as TString).Value
          else
            _Err.Add('Corrupt file: The "announce" segment should be a string')
        else
          _Err.Add('Corrupt File: Missing "announce" segment');
        if (_Tree.Exists('announce-list')) then begin
          if _Tree['announce-list'] is TObjectList then begin
            announcelist := _Tree['announce-list'] as TObjectList;
            for i := 0 to announcelist.Count - 1 do begin
              if announcelist[i] is TObjectList then begin
                announcetier := announcelist[i] as TObjectList;
                thistier := TStringList.Create();
                for j := 0 to announcetier.Count - 1 do
                  if announcetier[j] is TString then
                    thistier.Add((announcetier[j] as TString).Value)
                  else
                    _Err.Add('Corrupt file: The entries in each tier of the "announce-list" segment should be strings');
                if thistier.Count > 0 then begin
                  _AnnounceList.Add(thistier);
                  thistier := nil;
                end else
                  FreeAndNil(thistier);
              end else begin
                _Err.Add('Corrupt file: The tiers in the "announce-list" segment should also be lists ')
              end; // if is a list
            end; // for i
          end else begin
            _Err.Add('Corrupt file: The "announce-list" segment should be a list');
          end; // if is an object list
        end; // if has key
        if (_Tree.Exists('creation date')) then
          if _Tree['creation date'] is TInt64 then
            _CreationDate := (_Tree['creation date'] as TInt64).Value
          else if _Tree['creation date'] is TString then
            _CreationDateAsString := (_Tree['creation date'] as TString).Value
          else
            _Err.Add('Corrupt file: The "creation date" segment should be an integer');
        if (_Tree.Exists('created by')) then
          if _Tree['created by'] is TString then
            _CreatedBy := (_Tree['created by'] as TString).Value
          else
            _Err.Add('Corrupt file: The "created by" segment should be a string');
        if (_Tree.Exists('user-agent')) then
          if _Tree['user-agent'] is TString then
            _CreatedBy := (_Tree['user-agent'] as TString).Value
          else
            _Err.Add('Corrupt file: The "user-agent" segment should be a string');
        if (_Tree.Exists('comment')) then
          if _Tree['comment'] is TString then
            _Comment := (_Tree['comment'] as TString).Value
          else
            _Err.Add('Corrupt File: The "comment" segment should be a string');
        if (_Tree.Exists('info')) then begin
          if _Tree['info'] is TObjectHash then begin
            info := _Tree['info'] as TObjectHash;
            if (info.Exists('name')) then begin
              if info['name'] is TString then
                _Name := (info['name'] as TString).Value
              else
                _Err.Add('Corrupt File: The "info.name" segment should be a string')
            end else begin
              _Err.Add('Corrupt File: Missing "info.name" segment');
            end;
            if (info.Exists('piece length')) then begin
              if info['piece length'] is TInt64 then
                _PieceLength := (info['piece length'] as TInt64).Value
              else
                _Err.Add('Corrupt File: The "info.piece length" segment should be an integer');
            end else begin
              _Err.Add('Corrupt File: Missing "info.piece length" segment');
            end;
            if (info.Exists('pieces')) then begin
              if info['pieces'] is TString then begin
                //fp := (info['pieces'] as TString).Value;
                //pcount := Length(fp);
                //pcount := pcount div 20;
                //SetLength(Pieces,pcount);
                //注释掉
                //for i := 0 to pcount - 1 do begin
                //  Pieces[i] := TTorrentPiece.Create(bin2hex(MidStr(fp,(i * 20) + 1,20)), False);
                //end;
              end else
                _Err.Add('Corrupt File: The "info.pieces" segment should be a string');
            end else begin
              _Err.Add('Corrupt File: Missing "info.pieces" segment');
            end;
            if (info.Exists('length')) then begin // single-file archive
              if info['length'] is TInt64 then begin
                sz := (info['length'] as TInt64).Value;
                _Count := 1;
                md5sum := '';
                if (info.Exists('md5sum')) then
                  if info['md5sum'] is TString then
                    md5sum := (info['md5sum'] as TString).Value
                  else
                    _Err.Add('Corrupt File: The "info.md5sum" segment should be a string');
                md4sum := '';
                if (info.Exists('ed2k')) then
                  if info['ed2k'] is TString then
                    md4sum := (info['ed2k'] as TString).Value
                  else
                    _Err.Add('Corrupt File: The "info.ed2k" segment should be a string');
                sha1sum := '';
                if (info.Exists('sha1')) then
                  if info['sha1'] is TString then
                    sha1sum := (info['sha1'] as TString).Value
                  else
                    _Err.Add('Corrupt File: The "info.sha1" segment should be a string');
                _Files.Add(TTorrentSubFile.Create(_Name, '', sz, Int64(0), md5sum, sha1sum, md4sum));
              end else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -