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