|
9 | 9 |
|
10 | 10 | from pprint import pformat |
11 | 11 | from urllib import urlencode, quote |
12 | | -from urlparse import urljoin |
| 12 | +from urlparse import urljoin, urlparse |
13 | 13 | try: |
14 | 14 | from cStringIO import StringIO |
15 | 15 | except ImportError: |
@@ -114,7 +114,7 @@ def __init__(self, *args, **kwargs): |
114 | 114 |
|
115 | 115 | from django.conf import settings |
116 | 116 | from django.core import signing |
117 | | -from django.core.exceptions import ImproperlyConfigured |
| 117 | +from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation |
118 | 118 | from django.core.files import uploadhandler |
119 | 119 | from django.http.multipartparser import MultiPartParser |
120 | 120 | from django.http.utils import * |
@@ -731,19 +731,21 @@ def tell(self): |
731 | 731 | raise Exception("This %s instance cannot tell its position" % self.__class__) |
732 | 732 | return sum([len(str(chunk)) for chunk in self._container]) |
733 | 733 |
|
734 | | -class HttpResponseRedirect(HttpResponse): |
735 | | - status_code = 302 |
| 734 | +class HttpResponseRedirectBase(HttpResponse): |
| 735 | + allowed_schemes = ['http', 'https', 'ftp'] |
736 | 736 |
|
737 | 737 | def __init__(self, redirect_to): |
738 | | - super(HttpResponseRedirect, self).__init__() |
| 738 | + super(HttpResponseRedirectBase, self).__init__() |
| 739 | + parsed = urlparse(redirect_to) |
| 740 | + if parsed.scheme and parsed.scheme not in self.allowed_schemes: |
| 741 | + raise SuspiciousOperation("Unsafe redirect to URL with scheme '%s'" % parsed.scheme) |
739 | 742 | self['Location'] = iri_to_uri(redirect_to) |
740 | 743 |
|
741 | | -class HttpResponsePermanentRedirect(HttpResponse): |
742 | | - status_code = 301 |
| 744 | +class HttpResponseRedirect(HttpResponseRedirectBase): |
| 745 | + status_code = 302 |
743 | 746 |
|
744 | | - def __init__(self, redirect_to): |
745 | | - super(HttpResponsePermanentRedirect, self).__init__() |
746 | | - self['Location'] = iri_to_uri(redirect_to) |
| 747 | +class HttpResponsePermanentRedirect(HttpResponseRedirectBase): |
| 748 | + status_code = 301 |
747 | 749 |
|
748 | 750 | class HttpResponseNotModified(HttpResponse): |
749 | 751 | status_code = 304 |
|
0 commit comments