Browse files

Started working on #1019, it should prevent the issue in most cases,

however it's really insanely hard to cover edge-cases (especially for
home-pages) since it's not trivial to check if a page will be the
homepage or not.
  • Loading branch information...
1 parent 7865ae9 commit bf448a164bb49dc21f801803afa45dc9a15ab15e Jonas Obrist committed Oct 14, 2011
Showing with 71 additions and 3 deletions.
  1. +29 −0 cms/admin/forms.py
  2. +15 −2 cms/api.py
  3. +21 −0 cms/tests/admin.py
  4. +6 −1 cms/tests/api.py
View
29 cms/admin/forms.py
@@ -170,6 +170,35 @@ def clean(self):
raise forms.ValidationError(_('A page with this reverse URL id exists already.'))
return cleaned_data
+ def clean_redirect(self):
+ """
+ Prevent infinite redirects
+ """
+ redirect = self.cleaned_data.get('redirect', None)
+ if not redirect:
+ return redirect
+ slug = self.cleaned_data.get('slug', None)
+ if not slug:
+ return redirect
+ parent_id = self.cleaned_data.get('parent', None)
+ old_slug = self.instance.get_slug()
+ if old_slug == slug and self.instance.parent_id == parent_id:
+ url = self.instance.get_absolute_url()
+ else:
+ if parent_id:
+ url = Page.objects.get(pk=parent_id).get_absolute_url()
+ else:
+ url = '/'
+ if parent_id:
+ url += slug
+ elif not self.instance.is_home():
+ url += slug
+ if not url.endswith('/'):
+ url += '/'
+ if url == redirect:
+ raise forms.ValidationError("Inifinite redirect, please chose a different redirect")
+ return redirect
+
def clean_overwrite_url(self):
if 'overwrite_url' in self.fields:
url = self.cleaned_data['overwrite_url']
View
17 cms/api.py
@@ -30,6 +30,12 @@
from cms.utils.permissions import _thread_locals
+#==============================================================================
+# Exceptions
+#==============================================================================
+
+class InfiniteRedirectLoop(Exception): pass
+
#===============================================================================
# Constants
#===============================================================================
@@ -193,7 +199,7 @@ def create_page(title, template, language, menu_title=None, slug=None,
if settings.CMS_MODERATOR and _thread_locals.user:
page.pagemoderator_set.create(user=_thread_locals.user)
- create_title(
+ title = create_title(
language=language,
title=title,
menu_title=menu_title,
@@ -207,8 +213,15 @@ def create_page(title, template, language, menu_title=None, slug=None,
)
del _thread_locals.user
- return page
+ redirect = page.get_redirect(language)
+ if redirect and redirect == page.get_absolute_url(language):
+ title.delete()
+ page.delete()
+ raise InfiniteRedirectLoop()
+
+ return page
+
def create_title(language, title, page, menu_title=None, slug=None,
apphook=None, redirect=None, meta_description=None,
meta_keywords=None, parent=None, overwrite_url=None):
View
21 cms/tests/admin.py
@@ -967,3 +967,24 @@ def test_clean_overwrite_url(self):
Title.objects.set_or_create(request, instance, form, 'en')
form = PageForm(data, instance=instance)
self.assertTrue(form.is_valid(), form.errors.as_text())
+
+ def test_infinite_redirect(self):
+ user = AnonymousUser()
+ user.is_superuser = True
+ user.pk = 1
+ site = Site.objects.get_current()
+ template = settings.CMS_TEMPLATES[0][0]
+ instance = create_page('Test Page', template, 'en', site=site, published=True)
+ with SettingsOverride(CMS_MODERATOR=False):
+ data = {
+ 'title': 'TestPage',
+ 'slug': 'test-page',
+ 'language': 'en',
+ 'redirect': '/',
+ 'site': site.pk,
+ 'template': template,
+ 'published': True
+ }
+
+ form = PageForm(data, instance=instance)
+ self.assertFalse(form.is_valid(), form.errors.as_text())
View
7 cms/tests/api.py
@@ -1,6 +1,6 @@
from __future__ import with_statement
from cms.api import (_generate_valid_slug, create_page, _verify_plugin_type,
- assign_user_to_page, publish_page)
+ assign_user_to_page, InfiniteRedirectLoop)
from cms.apphook_pool import apphook_pool
from cms.models.pagemodel import Page
from cms.plugin_base import CMSPluginBase
@@ -186,3 +186,8 @@ def test_create_page_can_overwrite_url(self):
page = create_page(**page_attrs)
self.assertTrue(page.get_title_obj_attribute('has_url_overwrite'))
self.assertEqual(page.get_title_obj_attribute('path'), 'test/home')
+
+ def test_create_page_infinite_redirect(self):
+ self.assertRaises(InfiniteRedirectLoop, create_page, "one",
+ "nav_playground.html", "en", published=True,
+ redirect='/')

0 comments on commit bf448a1

Please sign in to comment.