|
4 | 4 | import time |
5 | 5 | from pprint import pformat |
6 | 6 | from urllib import urlencode, quote |
7 | | -from urlparse import urljoin |
| 7 | +from urlparse import urljoin, urlparse |
8 | 8 | try: |
9 | 9 | from cStringIO import StringIO |
10 | 10 | except ImportError: |
@@ -117,6 +117,7 @@ def __init__(self, *args, **kwargs): |
117 | 117 | warnings.warn("CompatCookie is deprecated, use django.http.SimpleCookie instead.", |
118 | 118 | PendingDeprecationWarning) |
119 | 119 |
|
| 120 | +from django.core.exceptions import SuspiciousOperation |
120 | 121 | from django.utils.datastructures import MultiValueDict, ImmutableList |
121 | 122 | from django.utils.encoding import smart_str, iri_to_uri, force_unicode |
122 | 123 | from django.utils.http import cookie_date |
@@ -635,19 +636,21 @@ def tell(self): |
635 | 636 | raise Exception("This %s instance cannot tell its position" % self.__class__) |
636 | 637 | return sum([len(chunk) for chunk in self._container]) |
637 | 638 |
|
638 | | -class HttpResponseRedirect(HttpResponse): |
639 | | - status_code = 302 |
| 639 | +class HttpResponseRedirectBase(HttpResponse): |
| 640 | + allowed_schemes = ['http', 'https', 'ftp'] |
640 | 641 |
|
641 | 642 | def __init__(self, redirect_to): |
642 | | - super(HttpResponseRedirect, self).__init__() |
| 643 | + super(HttpResponseRedirectBase, self).__init__() |
| 644 | + parsed = urlparse(redirect_to) |
| 645 | + if parsed.scheme and parsed.scheme not in self.allowed_schemes: |
| 646 | + raise SuspiciousOperation("Unsafe redirect to URL with scheme '%s'" % parsed.scheme) |
643 | 647 | self['Location'] = iri_to_uri(redirect_to) |
644 | 648 |
|
645 | | -class HttpResponsePermanentRedirect(HttpResponse): |
646 | | - status_code = 301 |
| 649 | +class HttpResponseRedirect(HttpResponseRedirectBase): |
| 650 | + status_code = 302 |
647 | 651 |
|
648 | | - def __init__(self, redirect_to): |
649 | | - super(HttpResponsePermanentRedirect, self).__init__() |
650 | | - self['Location'] = iri_to_uri(redirect_to) |
| 652 | +class HttpResponsePermanentRedirect(HttpResponseRedirectBase): |
| 653 | + status_code = 301 |
651 | 654 |
|
652 | 655 | class HttpResponseNotModified(HttpResponse): |
653 | 656 | status_code = 304 |
|
0 commit comments