home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / webclean / !!!python!!! / BeOpen-Python-2.0.exe / QUOPRI.PY < prev    next >
Encoding:
Python Source  |  2000-10-05  |  4.3 KB  |  151 lines

  1. #! /usr/bin/env python
  2.  
  3. """Conversions to/from quoted-printable transport encoding as per RFC-1521."""
  4.  
  5. # (Dec 1991 version).
  6.  
  7. ESCAPE = '='
  8. MAXLINESIZE = 76
  9. HEX = '0123456789ABCDEF'
  10.  
  11. def needsquoting(c, quotetabs):
  12.     """Decide whether a particular character needs to be quoted.
  13.  
  14.     The 'quotetabs' flag indicates whether tabs should be quoted."""
  15.     if c == '\t':
  16.         return not quotetabs
  17.     return c == ESCAPE or not(' ' <= c <= '~')
  18.  
  19. def quote(c):
  20.     """Quote a single character."""
  21.     i = ord(c)
  22.     return ESCAPE + HEX[i/16] + HEX[i%16]
  23.  
  24. def encode(input, output, quotetabs):
  25.     """Read 'input', apply quoted-printable encoding, and write to 'output'.
  26.  
  27.     'input' and 'output' are files with readline() and write() methods.
  28.     The 'quotetabs' flag indicates whether tabs should be quoted.
  29.     """
  30.     while 1:
  31.         line = input.readline()
  32.         if not line:
  33.             break
  34.         new = ''
  35.         last = line[-1:]
  36.         if last == '\n':
  37.             line = line[:-1]
  38.         else:
  39.             last = ''
  40.         prev = ''
  41.         for c in line:
  42.             if needsquoting(c, quotetabs):
  43.                 c = quote(c)
  44.             if len(new) + len(c) >= MAXLINESIZE:
  45.                 output.write(new + ESCAPE + '\n')
  46.                 new = ''
  47.             new = new + c
  48.             prev = c
  49.         if prev in (' ', '\t'):
  50.             output.write(new + ESCAPE + '\n\n')
  51.         else:
  52.             output.write(new + '\n')
  53.  
  54. def decode(input, output):
  55.     """Read 'input', apply quoted-printable decoding, and write to 'output'.
  56.  
  57.     'input' and 'output' are files with readline() and write() methods."""
  58.     new = ''
  59.     while 1:
  60.         line = input.readline()
  61.         if not line: break
  62.         i, n = 0, len(line)
  63.         if n > 0 and line[n-1] == '\n':
  64.             partial = 0; n = n-1
  65.             # Strip trailing whitespace
  66.             while n > 0 and line[n-1] in (' ', '\t'):
  67.                 n = n-1
  68.         else:
  69.             partial = 1
  70.         while i < n:
  71.             c = line[i]
  72.             if c <> ESCAPE:
  73.                 new = new + c; i = i+1
  74.             elif i+1 == n and not partial:
  75.                 partial = 1; break
  76.             elif i+1 < n and line[i+1] == ESCAPE:
  77.                 new = new + ESCAPE; i = i+2
  78.             elif i+2 < n and ishex(line[i+1]) and ishex(line[i+2]):
  79.                 new = new + chr(unhex(line[i+1:i+3])); i = i+3
  80.             else: # Bad escape sequence -- leave it in
  81.                 new = new + c; i = i+1
  82.         if not partial:
  83.             output.write(new + '\n')
  84.             new = ''
  85.     if new:
  86.         output.write(new)
  87.  
  88. def ishex(c):
  89.     """Return true if the character 'c' is a hexadecimal digit."""
  90.     return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F'
  91.  
  92. def unhex(s):
  93.     """Get the integer value of a hexadecimal number."""
  94.     bits = 0
  95.     for c in s:
  96.         if '0' <= c <= '9':
  97.             i = ord('0')
  98.         elif 'a' <= c <= 'f':
  99.             i = ord('a')-10
  100.         elif 'A' <= c <= 'F':
  101.             i = ord('A')-10
  102.         else:
  103.             break
  104.         bits = bits*16 + (ord(c) - i)
  105.     return bits
  106.  
  107. def test():
  108.     import sys
  109.     import getopt
  110.     try:
  111.         opts, args = getopt.getopt(sys.argv[1:], 'td')
  112.     except getopt.error, msg:
  113.         sys.stdout = sys.stderr
  114.         print msg
  115.         print "usage: quopri [-t | -d] [file] ..."
  116.         print "-t: quote tabs"
  117.         print "-d: decode; default encode"
  118.         sys.exit(2)
  119.     deco = 0
  120.     tabs = 0
  121.     for o, a in opts:
  122.         if o == '-t': tabs = 1
  123.         if o == '-d': deco = 1
  124.     if tabs and deco:
  125.         sys.stdout = sys.stderr
  126.         print "-t and -d are mutually exclusive"
  127.         sys.exit(2)
  128.     if not args: args = ['-']
  129.     sts = 0
  130.     for file in args:
  131.         if file == '-':
  132.             fp = sys.stdin
  133.         else:
  134.             try:
  135.                 fp = open(file)
  136.             except IOError, msg:
  137.                 sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
  138.                 sts = 1
  139.                 continue
  140.         if deco:
  141.             decode(fp, sys.stdout)
  142.         else:
  143.             encode(fp, sys.stdout, tabs)
  144.         if fp is not sys.stdin:
  145.             fp.close()
  146.     if sts:
  147.         sys.exit(sts)
  148.  
  149. if __name__ == '__main__':
  150.     test()
  151.