Header-encode a string by converting it first to bytes. This is similar to `header_encode()` except that the string is fit into maximum line lengths as given by the argument. :param string: A unicode string for the header. It must be possible to encode this str
(self, string, maxlengths)
| 291 | return encoder_module.header_encode(header_bytes, codec) |
| 292 | |
| 293 | def header_encode_lines(self, string, maxlengths): |
| 294 | """Header-encode a string by converting it first to bytes. |
| 295 | |
| 296 | This is similar to `header_encode()` except that the string is fit |
| 297 | into maximum line lengths as given by the argument. |
| 298 | |
| 299 | :param string: A unicode string for the header. It must be possible |
| 300 | to encode this string to bytes using the character set's |
| 301 | output codec. |
| 302 | :param maxlengths: Maximum line length iterator. Each element |
| 303 | returned from this iterator will provide the next maximum line |
| 304 | length. This parameter is used as an argument to built-in next() |
| 305 | and should never be exhausted. The maximum line lengths should |
| 306 | not count the RFC 2047 chrome. These line lengths are only a |
| 307 | hint; the splitter does the best it can. |
| 308 | :return: Lines of encoded strings, each with RFC 2047 chrome. |
| 309 | """ |
| 310 | # See which encoding we should use. |
| 311 | codec = self.output_codec or 'us-ascii' |
| 312 | header_bytes = _encode(string, codec) |
| 313 | encoder_module = self._get_encoder(header_bytes) |
| 314 | encoder = partial(encoder_module.header_encode, charset=codec) |
| 315 | # Calculate the number of characters that the RFC 2047 chrome will |
| 316 | # contribute to each line. |
| 317 | charset = self.get_output_charset() |
| 318 | extra = len(charset) + RFC2047_CHROME_LEN |
| 319 | # Now comes the hard part. We must encode bytes but we can't split on |
| 320 | # bytes because some character sets are variable length and each |
| 321 | # encoded word must stand on its own. So the problem is you have to |
| 322 | # encode to bytes to figure out this word's length, but you must split |
| 323 | # on characters. This causes two problems: first, we don't know how |
| 324 | # many octets a specific substring of unicode characters will get |
| 325 | # encoded to, and second, we don't know how many ASCII characters |
| 326 | # those octets will get encoded to. Unless we try it. Which seems |
| 327 | # inefficient. In the interest of being correct rather than fast (and |
| 328 | # in the hope that there will be few encoded headers in any such |
| 329 | # message), brute force it. :( |
| 330 | lines = [] |
| 331 | current_line = [] |
| 332 | maxlen = next(maxlengths) - extra |
| 333 | for character in string: |
| 334 | current_line.append(character) |
| 335 | this_line = EMPTYSTRING.join(current_line) |
| 336 | length = encoder_module.header_length(_encode(this_line, charset)) |
| 337 | if length > maxlen: |
| 338 | # This last character doesn't fit so pop it off. |
| 339 | current_line.pop() |
| 340 | # Does nothing fit on the first line? |
| 341 | if not lines and not current_line: |
| 342 | lines.append(None) |
| 343 | else: |
| 344 | joined_line = EMPTYSTRING.join(current_line) |
| 345 | header_bytes = _encode(joined_line, codec) |
| 346 | lines.append(encoder(header_bytes)) |
| 347 | current_line = [character] |
| 348 | maxlen = next(maxlengths) - extra |
| 349 | joined_line = EMPTYSTRING.join(current_line) |
| 350 | header_bytes = _encode(joined_line, codec) |
no test coverage detected