File Coverage

blib/lib/CGI/SSI.pm
Criterion Covered Total %
statement 255 343 74.3
branch 93 182 51.1
condition 28 50 56.0
subroutine 50 54 92.5
pod 14 16 87.5
total 440 645 68.2


line stmt bran cond sub pod time code
1             package CGI::SSI;
2 1     1   1112 use strict;
  1         2  
  1         38  
3            
4 1     1   962 use HTML::SimpleParse;
  1         6873  
  1         42  
5 1     1   1105 use File::Spec::Functions; # catfile()
  1         905  
  1         100  
6 1     1   827 use FindBin;
  1         1183  
  1         42  
7 1     1   1036 use LWP::UserAgent;
  1         112381  
  1         43  
8 1     1   15 use HTTP::Response;
  1         2  
  1         22  
9 1     1   1659 use HTTP::Cookies;
  1         15002  
  1         279  
10 1     1   12 use URI;
  1         2  
  1         271  
11 1     1   1723 use Date::Format;
  1         9365  
  1         585  
12            
13             our $VERSION = '0.92';
14            
15             our $DEBUG = 0;
16            
17             sub import {
18 1     1   20 my($class,%args) = @_;
19 1 50       20 return unless exists $args{'autotie'};
20 0 0       0 $args{'filehandle'} = $args{'autotie'} =~ /::/ ? $args{'autotie'} : caller().'::'.$args{'autotie'};
21 1     1   13 no strict 'refs';
  1         2  
  1         10891  
22 0         0 my $self = tie(*{$args{'filehandle'}},$class,%args);
  0         0  
23 0         0 return $self;
24             }
25            
26             my($gmt,$loc,$lmod);
27            
28             sub new {
29 26     26 1 18684 my($class,%args) = @_;
30 26         104 my $self = bless {}, $class;
31            
32 26         96 $self->{'_handle'} = undef;
33            
34 26         52 my $script_name = '';
35 26 50       101 if(exists $ENV{'SCRIPT_NAME'}) {
36 0         0 ($script_name) = $ENV{'SCRIPT_NAME'} =~ /([^\/]+)$/;
37             }
38            
39 26         232 tie $gmt, 'CGI::SSI::Gmt', $self;
40 26         153 tie $loc, 'CGI::SSI::Local', $self;
41 26         106 tie $lmod, 'CGI::SSI::LMOD', $self;
42            
43 26   50     798 $ENV{'DOCUMENT_ROOT'} ||= '';
44 26   66     363 $self->{'_variables'} = {
      66        
      66        
45             DOCUMENT_URI => ($args{'DOCUMENT_URI'} || $ENV{'SCRIPT_NAME'}),
46             DATE_GMT => $gmt,
47             DATE_LOCAL => $loc,
48             LAST_MODIFIED => $lmod,
49             DOCUMENT_NAME => ($args{'DOCUMENT_NAME'} || $script_name),
50             DOCUMENT_ROOT => ($args{'DOCUMENT_ROOT'} || $ENV{DOCUMENT_ROOT}),
51             };
52            
53 26   100     346 $self->{'_config'} = {
      100        
      100        
54             errmsg => ($args{'errmsg'} || '[an error occurred while processing this directive]'),
55             sizefmt => ($args{'sizefmt'} || 'abbrev'),
56             timefmt => ($args{'timefmt'} || undef),
57             };
58            
59 26   100     130 $self->{_max_recursions} = $args{MAX_RECURSIONS} || 100; # no "infinite" loops
60 26         53 $self->{_recursions} = {};
61            
62 26   66     368 $self->{_cookie_jar} = $args{COOKIE_JAR} || HTTP::Cookies->new();
63            
64 26         542 $self->{'_in_if'} = 0;
65 26         109 $self->{'_suspend'} = [0];
66 26         72 $self->{'_seen_true'} = [1];
67            
68 26         78 return $self;
69             }
70            
71             sub TIEHANDLE {
72 1     1   1403 my($class,%args) = @_;
73 1         10 my $self = $class->new(%args);
74 1         3 $self->{'_handle'} = do { local *STDOUT };
  1         7  
75 1         3 my $handle_to_tie = '';
76 1 50       5 if($args{'filehandle'} !~ /::/) {
77 1         4 $handle_to_tie = caller().'::'.$args{'filehandle'};
78             } else {
79 0         0 $handle_to_tie = $args{'filehandle'};
80             }
81 1 50       27 open($self->{'_handle'},'>&'.$handle_to_tie) or die "Failed to copy the filehandle ($handle_to_tie): $!";
82 1         5 return $self;
83             }
84            
85             sub PRINT {
86 2     2   403 my $self = shift;
87 2         3 print {$self->{'_handle'}} map { $self->process($_) } @_;
  2         6  
  2         6  
88             }
89            
90             sub PRINTF {
91 0     0   0 my $self = shift;
92 0         0 my $fmt = shift;
93 0         0 printf {$self->{'_handle'}} $fmt, map { $self->process($_) } @_;
  0         0  
  0         0  
94             }
95            
96             sub CLOSE {
97 1     1   7 my($self) = @_;
98 1         49 close $self->{'_handle'};
99             }
100            
101             sub process {
102 62     62 0 257 my($self,@shtml) = @_;
103 62         268 my $processed = '';
104 62         586 @shtml = split(/()/s,join '',@shtml);
105 62         144 local($HTML::SimpleParse::FIX_CASE) = 0; # prevent var => value from becoming VAR => value
106 62         233 for my $token (@shtml) {
107             # next unless(defined $token and length $token);
108 195 100       917 if($token =~ /^$/s) {
109 95         231 $processed .= $self->_process_ssi_text($self->_interp_vars($1));
110             } else {
111 100 100       301 next if $self->_suspended;
112 82         176 $processed .= $token;
113             }
114             }
115 62         1131 return $processed;
116             }
117            
118             sub _process_ssi_text {
119 95     95   209 my($self,$text) = @_;
120            
121             # are we suspended?
122 95 50 66     219 return '' if($self->_suspended and $text !~ /^(?:if|else|elif|endif)\b/);
123            
124             # what's the first \S+?
125 95 50       440 if($text !~ s/^(\S+)\s*//) {
126 0         0 warn ref($self)." error: failed to find method name at beginning of string: '$text'.\n";
127 0         0 return $self->{'_config'}->{'errmsg'};
128             }
129 95         315 my $method = $1;
130 95         2036 return $self->$method( HTML::SimpleParse->parse_args($text) );
131             }
132            
133             # many thanks to Apache::SSI
134             sub _interp_vars {
135 95     95   280 local $^W = 0;
136 95         208 my($self,$text) = @_;
137 95         147 my($a,$b,$c) = ('','','');
138 95         189 $text =~ s{ (^|[^\\]) (\\\\)* \$(?:\{)?(\w+)(?:\})? }
139 2         19 {($a,$b,$c)=($1,$2,$3); $a . substr($b,length($b)/2) . $self->_echo($c) }exg;
  2         49  
140 95         515 return $text;
141             }
142            
143             # for internal use only - returns the thing passed in if it's not defined. echo() returns '' in that case.
144             sub _echo {
145 2     2   9 my($self,$key,$var) = @_;
146 2 50       31 $var = $key if @_ == 2;
147            
148 2 100       35 if($var eq 'DATE_LOCAL') {
    50          
    50          
149 1         4 return $loc;
150             } elsif($var eq 'DATE_GMT') {
151 0         0 return $gmt;
152             } elsif($var eq 'LAST_MODIFIED') {
153 0         0 return $lmod;
154             }
155            
156 1 50       24 return $self->{'_variables'}->{$var} if exists $self->{'_variables'}->{$var};
157 0 0       0 return $ENV{$var} if exists $ENV{$var};
158 0         0 return $var;
159             }
160            
161             #
162             # ssi directive methods
163             #
164            
165             sub config {
166 5     5 1 2184 my($self,$type,$value) = @_;
167 5 100       34 if($type =~ /^timefmt$/i) {
    100          
    50          
168 3         9 $self->{'_config'}->{'timefmt'} = $value;
169             } elsif($type =~ /^sizefmt$/i) {
170 1 50       7 if(lc $value eq 'abbrev') {
    50          
171 0         0 $self->{'_config'}->{'sizefmt'} = 'abbrev';
172             } elsif(lc $value eq 'bytes') {
173 1         4 $self->{'_config'}->{'sizefmt'} = 'bytes';
174             } else {
175 0         0 warn ref($self)." error: value for sizefmt is '$value'. It must be 'abbrev' or 'bytes'.\n";
176 0         0 return $self->{'_config'}->{'errmsg'};
177             }
178             } elsif($type =~ /^errmsg$/i) {
179 1         3 $self->{'_config'}->{'errmsg'} = $value;
180             } else {
181 0         0 warn ref($self)." error: arg to config is '$type'. It must be one of: 'timefmt', 'sizefmt', or 'errmsg'.\n";
182 0         0 return $self->{'_config'}->{'errmsg'};
183             }
184 5         13 return '';
185             }
186            
187             sub set {
188 7     7 1 154 my($self,%args) = @_;
189 7 100       21 if(scalar keys %args > 1) {
190 3         11 $self->{'_variables'}->{$args{'var'}} = $args{'value'};
191             } else { # var => value notation
192 4         12 my($var,$value) = %args;
193 4         9 $self->{'_variables'}->{$var} = $value;
194             }
195 7         28 return '';
196             }
197            
198             sub echo {
199 12     12 1 149 my($self,$key,$var) = @_;
200 12 100       30 $var = $key if @_ == 2;
201            
202 12 100       121 if($var eq 'DATE_LOCAL') {
    50          
    100          
203 1         3 return $loc;
204             } elsif($var eq 'DATE_GMT') {
205 0         0 return $gmt;
206             } elsif($var eq 'LAST_MODIFIED') {
207 2         5 return $lmod;
208             }
209            
210 9 50       129 return $self->{'_variables'}->{$var} if exists $self->{'_variables'}->{$var};
211 0 0       0 return $ENV{$var} if exists $ENV{$var};
212 0         0 return '';
213             }
214            
215             sub printenv {
216             #my $self = shift;
217 0     0 1 0 return join "\n",map {"$_=$ENV{$_}"} keys %ENV;
  0         0  
218             }
219            
220             sub include {
221 45 50   45 1 1354 $DEBUG and do { local $" = "','"; warn "DEBUG: include('@_')\n" };
  0         0  
  0         0  
222 45         81 my($self,$type,$filename) = @_;
223 45 100       106 if(lc $type eq 'file') {
    50          
224 42         243 return $self->_include_file($filename);
225             } elsif(lc $type eq 'virtual') {
226 3         12 return $self->_include_virtual($filename);
227             } else {
228 0         0 warn ref($self)." error: arg to include is '$type'. It must be one of: 'file' or 'virtual'.\n";
229 0         0 return $self->{'_config'}->{'errmsg'};
230             }
231             }
232            
233             sub _include_file {
234 43 50   43   82 $DEBUG and do { local $" = "','"; warn "DEBUG: _include_file('@_')\n" };
  0         0  
  0         0  
235 43         66 my($self,$filename) = @_;
236            
237             # get the filename to open
238 43 50       731 $filename = catfile($FindBin::Bin,$filename) unless -e $filename;
239            
240             # if we've reached MAX_RECURSIONS for this filename, warn and return the error
241 43 100       172 if(++$self->{_recursions}->{$filename} >= $self->{_max_recursions}) {
242 1         8 warn ref($self)." error: the maximum number of 'include file' recursions has been exceeded for '$filename'.\n";
243 1         9 return $self->{'_config'}->{'errmsg'};
244             }
245            
246             # open the file, or warn and return an error
247 42         45 my $fh = do { local *STDIN };
  42         163  
248 42 50       1478 open($fh,$filename) or do {
249 0         0 warn ref($self)." error: failed to open file ($filename): $!\n";
250 0         0 return $self->{'_config'}->{'errmsg'};
251             };
252            
253             # process the included file and return the result
254 42         1155 return $self->process(join '',<$fh>);
255             }
256            
257             sub _include_virtual {
258 3 50   3   11 $DEBUG and do { local $" = "','"; warn "DEBUG: _include_virtual('@_')\n" };
  0         0  
  0         0  
259 3         7 my($self,$filename) = @_;
260            
261             # if this is a local file that we can just read, let's do that instead of getting it virtually
262 3 100       12 if($filename =~ m|^/(.+)|) { # could be on the local server: absolute filename, relative to ., relative to $ENV{DOCUMENT_ROOT}
263 1         3 my $file = $1;
264 1 50       33 if(-e '/'.$file) { # back to the original
    50          
    0          
265 0         0 $file = '/'.$file;
266             } elsif(-e catfile($self->{'_variables'}->{'DOCUMENT_ROOT'},$file)) {
267 1         6 $file = catfile($self->{'_variables'}->{'DOCUMENT_ROOT'},$file);
268             } elsif(-e catfile($FindBin::Bin,$file)) {
269 0         0 $file = atfile($FindBin::Bin,$file);
270             }
271 1 50       16 return $self->_include_file($file) if -e $file;
272             }
273            
274             # create the URI to get(), or warn and return the error
275             my $uri = eval {
276 2         36 my $uri = URI->new($filename);
277 2   33     19733 $uri->scheme($uri->scheme || ($ENV{HTTPS} ? 'https' : 'http')); # ??
278 2   0     539 $uri->host($uri->host || $ENV{'HTTP_HOST'} || $ENV{'SERVER_NAME'} || 'localhost');
279 2         396 $uri;
280 2 50       3 } or do {
281 0         0 warn ref($self)." error: failed to create a URI based on '$filename'.\n";
282 0         0 return $self->{'_config'}->{'errmsg'};
283             };
284 2 50       25 if($@) {
285 0         0 warn ref($self)." error: failed to create a URI based on '$filename'.\n";
286 0 0       0 return $self->{'_config'}->{'errmsg'} if $@;
287             }
288            
289             # get the content of the request
290 2   33     27 $self->{_ua} ||= $self->_get_ua();
291 2         55 my $url = $uri->canonical;
292            
293             # have we reached MAX_RECURSIONS?
294 2 50       632 if(++$self->{_recursions}->{$url} >= $self->{_max_recursions}) {
295 0         0 warn ref($self)." error: the maximum number of 'include virtual' recursions has been exceeded for '$url'.\n";
296 0         0 return $self->{'_config'}->{'errmsg'};
297             }
298            
299 2         34 my $response = $self->{_ua}->get($url);
300            
301             # is it a success?
302 2 50       846903 unless($response->is_success) {
303 2         38 warn ref($self)." error: failed to get('$url'): ".$response->status_line.".\n";
304 2         196 return $self->{_config}->{errmsg};
305             }
306            
307             # process the included content and return the result
308 0         0 return $self->process($response->content);
309             }
310            
311             sub _get_ua {
312 3     3   8 my $self = shift;
313 3         8 my %conf = ();
314 3 50       13 $conf{agent} = $ENV{HTTP_USER_AGENT} if $ENV{HTTP_USER_AGENT};
315 3         47 my $ua = LWP::UserAgent->new(%conf);
316 3         7806 $ua->cookie_jar($self->{_cookie_jar});
317 3         411 return $ua;
318             }
319            
320             sub cookie_jar {
321 0     0 1 0 my $self = shift;
322 0 0       0 if(my $jar = shift) {
323 0         0 $self->{_cookie_jar} = $jar;
324             }
325 0         0 return $self->{_cookie_jar};
326             }
327            
328             sub exec {
329 2     2 1 67 my($self,$type,$filename) = @_;
330 2 100       10 if(lc $type eq 'cmd') {
    50          
331 1         5 return $self->_exec_cmd($filename);
332             } elsif(lc $type eq 'cgi') {
333 1         5 return $self->_exec_cgi($filename);
334             } else {
335 0         0 warn ref($self)." error: arg to exec() is '$type'. It must be one of: 'cmd' or 'cgi'.\n";
336 0         0 return $self->{'_config'}->{'errmsg'};
337             }
338             }
339            
340             sub _exec_cmd {
341 1     1   2 my($self,$filename) = @_;
342            
343             # have we reached MAX_RECURSIONS?
344 1 50       7 if(++$self->{_recursions}->{$filename} >= $self->{_max_recursions}) {
345 0         0 warn ref($self)." error: the maximum number of 'exec cmd' recursions has been exceeded for '$filename'.\n";
346 0         0 return $self->{'_config'}->{'errmsg'};
347             }
348            
349 1         10276 my $output = `$filename`; # security here is mighty bad.
350            
351             # was the command a success?
352 1 50       43 if($?) {
353 0         0 warn ref($self)." error: `$filename` was not successful.\n";
354 0         0 return $self->{'_config'}->{'errmsg'};
355             }
356            
357             # process the output, and return the result
358 1         35 return $self->process($output);
359             }
360            
361             sub _exec_cgi { # no relative $filename allowed.
362 1     1   3 my($self,$filename) = @_;
363            
364             # have we reached MAX_RECURSIONS?
365 1 50       7 if(++$self->{_recursions}->{$filename} >= $self->{_max_recursions}) {
366 0         0 warn ref($self)." error: the maximum number of 'exec cgi' recursions has been exceeded for '$filename'.\n";
367 0         0 return $self->{'_config'}->{'errmsg'};
368             }
369            
370             # create the URI from the filename
371             my $uri = eval {
372 1         8 my $uri = URI->new($filename);
373 1   33     88 $uri->scheme($uri->scheme || ($ENV{HTTPS} ? 'https' : 'http')); # ??
374 1   33     94 $uri->host($uri->host || $ENV{'HTTP_HOST'} || $ENV{'SERVER_NAME'});
375 1   33     121 $uri->query($uri->query || $ENV{'QUERY_STRING'});
376 1         37 $uri;
377 1 50       2 } or do {
378 0         0 warn ref($self)." error: failed to create a URI from '$filename'.\n";
379 0         0 return $self->{'_config'}->{'errmsg'};
380             };
381 1 50       15 if($@) {
382 0         0 warn ref($self)." error: failed to create a URI from '$filename'.\n";
383 0 0       0 return $self->{'_config'}->{'errmsg'} if $@;
384             }
385            
386             # get the content
387 1   33     10 $self->{_ua} ||= $self->_get_ua();
388 1         6 my $url = $uri->canonical;
389 1         106 my $response = $self->{_ua}->get($url);
390            
391             # success?
392 1 50       222861 unless($response->is_success) {
393 1         55 warn ref($self)." error: failed to get('$filename').\n";
394 1         30 return $self->{_config}->{errmsg};
395             }
396            
397             # process the content and return the result
398 0         0 return $self->process($response->content);
399             }
400            
401             sub flastmod {
402 56     56 1 605 my($self,$type,$filename) = @_;
403            
404 56 100       151 if(lc $type eq 'file') {
    50          
405 55 100       738 $filename = catfile($FindBin::Bin,$filename) unless -e $filename;
406             } elsif(lc $type eq 'virtual') {
407 0 0       0 $filename = catfile($self->{'_variables'}->{'DOCUMENT_ROOT'},$filename)
408             unless $filename =~ /$self->{'_variables'}->{'DOCUMENT_ROOT'}/;
409             } else {
410 1         16 warn ref($self)." error: the first argument to flastmod is '$type'. It must be one of: 'file' or 'virtual'.\n";
411 1         6 return $self->{'_config'}->{'errmsg'};
412             }
413 55 50       1721 unless(-e $filename) {
414 0         0 warn ref($self)." error: flastmod failed to find '$filename'.\n";
415 0         0 return $self->{'_config'}->{'errmsg'};
416             }
417            
418 55         1102 my $flastmod = (stat $filename)[9];
419            
420 55 100       163 if($self->{'_config'}->{'timefmt'}) {
421 3         58 my @localtime = localtime($flastmod); # need this??
422 3         21 return Date::Format::strftime($self->{'_config'}->{'timefmt'},@localtime);
423             } else {
424 52         1740 return scalar localtime($flastmod);
425             }
426             }
427            
428             sub fsize {
429 1     1 1 7 my($self,$type,$filename) = @_;
430            
431 1 50       4 if(lc $type eq 'file') {
    0          
432 1 50       32 $filename = catfile($FindBin::Bin,$filename) unless -e $filename;
433             } elsif(lc $type eq 'virtual') {
434 0 0       0 $filename = catfile($ENV{'DOCUMENT_ROOT'},$filename) unless $filename =~ /$ENV{'DOCUMENT_ROOT'}/;
435             } else {
436 0         0 warn ref($self)." error: the first argument to fsize is '$type'. It must be one of: 'file' or 'virtual'.\n";
437 0         0 return $self->{'_config'}->{'errmsg'};
438             }
439 1 50       17 unless(-e $filename) {
440 0         0 warn ref($self)." error: fsize failed to find '$filename'.\n";
441 0         0 return $self->{'_config'}->{'errmsg'};
442             }
443            
444 1         21 my $fsize = (stat $filename)[7];
445            
446 1 50       6 if(lc $self->{'_config'}->{'sizefmt'} eq 'bytes') {
447 1         5 1 while $fsize =~ s/^(\d+)(\d{3})/$1,$2/g;
448 1         6 return $fsize;
449             } else { # abbrev
450             # gratefully lifted from Apache::SSI
451 0 0       0 return " 0k" unless $fsize;
452 0 0       0 return " 1k" if $fsize < 1024;
453 0 0       0 return sprintf("%4dk", ($fsize + 512)/1024) if $fsize < 1048576;
454 0 0       0 return sprintf("%4.1fM", $fsize/1048576.0) if $fsize < 103809024;
455 0 0       0 return sprintf("%4dM", ($fsize + 524288)/1048576) if $fsize < 1048576;
456             }
457             }
458            
459             #
460             # if/elsif/else/endif and related methods
461             #
462            
463             sub _test {
464 18     18   28 my($self,$test) = @_;
465 18         1261 my $retval = eval($test);
466 18 50       67 return undef if $@;
467 18 50       72 return defined $retval ? $retval : 0;
468             }
469            
470             sub _entering_if {
471 14     14   24 my $self = shift;
472 14         24 $self->{'_in_if'}++;
473 14         52 $self->{'_suspend'}->[$self->{'_in_if'}] = $self->{'_suspend'}->[$self->{'_in_if'} - 1];
474 14         38 $self->{'_seen_true'}->[$self->{'_in_if'}] = 0;
475             }
476            
477             sub _seen_true {
478 13     13   15 my $self = shift;
479 13         57 return $self->{'_seen_true'}->[$self->{'_in_if'}];
480             }
481            
482             sub _suspended {
483 196     196   267 my $self = shift;
484 196         2150 return $self->{'_suspend'}->[$self->{'_in_if'}];
485             }
486            
487             sub _leaving_if {
488 14     14   17 my $self = shift;
489 14 50       48 $self->{'_in_if'}-- if $self->{'_in_if'};
490             }
491            
492             sub _true {
493 10     10   15 my $self = shift;
494 10         30 return $self->{'_seen_true'}->[$self->{'_in_if'}]++;
495             }
496            
497             sub _suspend {
498 13     13   19 my $self = shift;
499 13         34 $self->{'_suspend'}->[$self->{'_in_if'}]++;
500             }
501            
502             sub _resume {
503 6     6   12 my $self = shift;
504 6 50       24 $self->{'_suspend'}->[$self->{'_in_if'}]--
505             if $self->{'_suspend'}->[$self->{'_in_if'}];
506             }
507            
508             sub _in_if {
509 27     27   34 my $self = shift;
510 27         77 return $self->{'_in_if'};
511             }
512            
513             sub if {
514 14     14 1 500 my($self,$expr,$test) = @_;
515 14 50       48 $expr = $test if @_ == 3;
516 14         109 $self->_entering_if();
517 14 100       33 if($self->_test($expr)) {
518 7         22 $self->_true();
519             } else {
520 7         2642 $self->_suspend();
521             }
522 14         73 return '';
523             }
524            
525             sub elif {
526 4     4 1 127 my($self,$expr,$test) = @_;
527 4 50       13 die "Incorrect use of elif ssi directive: no preceeding 'if'." unless $self->_in_if();
528 4 50       16 $expr = $test if @_ == 3;
529 4 100 66     11 if(! $self->_seen_true() and $self->_test($expr)) {
530 3         13 $self->_true();
531 3         12 $self->_resume();
532             } else {
533 1 50       5 $self->_suspend() unless $self->_suspended();
534             }
535 4         20 return '';
536             }
537            
538             sub else {
539 9     9 1 119 my $self = shift;
540 9 50       22 die "Incorrect use of else ssi directive: no preceeding 'if'." unless $self->_in_if();
541 9 100       22 unless($self->_seen_true()) {
542 3         9 $self->_resume();
543             } else {
544 6         15 $self->_suspend();
545             }
546 9         30 return '';
547             }
548            
549             sub endif {
550 14     14 1 239 my $self = shift;
551 14 50       33 die "Incorrect use of endif ssi directive: no preceeding 'if'." unless $self->_in_if();
552 14         31 $self->_leaving_if();
553             # $self->_resume() if $self->_suspended();
554 14         49 return '';
555             }
556            
557             #
558             # if we're called like this, it means that we're to handle a CGI request ourselves.
559             # that means that we're to open the file and process the content, sending it to STDOUT
560             # along with a standard HTTP content header
561             #
562             unless(caller) {
563             goto &handler;
564             }
565            
566             sub handler {
567 0     0 0 0 eval "use CGI qw(:standard);";
568 0         0 print header();
569            
570 0 0       0 unless(UNIVERSAL::isa(tied(*STDOUT),'CGI::SSI')) {
571 0         0 tie *STDOUT, 'CGI::SSI', filehandle => 'main::STDOUT';
572             }
573            
574 0         0 my $filename = "$ENV{DOCUMENT_ROOT}$ENV{REQUEST_URI}";
575 0 0       0 if(-f $filename) {
576 0 0       0 open my $fh, '<', $filename or die "Failed to open file ($filename): $!";
577 0         0 print <$fh>;
578             } else {
579 0         0 print "Failed to find file ($filename).";
580             }
581            
582 0         0 exit;
583             }
584            
585             #
586             # packages for tie()
587             #
588            
589             package CGI::SSI::Gmt;
590            
591 26     26   173 sub TIESCALAR { bless [@_], shift() }
592             sub FETCH {
593 52     52   79 my $self = shift;
594 52 50       157 if($self->[-1]->{'_config'}->{'timefmt'}) {
595 0         0 my @gt = gmtime;
596 0         0 return Date::Format::strftime($self->[-1]->{'_config'}->{'timefmt'},@gt);
597             } else {
598 52         512 return scalar gmtime;
599             }
600             }
601            
602             package CGI::SSI::Local;
603            
604 26     26   143 sub TIESCALAR { bless [@_], shift() }
605             sub FETCH {
606 54     54   84 my $self = shift;
607 54 100       371 if($self->[-1]->{'_config'}->{'timefmt'}) {
608 1         29 my @lt = localtime;
609 1         16 return Date::Format::strftime($self->[-1]->{'_config'}->{'timefmt'},@lt);
610             } else {
611 53         5225 return scalar localtime;
612             }
613             }
614            
615             package CGI::SSI::LMOD;
616            
617 26     26   1035 sub TIESCALAR { bless [@_], shift() }
618             sub FETCH {
619 54     54   84 my $self = shift;
620 54   50     484 return $self->[-1]->flastmod('file', $ENV{'SCRIPT_FILENAME'} || $ENV{'PATH_TRANSLATED'} || '');
621             }
622            
623             1;
624             __END__