File Coverage

blib/lib/Apache/Handlers.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Apache::Handlers;
2              
3             # $Id: Handlers.pm,v 1.2 2002/01/07 15:28:35 jgsmith Exp $
4              
5 2     2   1447 use strict;
  2         5  
  2         69  
6 2     2   11 use Carp;
  2         4  
  2         183  
7 2     2   3550 use Apache::Constants qw(OK SERVER_ERROR DECLINED);
  0            
  0            
8             use Perl::WhichPhase qw: in_BEGIN :;
9             use vars qw:$VERSION @EXPORT_OK @ISA:;
10              
11             my $has_mod_perl = defined $INC{'Apache'};
12              
13             eval {
14             use Apache::Log ();
15             Apache::ModuleConfig -> has_srv_config;
16             } if $has_mod_perl;
17              
18             $VERSION = "0.02";
19             @ISA = qw!Exporter!;
20              
21             my %code = ( );
22              
23             sub dump {
24             eval {
25             use Data::Dumper;
26             return Data::Dumper -> Dump([\%code]);
27             };
28             }
29              
30             my %phases = qw:
31             CHILDINIT PerlChildInitHandler
32             POSTREADREQUEST PerlPostReadRequestHandler
33             CHILDEXIT PerlChildExitHandler
34             CLEANUP PerlCleanupHandler
35             LOG PerlLogHandler
36             CONTENT PerlHandler
37             FIXUP PerlFixupHandler
38             TYPE PerlTypeHandler
39             AUTHZ PerlAuthzHandler
40             AUTHEN PerlAuthenHandler
41             ACCESS PerlAccessHandler
42             HEADERPARSER PerlHeaderParserHandler
43             TRANS PerlTransHandler
44             RESTART PerlRestartHandler
45             :;
46              
47             @EXPORT_OK = (qw:run_phase:, keys %phases);
48              
49             my %sigil = qw:
50             CODE &
51             ARRAY @
52             SCALAR $
53             HASH %
54             :;
55              
56             sub _do_handler {
57             my($method, $referent, $data) = @_;
58             my($rsig, $dsig);
59              
60             foreach my $s (keys %sigil) {
61             $rsig = $sigil{$s} if(UNIVERSAL::isa($referent, $s));
62             $dsig = $sigil{$s} if(UNIVERSAL::isa($data, $s));
63             }
64              
65             croak "Unknown referent type" if !defined $rsig;
66              
67             if(UNIVERSAL::isa($referent, 'CODE')) {
68             $method->($referent);
69             } elsif(!defined $data) {
70             $method->(eval "sub { undef $rsig\$referent; }");
71             } elsif(!defined $dsig and $rsig eq q+$+) {
72             $method->(sub { $$referent = $data; });
73             } else {
74             croak "Potential referent and data mismatch" if !defined $dsig;
75             if($dsig eq '&') {
76             $method -> (eval "sub { $rsig\$referent = &\$data(\$referent); }");
77             } else {
78             $method -> (eval "sub { $rsig\$referent = $dsig\$data; }");
79             }
80             }
81             }
82              
83             foreach my $p (keys %phases) {
84             my($code, $keeper, $pusher);
85              
86             if($p eq 'ACCESS' || $p eq 'AUTHEN' || $p eq 'AUTHZ') {
87             $pusher = "\$r -> push_handlers('$phases{$p}', sub { &\$c; return DECLINED; })";
88             } else {
89             $pusher = "\$r -> push_handlers('$phases{$p}', sub { &\$c; return OK; })";
90             }
91              
92             if($p eq 'CLEANUP' || $p eq 'CHILDEXIT') {
93             $keeper = "unshift \@{\$code{$p}}, shift";
94             } else {
95             $keeper = "push \@{\$code{$p}}, shift";
96             }
97              
98             if($has_mod_perl) {
99             eval qq{
100             sub $p (&) {
101             my \$r;
102             if(!in_BEGIN && \$r = Apache->request) {
103             my \$c = shift;
104             $pusher;
105             } else {
106             \$code{$p} = [ ] if !ref \$code{$p};
107             $keeper;
108             }
109             }
110             };
111             } else {
112             eval qq{
113             sub $p (&) {
114             \$code{$p} = [ ] if !ref \$code{$p};
115             $keeper;
116             }
117             };
118             }
119             }
120              
121             sub run_phase {
122             my $r;
123             foreach my $h (@_) {
124             if(defined $code{$h}) {
125             foreach my $c (@{$code{$h}}) {
126             eval{ &$c };
127             next unless $@;
128             if($has_mod_perl && ($r = Apache -> request)) {
129             $r -> log -> debug($@);
130             return SERVER_ERROR;
131             } else {
132             die "$@\n";
133             }
134             }
135             }
136             }
137             }
138              
139             my $yet_initialized = 0;
140              
141             sub reset {
142             &run_phase( qw: RESTART :);
143             %code = ( );
144             $yet_initialized = 0;
145             }
146              
147             sub handler($) {
148             my($r) = @_;
149              
150             return SERVER_ERROR
151             if not $yet_initialized and run_phase(qw: CHILDINIT :) == SERVER_ERROR;
152              
153             $yet_initialized = 1;
154              
155             return OK if $r -> current_callback() eq 'PerlChildInitHandler';
156              
157             # install handlers
158             foreach my $p (keys %code) {
159             my $count;
160             next if $p eq 'CHILDINIT' or $p eq 'POSTREADREQUEST' or $p eq 'CHILDEXIT';
161             $r -> push_handlers($phases{$p} => sub {
162             my $ret;
163             foreach my $c (@{$code{$p} || []}) {
164             eval { &$c() };
165             if($@) {
166             $r -> log -> debug($@);
167             return SERVER_ERROR;
168             }
169             }
170             if($p eq 'AUTHZ' || $p eq 'AUTHEN' || $p eq 'ACCESS') {
171             return DECLINED;
172             }
173             return OK;
174             });
175             }
176              
177             return SERVER_ERROR
178             if run_phase(qw: POSTREADREQUEST :) == SERVER_ERROR;
179            
180             }
181              
182             INIT {
183             run_phase(qw: CHILDINIT TRANS HEADERPARSER ACCESS
184             AUTHEN AUTHZ TYPE FIXUP CONTENT :) unless $has_mod_perl;
185             }
186              
187             END {
188             run_phase(qw: LOG CLEANUP CHILDEXIT :) unless $has_mod_perl;
189             }
190              
191             # the eval has an "uninitialized string" warning for some reason, but since
192             # this is the last bit and we don't care so much if it fails, we're turning
193             # off warnings through the end of this file...
194              
195             no warnings;
196              
197             eval {
198              
199             use Attribute::Handlers;
200              
201             sub UNIVERSAL::PerlChildInitHandler : ATTR(BEGIN)
202             { _do_handler(\&CHILDINIT, $_[2], $_[4]); }
203              
204             sub UNIVERSAL::PerlPostReadRequestHandler : ATTR(BEGIN)
205             { _do_handler(\&POSTREADREQUEST, $_[2], $_[4]); }
206              
207             sub UNIVERSAL::PerlTransHandler : ATTR(BEGIN)
208             { _do_handler(\&TRANS, $_[2], $_[4]); }
209              
210             sub UNIVERSAL::PerlHeaderParserHandler : ATTR(BEGIN)
211             { _do_handler(\&HEADERPARSER, $_[2], $_[4]); }
212              
213             sub UNIVERSAL::PerlAccessHandler : ATTR(BEGIN)
214             { _do_handler(\&ACCESS, $_[2], $_[4]); }
215              
216             sub UNIVERSAL::PerlAuthenHandler : ATTR(BEGIN)
217             { _do_handler(\&AUTHEN, $_[2], $_[4]); }
218              
219             sub UNIVERSAL::PerlAuthzHandler : ATTR(BEGIN)
220             { _do_handler(\&AUTHZ, $_[2], $_[4]); }
221              
222             sub UNIVERSAL::PerlTypeHandler : ATTR(BEGIN)
223             { _do_handler(\&TYPE, $_[2], $_[4]); }
224              
225             sub UNIVERSAL::PerlFixupHandler : ATTR(BEGIN)
226             { _do_handler(\&FIXUP, $_[2], $_[4]); }
227              
228             sub UNIVERSAL::PerlHandler : ATTR(BEGIN)
229             { _do_handler(\&CONTENT, $_[2], $_[4]); }
230              
231             sub UNIVERSAL::PerlLogHandler : ATTR(BEGIN)
232             { _do_handler(\&LOG, $_[2], $_[4]); }
233              
234             sub UNIVERSAL::PerlCleanupHandler : ATTR(BEGIN)
235             { _do_handler(\&CLEANUP, $_[2], $_[4]); }
236              
237             sub UNIVERSAL::PerlChildExitHandler : ATTR(BEGIN)
238             { _do_handler(\&CHILDEXIT, $_[2], $_[4]); }
239              
240             sub UNIVERSAL::PerlRestartHandler : ATTR(BEGIN)
241             { _do_handler(\&RESTART, $_[2], $_[4]); }
242              
243             };
244              
245             1;
246              
247             __END__