Loading django/views/i18n.py +3 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from django.utils import six from django.utils._os import upath from django.utils.encoding import smart_text from django.utils.formats import get_format, get_format_modules from django.utils.http import is_safe_url from django.utils.http import is_safe_url, urlunquote from django.utils.translation import ( LANGUAGE_SESSION_KEY, check_for_language, get_language, to_locale, ) Loading @@ -36,6 +36,8 @@ def set_language(request): next = request.POST.get('next', request.GET.get('next')) if (next or not request.is_ajax()) and not is_safe_url(url=next, host=request.get_host()): next = request.META.get('HTTP_REFERER') if next: next = urlunquote(next) # HTTP_REFERER may be encoded. if not is_safe_url(url=next, host=request.get_host()): next = '/' response = http.HttpResponseRedirect(next) if next else http.HttpResponse(status=204) Loading tests/view_tests/tests/test_i18n.py +12 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,18 @@ class I18NTests(TestCase): self.assertEqual(language_cookie['path'], '/test/') self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2) def test_setlang_decodes_http_referer_url(self): """ The set_language view decodes the HTTP_REFERER URL. """ # The url() & view must exist for this to work as a regression test. self.assertEqual(reverse('with_parameter', kwargs={'parameter': 'x'}), '/test-setlang/x/') lang_code = self._get_inactive_language_code() encoded_url = '/test-setlang/%C3%A4/' # (%C3%A4 decodes to ä) response = self.client.post('/i18n/setlang/', {'language': lang_code}, HTTP_REFERER=encoded_url) self.assertRedirects(response, encoded_url, fetch_redirect_response=False) self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) @modify_settings(MIDDLEWARE_CLASSES={ 'append': 'django.middleware.locale.LocaleMiddleware', }) Loading tests/view_tests/urls.py +1 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,5 @@ urlpatterns += [ name='raises_template_does_not_exist' ), url(r'^render_no_template/$', views.render_no_template, name='render_no_template'), url(r'^test-setlang/(?P<parameter>[^/]+)/$', views.with_parameter, name='with_parameter'), ] tests/view_tests/views.py +4 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ def index_page(request): return HttpResponse('<html><body>Dummy page</body></html>') def with_parameter(request, parameter): return HttpResponse('ok') def raises(request): # Make sure that a callable that raises an exception in the stack frame's # local vars won't hijack the technical 500 response. See: Loading Loading
django/views/i18n.py +3 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from django.utils import six from django.utils._os import upath from django.utils.encoding import smart_text from django.utils.formats import get_format, get_format_modules from django.utils.http import is_safe_url from django.utils.http import is_safe_url, urlunquote from django.utils.translation import ( LANGUAGE_SESSION_KEY, check_for_language, get_language, to_locale, ) Loading @@ -36,6 +36,8 @@ def set_language(request): next = request.POST.get('next', request.GET.get('next')) if (next or not request.is_ajax()) and not is_safe_url(url=next, host=request.get_host()): next = request.META.get('HTTP_REFERER') if next: next = urlunquote(next) # HTTP_REFERER may be encoded. if not is_safe_url(url=next, host=request.get_host()): next = '/' response = http.HttpResponseRedirect(next) if next else http.HttpResponse(status=204) Loading
tests/view_tests/tests/test_i18n.py +12 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,18 @@ class I18NTests(TestCase): self.assertEqual(language_cookie['path'], '/test/') self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2) def test_setlang_decodes_http_referer_url(self): """ The set_language view decodes the HTTP_REFERER URL. """ # The url() & view must exist for this to work as a regression test. self.assertEqual(reverse('with_parameter', kwargs={'parameter': 'x'}), '/test-setlang/x/') lang_code = self._get_inactive_language_code() encoded_url = '/test-setlang/%C3%A4/' # (%C3%A4 decodes to ä) response = self.client.post('/i18n/setlang/', {'language': lang_code}, HTTP_REFERER=encoded_url) self.assertRedirects(response, encoded_url, fetch_redirect_response=False) self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code) @modify_settings(MIDDLEWARE_CLASSES={ 'append': 'django.middleware.locale.LocaleMiddleware', }) Loading
tests/view_tests/urls.py +1 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,5 @@ urlpatterns += [ name='raises_template_does_not_exist' ), url(r'^render_no_template/$', views.render_no_template, name='render_no_template'), url(r'^test-setlang/(?P<parameter>[^/]+)/$', views.with_parameter, name='with_parameter'), ]
tests/view_tests/views.py +4 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ def index_page(request): return HttpResponse('<html><body>Dummy page</body></html>') def with_parameter(request, parameter): return HttpResponse('ok') def raises(request): # Make sure that a callable that raises an exception in the stack frame's # local vars won't hijack the technical 500 response. See: Loading