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