import re import crack import phonenumbers from django.core import validators from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from IPy import IP from ..utils.python import import_class def all_valid(kwargs): """ helper function to merge multiple validators at once """ errors = {} for field, validator in kwargs.items(): try: validator[0](*validator[1:]) except ValidationError as error: errors[field] = error if errors: raise ValidationError(errors) def validate_ipv4_address(value): msg = _("%s is not a valid IPv4 address") % value try: ip = IP(value) except: raise ValidationError(msg) if ip.version() != 4: raise ValidationError(msg) def validate_ipv6_address(value): msg = _("%s is not a valid IPv6 address") % value try: ip = IP(value) except: raise ValidationError(msg) if ip.version() != 6: raise ValidationError(msg) def validate_ip_address(value): msg = _("%s is not a valid IP address") % value try: IP(value) except: raise ValidationError(msg) def validate_name(value): """ A single non-empty line of free-form text with no whitespace. """ validators.RegexValidator('^[\.\_\-0-9a-z]+$', _("Enter a valid name (spaceless lowercase text including _.-)."), 'invalid')(value) def validate_ascii(value): try: value.encode('ascii') except UnicodeDecodeError: raise ValidationError('This is not an ASCII string.') def validate_hostname(hostname): """ Ensures that each segment * contains at least one character and a maximum of 63 characters * consists only of allowed characters * doesn't begin or end with a hyphen. http://stackoverflow.com/a/2532344 """ if len(hostname) > 255: raise ValidationError(_("Too long for a hostname.")) hostname = hostname.rstrip('.') allowed = re.compile('(?!-)[A-Z\d-]{1,63}(?<!-)$', re.IGNORECASE) for name in hostname.split('.'): if not allowed.match(name): raise ValidationError(_("Not a valid hostname (%s).") % name) def validate_username(value): validators.RegexValidator(r'^[\w.-]+$', _("Enter a valid username."))(value) def validate_password(value): try: crack.VeryFascistCheck(value) except ValueError as message: raise ValidationError("Password %s." % str(message)[3:]) def validate_url_path(value): if not re.match(r'^\/[/.a-zA-Z0-9-_]*$', value): raise ValidationError(_('"%s" is not a valid URL path.') % value) def validate_vat(vat, country): field = 'localflavor.{lower}.forms.{upper}IdentityCardNumberField'.format( lower=country.lower(), upper=country.upper() ) try: field = import_class(field) except (ImportError, AttributeError, ValueError): pass else: field().clean(vat) def validate_zipcode(zipcode, country): field = 'localflavor.{lower}.forms.{upper}PostalCodeField'.format( lower=country.lower(), upper=country.upper() ) try: field = import_class(field) except (ImportError, AttributeError, ValueError): pass else: field().clean(zipcode) def validate_phone(value, country): """ local phone number or international """ msg = _("Not a valid %s nor international phone number.") % country try: number = phonenumbers.parse(value, country) except phonenumbers.phonenumberutil.NumberParseException: raise ValidationError(msg) if not phonenumbers.is_valid_number(number): raise ValidationError(msg)