| # uu.py |
| # Copyright 1994 by Lance Ellinghouse |
| # Cathedral City, California Republic, United States of America. |
| # All Rights Reserved |
| # Permission to use, copy, modify, and distribute this software and its |
| # documentation for any purpose and without fee is hereby granted, |
| # provided that the above copyright notice appear in all copies and that |
| # both that copyright notice and this permission notice appear in |
| # supporting documentation, and that the name of Lance Ellinghouse |
| # not be used in advertising or publicity pertaining to distribution |
| # of the software without specific, written prior permission. |
| # LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| # FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE |
| # FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| # This file implements the UUencode and UUdecode functions. |
| |
| # encode(filename, mode, in_file, out_file) |
| # decode(filename, mode, in_file) |
| # decode(in_file, out_file) |
| # decode(in_file) |
| |
| # encode a single char to always be printable |
| def _ENC(ch): |
| if type(ch) == type(''): |
| a = ch[:1] # only 1 char |
| if len(a) == 0: |
| raise ValueError, 'need to pass in at least 1 char' |
| a = ord(a) |
| elif type(ch) == type(0): |
| a = ch |
| else: |
| raise TypeError, 'must pass in an integer or single character' |
| return chr((a & 077) + ord(' ')) |
| |
| # input 3 chars, output 4 encoded chars |
| def _outenc(str): |
| if len(str) > 3: |
| raise ValueError, 'can only accept strings of 3 chars' |
| p0, p1, p2 = 0, 0, 0 |
| if len(str) > 2: |
| p2 = ord(str[2]) |
| if len(str) > 1: |
| p1 = ord(str[1]) |
| if len(str) > 0: |
| p0 = ord(str[0]) |
| c1 = p0 >> 2 |
| c2 = (p0 << 4) & 060 | (p1 >> 4) & 017 |
| c3 = (p1 << 2) & 074 | (p2 >> 6) & 03 |
| c4 = p2 & 077 |
| rtn = _ENC(c1) |
| rtn = rtn + _ENC(c2) |
| rtn = rtn + _ENC(c3) |
| rtn = rtn + _ENC(c4) |
| return rtn |
| |
| # pass in 45 bytes max, returns 62 bytes encoded |
| def _encode(str): |
| if len(str) > 45: |
| raise ValueError, 'cannot handle more than 45 chars at once' |
| length = len(str) |
| rtn = _ENC(length) |
| i = 0 |
| while i < length: |
| rtn = rtn + _outenc(str[i:(i+3)]) |
| i = i + 3 |
| rtn = rtn + '\n' |
| return rtn |
| |
| # encode a fileobject and write out to a file object |
| def encode(filename, mode, in_file, out_file): |
| out_file.write('begin %o %s\n' % ((mode&0777),filename)) |
| str = in_file.read(45) |
| while len(str) > 0: |
| out_file.write(_encode(str)) |
| str = in_file.read(45) |
| out_file.write(' \nend\n') |
| return None |
| |
| # def decode a single char from printable to possibly non-printable |
| def _DEC(ch): |
| if type(ch) != type('') or len(ch) != 1: |
| raise ValueError, 'need to pass in a single char' |
| a = ord(ch[0:1]) |
| return (a - ord(' ')) |
| |
| # input 4 chars encoded, output 3 chars unencoded |
| def _outdec(str): |
| if len(str) > 4: |
| raise ValueError, 'can only accept strings of 4 chars' |
| p0, p1, p2, p3 = 0, 0, 0, 0 |
| if len(str) > 3: |
| p3 = _DEC(str[3]) |
| if len(str) > 2: |
| p2 = _DEC(str[2]) |
| if len(str) > 1: |
| p1 = _DEC(str[1]) |
| if len(str) > 0: |
| p0 = _DEC(str[0]) |
| c1 = p0 << 2 | (p1 & 060) >> 4 |
| c2 = (p1 & 017) << 4 | (p2 & 074) >> 2 |
| c3 = (p2 & 03) << 6 | (p3 & 077) |
| rtn = chr(c1) |
| rtn = rtn + chr(c2) |
| rtn = rtn + chr(c3) |
| return rtn |
| |
| # pass in 62 bytes and return 45 bytes unencoded |
| def _decode(str): |
| if len(str) > 62: |
| raise ValueError, 'cannot handle more than 62 chars at once' |
| length = _DEC(str[0]) |
| i = 1 |
| rtn = '' |
| while len(rtn) < length: |
| rtn = rtn + _outdec(str[i:(i+4)]) |
| i = i + 4 |
| return rtn[0:length] |
| |
| # decode(filename, mode, in_file) |
| # decode(in_file, out_file) |
| # decode(in_file) |
| def decode(*args): |
| ok = 1 |
| _setup = None |
| out_file = None |
| if len(args) == 3: |
| filename, mode, in_file = args |
| if type(filename) != type(''): |
| ok = 0 |
| if type(mode) != type(0): |
| ok = 0 |
| try: |
| _ = getattr(in_file,'readline') |
| except AttributeError: |
| ok = 0 |
| def _setup(out_file,args): |
| filename, mode, in_file = args |
| # open file as specified and assign out_file for later use |
| out_file = open(filename,'w',mode) |
| _out_file_orig = 0 |
| _ = in_file.readline() |
| return (out_file,_out_file_orig) |
| elif len(args) == 2: |
| in_file, out_file = args |
| try: |
| _ = getattr(in_file,'readline') |
| _ = getattr(out_file,'write') |
| except AttributeError: |
| ok = 0 |
| def _setup(out_file, args): |
| in_file, out_file = args |
| # Toss the 'begin mode filename' part.. not needed |
| _ = in_file.readline() |
| _out_file_orig = 1 |
| return (out_file,_out_file_orig) |
| elif len(args) == 1: |
| in_file = args[0] |
| try: |
| _ = getattr(in_file,'readline') |
| except AttributeError: |
| ok = 0 |
| def _setup(out_file, args): |
| import strop |
| in_file = args[0] |
| # open file as specified in uu file and |
| # assign out_file for later use |
| i = in_file.readline() |
| i = strop.strip(i) |
| if 'begin' != i[:5]: |
| raise IOError, 'input file not in UUencoded format' |
| [dummy, mode, filename] = strop.split(i) |
| mode = strop.atoi(mode, 8) |
| out_file = open(filename,'w',mode) |
| _out_file_orig = 0 |
| return (out_file,_out_file_orig) |
| if ok != 1: |
| raise SyntaxError, 'must be (filename, mode, in_file) or (in_file,out_file) or (in_file)' |
| out_file, _out_file_orig = _setup(out_file, args) |
| str = in_file.readline() |
| while len(str) > 0 and str != ' \n' and str != 'end\n': |
| out_file.write(_decode(str)) |
| str = in_file.readline() |
| if _out_file_orig == 0: |
| out_file.close() |
| del out_file |
| return None |
| |
| def test(): |
| import sys |
| if sys.argv[1:2] == ['-d']: |
| if sys.argv[2:]: |
| decode(open(sys.argv[2]), sys.stdout) |
| else: |
| decode(sys.stdin, sys.stdout) |
| elif sys.argv[1:2] == ['-e']: |
| if sys.argv[2:]: |
| file = sys.argv[2] |
| fp = open(file) |
| else: |
| file = '-' |
| fp = sys.stdin |
| encode(file, 0644, fp, sys.stdout) |
| else: |
| print 'usage: uu -d [file]; (to decode)' |
| print 'or: uu -e [file]; (to encode)' |
| sys.exit(2) |
| |
| if __name__ == '__main__': |
| test() |