File Coverage

blib/lib/CGI/CIPP.pm
Criterion Covered Total %
statement 117 622 18.8
branch 11 168 6.5
condition 2 24 8.3
subroutine 21 60 35.0
pod 0 44 0.0
total 151 918 16.4


line stmt bran cond sub pod time code
1             package CGI::CIPP;
2              
3             $VERSION = "0.07";
4             $REVISION = q$Revision: 1.8 $;
5              
6 1     1   930 use strict;
  1     1   1  
  1         36  
  1         5  
  1         2  
  1         66  
7 1     1   4 use Carp;
  1     1   2  
  1         96  
  1         6  
  1         2  
  1         68  
8 1     1   9892 use FileHandle;
  1     1   31161  
  1         7  
  1         4  
  1         2  
  1         8  
9 1     1   525 use Config;
  1     1   2  
  1         50  
  1         402  
  1         9  
  1         29  
10 1     1   5 use File::Path;
  1     1   2  
  1         62  
  1         5  
  1         1  
  1         46  
11 1     1   5 use Fcntl ':flock';
  1     1   1  
  1         1845  
  1         4  
  1         1  
  1         7527  
12              
13             # this global hash holds the timestamps of the compiled perl
14             # subroutines for this instance
15              
16             %CGI::CIPP::compiled = ();
17              
18             sub request {
19 1     1 0 86 my $type = shift;
  0     0 0 0  
20 1         8 my %par = @_;
  0         0  
21            
22 1         3 my $path_info = $ENV{PATH_INFO};
  0         0  
23              
24             # if the request accesses a directory, we add the directory
25             # index name
26            
27 1 50       5 if ( $path_info =~ m!/$! ) {
  0 0       0  
28 0         0 $path_info .= $par{directory_index};
  0         0  
29             }
30              
31 1 50       6 $par{debug} && print STDERR "path_info=$path_info\n";
  0 0       0  
32              
33             # first bless the object, we need the lookup_uri
34             # method to resolve the PATH_INFO and to set up
35             # all filename attributes of the object
36              
37 1   50     29 my $self = bless {
  0   0     0  
38             document_root => $par{document_root},
39             directory_index => $par{directory_index},
40             cache_dir => $par{cache_dir},
41             databases => $par{databases},
42             default_database => $par{default_database},
43             filename => undef,
44             uri => $path_info,
45             error => undef,
46             debug => $par{debug} || 0,
47             lang => $par{lang},
48             status => {
49             pid => $$
50             },
51             }, $type;
52              
53             # resolve PATH_INFO to physical filename
54 1         5 my $filename = $self->resolve_uri ($path_info);
  0         0  
55 1         6 $self->{filename} = $filename;
  0         0  
56              
57 1 50       3 $self->{debug} && print STDERR "filename=$filename\n";
  0 0       0  
58              
59             # now set sub_filename, sub_name, err_filename and
60             # dep_filename
61 1         7 $self->set_sub_filename;
  0         0  
62 1         4 $self->set_sub_name;
  0         0  
63 1         3 $self->{err_filename} = $self->{sub_filename}.".err";
  0         0  
64 1         3 $self->{dep_filename} = $self->{sub_filename}.".dep";
  0         0  
65              
66             # now process the request, if the file exists
67 1 50 33     40 if ( -f $filename and -r $filename ) {
  0 0 0     0  
68 1 0       3 if ( not $self->process ) {
  0 0       0  
69 0         0 $self->error;
  0         0  
70             }
71             } else {
72 0         0 print "Content-type: text/plain\n\n";
  0         0  
73 0         0 print "File $path_info not found!\n";
  0         0  
74 0         0 return;
  0         0  
75             }
76              
77 0         0 return 1;
  0         0  
78             }
79              
80             sub process {
81 1     1 0 2 my $self = shift;
  0     0 0 0  
82            
83 1 50       6 $self->{debug} && print STDERR "processing...\n";
  0 0       0  
84 1 0       5 $self->preprocess or return;
  0 0       0  
85              
86 0 0       0 $self->{debug} && print STDERR "compiling...\n";
  0 0       0  
87 0 0       0 $self->compile or return;
  0 0       0  
88              
89 0 0       0 $self->{debug} && print STDERR "executing...\n";
  0 0       0  
90 0 0       0 $self->execute or return;
  0 0       0  
91            
92 0         0 return 1;
  0         0  
93             }
94              
95             sub preprocess {
96 1     1 0 2 my $self = shift;
  0     0 0 0  
97              
98 1 50       4 if ( $self->file_cache_ok ) {
  0 0       0  
99 0         0 return not $self->has_cached_error;
  0         0  
100             }
101              
102 1         2 my $sub_filename = $self->{sub_filename};
  0         0  
103 1         1 my $sub_name = $self->{sub_name};
  0         0  
104 1         2 my $filename = $self->{filename};
  0         0  
105              
106             # CIPP Parameter
107 1         1 my $perl_code = "";
  0         0  
108            
109 1         2 my $source = $filename;
  0         0  
110 1         2 my $target = \$perl_code;
  0         0  
111 1         1 my $project_hash = undef;
  0         0  
112            
113 1         2 my $db_href = $self->{databases};
  0         0  
114              
115 1         1 my $db;
  0         0  
116             my $database_hash;
117 1         2 foreach $db (keys %{$db_href}) {
  1         3  
  0         0  
  0         0  
118 1         3 $database_hash->{$db} = "CIPP_DB_DBI";
  0         0  
119             }
120 1         3 my $default_db = $self->{default_database};
  0         0  
121              
122 1         1 my $mime_type = "text/html";
  0         0  
123 1         2 my $call_path = $self->{uri};
  0         0  
124 1         2 my $skip_header_line = undef;
  0         0  
125 1         1 my $debugging = 0;
  0         0  
126 1         1 my $result_type = "cipp";
  0         0  
127 1         2 my $use_strict = 1;
  0         0  
128 1         1 my $persistent = 0;
  0         0  
129 1         1 my $apache_mod = $self;
  0         0  
130 1         6 my $project = undef;
  0         0  
131 1         2 my $use_inc_cache = 0;
  0         0  
132 1         1 my $lang = $self->{lang};
  0         0  
133              
134 1         890 require "CIPP.pm";
  0         0  
135 1         232 my $CIPP = new CIPP (
  0         0  
136             $source, $target, $project_hash, $database_hash, $mime_type,
137             $default_db, $call_path, $skip_header_line, $debugging,
138             $result_type, $use_strict, $persistent, $apache_mod, $project,
139             $use_inc_cache, $lang
140             );
141 0         0 $CIPP->{print_content_type} = 0;
  0         0  
142            
143 0 0       0 if ( not $CIPP->Get_Init_Status ) {
  0 0       0  
144 0         0 $self->{error} = "cipp\tcan't initialize CIPP preprocessor";
  0         0  
145 0         0 return;
  0         0  
146             }
147              
148 0         0 $CIPP->Preprocess;
  0         0  
149              
150 0 0       0 if ( not $CIPP->Get_Preprocess_Status ) {
  0 0       0  
151 0         0 my $aref = $CIPP->Get_Messages;
  0         0  
152 0         0 $self->{error} = "cipp-syntax\t".join ("\n", @{$aref});
  0         0  
  0         0  
  0         0  
153 0         0 $self->{cipp_debug_text} = $CIPP->Format_Debugging_Source ();
  0         0  
154 0         0 return;
  0         0  
155             }
156              
157             # Wegschreiben
158             $perl_code =
159 0         0 "# mime-type: $CIPP->{mime_type}\n".
  0         0  
160             "sub $sub_name {\nmy (\$cipp_apache_request) = \@_;\n".
161             $perl_code.
162             "}\n";
163              
164 0         0 $self->write_locked ($sub_filename, \$perl_code);
  0         0  
165            
166             # Cache-Dependency-File updaten
167 0         0 $self->set_dependency ($CIPP->Get_Used_Macros);
  0         0  
168              
169             # Perl-Syntax-Check
170              
171 0         0 my %env_backup = %main::ENV; # SuSE 6.0 Workaround
  0         0  
172 0         0 %main::ENV = ();
  0         0  
173              
174 0         0 my $error = `$Config{perlpath} -c -Mstrict $sub_filename 2>&1`;
  0         0  
175              
176 0         0 %main::ENV = %env_backup;
  0         0  
177              
178 0 0       0 if ( $error !~ m/syntax OK/) {
  0 0       0  
179 0 0       0 $error = "perl-syntax\t$error" if $error;
  0 0       0  
180 0         0 $self->{error} = $error;
  0         0  
181 0         0 return;
  0         0  
182             }
183              
184 0         0 return 1;
  0         0  
185             }
186              
187             sub set_dependency {
188 0     0 0 0 my $self = shift;
  0     0 0 0  
189            
190 0         0 my ($href) = @_;
  0         0  
191            
192 0         0 my $dep_filename = $self->{dep_filename};
  0         0  
193            
194 0         0 my @list;
  0         0  
195 0         0 push @list, $self->{filename};
  0         0  
196              
197 0 0       0 if ( defined $href ) {
  0 0       0  
198 0         0 my $uri;
  0         0  
199 0         0 foreach $uri (keys %{$href}) {
  0         0  
  0         0  
  0         0  
200 0         0 push @list, $self->resolve_uri($uri);
  0         0  
201             }
202             }
203              
204 0         0 $self->write_locked ($dep_filename, join ("\t", @list));
  0         0  
205             }
206              
207             sub compile {
208 0     0 0 0 my $self = shift;
  0     0 0 0  
209              
210 0 0       0 return 1 if $self->sub_cache_ok;
  0 0       0  
211              
212 0         0 my $sub_name = $self->{sub_name};
  0         0  
213 0         0 my $sub_filename = $self->{sub_filename};
  0         0  
214            
215 0         0 my $sub_sref = $self->read_locked ($sub_filename);
  0         0  
216            
217             # cut off fist line (with mime type)
218 0         0 $$sub_sref =~ s/^(.*)\n//;
  0         0  
219            
220             # extract mime type
221 0         0 my $mime_type = $1;
  0         0  
222 0         0 $mime_type =~ s/^#\s*mime-type:\s*//;
  0         0  
223              
224             # compile the code
225 0         0 eval $$sub_sref;
  0         0  
226              
227 0 0       0 if ( $@ ) {
  0 0       0  
228 0         0 $self->{error} = "compilation\t$@";
  0         0  
229 0         0 $CGI::CIPP::compiled{$sub_name} = undef;
  0         0  
230 0         0 return;
  0         0  
231             }
232            
233 0         0 $CGI::CIPP::compiled{$sub_name} = time;
  0         0  
234 0         0 $CGI::CIPP::mime_type{$sub_name} = $mime_type;
  0         0  
235            
236 0         0 unlink $self->{err_filename};
  0         0  
237              
238 0         0 return 1;
  0         0  
239             }
240              
241             sub execute {
242 0     0 0 0 my $self = shift;
  0     0 0 0  
243              
244 0         0 my $sub_name = $self->{sub_name};
  0         0  
245            
246 0 0       0 if ( $CGI::CIPP::mime_type{$sub_name} ne 'cipp/dynamic' ) {
  0 0       0  
247 0         0 $CIPP::REVISION =~ /(\d+\.\d+)/;
  0         0  
248 0         0 my $cipp_revision = $1;
  0         0  
249 0         0 $CGI::CIPP::REVISION =~ /(\d+\.\d+)/;
  0         0  
250 0         0 my $cipp_handler_revision = $1;
  0         0  
251              
252 0         0 print "Content-type: text/html\n\n";
  0         0  
253 0         0 print "\n";
256             }
257              
258 1     1   8 no strict 'refs';
  1     1   2  
  1         2681  
  1         7  
  1         1  
  1         2517  
259 0         0 eval { &$sub_name ($self) };
  0         0  
  0         0  
  0         0  
260              
261 0 0       0 if ( $@ ) {
  0 0       0  
262 0         0 $self->{error} = "runtime\t$@";
  0         0  
263 0         0 return;
  0         0  
264             }
265              
266 0         0 return 1;
  0         0  
267             }
268              
269              
270             sub error {
271 0     0 0 0 my $self = shift;
  0     0 0 0  
272            
273 0         0 my $sub_filename = $self->{sub_filename};
  0         0  
274 0         0 my $err_filename = $self->{err_filename};
  0         0  
275 0         0 my $error = $self->{error};
  0         0  
276 0         0 my $uri = $self->{uri};
  0         0  
277              
278 0         0 my ($type) = split ("\t", $error);
  0         0  
279              
280 0 0       0 if ( $type eq 'cipp-syntax' ) {
  0 0       0  
281 0         0 $self->write_locked ($err_filename, $error);
  0         0  
282             } else {
283 0         0 unlink $sub_filename;
  0         0  
284 0         0 unlink $err_filename;
  0         0  
285             }
286              
287 0         0 $error =~ s/^([^\t]+)\t//;
  0         0  
288            
289 0         0 print "Content-type: text/html\n\n";
  0         0  
290 0         0 print "Error executing $uri\n";
  0         0  
291 0         0 print "\n";
  0         0  
292              
293 0         0 print "

Error executing $uri:\n";

  0         0  
294 0         0 print "
Type:
$type
\n";
  0         0  
295 0         0 print "

Message:
$error
\n";
  0         0  
296              
297 0 0       0 if ( $self->{cipp_debug_text} ) {
  0 0       0  
298 0         0 print ${$self->{cipp_debug_text}};
  0         0  
  0         0  
  0         0  
299             }
300              
301 0         0 1;
  0         0  
302             }
303              
304             sub debug {
305 0     0 0 0 my $self = shift;
  0     0 0 0  
306            
307 0         0 my $sub_name = $self->{sub_name};
  0         0  
308 0         0 my $sub_filename = $self->{sub_filename};
  0         0  
309            
310 0         0 my ($k, $v);
  0         0  
311 0         0 my $str = "cache=$sub_filename sub=$sub_name";
  0         0  
312 0         0 while ( ($k, $v) = each %{$self->{status}} ) {
  0         0  
  0         0  
  0         0  
313 0         0 $str .= " $k=$v";
  0         0  
314             }
315              
316 0         0 return;
  0         0  
317            
318 0         0 while ( ($k, $v) = each %CGI::CIPP::sub_cnt ) {
  0         0  
319 0 0       0 $self->{debug} && print STDERR ("$k: $v\n");
  0 0       0  
320             }
321              
322 0         0 1;
  0         0  
323             }
324              
325             # Helper Functions ----------------------------------------------------------------
326              
327             sub set_sub_filename {
328 1     1 0 2 my $self = shift;
  0     0 0 0  
329            
330 1         2 my $filename = $self->{uri};
  0         0  
331 1         2 my $cache_dir = $self->{cache_dir};
  0         0  
332            
333 1         22 my $dir = $filename;
  0         0  
334 1         6 $dir =~ s!/[^/]+$!!;
  0         0  
335 1         3 $dir = $cache_dir.$dir;
  0         0  
336            
337 1 50 0     25 ( mkpath ($dir, 0, 0770) or die "can't create $dir" ) if not -d $dir;
  0 0 0     0  
338            
339 1         4 $filename =~ s!^/!!;
  0         0  
340 1         4 $self->{sub_filename} = "$cache_dir/$filename.sub";
  0         0  
341            
342 1         3 return 1;
  0         0  
343             }
344              
345             sub set_sub_name {
346 0     0 0 0 my $self = shift;
  1     1 0 2  
347            
348 0         0 my $uri = $self->{uri};
  1         2  
349 0         0 $uri =~ s!^/!!;
  1         3  
350 0         0 $uri =~ s/\W/_/g;
  1         5  
351            
352 0         0 $self->{sub_name} = "CIPP_Pages::process_$uri";
  1         3  
353            
354 0         0 return 1;
  1         2  
355             }
356              
357             sub file_cache_ok {
358 0     0 0 0 my $self = shift;
  1     1 0 2  
359            
360 0         0 $self->{status}->{file_cache} = 'dirty';
  1         4  
361              
362 0         0 my $cache_file = $self->{sub_filename};
  1         21  
363            
364 0 0       0 if ( -e $cache_file ) {
  1 50       11  
365 0         0 my $cache_time = (stat ($cache_file))[9];
  0         0  
366              
367 0         0 my $dep_filename = $self->{dep_filename};
  0         0  
368 0         0 my $data_sref = $self->read_locked ($dep_filename);
  0         0  
369 0         0 my @list = split ("\t", $$data_sref);
  0         0  
370              
371 0         0 my $path;
  0         0  
372 0         0 foreach $path (@list) {
  0         0  
373 0         0 my $file_time = (stat ($path))[9];
  0         0  
374 0 0       0 return if $file_time > $cache_time;
  0 0       0  
375             }
376             } else {
377             # check if cache_dir exists and create it if not
378 0 0       0 mkdir ($self->{cache_dir},0770) if not -d $self->{cache_dir};
  1 50       11  
379 0         0 return;
  1         5  
380             }
381              
382 0         0 $self->{status}->{file_cache} = 'ok';
  0         0  
383              
384 0         0 return 1;
  0         0  
385             }
386              
387             sub sub_cache_ok {
388 0     0 0 0 my $self = shift;
  0     0 0 0  
389              
390 0         0 $self->{status}->{sub_cache} = 'dirty';
  0         0  
391              
392 0         0 my $cache_file = $self->{sub_filename};
  0         0  
393 0         0 my $sub_name = $self->{sub_name};
  0         0  
394            
395 0         0 my $cache_time = (stat ($cache_file))[9];
  0         0  
396 0         0 my $sub_time = $CGI::CIPP::compiled{$sub_name};
  0         0  
397              
398 0 0 0     0 if ( not defined $sub_time or $cache_time > $sub_time ) {
  0 0 0     0  
399 0         0 $CGI::CIPP::sub_cnt{$sub_name} = 0;
  0         0  
400 0         0 return;
  0         0  
401             }
402              
403 0         0 $self->{status}->{sub_cache} = 'ok';
  0         0  
404            
405 0         0 ++$CGI::CIPP::sub_cnt{$sub_name};
  0         0  
406            
407 0         0 return 1;
  0         0  
408             }
409              
410             sub has_cached_error {
411 0     0 0 0 my $self = shift;
  0     0 0 0  
412            
413 0         0 my $err_filename = $self->{err_filename};
  0         0  
414            
415 0 0       0 if ( -e $err_filename ) {
  0 0       0  
416 0         0 my $error_sref = $self->read_locked ($err_filename);
  0         0  
417              
418 0         0 $self->{'error'} = $$error_sref;
  0         0  
419 0         0 $self->{status}->{cached_error} = 1;
  0         0  
420            
421 0         0 return 1;
  0         0  
422             }
423              
424 0         0 return;
  0         0  
425             }
426              
427             sub resolve_uri {
428 1     1 0 2 my $self = shift;
  0     0 0    
429              
430 1         2 my ($uri) = @_;
  0            
431 1         1 my $filename;
  0            
432            
433 1 50       8 if ( $uri =~ m!^/! ) {
  0 0          
434 1         6 $filename = $self->{document_root}.$uri;
  0            
435             } else {
436 0         0 my $uri_dir = $self->{uri};
  0            
437 0         0 $uri_dir =~ s!/[^/]+$!!;
  0            
438 0         0 $filename = $self->{document_root}.$uri_dir."/".$uri;
  0            
439             }
440              
441 1 50       4 $self->{'debug'} && print STDERR "lookup_uri: base=$self->{uri}: '$uri' -> '$filename'\n";
  0 0          
442              
443 1         3 return $filename;
  0            
444             }
445              
446             sub write_locked {
447 0     0 0   my $self = shift;
  0     0 0    
448            
449 0           my ($filename, $data) = @_;
  0            
450            
451 0           my $data_sref;
  0            
452 0 0         if ( not ref $data ) {
  0 0          
453 0           $data_sref = \$data;
  0            
454             } else {
455 0           $data_sref = $data;
  0            
456             }
457            
458 0           my $fh = new FileHandle;
  0            
459              
460 0 0         open ($fh, "+> $filename") or croak "can't write $filename";
  0 0          
461 0           binmode $fh;
  0            
462 0 0         flock $fh, LOCK_EX or croak "can't exclusive lock $filename";
  0 0          
463 0 0         seek $fh, 0, 0 or croak "can't seek $filename";
  0 0          
464 0 0         print $fh $$data_sref or croak "can't write data $filename";
  0 0          
465 0 0         truncate $fh, length($$data_sref) or croak "can't truncate $filename";
  0 0          
466 0           close $fh;
  0            
467             }
468              
469             sub read_locked {
470 0     0 0   my $self = shift;
  0     0 0    
471            
472 0           my ($filename) = @_;
  0            
473              
474 0           my $fh = new FileHandle;
  0            
475 0 0         open ($fh, $filename) or croak "can't read $filename";
  0 0          
476 0           binmode $fh;
  0            
477 0 0         flock $fh, LOCK_SH or croak "can't share lock $filename";
  0 0          
478 0           my $data = join ('', <$fh>);
  0            
479 0           close $fh;
  0            
480              
481 0           return \$data;
  0            
482             }
483              
484             # Apache::Request compatibility routines
485              
486             sub dir_config {
487 0     0 0   my $self = shift;
  0     0 0    
488            
489 0           my ($par) = @_;
  0            
490              
491 0           my $value;
  0            
492              
493             # check if a db_ parameter is requested
494            
495 0 0         if ( $par =~ /^db_([^_]+)_(.*)/ ) {
  0 0          
496 0           my ($db, $db_par) = ($1, $2);
  0            
497 0           $value = $self->{databases}->{$db}->{$db_par};
  0            
498             }
499              
500 0           return $value;
  0            
501             }
502              
503             sub lookup_uri {
504 0     0 0   my $self = shift;
  0     0 0    
505 0           my ($uri) = @_;
  0            
506              
507 0           my $filename = $self->resolve_uri ($uri);
  0            
508              
509 0           return bless \$filename, "CGI::CIPP::Lookup";
  0            
510             }
511              
512             sub content_type {
513 0     0 0   my $self = shift;
  0     0 0    
514            
515 0           my ($content_type) = @_;
  0            
516            
517 0           $self->{content_type} = $content_type;
  0            
518            
519 0           1;
  0            
520             }
521              
522             sub header_out {
523 0     0 0   my $self = shift;
  0     0 0    
524 0           my %par = @_;
  0            
525            
526 0           $self->{header_out} = \%par;
  0            
527            
528 0           1;
  0            
529             }
530              
531             sub send_http_header {
532 0     0 0   my $self = shift;
  0     0 0    
533            
534 0   0       my $content_type = $self->{'content_type'} || 'text/html';
  0   0        
535              
536 0           print "Content-type: $content_type\n";
  0            
537            
538 0 0         if ( defined $self->{'header_out'} ) {
  0 0          
539 0           my ($k,$v);
  0            
540 0           while ( ($k,$v) = each %{$self->{'header_out'}} ) {
  0            
  0            
  0            
541 0           print "$k: $v\n";
  0            
542             }
543             }
544 0           print "\n";
  0            
545            
546 0           1;
  0            
547             }
548              
549             sub internal_redirect {
550 0     0 0   my $self = shift;
  0     0 0    
551              
552 0           my ($url) = @_;
  0            
553              
554 0           my ($path_info, $query_string) = split (/\?/, $url, 2);
  0            
555              
556 0           my $old_path_info = $ENV{PATH_INFO};
  0            
557 0           my $old_query_string = $ENV{QUERY_STRING};
  0            
558 0           my $old_request_method = $ENV{REQUEST_METHOD};
  0            
559            
560 0           $ENV{PATH_INFO} = $path_info;
  0            
561 0           $ENV{QUERY_STRING} = $query_string;
  0            
562 0           $ENV{REQUEST_METHOD} = "GET";
  0            
563            
564             # print STDERR "query_string=$query_string\n";
565            
566             # so werden keine Datenbankverbindungen vom
567             # aufgerufenen Script geöffnet oder geschlossen
568 0           $CIPP_Exec::no_db_connect = 1;
  0            
569              
570 0           CGI::CIPP->request ( %{$self} );
  0            
  0            
  0            
571              
572             # Flag wieder zurücksetzen
573 0           $CIPP_Exec::no_db_connect = 0;
  0            
574            
575 0           $ENV{PATH_INFO} = $old_path_info;
  0            
576 0           $ENV{QUERY_STRING} = $old_query_string;
  0            
577 0           $ENV{REQUEST_METHOD} = $old_request_method;
  0            
578            
579 0           1;
  0            
580             }
581              
582              
583             package CGI::CIPP::Lookup;
584              
585             sub filename {
586 0     0     return ${$_[0]};
  0     0      
  0            
  0            
587             }
588              
589             1;
590             __END__