17db96d56Sopenharmony_ci#! /usr/bin/env python3 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci# Copyright 1994 by Lance Ellinghouse 47db96d56Sopenharmony_ci# Cathedral City, California Republic, United States of America. 57db96d56Sopenharmony_ci# All Rights Reserved 67db96d56Sopenharmony_ci# Permission to use, copy, modify, and distribute this software and its 77db96d56Sopenharmony_ci# documentation for any purpose and without fee is hereby granted, 87db96d56Sopenharmony_ci# provided that the above copyright notice appear in all copies and that 97db96d56Sopenharmony_ci# both that copyright notice and this permission notice appear in 107db96d56Sopenharmony_ci# supporting documentation, and that the name of Lance Ellinghouse 117db96d56Sopenharmony_ci# not be used in advertising or publicity pertaining to distribution 127db96d56Sopenharmony_ci# of the software without specific, written prior permission. 137db96d56Sopenharmony_ci# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO 147db96d56Sopenharmony_ci# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 157db96d56Sopenharmony_ci# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE 167db96d56Sopenharmony_ci# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 177db96d56Sopenharmony_ci# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 187db96d56Sopenharmony_ci# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 197db96d56Sopenharmony_ci# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 207db96d56Sopenharmony_ci# 217db96d56Sopenharmony_ci# Modified by Jack Jansen, CWI, July 1995: 227db96d56Sopenharmony_ci# - Use binascii module to do the actual line-by-line conversion 237db96d56Sopenharmony_ci# between ascii and binary. This results in a 1000-fold speedup. The C 247db96d56Sopenharmony_ci# version is still 5 times faster, though. 257db96d56Sopenharmony_ci# - Arguments more compliant with python standard 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci"""Implementation of the UUencode and UUdecode functions. 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ciencode(in_file, out_file [,name, mode], *, backtick=False) 307db96d56Sopenharmony_cidecode(in_file [, out_file, mode, quiet]) 317db96d56Sopenharmony_ci""" 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ciimport binascii 347db96d56Sopenharmony_ciimport os 357db96d56Sopenharmony_ciimport sys 367db96d56Sopenharmony_ciimport warnings 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ciwarnings._deprecated(__name__, remove=(3, 13)) 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci__all__ = ["Error", "encode", "decode"] 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ciclass Error(Exception): 437db96d56Sopenharmony_ci pass 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_cidef encode(in_file, out_file, name=None, mode=None, *, backtick=False): 467db96d56Sopenharmony_ci """Uuencode file""" 477db96d56Sopenharmony_ci # 487db96d56Sopenharmony_ci # If in_file is a pathname open it and change defaults 497db96d56Sopenharmony_ci # 507db96d56Sopenharmony_ci opened_files = [] 517db96d56Sopenharmony_ci try: 527db96d56Sopenharmony_ci if in_file == '-': 537db96d56Sopenharmony_ci in_file = sys.stdin.buffer 547db96d56Sopenharmony_ci elif isinstance(in_file, str): 557db96d56Sopenharmony_ci if name is None: 567db96d56Sopenharmony_ci name = os.path.basename(in_file) 577db96d56Sopenharmony_ci if mode is None: 587db96d56Sopenharmony_ci try: 597db96d56Sopenharmony_ci mode = os.stat(in_file).st_mode 607db96d56Sopenharmony_ci except AttributeError: 617db96d56Sopenharmony_ci pass 627db96d56Sopenharmony_ci in_file = open(in_file, 'rb') 637db96d56Sopenharmony_ci opened_files.append(in_file) 647db96d56Sopenharmony_ci # 657db96d56Sopenharmony_ci # Open out_file if it is a pathname 667db96d56Sopenharmony_ci # 677db96d56Sopenharmony_ci if out_file == '-': 687db96d56Sopenharmony_ci out_file = sys.stdout.buffer 697db96d56Sopenharmony_ci elif isinstance(out_file, str): 707db96d56Sopenharmony_ci out_file = open(out_file, 'wb') 717db96d56Sopenharmony_ci opened_files.append(out_file) 727db96d56Sopenharmony_ci # 737db96d56Sopenharmony_ci # Set defaults for name and mode 747db96d56Sopenharmony_ci # 757db96d56Sopenharmony_ci if name is None: 767db96d56Sopenharmony_ci name = '-' 777db96d56Sopenharmony_ci if mode is None: 787db96d56Sopenharmony_ci mode = 0o666 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci # 817db96d56Sopenharmony_ci # Remove newline chars from name 827db96d56Sopenharmony_ci # 837db96d56Sopenharmony_ci name = name.replace('\n','\\n') 847db96d56Sopenharmony_ci name = name.replace('\r','\\r') 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci # 877db96d56Sopenharmony_ci # Write the data 887db96d56Sopenharmony_ci # 897db96d56Sopenharmony_ci out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii")) 907db96d56Sopenharmony_ci data = in_file.read(45) 917db96d56Sopenharmony_ci while len(data) > 0: 927db96d56Sopenharmony_ci out_file.write(binascii.b2a_uu(data, backtick=backtick)) 937db96d56Sopenharmony_ci data = in_file.read(45) 947db96d56Sopenharmony_ci if backtick: 957db96d56Sopenharmony_ci out_file.write(b'`\nend\n') 967db96d56Sopenharmony_ci else: 977db96d56Sopenharmony_ci out_file.write(b' \nend\n') 987db96d56Sopenharmony_ci finally: 997db96d56Sopenharmony_ci for f in opened_files: 1007db96d56Sopenharmony_ci f.close() 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_cidef decode(in_file, out_file=None, mode=None, quiet=False): 1047db96d56Sopenharmony_ci """Decode uuencoded file""" 1057db96d56Sopenharmony_ci # 1067db96d56Sopenharmony_ci # Open the input file, if needed. 1077db96d56Sopenharmony_ci # 1087db96d56Sopenharmony_ci opened_files = [] 1097db96d56Sopenharmony_ci if in_file == '-': 1107db96d56Sopenharmony_ci in_file = sys.stdin.buffer 1117db96d56Sopenharmony_ci elif isinstance(in_file, str): 1127db96d56Sopenharmony_ci in_file = open(in_file, 'rb') 1137db96d56Sopenharmony_ci opened_files.append(in_file) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci try: 1167db96d56Sopenharmony_ci # 1177db96d56Sopenharmony_ci # Read until a begin is encountered or we've exhausted the file 1187db96d56Sopenharmony_ci # 1197db96d56Sopenharmony_ci while True: 1207db96d56Sopenharmony_ci hdr = in_file.readline() 1217db96d56Sopenharmony_ci if not hdr: 1227db96d56Sopenharmony_ci raise Error('No valid begin line found in input file') 1237db96d56Sopenharmony_ci if not hdr.startswith(b'begin'): 1247db96d56Sopenharmony_ci continue 1257db96d56Sopenharmony_ci hdrfields = hdr.split(b' ', 2) 1267db96d56Sopenharmony_ci if len(hdrfields) == 3 and hdrfields[0] == b'begin': 1277db96d56Sopenharmony_ci try: 1287db96d56Sopenharmony_ci int(hdrfields[1], 8) 1297db96d56Sopenharmony_ci break 1307db96d56Sopenharmony_ci except ValueError: 1317db96d56Sopenharmony_ci pass 1327db96d56Sopenharmony_ci if out_file is None: 1337db96d56Sopenharmony_ci # If the filename isn't ASCII, what's up with that?!? 1347db96d56Sopenharmony_ci out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii") 1357db96d56Sopenharmony_ci if os.path.exists(out_file): 1367db96d56Sopenharmony_ci raise Error(f'Cannot overwrite existing file: {out_file}') 1377db96d56Sopenharmony_ci if (out_file.startswith(os.sep) or 1387db96d56Sopenharmony_ci f'..{os.sep}' in out_file or ( 1397db96d56Sopenharmony_ci os.altsep and 1407db96d56Sopenharmony_ci (out_file.startswith(os.altsep) or 1417db96d56Sopenharmony_ci f'..{os.altsep}' in out_file)) 1427db96d56Sopenharmony_ci ): 1437db96d56Sopenharmony_ci raise Error(f'Refusing to write to {out_file} due to directory traversal') 1447db96d56Sopenharmony_ci if mode is None: 1457db96d56Sopenharmony_ci mode = int(hdrfields[1], 8) 1467db96d56Sopenharmony_ci # 1477db96d56Sopenharmony_ci # Open the output file 1487db96d56Sopenharmony_ci # 1497db96d56Sopenharmony_ci if out_file == '-': 1507db96d56Sopenharmony_ci out_file = sys.stdout.buffer 1517db96d56Sopenharmony_ci elif isinstance(out_file, str): 1527db96d56Sopenharmony_ci fp = open(out_file, 'wb') 1537db96d56Sopenharmony_ci os.chmod(out_file, mode) 1547db96d56Sopenharmony_ci out_file = fp 1557db96d56Sopenharmony_ci opened_files.append(out_file) 1567db96d56Sopenharmony_ci # 1577db96d56Sopenharmony_ci # Main decoding loop 1587db96d56Sopenharmony_ci # 1597db96d56Sopenharmony_ci s = in_file.readline() 1607db96d56Sopenharmony_ci while s and s.strip(b' \t\r\n\f') != b'end': 1617db96d56Sopenharmony_ci try: 1627db96d56Sopenharmony_ci data = binascii.a2b_uu(s) 1637db96d56Sopenharmony_ci except binascii.Error as v: 1647db96d56Sopenharmony_ci # Workaround for broken uuencoders by /Fredrik Lundh 1657db96d56Sopenharmony_ci nbytes = (((s[0]-32) & 63) * 4 + 5) // 3 1667db96d56Sopenharmony_ci data = binascii.a2b_uu(s[:nbytes]) 1677db96d56Sopenharmony_ci if not quiet: 1687db96d56Sopenharmony_ci sys.stderr.write("Warning: %s\n" % v) 1697db96d56Sopenharmony_ci out_file.write(data) 1707db96d56Sopenharmony_ci s = in_file.readline() 1717db96d56Sopenharmony_ci if not s: 1727db96d56Sopenharmony_ci raise Error('Truncated input file') 1737db96d56Sopenharmony_ci finally: 1747db96d56Sopenharmony_ci for f in opened_files: 1757db96d56Sopenharmony_ci f.close() 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_cidef test(): 1787db96d56Sopenharmony_ci """uuencode/uudecode main program""" 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci import optparse 1817db96d56Sopenharmony_ci parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]') 1827db96d56Sopenharmony_ci parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true') 1837db96d56Sopenharmony_ci parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true') 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci (options, args) = parser.parse_args() 1867db96d56Sopenharmony_ci if len(args) > 2: 1877db96d56Sopenharmony_ci parser.error('incorrect number of arguments') 1887db96d56Sopenharmony_ci sys.exit(1) 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci # Use the binary streams underlying stdin/stdout 1917db96d56Sopenharmony_ci input = sys.stdin.buffer 1927db96d56Sopenharmony_ci output = sys.stdout.buffer 1937db96d56Sopenharmony_ci if len(args) > 0: 1947db96d56Sopenharmony_ci input = args[0] 1957db96d56Sopenharmony_ci if len(args) > 1: 1967db96d56Sopenharmony_ci output = args[1] 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci if options.decode: 1997db96d56Sopenharmony_ci if options.text: 2007db96d56Sopenharmony_ci if isinstance(output, str): 2017db96d56Sopenharmony_ci output = open(output, 'wb') 2027db96d56Sopenharmony_ci else: 2037db96d56Sopenharmony_ci print(sys.argv[0], ': cannot do -t to stdout') 2047db96d56Sopenharmony_ci sys.exit(1) 2057db96d56Sopenharmony_ci decode(input, output) 2067db96d56Sopenharmony_ci else: 2077db96d56Sopenharmony_ci if options.text: 2087db96d56Sopenharmony_ci if isinstance(input, str): 2097db96d56Sopenharmony_ci input = open(input, 'rb') 2107db96d56Sopenharmony_ci else: 2117db96d56Sopenharmony_ci print(sys.argv[0], ': cannot do -t from stdin') 2127db96d56Sopenharmony_ci sys.exit(1) 2137db96d56Sopenharmony_ci encode(input, output) 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ciif __name__ == '__main__': 2167db96d56Sopenharmony_ci test() 217