PageRenderTime 46ms CodeModel.GetById 24ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/uu.py

http://unladen-swallow.googlecode.com/
Python | 186 lines | 115 code | 14 blank | 57 comment | 35 complexity | be218390eea294156c164df7165b249a MD5 | raw file
  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
 29encode(in_file, out_file [,name, mode])
 30decode(in_file [, out_file, mode])
 31"""
 32
 33import binascii
 34import os
 35import sys
 36
 37__all__ = ["Error", "encode", "decode"]
 38
 39class Error(Exception):
 40    pass
 41
 42def encode(in_file, out_file, name=None, mode=None):
 43    """Uuencode file"""
 44    #
 45    # If in_file is a pathname open it and change defaults
 46    #
 47    if in_file == '-':
 48        in_file = sys.stdin
 49    elif isinstance(in_file, basestring):
 50        if name is None:
 51            name = os.path.basename(in_file)
 52        if mode is None:
 53            try:
 54                mode = os.stat(in_file).st_mode
 55            except AttributeError:
 56                pass
 57        in_file = open(in_file, 'rb')
 58    #
 59    # Open out_file if it is a pathname
 60    #
 61    if out_file == '-':
 62        out_file = sys.stdout
 63    elif isinstance(out_file, basestring):
 64        out_file = open(out_file, 'w')
 65    #
 66    # Set defaults for name and mode
 67    #
 68    if name is None:
 69        name = '-'
 70    if mode is None:
 71        mode = 0666
 72    #
 73    # Write the data
 74    #
 75    out_file.write('begin %o %s\n' % ((mode&0777),name))
 76    data = in_file.read(45)
 77    while len(data) > 0:
 78        out_file.write(binascii.b2a_uu(data))
 79        data = in_file.read(45)
 80    out_file.write(' \nend\n')
 81
 82
 83def decode(in_file, out_file=None, mode=None, quiet=0):
 84    """Decode uuencoded file"""
 85    #
 86    # Open the input file, if needed.
 87    #
 88    if in_file == '-':
 89        in_file = sys.stdin
 90    elif isinstance(in_file, basestring):
 91        in_file = open(in_file)
 92    #
 93    # Read until a begin is encountered or we've exhausted the file
 94    #
 95    while True:
 96        hdr = in_file.readline()
 97        if not hdr:
 98            raise Error('No valid begin line found in input file')
 99        if not hdr.startswith('begin'):
100            continue
101        hdrfields = hdr.split(' ', 2)
102        if len(hdrfields) == 3 and hdrfields[0] == 'begin':
103            try:
104                int(hdrfields[1], 8)
105                break
106            except ValueError:
107                pass
108    if out_file is None:
109        out_file = hdrfields[2].rstrip()
110        if os.path.exists(out_file):
111            raise Error('Cannot overwrite existing file: %s' % out_file)
112    if mode is None:
113        mode = int(hdrfields[1], 8)
114    #
115    # Open the output file
116    #
117    opened = False
118    if out_file == '-':
119        out_file = sys.stdout
120    elif isinstance(out_file, basestring):
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        opened = True
128    #
129    # Main decoding loop
130    #
131    s = in_file.readline()
132    while s and s.strip() != 'end':
133        try:
134            data = binascii.a2b_uu(s)
135        except binascii.Error, v:
136            # Workaround for broken uuencoders by /Fredrik Lundh
137            nbytes = (((ord(s[0])-32) & 63) * 4 + 5) // 3
138            data = binascii.a2b_uu(s[:nbytes])
139            if not quiet:
140                sys.stderr.write("Warning: %s\n" % v)
141        out_file.write(data)
142        s = in_file.readline()
143    if not s:
144        raise Error('Truncated input file')
145    if opened:
146        out_file.close()
147
148def test():
149    """uuencode/uudecode main program"""
150
151    import optparse
152    parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
153    parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
154    parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
155
156    (options, args) = parser.parse_args()
157    if len(args) > 2:
158        parser.error('incorrect number of arguments')
159        sys.exit(1)
160
161    input = sys.stdin
162    output = sys.stdout
163    if len(args) > 0:
164        input = args[0]
165    if len(args) > 1:
166        output = args[1]
167
168    if options.decode:
169        if options.text:
170            if isinstance(output, basestring):
171                output = open(output, 'w')
172            else:
173                print sys.argv[0], ': cannot do -t to stdout'
174                sys.exit(1)
175        decode(input, output)
176    else:
177        if options.text:
178            if isinstance(input, basestring):
179                input = open(input, 'r')
180            else:
181                print sys.argv[0], ': cannot do -t from stdin'
182                sys.exit(1)
183        encode(input, output)
184
185if __name__ == '__main__':
186    test()