我想使用Delphi获取* .torrent文件的info_hash。 试过this BEncode decorder。 但它在解码时会给出疯狂的角色。 Delphi中的任何其他工作BEncode解码器?或者我做错了什么? 这是我的代码:
procedure TForm.Button1Click(Sender: TObject);
var
be: TBEncoded;
fs: tfilestream;
op: string;
begin
fs := tfilestream.Create('xx.torrent', fmOpenReadWrite);
be := TBEncoded.Create(fs);
be.Encode(be.ListData.Items[0].Data, op);
showmessage(op);
be.Encode(be.ListData.FindElement('info'), op);
showmessage(op);
end;
答案 0 :(得分:3)
我刚试过这个解码器,它正常工作。您不需要使用Encode程序,其目的(从名称上看)是将元素编码回BEncode。该测试程序在TMemo中显示了torrent信息:
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(对象)而不是&#34;对象作为TBEncoded&#34;, 在object.free之前检查nil对象,这是重言式,但一般来说它都有效。
更新1 简单的代码,可以使用其中一个字段,&#39; pieces&#39;并以十六进制显示。
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;
如您所见,我们通过char访问StringData char并将其转换为Byte。我只是用十六进制显示它,当然你可以使用这些字节进行进一步处理。
注意:您将获得十六进制值的LOADS,这不是MD5哈希或WHOLE torrent的任何其他哈希,它是每个数据的哈希函数序列,通常是1或2的块MB。
更新2
这个单元可以在较新版本的Delphi中使用,你需要做的就是从&#39; string&#39;中替换其中的所有字符串变量。到&#39; ANSIstring&#39;,只需使用Ctrl + R - &#39;:string&#39;替换为&#39;:ANSIstring&#39;。
更新3
好的,最后我明白了。这是计算info_hash并以十六进制显示的过程,这需要更新版本的Delphi。另外,添加IdGlobal和IdHashSHA以使用&#39;部分。
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
您必须将所有字符串替换为BENcode.pas中的ANSIstring,如更新2中所述。享受!