blib/lib/POE/Component/Server/HTTPServer/StaticHandler.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 15 | 76 | 19.7 |
branch | 0 | 24 | 0.0 |
condition | n/a | ||
subroutine | 5 | 9 | 55.5 |
pod | 3 | 3 | 100.0 |
total | 23 | 112 | 20.5 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package POE::Component::Server::HTTPServer::StaticHandler; | ||||||
2 | 1 | 1 | 1054 | use strict; | |||
1 | 1 | ||||||
1 | 31 | ||||||
3 | 1 | 1 | 1226 | use HTTP::Status; | |||
1 | 2 | ||||||
1 | 315 | ||||||
4 | 1 | 1 | 746 | use MIME::Types; | |||
1 | 4708 | ||||||
1 | 34 | ||||||
5 | 1 | 1 | 8 | use POE::Component::Server::HTTPServer::Handler; | |||
1 | 2 | ||||||
1 | 43 | ||||||
6 | 1 | 1 | 4 | use base 'POE::Component::Server::HTTPServer::Handler'; | |||
1 | 1 | ||||||
1 | 644 | ||||||
7 | |||||||
8 | # _init( $root [, index_file => $index_file] [, auto_index => $auto_index ] ) | ||||||
9 | # Files will be served relative to $root | ||||||
10 | # If a request is made for a directory, then: | ||||||
11 | # If $index_file is defined and found, it will be returned. | ||||||
12 | # Else, if $auto_index is defined, a directory index will be generated. | ||||||
13 | # Otherwise, this handler will pass on the request. | ||||||
14 | sub _init { | ||||||
15 | 0 | 0 | my $self = shift; | ||||
16 | 0 | my $root = shift; | |||||
17 | 0 | my %args = @_; | |||||
18 | 0 | $self->{root} = $root; | |||||
19 | 0 | $self->{mimetypes} = MIME::Types->new(); # ugh | |||||
20 | 0 | 0 | if ( exists($args{index_file}) ) { | ||||
21 | 0 | $self->{index_file} = $args{index_file}; | |||||
22 | } else { | ||||||
23 | 0 | $self->{index_file} = 'index.html'; | |||||
24 | } | ||||||
25 | 0 | 0 | if ( exists($args{auto_index}) ) { | ||||
26 | 0 | $self->{auto_index} = $args{auto_index}; | |||||
27 | } else { | ||||||
28 | 0 | $self->{auto_index} = 0; | |||||
29 | } | ||||||
30 | } | ||||||
31 | |||||||
32 | sub handle { | ||||||
33 | 0 | 0 | 1 | my $self = shift; | |||
34 | 0 | my $context = shift; | |||||
35 | #print "Handling static request (", __PACKAGE__, ")\n"; | ||||||
36 | 0 | my $cpath = $context->{contextpath}; | |||||
37 | #print "Context path=$cpath\n"; | ||||||
38 | # scrub path (badly): XXX fix this with file::spec or the like | ||||||
39 | 0 | 0 | if ( $cpath =~ m[(^|/)\.\.(/|$)] ) { | ||||
40 | 0 | warn "Will not serve dangerous path '$cpath'\n"; # should keep silent here | |||||
41 | 0 | return H_CONT; | |||||
42 | } | ||||||
43 | 0 | my $filepath = "$self->{root}/$cpath"; | |||||
44 | #print "static root: $filepath\n"; | ||||||
45 | 0 | 0 | if ( -d $filepath ) { | ||||
0 | |||||||
46 | 0 | return $self->handle_directory($filepath, $context); | |||||
47 | } elsif ( -f $filepath ) { | ||||||
48 | 0 | return $self->handle_plainfile($filepath, $context); | |||||
49 | } else { | ||||||
50 | #print "Request for non-existant file: $filepath\n"; | ||||||
51 | 0 | return H_CONT; | |||||
52 | } | ||||||
53 | } | ||||||
54 | |||||||
55 | sub handle_plainfile { | ||||||
56 | 0 | 0 | 1 | my $self = shift; | |||
57 | 0 | my $filepath = shift; | |||||
58 | 0 | my $context = shift; | |||||
59 | 0 | 0 | if ( open(my $in, $filepath) ) { | ||||
60 | 0 | binmode($in); | |||||
61 | 0 | local $/ = undef; | |||||
62 | 0 | $context->{response}->code( RC_OK ); | |||||
63 | 0 | my $type = $self->{mimetypes}->mimeTypeOf( $filepath ); | |||||
64 | 0 | 0 | $type='text/plain' unless defined($type); | ||||
65 | 0 | $context->{response}->content_type( $type ); | |||||
66 | 0 | $context->{response}->content(<$in>); | |||||
67 | 0 | return H_FINAL; | |||||
68 | } else { | ||||||
69 | #print "Failed to open $filepath ($!)\n"; | ||||||
70 | 0 | $context->{error_message} = $!; # XXX security: returned with 404 response | |||||
71 | 0 | return H_CONT; | |||||
72 | } | ||||||
73 | } | ||||||
74 | |||||||
75 | sub handle_directory { | ||||||
76 | 0 | 0 | 1 | my $self = shift; | |||
77 | 0 | my $filepath = shift; | |||||
78 | 0 | my $context = shift; | |||||
79 | #print "directory( $filepath )\n"; | ||||||
80 | 0 | 0 | if ( $self->{index_file} ) { | ||||
81 | 0 | my $index_file = "$filepath/$self->{index_file}"; | |||||
82 | 0 | 0 | if ( -e $index_file ) { | ||||
83 | 0 | return $self->handle_plainfile( $index_file, $context ); | |||||
84 | } | ||||||
85 | } | ||||||
86 | 0 | 0 | if ( $self->{auto_index} ) { | ||||
87 | # nasty hack: should probably just not include this option | ||||||
88 | 0 | 0 | if ( opendir(my $dir, $filepath) ) { | ||||
89 | 0 | my $page = qq{ |
|||||
90 | 0 | $page .= qq{\n}; | |||||
91 | 0 | $page .= qq{ Directory Index \n}; |
|||||
92 | 0 | $page .= qq{
|
|||||
93 | 0 | my $base = $context->{request}->uri; | |||||
94 | 0 | while(my $fn = readdir($dir)) { | |||||
95 | 0 | 0 | next if $fn=~/^\./; | ||||
96 | 0 | $page .= qq{ |
|||||
97 | } | ||||||
98 | 0 | $page .= qq{\n}; | |||||
99 | 0 | $page .= qq{\n}; | |||||
100 | 0 | $context->{response}->code( RC_OK ); | |||||
101 | 0 | $context->{response}->content( $page ); | |||||
102 | 0 | return H_FINAL; | |||||
103 | } else { | ||||||
104 | # XXX should this class of problem be a 500? | ||||||
105 | #print "Failed to opendir ($!)\n"; | ||||||
106 | 0 | $context->{error_message} = $!; # XXX security: returned with 404 resp | |||||
107 | 0 | return H_CONT; | |||||
108 | } | ||||||
109 | } | ||||||
110 | 0 | return H_CONT; | |||||
111 | } | ||||||
112 | |||||||
113 | 1; | ||||||
114 | __END__ |