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