File Coverage

blib/lib/Apache/ASP/GlobalASA.pm
Criterion Covered Total %
statement 111 127 87.4
branch 48 60 80.0
condition 11 19 57.8
subroutine 12 15 80.0
pod 0 11 0.0
total 182 232 78.4


line stmt bran cond sub pod time code
1              
2             package Apache::ASP::GlobalASA;
3              
4             # GlobalASA Object
5             # global.asa processes, whether or not there is a global.asa file.
6             # if there is not one, the code is left blank, and empty routines
7             # are filled in
8              
9 46     46   312 use strict;
  46         162  
  46         4377  
10 46     46   389 no strict qw(refs);
  46         123  
  46         1971  
11 46     46   348 use vars qw(%stash *stash @ISA @Routines);
  46         95  
  46         106323  
12              
13             # these define the default routines that get parsed out of the
14             # GLOBAL.ASA file
15             @Routines =
16             (
17             "Application_OnStart",
18             "Application_OnEnd",
19             "Session_OnStart",
20             "Session_OnEnd",
21             "Script_OnStart",
22             "Script_OnEnd",
23             "Script_OnParse",
24             "Script_OnFlush"
25             );
26             my $match_events = join('|', @Routines);
27              
28             sub new {
29 69   50 69 0 348 my $asp = shift || die("no asp passed to GlobalASA");
30              
31 69         264 my $filename = $asp->{global}.'/global.asa';
32 69         419 my $id = &Apache::ASP::FileId($asp, $asp->{global}, undef, 1);
33 69 100       545 my $package = $asp->{global_package} ? $asp->{global_package} : "Apache::ASP::Compiles::".$id;
34 69         238 $id .= 'x'.$package; # need to recompile when either file or namespace changes
35              
36             # make sure that when either the file or package changes, that we
37             # update the global.asa compilation
38              
39 69         673 my $self = bless {
40             asp => $asp,
41             'package' => $package,
42             # filename => $filename,
43             # id => $id,
44             };
45              
46             # assign early, since something like compiling reference the global asa,
47             # and we need to do that in here
48 69         219 $asp->{GlobalASA} = $self;
49              
50 69 100       363 $asp->{dbg} && $asp->Debug("GlobalASA package $self->{'package'}");
51 69         698 my $compiled = $Apache::ASP::Compiled{$id};
52 69 50 66     404 if($compiled && ! $asp->{stat_scripts}) {
53              
54             # $asp->{dbg} && $asp->Debug("no stat: GlobalASA already compiled");
55 0         0 $self->{'exists'} = $compiled->{'exists'};
56 0         0 $self->{'compiled'} = $compiled; # for event lookups
57 0         0 return $self;
58             }
59              
60 69 100       258 if($compiled) {
61             # $asp->{dbg} && $asp->Debug("global.asa was cached for $id");
62             } else {
63 48 100       473 $asp->{dbg} && $asp->Debug("global.asa was not cached for $id");
64 48         823 $compiled = $Apache::ASP::Compiled{$id} = { mtime => 0, 'exists' => 0 };
65             }
66 69         379 $self->{compiled} = $compiled;
67            
68 69         1342 my $exists = $self->{'exists'} = -e $filename;
69 69         421 my $changed = 0;
70 69 100 66     1212 if(! $exists && ! $compiled->{'exists'}) {
    50 33        
    100 66        
71             # fastest exit for simple case of no global.asa
72 3         15 return $self;
73             } elsif(! $exists && $compiled->{'exists'}) {
74             # if the global.asa disappeared
75 0         0 $changed = 1;
76             } elsif($exists && ! $compiled->{'exists'}) {
77             # if global.asa reappeared
78 45         126 $changed = 1;
79             } else {
80 21 50       121 $self->{mtime} = $exists ? (stat(_))[9] : 0;
81 21 50       96 if($self->{mtime} > $compiled->{mtime}) {
82             # if the modification time is greater than the compile time
83 0         0 $changed = 1;
84             }
85             }
86 66 100       431 $changed || return($self);
87              
88 45 50       286 my $code = $exists ? ${$asp->ReadFile($filename)} : "";
  45         345  
89 45 100       252 my $strict = $asp->{use_strict} ? "use strict" : "no strict";
90              
91 45 100       25619 if($code =~ s/\]*\>((.*)\s+sub\s+($match_events).*)\<\/script\>/$1/isg) {
92 38         288 $asp->Debug("script tags removed from $filename for IIS PerlScript compatibility");
93             }
94             $code = (
95 45         1753 "\n#line 1 $filename\n".
96             join(" ;; ",
97             "package $self->{'package'};",
98             $strict,
99             "use vars qw(\$".join(" \$",@Apache::ASP::Objects).');',
100             "use lib qw($self->{asp}->{global});",
101             $code,
102             'sub exit { $main::Response->End(); } ',
103             "no lib qw($self->{asp}->{global});",
104             '1;',
105             )
106             );
107              
108 45 100       336 $asp->{dbg} && $asp->Debug("compiling global.asa $self->{'package'} $id exists $exists", $self, '---', $compiled);
109 45         254 $code =~ /^(.*)$/s;
110 45         209 $code = $1;
111              
112             # turn off $^W to suppress warnings about reloading subroutines
113             # which is a valid use of global.asa. We cannot just undef
114             # all the events possible in global.asa, as global.asa can be
115             # used as a general package library for the web application
116             # --jc, 9/6/2002
117 45         246 local $^W = 0;
118              
119             # only way to catch strict errors here
120 45 100       210 if($asp->{use_strict}) {
121 15     0   136 local $SIG{__WARN__} = sub { die("maybe use strict error: ", @_) };
  0         0  
122 15         4729 eval $code;
123             } else {
124 30         8565 eval $code;
125             }
126              
127             # if we have success compiling, then update the compile time
128 45 50       121256 if(! $@) {
129             # if file mod times are bad, we need to use them anyway
130             # for relative comparison, time() was used here before, but
131             # doesn't work
132 45   33     1537 $compiled->{mtime} = $self->{mtime} || (stat($filename))[9];
133            
134             # remember whether the file really exists
135 45         196 $compiled->{'exists'} = $exists;
136            
137             # we cache whether the code was compiled so we can do quick
138             # lookups before executing it
139 45         141 my $routines = {};
140 45         109 local *stash = *{"$self->{'package'}::"};
  45         4424  
141 45         339 for(@Routines) {
142 360 100       1514 if($stash{$_}) {
143 195         674 $routines->{$_} = 1;
144             }
145             }
146 45         323 $compiled->{'routines'} = $routines;
147 45         388 $asp->Debug('global.asa routines', $routines);
148 45         135 $self->{'compiled'} = $compiled;
149             } else {
150 0         0 $asp->CompileErrorThrow($code, "errors compiling global.asa: $@");
151             }
152              
153 45         542 $self;
154             }
155              
156             sub IsCompiled {
157 15     15 0 33 my($self, $routine) = @_;
158 15         81 $self->{'compiled'}{routines}{$routine};
159             }
160              
161             sub ExecuteEvent {
162 279     279 0 706 my($self, $event) = @_;
163 279 100       1417 if($self->{'compiled'}{routines}{$event}) {
164 158         662 $self->{'asp'}->Execute($event);
165             }
166             }
167              
168             sub SessionOnStart {
169 28     28 0 55 my $self = shift;
170 28         69 my $asp = $self->{asp};
171 28         52 my $zero_sessions = 0;
172              
173 28 100       108 if($asp->{session_count}) {
174 15         58 $asp->{Internal}->LOCK();
175 15   100     3039 my $session_count = $asp->{Internal}{SessionCount} || 0;
176 15 100       59 if($session_count <= 0) {
177 1         5 $asp->{Internal}{SessionCount} = 1;
178 1         3 $zero_sessions = 1;
179             } else {
180 14         89 $asp->{Internal}{SessionCount} = $session_count + 1;
181             }
182 15         62 $asp->{Internal}->UNLOCK();
183             }
184              
185             #X: would like to run application startup code here after
186             # zero sessions is true, but doesn't seem to account for
187             # case of busy server, then 10 minutes later user comes in...
188             # since group cleanup happens after session, Application
189             # never starts. Its only when a user times out his own
190             # session, and comes back that this code would kick in.
191            
192 28         753 $asp->Debug("Session_OnStart", {session => $asp->{Session}->SessionID});
193 28         135 $self->ExecuteEvent('Session_OnStart');
194             }
195              
196             sub SessionOnEnd {
197 15     15 0 31 my($self, $id) = @_;
198 15         33 my $asp = $self->{asp};
199 15         39 my $internal = $asp->{Internal};
200              
201             # session count tracking
202 15 50       53 if($asp->{session_count}) {
203 15         46 $internal->LOCK();
204 15 50       3450 if((my $count = $internal->{SessionCount}) > 0) {
205 15         86 $internal->{SessionCount} = $count - 1;
206             } else {
207 0         0 $internal->{SessionCount} = 0;
208             }
209 15         70 $internal->UNLOCK();
210             }
211              
212             # only retie session if there is a Session_OnEnd event to execute
213 15 50       841 if($self->IsCompiled('Session_OnEnd')) {
214 15         31 my $old_session = $asp->{Session};
215 15         21 my $dead_session;
216 15 50       33 if($id) {
217 15         64 $dead_session = &Apache::ASP::Session::new($asp, $id);
218 15         36 $asp->{Session} = $dead_session;
219             } else {
220 0         0 $dead_session = $old_session;
221             }
222            
223 15 50       50 $asp->{dbg} && $asp->Debug("Session_OnEnd", {session => $dead_session->SessionID()});
224 15         52 $self->ExecuteEvent('Session_OnEnd');
225 15         35 $asp->{Session} = $old_session;
226            
227 15 50       37 if($id) {
228 15         19 untie %{$dead_session};
  15         81  
229             }
230             }
231              
232 15         51 1;
233             }
234              
235             sub ApplicationOnStart {
236 1     1 0 2 my $self = shift;
237 1         3 $self->{asp}->Debug("Application_OnStart");
238 1         1 %{$self->{asp}{Application}} = ();
  1         10  
239 1         5 $self->ExecuteEvent('Application_OnStart');
240             }
241              
242             sub ApplicationOnEnd {
243 0     0 0 0 my $self = shift;
244 0         0 my $asp = $self->{asp};
245 0         0 $asp->Debug("Application_OnEnd");
246 0         0 $self->ExecuteEvent('Application_OnEnd');
247 0         0 %{$self->{asp}{Application}} = ();
  0         0  
248              
249             # PROBLEM, since we are not resetting ASP objects
250             # every execute now, useless code anyway
251              
252             # delete $asp->{Internal}{'application'};
253             # local $^W = 0;
254             # my $tied = tied %{$asp->{Application}};
255             # untie %{$asp->{Application}};
256             # $tied->DESTROY(); # call explicit DESTROY
257             # $asp->{Application} = &Apache::ASP::Application::new($self->{asp})
258             # || $self->Error("can't get application state");
259             }
260              
261             sub ScriptOnStart {
262 46     46 0 111 my $self = shift;
263 46 100       243 $self->{asp}{dbg} && $self->{asp}->Debug("Script_OnStart");
264 46         158 $self->ExecuteEvent('Script_OnStart');
265             }
266              
267             sub ScriptOnEnd {
268 46     46 0 111 my $self = shift;
269 46 100       288 $self->{asp}{dbg} && $self->{asp}->Debug("Script_OnEnd");
270 46         252 $self->ExecuteEvent('Script_OnEnd');
271             }
272              
273             sub ScriptOnFlush {
274 51     51 0 120 my $self = shift;
275 51 100       241 $self->{asp}{dbg} && $self->{asp}->Debug("Script_OnFlush");
276 51         186 $self->ExecuteEvent('Script_OnFlush');
277             }
278              
279             sub EventsList {
280 0     0 0   @Routines;
281             }
282              
283             1;