import re import logging import binascii class bencoding(): def __init__(self): self.decimal_match = re.compile('\d') self.data = b'' self.dict = {} def get_dict(self, key): if key not in self.dict: return '' start = self.dict[key][0] end = self.dict[key][1] return self.data[start:end] def get_item(self, chunks): item = chunks[self.i] self.i += 1 if not type(item) == str: item = bytes([item]) try: item = item.decode('utf-8') except: item = '\\x{}'.format(binascii.hexlify(item)) return item def decoding_byte_string(self, chunks, item): # logging.debug('decoding string') num = '' while self.decimal_match.search(item): num += item item = self.get_item(chunks) line = '' for i in range(int(num)): line += self.get_item(chunks) return line def decoding_integer(self, chunks): # logging.debug('decoding integer') item = self.get_item(chunks) num = '' while item != 'e': num += item item = self.get_item(chunks) return int(num) def decoding_list(self, chunks): # logging.debug('decoding list') item = self.get_item(chunks) list = [] while item != 'e': self.i -= 1 list.append(self._dechunk(chunks)) item = self.get_item(chunks) return list def decoding_dictionnary(self, chunks): # logging.debug('decoding dictionnary') item = self.get_item(chunks) hash = {} while item != 'e': self.i -= 1 key = self._dechunk(chunks) start = self.i hash[key] = self._dechunk(chunks) end = self.i self.dict[key] = (start, end) item = self.get_item(chunks) return hash def _dechunk(self, chunks): item = self.get_item(chunks) if item == 'd': return self.decoding_dictionnary(chunks) elif item == 'l': return self.decoding_list(chunks) elif item == 'i': return self.decoding_integer(chunks) elif self.decimal_match.search(item): return self.decoding_byte_string(chunks, item) raise "Invalid input!" def bdecode(self, data): self.data = data chunks = list(self.data) self.i = 0 root = self._dechunk(chunks) return root