|
| 1 | +# uu.py |
| 2 | +# Copyright 1994 by Lance Ellinghouse |
| 3 | +# Cathedral City, California Republic, United States of America. |
| 4 | +# All Rights Reserved |
| 5 | +# Permission to use, copy, modify, and distribute this software and its |
| 6 | +# documentation for any purpose and without fee is hereby granted, |
| 7 | +# provided that the above copyright notice appear in all copies and that |
| 8 | +# both that copyright notice and this permission notice appear in |
| 9 | +# supporting documentation, and that the name of Lance Ellinghouse |
| 10 | +# not be used in advertising or publicity pertaining to distribution |
| 11 | +# of the software without specific, written prior permission. |
| 12 | +# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| 13 | +# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 14 | +# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE |
| 15 | +# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 16 | +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 17 | +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| 18 | +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 19 | + |
| 20 | +# This file implements the UUencode and UUdecode functions. |
| 21 | + |
| 22 | +# encode(filename, mode, in_file, out_file) |
| 23 | +# decode(filename, mode, in_file) |
| 24 | +# decode(in_file, out_file) |
| 25 | +# decode(in_file) |
| 26 | + |
| 27 | +# encode a single char to always be printable |
| 28 | +def _ENC(ch): |
| 29 | + if type(ch) == type(''): |
| 30 | + a = ch[:1] # only 1 char |
| 31 | + if len(a) == 0: |
| 32 | + raise ValueError, 'need to pass in at least 1 char' |
| 33 | + a = ord(a) |
| 34 | + elif type(ch) == type(0): |
| 35 | + a = ch |
| 36 | + else: |
| 37 | + raise TypeError, 'must pass in an integer or single character' |
| 38 | + return chr((a & 077) + ord(' ')) |
| 39 | + |
| 40 | +# input 3 chars, output 4 encoded chars |
| 41 | +def _outenc(str): |
| 42 | + if len(str) > 3: |
| 43 | + raise ValueError, 'can only accept strings of 3 chars' |
| 44 | + p0, p1, p2 = 0, 0, 0 |
| 45 | + if len(str) > 2: |
| 46 | + p2 = ord(str[2]) |
| 47 | + if len(str) > 1: |
| 48 | + p1 = ord(str[1]) |
| 49 | + if len(str) > 0: |
| 50 | + p0 = ord(str[0]) |
| 51 | + c1 = p0 >> 2 |
| 52 | + c2 = (p0 << 4) & 060 | (p1 >> 4) & 017 |
| 53 | + c3 = (p1 << 2) & 074 | (p2 >> 6) & 03 |
| 54 | + c4 = p2 & 077 |
| 55 | + rtn = _ENC(c1) |
| 56 | + rtn = rtn + _ENC(c2) |
| 57 | + rtn = rtn + _ENC(c3) |
| 58 | + rtn = rtn + _ENC(c4) |
| 59 | + return rtn |
| 60 | + |
| 61 | +# pass in 45 bytes max, returns 62 bytes encoded |
| 62 | +def _encode(str): |
| 63 | + if len(str) > 45: |
| 64 | + raise ValueError, 'cannot handle more than 45 chars at once' |
| 65 | + length = len(str) |
| 66 | + rtn = _ENC(length) |
| 67 | + i = 0 |
| 68 | + while i < length: |
| 69 | + rtn = rtn + _outenc(str[i:(i+3)]) |
| 70 | + i = i + 3 |
| 71 | + rtn = rtn + '\n' |
| 72 | + return rtn |
| 73 | + |
| 74 | +# encode a fileobject and write out to a file object |
| 75 | +def encode(filename, mode, in_file, out_file): |
| 76 | + out_file.write('begin %o %s\n' % ((mode&0777),filename)) |
| 77 | + str = in_file.read(45) |
| 78 | + while len(str) > 0: |
| 79 | + out_file.write(_encode(str)) |
| 80 | + str = in_file.read(45) |
| 81 | + out_file.write(' \nend\n') |
| 82 | + return None |
| 83 | + |
| 84 | +# def decode a single char from printable to possibly non-printable |
| 85 | +def _DEC(ch): |
| 86 | + if type(ch) != type('') or len(ch) != 1: |
| 87 | + raise ValueError, 'need to pass in a single char' |
| 88 | + a = ord(ch[0:1]) |
| 89 | + return (a - ord(' ')) |
| 90 | + |
| 91 | +# input 4 chars encoded, output 3 chars unencoded |
| 92 | +def _outdec(str): |
| 93 | + if len(str) > 4: |
| 94 | + raise ValueError, 'can only accept strings of 4 chars' |
| 95 | + p0, p1, p2, p3 = 0, 0, 0, 0 |
| 96 | + if len(str) > 3: |
| 97 | + p3 = _DEC(str[3]) |
| 98 | + if len(str) > 2: |
| 99 | + p2 = _DEC(str[2]) |
| 100 | + if len(str) > 1: |
| 101 | + p1 = _DEC(str[1]) |
| 102 | + if len(str) > 0: |
| 103 | + p0 = _DEC(str[0]) |
| 104 | + c1 = p0 << 2 | (p1 & 060) >> 4 |
| 105 | + c2 = (p1 & 017) << 4 | (p2 & 074) >> 2 |
| 106 | + c3 = (p2 & 03) << 6 | (p3 & 077) |
| 107 | + rtn = chr(c1) |
| 108 | + rtn = rtn + chr(c2) |
| 109 | + rtn = rtn + chr(c3) |
| 110 | + return rtn |
| 111 | + |
| 112 | +# pass in 62 bytes and return 45 bytes unencoded |
| 113 | +def _decode(str): |
| 114 | + if len(str) > 62: |
| 115 | + raise ValueError, 'cannot handle more than 62 chars at once' |
| 116 | + length = _DEC(str[0]) |
| 117 | + i = 1 |
| 118 | + rtn = '' |
| 119 | + while len(rtn) < length: |
| 120 | + rtn = rtn + _outdec(str[i:(i+4)]) |
| 121 | + i = i + 4 |
| 122 | + return rtn[0:length] |
| 123 | + |
| 124 | +# decode(filename, mode, in_file) |
| 125 | +# decode(in_file, out_file) |
| 126 | +# decode(in_file) |
| 127 | +def decode(*args): |
| 128 | + ok = 1 |
| 129 | + _setup = None |
| 130 | + out_file = None |
| 131 | + if len(args) == 3: |
| 132 | + filename, mode, in_file = args |
| 133 | + if type(filename) != type(''): |
| 134 | + ok = 0 |
| 135 | + if type(mode) != type(0): |
| 136 | + ok = 0 |
| 137 | + try: |
| 138 | + _ = getattr(in_file,'readline') |
| 139 | + except AttributeError: |
| 140 | + ok = 0 |
| 141 | + def _setup(out_file,args): |
| 142 | + filename, mode, in_file = args |
| 143 | + # open file as specified and assign out_file for later use |
| 144 | + out_file = open(filename,'w',mode) |
| 145 | + _out_file_orig = 0 |
| 146 | + _ = in_file.readline() |
| 147 | + return (out_file,_out_file_orig) |
| 148 | + elif len(args) == 2: |
| 149 | + in_file, out_file = args |
| 150 | + try: |
| 151 | + _ = getattr(in_file,'readline') |
| 152 | + _ = getattr(out_file,'write') |
| 153 | + except AttributeError: |
| 154 | + ok = 0 |
| 155 | + def _setup(out_file, args): |
| 156 | + in_file, out_file = args |
| 157 | + # Toss the 'begin mode filename' part.. not needed |
| 158 | + _ = in_file.readline() |
| 159 | + _out_file_orig = 1 |
| 160 | + return (out_file,_out_file_orig) |
| 161 | + elif len(args) == 1: |
| 162 | + in_file = args[0] |
| 163 | + try: |
| 164 | + _ = getattr(in_file,'readline') |
| 165 | + except AttributeError: |
| 166 | + ok = 0 |
| 167 | + def _setup(out_file, args): |
| 168 | + import strop |
| 169 | + in_file = args[0] |
| 170 | + # open file as specified in uu file and |
| 171 | + # assign out_file for later use |
| 172 | + i = in_file.readline() |
| 173 | + i = strop.strip(i) |
| 174 | + if 'begin' != i[:5]: |
| 175 | + raise IOError, 'input file not in UUencoded format' |
| 176 | + [dummy, mode, filename] = strop.split(i) |
| 177 | + mode = strop.atoi(mode, 8) |
| 178 | + out_file = open(filename,'w',mode) |
| 179 | + _out_file_orig = 0 |
| 180 | + return (out_file,_out_file_orig) |
| 181 | + if ok != 1: |
| 182 | + raise SyntaxError, 'must be (filename, mode, in_file) or (in_file,out_file) or (in_file)' |
| 183 | + out_file, _out_file_orig = _setup(out_file, args) |
| 184 | + str = in_file.readline() |
| 185 | + while len(str) > 0 and str != ' \n' and str != 'end\n': |
| 186 | + out_file.write(_decode(str)) |
| 187 | + str = in_file.readline() |
| 188 | + if _out_file_orig == 0: |
| 189 | + out_file.close() |
| 190 | + del out_file |
| 191 | + return None |
| 192 | + |
| 193 | +def test(): |
| 194 | + import sys |
| 195 | + if sys.argv[1:2] == ['-d']: |
| 196 | + if sys.argv[2:]: |
| 197 | + decode(open(sys.argv[2]), sys.stdout) |
| 198 | + else: |
| 199 | + decode(sys.stdin, sys.stdout) |
| 200 | + elif sys.argv[1:2] == ['-e']: |
| 201 | + if sys.argv[2:]: |
| 202 | + file = sys.argv[2] |
| 203 | + fp = open(file) |
| 204 | + else: |
| 205 | + file = '-' |
| 206 | + fp = sys.stdin |
| 207 | + encode(file, 0644, fp, sys.stdout) |
| 208 | + else: |
| 209 | + print 'usage: uu -d [file]; (to decode)' |
| 210 | + print 'or: uu -e [file]; (to encode)' |
| 211 | + sys.exit(2) |
| 212 | + |
| 213 | +if __name__ == '__main__': |
| 214 | + test() |
0 commit comments