Add bencode.py, required by torrent2magnet.py.
This commit is contained in:
parent
59eff6fe6c
commit
d92e1ba840
1 changed files with 109 additions and 0 deletions
109
bencode.py
Executable file
109
bencode.py
Executable file
|
|
@ -0,0 +1,109 @@
|
|||
#! /usr/bin/python3
|
||||
|
||||
import collections
|
||||
|
||||
def bencode(elem):
|
||||
if type(elem) == str:
|
||||
elem = str.encode(elem)
|
||||
|
||||
if type(elem) == bytes:
|
||||
result = str.encode(str(len(elem)))+b":"+elem
|
||||
elif type(elem) == int:
|
||||
result = str.encode("i"+str(elem)+"e")
|
||||
elif type(elem) == list:
|
||||
result = b"l"
|
||||
for item in elem:
|
||||
result += bencode(item)
|
||||
result += b"e"
|
||||
elif type(elem) in [dict, collections.OrderedDict]:
|
||||
result = b"d"
|
||||
for key in elem:
|
||||
result += bencode(key)+bencode(elem[key])
|
||||
result += b"e"
|
||||
return result
|
||||
|
||||
def bdecode(bytestr, recursiveCall=False):
|
||||
startingChars = dict({
|
||||
b"i" : int,
|
||||
b":" : str,
|
||||
b"l" : list,
|
||||
b"d" : dict
|
||||
})
|
||||
digits = [b"0", b"1", b"2", b"3", b"4", b"5", b"6", b"7", b"8", b"9"]
|
||||
|
||||
started = ended = False
|
||||
curtype = None
|
||||
|
||||
numstring = b"" # for str, int
|
||||
result = None # for list, dict
|
||||
key = None # for dict
|
||||
|
||||
while len(bytestr) > 0:
|
||||
# reading and popping from the beginning
|
||||
char = bytestr[:1]
|
||||
|
||||
if not started:
|
||||
|
||||
bytestr = bytestr[1:]
|
||||
|
||||
if char in digits:
|
||||
numstring += char
|
||||
|
||||
elif char in startingChars:
|
||||
|
||||
started = True
|
||||
curtype = startingChars[char]
|
||||
|
||||
if curtype == str:
|
||||
size = int(bytes.decode(numstring))
|
||||
# try to decode strings
|
||||
try:
|
||||
result = bytes.decode(bytestr[:size])
|
||||
except UnicodeDecodeError:
|
||||
result = bytestr[:size]
|
||||
bytestr = bytestr[size:]
|
||||
ended = True
|
||||
break
|
||||
|
||||
elif curtype == list:
|
||||
result = []
|
||||
|
||||
elif curtype == dict:
|
||||
result = collections.OrderedDict()
|
||||
else:
|
||||
raise ValueError("Expected starting char, got ‘"+bytes.decode(char)+"’")
|
||||
|
||||
else: # if started
|
||||
|
||||
if not char == b"e":
|
||||
|
||||
if curtype == int:
|
||||
bytestr = bytestr[1:]
|
||||
numstring += char
|
||||
|
||||
elif curtype == list:
|
||||
item, bytestr = bdecode(bytestr, recursiveCall=True)
|
||||
result.append(item)
|
||||
|
||||
elif curtype == dict:
|
||||
|
||||
if key == None:
|
||||
key, bytestr = bdecode(bytestr, recursiveCall=True)
|
||||
|
||||
else:
|
||||
result[key], bytestr = bdecode(bytestr, recursiveCall=True)
|
||||
key = None
|
||||
|
||||
else: # ending: char == b"e"
|
||||
bytestr = bytestr[1:]
|
||||
if curtype == int:
|
||||
result = int(bytes.decode(numstring))
|
||||
ended = True
|
||||
break
|
||||
if ended:
|
||||
if recursiveCall:
|
||||
return result, bytestr
|
||||
else:
|
||||
return result
|
||||
else:
|
||||
raise ValueError("String ended unexpectedly")
|
||||
Loading…
Add table
Add a link
Reference in a new issue