diff options
| author | Aymeric Augustin <aymeric.augustin@m4x.org> | 2012-09-07 19:08:57 -0400 |
|---|---|---|
| committer | Aymeric Augustin <aymeric.augustin@m4x.org> | 2012-09-07 19:08:57 -0400 |
| commit | 9b07b5edeb770b037dc735d48dfd6f979422f586 (patch) | |
| tree | 9cd734f52b4ce859c79c66e43538a0871009dfb0 /django/http/__init__.py | |
| parent | 1d235b39142d830a221bda4c55dc3357446deb57 (diff) | |
Fixed #18916 -- Allowed non-ASCII headers.
Thanks Malcolm Tredinnick for the review.
Diffstat (limited to 'django/http/__init__.py')
| -rw-r--r-- | django/http/__init__.py | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/django/http/__init__.py b/django/http/__init__.py index 2198f38cbb..ecb39129ad 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals import copy import datetime +from email.header import Header import os import re import sys @@ -560,31 +561,44 @@ class HttpResponse(object): else: __str__ = serialize - def _convert_to_ascii(self, *values): - """Converts all values to ascii strings.""" - for value in values: - if not isinstance(value, six.string_types): - value = str(value) - try: - if six.PY3: - # Ensure string only contains ASCII - value.encode('us-ascii') + def _convert_to_charset(self, value, charset, mime_encode=False): + """Converts headers key/value to ascii/latin1 native strings. + + `charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and + `value` value can't be represented in the given charset, MIME-encoding + is applied. + """ + if not isinstance(value, (bytes, six.text_type)): + value = str(value) + try: + if six.PY3: + if isinstance(value, str): + # Ensure string is valid in given charset + value.encode(charset) else: - if isinstance(value, str): - # Ensure string only contains ASCII - value.decode('us-ascii') - else: - # Convert unicode to an ASCII string - value = value.encode('us-ascii') - except UnicodeError as e: - e.reason += ', HTTP response headers must be in US-ASCII format' + # Convert bytestring using given charset + value = value.decode(charset) + else: + if isinstance(value, str): + # Ensure string is valid in given charset + value.decode(charset) + else: + # Convert unicode string to given charset + value = value.encode(charset) + except UnicodeError as e: + if mime_encode: + # Wrapping in str() is a workaround for #12422 under Python 2. + value = str(Header(value, 'utf-8').encode()) + else: + e.reason += ', HTTP response headers must be in %s format' % charset raise - if '\n' in value or '\r' in value: - raise BadHeaderError("Header values can't contain newlines (got %r)" % value) - yield value + if str('\n') in value or str('\r') in value: + raise BadHeaderError("Header values can't contain newlines (got %r)" % value) + return value def __setitem__(self, header, value): - header, value = self._convert_to_ascii(header, value) + header = self._convert_to_charset(header, 'ascii') + value = self._convert_to_charset(value, 'latin1', mime_encode=True) self._headers[header.lower()] = (header, value) def __delitem__(self, header): |
