| 1 | Index: core/validators.py
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- core/validators.py (revision 17904)
|
|---|
| 4 | +++ core/validators.py (working copy)
|
|---|
| 5 | @@ -33,6 +33,37 @@
|
|---|
| 6 | if not self.regex.search(smart_unicode(value)):
|
|---|
| 7 | raise ValidationError(self.message, code=self.code)
|
|---|
| 8 |
|
|---|
| 9 | +class DomainNameValidator(RegexValidator):
|
|---|
| 10 | + # from URLValidator + there can be most 127 labels (at most 255 total chars)
|
|---|
| 11 | + regex = re.compile(
|
|---|
| 12 | + r'^(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.){0,126}(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?))$',
|
|---|
| 13 | + re.IGNORECASE
|
|---|
| 14 | + )
|
|---|
| 15 | + message = 'Enter a valid plain or IDNA domain name value'
|
|---|
| 16 | +
|
|---|
| 17 | + def __init__(self, *args, **kwargs):
|
|---|
| 18 | + if 'accept_idna' in kwargs:
|
|---|
| 19 | + self.accept_idna = kwargs['accept_idna']
|
|---|
| 20 | + else:
|
|---|
| 21 | + self.accept_idna = True
|
|---|
| 22 | + super(DomainNameValidator, self).__init__(*args, **kwargs)
|
|---|
| 23 | +
|
|---|
| 24 | + def __call__(self, value):
|
|---|
| 25 | + # validate
|
|---|
| 26 | + try:
|
|---|
| 27 | + super(DomainNameValidator, self).__call__(value)
|
|---|
| 28 | + except ValidationError as e:
|
|---|
| 29 | + # maybe this is a unicode-encoded IDNA string?
|
|---|
| 30 | + if not self.accept_idna: raise
|
|---|
| 31 | + if not value: raise
|
|---|
| 32 | + # convert it unicode -> ascii
|
|---|
| 33 | + try:
|
|---|
| 34 | + asciival = smart_unicode(value).encode('idna')
|
|---|
| 35 | + except UnicodeError:
|
|---|
| 36 | + raise e # raise the original ASCII error
|
|---|
| 37 | + # validate the ascii encoding of it
|
|---|
| 38 | + super(DomainNameValidator, self).__call__(asciival)
|
|---|
| 39 | +
|
|---|
| 40 | class URLValidator(RegexValidator):
|
|---|
| 41 | regex = re.compile(
|
|---|
| 42 | r'^(?:http|ftp)s?://' # http:// or https://
|
|---|
| 43 |
|
|---|