summaryrefslogtreecommitdiff
path: root/MAT/bencode/bencode.py
diff options
context:
space:
mode:
authorjvoisin2012-12-08 02:02:25 +0100
committerjvoisin2012-12-13 14:24:01 +0100
commitcbf8a2a65928694202e19b6bcf56ec84bcbf613c (patch)
treee106475b0d5c003505336b5ae6416e4508bb768b /MAT/bencode/bencode.py
parent67d5c1fa6b9ab6e1e7328ee57b15d8e46526d72a (diff)
Reorganize source tree and files installation location, cleanup setup.py (Closes: #689409)
Diffstat (limited to 'MAT/bencode/bencode.py')
-rw-r--r--MAT/bencode/bencode.py152
1 files changed, 152 insertions, 0 deletions
diff --git a/MAT/bencode/bencode.py b/MAT/bencode/bencode.py
new file mode 100644
index 0000000..739ffe5
--- /dev/null
+++ b/MAT/bencode/bencode.py
@@ -0,0 +1,152 @@
1# Copyright 2007 by Petru Paler
2# Copyright 2011 by Julien (jvoisin) Voisin
3#
4# Permission is hereby granted, free of charge, to any person obtaining a copy
5# of this software and associated documentation files (the "Software"), to deal
6# in the Software without restriction, including without limitation the rights
7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8# copies of the Software, and to permit persons to whom the Software is
9# furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be included in
12# all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19# FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22#
23
24'''
25 A quick (and also nice) lib to bencode/bdecode torrent files
26'''
27
28
29import types
30
31
32class BTFailure(Exception):
33 '''Custom Exception'''
34 pass
35
36
37class Bencached(object):
38 '''Custom type : cached string'''
39 __slots__ = ['bencoded']
40
41 def __init__(self, string):
42 self.bencoded = string
43
44
45def decode_int(x, f):
46 '''decode an int'''
47 f += 1
48 newf = x.index('e', f)
49 n = int(x[f:newf])
50 if x[f] == '-':
51 if x[f + 1] == '0':
52 raise ValueError
53 elif x[f] == '0' and newf != f + 1:
54 raise ValueError
55 return (n, newf + 1)
56
57
58def decode_string(x, f):
59 '''decode a string'''
60 colon = x.index(':', f)
61 n = int(x[f:colon])
62 if x[f] == '0' and colon != f + 1:
63 raise ValueError
64 colon += 1
65 return (x[colon:colon + n], colon + n)
66
67
68def decode_list(x, f):
69 '''decode a list'''
70 result = []
71 f += 1
72 while x[f] != 'e':
73 v, f = DECODE_FUNC[x[f]](x, f)
74 result.append(v)
75 return (result, f + 1)
76
77
78def decode_dict(x, f):
79 '''decode a dict'''
80 result = {}
81 f += 1
82 while x[f] != 'e':
83 k, f = decode_string(x, f)
84 result[k], f = DECODE_FUNC[x[f]](x, f)
85 return (result, f + 1)
86
87
88def encode_bool(x, r):
89 '''bencode a boolean'''
90 if x:
91 encode_int(1, r)
92 else:
93 encode_int(0, r)
94
95
96def encode_int(x, r):
97 '''bencode an integer/float'''
98 r.extend(('i', str(x), 'e'))
99
100
101def encode_list(x, r):
102 '''bencode a list/tuple'''
103 r.append('l')
104 [ENCODE_FUNC[type(item)](item, r) for item in x]
105 r.append('e')
106
107
108def encode_dict(x, result):
109 '''bencode a dict'''
110 result.append('d')
111 ilist = x.items()
112 ilist.sort()
113 for k, v in ilist:
114 result.extend((str(len(k)), ':', k))
115 ENCODE_FUNC[type(v)](v, result)
116 result.append('e')
117
118
119DECODE_FUNC = {}
120DECODE_FUNC.update(dict([(str(x), decode_string) for x in xrange(9)]))
121DECODE_FUNC['l'] = decode_list
122DECODE_FUNC['d'] = decode_dict
123DECODE_FUNC['i'] = decode_int
124
125
126ENCODE_FUNC = {}
127ENCODE_FUNC[Bencached] = lambda x, r: r.append(x.bencoded)
128ENCODE_FUNC[types.IntType] = encode_int
129ENCODE_FUNC[types.LongType] = encode_int
130ENCODE_FUNC[types.StringType] = lambda x, r: r.extend((str(len(x)), ':', x))
131ENCODE_FUNC[types.ListType] = encode_list
132ENCODE_FUNC[types.TupleType] = encode_list
133ENCODE_FUNC[types.DictType] = encode_dict
134ENCODE_FUNC[types.BooleanType] = encode_bool
135
136
137def bencode(string):
138 '''bencode $string'''
139 table = []
140 ENCODE_FUNC[type(string)](string, table)
141 return ''.join(table)
142
143
144def bdecode(string):
145 '''decode $string'''
146 try:
147 result, lenght = DECODE_FUNC[string[0]](string, 0)
148 except (IndexError, KeyError, ValueError):
149 raise BTFailure('Not a valid bencoded string')
150 if lenght != len(string):
151 raise BTFailure('Invalid bencoded value (data after valid prefix)')
152 return result