File Coverage

blib/lib/Plack/App/DirectoryIndex.pm
Criterion Covered Total %
statement 49 54 90.7
branch 10 14 71.4
condition 10 13 76.9
subroutine 9 10 90.0
pod 0 5 0.0
total 78 96 81.2


line stmt bran cond sub pod time code
1             package Plack::App::DirectoryIndex;
2              
3 1     1   105001 use parent qw[Plack::App::Directory];
  1         4  
  1         5  
4              
5 1     1   91899 use strict;
  1         3  
  1         24  
6 1     1   6 use warnings;
  1         2  
  1         34  
7              
8 1     1   5 use Plack::Util::Accessor qw[dir_index pretty];
  1         2  
  1         9  
9 1     1   64 use URI::Escape;
  1         2  
  1         709  
10              
11             our $VERSION = '0.0.4';
12              
13             sub standard_css {
14 1     1 0 25 return <
15             table {
16             width: 100%;
17             }
18             .name {
19             text-align:l eft;
20             }
21             .size, .mtime {
22             text-align: right;
23             }
24             .type {
25             width: 11em;
26             }
27             .mtime {
28             width: 15em;
29             }
30             CSS
31             }
32              
33             sub pretty_css {
34 0     0 0 0 return <
35             body {
36             color: #000;
37             background-color: #fff;
38             font-family: Calibri, Candara, Segoe, Segoe UI, Helvetica Neue, Helvetica, Optima, Arial, sans-serif;
39             font-size: normal 1em sans-serif;
40             text-align: center;
41             padding: 0;
42             margin: 0;
43             }
44              
45             h2 {
46             font-size: 2.000em;
47             font-weight: 700;
48             }
49              
50             table {
51             width: 90%;
52             margin: 3em;
53             border: 1px solid #aaa;
54             border-collapse: collapse;
55             background-color: #eee;
56             }
57              
58             thead {
59             background-color: #bbb;
60             font-weight: 700;
61             font-size: 1.300em;
62             }
63              
64             td, th {
65             padding: 1em;
66             text-align: left;
67             border-bottom: 1px solid #999999;
68             color: #000;
69             }
70              
71             tr:nth-child(even) {
72             background: #ccc;
73             }
74              
75             .size {
76             text-align: right;
77             padding-right: 1.700em;
78             }
79              
80             a:link {
81             font-size: 1.200em;
82             font-weight: 500;
83             color: #000;
84             text-decoration: none;
85             }
86              
87             a:link:hover {
88             text-decoration: underline;
89             }
90              
91             a:visited {
92             font-size: 1.200em;
93             font-weight: 500;
94             color: #301934;
95             text-decoration: none;
96             }
97             CSS
98             }
99              
100             sub file_html {
101 2     2 0 7 return <
102            
103             %s
104             %s
105             %s
106             %s
107            
108             FILE
109             }
110              
111             sub dir_html {
112 1     1 0 20 return <
113            
114            
115             %s
116            
117            
120            
121            
122            

%s

123            
124            
125            
126            
127             Name
128             Size
129             Type
130             Last Modified
131            
132            
133            
134             %s
135            
136            
137            
138            
139            
140             DIR
141             }
142              
143             # NOTE: Copied from Plack::App::Directory as that module makes it
144             # impossible to override the HTML.
145              
146             sub serve_path {
147 4     4 0 25409 my $self = shift;
148 4         10 my ($env, $dir) = @_;
149              
150 4   100     14 my $dir_index = $self->dir_index // 'index.html';
151              
152 4 100 66     121 if (-d $dir and $dir_index and -f "$dir$dir_index") {
      66        
153 3         11 $dir .= $dir_index;
154             }
155              
156 4 100       44 if (-f $dir) {
157 3         23 return $self->SUPER::serve_path($env, $dir);
158             }
159            
160 1         5 my $dir_url = $env->{SCRIPT_NAME} . $env->{PATH_INFO};
161            
162 1 50       7 if ($dir_url !~ m{/$}) {
163 0         0 return $self->return_dir_redirect($env);
164             }
165            
166 1         6 my @files = ([ "../", "Parent Directory", '', '', '' ]);
167            
168 1         9 my $dh = DirHandle->new($dir);
169 1         106 my @children;
170 1         6 while (defined(my $ent = $dh->read)) {
171 3 100 100     74 next if $ent eq '.' or $ent eq '..';
172 1         6 push @children, $ent;
173             }
174            
175 1         22 for my $basename (sort { $a cmp $b } @children) {
  0         0  
176 1         12 my $file = "$dir/$basename";
177 1         5 my $url = $dir_url . $basename;
178            
179 1         15 my $is_dir = -d $file;
180 1         10 my @stat = stat _;
181            
182 1         6 $url = join '/', map {uri_escape($_)} split m{/}, $url;
  2         41  
183            
184 1 50       16 if ($is_dir) {
185 0         0 $basename .= "/";
186 0         0 $url .= "/";
187             }
188            
189 1 50 50     21 my $mime_type = $is_dir ? 'directory' : ( Plack::MIME->mime_type($file) || 'text/plain' );
190 1         43 push @files, [ $url, $basename, $stat[7], $mime_type, HTTP::Date::time2str($stat[9]) ];
191             }
192            
193 1         35 my $path = Plack::Util::encode_html("Index of $env->{PATH_INFO}");
194             my $files = join "\n", map {
195 1         29 my $f = $_;
  2         43  
196 2         6 sprintf $self->file_html, map Plack::Util::encode_html($_), @$f;
197             } @files;
198 1 50       46 my $page = sprintf $self->dir_html, $path,
199             ($self->pretty ? $self->pretty_css : $self->standard_css),
200             $path, $files;
201            
202 1         11 return [ 200, ['Content-Type' => 'text/html; charset=utf-8'], [ $page ] ];
203             }
204              
205             1;
206              
207             __END__