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 # Remove newline chars from filename 24 filename = filename.replace('\n','\\n') 25 filename = filename.replace('\r','\\r') 26 27 # Encode 28 write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii')) 29 chunk = read(45) 30 while chunk: 31 write(binascii.b2a_uu(chunk)) 32 chunk = read(45) 33 write(b' \nend\n') 34 35 return (outfile.getvalue(), len(input)) 36 37def uu_decode(input, errors='strict'): 38 assert errors == 'strict' 39 infile = BytesIO(input) 40 outfile = BytesIO() 41 readline = infile.readline 42 write = outfile.write 43 44 # Find start of encoded data 45 while 1: 46 s = readline() 47 if not s: 48 raise ValueError('Missing "begin" line in input data') 49 if s[:5] == b'begin': 50 break 51 52 # Decode 53 while True: 54 s = readline() 55 if not s or s == b'end\n': 56 break 57 try: 58 data = binascii.a2b_uu(s) 59 except binascii.Error as v: 60 # Workaround for broken uuencoders by /Fredrik Lundh 61 nbytes = (((s[0]-32) & 63) * 4 + 5) // 3 62 data = binascii.a2b_uu(s[:nbytes]) 63 #sys.stderr.write("Warning: %s\n" % str(v)) 64 write(data) 65 if not s: 66 raise ValueError('Truncated input data') 67 68 return (outfile.getvalue(), len(input)) 69 70class Codec(codecs.Codec): 71 def encode(self, input, errors='strict'): 72 return uu_encode(input, errors) 73 74 def decode(self, input, errors='strict'): 75 return uu_decode(input, errors) 76 77class IncrementalEncoder(codecs.IncrementalEncoder): 78 def encode(self, input, final=False): 79 return uu_encode(input, self.errors)[0] 80 81class IncrementalDecoder(codecs.IncrementalDecoder): 82 def decode(self, input, final=False): 83 return uu_decode(input, self.errors)[0] 84 85class StreamWriter(Codec, codecs.StreamWriter): 86 charbuffertype = bytes 87 88class StreamReader(Codec, codecs.StreamReader): 89 charbuffertype = bytes 90 91### encodings module API 92 93def getregentry(): 94 return codecs.CodecInfo( 95 name='uu', 96 encode=uu_encode, 97 decode=uu_decode, 98 incrementalencoder=IncrementalEncoder, 99 incrementaldecoder=IncrementalDecoder, 100 streamreader=StreamReader, 101 streamwriter=StreamWriter, 102 _is_text_encoding=False, 103 ) 104