blob: 2a5728fb5b74ad648dc2265afb34010d2d0a0552 [file] [log] [blame]
Georg Brandl02524622010-12-02 18:06:51 +00001"""Python 'uu_codec' Codec - UU content transfer encoding.
2
R David Murraye5cb8362014-03-13 20:54:30 -04003This codec de/encodes from bytes to bytes.
Georg Brandl02524622010-12-02 18:06:51 +00004
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
Serhiy Storchaka519114d2014-11-07 14:04:37 +020057 nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
Georg Brandl02524622010-12-02 18:06:51 +000058 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,
Serhiy Storchaka94ee3892014-02-24 14:43:03 +020098 _is_text_encoding=False,
Georg Brandl02524622010-12-02 18:06:51 +000099 )