svn-gvsig-desktop / tags / v1_1_Build_1013 / extensions / extScripting / scripts / jython / Lib / quopri.py @ 13521
History | View | Annotate | Download (4.17 KB)
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 |
__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() |