File Coverage

blib/lib/OpenID/Lite/Util/URI.pm
Criterion Covered Total %
statement 66 80 82.5
branch 13 32 40.6
condition 2 6 33.3
subroutine 9 10 90.0
pod 0 2 0.0
total 90 130 69.2


line stmt bran cond sub pod time code
1             package OpenID::Lite::Util::URI;
2              
3 3     3   1733 use strict;
  3         6  
  3         140  
4 3     3   15 use warnings;
  3         5  
  3         73  
5              
6 3     3   1054 use URI;
  3         8021  
  3         78  
7 3     3   2586 use List::MoreUtils qw(none any);
  3         3724  
  3         4444  
8              
9              
10             sub _build_url_regexp {
11 3     3   9 my $class = shift;
12 3         6 my $digit = q{[0-9]};
13 3         6 my $upalpha = q{[A-Z]};
14 3         7 my $lowalpha = q{[a-z]};
15 3         36 my $alpha = qq{(?:$lowalpha|$upalpha)};
16 3         10 my $alphanum = qq{(?:$alpha|$digit)};
17 3         9 my $hex = qq{(?:$digit|[A-Fa-f])};
18 3         9 my $escaped = qq{%$hex$hex};
19 3         7 my $mark = q{[-_.!~*'()]};
20 3         9 my $unreserved = qq{(?:$alphanum|$mark)};
21 3         7 my $reserved = q{[;/?:@&=+$,]};
22 3         10 my $uric = qq{(?:$reserved|$unreserved|$escaped)};
23 3         9 my $query = qq{$uric*};
24 3         11 my $pchar = qq{(?:$unreserved|$escaped|} . q{[:@&=+$,])};
25 3         8 my $param = qq{$pchar*};
26 3         10 my $segment = qq{$pchar*(?:;$param)*};
27 3         10 my $path_segments = qq{$segment(?:/$segment)*};
28 3         10 my $abs_path = qq{/$path_segments};
29 3         7 my $port = qq{$digit*};
30 3         9 my $IPv4address = qq{$digit+\\.$digit+\\.$digit+\\.$digit+};
31 3         15 my $toplabel = qq{(?:$alpha|$alpha(?:$alphanum|-)*$alphanum)};
32 3         12 my $domainlabel = qq{(?:$alphanum|$alphanum(?:$alphanum|-)*$alphanum)};
33 3         11 my $hostname = qq{(?:$domainlabel\\.)*$toplabel\\.?};
34 3         13 my $host = qq{(?:$hostname|$IPv4address)};
35 3         8 my $fragment = qq{$uric*};
36 3         24 my $pattern = qq{https?://$host(?::$port)?(?:$abs_path(?:\\?$query)?)?(?:#$fragment)?};
37 3         17 return $pattern;
38             }
39              
40             my $REGEX = __PACKAGE__->_build_url_regexp();
41              
42             sub is_uri {
43 11     11 0 11928 my $class = shift;
44 11         14 my $uri = shift;
45 11         931 return $uri =~ /^$REGEX$/o;
46             }
47              
48             sub normalize {
49 10     10 0 19 my $class = shift;
50 10         13 my $uri = shift;
51 10         50 my $u = URI->new($uri);
52 10 50       10675 return unless $u->scheme;
53 10 50   10   401 return if ( none { $_ eq $u->scheme } qw(http https));
  10         23  
54 10 50 33     190 return unless $u->can('host') && $u->host;
55              
56 10         361 my $path = $class->_remove_dot_segments($u->path);
57 10 50       25 $path = '/' if length($path) == 0;
58 10         29 $u->path($path);
59              
60 10         259 my $u_str = $u->canonical->as_string;
61 10         746 $u_str =~ s/(%[a-fA-F0-9]{2})/uc $class->_encode($1)/eg;
  0         0  
62 10         42 return $u_str;
63             }
64              
65             sub _encode {
66 0     0   0 my ( $class, $u ) = @_;
67 0         0 my $num = substr($u, 1);
68 0         0 my $packed = pack('H*', $num);
69 0 0       0 return $packed =~ /[A-Za-z0-9._~-]/ ? $packed : $u;
70             }
71              
72             sub _remove_dot_segments {
73 10     10   115 my ( $class, $path ) = @_;
74 10         11 my @result_segments;
75 10         25 while ( length($path) > 0 ) {
76 10 50 33     116 if ($path =~ m!^\.\./!) {
    50          
    50          
    50          
    50          
    50          
    50          
77 0         0 $path = substr($path, 3);
78             } elsif ($path =~ m!^\./!) {
79 0         0 $path = substr($path, 2);
80             } elsif ($path =~ m!^/\./!) {
81 0         0 $path = substr($path, 2);
82             } elsif ($path eq q{/.}) {
83 0         0 $path = q{/};
84             } elsif ($path =~ m!^/\.\./!) {
85 0         0 $path = substr($path, 3);
86 0 0       0 pop(@result_segments) if @result_segments > 0;
87             } elsif ($path eq q{/..}) {
88 0         0 $path = q{/};
89 0 0       0 pop(@result_segments) if @result_segments > 0;
90             } elsif ($path eq q{..} || $path eq q{.}) {
91 0         0 $path = q{};
92             } else {
93 10         14 my $i = 0;
94 10 50       33 $i = 1 if substr($path, 0, 1) eq q{/};
95 10         19 $i = index($path, q{/}, $i);
96 10 50       26 $i = length($path) unless $i >= 0;
97 10         21 push(@result_segments, substr($path, 0, $i));
98 10         25 $path = substr($path, $i);
99             }
100             }
101 10         29 return join('', @result_segments);
102             }
103              
104             1;