]>
Commit | Line | Data |
---|---|---|
43d991f6 MT |
1 | #!/usr/bin/python |
2 | ||
9068dba1 | 3 | from __future__ import division |
43d991f6 | 4 | |
170e8c36 | 5 | def ncode_hex(s): |
f1349ebc | 6 | return s.encode("hex") |
43d991f6 | 7 | |
f1349ebc MT |
8 | def decode_hex(s): |
9 | return s.decode("hex") | |
43d991f6 | 10 | |
43d991f6 MT |
11 | ##### This is borrowed from the bittorrent client libary ##### |
12 | ||
13 | def decode_int(x, f): | |
14 | f += 1 | |
15 | newf = x.index('e', f) | |
16 | n = int(x[f:newf]) | |
17 | if x[f] == '-': | |
18 | if x[f + 1] == '0': | |
19 | raise ValueError | |
20 | elif x[f] == '0' and newf != f+1: | |
21 | raise ValueError | |
22 | return (n, newf+1) | |
23 | ||
24 | def decode_string(x, f): | |
25 | colon = x.index(':', f) | |
26 | n = int(x[f:colon]) | |
27 | if x[f] == '0' and colon != f+1: | |
28 | raise ValueError | |
29 | colon += 1 | |
30 | return (x[colon:colon+n], colon+n) | |
31 | ||
32 | def decode_list(x, f): | |
33 | r, f = [], f+1 | |
34 | while x[f] != 'e': | |
35 | v, f = decode_func[x[f]](x, f) | |
36 | r.append(v) | |
37 | return (r, f + 1) | |
38 | ||
39 | def decode_dict(x, f): | |
40 | r, f = {}, f+1 | |
41 | while x[f] != 'e': | |
42 | k, f = decode_string(x, f) | |
43 | r[k], f = decode_func[x[f]](x, f) | |
44 | return (r, f + 1) | |
45 | ||
46 | decode_func = {} | |
47 | decode_func['l'] = decode_list | |
48 | decode_func['d'] = decode_dict | |
49 | decode_func['i'] = decode_int | |
50 | decode_func['0'] = decode_string | |
51 | decode_func['1'] = decode_string | |
52 | decode_func['2'] = decode_string | |
53 | decode_func['3'] = decode_string | |
54 | decode_func['4'] = decode_string | |
55 | decode_func['5'] = decode_string | |
56 | decode_func['6'] = decode_string | |
57 | decode_func['7'] = decode_string | |
58 | decode_func['8'] = decode_string | |
59 | decode_func['9'] = decode_string | |
60 | ||
61 | def bdecode(x): | |
62 | try: | |
63 | r, l = decode_func[x[0]](x, 0) | |
64 | except (IndexError, KeyError, ValueError): | |
65 | raise Exception("not a valid bencoded string") | |
66 | if l != len(x): | |
67 | raise Exception("invalid bencoded value (data after valid prefix)") | |
68 | return r | |
69 | ||
70 | from types import StringType, IntType, LongType, DictType, ListType, TupleType | |
71 | ||
72 | ||
73 | class Bencached(object): | |
74 | ||
75 | __slots__ = ['bencoded'] | |
76 | ||
77 | def __init__(self, s): | |
78 | self.bencoded = s | |
79 | ||
80 | def encode_bencached(x,r): | |
81 | r.append(x.bencoded) | |
82 | ||
83 | def encode_int(x, r): | |
84 | r.extend(('i', str(x), 'e')) | |
85 | ||
86 | def encode_bool(x, r): | |
87 | if x: | |
88 | encode_int(1, r) | |
89 | else: | |
90 | encode_int(0, r) | |
91 | ||
92 | def encode_string(x, r): | |
93 | r.extend((str(len(x)), ':', x)) | |
94 | ||
95 | def encode_list(x, r): | |
96 | r.append('l') | |
97 | for i in x: | |
98 | encode_func[type(i)](i, r) | |
99 | r.append('e') | |
100 | ||
101 | def encode_dict(x,r): | |
102 | r.append('d') | |
103 | ilist = x.items() | |
104 | ilist.sort() | |
105 | for k, v in ilist: | |
106 | r.extend((str(len(k)), ':', k)) | |
107 | encode_func[type(v)](v, r) | |
108 | r.append('e') | |
109 | ||
110 | encode_func = {} | |
111 | encode_func[Bencached] = encode_bencached | |
112 | encode_func[IntType] = encode_int | |
113 | encode_func[LongType] = encode_int | |
114 | encode_func[StringType] = encode_string | |
115 | encode_func[ListType] = encode_list | |
116 | encode_func[TupleType] = encode_list | |
117 | encode_func[DictType] = encode_dict | |
118 | ||
119 | try: | |
120 | from types import BooleanType | |
121 | encode_func[BooleanType] = encode_bool | |
122 | except ImportError: | |
123 | pass | |
124 | ||
125 | def bencode(x): | |
126 | r = [] | |
127 | encode_func[type(x)](x, r) | |
128 | return ''.join(r) |