# Written by Petru paler
# See license.txt for license information
"""
Code Reading diary: Author:
Pen: zfive5
Note: The file is a write function that mainly performs operations on the BT seed file. You can
Use make to create a. torrent file and check the content. There are two files in my E:/1/directory,
Dir:
.
..
10 1.txt
11 2.txt
The content of the. torrent file made by using maketorrent is as follows (the linefeed and space comment are added because it is too long ):
D
8: announce
30: http: // FIG: 6969/announce
13: creation date
I00003944351e
4: info
D
5: Files
L
D
6: Length
I10e
4: Path
L
5:1. txt
E
E
D
6: Length
I11e
4: Path
L
5: 2. txt
E
E
E
4: Name
1:1
12: piece length
I32768e
6: Pieces
20: Why ^? G? Comment 'maximum latency (D4 44 5E E4 de 67 D1 18 03 D3 55 27 D7 EE 8A A2 af 71 EB D8) (this is the 20-bit Sha message digest of one BT file block)
E
3: nfo
D
E
E
The write is directly like this:
Announce: http: // 127.0.0.1: 6969/announce
Creation date: 1093944351 (seconds)
Info
Files
{
Length = 10 (bytes)
Pathpattern 1.txt
,
Length = 11 (bytes)
Pathpattern 2.txt
}
Name = 1
Piece length = 32768 (size of each file)
Pieces = D4 44 5E E4 de 67 D1 18 03 D3 55 27 D7 EE 8A A2 af 71 EB D8
Nfo = NULL (null)
There are several types of data structures to describe:
Integer: IE For example: i00003944351e
String: N: Example: 30: http: // 127.0.0.1: 6969/announce
List: L <content> E for example: L5: 1.txt E
Dictionary: d <content> E example: D6: lengthi10e4: pathl5: 1.txt eed6: lengthi11e4: pathl5: 2.txt eee
"""
# BT source code is better than everything else
Import re
From cstringio import stringio
Int_filter = Re. Compile ('(0 | -? [1-9] [0-9] *) e ')
# Decode integer Functions
Def decode_int (x, f ):
M = int_filter.match (x, F)
If M is none:
Raise valueerror
Return (long (M. Group (1), M. End ())
String_filter = Re. Compile ('(0 | [1-9] [0-9] *):')
# Decodes string functions
Def decode_string (x, f ):
M = string_filter.match (x, F)
If M is none:
Raise valueerror
L = int (M. Group (1 ))
S = M. End ()
Return (X [s: S + L], S + l)
# Decoding list Functions
Def decode_list (x, f ):
R = []
While X [f]! = 'E ':
V, F = bdecode_rec (x, F)
R. append (V)
Return (r, f + 1)
# Decode dictionary Functions
Def decode_dict (x, f ):
R = {}
Lastkey = none
While X [f]! = 'E ':
K, F = decode_string (x, F)
If lastkey is not none and lastkey> = K:
Raise valueerror
Lastkey = K
V, F = bdecode_rec (x, F)
R [k] = V
Return (r, f + 1)
# Internal decoding Functions
Def bdecode_rec (x, f ):
T = x [F]
If t = 'I ':
Return decode_int (x, F + 1)
Elif T = 'l ':
Return decode_list (x, F + 1)
Elif T = 'D ':
Return decode_dict (x, F + 1)
Else:
Return decode_string (x, F)
# External decoding Functions
Def bdecode (x ):
Try:
R, L = bdecode_rec (x, 0)
Failed t indexerror:
Raise valueerror
If l! = Len (x ):
Raise valueerror
Return R
# Test the decoding function
Def test_bdecode ():
Try:
Bdecode ('0: 0 :')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('ie ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('i341foo382e ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('i4e ') = 4l
Assert bdecode ('0e') = 0l
Assert bdecode ('i123456789e ') = 123456789l
Assert bdecode ('I-10e') =-10l
Try:
Bdecode ('I-0e ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('i123 ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('i6easd ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('35208734823ljdahflajhdf ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('2: abfdjslhsecret ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('0: ') =''
Assert bdecode ('3: abc') = 'abc'
Assert bdecode ('10: 1234567890 ') = '20140901'
Try:
Bdecode ('02: xy ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('l ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('le') = []
Try:
Bdecode ('leanfdldjfh ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('l0: 0: 0: e') = ['','', '']
Try:
Bdecode ('relwjhrlewjh ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('li1ei2ei3ee ') = [1, 2, 3]
Assert bdecode ('l3: asd2: xye') = ['asd ', 'xy']
Assert bdecode ('ll5: alice3: bobeli2ei3eee ') = [['Alice', 'bob'], [2, 3]
Try:
Bdecode ('D ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('foobar ')
Assert 0
Failed t valueerror:
Pass
Assert bdecode ('de') == {}
Assert bdecode ('d3: agei25e4: eyes4: bluee ') =={ 'age': 25, 'ayes': 'blue '}
Assert bdecode ('d8: spam.mp3 D6: author5: alice6: lengthi100000eee ') = 'samples': {'author': 'Alice', 'length': 100000 }}
Try:
Bdecode ('d3: fooe ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('di1e0: e ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('d1: B0: 1: A0: e ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('d1: A0: 1: A0: e ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('i03e ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('l01: AE ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('2014: x ')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('l0 :')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('d0: 0 :')
Assert 0
Failed t valueerror:
Pass
Try:
Bdecode ('d0 :')
Assert 0
Failed t valueerror:
Pass
# Internal encoding Functions
Def bencode_rec (X, B ):
T = type (X)
If t in (INT, long, bool ):
B. Write ('I % de' % x)
Elif T is str:
B. Write ('% d: % s' % (LEN (x), x ))
Elif t in (list, tuple ):
B. Write ('l ')
For E in X:
Bencode_rec (E, B)
B. Write ('E ')
Elif T is dict:
B. Write ('D ')
Keylist = x. Keys ()
Keylist. Sort ()
For k in keylist:
Assert type (k) is str
Bencode_rec (K, B)
Bencode_rec (X [K], B)
B. Write ('E ')
Else:
Assert 0
# External Encoding Functions
Def bencode (x ):
B = stringio ()
Bencode_rec (X, B)
Return B. getvalue ()
# Test the encoding function
Def test_bencode ():
Assert bencode (4) = 'i4e'
Assert bencode (0) = 'i0e'
Assert bencode (-10) = 'I-10e'
Assert bencode (12345678901234567890l) = 'i12345678901234567890e'
Assert bencode ('') = '0 :'
Assert bencode ('abc') = '3: abc'
Assert bencode ('20140901') = '10: 123'
Assert bencode ([]) = 'le'
Assert bencode ([1, 2, 3]) = 'li1ei2ei3ee'
Assert bencode ([['Alice ', 'bob'], [2, 3]) = 'll5: alice3: bobeli2ei3eee'
Assert bencode ({}) = 'de'
Assert bencode ({'age': 25, 'ayes': 'blue'}) = 'd3: agei25e4: eyes4: bluee'
Assert bencode('spamath': {'author': 'Alice ', 'length': 100000}) = 'd8: spamd6 D6: author5: alice6: lengthi100000eee'
Try:
Bencode ({1: 'foo '})
Assert 0
Failed t assertionerror:
Pass