- Timestamp:
- 03/17/13 22:26:27 (12 years ago)
- Location:
- trunk/lib/bletchley
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/bletchley/blobtools.py
r35 r40 22 22 import base64 23 23 import binascii 24 import urllib25 24 import fractions 26 25 import operator 27 26 import functools 28 27 import itertools 29 import buffertools 28 from . import buffertools 29 30 31 # urllib.parse's functions are not well suited for encoding/decoding 32 # bytes or managing encoded case 33 def _percentEncode(binary, plus=False, upper=True): 34 fmt = "%%%.2X" 35 if upper: 36 fmt = "%%%.2x" 37 38 ret_val = b'' 39 for c in binary: 40 if c not in b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789': 41 ret_val += (fmt % c).encode('ascii') 42 elif plus and (c == 20): 43 ret_val += b'+' 44 else: 45 ret_val += c 46 47 return ret_val 48 49 50 def _percentDecode(binary, plus=False): 51 ret_val = b'' 52 if plus: 53 binary = binary.replace(b'+', b' ') 54 if binary == b'': 55 return b'' 56 chunks = binary.split(b'%') 57 if binary[0] == 0x25: 58 chunks = chunks[1:] 59 60 for chunk in chunks: 61 if len(chunk) < 2: 62 return None 63 try: 64 ret_val += bytes([int(chunk[0:2], 16)]) + chunk[2:] 65 except: 66 print(repr(chunk)) 67 return None 68 69 return ret_val 70 30 71 31 72 # abstract class 32 73 class DataEncoding(object): 33 charset = frozenset( '')34 extraneous_chars = ''74 charset = frozenset(b'') 75 extraneous_chars = b'' 35 76 dialect = None 36 77 name = None … … 65 106 super(base64Encoding, self).__init__(dialect) 66 107 if dialect.startswith('rfc3548'): 67 self.c62 = '+'68 self.c63 = '/'69 self.pad = '='108 self.c62 = b'+' 109 self.c63 = b'/' 110 self.pad = b'=' 70 111 elif dialect.startswith('filename'): 71 self.c62 = '+'72 self.c63 = '-'73 self.pad = '='112 self.c62 = b'+' 113 self.c63 = b'-' 114 self.pad = b'=' 74 115 elif dialect.startswith('url1'): 75 self.c62 = '-'76 self.c63 = '_'77 self.pad = '='116 self.c62 = b'-' 117 self.c63 = b'_' 118 self.pad = b'=' 78 119 elif dialect.startswith('url2'): 79 self.c62 = '-'80 self.c63 = '_'81 self.pad = '.'120 self.c62 = b'-' 121 self.c63 = b'_' 122 self.pad = b'.' 82 123 elif dialect.startswith('url3'): 83 self.c62 = '_'84 self.c63 = '-'85 self.pad = '.'124 self.c62 = b'_' 125 self.c63 = b'-' 126 self.pad = b'.' 86 127 elif dialect.startswith('url4'): 87 self.c62 = '-'88 self.c63 = '_'89 self.pad = '!'128 self.c62 = b'-' 129 self.c63 = b'_' 130 self.pad = b'!' 90 131 elif dialect.startswith('url5'): 91 self.c62 = '+'92 self.c63 = '/'93 self.pad = '$'132 self.c62 = b'+' 133 self.c63 = b'/' 134 self.pad = b'$' 94 135 elif dialect.startswith('otkurl'): 95 self.c62 = '-'96 self.c63 = '_'97 self.pad = '*'136 self.c62 = b'-' 137 self.c63 = b'_' 138 self.pad = b'*' 98 139 elif dialect.startswith('xmlnmtoken'): 99 self.c62 = '.'100 self.c63 = '-'101 self.pad = '='140 self.c62 = b'.' 141 self.c63 = b'-' 142 self.pad = b'=' 102 143 elif dialect.startswith('xmlname'): 103 self.c62 = '_'104 self.c63 = ':'105 self.pad = '='144 self.c62 = b'_' 145 self.c63 = b':' 146 self.pad = b'=' 106 147 107 148 if 'newline' in dialect: 108 self.extraneous_chars = '\r\n'109 110 self.charset = frozenset( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'111 + 'abcdefghijklmnopqrstuvwxyz0123456789'149 self.extraneous_chars = b'\r\n' 150 151 self.charset = frozenset(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 152 +b'abcdefghijklmnopqrstuvwxyz0123456789' 112 153 +self.c62+self.c63+self.pad+self.extraneous_chars) 113 154 … … 120 161 def extraTests(self, blob): 121 162 for c in self.extraneous_chars: 122 blob = blob.replace( c,'')163 blob = blob.replace(bytes([c]), b'') 123 164 124 165 nopad = blob.rstrip(self.pad) … … 137 178 def decode(self, blob): 138 179 for c in self.extraneous_chars: 139 blob = blob.replace( c,'')180 blob = blob.replace(bytes(c), b'') 140 181 141 182 if self.dialect.endswith('nopad'): … … 150 191 151 192 if not self.dialect.startswith('rfc3548'): 152 table = string.maketrans(self.c62+self.c63+self.pad, '+/=')193 table = string.maketrans(self.c62+self.c63+self.pad, b'+/=') 153 194 blob = blob.translate(table) 154 195 … … 160 201 161 202 if not self.dialect.startswith('rfc3548'): 162 table = string.maketrans( '+/=', self.c62+self.c63+self.pad)203 table = string.maketrans(b'+/=', self.c62+self.c63+self.pad) 163 204 ret_val = ret_val.translate(table) 164 205 … … 174 215 super(base32Encoding, self).__init__(dialect) 175 216 if dialect.startswith('rfc3548upper'): 176 self.pad = '='177 self.charset = frozenset( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'+self.pad)217 self.pad = b'=' 218 self.charset = frozenset(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'+self.pad) 178 219 179 220 elif dialect.startswith('rfc3548lower'): 180 self.pad = '='181 self.charset = frozenset( 'abcdefghijklmnopqrstuvwxyz234567'+self.pad)221 self.pad = b'=' 222 self.charset = frozenset(b'abcdefghijklmnopqrstuvwxyz234567'+self.pad) 182 223 183 224 def _guessPadLength(self, nopad_len): … … 203 244 if self.dialect.endswith('nopad'): 204 245 if self.pad in blob: 205 raise Exception("Unpadded base 64string contains pad character")246 raise Exception("Unpadded base32 string contains pad character") 206 247 207 248 padlen = self._guessPadLength(len(blob)) … … 233 274 super(hexEncoding, self).__init__(dialect) 234 275 if 'mixed' in dialect: 235 self.charset = frozenset( 'ABCDEFabcdef0123456789')276 self.charset = frozenset(b'ABCDEFabcdef0123456789') 236 277 elif 'upper' in dialect: 237 self.charset = frozenset( 'ABCDEF0123456789')278 self.charset = frozenset(b'ABCDEF0123456789') 238 279 elif 'lower' in dialect: 239 self.charset = frozenset( 'abcdef0123456789')280 self.charset = frozenset(b'abcdef0123456789') 240 281 241 282 … … 261 302 self.charset = None 262 303 if 'mixed' in dialect: 263 self.hexchars = frozenset( 'ABCDEFabcdef0123456789')304 self.hexchars = frozenset(b'ABCDEFabcdef0123456789') 264 305 elif 'upper' in dialect: 265 self.hexchars = frozenset( 'ABCDEF0123456789')306 self.hexchars = frozenset(b'ABCDEF0123456789') 266 307 elif 'lower' in dialect: 267 self.hexchars = frozenset( 'abcdef0123456789')308 self.hexchars = frozenset(b'abcdef0123456789') 268 309 269 310 def extraTests(self, blob): 270 chunks = blob.split( '%')311 chunks = blob.split(b'%') 271 312 if len(chunks) < 2: 272 313 return None … … 279 320 280 321 def decode(self, blob): 322 plus = False 281 323 if 'plus' in self.dialect: 282 return urllib.unquote(blob) 283 else: 284 return urllib.unquote_plus(blob) 285 286 # XXX: should technically produce quoted digits in same upper/lower case 324 plus = True 325 return _percentDecode(blob, plus=plus) 326 287 327 def encode(self, blob): 328 upper = True 329 plus = False 288 330 if 'plus' in self.dialect: 289 return urllib.quote(blob, '') 290 else: 291 return urllib.quote_plus(blob, '') 331 plus = True 332 if 'lower' in self.dialect: 333 upper = False 334 335 return _percentEncode(blob, plus=plus, upper=upper) 292 336 293 337 … … 336 380 337 381 def supportedEncodings(): 338 e = encodings.keys()382 e = list(encodings.keys()) 339 383 e.sort() 340 384 return e … … 380 424 381 425 def decodeAll(encoding, blobs): 382 return map(encodings[encoding].decode, blobs)426 return [encodings[encoding].decode(b) for b in blobs] 383 427 384 428 def encodeAll(encoding, blobs): 385 return map(encodings[encoding].encode, blobs)429 return [encodings[encoding].encode(b) for b in blobs] 386 430 387 431 def decodeChain(decoding_chain, blob): … … 412 456 413 457 414 allTrue = functools.partial( reduce, (lambda x,y: x and y))458 allTrue = functools.partial(functools.reduce, (lambda x,y: x and y)) 415 459 416 460 def checkCommonBlocksizes(lengths): -
trunk/lib/bletchley/buffertools.py
r36 r40 75 75 76 76 colors = {} 77 for block,count in block_counts.ite ritems():77 for block,count in block_counts.items(): 78 78 if count == 1: 79 79 # mask needed for portability
Note: See TracChangeset
for help on using the changeset viewer.