Я только что попробовал этот декодер, он работает нормально. Вам не нужно было использовать процедуру Encode, ее цель (как видно из названия) — кодировать элементы обратно в BEncode. Это тестовая программа, которая показывает информацию о торрентах в TMemo:
procedure ShowDecoded(be: TBEncoded; indent: string='');
var i: Integer;
begin
with form1.Memo1.Lines do
case be.Format of
befstring: Add(indent+be.StringData);
befInteger: Add(indent+IntToStr(be.IntegerData));
befList: begin
Add(indent+'list');
for i:=0 to be.ListData.Count-1 do
ShowDecoded(be.ListData.Items[i].Data as TBEncoded,indent+' ');
Add(indent+'end of list');
end;
befDictionary: begin
Add(indent+'dict');
for i:=0 to be.ListData.Count-1 do begin
Add(indent+' '+be.ListData.Items[i].Header+'=');
ShowDecoded(be.listData.Items[i].Data as TBEncoded,indent+' ');
end;
Add(indent+'end of dict');
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var fs: TFileStream;
be: TBEncoded;
i: Integer;
begin
if OpenDialog1.Execute then begin
fs:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
try
be:=TBEncoded.Create(fs);
ShowDecoded(be);
be.Free;
finally
fs.Free;
end;
end;
end;
Это результат теста:
dict
created by=
uTorrent/3.4.3
creation date=
1439626950
encoding=
UTF-8
info=
dict
length=
1345178
name=
Алябьев А., Лист Ф. - Соловей - 1987.pdf
piece length=
16384
pieces=
)Lo.Î ’üXí»IÙçsáôt£ˆb›hŒˆ*Ð誺š¤/N7’`0âÓ†nË5&T€:V•Ìפ¯9¤Ý:¦J©Ï|Œ•A¥,¼R¯þ:H:X&…¢<¸º"2îV-vÀÖˆD†¨¬ß‰ƒ,ümjà?éÛoe¬r£{¨¾]•4òØžhô†›¼AØBeJÕÌ4³·Œ‹¶ËAG— f„\pa
end of dict
end of dict
Я бы внес некоторые изменения в модуль BEncode, там беспорядок: создание пустых исключений, небезопасное приведение: TBEncoded(object) вместо «object as TBEncoded», проверка нулевого объекта перед object.free, что является тавтологией, но в вообще работает.
Обновление 1. Простой код, который берет одно из полей, "кусочки" и отображает его в шестнадцатеричном формате.
procedure FindAndShowHash(be: TBEncoded);
var i: Integer;
s: string;
infoChunk, piecesChunk: TBencoded;
begin
s:='';
infoChunk:=be.ListData.FindElement('info') as TBencoded;
piecesChunk:=infoChunk.ListData.FindElement('pieces') as TBencoded;
for i:=1 to Length(piecesChunk.StringData) do
s:=s+IntToHex(Byte(piecesChunk.StringData[i]),2);
form1.Memo1.Lines.Add('Hash function:');
form1.Memo1.Lines.Add(s);
end;
Как видите, мы обращаемся к StringData char по char и приводим его к типу Byte. Я просто показал его в шестнадцатеричном формате, конечно, вы можете использовать эти байты для дальнейшей обработки.
Остерегайтесь: вы получите МНОГО шестнадцатеричных значений, это не хэш MD5 или любой другой хэш ВСЕГО торрента, это последовательность хэш-функций для каждого фрагмента данных, обычно блоков по 1 или 2 МБ.
ОБНОВЛЕНИЕ 2
Этот модуль можно использовать в более новых версиях Delphi, все, что вам нужно сделать, это заменить в нем ВСЕ строковые переменные с 'string' на 'ANSIstring', просто с помощью Ctrl+R - ':string' заменить на ':ANSIstring'.
ОБНОВЛЕНИЕ 3
Хорошо, наконец я понял. Вот процедура, которая вычисляет info_hash и показывает его в шестнадцатеричном формате, для этого требуется более новая версия Delphi. Кроме того, добавьте IdGlobal и IdHashSHA в раздел «использует».
procedure makeInfoHash(be: TBEncoded);
var SHA1: TIdHashSHA1;
s: string;
infoChunk: TBencoded;
infoEncoded: ANSIString;
bytes: TIdBytes;
begin
infoChunk:=be.ListData.FindElement('info') as TBencoded;
TBencoded.Encode(infoChunk,infoEncoded);
bytes:=RawToBytes(infoEncoded[1],Length(infoEncoded));
SHA1:=TIdHashSHA1.Create;
try
s:=SHA1.HashBytesAsHex(bytes);
finally
SHA1.Free;
end;
Form1.Memo1.Lines.Add(s);
end;
Он дает правильный info_hash, такой же, который отображается в uTorrent, например:
7D0487D3D99D9C27A7C09CDCBB2F2A8034D4F9BF
Вы должны заменить все строки на ANSIString в BENcode.pas, как сказано в обновлении 2. Наслаждайтесь!
person
Yuriy Afanasenkov
schedule
08.12.2015