Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
# Written by Petru Paler, Uoti Urpala, Ross Cohen and John Hoffman
2
# see LICENSE.txt for license information
3
 
4
from types import IntType, LongType, StringType, ListType, TupleType, DictType
5
try:
6
    from types import BooleanType
7
except ImportError:
8
    BooleanType = None
9
try:
10
    from types import UnicodeType
11
except ImportError:
12
    UnicodeType = None
13
from cStringIO import StringIO
14
 
15
def decode_int(x, f):
16
    f += 1
17
    newf = x.index('e', f)
18
    try:
19
        n = int(x[f:newf])
20
    except:
21
        n = long(x[f:newf])
22
    if x[f] == '-':
23
        if x[f + 1] == '0':
24
            raise ValueError
25
    elif x[f] == '0' and newf != f+1:
26
        raise ValueError
27
    return (n, newf+1)
28
 
29
def decode_string(x, f):
30
    colon = x.index(':', f)
31
    try:
32
        n = int(x[f:colon])
33
    except (OverflowError, ValueError):
34
        n = long(x[f:colon])
35
    if x[f] == '0' and colon != f+1:
36
        raise ValueError
37
    colon += 1
38
    return (x[colon:colon+n], colon+n)
39
 
40
def decode_unicode(x, f):
41
    s, f = decode_string(x, f+1)
42
    return (s.decode('UTF-8'),f)
43
 
44
def decode_list(x, f):
45
    r, f = [], f+1
46
    while x[f] != 'e':
47
        v, f = decode_func[x[f]](x, f)
48
        r.append(v)
49
    return (r, f + 1)
50
 
51
def decode_dict(x, f):
52
    r, f = {}, f+1
53
    lastkey = None
54
    while x[f] != 'e':
55
        k, f = decode_string(x, f)
56
        if lastkey >= k:
57
            raise ValueError
58
        lastkey = k
59
        r[k], f = decode_func[x[f]](x, f)
60
    return (r, f + 1)
61
 
62
decode_func = {}
63
decode_func['l'] = decode_list
64
decode_func['d'] = decode_dict
65
decode_func['i'] = decode_int
66
decode_func['0'] = decode_string
67
decode_func['1'] = decode_string
68
decode_func['2'] = decode_string
69
decode_func['3'] = decode_string
70
decode_func['4'] = decode_string
71
decode_func['5'] = decode_string
72
decode_func['6'] = decode_string
73
decode_func['7'] = decode_string
74
decode_func['8'] = decode_string
75
decode_func['9'] = decode_string
76
#decode_func['u'] = decode_unicode
77
 
78
def bdecode(x, sloppy = 0):
79
    try:
80
        r, l = decode_func[x[0]](x, 0)
81
#    except (IndexError, KeyError):
82
    except (IndexError, KeyError, ValueError):
83
        raise ValueError, "bad bencoded data"
84
    if not sloppy and l != len(x):
85
        raise ValueError, "bad bencoded data"
86
    return r
87
 
88
def test_bdecode():
89
    try:
90
        bdecode('0:0:')
91
        assert 0
92
    except ValueError:
93
        pass
94
    try:
95
        bdecode('ie')
96
        assert 0
97
    except ValueError:
98
        pass
99
    try:
100
        bdecode('i341foo382e')
101
        assert 0
102
    except ValueError:
103
        pass
104
    assert bdecode('i4e') == 4L
105
    assert bdecode('i0e') == 0L
106
    assert bdecode('i123456789e') == 123456789L
107
    assert bdecode('i-10e') == -10L
108
    try:
109
        bdecode('i-0e')
110
        assert 0
111
    except ValueError:
112
        pass
113
    try:
114
        bdecode('i123')
115
        assert 0
116
    except ValueError:
117
        pass
118
    try:
119
        bdecode('')
120
        assert 0
121
    except ValueError:
122
        pass
123
    try:
124
        bdecode('i6easd')
125
        assert 0
126
    except ValueError:
127
        pass
128
    try:
129
        bdecode('35208734823ljdahflajhdf')
130
        assert 0
131
    except ValueError:
132
        pass
133
    try:
134
        bdecode('2:abfdjslhfld')
135
        assert 0
136
    except ValueError:
137
        pass
138
    assert bdecode('0:') == ''
139
    assert bdecode('3:abc') == 'abc'
140
    assert bdecode('10:1234567890') == '1234567890'
141
    try:
142
        bdecode('02:xy')
143
        assert 0
144
    except ValueError:
145
        pass
146
    try:
147
        bdecode('l')
148
        assert 0
149
    except ValueError:
150
        pass
151
    assert bdecode('le') == []
152
    try:
153
        bdecode('leanfdldjfh')
154
        assert 0
155
    except ValueError:
156
        pass
157
    assert bdecode('l0:0:0:e') == ['', '', '']
158
    try:
159
        bdecode('relwjhrlewjh')
160
        assert 0
161
    except ValueError:
162
        pass
163
    assert bdecode('li1ei2ei3ee') == [1, 2, 3]
164
    assert bdecode('l3:asd2:xye') == ['asd', 'xy']
165
    assert bdecode('ll5:Alice3:Bobeli2ei3eee') == [['Alice', 'Bob'], [2, 3]]
166
    try:
167
        bdecode('d')
168
        assert 0
169
    except ValueError:
170
        pass
171
    try:
172
        bdecode('defoobar')
173
        assert 0
174
    except ValueError:
175
        pass
176
    assert bdecode('de') == {}
177
    assert bdecode('d3:agei25e4:eyes4:bluee') == {'age': 25, 'eyes': 'blue'}
178
    assert bdecode('d8:spam.mp3d6:author5:Alice6:lengthi100000eee') == {'spam.mp3': {'author': 'Alice', 'length': 100000}}
179
    try:
180
        bdecode('d3:fooe')
181
        assert 0
182
    except ValueError:
183
        pass
184
    try:
185
        bdecode('di1e0:e')
186
        assert 0
187
    except ValueError:
188
        pass
189
    try:
190
        bdecode('d1:b0:1:a0:e')
191
        assert 0
192
    except ValueError:
193
        pass
194
    try:
195
        bdecode('d1:a0:1:a0:e')
196
        assert 0
197
    except ValueError:
198
        pass
199
    try:
200
        bdecode('i03e')
201
        assert 0
202
    except ValueError:
203
        pass
204
    try:
205
        bdecode('l01:ae')
206
        assert 0
207
    except ValueError:
208
        pass
209
    try:
210
        bdecode('9999:x')
211
        assert 0
212
    except ValueError:
213
        pass
214
    try:
215
        bdecode('l0:')
216
        assert 0
217
    except ValueError:
218
        pass
219
    try:
220
        bdecode('d0:0:')
221
        assert 0
222
    except ValueError:
223
        pass
224
    try:
225
        bdecode('d0:')
226
        assert 0
227
    except ValueError:
228
        pass
229
 
230
bencached_marker = []
231
 
232
class Bencached:
233
    def __init__(self, s):
234
        self.marker = bencached_marker
235
        self.bencoded = s
236
 
237
BencachedType = type(Bencached('')) # insufficient, but good as a filter
238
 
239
def encode_bencached(x,r):
240
    assert x.marker == bencached_marker
241
    r.append(x.bencoded)
242
 
243
def encode_int(x,r):
244
    r.extend(('i',str(x),'e'))
245
 
246
def encode_bool(x,r):
247
    encode_int(int(x),r)
248
 
249
def encode_string(x,r):    
250
    r.extend((str(len(x)),':',x))
251
 
252
def encode_unicode(x,r):
253
    #r.append('u')
254
    encode_string(x.encode('UTF-8'),r)
255
 
256
def encode_list(x,r):
257
        r.append('l')
258
        for e in x:
259
            encode_func[type(e)](e, r)
260
        r.append('e')
261
 
262
def encode_dict(x,r):
263
    r.append('d')
264
    ilist = x.items()
265
    ilist.sort()
266
    for k,v in ilist:
267
        r.extend((str(len(k)),':',k))
268
        encode_func[type(v)](v, r)
269
    r.append('e')
270
 
271
encode_func = {}
272
encode_func[BencachedType] = encode_bencached
273
encode_func[IntType] = encode_int
274
encode_func[LongType] = encode_int
275
encode_func[StringType] = encode_string
276
encode_func[ListType] = encode_list
277
encode_func[TupleType] = encode_list
278
encode_func[DictType] = encode_dict
279
if BooleanType:
280
    encode_func[BooleanType] = encode_bool
281
if UnicodeType:
282
    encode_func[UnicodeType] = encode_unicode
283
 
284
def bencode(x):
285
    r = []
286
    try:
287
        encode_func[type(x)](x, r)
288
    except:
289
        print "*** error *** could not encode type %s (value: %s)" % (type(x), x)
290
        assert 0
291
    return ''.join(r)
292
 
293
def test_bencode():
294
    assert bencode(4) == 'i4e'
295
    assert bencode(0) == 'i0e'
296
    assert bencode(-10) == 'i-10e'
297
    assert bencode(12345678901234567890L) == 'i12345678901234567890e'
298
    assert bencode('') == '0:'
299
    assert bencode('abc') == '3:abc'
300
    assert bencode('1234567890') == '10:1234567890'
301
    assert bencode([]) == 'le'
302
    assert bencode([1, 2, 3]) == 'li1ei2ei3ee'
303
    assert bencode([['Alice', 'Bob'], [2, 3]]) == 'll5:Alice3:Bobeli2ei3eee'
304
    assert bencode({}) == 'de'
305
    assert bencode({'age': 25, 'eyes': 'blue'}) == 'd3:agei25e4:eyes4:bluee'
306
    assert bencode({'spam.mp3': {'author': 'Alice', 'length': 100000}}) == 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee'
307
    try:
308
        bencode({1: 'foo'})
309
        assert 0
310
    except AssertionError:
311
        pass
312
 
313
 
314
try:
315
    import psyco
316
    psyco.bind(bdecode)
317
    psyco.bind(bencode)
318
except ImportError:
319
    pass