File Coverage

blib/lib/Plack/App/Directory.pm
Criterion Covered Total %
statement 57 63 90.4
branch 7 10 70.0
condition 7 8 87.5
subroutine 11 12 91.6
pod 0 3 0.0
total 82 96 85.4


";
line stmt bran cond sub pod time code
1             package Plack::App::Directory;
2 1     1   424 use parent qw(Plack::App::File);
  1         2  
  1         5  
3 1     1   36 use strict;
  1         2  
  1         16  
4 1     1   4 use warnings;
  1         2  
  1         18  
5 1     1   3 use Plack::Util;
  1         2  
  1         15  
6 1     1   4 use HTTP::Date;
  1         1  
  1         36  
7 1     1   4 use Plack::MIME;
  1         2  
  1         26  
8 1     1   1068 use DirHandle;
  1         466  
  1         67  
9 1     1   7 use URI::Escape;
  1         1  
  1         45  
10 1     1   363 use Plack::Request;
  1         3  
  1         480  
11              
12             # Stolen from rack/directory.rb
13             my $dir_file = "
%s%s%s%s
14             my $dir_page = <
15            
16             %s
17            
18            
25            
26            

%s

27            
28            
29            
30             Name
31             Size
32             Type
33             Last Modified
34            
35             %s
36            
37            
38            
39             PAGE
40              
41             sub should_handle {
42 3     3 0 7 my($self, $file) = @_;
43 3   66     65 return -d $file || -f $file;
44             }
45              
46             sub return_dir_redirect {
47 0     0 0 0 my ($self, $env) = @_;
48 0         0 my $uri = Plack::Request->new($env)->uri;
49 0         0 return [ 301,
50             [
51             'Location' => $uri . '/',
52             'Content-Type' => 'text/plain',
53             'Content-Length' => 8,
54             ],
55             [ 'Redirect' ],
56             ];
57             }
58              
59             sub serve_path {
60 3     3 0 7 my($self, $env, $dir) = @_;
61              
62 3 100       33 if (-f $dir) {
63 1         10 return $self->SUPER::serve_path($env, $dir);
64             }
65              
66 2         8 my $dir_url = $env->{SCRIPT_NAME} . $env->{PATH_INFO};
67              
68 2 50       9 if ($dir_url !~ m{/$}) {
69 0         0 return $self->return_dir_redirect($env);
70             }
71              
72 2         7 my @files = ([ "../", "Parent Directory", '', '', '' ]);
73              
74 2         12 my $dh = DirHandle->new($dir);
75 2         130 my @children;
76 2         7 while (defined(my $ent = $dh->read)) {
77 10 100 100     170 next if $ent eq '.' or $ent eq '..';
78 6         23 push @children, $ent;
79             }
80              
81 2         29 for my $basename (sort { $a cmp $b } @children) {
  6         14  
82 6         70 my $file = "$dir/$basename";
83 6         11 my $url = $dir_url . $basename;
84              
85 6         68 my $is_dir = -d $file;
86 6         18 my @stat = stat _;
87              
88 6         21 $url = join '/', map {uri_escape($_)} split m{/}, $url;
  12         111  
89              
90 6 50       79 if ($is_dir) {
91 0         0 $basename .= "/";
92 0         0 $url .= "/";
93             }
94              
95 6 50 100     26 my $mime_type = $is_dir ? 'directory' : ( Plack::MIME->mime_type($file) || 'text/plain' );
96 6         22 push @files, [ $url, $basename, $stat[7], $mime_type, HTTP::Date::time2str($stat[9]) ];
97             }
98              
99 2         30 my $path = Plack::Util::encode_html("Index of $env->{PATH_INFO}");
100             my $files = join "\n", map {
101 2         5 my $f = $_;
  8         10  
102 8         14 sprintf $dir_file, map Plack::Util::encode_html($_), @$f;
103             } @files;
104 2         22 my $page = sprintf $dir_page, $path, $path, $files;
105              
106 2         13 return [ 200, ['Content-Type' => 'text/html; charset=utf-8'], [ $page ] ];
107             }
108              
109             1;
110              
111             __END__