Bencoding encoding and ASP extract Torrent File Information
1. bencoding Encoding
Bencoding encoding is a data format used by the BT protocol to describe and organize information. It is derived from the Python language. The main data structure is:
Font = <ASCII code 0-9>
Character = <any single-byte Binary Character>
Integer = (character "I") <1-N> (number) (character "e ")
String = <1-N> (number) (character ":") <1-m> (character) * number is the length of the subsequent string
Column table = (character "L") <1-N> (integer | string | list | dictionary) (character "e ")
Code = (character "D") <1-N> (string) (integer | string | list | dictionary) (character "e ")
Torrent file = (dictionary)
As you can see, this data structure divides the information into two parts: the East and the West, which are composed of a tree structure and cannot be read in sequence, but it can be parsed into objects in recursion mode, an object tree with the same logical structure is formed in the memory and then read from the logical location. Because it is a binary structure, it can be read only after all the objects are parsed. It is very costly to use ASP.
2. torrent files
A torrent file is a "single" dictionary file. Its information is stored in a hierarchical structure in dictionary items. dictionary keywords are case sensitive. The main Dictionary data items are:
Announce: (string) seed Server
Announce-list: (list) backup seed Server
Creation-date: (integer) UNIX time
Created by: (string) creator
Info: (dictionary)
Length: (integer) File Size
Name :( string) Top directory name
Piece length: (integer) download structure information.
Pieces: (string) download structure information.
Files: (dictionary) It only exists when multiple files exist.
Length: (integer) File Size
Path: (list) file path. List Directory users layer by layer in a way that is more annoying than JB.
From the logic structure, we can know the read method after parsing.
For example:
Release time = Dictionary ("creation date"). readinteger
A node = Dictionary ("nodes "). list (I ). list (0 ). readstring & ":" & Dictionary ("nodes "). list (I ). list (0 ). readinteger
The path of the 3rd files in the list is
Suppose TMP = Dictionary ("info"). Dictionary ("Files"). List (3). Dictionary ("path ")
Strpath = TMP. List (0). readstring & "/" & TMP. List (1). readstring &"/"...
3. Programming Overview
A. Pay attention to the following points:
The integer in bencoding has no length limit, but it is best to store it in DBL. However, to avoid overflow, you can set a limit, for example, a maximum of 20 integers.
Debugging is troublesome During the parsing process. It is best to actively set the error information. For example, if the Parsing Integer does not have the 'I' header, put an err. raise vbobjecterror, "readinteger ()", "'I 'head missing", instead of waiting for errors in script-level data conversion.
The same is string type. The dictionary keyword is ASC encoding, while some string Dictionary data, such as name. UTF-8 and path. UTF-8, are usually UTF-8 encoded to prevent garbled characters. Therefore, we recommend that you use ASCII to convert dictionary keywords directly. All Dictionary data items use the byte () structure for specific processing.
I have read some asp bencoding parsing methods, using the method of using B (bin, ":") to find the logo, and then directly midb-> cdbl conversion, I personally think this is against the lexical analysis principle and may have unpredictable consequences, such as decimal negative numbers. It is best to use the while midb (bin, I, 1) & CHR (0) <= "9" and...> = "0" Method
Information is stored as the file suffix. Because bencoding parsing cannot filter <%>, saving with the suffix of ASP or other Web applications may lead to website vulnerabilities.
Do You Want To Recursive erase when class_terminate is used? What if setnoting clears the object? I don't think these objects need to be used repeatedly, and they won't expand during the running process. The ASP end system will automatically recycle them, so don't worry about the issue.
B. bencoding is organized in layers and parsed recursively. You can create a class for each data structure. Each time you parse a data structure, you can encapsulate it as an object and return it to the previous layer through recursion, the system will return the backward-ended node. ASP does not support static processes, so the parsing process of each data structure should be placed outside the class.
The main process is as follows:
Class cbencodinginteger
Position of Public lngposition in the file
Public lnglength 'the entire structure includes the length of Child Data
Public dblvalue' Value
End Class
Class cbencodingstring
Position of Public lngposition in the file
Public lnglength 'the entire structure includes the length of Child Data
Public binvalue' Value
End Class
Class cbencodinglist
Public lngposition, lnglength
Private m_aobj, m_intcount
Private sub class_initialize ()
Redim m_aobj (0)
M_intcount = 0
End sub
Public property get count ()
Count = m_intcount
End Property
Public default function item (intindex)
If intindex <0 or intindex> = m_intcount then err. Raise vbobjecterror, "item ()", "index overflow"
Set item = m_aobj (intindex)
End Function
Public Function add (objitem)
Redim preserve m_aobj (m_intcount)
Set m_aobj (m_intcount) = objitem
M_intcount = m_intcount + 1
End Function
End Class
Class cbencodingdictionary
Public lngposition, lnglength
Private m_objdict
Public sub class_initialize ()
Set m_objdict = Createobject ("scripting. Dictionary ")
End sub
Public default function item (strindex)
If m_objdict.exists (strindex) then
Set item = m_objdict.item (strindex)
Else
Err. Raise vbobjecterror, "item ()", "not such key in dictionary ."
End if
End Function
Public Function add (strkey, objitem)
M_objdict.add strkey, objitem
End Function
Public property get count ()
Count = mobjdict. Count
End Property
End Class
'Convert byte () to vbstring
Function pickbinchar (binsrc, lngpos)
Pickbinchar = midb (binsrc, lngpos, 1) & chrb (0)
End Function
'Read Integers
'[In] binsrc
'[In, out] lngcurpos
'[In] lngmaxpos
'[Out] objret
Function readinteger (binsrc, lngcurpos, objret)
Dim I, j
Dim chrbuf
Dim strnum, dblnum
Dim lngbakpos
Lngbakpos = lngcurpos 'directly change the resolution position. The advantage of lngcurpos is that the err occurs and you can know the wrong character location.
Set objret = nothing
If pickbinchar (binsrc, lngcurpos) <> "I" then err. Raise vbobjecterror, "readinteger ()", "'I 'head missing ."
Lngcurpos = lngcurpos + 1
I = 0
Strnum = ""
Chrbuf = pickbinchar (binsrc, lngcurpos)
Do While chrbuf <= "9" and chrbuf> = "0"
Strnum = strnum & chrbuf
Lngcurpos = lngcurpos + 1
Chrbuf = pickbinchar (binsrc, lngcurpos)
I = I + 1
If I> max_int_len then err. Raise vbobjecterror, "readinteger ()", "integer overflow ."
Loop
If chrbuf <> "E" then err. Raise vbobjecterror, "readinteger ()", "'E' rare missing ."
If strnum = "" Then err. Raise vbobjecterror, "readinteger ()", "EMPTY between 'I' and 'E '."
Set objret = new cbencodinginteger
Objret. lngposition = lngbakpos
Objret. lnglength = lngcurpos-lngbakpos
Objret. dblvalue = cdbl (strnum)
Lngcurpos = lngcurpos + 1
End Function
'Readstring, readlist, and readdictionary will not be pasted. This is basically the same, that is, the pointer of the positions of dictionary and list should be careful.
'Test
Function loadfromfile (strpath, BIN) 'can also be changed to request. binaryread, but the multiform data format must be processed first.
Dim objadostm
Set objadostm = Createobject ("ADODB. Stream ")
Objadostm. type = 1
Objadostm. mode = 3
Objadostm. Open
Objadostm. loadfromfile strpath
Objadostm. Position = 0
Bin = objadostm. Read (-1)
Objadostm. Close
Set objadostm = nothing
End Function
Debug: Sub debug ()
Dim Bin
Loadfromfile "test. torrent", Bin
Dim objtmp
'Parse the root node to recursively parse all files
Readdictionary bin, 1, 0, objtmp
'Display the IP address location of 0th nodes
Msgbox byte2str (objtmp. Item ("nodes"). Item (0). Item (0). binvalue)
End sub
================
Sorry, I finally got it done for a few days. It was because of poor expression ability that I could not write the experience, so I had to put something dry up.