File Coverage

lib/HTTP/Server/Directory.pm
Criterion Covered Total %
statement 18 61 29.5
branch 0 40 0.0
condition 0 2 0.0
subroutine 6 20 30.0
pod 0 6 0.0
total 24 129 18.6


line stmt bran cond sub pod time code
1             # Copyrights 2008 by Mark Overmeer.
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 1.05.
5             package HTTP::Server::Directory;
6 1     1   5 use vars '$VERSION';
  1         2  
  1         56  
7             $VERSION = '0.11';
8              
9 1     1   5 use warnings;
  1         2  
  1         27  
10 1     1   43 use strict;
  1         2  
  1         40  
11              
12 1     1   1015 use Log::Report 'httpd-multiplex', syntax => 'SHORT';
  1         93230  
  1         6  
13              
14 1     1   333 use Net::CIDR qw/cidrlookup/;
  1         2  
  1         73  
15 1     1   6 use File::Spec ();
  1         2  
  1         957  
16              
17             sub _allow_cleanup($);
18             sub _allow_match($$$$);
19             sub _filename_trans($$);
20              
21              
22             sub new(@)
23 0     0 0   { my $class = shift;
24 0 0         my $args = @_==1 ? shift : {@_};
25 0           (bless {}, $class)->init($args);
26             }
27              
28             sub init($)
29 0     0 0   { my ($self, $args) = @_;
30              
31 0   0       my $path = $self->{HSD_path} = $args->{path} || '/';
32 0 0         my $loc = $args->{location}
33             or error __x"directory definition requires location";
34              
35 0 0         if(ref $loc eq 'CODE') {;}
36             else
37 0 0         { File::Spec->file_name_is_absolute($loc)
38             or error __x"directory location {loc} for path {path} not absolute"
39             , loc => $loc, path => $path;
40 0 0         -d $loc
41             or error __x"directory location {loc} for path {path} does not exist"
42             , loc => $loc, path => $path;
43              
44 0 0         substr($loc,-1) eq '/' or $loc .= '/';
45             }
46 0           $self->{HSD_loc} = $loc;
47 0           $self->{HSD_fn} = _filename_trans $path, $loc;
48              
49 0           $self->{HSD_allow} = _allow_cleanup $args->{allow};
50 0           $self->{HSD_deny} = _allow_cleanup $args->{deny};
51              
52 0           $self;
53             }
54              
55             #-----------------
56              
57 0     0 0   sub path() {shift->{HSD_path}}
58 0     0 0   sub location() {shift->{HSD_location}}
59              
60             #-----------------
61              
62             sub allow($$$$)
63 0     0 0   { my ($self, $client, $session, $req, $uri) = @_;
64 0 0         if(my $allow = $self->{HSD_allow})
65 0 0         { $self->_allow_match($client, $session, $uri, $allow) or return 0;
66             }
67 0 0         if(my $deny = $self->{HSD_deny})
68 0 0         { $self->_allow_match($client, $session, $uri, $deny) and return 0;
69             }
70 0           1;
71             }
72              
73             sub _allow_match($$$$)
74 0     0     { my ($self, $client, $session, $uri, $rules) = @_;
75 0           my ($ip, $host) = @$client{'ip', 'host'};
76 0 0         first { $_->($ip, $host, $session, $uri) } @$rules ? 1 : 0;
  0            
77             }
78              
79             sub _allow_cleanup($)
80 0 0   0     { my $p = shift or return;
81 0           my @p;
82 0 0         foreach my $r (ref $p eq 'ARRAY' ? @$p : $p)
83 0     0     { push @p
84             , ref $r eq 'CODE' ? $r
85             : index($r, ':') >= 0 ? sub {cidrlookup $_[0], $r} # IPv6
86 0     0     : $r !~ m/[a-zA-Z]/ ? sub {cidrlookup $_[0], $r} # IPv4
87 0     0     : $r =~ s/^\.// ? sub {$_[1] =~ qr/(^|\.)\Q$r\E$/i} # Domain
88 0     0     : sub {lc($_[1]) eq lc($r)} # hostname
89 0 0         }
    0          
    0          
    0          
90 0 0         @p ? \@p : undef;
91             }
92              
93              
94 0     0 0   sub filename($) { $_[0]->{HSD_fn}->($_[1]) }
95              
96             sub _filename_trans($$)
97 0     0     { my ($path, $loc) = @_;
98 0 0         return $loc if ref $loc eq 'CODE';
99             sub
100 0     0     { my $x = shift;
101 0 0         $x =~ s!^\Q$path!$loc! or panic "path $x not within $path";
102 0           $x;
103 0           };
104             }
105              
106              
107             1;