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; |