From 54b897cf7eb8b3840b7b53d355d6db6462002b28 Mon Sep 17 00:00:00 2001 From: Stephen Burrows Date: Wed, 11 May 2011 17:12:49 -0400 Subject: [PATCH] Removed the various philo.validators URL validators since they served no real purpose. (The only strings that would not validate actually were valid.) Added docstrings to the validators and added a validators doc file. --- docs/index.rst | 1 + docs/validators.rst | 5 +++++ philo/contrib/shipherd/models.py | 1 - philo/contrib/sobol/models.py | 4 ++-- philo/models/nodes.py | 5 ++--- philo/validators.py | 38 +++++++++----------------------- 6 files changed, 20 insertions(+), 34 deletions(-) create mode 100644 docs/validators.rst diff --git a/docs/index.rst b/docs/index.rst index a1490b3..36470fb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,7 @@ Contents: exceptions middleware signals + validators Indices and tables ================== diff --git a/docs/validators.rst b/docs/validators.rst new file mode 100644 index 0000000..f91818b --- /dev/null +++ b/docs/validators.rst @@ -0,0 +1,5 @@ +Validators +========== + +.. automodule:: philo.validators + :members: diff --git a/philo/contrib/shipherd/models.py b/philo/contrib/shipherd/models.py index 3ff5c44..a09f385 100644 --- a/philo/contrib/shipherd/models.py +++ b/philo/contrib/shipherd/models.py @@ -8,7 +8,6 @@ from django.db import models from django.forms.models import model_to_dict from philo.models import TreeEntity, Node, TreeManager, Entity, TargetURLModel -from philo.validators import RedirectValidator DEFAULT_NAVIGATION_DEPTH = 3 diff --git a/philo/contrib/sobol/models.py b/philo/contrib/sobol/models.py index 2cb1651..dbf37ef 100644 --- a/philo/contrib/sobol/models.py +++ b/philo/contrib/sobol/models.py @@ -4,6 +4,7 @@ from django.conf import settings from django.conf.urls.defaults import patterns, url from django.contrib import messages from django.core.exceptions import ValidationError +from django.core.validators import URLValidator from django.db import models from django.http import HttpResponseRedirect, Http404, HttpResponse from django.utils import simplejson as json @@ -15,7 +16,6 @@ from philo.contrib.sobol.utils import HASH_REDIRECT_GET_KEY, URL_REDIRECT_GET_KE from philo.exceptions import ViewCanNotProvideSubpath from philo.models import MultiView, Page from philo.models.fields import SlugMultipleChoiceField -from philo.validators import RedirectValidator eventlet = None if getattr(settings, 'SOBOL_USE_EVENTLET', False): @@ -83,7 +83,7 @@ class Search(models.Model): class ResultURL(models.Model): search = models.ForeignKey(Search, related_name='result_urls') - url = models.TextField(validators=[RedirectValidator()]) + url = models.TextField(validators=[URLValidator()]) def __unicode__(self): return self.url diff --git a/philo/models/nodes.py b/philo/models/nodes.py index 899303f..a9b77fb 100644 --- a/philo/models/nodes.py +++ b/philo/models/nodes.py @@ -15,7 +15,6 @@ from philo.exceptions import MIDDLEWARE_NOT_CONFIGURED, ViewCanNotProvideSubpath from philo.models.base import TreeEntity, Entity, QuerySetMapper, register_value_model from philo.models.fields import JSONField from philo.utils import ContentTypeSubclassLimiter -from philo.validators import RedirectValidator from philo.signals import view_about_to_render, view_finished_rendering @@ -291,8 +290,8 @@ class TargetURLModel(models.Model): """An abstract parent class for models which deal in targeting a url.""" #: An optional :class:`ForeignKey` to a :class:`Node`. If provided, that node will be used as the basis for the redirect. target_node = models.ForeignKey(Node, blank=True, null=True, related_name="%(app_label)s_%(class)s_related") - #: A :class:`CharField` which may contain an absolute or relative URL. This will be validated with :class:`philo.validators.RedirectValidator`. - url_or_subpath = models.CharField(max_length=200, validators=[RedirectValidator()], blank=True, help_text="Point to this url or, if a node is defined and accepts subpaths, this subpath of the node.") + #: A :class:`CharField` which may contain an absolute or relative URL, or the name of a node's subpath. + url_or_subpath = models.CharField(max_length=200, blank=True, help_text="Point to this url or, if a node is defined and accepts subpaths, this subpath of the node.") #: A :class:`~philo.models.fields.JSONField` instance. If the value of :attr:`reversing_parameters` is not None, the :attr:`url_or_subpath` will be treated as the name of a view to be reversed. The value of :attr:`reversing_parameters` will be passed into the reversal as args if it is a list or as kwargs if it is a dictionary. Otherwise it will be ignored. reversing_parameters = JSONField(blank=True, help_text="If reversing parameters are defined, url_or_subpath will instead be interpreted as the view name to be reversed.") diff --git a/philo/validators.py b/philo/validators.py index 144699e..349dd56 100644 --- a/philo/validators.py +++ b/philo/validators.py @@ -1,7 +1,6 @@ import re from django.core.exceptions import ValidationError -from django.core.validators import RegexValidator from django.template import Template, Parser, Lexer, TOKEN_BLOCK, TOKEN_VAR, TemplateSyntaxError from django.utils import simplejson as json from django.utils.html import escape, mark_safe @@ -10,6 +9,7 @@ from django.utils.translation import ugettext_lazy as _ from philo.utils import LOADED_TEMPLATE_ATTR +#: Tags which are considered insecure and are therefore always disallowed by secure :class:`TemplateValidator` instances. INSECURE_TAGS = ( 'load', 'extends', @@ -18,34 +18,8 @@ INSECURE_TAGS = ( ) -class RedirectValidator(RegexValidator): - """Based loosely on the URLValidator, but no option to verify_exists""" - regex = re.compile( - r'^(?:https?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' #domain... - r'localhost|' #localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'(?:/?|[/?#]?\S+)|' - r'[^?#\s]\S*)$', - re.IGNORECASE) - message = _(u'Enter a valid absolute or relative redirect target') - - -class URLLinkValidator(RegexValidator): - """Based loosely on the URLValidator, but no option to verify_exists""" - regex = re.compile( - r'^(?:https?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' #domain... - r'localhost|' #localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'|)' # also allow internal links - r'(?:/?|[/?#]?\S+)$', re.IGNORECASE) - message = _(u'Enter a valid absolute or relative redirect target') - - def json_validator(value): + """Validates whether ``value`` is a valid json string.""" try: json.loads(value) except Exception, e: @@ -130,6 +104,14 @@ def linebreak_iter(template_source): class TemplateValidator(object): + """ + Validates whether a string represents valid Django template code. + + :param allow: ``None`` or an iterable of tag names which are explicitly allowed. If provided, tags whose names are not in the iterable will cause a ValidationError to be raised if they are used in the template code. + :param disallow: ``None`` or an iterable of tag names which are explicitly allowed. If provided, tags whose names are in the iterable will cause a ValidationError to be raised if they are used in the template code. If a tag's name is in ``allow`` and ``disallow``, it will be disallowed. + :param secure: If the validator is set to secure, it will automatically disallow the tag names listed in :const:`INSECURE_TAGS`. Defaults to ``True``. + + """ def __init__(self, allow=None, disallow=None, secure=True): self.allow = allow self.disallow = disallow -- 2.20.1