(root)/
Python-3.11.7/
Lib/
uu.py
       1  #! /usr/bin/env python3
       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], *, backtick=False)
      30  decode(in_file [, out_file, mode, quiet])
      31  """
      32  
      33  import binascii
      34  import os
      35  import sys
      36  import warnings
      37  
      38  warnings._deprecated(__name__, remove=(3, 13))
      39  
      40  __all__ = ["Error", "encode", "decode"]
      41  
      42  class ESC[4;38;5;81mError(ESC[4;38;5;149mException):
      43      pass
      44  
      45  def encode(in_file, out_file, name=None, mode=None, *, backtick=False):
      46      """Uuencode file"""
      47      #
      48      # If in_file is a pathname open it and change defaults
      49      #
      50      opened_files = []
      51      try:
      52          if in_file == '-':
      53              in_file = sys.stdin.buffer
      54          elif isinstance(in_file, str):
      55              if name is None:
      56                  name = os.path.basename(in_file)
      57              if mode is None:
      58                  try:
      59                      mode = os.stat(in_file).st_mode
      60                  except AttributeError:
      61                      pass
      62              in_file = open(in_file, 'rb')
      63              opened_files.append(in_file)
      64          #
      65          # Open out_file if it is a pathname
      66          #
      67          if out_file == '-':
      68              out_file = sys.stdout.buffer
      69          elif isinstance(out_file, str):
      70              out_file = open(out_file, 'wb')
      71              opened_files.append(out_file)
      72          #
      73          # Set defaults for name and mode
      74          #
      75          if name is None:
      76              name = '-'
      77          if mode is None:
      78              mode = 0o666
      79  
      80          #
      81          # Remove newline chars from name
      82          #
      83          name = name.replace('\n','\\n')
      84          name = name.replace('\r','\\r')
      85  
      86          #
      87          # Write the data
      88          #
      89          out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii"))
      90          data = in_file.read(45)
      91          while len(data) > 0:
      92              out_file.write(binascii.b2a_uu(data, backtick=backtick))
      93              data = in_file.read(45)
      94          if backtick:
      95              out_file.write(b'`\nend\n')
      96          else:
      97              out_file.write(b' \nend\n')
      98      finally:
      99          for f in opened_files:
     100              f.close()
     101  
     102  
     103  def decode(in_file, out_file=None, mode=None, quiet=False):
     104      """Decode uuencoded file"""
     105      #
     106      # Open the input file, if needed.
     107      #
     108      opened_files = []
     109      if in_file == '-':
     110          in_file = sys.stdin.buffer
     111      elif isinstance(in_file, str):
     112          in_file = open(in_file, 'rb')
     113          opened_files.append(in_file)
     114  
     115      try:
     116          #
     117          # Read until a begin is encountered or we've exhausted the file
     118          #
     119          while True:
     120              hdr = in_file.readline()
     121              if not hdr:
     122                  raise Error('No valid begin line found in input file')
     123              if not hdr.startswith(b'begin'):
     124                  continue
     125              hdrfields = hdr.split(b' ', 2)
     126              if len(hdrfields) == 3 and hdrfields[0] == b'begin':
     127                  try:
     128                      int(hdrfields[1], 8)
     129                      break
     130                  except ValueError:
     131                      pass
     132          if out_file is None:
     133              # If the filename isn't ASCII, what's up with that?!?
     134              out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
     135              if os.path.exists(out_file):
     136                  raise Error(f'Cannot overwrite existing file: {out_file}')
     137              if (out_file.startswith(os.sep) or
     138                  f'..{os.sep}' in out_file or (
     139                      os.altsep and
     140                      (out_file.startswith(os.altsep) or
     141                       f'..{os.altsep}' in out_file))
     142                 ):
     143                  raise Error(f'Refusing to write to {out_file} due to directory traversal')
     144          if mode is None:
     145              mode = int(hdrfields[1], 8)
     146          #
     147          # Open the output file
     148          #
     149          if out_file == '-':
     150              out_file = sys.stdout.buffer
     151          elif isinstance(out_file, str):
     152              fp = open(out_file, 'wb')
     153              os.chmod(out_file, mode)
     154              out_file = fp
     155              opened_files.append(out_file)
     156          #
     157          # Main decoding loop
     158          #
     159          s = in_file.readline()
     160          while s and s.strip(b' \t\r\n\f') != b'end':
     161              try:
     162                  data = binascii.a2b_uu(s)
     163              except binascii.Error as v:
     164                  # Workaround for broken uuencoders by /Fredrik Lundh
     165                  nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
     166                  data = binascii.a2b_uu(s[:nbytes])
     167                  if not quiet:
     168                      sys.stderr.write("Warning: %s\n" % v)
     169              out_file.write(data)
     170              s = in_file.readline()
     171          if not s:
     172              raise Error('Truncated input file')
     173      finally:
     174          for f in opened_files:
     175              f.close()
     176  
     177  def test():
     178      """uuencode/uudecode main program"""
     179  
     180      import optparse
     181      parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
     182      parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
     183      parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
     184  
     185      (options, args) = parser.parse_args()
     186      if len(args) > 2:
     187          parser.error('incorrect number of arguments')
     188          sys.exit(1)
     189  
     190      # Use the binary streams underlying stdin/stdout
     191      input = sys.stdin.buffer
     192      output = sys.stdout.buffer
     193      if len(args) > 0:
     194          input = args[0]
     195      if len(args) > 1:
     196          output = args[1]
     197  
     198      if options.decode:
     199          if options.text:
     200              if isinstance(output, str):
     201                  output = open(output, 'wb')
     202              else:
     203                  print(sys.argv[0], ': cannot do -t to stdout')
     204                  sys.exit(1)
     205          decode(input, output)
     206      else:
     207          if options.text:
     208              if isinstance(input, str):
     209                  input = open(input, 'rb')
     210              else:
     211                  print(sys.argv[0], ': cannot do -t from stdin')
     212                  sys.exit(1)
     213          encode(input, output)
     214  
     215  if __name__ == '__main__':
     216      test()