1
|
|
|
package is |
2
|
|
|
|
3
|
|
|
import ( |
4
|
|
|
"net" |
5
|
|
|
"net/url" |
6
|
|
|
"regexp" |
7
|
|
|
"strings" |
8
|
|
|
|
9
|
|
|
"github.com/muonsoft/validation/validate" |
10
|
|
|
) |
11
|
|
|
|
12
|
|
|
// Email is used for simplified validation of an email address. It allows all values |
13
|
|
|
// with an "@" symbol in, and a "." in the second host part of the email address. |
14
|
|
|
func Email(value string) bool { |
15
|
|
|
return looseEmailRegex.MatchString(value) |
16
|
|
|
} |
17
|
|
|
|
18
|
|
|
// HTML5Email is used for validation of an email address based on pattern for HTML5 |
19
|
|
|
// (see https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address). |
20
|
|
|
func HTML5Email(value string) bool { |
21
|
|
|
return html5EmailRegex.MatchString(value) |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
// URL is used to validate that value is a valid URL string. You can use a list of restrictions |
25
|
|
|
// to additionally check for a restricted set of URLs. By default, if no restrictions are passed, |
26
|
|
|
// the function checks for the http:// and https:// schemas. |
27
|
|
|
// |
28
|
|
|
// Use the callable option to configure the list of expected schemas. If an empty string |
29
|
|
|
// is passed as a schema, then URL value may be treated as relative (without schema, e.g. "//example.com"). |
30
|
|
|
// |
31
|
|
|
// Use the [github.com/muonsoft/validation/validate.RestrictURLHosts] or |
32
|
|
|
// [github.com/muonsoft/validation/validate.RestrictURLHostByPattern] option to configure |
33
|
|
|
// the list of allowed hosts. |
34
|
|
|
func URL(value string, restrictions ...func(u *url.URL) error) bool { |
35
|
|
|
return validate.URL(value, restrictions...) == nil |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
// IP checks that a value is a valid IP address (IPv4 or IPv6). You can use a list |
39
|
|
|
// of restrictions to additionally check for a restricted range of IPs. |
40
|
|
|
func IP(value string, restrictions ...func(ip net.IP) error) bool { |
41
|
|
|
return validate.IP(value, restrictions...) == nil |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
// IPv4 checks that a value is a valid IPv4 address. You can use a list |
45
|
|
|
// of restrictions to additionally check for a restricted range of IPs. |
46
|
|
|
func IPv4(value string, restrictions ...func(ip net.IP) error) bool { |
47
|
|
|
return validate.IPv4(value, restrictions...) == nil |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
// IPv6 checks that a value is a valid IPv6 address. You can use a list |
51
|
|
|
// of restrictions to additionally check for a restricted range of IPs. |
52
|
|
|
func IPv6(value string, restrictions ...func(ip net.IP) error) bool { |
53
|
|
|
return validate.IPv6(value, restrictions...) == nil |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
// Hostname checks that a value is a valid hostname. It checks that each label |
57
|
|
|
// within a valid hostname may be no more than 63 octets long. Also, it checks that |
58
|
|
|
// the total length of the hostname must not exceed 255 characters. |
59
|
|
|
// |
60
|
|
|
// See [StrictHostname] for additional checks. |
61
|
|
|
func Hostname(value string) bool { |
62
|
|
|
return hostnameRegex.MatchString(value) && len(strings.ReplaceAll(value, ".", "")) <= 255 |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
// StrictHostname checks that a value is a valid hostname. Beside checks from Hostname function |
66
|
|
|
// it checks that hostname is fully qualified and include its top-level domain name (TLD). |
67
|
|
|
// For instance, example.com is valid but example is not. |
68
|
|
|
// |
69
|
|
|
// Additionally it checks for reserved top-level domains according to RFC 2606 and |
70
|
|
|
// that's why hostnames containing them are not considered valid: |
71
|
|
|
// .example, .invalid, .localhost, and .test. |
72
|
|
|
func StrictHostname(value string) bool { |
73
|
|
|
if !Hostname(value) { |
74
|
|
|
return false |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
domains := strings.Split(value, ".") |
78
|
|
|
if len(domains) < 2 { |
79
|
|
|
return false |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
tld := domains[len(domains)-1] |
83
|
|
|
for _, reservedTLD := range reservedTopLevelDomains { |
84
|
|
|
if tld == reservedTLD { |
85
|
|
|
return false |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
return true |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
var reservedTopLevelDomains = []string{ |
93
|
|
|
"example", |
94
|
|
|
"invalid", |
95
|
|
|
"localhost", |
96
|
|
|
"test", |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
const ( |
100
|
|
|
looseEmailPattern = `^.+\@\S+\.\S+$` |
101
|
|
|
html5EmailPattern = "^[a-zA-Z0-9.!#$%&\\'*+\\\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$" |
102
|
|
|
|
103
|
|
|
// source https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address |
104
|
|
|
hostnamePattern = `^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$` |
105
|
|
|
) |
106
|
|
|
|
107
|
|
|
var ( |
108
|
|
|
looseEmailRegex = regexp.MustCompile(looseEmailPattern) |
109
|
|
|
html5EmailRegex = regexp.MustCompile(html5EmailPattern) |
110
|
|
|
hostnameRegex = regexp.MustCompile(hostnamePattern) |
111
|
|
|
) |
112
|
|
|
|