Skip to content

Commit 9604e66

Browse files
committed
Oops. I copied a slightly older version of the email package from the sandbox.
This should restore the email package in the py3k branch to exactly what's in the sandbox. This wipes out 1-2 fixes made post-copy, which I'll re-apply shortly.
1 parent 2c440a1 commit 9604e66

8 files changed

Lines changed: 536 additions & 474 deletions

File tree

Lib/email/base64mime.py

Lines changed: 27 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@
2525
"""
2626

2727
__all__ = [
28-
'base64_len',
2928
'body_decode',
3029
'body_encode',
3130
'decode',
3231
'decodestring',
3332
'encode',
3433
'encodestring',
3534
'header_encode',
35+
'header_length',
3636
]
3737

3838
import re
3939

40+
from base64 import b64encode
4041
from binascii import b2a_base64, a2b_base64
41-
from email.utils import fix_eols
4242

4343
CRLF = '\r\n'
4444
NL = '\n'
@@ -50,96 +50,44 @@
5050

5151

5252
# Helpers
53-
def base64_len(s):
53+
def header_length(bytearray):
5454
"""Return the length of s when it is encoded with base64."""
55-
groups_of_3, leftover = divmod(len(s), 3)
55+
groups_of_3, leftover = divmod(len(bytearray), 3)
5656
# 4 bytes out for each 3 bytes (or nonzero fraction thereof) in.
57-
# Thanks, Tim!
5857
n = groups_of_3 * 4
5958
if leftover:
6059
n += 4
6160
return n
6261

6362

6463

65-
def header_encode(header, charset='iso-8859-1', keep_eols=False,
66-
maxlinelen=76, eol=NL):
64+
def header_encode(header_bytes, charset='iso-8859-1'):
6765
"""Encode a single header line with Base64 encoding in a given charset.
6866
69-
Defined in RFC 2045, this Base64 encoding is identical to normal Base64
70-
encoding, except that each line must be intelligently wrapped (respecting
71-
the Base64 encoding), and subsequent lines must start with a space.
72-
7367
charset names the character set to use to encode the header. It defaults
74-
to iso-8859-1.
75-
76-
End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted
77-
to the canonical email line separator \\r\\n unless the keep_eols
78-
parameter is True (the default is False).
79-
80-
Each line of the header will be terminated in the value of eol, which
81-
defaults to "\\n". Set this to "\\r\\n" if you are using the result of
82-
this function directly in email.
83-
84-
The resulting string will be in the form:
85-
86-
"=?charset?b?WW/5ciBtYXp66XLrIHf8eiBhIGhhbXBzdGHuciBBIFlv+XIgbWF6euly?=\\n
87-
=?charset?b?6yB3/HogYSBoYW1wc3Rh7nIgQkMgWW/5ciBtYXp66XLrIHf8eiBhIGhh?="
88-
89-
with each line wrapped at, at most, maxlinelen characters (defaults to 76
90-
characters).
68+
to iso-8859-1. Base64 encoding is defined in RFC 2045.
9169
"""
9270
# Return empty headers unchanged
93-
if not header:
94-
return header
95-
96-
if not keep_eols:
97-
header = fix_eols(header)
98-
99-
# Base64 encode each line, in encoded chunks no greater than maxlinelen in
100-
# length, after the RFC chrome is added in.
101-
base64ed = []
102-
max_encoded = maxlinelen - len(charset) - MISC_LEN
103-
max_unencoded = max_encoded * 3 // 4
104-
105-
for i in range(0, len(header), max_unencoded):
106-
base64ed.append(b2a_base64(header[i:i+max_unencoded]))
107-
108-
# Now add the RFC chrome to each encoded chunk
109-
lines = []
110-
for line in base64ed:
111-
# Ignore the last character of each line if it is a newline
112-
if line[-1] == ord(NL):
113-
line = line[:-1]
114-
# Add the chrome
115-
lines.append('=?%s?b?%s?=' % (charset, line))
116-
# Glue the lines together and return it. BAW: should we be able to
117-
# specify the leading whitespace in the joiner?
118-
joiner = eol + ' '
119-
return joiner.join(lines)
71+
if not header_bytes:
72+
return str(header_bytes)
73+
encoded = b64encode(header_bytes)
74+
return '=?%s?b?%s?=' % (charset, encoded)
12075

12176

12277

123-
def encode(s, binary=True, maxlinelen=76, eol=NL):
78+
def body_encode(s, maxlinelen=76, eol=NL):
12479
"""Encode a string with base64.
12580
12681
Each line will be wrapped at, at most, maxlinelen characters (defaults to
12782
76 characters).
12883
129-
If binary is False, end-of-line characters will be converted to the
130-
canonical email end-of-line sequence \\r\\n. Otherwise they will be left
131-
verbatim (this is the default).
132-
13384
Each line of encoded text will end with eol, which defaults to "\\n". Set
13485
this to "\r\n" if you will be using the result of this function directly
13586
in an email.
13687
"""
13788
if not s:
13889
return s
13990

140-
if not binary:
141-
s = fix_eols(s)
142-
14391
encvec = []
14492
max_unencoded = maxlinelen * 3 // 4
14593
for i in range(0, len(s), max_unencoded):
@@ -152,25 +100,26 @@ def encode(s, binary=True, maxlinelen=76, eol=NL):
152100
return EMPTYSTRING.join(encvec)
153101

154102

155-
# For convenience and backwards compatibility w/ standard base64 module
156-
body_encode = encode
157-
encodestring = encode
158-
159-
160103

161-
def decode(string):
104+
def decode(s, convert_eols=False):
162105
"""Decode a raw base64 string, returning a bytes object.
163106
164-
This function does not parse a full MIME header value encoded with base64
165-
(like =?iso-8895-1?b?bmloISBuaWgh?=) -- use the high level
166-
email.Header class for that functionality.
107+
If convert_eols is set to a string value, all canonical email linefeeds,
108+
e.g. "\\r\\n", in the decoded text will be converted to the value of
109+
convert_eols. os.linesep is a good choice for convert_eols if you are
110+
decoding a text attachment.
111+
112+
This function does not parse a full MIME header value encoded with
113+
base64 (like =?iso-8895-1?b?bmloISBuaWgh?=) -- please use the high
114+
level email.Header class for that functionality.
167115
"""
168-
if not string:
169-
return bytes()
170-
elif isinstance(string, str):
171-
return a2b_base64(string.encode('raw-unicode-escape'))
172-
else:
173-
return a2b_base64(string)
116+
if not s:
117+
return s
118+
119+
dec = a2b_base64(s)
120+
if convert_eols:
121+
return dec.replace(CRLF, convert_eols)
122+
return dec
174123

175124

176125
# For convenience and backwards compatibility w/ standard base64 module

0 commit comments

Comments
 (0)