forked from bear/ronkyuu
/
validators.py
90 lines (75 loc) · 2.91 KB
/
validators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env python
"""
:copyright: (c) 2013 by Mike Taylor and Kartik Prabhu
:license: MIT, see LICENSE for more details.
IndieWeb URL Validation
Regex and URL validators borrowed from django.core.validators
https://github.com/django/django/blob/master/django/core/validators.py
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.
BSD Licensed
"""
import re
from urlparse import urlsplit, urlunsplit
class RegexValidator(object):
regex = ''
message = 'Enter a valid value.'
def __init__(self, regex=None, message=None):
if regex is not None:
self.regex = regex
if message is not None:
self.message = message
# Compile the regex if it was not passed pre-compiled.
if isinstance(self.regex, str):
self.regex = re.compile(self.regex)
def __call__(self, value):
"""
Validates that the input matches the regular expression.
"""
if not self.regex.search(value):
raise ValueError(self.message)
def __eq__(self, other):
return isinstance(other, RegexValidator) and (self.regex == other.regex) and (self.message == other.message)
class URLValidator(RegexValidator):
regex = re.compile(
r'^(?:[a-z0-9\.\-]*)://' # scheme is validated separately
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
r'localhost|' # localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4
r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6
r'(?::\d+)?' # optional port
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
message = 'Enter a valid URL.'
# check only http and https
schemes = ['http', 'https']
def __init__(self, schemes=None, **kwargs):
super(URLValidator, self).__init__(**kwargs)
if schemes is not None:
self.schemes = schemes
def __call__(self, value):
e = ValueError(self.message)
#check for None, and empty string
if value in {None, ''}:
raise e
value = str(value)
# Check first if the scheme is valid
scheme = value.split('://')[0].lower()
if scheme not in self.schemes:
raise e
# Then check full URL
try:
super(URLValidator, self).__call__(value)
except ValueError:
# Trivial case failed. Try for possible IDN domain
if value:
scheme, netloc, path, query, fragment = urlsplit(value)
try:
netloc = netloc.encode('idna').decode('ascii') # IDN -> ACE
except UnicodeError: # invalid domain part
raise e
url = urlunsplit((scheme, netloc, path, query, fragment))
super(URLValidator, self).__call__(url)
else:
raise e
else:
url = value