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

📄 bcode.pas

📁 分析torrent的东西是拿别人的
💻 PAS
字号:
unit BCode;

interface

uses
  SysUtils, Classes, Contnrs, Hashes;

type
  TBEType = (beInt64, beString, beList, beDicionary);
  TInt64 = class(TOBject)
  private
    _Value: Int64;
  public
    property Value: Int64 read _Value write _Value;
    constructor Create(Value: Int64);
  end;
  TString = class(TObject)
  private
    _Value: String;
  public
    property Value: String read _Value write _Value;
    constructor Create(Value: String);
  end;
  function bencodeStream(Root: TObject; Stream: TStream): Boolean;
  function bdecodeStream(s: TStream): TObject;
  function bdecodeInt64(s: TStream): TInt64;
  function bdecodeString(s: TStream; i: Integer = 0): TString;
  function bdecodeHash(s: TStream): TObjectHash;
  function bdecodeList(s: TStream): TObjectList;

implementation

function bencodeInt64(Root: TInt64; Stream: TStream): Boolean;
var
  s: String;
  l: Integer;
begin
  s := 'i' + IntToStr(Root.Value) + 'e';
  l := Length(s);
  if (l = Stream.Write(PChar(s)^,l)) then Result := True else Result := False;
end;

function bencodeString(Root: TString; Stream: TStream): Boolean;
var
  s: String;
  l: Integer;
begin
  s := IntToStr(Length(Root.Value)) + ':' + Root.Value;
  l := Length(s);
  if (l = Stream.Write(PChar(s)^,l)) then Result := True else Result := False;
end;

function bencodeList(Root: TObjectList; Stream: TStream): Boolean;
var
  i: Integer;
  s: String;
begin
  s := 'l';
  if (Stream.Write(PChar(s)^,1) = 1) then begin
    for i := 0 to Root.Count - 1 do bencodeStream(Root[i],Stream);
    s := 'e';
    if (Stream.Write(PChar(s)^,1) = 1) then Result := True else Result := False;
  end else Result := False;
end;

function bencodeStringList(Root: TStringList; Stream: TStream): Boolean;
var
  i: Integer;
  s: String;
begin
  s := 'l';
  if (Stream.Write(PChar(s)^,1) = 1) then begin
    for i := 0 to Root.Count - 1 do bencodeString(TString.Create(Root[i]),Stream);
    s := 'e';
    if (Stream.Write(PChar(s)^,1) = 1) then Result := True else Result := False;
  end else Result := False;
end;

function bencodeDictionary(Root: TObjectHash; Stream: TStream): Boolean;
var
  sl: TStringList;
  i: Integer;
  s: TString;
  t: String;
begin
  t := 'd';
  if (Stream.Write(PChar(t)^,1) = 1) then begin
    sl := TStringList.Create();
    Root.Restart();
    while (Root.Next) do sl.Add(Root.CurrentKey);
    sl.Sort(); // official spec requires dictionaries to be sorted by key
    s := TString.Create('');
    for i := 0 to sl.Count - 1 do begin
      s.Value := sl[i];
      if not bencodeString(s,Stream) then begin
        Result := False;
        FreeAndNil(sl);
        Exit;
      end;
      if not bencodeStream(Root[sl[i]],Stream) then begin
        Result := False;
        FreeAndNil(sl);
        Exit;
      end;
    end;
    FreeAndNil(s);
    t := 'e';
    if (Stream.Write(PChar(t)^,1) = 1) then Result := True else Result := False;
    FreeAndNil(sl);
  end else Result := False;
end;

function bencodeStream(Root: TObject; Stream: TStream): Boolean;
begin
  if (Root is TInt64) then Result := bencodeInt64(Root as TInt64,Stream)
  else if (Root is TString) then Result := bencodeString(Root as TString,Stream)
  else if (Root is TStringList) then Result := bencodeStringList(Root as TStringList,Stream)
  else if (Root is TObjectList) then Result := bencodeList(Root as TObjectList,Stream)
  else if (Root is TObjectHash) then Result := bencodeDictionary(Root as TObjectHash,Stream)
  else Result := False;
end;

function bdecodeStream(s: TStream): TObject;
var
  r: TObject;
  c: Char;
  n: Integer;
begin
  n := s.Read(c, 1);
  if(n > 0) then begin
    case c of
    'd' : r:= bdecodeHash(s);
    'l' : r:= bdecodeList(s);
    'i' : r:= bdecodeInt64(s);
    '0'..'9' : r:= bdecodeString(s,StrToInt(c));
    else r := nil;
    end;
  end else begin
    r := nil;
  end;
  bdecodeStream := r;
end;

function bdecodeHash(s: TStream): TObjectHash;
var
  r: TObjectHash;
  o: TObject;
  n, st: Integer;
  c: Char;
  l: TInt64;
  k: TString;
begin
  r := TObjectHash.Create();
  n := s.Read(c, 1);
  while((n > 0) and (c <> 'e')) do begin
    n := StrToInt(c);
    k := bdecodeString(s, n);
    if(k <> nil) then begin
      st := s.Position;
      o := bdecodeStream(s);
      if((o <> nil) and (k.Value <> '')) then r[k.Value] := o;
      if(k.Value = 'info') then begin
        l := TInt64.Create(st);
        r['_info_start'] := l;
        l := TInt64.Create(s.Position - st);
        r['_info_length'] := l;
      end;
    end;
    n := s.Read(c, 1);
  end;
  bdecodeHash := r;
end;

function bdecodeList(s: TStream): TObjectList;
var
  r: TObjectList;
  o: TObject;
  n: Integer;
  c: Char;
begin
  r := TObjectList.Create();
  n := s.Read(c, 1);
  while((n > 0) and (c <> 'e')) do begin
    s.Seek(-1, soFromCurrent);
    o := bdecodeStream(s);
    if(o <> nil) then r.Add(o);
    n := s.Read(c, 1);
  end;
  bdecodeList := r;
end;

function bdecodeString(s: TStream; i: Integer = 0): TString;
var
  r: TString;
  t: String;
  c: Char;
  n: Integer;
begin
  c := '0';
  n := s.Read(c, 1);
  while((n > 0) and (c >= '0') and (c <= '9')) do begin
    i := (i * 10) + StrToInt(c);
    n := s.Read(c, 1);
  end;
  SetLength(t, i);
  s.Read(PChar(t)^, i);
  r := TString.Create(t);
  bdecodeString := r;
end;

function bdecodeInt64(s: TStream): TInt64;
var
  r: TInt64;
  i: Int64;
  c: Char;
  n: Integer;
  neg: Boolean;
begin
  i := 0;
  c := '0';
  neg := False;
  repeat
    if (c = '-') then neg:= true else i := (i * 10) + StrToInt(c);
    n := s.Read(c, 1);
  until not ((n > 0) and (((c >= '0') and (c <= '9'))) or (c = '-'));
  if neg then i := -i;
  r := TInt64.Create(i);
  bdecodeInt64 := r;
end;

{ TInt64 }

constructor TInt64.Create(Value: Int64);
begin
  _Value := Value;
  inherited Create();
end;

{ TString }

constructor TString.Create(Value: String);
begin
  _Value := Value;
  inherited Create();
end;

end.

⌨️ 快捷键说明

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