Home | History | Annotate | Download | only in encodings
      1 """Python 'uu_codec' Codec - UU content transfer encoding.
      2 
      3 This codec de/encodes from bytes to bytes.
      4 
      5 Written by Marc-Andre Lemburg (mal (at] lemburg.com). Some details were
      6 adapted from uu.py which was written by Lance Ellinghouse and
      7 modified by Jack Jansen and Fredrik Lundh.
      8 """
      9 
     10 import codecs
     11 import binascii
     12 from io import BytesIO
     13 
     14 ### Codec APIs
     15 
     16 def uu_encode(input, errors='strict', filename='<data>', mode=0o666):
     17     assert errors == 'strict'
     18     infile = BytesIO(input)
     19     outfile = BytesIO()
     20     read = infile.read
     21     write = outfile.write
     22 
     23     # Encode
     24     write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
     25     chunk = read(45)
     26     while chunk:
     27         write(binascii.b2a_uu(chunk))
     28         chunk = read(45)
     29     write(b' \nend\n')
     30 
     31     return (outfile.getvalue(), len(input))
     32 
     33 def uu_decode(input, errors='strict'):
     34     assert errors == 'strict'
     35     infile = BytesIO(input)
     36     outfile = BytesIO()
     37     readline = infile.readline
     38     write = outfile.write
     39 
     40     # Find start of encoded data
     41     while 1:
     42         s = readline()
     43         if not s:
     44             raise ValueError('Missing "begin" line in input data')
     45         if s[:5] == b'begin':
     46             break
     47 
     48     # Decode
     49     while True:
     50         s = readline()
     51         if not s or s == b'end\n':
     52             break
     53         try:
     54             data = binascii.a2b_uu(s)
     55         except binascii.Error as v:
     56             # Workaround for broken uuencoders by /Fredrik Lundh
     57             nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
     58             data = binascii.a2b_uu(s[:nbytes])
     59             #sys.stderr.write("Warning: %s\n" % str(v))
     60         write(data)
     61     if not s:
     62         raise ValueError('Truncated input data')
     63 
     64     return (outfile.getvalue(), len(input))
     65 
     66 class Codec(codecs.Codec):
     67     def encode(self, input, errors='strict'):
     68         return uu_encode(input, errors)
     69 
     70     def decode(self, input, errors='strict'):
     71         return uu_decode(input, errors)
     72 
     73 class IncrementalEncoder(codecs.IncrementalEncoder):
     74     def encode(self, input, final=False):
     75         return uu_encode(input, self.errors)[0]
     76 
     77 class IncrementalDecoder(codecs.IncrementalDecoder):
     78     def decode(self, input, final=False):
     79         return uu_decode(input, self.errors)[0]
     80 
     81 class StreamWriter(Codec, codecs.StreamWriter):
     82     charbuffertype = bytes
     83 
     84 class StreamReader(Codec, codecs.StreamReader):
     85     charbuffertype = bytes
     86 
     87 ### encodings module API
     88 
     89 def getregentry():
     90     return codecs.CodecInfo(
     91         name='uu',
     92         encode=uu_encode,
     93         decode=uu_decode,
     94         incrementalencoder=IncrementalEncoder,
     95         incrementaldecoder=IncrementalDecoder,
     96         streamreader=StreamReader,
     97         streamwriter=StreamWriter,
     98         _is_text_encoding=False,
     99     )
    100