File Coverage

blib/lib/MojoMojo/Formatter/Dir.pm
Criterion Covered Total %
statement 88 88 100.0
branch 28 34 82.3
condition 3 3 100.0
subroutine 10 10 100.0
pod 5 5 100.0
total 134 140 95.7


line stmt bran cond sub pod time code
1             package MojoMojo::Formatter::Dir;
2              
3 26     26   14589 use strict;
  26         66  
  26         696  
4 26     26   123 use warnings;
  26         55  
  26         611  
5 26     26   126 use base qw/MojoMojo::Formatter/;
  26         60  
  26         1850  
6 26     26   839 use Path::Class ();
  26         61927  
  26         422  
7 26     26   8692 use MojoMojo::Formatter::File::Image;
  26         69  
  26         1739  
8              
9             my $debug=0;
10              
11             =head1 NAME
12              
13             MojoMojo::Formatter::Dir - format local directory as XHTML
14              
15             =head1 DESCRIPTION
16              
17             This formatter will format the directory argument as XHTML.
18             Usage:
19              
20             {{dir directory exclude=exclude_regex}}
21              
22              
23             For security reasons the directory must be include in 'whitelisting'. You can use path_to(DIR) to describe directory in mojomojo.conf:
24              
25             <Formatter::Dir>
26             prefix_url /myfiles
27             whitelisting __path_to(uploads)__
28             </Formatter::Dir>
29              
30              
31             =head1 METHODS
32              
33             =over 4
34              
35             =item format_content_order
36              
37             Format order can be 1-99. The File formatter runs on 92.
38              
39             =cut
40              
41 620     620 1 2517 sub format_content_order { 92 }
42              
43             =item format_content
44              
45             Calls the formatter. Takes a ref to the content as well as the
46             context object.
47              
48             =cut
49              
50              
51             sub format_content {
52 128     128 1 4753 my ( $self, $content, $c ) = @_;
53              
54              
55             # TODO : Add cache if directory is not modified
56              
57 128         676 my @lines = split /\n/, $$content;
58              
59 128         390 $$content = "";
60 128         357 foreach my $line (@lines) {
61              
62 734 100       1642 if ( $line =~ m|<p>\{\{dir\s*(\S*)\s*(\S*)}}</p>| ) {
63 4         13 my $dir = $1;
64 4         10 my $exclude = $2;
65              
66 4         8 $exclude =~ s/exclude=//;
67              
68 4         19 my $path_to = $c->path_to();
69             # use path_to(dir) ?
70 4         748 $dir =~ s/path_to\((\S*)\)/${path_to}\/$1/;
71 4         16 $dir =~ s/\/$//;
72              
73 4         7 my $error;
74 4 100       14 if ( $error = $self->checkdir($dir, $c)){
75 3         8 $$content .= $error;
76             }
77              
78 4 100       18 if ( ! $error ){
79             # format with plugin
80 1         6 $$content .= $self->format($dir, $exclude, $c);
81             }
82             }
83             else{
84 730         1375 $$content .= $line . "\n";
85             }
86             }
87 128         677 return $content;
88             }
89              
90              
91              
92             =item format
93              
94             Return the content formatted
95              
96             =cut
97              
98             sub format {
99 1     1 1 2 my $self = shift;
100 1         2 my $dir = shift;
101 1         3 my $exclude = shift;
102 1         2 my $c = shift;
103              
104 1         6 my $baseuri = $c->base_uri;
105 1         200 my $path = $c->stash->{path};
106              
107 1         76 return $self->to_xhtml($dir, $exclude, $baseuri, $path);
108             }
109              
110              
111             =item to_xhtml
112              
113             Return Directory and files lists in xhtml
114              
115             =cut
116              
117             sub to_xhtml{
118 4     4 1 3703 my ($self, $dir, $exclude, $baseuri, $path) = @_;
119              
120 4         14 my $pcdir = Path::Class::dir->new("$dir");
121              
122 4         384 my @subdirs;
123             my @files;
124 4         16 while (my $file = $pcdir->next) {
125 16 100       3615 next if ($file =~ m/^$dir\/?\.*$/ );
126 8 100 100     326 next if ( "$exclude" && grep(/$exclude/, $file ));
127              
128 6 100       75 if ( -d $file ){
129 2         50 push @subdirs , $file;
130             }
131             else{
132 4         164 push @files, $file;
133             }
134             }
135              
136             #-mxh Sort the array for predictable ordering in formatter_dir.t
137 4         316 @subdirs = sort @subdirs;
138 4         15 @files = sort @files;
139              
140 4         174 $path =~ s/^\///;
141 4         10 $path =~ s/\/$//;
142 4         13 my $url = "${baseuri}/${path}";
143              
144 4         13 my $ret;
145 4 100       16 if ( $subdirs[0] ){
146 2         13 $ret = '<div id="dirs"><ul>';
147 2 50       9 $ret .= "<li><a href=\"$url\">..</a></li>" if ( $url =! "/$path");
148 2         6 foreach my $d (@subdirs){
149 2 50       8 next if ( ! -r $d);
150 2         59 $d =~ s/$dir\///;
151              
152 2         106 $ret .= "<li><a href=\"$url/$path/$d\">[$d]</a></li>";
153             }
154 2         6 $ret .= "</ul></div>\n";
155             }
156              
157 4 100       12 if ( $files[0] ){
158 2         16 $ret .= '<div id="files"><ul>';
159 2         5 foreach my $f (@files){
160 4 50       16 next if ( ! -r $f);
161 4         182 $f =~ s/$dir\///;
162 4         325 $f =~ s/^\///;
163              
164             # Use Image controller if it is a image
165 4         19 $f =~ /.*\.(.*)$/;
166              
167             # replace dot with '_' if it's not a image
168 4 50       26 $f =~ s/\./_/
169             if ( ! MojoMojo::Formatter::File::Image->can_format($1) );
170              
171 4         21 $ret .= "<li><a href=\"$url/$f\">$f</a></li>";
172             }
173 2         5 $ret .= "</ul></div>\n";
174             }
175 4         21 return $ret;
176             }
177              
178              
179             =item checkdir
180              
181             Directory must be include in whitelisting
182              
183             =cut
184             sub checkdir{
185 6     6 1 16817 my ($self,$dir,$c) = @_;
186              
187 6 50       20 return "Append a directory after 'dir'"
188             if ( ! $dir );
189              
190 6 100       25 return "You can't use '..' in the name of directory"
191             if ( $dir =~ /\.\./ );
192              
193 5         20 my $confwl = $c->config->{'Formatter::Dir'}{whitelisting};
194 5 50       478 my @whitelist = ref $confwl eq 'ARRAY' ?
195             @$confwl : ( $confwl );
196             # Add '/' if not exist at the end of whitelist directories
197 5         137 my @wl = map { $_ . '/' } # Add '/'
198 5         12 ( map{ /(\S*[^\/])/ } # Delete '/' if exist
  5         20  
199             @whitelist );
200              
201             # Add '/' if not exist at the end of dierctory
202 5         37 $dir =~ s|^(\S*[^/])$|$1\/|;
203              
204             # if $dir is not include in whitelisting
205 5 100       42 if ( ! map ( $dir =~ m|^$_| , @wl) ){
206 2         11 return "Directory '$dir' must be include in whitelisting ! see Formatter::Dir:whitelisting in mojomojo.conf"
207             }
208              
209              
210 3 100       66 return "'$dir' is not a directory !\n"
211             if ( ! -d $dir );
212              
213 2         22 return 0;
214             }
215              
216             =back
217              
218             =head1 SEE ALSO
219              
220             L<MojoMojo>
221              
222             =head1 AUTHORS
223              
224             Daniel Brosseau <dab@catapulse.org>
225              
226             =head1 LICENSE
227              
228             This module is licensed under the same terms as Perl itself.
229              
230             =cut
231              
232             1;