| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# Copyright (C) 2006-2010 Andrew Speer . |
|
4
|
|
|
|
|
|
|
# All rights reserved. |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
# This file is part of WebDyne::Chain. |
|
7
|
|
|
|
|
|
|
# |
|
8
|
|
|
|
|
|
|
# WebDyne::Chain is free software; you can redistribute it and/or modify |
|
9
|
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by |
|
10
|
|
|
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or |
|
11
|
|
|
|
|
|
|
# (at your option) any later version. |
|
12
|
|
|
|
|
|
|
# |
|
13
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
|
14
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16
|
|
|
|
|
|
|
# GNU General Public License for more details. |
|
17
|
|
|
|
|
|
|
# |
|
18
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License |
|
19
|
|
|
|
|
|
|
# along with this program; if not, write to the Free Software |
|
20
|
|
|
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
21
|
|
|
|
|
|
|
# |
|
22
|
|
|
|
|
|
|
# |
|
23
|
|
|
|
|
|
|
package WebDyne::Chain; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# Compiler Pragma |
|
27
|
|
|
|
|
|
|
# |
|
28
|
1
|
|
|
1
|
|
21919
|
sub BEGIN { $^W=0 }; |
|
29
|
1
|
|
|
1
|
|
7
|
use strict qw(vars); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
27
|
|
|
30
|
1
|
|
|
1
|
|
4
|
use vars qw($VERSION); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
46
|
|
|
31
|
1
|
|
|
1
|
|
9
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
38
|
|
|
32
|
1
|
|
|
1
|
|
4
|
no warnings qw(uninitialized); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
26
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Webmod, WebDyne Modules. |
|
36
|
|
|
|
|
|
|
# |
|
37
|
1
|
|
|
1
|
|
1336
|
use WebDyne; |
|
|
1
|
|
|
|
|
234229
|
|
|
|
1
|
|
|
|
|
45
|
|
|
38
|
1
|
|
|
1
|
|
10
|
use WebDyne::Constant; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
577
|
|
|
39
|
1
|
|
|
1
|
|
872
|
use WebDyne::Chain::Constant; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
49
|
|
|
40
|
1
|
|
|
1
|
|
8
|
use WebDyne::Base; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
72
|
|
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Version information in a formate suitable for CPAN etc. Must be |
|
44
|
|
|
|
|
|
|
# all on one line |
|
45
|
|
|
|
|
|
|
# |
|
46
|
|
|
|
|
|
|
$VERSION='1.050'; |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# Debug using WebDyne debug handler |
|
50
|
|
|
|
|
|
|
# |
|
51
|
|
|
|
|
|
|
0 && debug("%s loaded, version $VERSION", __PACKAGE__); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Shortcut error handler, save using ISA; |
|
55
|
|
|
|
|
|
|
# |
|
56
|
|
|
|
|
|
|
require WebDyne::Err; |
|
57
|
|
|
|
|
|
|
*err_html=\&WebDyne::Err::err_html || *err_html; |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Package wide hash ref for data storage |
|
61
|
|
|
|
|
|
|
# |
|
62
|
|
|
|
|
|
|
my %Package; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Make all errors non-fatal |
|
66
|
|
|
|
|
|
|
# |
|
67
|
|
|
|
|
|
|
errnofatal(1); |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# And done |
|
71
|
|
|
|
|
|
|
# |
|
72
|
|
|
|
|
|
|
1; |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub handler : method { |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Get class, request object |
|
82
|
|
|
|
|
|
|
# |
|
83
|
0
|
|
|
0
|
0
|
|
my ($self, $r, $param_hr)=@_; |
|
84
|
0
|
|
0
|
|
|
|
my $class=ref($self) || do { |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Need new self ref |
|
88
|
|
|
|
|
|
|
# |
|
89
|
|
|
|
|
|
|
my %self=( |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
_time => time(), |
|
92
|
|
|
|
|
|
|
_r => $r, |
|
93
|
|
|
|
|
|
|
%{delete $self->{'_self'}}, |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
); |
|
96
|
|
|
|
|
|
|
$self=bless \%self, $self; |
|
97
|
|
|
|
|
|
|
ref($self); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
}; |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Setup error handlers |
|
104
|
|
|
|
|
|
|
# |
|
105
|
0
|
|
|
0
|
|
|
local $SIG{__DIE__} =sub { return $self->err_html(@_) }; |
|
|
0
|
|
|
|
|
|
|
|
106
|
0
|
0
|
|
0
|
|
|
local $SIG{__WARN__}=sub { return $self->err_html(@_) } if $WEBDYNE_WARNINGS_FATAL; |
|
|
0
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Debug |
|
110
|
|
|
|
|
|
|
# |
|
111
|
0
|
|
|
|
|
|
0 && debug("in WebDyne::Chain::handler, class $class, r $r, self $self, param_hr %s", |
|
112
|
|
|
|
|
|
|
Dumper($param_hr)); |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# Log URI |
|
116
|
|
|
|
|
|
|
# |
|
117
|
0
|
|
|
|
|
|
0 && debug("URI %s", $r->uri()); |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Get string of modules to chain |
|
121
|
|
|
|
|
|
|
# |
|
122
|
0
|
|
|
|
|
|
my @module; |
|
123
|
0
|
0
|
|
|
|
|
if (my $module_ar=$param_hr->{'meta'}{'webdynechain'}) { |
|
|
|
0
|
|
|
|
|
|
|
124
|
0
|
|
|
|
|
|
0 && debug("using module_ar $module_ar %s from meta", Dumper($module_ar)); |
|
125
|
0
|
|
|
|
|
|
@module=@{$module_ar}; |
|
|
0
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
elsif (my $module=$r->dir_config('WebDyneChain')) { |
|
128
|
0
|
|
|
|
|
|
0 && debug("using module $module dir_config"); |
|
129
|
0
|
|
|
|
|
|
@module=split(/\s+/, $module); |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
else { |
|
132
|
0
|
|
|
|
|
|
0 && debug('could not find any module chain info'); |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# WebDyne::Chain must be the first handler in line, Webdyne the last |
|
137
|
|
|
|
|
|
|
# |
|
138
|
0
|
0
|
|
|
|
|
unshift @module, __PACKAGE__ unless ($module[0] eq +__PACKAGE__); |
|
139
|
0
|
0
|
|
|
|
|
push @module, 'WebDyne' unless ($module[$#module] eq 'WebDyne'); |
|
140
|
0
|
|
|
|
|
|
0 && debug('final module chain %s', join('*', @module)); |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Store current chain |
|
144
|
|
|
|
|
|
|
# |
|
145
|
0
|
|
|
|
|
|
$Package{'_chain_ar'}=\@module; |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# If only two modules (WebDyne::Chain, WebDyne) something is wrong |
|
149
|
|
|
|
|
|
|
# |
|
150
|
0
|
0
|
|
|
|
|
if (@module==2) { |
|
151
|
|
|
|
|
|
|
return |
|
152
|
0
|
|
|
|
|
|
$self->err_html('unable to determine module chain - have you set WebDyneChain var ?'); |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Get location. Used to use r->location, now use module array to generate pseudo |
|
157
|
|
|
|
|
|
|
# location data; |
|
158
|
|
|
|
|
|
|
# |
|
159
|
0
|
|
|
|
|
|
my $location=join(undef, @module); |
|
160
|
0
|
|
|
|
|
|
0 && debug("location $location"); |
|
161
|
0
|
0
|
|
|
|
|
unless ($Package{'_chain_loaded_hr'}{$location}++) { |
|
162
|
0
|
|
|
|
|
|
0 && debug("modules not loaded, doing now"); |
|
163
|
0
|
|
|
|
|
|
local $SIG{'__DIE__'}; |
|
164
|
0
|
|
|
|
|
|
foreach my $package (@module) { |
|
165
|
0
|
0
|
|
|
|
|
eval("require $package") || |
|
166
|
|
|
|
|
|
|
return $self->err_html("unable to load package $package, ".lcfirst($@)); |
|
167
|
0
|
|
|
|
|
|
0 && debug("loaded $package"); |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# If location not same as last time we were run, then unload chain |
|
173
|
|
|
|
|
|
|
# |
|
174
|
0
|
0
|
|
|
|
|
if ((my $location_current=$Package{'_location_current'}) ne $location) { |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Need to unload cached code refs |
|
178
|
|
|
|
|
|
|
# |
|
179
|
0
|
|
|
|
|
|
0 && debug("location_current '$location_current' is ne this location ('$location'). restoring cr's"); |
|
180
|
0
|
|
|
|
|
|
&ISA_restore(); |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# Update location |
|
184
|
|
|
|
|
|
|
# |
|
185
|
0
|
|
|
|
|
|
$Package{'_location_current'}=$location; |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# If code ref's cached, load up now |
|
189
|
|
|
|
|
|
|
# |
|
190
|
0
|
0
|
|
|
|
|
if (my $chain_hr=$Package{'_chain_hr'}{$location}) { |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Debug |
|
194
|
|
|
|
|
|
|
# |
|
195
|
0
|
|
|
|
|
|
0 && debug("found cached code ref's for location $location loading"); |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Yes found, load up |
|
199
|
|
|
|
|
|
|
# |
|
200
|
0
|
|
|
|
|
|
while (my($method,$cr)=each %{$chain_hr}) { |
|
|
0
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Debug |
|
204
|
|
|
|
|
|
|
# |
|
205
|
0
|
|
|
|
|
|
0 && debug("loading cr $cr for method $method"); |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Install code ref |
|
209
|
|
|
|
|
|
|
# |
|
210
|
0
|
|
|
|
|
|
*{$method}=$cr; |
|
|
0
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# Update current pointer |
|
216
|
|
|
|
|
|
|
# |
|
217
|
0
|
|
|
|
|
|
$Package{'_chain_current_hr'}=$chain_hr; |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
} |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
else { |
|
223
|
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
0 && debug('location chain same as last request, caching'); |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Debug |
|
230
|
|
|
|
|
|
|
# |
|
231
|
0
|
|
|
|
|
|
0 && debug('module array %s', Dumper(\@module)); |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# All done, pass onto next handler in chain. NOTE no error handler (eg || $self->err_html). It is |
|
235
|
|
|
|
|
|
|
# not our job to check for errors here, we should just pass back whatever the next handler does. |
|
236
|
|
|
|
|
|
|
# |
|
237
|
0
|
|
|
|
|
|
return $self->SUPER::handler($r, @_[2..$#_]); |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Only get here if error handler invoked |
|
241
|
|
|
|
|
|
|
# |
|
242
|
0
|
|
|
|
|
|
RENDER_ERROR: |
|
243
|
|
|
|
|
|
|
return $self->err_html(); |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Only get here if subrequest invoked. |
|
247
|
0
|
|
|
|
|
|
HANDLER_COMPLETE: |
|
248
|
|
|
|
|
|
|
return &Apache::OK; |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
} |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub ISA_restore { |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Get cuurent chain hash |
|
258
|
|
|
|
|
|
|
# |
|
259
|
0
|
|
|
0
|
0
|
|
my $chain_hr=delete $Package{'_chain_current_hr'}; |
|
260
|
0
|
|
|
|
|
|
0 && debug('in ISA_restore, chain %s', Dumper($chain_hr)); |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# Go through each module, restoring |
|
264
|
|
|
|
|
|
|
# |
|
265
|
0
|
|
|
|
|
|
foreach my $method (keys %{$chain_hr}) { |
|
|
0
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# Free up |
|
269
|
|
|
|
|
|
|
# |
|
270
|
0
|
|
|
|
|
|
0 && debug("free $method"); |
|
271
|
0
|
|
|
|
|
|
undef *{$method}; |
|
|
0
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
} |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub DESTROY { |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# Get chain array ref |
|
284
|
|
|
|
|
|
|
# |
|
285
|
0
|
|
|
0
|
|
|
my $self=shift(); |
|
286
|
0
|
|
|
|
|
|
my $chain_ar=$Package{'_chain_ar'}; |
|
287
|
0
|
|
|
|
|
|
0 && debug("self $self, going through DESTROY chain %s", Dumper($chain_ar)); |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Handle destroys specially, mini version of AUTOLOAD code below |
|
291
|
|
|
|
|
|
|
# |
|
292
|
0
|
|
|
|
|
|
foreach my $i (1 .. $#{$chain_ar}) { |
|
|
0
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
my $package_chain=$chain_ar->[$i]; |
|
294
|
0
|
|
|
|
|
|
0 && debug("looking for DESTROY $package_chain"); |
|
295
|
0
|
0
|
|
|
|
|
if (my $cr=UNIVERSAL::can($package_chain, 'DESTROY')) { |
|
296
|
0
|
|
|
|
|
|
0 && debug("DESTROY hit on $package_chain"); |
|
297
|
0
|
|
|
|
|
|
$cr->($self); |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
} |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# Destroy object |
|
303
|
|
|
|
|
|
|
# |
|
304
|
0
|
|
|
|
|
|
%{$self}=(); |
|
|
0
|
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
undef $self; |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub UNIVERSAL::AUTOLOAD { |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# Get self ref, calling class, autoloaded method |
|
316
|
|
|
|
|
|
|
# |
|
317
|
0
|
|
|
0
|
|
|
my $self=$_[0]; |
|
318
|
0
|
|
0
|
|
|
|
my $autoload=$UNIVERSAL::AUTOLOAD || return; |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Do not handle DESTROY's |
|
322
|
|
|
|
|
|
|
# |
|
323
|
0
|
0
|
|
|
|
|
return if $autoload=~/::DESTROY$/; |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
# Debug |
|
327
|
|
|
|
|
|
|
# |
|
328
|
0
|
|
|
|
|
|
0 && debug("in UNIVERSAL::AUTOLOAD, self $self, autoload $autoload, caller %s", |
|
329
|
|
|
|
|
|
|
Dumper([(caller(1))[0..3]])); |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# Get apache request ref, location. If not present means called by non-WebDyne class, not supported |
|
333
|
|
|
|
|
|
|
# |
|
334
|
0
|
|
|
|
|
|
my $r; { |
|
335
|
0
|
|
|
|
|
|
local $SIG{'__DIE__'}=undef; |
|
|
0
|
|
|
|
|
|
|
|
336
|
0
|
0
|
|
|
|
|
unless (eval{ ref($self) && ($r=$self->{'_r'}) }) { |
|
|
0
|
0
|
|
|
|
|
|
|
337
|
0
|
|
|
|
|
|
err("call to run %s UNIVERSAL::AUTOLOAD for non chained method '$autoload', self ref '$self'.", +__PACKAGE__); |
|
338
|
0
|
|
|
|
|
|
goto RENDER_ERROR; |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# Get method user was looking for, keep full package name. |
|
345
|
|
|
|
|
|
|
# |
|
346
|
0
|
|
|
|
|
|
my ($package_autoload, $method_autoload)=($autoload=~/(.*)::(.*?)$/); |
|
347
|
0
|
|
|
|
|
|
0 && debug("package_autoload $package_autoload, method_autoload $method_autoload"); |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# And chain for this location |
|
351
|
|
|
|
|
|
|
# |
|
352
|
0
|
|
|
|
|
|
my $chain_ar=$Package{'_chain_ar'}; |
|
353
|
0
|
|
|
|
|
|
my $location=join(undef, @{$chain_ar}); |
|
|
0
|
|
|
|
|
|
|
|
354
|
0
|
|
|
|
|
|
0 && debug('going through chain %s', Dumper($chain_ar)); |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Caller information |
|
358
|
|
|
|
|
|
|
# |
|
359
|
0
|
|
|
|
|
|
my $subroutine_caller=(caller(1))[3]; |
|
360
|
0
|
|
|
|
|
|
my $subroutine_caller_cr=\&{"$subroutine_caller"}; |
|
|
0
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
my ($package_caller, $method_caller)=($subroutine_caller=~/(.*)::(.*?)$/); |
|
362
|
0
|
|
|
|
|
|
0 && debug("package_caller $package_caller, method_caller $method_caller"); |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# If SUPER method trawl through chain to find the package it was called from, make sure we start |
|
366
|
|
|
|
|
|
|
# from there in iteration code below |
|
367
|
|
|
|
|
|
|
# |
|
368
|
0
|
|
|
|
|
|
my $i=0; |
|
369
|
0
|
0
|
|
|
|
|
if ($autoload=~/\QSUPER::$method_autoload\E$/) { |
|
370
|
0
|
|
|
|
|
|
0 && debug("SUPER method"); |
|
371
|
0
|
|
|
|
|
|
for (1; $i < @{$chain_ar}; $i++) { |
|
|
0
|
|
|
|
|
|
|
|
372
|
0
|
0
|
|
|
|
|
if (UNIVERSAL::can($chain_ar->[$i], $method_caller) eq $subroutine_caller_cr) { |
|
373
|
0
|
|
|
|
|
|
$i++; |
|
374
|
0
|
|
|
|
|
|
last; |
|
375
|
|
|
|
|
|
|
} |
|
376
|
|
|
|
|
|
|
else { |
|
377
|
0
|
|
|
|
|
|
0 && debug("miss on package $chain_ar->[$i], $_ ne $subroutine_caller_cr"); |
|
378
|
|
|
|
|
|
|
} |
|
379
|
|
|
|
|
|
|
} |
|
380
|
0
|
|
|
|
|
|
0 && debug("loop finished, i $i, chain_ar %s", $#{$chain_ar}); |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Iterate through the chain (in order) looking for the method |
|
385
|
|
|
|
|
|
|
# |
|
386
|
0
|
|
|
|
|
|
foreach $i ($i .. $#{$chain_ar}) { |
|
|
0
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# Can this package in the chain support the calling method ? |
|
390
|
|
|
|
|
|
|
# |
|
391
|
0
|
|
|
|
|
|
0 && debug("look for $method_autoload in package $chain_ar->[$i]"); |
|
392
|
0
|
0
|
|
|
|
|
if (my $cr=UNIVERSAL::can($chain_ar->[$i], $method_autoload)) { |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# Yes. Check for loops |
|
396
|
|
|
|
|
|
|
# |
|
397
|
0
|
0
|
|
|
|
|
if ($cr eq $subroutine_caller_cr) { |
|
398
|
0
|
|
|
|
|
|
err("detected AUTOLOAD loop for method '$method_autoload' ". |
|
399
|
0
|
|
|
|
|
|
"package $package_caller. Current chain: %s", join(', ', @{$chain_ar})); |
|
400
|
0
|
|
|
|
|
|
goto RENDER_ERROR; |
|
401
|
|
|
|
|
|
|
} |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# Update |
|
405
|
|
|
|
|
|
|
# |
|
406
|
0
|
|
|
|
|
|
0 && debug('hit'); |
|
407
|
0
|
|
|
|
|
|
*{$autoload}=$cr; |
|
|
0
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
# And keep a record |
|
411
|
|
|
|
|
|
|
# |
|
412
|
0
|
|
|
|
|
|
$Package{'_chain_hr'}{$location}{$autoload}=$cr; |
|
413
|
0
|
|
0
|
|
|
|
$Package{'_chain_current_hr'} ||= $Package{'_chain_hr'}{$location}; |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
# And dispatch. The commented out code is good for debugging internal |
|
417
|
|
|
|
|
|
|
# server errors, esp if comment out *{$autoload} above and turn on |
|
418
|
|
|
|
|
|
|
# debugging |
|
419
|
|
|
|
|
|
|
# |
|
420
|
0
|
|
|
|
|
|
goto &{$cr}; |
|
|
0
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
} |
|
423
|
|
|
|
|
|
|
else { |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# Debug |
|
427
|
|
|
|
|
|
|
# |
|
428
|
0
|
|
|
|
|
|
0 && debug("unable to find method $method_autoload in package $chain_ar->[$i]"); |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
} |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# Last resort - look back through call chain |
|
436
|
|
|
|
|
|
|
# |
|
437
|
0
|
|
|
|
|
|
0 && debug("checking back through callstack for method $method_autoload"); |
|
438
|
0
|
|
|
|
|
|
my %chain=map { $_=> 1} @{$chain_ar}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
|
my @caller; |
|
440
|
0
|
|
|
|
|
|
for ($i=0; my $caller=(caller($i))[0]; $i++) { |
|
441
|
0
|
0
|
|
|
|
|
next if $chain{$caller}++; #already looked there |
|
442
|
0
|
|
|
|
|
|
push @caller, $caller; |
|
443
|
0
|
0
|
|
|
|
|
if (my $cr=UNIVERSAL::can($caller, $method_autoload)) { |
|
444
|
0
|
0
|
|
|
|
|
if ($cr eq $subroutine_caller_cr) { |
|
445
|
0
|
|
|
|
|
|
err("detected AUTOLOAD loop for method '$method_autoload' ". |
|
446
|
0
|
|
|
|
|
|
"package $package_caller. Current chain: %s", join(', ', @{$chain_ar})); |
|
447
|
0
|
|
|
|
|
|
goto RENDER_ERROR; |
|
448
|
|
|
|
|
|
|
} |
|
449
|
0
|
0
|
|
|
|
|
if ($WEBDYNE_AUTOLOAD_POLLUTE) { |
|
450
|
0
|
|
|
|
|
|
*{$autoload}=$cr; |
|
|
0
|
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
|
$Package{'_chain_hr'}{$location}{$autoload}=$cr; |
|
452
|
|
|
|
|
|
|
} |
|
453
|
0
|
|
|
|
|
|
goto &{$cr} |
|
|
0
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
} |
|
455
|
|
|
|
|
|
|
} |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# Return err |
|
459
|
|
|
|
|
|
|
# |
|
460
|
0
|
|
|
|
|
|
err("method '$method_autoload' not found in call chain: %s", join(',', @caller)); |
|
461
|
0
|
|
|
|
|
|
goto RENDER_ERROR; |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
} |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
__END__ |