| 415 | |
| 416 | |
| 417 | class _ValueFormatter: |
| 418 | def __init__(self, headerlen, maxlen, continuation_ws, splitchars): |
| 419 | self._maxlen = maxlen |
| 420 | self._continuation_ws = continuation_ws |
| 421 | self._continuation_ws_len = len(continuation_ws) |
| 422 | self._splitchars = splitchars |
| 423 | self._lines = [] |
| 424 | self._current_line = _Accumulator(headerlen) |
| 425 | |
| 426 | def _str(self, linesep): |
| 427 | self.newline() |
| 428 | return linesep.join(self._lines) |
| 429 | |
| 430 | def __str__(self): |
| 431 | return self._str(NL) |
| 432 | |
| 433 | def newline(self): |
| 434 | end_of_line = self._current_line.pop() |
| 435 | if end_of_line != (' ', ''): |
| 436 | self._current_line.push(*end_of_line) |
| 437 | if len(self._current_line) > 0: |
| 438 | if self._current_line.is_onlyws() and self._lines: |
| 439 | self._lines[-1] += str(self._current_line) |
| 440 | else: |
| 441 | self._lines.append(str(self._current_line)) |
| 442 | self._current_line.reset() |
| 443 | |
| 444 | def add_transition(self): |
| 445 | self._current_line.push(' ', '') |
| 446 | |
| 447 | def feed(self, fws, string, charset): |
| 448 | # If the charset has no header encoding (i.e. it is an ASCII encoding) |
| 449 | # then we must split the header at the "highest level syntactic break" |
| 450 | # possible. Note that we don't have a lot of smarts about field |
| 451 | # syntax; we just try to break on semi-colons, then commas, then |
| 452 | # whitespace. Eventually, this should be pluggable. |
| 453 | if charset.header_encoding is None: |
| 454 | self._ascii_split(fws, string, self._splitchars) |
| 455 | return |
| 456 | # Otherwise, we're doing either a Base64 or a quoted-printable |
| 457 | # encoding which means we don't need to split the line on syntactic |
| 458 | # breaks. We can basically just find enough characters to fit on the |
| 459 | # current line, minus the RFC 2047 chrome. What makes this trickier |
| 460 | # though is that we have to split at octet boundaries, not character |
| 461 | # boundaries but it's only safe to split at character boundaries so at |
| 462 | # best we can only get close. |
| 463 | encoded_lines = charset.header_encode_lines(string, self._maxlengths()) |
| 464 | # The first element extends the current line, but if it's None then |
| 465 | # nothing more fit on the current line so start a new line. |
| 466 | try: |
| 467 | first_line = encoded_lines.pop(0) |
| 468 | except IndexError: |
| 469 | # There are no encoded lines, so we're done. |
| 470 | return |
| 471 | if first_line is not None: |
| 472 | self._append_chunk(fws, first_line) |
| 473 | try: |
| 474 | last_line = encoded_lines.pop() |
no outgoing calls
no test coverage detected
searching dependent graphs…