File Coverage

blib/lib/URI/Normalize.pm
Criterion Covered Total %
statement 42 42 100.0
branch 13 18 72.2
condition 3 6 50.0
subroutine 7 7 100.0
pod 2 2 100.0
total 67 75 89.3


line stmt bran cond sub pod time code
1             package URI::Normalize;
2             $URI::Normalize::VERSION = '0.001';
3 1     1   21331 use strict;
  1         2  
  1         32  
4 1     1   6 use warnings;
  1         1  
  1         33  
5              
6 1     1   5 use base 'Exporter';
  1         1  
  1         112  
7              
8 1     1   6 use URI;
  1         1  
  1         30  
9 1     1   5 use Scalar::Util qw( blessed );
  1         1  
  1         558  
10              
11             our @EXPORT_OK = qw( normalize_uri remove_dot_segments );
12              
13             # ABSTRACT: Normalize URIs according to RFC 3986
14              
15              
16             sub normalize_uri {
17 4     4 1 891 my $uri = shift;
18              
19 4 50       9 die '$uri is a required parameter to normalize_uri' unless defined $uri;
20              
21 4 50 33     29 $uri = URI->new($uri) unless blessed($uri) and $uri->isa('URI');
22              
23             # Start by placing the URI in canonical form
24 4         5989 $uri = $uri->canonical;
25 4         541 $uri = remove_dot_segments($uri);
26              
27 4         14 return $uri;
28             }
29              
30              
31             sub remove_dot_segments {
32 12     12 1 1926 my $uri = shift;
33              
34 12 50       22 die '$uri is a required parameter to normalize_uri' unless defined $uri;
35              
36 12 100 66     52 if (not (blessed($uri) and $uri->isa('URI'))) {
37 8         16 $uri = URI->new($uri);
38             }
39             else {
40 4         9 $uri = $uri->clone;
41             }
42              
43 12         322 my $input = $uri->path;
44 12         115 my $output = '';
45              
46 12         22 while (length $input > 0) {
47              
48             # A. ^./ and ^../ are deleted
49 39 50       55 next if $input =~ s{ ^ [.][.]? / }{}x;
50              
51             # B. ^/./ and ^/.$ are deleted
52 39 100       58 next if $input =~ s{ ^ /[.] (?: / | $ ) }{/}x;
53              
54             # C. ^/../ and ^/..$ remove last element of output and delete
55 35 100       51 if ($input =~ s{ ^ /[.][.] (?: / | $ ) }{/}x) {
56 10         7 my $segstart = rindex($output, '/');
57 10 100       19 next unless $segstart >= 0;
58              
59 5         5 my $segend = length($output) - $segstart;
60 5         7 substr $output, $segstart, $segend, '';
61 5         8 next;
62             }
63              
64             # D. ^.$ and ^..$ are deleted
65 25 50       30 next if $input =~ s{ ^ [.][.]? $ }{}x;
66              
67             # E. move ^/?[^/]* to output
68 25         50 $input =~ s{ (/? [^/]*) }{}x;
69 25         45 $output .= $1;
70             }
71              
72 12         19 $uri->path($output);
73 12         206 return $uri;
74             }
75              
76              
77             1;
78              
79             __END__