Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | #! /usr/bin/env python |
2 | ||
3 | # Copyright 1994 by Lance Ellinghouse | |
4 | # Cathedral City, California Republic, United States of America. | |
5 | # All Rights Reserved | |
6 | # Permission to use, copy, modify, and distribute this software and its | |
7 | # documentation for any purpose and without fee is hereby granted, | |
8 | # provided that the above copyright notice appear in all copies and that | |
9 | # both that copyright notice and this permission notice appear in | |
10 | # supporting documentation, and that the name of Lance Ellinghouse | |
11 | # not be used in advertising or publicity pertaining to distribution | |
12 | # of the software without specific, written prior permission. | |
13 | # LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO | |
14 | # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
15 | # FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE | |
16 | # FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
17 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
18 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
19 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
20 | # | |
21 | # Modified by Jack Jansen, CWI, July 1995: | |
22 | # - Use binascii module to do the actual line-by-line conversion | |
23 | # between ascii and binary. This results in a 1000-fold speedup. The C | |
24 | # version is still 5 times faster, though. | |
25 | # - Arguments more compliant with python standard | |
26 | ||
27 | """Implementation of the UUencode and UUdecode functions. | |
28 | ||
29 | encode(in_file, out_file [,name, mode]) | |
30 | decode(in_file [, out_file, mode]) | |
31 | """ | |
32 | ||
33 | import binascii | |
34 | import os | |
35 | import sys | |
36 | from types import StringType | |
37 | ||
38 | __all__ = ["Error", "encode", "decode"] | |
39 | ||
40 | class Error(Exception): | |
41 | pass | |
42 | ||
43 | def encode(in_file, out_file, name=None, mode=None): | |
44 | """Uuencode file""" | |
45 | # | |
46 | # If in_file is a pathname open it and change defaults | |
47 | # | |
48 | if in_file == '-': | |
49 | in_file = sys.stdin | |
50 | elif isinstance(in_file, StringType): | |
51 | if name is None: | |
52 | name = os.path.basename(in_file) | |
53 | if mode is None: | |
54 | try: | |
55 | mode = os.stat(in_file).st_mode | |
56 | except AttributeError: | |
57 | pass | |
58 | in_file = open(in_file, 'rb') | |
59 | # | |
60 | # Open out_file if it is a pathname | |
61 | # | |
62 | if out_file == '-': | |
63 | out_file = sys.stdout | |
64 | elif isinstance(out_file, StringType): | |
65 | out_file = open(out_file, 'w') | |
66 | # | |
67 | # Set defaults for name and mode | |
68 | # | |
69 | if name is None: | |
70 | name = '-' | |
71 | if mode is None: | |
72 | mode = 0666 | |
73 | # | |
74 | # Write the data | |
75 | # | |
76 | out_file.write('begin %o %s\n' % ((mode&0777),name)) | |
77 | str = in_file.read(45) | |
78 | while len(str) > 0: | |
79 | out_file.write(binascii.b2a_uu(str)) | |
80 | str = in_file.read(45) | |
81 | out_file.write(' \nend\n') | |
82 | ||
83 | ||
84 | def decode(in_file, out_file=None, mode=None, quiet=0): | |
85 | """Decode uuencoded file""" | |
86 | # | |
87 | # Open the input file, if needed. | |
88 | # | |
89 | if in_file == '-': | |
90 | in_file = sys.stdin | |
91 | elif isinstance(in_file, StringType): | |
92 | in_file = open(in_file) | |
93 | # | |
94 | # Read until a begin is encountered or we've exhausted the file | |
95 | # | |
96 | while 1: | |
97 | hdr = in_file.readline() | |
98 | if not hdr: | |
99 | raise Error, 'No valid begin line found in input file' | |
100 | if hdr[:5] != 'begin': | |
101 | continue | |
102 | hdrfields = hdr.split(" ", 2) | |
103 | if len(hdrfields) == 3 and hdrfields[0] == 'begin': | |
104 | try: | |
105 | int(hdrfields[1], 8) | |
106 | break | |
107 | except ValueError: | |
108 | pass | |
109 | if out_file is None: | |
110 | out_file = hdrfields[2].rstrip() | |
111 | if os.path.exists(out_file): | |
112 | raise Error, 'Cannot overwrite existing file: %s' % out_file | |
113 | if mode is None: | |
114 | mode = int(hdrfields[1], 8) | |
115 | # | |
116 | # Open the output file | |
117 | # | |
118 | if out_file == '-': | |
119 | out_file = sys.stdout | |
120 | elif isinstance(out_file, StringType): | |
121 | fp = open(out_file, 'wb') | |
122 | try: | |
123 | os.path.chmod(out_file, mode) | |
124 | except AttributeError: | |
125 | pass | |
126 | out_file = fp | |
127 | # | |
128 | # Main decoding loop | |
129 | # | |
130 | s = in_file.readline() | |
131 | while s and s.strip() != 'end': | |
132 | try: | |
133 | data = binascii.a2b_uu(s) | |
134 | except binascii.Error, v: | |
135 | # Workaround for broken uuencoders by /Fredrik Lundh | |
136 | nbytes = (((ord(s[0])-32) & 63) * 4 + 5) / 3 | |
137 | data = binascii.a2b_uu(s[:nbytes]) | |
138 | if not quiet: | |
139 | sys.stderr.write("Warning: %s\n" % str(v)) | |
140 | out_file.write(data) | |
141 | s = in_file.readline() | |
142 | if not s: | |
143 | raise Error, 'Truncated input file' | |
144 | ||
145 | def test(): | |
146 | """uuencode/uudecode main program""" | |
147 | import getopt | |
148 | ||
149 | dopt = 0 | |
150 | topt = 0 | |
151 | input = sys.stdin | |
152 | output = sys.stdout | |
153 | ok = 1 | |
154 | try: | |
155 | optlist, args = getopt.getopt(sys.argv[1:], 'dt') | |
156 | except getopt.error: | |
157 | ok = 0 | |
158 | if not ok or len(args) > 2: | |
159 | print 'Usage:', sys.argv[0], '[-d] [-t] [input [output]]' | |
160 | print ' -d: Decode (in stead of encode)' | |
161 | print ' -t: data is text, encoded format unix-compatible text' | |
162 | sys.exit(1) | |
163 | ||
164 | for o, a in optlist: | |
165 | if o == '-d': dopt = 1 | |
166 | if o == '-t': topt = 1 | |
167 | ||
168 | if len(args) > 0: | |
169 | input = args[0] | |
170 | if len(args) > 1: | |
171 | output = args[1] | |
172 | ||
173 | if dopt: | |
174 | if topt: | |
175 | if isinstance(output, StringType): | |
176 | output = open(output, 'w') | |
177 | else: | |
178 | print sys.argv[0], ': cannot do -t to stdout' | |
179 | sys.exit(1) | |
180 | decode(input, output) | |
181 | else: | |
182 | if topt: | |
183 | if isinstance(input, StringType): | |
184 | input = open(input, 'r') | |
185 | else: | |
186 | print sys.argv[0], ': cannot do -t from stdin' | |
187 | sys.exit(1) | |
188 | encode(input, output) | |
189 | ||
190 | if __name__ == '__main__': | |
191 | test() |