3 """Conversions to/from quoted-printable transport encoding as per RFC-1521."""
9 HEX
= '0123456789ABCDEF'
11 def needsquoting(c
, quotetabs
):
12 """Decide whether a particular character needs to be quoted.
14 The 'quotetabs' flag indicates whether tabs should be quoted."""
17 return c
== ESCAPE
or not(' ' <= c
<= '~')
20 """Quote a single character."""
25 return ESCAPE
+ HEX
[i
/16] + HEX
[i
%16]
27 def encode(input, output
, quotetabs
):
28 """Read 'input', apply quoted-printable encoding, and write to 'output'.
30 'input' and 'output' are files with readline() and write() methods.
31 The 'quotetabs' flag indicates whether tabs should be quoted."""
33 line
= input.readline()
37 if last
== '\n': line
= line
[:-1]
41 if needsquoting(c
, quotetabs
):
43 if len(new
) + len(c
) >= MAXLINESIZE
:
44 output
.write(new
+ ESCAPE
+ '\n')
48 if prev
in (' ', '\t'):
49 output
.write(new
+ ESCAPE
+ '\n\n')
51 output
.write(new
+ '\n')
53 def decode(input, output
):
54 """Read 'input', apply quoted-printable decoding, and write to 'output'.
56 'input' and 'output' are files with readline() and write() methods."""
59 line
= input.readline()
62 if n
> 0 and line
[n
-1] == '\n':
64 # Strip trailing whitespace
65 while n
> 0 and line
[n
-1] in (' ', '\t'):
72 new
= new
+ c
; i
= i
+1
73 elif i
+1 == n
and not partial
:
75 elif i
+1 < n
and line
[i
+1] == ESCAPE
:
76 new
= new
+ ESCAPE
; i
= i
+2
77 elif i
+2 < n
and ishex(line
[i
+1]) and ishex(line
[i
+2]):
78 new
= new
+ chr(unhex(line
[i
+1:i
+3])); i
= i
+3
79 else: # Bad escape sequence -- leave it in
80 new
= new
+ c
; i
= i
+1
82 output
.write(new
+ '\n')
88 """Return true if the character 'c' is a hexadecimal digit."""
89 return '0' <= c
<= '9' or 'a' <= c
<= 'f' or 'A' <= c
<= 'F'
92 """Get the integer value of a hexadecimal number."""
103 bits
= bits
*16 + (ord(c
) - i
)
110 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'td')
111 except getopt
.error
, msg
:
112 sys
.stdout
= sys
.stderr
114 print "usage: quopri [-t | -d] [file] ..."
115 print "-t: quote tabs"
116 print "-d: decode; default encode"
121 if o
== '-t': tabs
= 1
122 if o
== '-d': deco
= 1
124 sys
.stdout
= sys
.stderr
125 print "-t and -d are mutually exclusive"
127 if not args
: args
= ['-']
136 sys
.stderr
.write("%s: can't open (%s)\n" % (file, msg
))
140 decode(fp
, sys
.stdout
)
142 encode(fp
, sys
.stdout
, tabs
)
143 if fp
is not sys
.stdin
:
148 if __name__
== '__main__':