diff -r 8d941af65caf -r 77b6da96e6f1 web/lib/django/core/validators.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/django/core/validators.py Wed Jun 02 18:57:35 2010 +0200 @@ -0,0 +1,172 @@ +import re +import urlparse + +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import smart_unicode + +# These values, if given to validate(), will trigger the self.required check. +EMPTY_VALUES = (None, '', [], (), {}) + +try: + from django.conf import settings + URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT +except ImportError: + # It's OK if Django settings aren't configured. + URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' + +class RegexValidator(object): + regex = '' + message = _(u'Enter a valid value.') + code = 'invalid' + + def __init__(self, regex=None, message=None, code=None): + if regex is not None: + self.regex = regex + if message is not None: + self.message = message + if code is not None: + self.code = code + + if isinstance(self.regex, basestring): + self.regex = re.compile(regex) + + def __call__(self, value): + """ + Validates that the input matches the regular expression. + """ + if not self.regex.search(smart_unicode(value)): + raise ValidationError(self.message, code=self.code) + +class URLValidator(RegexValidator): + 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+)$', re.IGNORECASE) + + def __init__(self, verify_exists=False, validator_user_agent=URL_VALIDATOR_USER_AGENT): + super(URLValidator, self).__init__() + self.verify_exists = verify_exists + self.user_agent = validator_user_agent + + def __call__(self, value): + try: + super(URLValidator, self).__call__(value) + except ValidationError, e: + # Trivial case failed. Try for possible IDN domain + if value: + value = smart_unicode(value) + scheme, netloc, path, query, fragment = urlparse.urlsplit(value) + try: + netloc = netloc.encode('idna') # IDN -> ACE + except UnicodeError: # invalid domain part + raise e + url = urlparse.urlunsplit((scheme, netloc, path, query, fragment)) + super(URLValidator, self).__call__(url) + else: + raise + else: + url = value + + if self.verify_exists: + import urllib2 + headers = { + "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", + "Accept-Language": "en-us,en;q=0.5", + "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Connection": "close", + "User-Agent": self.user_agent, + } + try: + req = urllib2.Request(url, None, headers) + u = urllib2.urlopen(req) + except ValueError: + raise ValidationError(_(u'Enter a valid URL.'), code='invalid') + except: # urllib2.URLError, httplib.InvalidURL, etc. + raise ValidationError(_(u'This URL appears to be a broken link.'), code='invalid_link') + + +def validate_integer(value): + try: + int(value) + except (ValueError, TypeError), e: + raise ValidationError('') + +class EmailValidator(RegexValidator): + + def __call__(self, value): + try: + super(EmailValidator, self).__call__(value) + except ValidationError, e: + # Trivial case failed. Try for possible IDN domain-part + if value and u'@' in value: + parts = value.split(u'@') + domain_part = parts[-1] + try: + parts[-1] = parts[-1].encode('idna') + except UnicodeError: + raise e + super(EmailValidator, self).__call__(u'@'.join(parts)) + else: + raise + +email_re = re.compile( + r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string + r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE) # domain +validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid') + +slug_re = re.compile(r'^[-\w]+$') +validate_slug = RegexValidator(slug_re, _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 'invalid') + +ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') +validate_ipv4_address = RegexValidator(ipv4_re, _(u'Enter a valid IPv4 address.'), 'invalid') + +comma_separated_int_list_re = re.compile('^[\d,]+$') +validate_comma_separated_integer_list = RegexValidator(comma_separated_int_list_re, _(u'Enter only digits separated by commas.'), 'invalid') + + +class BaseValidator(object): + compare = lambda self, a, b: a is not b + clean = lambda self, x: x + message = _(u'Ensure this value is %(limit_value)s (it is %(show_value)s).') + code = 'limit_value' + + def __init__(self, limit_value): + self.limit_value = limit_value + + def __call__(self, value): + cleaned = self.clean(value) + params = {'limit_value': self.limit_value, 'show_value': cleaned} + if self.compare(cleaned, self.limit_value): + raise ValidationError( + self.message % params, + code=self.code, + params=params, + ) + +class MaxValueValidator(BaseValidator): + compare = lambda self, a, b: a > b + message = _(u'Ensure this value is less than or equal to %(limit_value)s.') + code = 'max_value' + +class MinValueValidator(BaseValidator): + compare = lambda self, a, b: a < b + message = _(u'Ensure this value is greater than or equal to %(limit_value)s.') + code = 'min_value' + +class MinLengthValidator(BaseValidator): + compare = lambda self, a, b: a < b + clean = lambda self, x: len(x) + message = _(u'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).') + code = 'min_length' + +class MaxLengthValidator(BaseValidator): + compare = lambda self, a, b: a > b + clean = lambda self, x: len(x) + message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).') + code = 'max_length' +