random-commands/bencode.py

109 lines
3 KiB
Python
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /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")