summaryrefslogtreecommitdiff
path: root/src/torrent.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/torrent.py')
-rw-r--r--src/torrent.py42
1 files changed, 22 insertions, 20 deletions
diff --git a/src/torrent.py b/src/torrent.py
index bdf83ce..cb4b5e3 100644
--- a/src/torrent.py
+++ b/src/torrent.py
@@ -11,7 +11,7 @@ class TorrentParser(abstract.AbstractParser):
11 d = _BencodeHandler().bdecode(f.read()) 11 d = _BencodeHandler().bdecode(f.read())
12 if d is None: 12 if d is None:
13 return {'Unknown meta': 'Unable to parse torrent file "%s".' % self.filename} 13 return {'Unknown meta': 'Unable to parse torrent file "%s".' % self.filename}
14 for k,v in d.items(): 14 for k, v in d.items():
15 if k not in self.whitelist: 15 if k not in self.whitelist:
16 metadata[k.decode('utf-8')] = v 16 metadata[k.decode('utf-8')] = v
17 return metadata 17 return metadata
@@ -23,7 +23,7 @@ class TorrentParser(abstract.AbstractParser):
23 d = _BencodeHandler().bdecode(f.read()) 23 d = _BencodeHandler().bdecode(f.read())
24 if d is None: 24 if d is None:
25 return False 25 return False
26 for k,v in d.items(): 26 for k, v in d.items():
27 if k in self.whitelist: 27 if k in self.whitelist:
28 cleaned[k] = v 28 cleaned[k] = v
29 with open(self.output_filename, 'wb') as f: 29 with open(self.output_filename, 'wb') as f:
@@ -39,21 +39,22 @@ class _BencodeHandler(object):
39 """ 39 """
40 def __init__(self): 40 def __init__(self):
41 self.__decode_func = { 41 self.__decode_func = {
42 ord('d'): self.__decode_dict, 42 ord('d'): self.__decode_dict,
43 ord('i'): self.__decode_int, 43 ord('i'): self.__decode_int,
44 ord('l'): self.__decode_list, 44 ord('l'): self.__decode_list,
45 } 45 }
46 for i in range(0, 10): 46 for i in range(0, 10):
47 self.__decode_func[ord(str(i))] = self.__decode_string 47 self.__decode_func[ord(str(i))] = self.__decode_string
48 48
49 self.__encode_func = { 49 self.__encode_func = {
50 bytes: self.__encode_string, 50 bytes: self.__encode_string,
51 dict: self.__encode_dict, 51 dict: self.__encode_dict,
52 int: self.__encode_int, 52 int: self.__encode_int,
53 list: self.__encode_list, 53 list: self.__encode_list,
54 } 54 }
55 55
56 def __decode_int(self, s:str) -> (int, str): 56 @staticmethod
57 def __decode_int(s: str) -> (int, str):
57 s = s[1:] 58 s = s[1:]
58 next_idx = s.index(b'e') 59 next_idx = s.index(b'e')
59 if s.startswith(b'-0'): 60 if s.startswith(b'-0'):
@@ -62,7 +63,8 @@ class _BencodeHandler(object):
62 raise ValueError # no leading zero except for zero itself 63 raise ValueError # no leading zero except for zero itself
63 return int(s[:next_idx]), s[next_idx+1:] 64 return int(s[:next_idx]), s[next_idx+1:]
64 65
65 def __decode_string(self, s:str) -> (str, str): 66 @staticmethod
67 def __decode_string(s: str) -> (str, str):
66 sep = s.index(b':') 68 sep = s.index(b':')
67 str_len = int(s[:sep]) 69 str_len = int(s[:sep])
68 if str_len < 0: 70 if str_len < 0:
@@ -72,7 +74,7 @@ class _BencodeHandler(object):
72 s = s[1:] 74 s = s[1:]
73 return s[sep:sep+str_len], s[sep+str_len:] 75 return s[sep:sep+str_len], s[sep+str_len:]
74 76
75 def __decode_list(self, s:str) -> (list, str): 77 def __decode_list(self, s: str) -> (list, str):
76 r = list() 78 r = list()
77 s = s[1:] # skip leading `l` 79 s = s[1:] # skip leading `l`
78 while s[0] != ord('e'): 80 while s[0] != ord('e'):
@@ -80,7 +82,7 @@ class _BencodeHandler(object):
80 r.append(v) 82 r.append(v)
81 return r, s[1:] 83 return r, s[1:]
82 84
83 def __decode_dict(self, s:str) -> (dict, str): 85 def __decode_dict(self, s: str) -> (dict, str):
84 r = dict() 86 r = dict()
85 s = s[1:] # skip leading `d` 87 s = s[1:] # skip leading `d`
86 while s[0] != ord(b'e'): 88 while s[0] != ord(b'e'):
@@ -89,30 +91,30 @@ class _BencodeHandler(object):
89 return r, s[1:] 91 return r, s[1:]
90 92
91 @staticmethod 93 @staticmethod
92 def __encode_int(x:str) -> bytes: 94 def __encode_int(x: str) -> bytes:
93 return b'i' + bytes(str(x), 'utf-8') + b'e' 95 return b'i' + bytes(str(x), 'utf-8') + b'e'
94 96
95 @staticmethod 97 @staticmethod
96 def __encode_string(x:str) -> bytes: 98 def __encode_string(x: str) -> bytes:
97 return bytes((str(len(x))), 'utf-8') + b':' + x 99 return bytes((str(len(x))), 'utf-8') + b':' + x
98 100
99 def __encode_list(self, x:str) -> bytes: 101 def __encode_list(self, x: str) -> bytes:
100 ret = b'' 102 ret = b''
101 for i in x: 103 for i in x:
102 ret += self.__encode_func[type(i)](i) 104 ret += self.__encode_func[type(i)](i)
103 return b'l' + ret + b'e' 105 return b'l' + ret + b'e'
104 106
105 def __encode_dict(self, x:str) -> bytes: 107 def __encode_dict(self, x: str) -> bytes:
106 ret = b'' 108 ret = b''
107 for k, v in sorted(x.items()): 109 for k, v in sorted(x.items()):
108 ret += self.__encode_func[type(k)](k) 110 ret += self.__encode_func[type(k)](k)
109 ret += self.__encode_func[type(v)](v) 111 ret += self.__encode_func[type(v)](v)
110 return b'd' + ret + b'e' 112 return b'd' + ret + b'e'
111 113
112 def bencode(self, s:str) -> bytes: 114 def bencode(self, s: str) -> bytes:
113 return self.__encode_func[type(s)](s) 115 return self.__encode_func[type(s)](s)
114 116
115 def bdecode(self, s:str): 117 def bdecode(self, s: str):
116 try: 118 try:
117 r, l = self.__decode_func[s[0]](s) 119 r, l = self.__decode_func[s[0]](s)
118 except (IndexError, KeyError, ValueError) as e: 120 except (IndexError, KeyError, ValueError) as e: