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