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@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 # 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
37 def 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
70 class ESC[4;38;5;81mCodec(ESC[4;38;5;149mcodecsESC[4;38;5;149m.ESC[4;38;5;149mCodec):
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
77 class ESC[4;38;5;81mIncrementalEncoder(ESC[4;38;5;149mcodecsESC[4;38;5;149m.ESC[4;38;5;149mIncrementalEncoder):
78 def encode(self, input, final=False):
79 return uu_encode(input, self.errors)[0]
80
81 class ESC[4;38;5;81mIncrementalDecoder(ESC[4;38;5;149mcodecsESC[4;38;5;149m.ESC[4;38;5;149mIncrementalDecoder):
82 def decode(self, input, final=False):
83 return uu_decode(input, self.errors)[0]
84
85 class ESC[4;38;5;81mStreamWriter(ESC[4;38;5;149mCodec, ESC[4;38;5;149mcodecsESC[4;38;5;149m.ESC[4;38;5;149mStreamWriter):
86 charbuffertype = bytes
87
88 class ESC[4;38;5;81mStreamReader(ESC[4;38;5;149mCodec, ESC[4;38;5;149mcodecsESC[4;38;5;149m.ESC[4;38;5;149mStreamReader):
89 charbuffertype = bytes
90
91 ### encodings module API
92
93 def 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 )