1"""Python 'uu_codec' Codec - UU content transfer encoding. 2 3This codec de/encodes from bytes to bytes. 4 5Written by Marc-Andre Lemburg (mal@lemburg.com). Some details were 6adapted from uu.py which was written by Lance Ellinghouse and 7modified by Jack Jansen and Fredrik Lundh. 8""" 9 10import codecs 11import binascii 12from io import BytesIO 13 14### Codec APIs 15 16def 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 33def 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 66class 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 73class IncrementalEncoder(codecs.IncrementalEncoder): 74 def encode(self, input, final=False): 75 return uu_encode(input, self.errors)[0] 76 77class IncrementalDecoder(codecs.IncrementalDecoder): 78 def decode(self, input, final=False): 79 return uu_decode(input, self.errors)[0] 80 81class StreamWriter(Codec, codecs.StreamWriter): 82 charbuffertype = bytes 83 84class StreamReader(Codec, codecs.StreamReader): 85 charbuffertype = bytes 86 87### encodings module API 88 89def 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