annotate Lib/email/header.py @ 79691:05c8928362ee

Merge __next__ method link fixes with 3.3.
author Ezio Melotti <ezio.melotti@gmail.com>
date Fri, 12 Oct 2012 13:46:37 +0300
parents 8c03fe231877
children 15a391919deb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
1 # Copyright (C) 2002-2007 Python Software Foundation
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
2 # Author: Ben Gertzfield, Barry Warsaw
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
3 # Contact: email-sig@python.org
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
4
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
5 """Header encoding and decoding functionality."""
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
6
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
7 __all__ = [
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
8 'Header',
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
9 'decode_header',
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
10 'make_header',
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
11 ]
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
12
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
13 import re
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
14 import binascii
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
15
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
16 import email.quoprimime
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
17 import email.base64mime
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
18
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
19 from email.errors import HeaderParseError
67447
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
20 from email import charset as _charset
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
21 Charset = _charset.Charset
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
22
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
23 NL = '\n'
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
24 SPACE = ' '
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
25 BSPACE = b' '
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
26 SPACE8 = ' ' * 8
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
27 EMPTYSTRING = ''
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
28 MAXLINELEN = 78
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
29 FWS = ' \t'
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
30
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
31 USASCII = Charset('us-ascii')
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
32 UTF8 = Charset('utf-8')
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
33
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
34 # Match encoded-word strings in the form =?charset?q?Hello_World?=
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
35 ecre = re.compile(r'''
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
36 =\? # literal =?
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
37 (?P<charset>[^?]*?) # non-greedy up to the next ? is the charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
38 \? # literal ?
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
39 (?P<encoding>[qb]) # either a "q" or a "b", case insensitive
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
40 \? # literal ?
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
41 (?P<encoded>.*?) # non-greedy up to the next ?= is the encoded string
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
42 \?= # literal ?=
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
43 ''', re.VERBOSE | re.IGNORECASE | re.MULTILINE)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
44
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
45 # Field name regexp, including trailing colon, but not separating whitespace,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
46 # according to RFC 2822. Character range is from tilde to exclamation mark.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
47 # For use with .match()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
48 fcre = re.compile(r'[\041-\176]+:$')
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
49
68585
bf94b6a73fc8 #11565: Fix several typos. Patch by Piotr Kasprzyk.
Ezio Melotti <ezio.melotti@gmail.com>
parents: 67917
diff changeset
50 # Find a header embedded in a putative header value. Used to check for
67477
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
51 # header injection attack.
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
52 _embeded_header = re.compile(r'\n[^ \t]+:')
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
53
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
54
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
55
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
56 # Helpers
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
57 _max_append = email.quoprimime._max_append
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
58
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
59
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
60
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
61 def decode_header(header):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
62 """Decode a message header value without converting charset.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
63
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
64 Returns a list of (string, charset) pairs containing each of the decoded
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
65 parts of the header. Charset is None for non-encoded parts of the header,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
66 otherwise a lower-case string containing the name of the character set
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
67 specified in the encoded string.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
68
68928
b21fdfa0019c #11584: Since __getitem__ returns headers, make decode_header handle them.
R David Murray <rdmurray@bitdance.com>
parents: 68626
diff changeset
69 header may be a string that may or may not contain RFC2047 encoded words,
b21fdfa0019c #11584: Since __getitem__ returns headers, make decode_header handle them.
R David Murray <rdmurray@bitdance.com>
parents: 68626
diff changeset
70 or it may be a Header object.
b21fdfa0019c #11584: Since __getitem__ returns headers, make decode_header handle them.
R David Murray <rdmurray@bitdance.com>
parents: 68626
diff changeset
71
55226
57e9f2d367a8 Merged revisions 73952 via svnmerge from
Amaury Forgeot d'Arc <amauryfa@gmail.com>
parents: 43145
diff changeset
72 An email.errors.HeaderParseError may be raised when certain decoding error
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
73 occurs (e.g. a base64 decoding exception).
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
74 """
70860
d62e5682a8ac #11584: make decode_header handle Header objects correctly
R David Murray <rdmurray@bitdance.com>
parents: 69421
diff changeset
75 # If it is a Header object, we can just return the encoded chunks.
68928
b21fdfa0019c #11584: Since __getitem__ returns headers, make decode_header handle them.
R David Murray <rdmurray@bitdance.com>
parents: 68626
diff changeset
76 if hasattr(header, '_chunks'):
70860
d62e5682a8ac #11584: make decode_header handle Header objects correctly
R David Murray <rdmurray@bitdance.com>
parents: 69421
diff changeset
77 return [(_charset._encode(string, str(charset)), str(charset))
d62e5682a8ac #11584: make decode_header handle Header objects correctly
R David Murray <rdmurray@bitdance.com>
parents: 69421
diff changeset
78 for string, charset in header._chunks]
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
79 # If no encoding, just return the header with no charset.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
80 if not ecre.search(header):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
81 return [(header, None)]
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
82 # First step is to parse all the encoded parts into triplets of the form
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
83 # (encoded_string, encoding, charset). For unencoded strings, the last
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
84 # two parts will be None.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
85 words = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
86 for line in header.splitlines():
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
87 parts = ecre.split(line)
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
88 first = True
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
89 while parts:
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
90 unencoded = parts.pop(0)
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
91 if first:
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
92 unencoded = unencoded.lstrip()
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
93 first = False
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
94 if unencoded:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
95 words.append((unencoded, None, None))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
96 if parts:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
97 charset = parts.pop(0).lower()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
98 encoding = parts.pop(0).lower()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
99 encoded = parts.pop(0)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
100 words.append((encoded, encoding, charset))
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
101 # Now loop over words and remove words that consist of whitespace
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
102 # between two encoded strings.
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
103 import sys
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
104 droplist = []
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
105 for n, w in enumerate(words):
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
106 if n>1 and w[1] and words[n-2][1] and words[n-1][0].isspace():
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
107 droplist.append(n-1)
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
108 for d in reversed(droplist):
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
109 del words[d]
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
110
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
111 # The next step is to decode each encoded word by applying the reverse
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
112 # base64 or quopri transformation. decoded_words is now a list of the
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
113 # form (decoded_word, charset).
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
114 decoded_words = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
115 for encoded_string, encoding, charset in words:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
116 if encoding is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
117 # This is an unencoded word.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
118 decoded_words.append((encoded_string, charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
119 elif encoding == 'q':
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
120 word = email.quoprimime.header_decode(encoded_string)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
121 decoded_words.append((word, charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 elif encoding == 'b':
63708
21a9c940110d Merged revisions 83690 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 43145
diff changeset
123 paderr = len(encoded_string) % 4 # Postel's law: add missing padding
21a9c940110d Merged revisions 83690 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 43145
diff changeset
124 if paderr:
21a9c940110d Merged revisions 83690 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 43145
diff changeset
125 encoded_string += '==='[:4 - paderr]
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
126 try:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
127 word = email.base64mime.decode(encoded_string)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
128 except binascii.Error:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
129 raise HeaderParseError('Base64 decoding error')
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
130 else:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
131 decoded_words.append((word, charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
132 else:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
133 raise AssertionError('Unexpected encoding: ' + encoding)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
134 # Now convert all words to bytes and collapse consecutive runs of
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
135 # similarly encoded words.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
136 collapsed = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
137 last_word = last_charset = None
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
138 for word, charset in decoded_words:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
139 if isinstance(word, str):
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
140 word = bytes(word, 'raw-unicode-escape')
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
141 if last_word is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
142 last_word = word
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
143 last_charset = charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
144 elif charset != last_charset:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
145 collapsed.append((last_word, last_charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
146 last_word = word
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
147 last_charset = charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
148 elif last_charset is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
149 last_word += BSPACE + word
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
150 else:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
151 last_word += word
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
152 collapsed.append((last_word, last_charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
153 return collapsed
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
154
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
155
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
156
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
157 def make_header(decoded_seq, maxlinelen=None, header_name=None,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
158 continuation_ws=' '):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
159 """Create a Header from a sequence of pairs as returned by decode_header()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
160
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
161 decode_header() takes a header value string and returns a sequence of
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
162 pairs of the format (decoded_string, charset) where charset is the string
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
163 name of the character set.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
164
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
165 This function takes one of those sequence of pairs and returns a Header
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
166 instance. Optional maxlinelen, header_name, and continuation_ws are as in
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
167 the Header constructor.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
168 """
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
169 h = Header(maxlinelen=maxlinelen, header_name=header_name,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
170 continuation_ws=continuation_ws)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
171 for s, charset in decoded_seq:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
172 # None means us-ascii but we can simply pass it on to h.append()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
173 if charset is not None and not isinstance(charset, Charset):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
174 charset = Charset(charset)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
175 h.append(s, charset)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
176 return h
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
177
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
178
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
179
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
180 class Header:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
181 def __init__(self, s=None, charset=None,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
182 maxlinelen=None, header_name=None,
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
183 continuation_ws=' ', errors='strict'):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
184 """Create a MIME-compliant header that can contain many character sets.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
185
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
186 Optional s is the initial header value. If None, the initial header
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
187 value is not set. You can later append to the header with .append()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
188 method calls. s may be a byte string or a Unicode string, but see the
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
189 .append() documentation for semantics.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
190
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
191 Optional charset serves two purposes: it has the same meaning as the
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
192 charset argument to the .append() method. It also sets the default
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
193 character set for all subsequent .append() calls that omit the charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
194 argument. If charset is not provided in the constructor, the us-ascii
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
195 charset is used both as s's initial charset and as the default for
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
196 subsequent .append() calls.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
197
67214
2e592a4e68ab Merged revisions 87567 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 63708
diff changeset
198 The maximum line length can be specified explicitly via maxlinelen. For
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
199 splitting the first line to a shorter value (to account for the field
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
200 header which isn't included in s, e.g. `Subject') pass in the name of
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
201 the field in header_name. The default maxlinelen is 78 as recommended
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
202 by RFC 2822.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
203
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
204 continuation_ws must be RFC 2822 compliant folding whitespace (usually
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
205 either a space or a hard tab) which will be prepended to continuation
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
206 lines.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
207
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
208 errors is passed through to the .append() call.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
209 """
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
210 if charset is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
211 charset = USASCII
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
212 elif not isinstance(charset, Charset):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
213 charset = Charset(charset)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
214 self._charset = charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
215 self._continuation_ws = continuation_ws
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
216 self._chunks = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
217 if s is not None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
218 self.append(s, charset, errors)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
219 if maxlinelen is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
220 maxlinelen = MAXLINELEN
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
221 self._maxlinelen = maxlinelen
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
222 if header_name is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
223 self._headerlen = 0
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
224 else:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
225 # Take the separating colon and space into account.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
226 self._headerlen = len(header_name) + 2
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
227
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
228 def __str__(self):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
229 """Return the string value of the header."""
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
230 self._normalize()
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
231 uchunks = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
232 lastcs = None
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
233 lastspace = None
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
234 for string, charset in self._chunks:
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
235 # We must preserve spaces between encoded and non-encoded word
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
236 # boundaries, which means for us we need to add a space when we go
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
237 # from a charset to None/us-ascii, or from None/us-ascii to a
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
238 # charset. Only do this for the second and subsequent chunks.
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
239 # Don't add a space if the None/us-ascii string already has
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
240 # a space (trailing or leading depending on transition)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
241 nextcs = charset
67447
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
242 if nextcs == _charset.UNKNOWN8BIT:
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
243 original_bytes = string.encode('ascii', 'surrogateescape')
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
244 string = original_bytes.decode('ascii', 'replace')
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
245 if uchunks:
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
246 hasspace = string and self._nonctext(string[0])
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
247 if lastcs not in (None, 'us-ascii'):
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
248 if nextcs in (None, 'us-ascii') and not hasspace:
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
249 uchunks.append(SPACE)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
250 nextcs = None
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
251 elif nextcs not in (None, 'us-ascii') and not lastspace:
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
252 uchunks.append(SPACE)
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
253 lastspace = string and self._nonctext(string[-1])
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
254 lastcs = nextcs
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
255 uchunks.append(string)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
256 return EMPTYSTRING.join(uchunks)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
257
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
258 # Rich comparison operators for equality only. BAW: does it make sense to
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
259 # have or explicitly disable <, <=, >, >= operators?
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
260 def __eq__(self, other):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
261 # other may be a Header or a string. Both are fine so coerce
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
262 # ourselves to a unicode (of the unencoded header value), swap the
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
263 # args and do another comparison.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
264 return other == str(self)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
265
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
266 def __ne__(self, other):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
267 return not self == other
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
268
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
269 def append(self, s, charset=None, errors='strict'):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
270 """Append a string to the MIME header.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
271
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
272 Optional charset, if given, should be a Charset instance or the name
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
273 of a character set (which will be converted to a Charset instance). A
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
274 value of None (the default) means that the charset given in the
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
275 constructor is used.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
276
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
277 s may be a byte string or a Unicode string. If it is a byte string
67214
2e592a4e68ab Merged revisions 87567 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 63708
diff changeset
278 (i.e. isinstance(s, str) is false), then charset is the encoding of
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
279 that byte string, and a UnicodeError will be raised if the string
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
280 cannot be decoded with that charset. If s is a Unicode string, then
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
281 charset is a hint specifying the character set of the characters in
67365
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
282 the string. In either case, when producing an RFC 2822 compliant
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
283 header using RFC 2047 rules, the string will be encoded using the
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
284 output codec of the charset. If the string cannot be encoded to the
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
285 output codec, a UnicodeError will be raised.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
286
67365
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
287 Optional `errors' is passed as the errors argument to the decode
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
288 call if s is a byte string.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
289 """
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
290 if charset is None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
291 charset = self._charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
292 elif not isinstance(charset, Charset):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
293 charset = Charset(charset)
67365
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
294 if not isinstance(s, str):
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
295 input_charset = charset.input_codec or 'us-ascii'
70862
3875ccea6367 #11584: make Header and make_header handle binary unknown-8bit input
R David Murray <rdmurray@bitdance.com>
parents: 70860
diff changeset
296 if input_charset == _charset.UNKNOWN8BIT:
3875ccea6367 #11584: make Header and make_header handle binary unknown-8bit input
R David Murray <rdmurray@bitdance.com>
parents: 70860
diff changeset
297 s = s.decode('us-ascii', 'surrogateescape')
3875ccea6367 #11584: make Header and make_header handle binary unknown-8bit input
R David Murray <rdmurray@bitdance.com>
parents: 70860
diff changeset
298 else:
3875ccea6367 #11584: make Header and make_header handle binary unknown-8bit input
R David Murray <rdmurray@bitdance.com>
parents: 70860
diff changeset
299 s = s.decode(input_charset, errors)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
300 # Ensure that the bytes we're storing can be decoded to the output
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
301 # character set, otherwise an early error is thrown.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
302 output_charset = charset.output_codec or 'us-ascii'
67447
cad1811d9e13 #10686: recode non-ASCII headers to 'unknown-8bit' instead of ?s.
R. David Murray <rdmurray@bitdance.com>
parents: 67446
diff changeset
303 if output_charset != _charset.UNKNOWN8BIT:
75621
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
304 try:
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
305 s.encode(output_charset, errors)
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
306 except UnicodeEncodeError:
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
307 if output_charset!='us-ascii':
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
308 raise
fd4b4650856f #14291: if a header has non-ascii unicode, default to CTE using utf-8
R David Murray <rdmurray@bitdance.com>
parents: 70862
diff changeset
309 charset = UTF8
67365
0effb175c981 Merged revisions 87750 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67214
diff changeset
310 self._chunks.append((s, charset))
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
311
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
312 def _nonctext(self, s):
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
313 """True if string s is not a ctext character of RFC822.
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
314 """
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
315 return s.isspace() or s in ('(', ')', '\\')
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
316
65611
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
317 def encode(self, splitchars=';, \t', maxlinelen=None, linesep='\n'):
68471
f6cab3819160 Harmonize linesep docstrings, and fix the quoting of \r\n
R David Murray <rdmurray@bitdance.com>
parents: 68257
diff changeset
318 r"""Encode a message header into an RFC-compliant format.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
319
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
320 There are many issues involved in converting a given string for use in
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
321 an email header. Only certain character sets are readable in most
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
322 email clients, and as header strings can only contain a subset of
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
323 7-bit ASCII, care must be taken to properly convert and encode (with
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
324 Base64 or quoted-printable) header strings. In addition, there is a
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
325 75-character length limit on any given encoded header field, so
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
326 line-wrapping must be performed, even with double-byte character sets.
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
327
69323
bbed01a7d0d1 Fix typo in docstring.
Ezio Melotti <ezio.melotti@gmail.com>
parents: 69272
diff changeset
328 Optional maxlinelen specifies the maximum length of each generated
69272
f9bd0add9732 Add maxlinelen to docstring, delete obsolete wording
R David Murray <rdmurray@bitdance.com>
parents: 69201
diff changeset
329 line, exclusive of the linesep string. Individual lines may be longer
f9bd0add9732 Add maxlinelen to docstring, delete obsolete wording
R David Murray <rdmurray@bitdance.com>
parents: 69201
diff changeset
330 than maxlinelen if a folding point cannot be found. The first line
f9bd0add9732 Add maxlinelen to docstring, delete obsolete wording
R David Murray <rdmurray@bitdance.com>
parents: 69201
diff changeset
331 will be shorter by the length of the header name plus ": " if a header
f9bd0add9732 Add maxlinelen to docstring, delete obsolete wording
R David Murray <rdmurray@bitdance.com>
parents: 69201
diff changeset
332 name was specified at Header construction time. The default value for
f9bd0add9732 Add maxlinelen to docstring, delete obsolete wording
R David Murray <rdmurray@bitdance.com>
parents: 69201
diff changeset
333 maxlinelen is determined at header construction time.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
334
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
335 Optional splitchars is a string containing characters which should be
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
336 given extra weight by the splitting algorithm during normal header
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
337 wrapping. This is in very rough support of RFC 2822's `higher level
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
338 syntactic breaks': split points preceded by a splitchar are preferred
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
339 during line splitting, with the characters preferred in the order in
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
340 which they appear in the string. Space and tab may be included in the
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
341 string to indicate whether preference should be given to one over the
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
342 other as a split point when other split chars do not appear in the line
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
343 being split. Splitchars does not affect RFC 2047 encoded lines.
65611
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
344
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
345 Optional linesep is a string to be used to separate the lines of
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
346 the value. The default value is the most useful for typical
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
347 Python applications, but it can be set to \r\n to produce RFC-compliant
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
348 line separators when needed.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
349 """
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
350 self._normalize()
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
351 if maxlinelen is None:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
352 maxlinelen = self._maxlinelen
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
353 # A maxlinelen of 0 means don't wrap. For all practical purposes,
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
354 # choosing a huge number here accomplishes that and makes the
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
355 # _ValueFormatter algorithm much simpler.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
356 if maxlinelen == 0:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
357 maxlinelen = 1000000
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
358 formatter = _ValueFormatter(self._headerlen, maxlinelen,
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
359 self._continuation_ws, splitchars)
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
360 lastcs = None
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
361 hasspace = lastspace = None
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
362 for string, charset in self._chunks:
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
363 if hasspace is not None:
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
364 hasspace = string and self._nonctext(string[0])
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
365 import sys
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
366 if lastcs not in (None, 'us-ascii'):
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
367 if not hasspace or charset not in (None, 'us-ascii'):
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
368 formatter.add_transition()
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
369 elif charset not in (None, 'us-ascii') and not lastspace:
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
370 formatter.add_transition()
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
371 lastspace = string and self._nonctext(string[-1])
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
372 lastcs = charset
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
373 hasspace = False
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
374 lines = string.splitlines()
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
375 if lines:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
376 formatter.feed('', lines[0], charset)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
377 else:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
378 formatter.feed('', '', charset)
67917
8084c668b637 Merged revisions 87136,87221,87256,87337-87338,87571,87839,88164 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67477
diff changeset
379 for line in lines[1:]:
8084c668b637 Merged revisions 87136,87221,87256,87337-87338,87571,87839,88164 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67477
diff changeset
380 formatter.newline()
8084c668b637 Merged revisions 87136,87221,87256,87337-87338,87571,87839,88164 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67477
diff changeset
381 if charset.header_encoding is not None:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
382 formatter.feed(self._continuation_ws, ' ' + line.lstrip(),
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
383 charset)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
384 else:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
385 sline = line.lstrip()
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
386 fws = line[:len(line)-len(sline)]
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
387 formatter.feed(fws, sline, charset)
67917
8084c668b637 Merged revisions 87136,87221,87256,87337-87338,87571,87839,88164 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67477
diff changeset
388 if len(lines) > 1:
8084c668b637 Merged revisions 87136,87221,87256,87337-87338,87571,87839,88164 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67477
diff changeset
389 formatter.newline()
77308
8c03fe231877 #1079: Fix parsing of encoded words.
R David Murray <rdmurray@bitdance.com>
parents: 75621
diff changeset
390 if self._chunks:
43113
7ec04cb262d2 More email package fixes.
Barry Warsaw <barry@python.org>
parents: 43045
diff changeset
391 formatter.add_transition()
67476
8bbff1c24a31 #5871: protect against header injection attacks.
R. David Murray <rdmurray@bitdance.com>
parents: 67447
diff changeset
392 value = formatter._str(linesep)
67477
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
393 if _embeded_header.search(value):
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
394 raise HeaderParseError("header value appears to contain "
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
395 "an embedded header: {!r}".format(value))
966b87f2395c Merged revisions 87873 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 67365
diff changeset
396 return value
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
397
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
398 def _normalize(self):
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
399 # Step 1: Normalize the chunks so that all runs of identical charsets
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
400 # get collapsed into a single unicode string.
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
401 chunks = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
402 last_charset = None
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
403 last_chunk = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
404 for string, charset in self._chunks:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
405 if charset == last_charset:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
406 last_chunk.append(string)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
407 else:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
408 if last_charset is not None:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
409 chunks.append((SPACE.join(last_chunk), last_charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
410 last_chunk = [string]
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
411 last_charset = charset
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
412 if last_chunk:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
413 chunks.append((SPACE.join(last_chunk), last_charset))
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
414 self._chunks = chunks
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
415
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
416
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
417
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
418 class _ValueFormatter:
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
419 def __init__(self, headerlen, maxlen, continuation_ws, splitchars):
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
420 self._maxlen = maxlen
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
421 self._continuation_ws = continuation_ws
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
422 self._continuation_ws_len = len(continuation_ws)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
423 self._splitchars = splitchars
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
424 self._lines = []
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
425 self._current_line = _Accumulator(headerlen)
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
426
65611
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
427 def _str(self, linesep):
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
428 self.newline()
65611
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
429 return linesep.join(self._lines)
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
430
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
431 def __str__(self):
ebf6741a8d6e #1349106: add linesep argument to generator.flatten and header.encode.
R. David Murray <rdmurray@bitdance.com>
parents: 63705
diff changeset
432 return self._str(NL)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
433
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
434 def newline(self):
43113
7ec04cb262d2 More email package fixes.
Barry Warsaw <barry@python.org>
parents: 43045
diff changeset
435 end_of_line = self._current_line.pop()
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
436 if end_of_line != (' ', ''):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
437 self._current_line.push(*end_of_line)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
438 if len(self._current_line) > 0:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
439 if self._current_line.is_onlyws():
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
440 self._lines[-1] += str(self._current_line)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
441 else:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
442 self._lines.append(str(self._current_line))
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
443 self._current_line.reset()
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
444
43113
7ec04cb262d2 More email package fixes.
Barry Warsaw <barry@python.org>
parents: 43045
diff changeset
445 def add_transition(self):
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
446 self._current_line.push(' ', '')
43113
7ec04cb262d2 More email package fixes.
Barry Warsaw <barry@python.org>
parents: 43045
diff changeset
447
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
448 def feed(self, fws, string, charset):
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
449 # If the charset has no header encoding (i.e. it is an ASCII encoding)
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
450 # then we must split the header at the "highest level syntactic break"
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
451 # possible. Note that we don't have a lot of smarts about field
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
452 # syntax; we just try to break on semi-colons, then commas, then
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
453 # whitespace. Eventually, this should be pluggable.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
454 if charset.header_encoding is None:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
455 self._ascii_split(fws, string, self._splitchars)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
456 return
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
457 # Otherwise, we're doing either a Base64 or a quoted-printable
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
458 # encoding which means we don't need to split the line on syntactic
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
459 # breaks. We can basically just find enough characters to fit on the
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
460 # current line, minus the RFC 2047 chrome. What makes this trickier
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
461 # though is that we have to split at octet boundaries, not character
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
462 # boundaries but it's only safe to split at character boundaries so at
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
463 # best we can only get close.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
464 encoded_lines = charset.header_encode_lines(string, self._maxlengths())
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
465 # The first element extends the current line, but if it's None then
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
466 # nothing more fit on the current line so start a new line.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
467 try:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
468 first_line = encoded_lines.pop(0)
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
469 except IndexError:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
470 # There are no encoded lines, so we're done.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
471 return
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
472 if first_line is not None:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
473 self._append_chunk(fws, first_line)
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
474 try:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
475 last_line = encoded_lines.pop()
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
476 except IndexError:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
477 # There was only one line.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
478 return
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
479 self.newline()
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
480 self._current_line.push(self._continuation_ws, last_line)
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
481 # Everything else are full lines in themselves.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
482 for line in encoded_lines:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
483 self._lines.append(self._continuation_ws + line)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
484
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
485 def _maxlengths(self):
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
486 # The first line's length.
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
487 yield self._maxlen - len(self._current_line)
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
488 while True:
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
489 yield self._maxlen - self._continuation_ws_len
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
490
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
491 def _ascii_split(self, fws, string, splitchars):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
492 # The RFC 2822 header folding algorithm is simple in principle but
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
493 # complex in practice. Lines may be folded any place where "folding
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
494 # white space" appears by inserting a linesep character in front of the
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
495 # FWS. The complication is that not all spaces or tabs qualify as FWS,
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
496 # and we are also supposed to prefer to break at "higher level
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
497 # syntactic breaks". We can't do either of these without intimate
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
498 # knowledge of the structure of structured headers, which we don't have
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
499 # here. So the best we can do here is prefer to break at the specified
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
500 # splitchars, and hope that we don't choose any spaces or tabs that
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
501 # aren't legal FWS. (This is at least better than the old algorithm,
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
502 # where we would sometimes *introduce* FWS after a splitchar, or the
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
503 # algorithm before that, where we would turn all white space runs into
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
504 # single spaces or tabs.)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
505 parts = re.split("(["+FWS+"]+)", fws+string)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
506 if parts[0]:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
507 parts[:0] = ['']
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
508 else:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
509 parts.pop(0)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
510 for fws, part in zip(*[iter(parts)]*2):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
511 self._append_chunk(fws, part)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
512
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
513 def _append_chunk(self, fws, string):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
514 self._current_line.push(fws, string)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
515 if len(self._current_line) > self._maxlen:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
516 # Find the best split point, working backward from the end.
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
517 # There might be none, on a long first line.
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
518 for ch in self._splitchars:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
519 for i in range(self._current_line.part_count()-1, 0, -1):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
520 if ch.isspace():
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
521 fws = self._current_line[i][0]
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
522 if fws and fws[0]==ch:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
523 break
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
524 prevpart = self._current_line[i-1][1]
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
525 if prevpart and prevpart[-1]==ch:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
526 break
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
527 else:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
528 continue
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
529 break
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
530 else:
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
531 fws, part = self._current_line.pop()
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
532 if self._current_line._initial_size > 0:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
533 # There will be a header, so leave it on a line by itself.
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
534 self.newline()
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
535 if not fws:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
536 # We don't use continuation_ws here because the whitespace
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
537 # after a header should always be a space.
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
538 fws = ' '
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
539 self._current_line.push(fws, part)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
540 return
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
541 remainder = self._current_line.pop_from(i)
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
542 self._lines.append(str(self._current_line))
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
543 self._current_line.reset(remainder)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
544
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
545
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
546 class _Accumulator(list):
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
547
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
548 def __init__(self, initial_size=0):
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
549 self._initial_size = initial_size
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
550 super().__init__()
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
551
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
552 def push(self, fws, string):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
553 self.append((fws, string))
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
554
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
555 def pop_from(self, i=0):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
556 popped = self[i:]
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
557 self[i:] = []
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
558 return popped
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
559
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
560 def pop(self):
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
561 if self.part_count()==0:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
562 return ('', '')
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
563 return super().pop()
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
564
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
565 def __len__(self):
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
566 return sum((len(fws)+len(part) for fws, part in self),
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
567 self._initial_size)
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
568
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
569 def __str__(self):
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
570 return EMPTYSTRING.join((EMPTYSTRING.join((fws, part))
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
571 for fws, part in self))
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
572
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
573 def reset(self, startval=None):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
574 if startval is None:
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
575 startval = []
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
576 self[:] = startval
43019
d5f3c2f416f2 Copying the email package back, despite its failings.
Guido van Rossum <guido@python.org>
parents:
diff changeset
577 self._initial_size = 0
43024
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
578
1321ba0b670f Oops. I copied a slightly older version of the email package from the sandbox.
Guido van Rossum <guido@python.org>
parents: 43019
diff changeset
579 def is_onlyws(self):
69421
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
580 return self._initial_size==0 and (not self or str(self).isspace())
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
581
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
582 def part_count(self):
51a551acb60d #11492: rewrite header folding algorithm. Less code, more passing tests.
R David Murray <rdmurray@bitdance.com>
parents: 69324
diff changeset
583 return super().__len__()