line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Data::Validate::Domain; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
112521
|
use strict; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
30
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
58
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.15'; |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
856
|
use Net::Domain::TLD 1.74 qw(tld_exists); |
|
1
|
|
|
|
|
12637
|
|
|
1
|
|
|
|
|
127
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
8
|
use Exporter qw( import ); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
763
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
## no critic (Modules::ProhibitAutomaticExportation) |
13
|
|
|
|
|
|
|
our @EXPORT = qw( |
14
|
|
|
|
|
|
|
is_domain |
15
|
|
|
|
|
|
|
is_hostname |
16
|
|
|
|
|
|
|
is_domain_label |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
5
|
|
|
5
|
1
|
12
|
my $class = shift; |
21
|
|
|
|
|
|
|
|
22
|
5
|
|
33
|
|
|
31
|
return bless {@_}, ref($class) || $class; |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------- |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub is_domain { |
28
|
61
|
|
|
61
|
1
|
17571
|
my ( $value, $opt ) = _maybe_oo(@_); |
29
|
|
|
|
|
|
|
|
30
|
61
|
|
|
|
|
151
|
my ( $hostname, $bits ) = _domain_labels( $value, $opt ); |
31
|
|
|
|
|
|
|
|
32
|
61
|
100
|
|
|
|
170
|
return unless $bits; |
33
|
|
|
|
|
|
|
|
34
|
45
|
|
|
|
|
86
|
my $tld = $bits->[-1]; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# domain_allow_single_label set to true disables this check |
37
|
45
|
100
|
|
|
|
90
|
unless ( $opt->{domain_allow_single_label} ) { |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# All domains have more then 1 label (neely.cx good, com not good) |
40
|
40
|
100
|
|
|
|
49
|
return if @{$bits} < 2; |
|
40
|
|
|
|
|
115
|
|
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
36
|
100
|
|
|
|
79
|
return $hostname if $opt->{domain_disable_tld_validation}; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# If the option to enable domain_private_tld is enabled |
46
|
|
|
|
|
|
|
# and a private domain is specified, then we return if that matches |
47
|
35
|
100
|
66
|
|
|
101
|
if ( exists $opt->{domain_private_tld} |
48
|
|
|
|
|
|
|
&& ref( $opt->{domain_private_tld} ) ) { |
49
|
13
|
|
|
|
|
29
|
my $lc_tld = lc($tld); |
50
|
13
|
100
|
|
|
|
33
|
if ( ref( $opt->{domain_private_tld} ) eq 'HASH' ) { |
51
|
8
|
100
|
|
|
|
19
|
if ( exists $opt->{domain_private_tld}->{$lc_tld} ) { |
52
|
6
|
|
|
|
|
38
|
return $hostname; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
else { |
56
|
5
|
100
|
|
|
|
30
|
if ( $tld =~ $opt->{domain_private_tld} ) { |
57
|
3
|
|
|
|
|
27
|
return $hostname; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Verify domain has a valid TLD |
63
|
26
|
100
|
|
|
|
74
|
return unless tld_exists($tld); |
64
|
|
|
|
|
|
|
|
65
|
19
|
|
|
|
|
241
|
return $hostname; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------- |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub is_hostname { |
71
|
11
|
|
|
11
|
1
|
4207
|
my ( $value, $opt ) = _maybe_oo(@_); |
72
|
|
|
|
|
|
|
|
73
|
11
|
|
|
|
|
27
|
my ($hostname) = _domain_labels( $value, $opt ); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# We do not verify TLD for hostnames, as hostname.subhost is a valid hostname |
76
|
|
|
|
|
|
|
|
77
|
11
|
|
|
|
|
53
|
return $hostname; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub _domain_labels { |
81
|
72
|
|
|
72
|
|
131
|
my ( $value, $opt ) = @_; |
82
|
|
|
|
|
|
|
|
83
|
72
|
100
|
|
|
|
163
|
return unless defined($value); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# FYI: DNS limits names to 255 octets, encoded to RDATA. Each label |
86
|
|
|
|
|
|
|
# includes a length-octet prefix; those length octets count against the |
87
|
|
|
|
|
|
|
# 255-octet maximum. The number of labels exceeds the number of dots by 1 |
88
|
|
|
|
|
|
|
# (assuming no trailing dot), and the number of length octets exceeds |
89
|
|
|
|
|
|
|
# number of labels by 1 (since there’s always a trailing NUL octet). The |
90
|
|
|
|
|
|
|
# effective limit is thus 255 - 1 - 1, or 253. See |
91
|
|
|
|
|
|
|
# https://devblogs.microsoft.com/oldnewthing/20120412-00/?p=7873 for a |
92
|
|
|
|
|
|
|
# more detailed explanation of this. |
93
|
|
|
|
|
|
|
|
94
|
70
|
100
|
|
|
|
210
|
my $trailing_dot = $value =~ s/\.\z// ? q{.} : q{}; |
95
|
|
|
|
|
|
|
|
96
|
70
|
100
|
|
|
|
149
|
my $encoded_length = ( $trailing_dot ? 1 : 2 ) + length($value); |
97
|
|
|
|
|
|
|
|
98
|
70
|
100
|
|
|
|
137
|
return if $encoded_length > 255; |
99
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
99
|
my @bits; |
101
|
66
|
|
|
|
|
224
|
foreach my $label ( split /\./, $value, -1 ) { |
102
|
116
|
|
|
|
|
218
|
my $bit = is_domain_label( $label, $opt ); |
103
|
116
|
100
|
|
|
|
247
|
return unless defined $bit; |
104
|
104
|
|
|
|
|
224
|
push( @bits, $bit ); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
54
|
100
|
|
|
|
135
|
return unless @bits; |
108
|
|
|
|
|
|
|
|
109
|
51
|
|
|
|
|
204
|
return ( join( '.', @bits ) . $trailing_dot, \@bits ); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub is_domain_label { |
113
|
128
|
|
|
128
|
1
|
6040
|
my ( $value, $opt ) = _maybe_oo(@_); |
114
|
|
|
|
|
|
|
|
115
|
128
|
100
|
|
|
|
270
|
return unless defined($value); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Fix Bug: 41033 |
118
|
127
|
100
|
|
|
|
281
|
return if ( $value =~ /\n/ ); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# bail if we are dealing with more then just a hostname |
121
|
126
|
50
|
|
|
|
232
|
return if ( $value =~ /\./ ); |
122
|
126
|
|
|
|
|
182
|
my $length = length($value); |
123
|
126
|
|
|
|
|
157
|
my $hostname; |
124
|
126
|
100
|
100
|
|
|
418
|
if ( $length == 1 ) { |
|
|
100
|
|
|
|
|
|
125
|
8
|
50
|
|
|
|
19
|
if ( $opt->{domain_allow_underscore} ) { |
126
|
0
|
|
|
|
|
0
|
($hostname) = $value =~ /^([0-9A-Za-z\_])$/; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
else { |
129
|
8
|
|
|
|
|
25
|
($hostname) = $value =~ /^([0-9A-Za-z])$/; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
elsif ( $length > 1 && $length <= 63 ) { |
133
|
114
|
100
|
|
|
|
232
|
if ( $opt->{domain_allow_underscore} ) { |
134
|
9
|
|
|
|
|
39
|
($hostname) |
135
|
|
|
|
|
|
|
= $value =~ /^([0-9A-Za-z\_][0-9A-Za-z\-\_]*[0-9A-Za-z])$/; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
else { |
138
|
105
|
|
|
|
|
476
|
($hostname) |
139
|
|
|
|
|
|
|
= $value =~ /^([0-9A-Za-z][0-9A-Za-z\-]*[0-9A-Za-z])$/; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
else { |
143
|
4
|
|
|
|
|
13
|
return; |
144
|
|
|
|
|
|
|
} |
145
|
122
|
|
|
|
|
309
|
return $hostname; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub _maybe_oo { |
149
|
200
|
100
|
|
200
|
|
400
|
if ( ref $_[0] ) { |
150
|
15
|
|
|
|
|
42
|
return @_[ 1, 0 ]; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
else { |
153
|
185
|
100
|
|
|
|
528
|
return ( $_[0], ( defined $_[1] ? $_[1] : {} ) ); |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
1; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# ABSTRACT: Domain and host name validation |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
__END__ |