File Coverage

blib/lib/Data/Validate/Domain.pm
Criterion Covered Total %
statement 63 64 98.4
branch 44 46 95.6
condition 8 12 66.6
subroutine 10 10 100.0
pod 4 4 100.0
total 129 136 94.8


line stmt bran cond sub pod time code
1             package Data::Validate::Domain;
2              
3 1     1   45983 use strict;
  1         1  
  1         23  
4 1     1   2 use warnings;
  1         2  
  1         34  
5              
6             our $VERSION = '0.14';
7              
8 1     1   605 use Net::Domain::TLD 1.74 qw(tld_exists);
  1         7528  
  1         96  
9              
10 1     1   5 use Exporter qw( import );
  1         1  
  1         540  
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 9 my $class = shift;
21              
22 5   33     29 return bless {@_}, ref($class) || $class;
23             }
24              
25             # -------------------------------------------------------------------------------
26              
27             sub is_domain {
28 58     58 1 12123 my ( $value, $opt ) = _maybe_oo(@_);
29              
30 58         86 my ( $hostname, $bits ) = _domain_labels( $value, $opt );
31              
32 58 100       115 return unless $bits;
33              
34 44         41 my $tld = $bits->[-1];
35              
36             # domain_allow_single_label set to true disables this check
37 44 100       67 unless ( $opt->{domain_allow_single_label} ) {
38              
39             # All domains have more then 1 label (neely.cx good, com not good)
40 39 100       25 return if @{$bits} < 2;
  39         82  
41             }
42              
43 35 100       54 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 34 100 66     74 if ( exists $opt->{domain_private_tld}
48             && ref( $opt->{domain_private_tld} ) ) {
49 13         14 my $lc_tld = lc($tld);
50 13 100       33 if ( ref( $opt->{domain_private_tld} ) eq 'HASH' ) {
51 8 100       14 if ( exists $opt->{domain_private_tld}->{$lc_tld} ) {
52 6         22 return $hostname;
53             }
54             }
55             else {
56 5 100       25 if ( $tld =~ $opt->{domain_private_tld} ) {
57 3         11 return $hostname;
58             }
59             }
60             }
61              
62             # Verify domain has a valid TLD
63 25 100       50 return unless tld_exists($tld);
64              
65 18         151 return $hostname;
66             }
67              
68             # -------------------------------------------------------------------------------
69              
70             sub is_hostname {
71 11     11 1 3034 my ( $value, $opt ) = _maybe_oo(@_);
72              
73 11         18 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         40 return $hostname;
78             }
79              
80             sub _domain_labels {
81 69     69   54 my ( $value, $opt ) = @_;
82              
83 69 100       112 return unless defined($value);
84              
85 67         57 my $length = length($value);
86 67 100 66     221 return if $length < 0 || $length > 255;
87              
88 65 100       131 my $trailing_dot = $value =~ s/\.\z// ? q{.} : q{};
89              
90 65         47 my @bits;
91 65         144 foreach my $label ( split /\./, $value, -1 ) {
92 111         120 my $bit = is_domain_label( $label, $opt );
93 111 100       207 return unless defined $bit;
94 99         137 push( @bits, $bit );
95             }
96              
97 53 100       76 return unless @bits;
98              
99 50         138 return ( join( '.', @bits ) . $trailing_dot, \@bits );
100             }
101              
102             sub is_domain_label {
103 123     123 1 4645 my ( $value, $opt ) = _maybe_oo(@_);
104              
105 123 100       178 return unless defined($value);
106              
107             # Fix Bug: 41033
108 122 100       170 return if ( $value =~ /\n/ );
109              
110             # bail if we are dealing with more then just a hostname
111 121 50       159 return if ( $value =~ /\./ );
112 121         80 my $length = length($value);
113 121         77 my $hostname;
114 121 100 100     329 if ( $length == 1 ) {
    100          
115 8 50       11 if ( $opt->{domain_allow_underscore} ) {
116 0         0 ($hostname) = $value =~ /^([0-9A-Za-z\_])$/;
117             }
118             else {
119 8         18 ($hostname) = $value =~ /^([0-9A-Za-z])$/;
120             }
121             }
122             elsif ( $length > 1 && $length <= 63 ) {
123 109 100       129 if ( $opt->{domain_allow_underscore} ) {
124 9         41 ($hostname)
125             = $value =~ /^([0-9A-Za-z\_][0-9A-Za-z\-\_]*[0-9A-Za-z])$/;
126             }
127             else {
128 100         303 ($hostname)
129             = $value =~ /^([0-9A-Za-z][0-9A-Za-z\-]*[0-9A-Za-z])$/;
130             }
131             }
132             else {
133 4         9 return;
134             }
135 117         161 return $hostname;
136             }
137              
138             sub _maybe_oo {
139 192 100   192   264 if ( ref $_[0] ) {
140 15         28 return @_[ 1, 0 ];
141             }
142             else {
143 177 100       336 return ( $_[0], ( defined $_[1] ? $_[1] : {} ) );
144             }
145             }
146              
147             1;
148              
149             # ABSTRACT: Domain and host name validation
150              
151             __END__