Changeset 40 for trunk/lib


Ignore:
Timestamp:
03/17/13 22:26:27 (11 years ago)
Author:
tmorgan
Message:

Switched to python3 only, since supporting both 2.x and 3.x is such a pain

Added preliminary python-requests support to http2py

Location:
trunk/lib/bletchley
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/bletchley/blobtools.py

    r35 r40  
    2222import base64
    2323import binascii
    24 import urllib
    2524import fractions
    2625import operator
    2726import functools
    2827import itertools
    29 import buffertools
     28from . import buffertools
     29
     30
     31# urllib.parse's functions are not well suited for encoding/decoding
     32# bytes or managing encoded case
     33def _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
     50def _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
    3071
    3172# abstract class
    3273class DataEncoding(object):
    33     charset = frozenset('')
    34     extraneous_chars = ''
     74    charset = frozenset(b'')
     75    extraneous_chars = b''
    3576    dialect = None
    3677    name = None
     
    65106        super(base64Encoding, self).__init__(dialect)
    66107        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'='
    70111        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'='
    74115        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'='
    78119        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'.'
    82123        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'.'
    86127        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'!'
    90131        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'$'
    94135        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'*'
    98139        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'='
    102143        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'='
    106147       
    107148        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'
    112153                                 +self.c62+self.c63+self.pad+self.extraneous_chars)
    113154
     
    120161    def extraTests(self, blob):
    121162        for c in self.extraneous_chars:
    122             blob = blob.replace(c, '')
     163            blob = blob.replace(bytes([c]), b'')
    123164
    124165        nopad = blob.rstrip(self.pad)
     
    137178    def decode(self, blob):
    138179        for c in self.extraneous_chars:
    139             blob = blob.replace(c, '')
     180            blob = blob.replace(bytes(c), b'')
    140181
    141182        if self.dialect.endswith('nopad'):
     
    150191
    151192        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'+/=')
    153194            blob = blob.translate(table)
    154195
     
    160201
    161202        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)
    163204            ret_val = ret_val.translate(table)
    164205
     
    174215        super(base32Encoding, self).__init__(dialect)
    175216        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)
    178219
    179220        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)
    182223
    183224    def _guessPadLength(self, nopad_len):
     
    203244        if self.dialect.endswith('nopad'):
    204245            if self.pad in blob:
    205                 raise Exception("Unpadded base64 string contains pad character")
     246                raise Exception("Unpadded base32 string contains pad character")
    206247
    207248            padlen = self._guessPadLength(len(blob))
     
    233274        super(hexEncoding, self).__init__(dialect)
    234275        if 'mixed' in dialect:
    235             self.charset = frozenset('ABCDEFabcdef0123456789')
     276            self.charset = frozenset(b'ABCDEFabcdef0123456789')
    236277        elif 'upper' in dialect:
    237             self.charset = frozenset('ABCDEF0123456789')           
     278            self.charset = frozenset(b'ABCDEF0123456789')           
    238279        elif 'lower' in dialect:
    239             self.charset = frozenset('abcdef0123456789')
     280            self.charset = frozenset(b'abcdef0123456789')
    240281
    241282
     
    261302        self.charset = None
    262303        if 'mixed' in dialect:
    263             self.hexchars = frozenset('ABCDEFabcdef0123456789')
     304            self.hexchars = frozenset(b'ABCDEFabcdef0123456789')
    264305        elif 'upper' in dialect:
    265             self.hexchars = frozenset('ABCDEF0123456789')           
     306            self.hexchars = frozenset(b'ABCDEF0123456789')           
    266307        elif 'lower' in dialect:
    267             self.hexchars = frozenset('abcdef0123456789')
     308            self.hexchars = frozenset(b'abcdef0123456789')
    268309
    269310    def extraTests(self, blob):
    270         chunks = blob.split('%')
     311        chunks = blob.split(b'%')
    271312        if len(chunks) < 2:
    272313            return None
     
    279320
    280321    def decode(self, blob):
     322        plus = False
    281323        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
    287327    def encode(self, blob):
     328        upper = True
     329        plus = False
    288330        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)
    292336
    293337
     
    336380
    337381def supportedEncodings():
    338     e = encodings.keys()
     382    e = list(encodings.keys())
    339383    e.sort()
    340384    return e
     
    380424
    381425def decodeAll(encoding, blobs):
    382     return map(encodings[encoding].decode, blobs)
     426    return [encodings[encoding].decode(b) for b in blobs]
    383427
    384428def encodeAll(encoding, blobs):
    385     return map(encodings[encoding].encode, blobs)
     429    return [encodings[encoding].encode(b) for b in blobs]
    386430
    387431def decodeChain(decoding_chain, blob):
     
    412456
    413457
    414 allTrue = functools.partial(reduce, (lambda x,y: x and y))
     458allTrue = functools.partial(functools.reduce, (lambda x,y: x and y))
    415459
    416460def checkCommonBlocksizes(lengths):
  • trunk/lib/bletchley/buffertools.py

    r36 r40  
    7575
    7676    colors = {}
    77     for block,count in block_counts.iteritems():
     77    for block,count in block_counts.items():
    7878        if count == 1:
    7979            # mask needed for portability
Note: See TracChangeset for help on using the changeset viewer.