Filename | /var/www/foswiki11/lib/Foswiki/UI.pm |
Statements | Executed 93 statements in 2.73ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 1.14ms | 1.25ms | BEGIN@160 | Foswiki::UI::
1 | 1 | 1 | 221µs | 262µs | BEGIN@157 | Foswiki::UI::
1 | 1 | 1 | 178µs | 61.4s | _execute | Foswiki::UI::
1 | 1 | 1 | 79µs | 61.4s | handleRequest | Foswiki::UI::
1 | 1 | 1 | 45µs | 45µs | BEGIN@16 | Foswiki::UI::
1 | 1 | 1 | 45µs | 61.3s | __ANON__[:318] | Foswiki::UI::
1 | 1 | 1 | 15µs | 90µs | checkWebExists | Foswiki::UI::
1 | 1 | 1 | 13µs | 28µs | BEGIN@13 | Foswiki::UI::
1 | 1 | 1 | 13µs | 946µs | checkAccess | Foswiki::UI::
1 | 1 | 1 | 10µs | 130µs | BEGIN@149 | Foswiki::UI::
1 | 1 | 1 | 10µs | 22µs | BEGIN@150 | Foswiki::UI::
1 | 1 | 1 | 9µs | 16µs | BEGIN@14 | Foswiki::UI::
1 | 1 | 1 | 9µs | 38µs | BEGIN@165 | Foswiki::UI::
1 | 1 | 1 | 4µs | 4µs | BEGIN@158 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@151 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@159 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@155 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@154 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@156 | Foswiki::UI::
1 | 1 | 1 | 3µs | 3µs | BEGIN@153 | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:348] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:371] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:380] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:395] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:428] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | __ANON__[:435] | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | checkTopicExists | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | checkValidationKey | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | logon | Foswiki::UI::
0 | 0 | 0 | 0s | 0s | run | Foswiki::UI::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+!! package Foswiki::UI | ||||
6 | |||||
7 | Coordinator of execution flow and service functions used by the UI packages | ||||
8 | |||||
9 | =cut | ||||
10 | |||||
11 | package Foswiki::UI; | ||||
12 | |||||
13 | 2 | 27µs | 2 | 43µs | # spent 28µs (13+15) within Foswiki::UI::BEGIN@13 which was called:
# once (13µs+15µs) by main::BEGIN@23 at line 13 # spent 28µs making 1 call to Foswiki::UI::BEGIN@13
# spent 15µs making 1 call to strict::import |
14 | 2 | 343µs | 2 | 22µs | # spent 16µs (9+7) within Foswiki::UI::BEGIN@14 which was called:
# once (9µs+7µs) by main::BEGIN@23 at line 14 # spent 16µs making 1 call to Foswiki::UI::BEGIN@14
# spent 6µs making 1 call to warnings::import |
15 | |||||
16 | # spent 45µs within Foswiki::UI::BEGIN@16 which was called:
# once (45µs+0s) by main::BEGIN@23 at line 147 | ||||
17 | |||||
18 | #Monitor::MARK("Start of BEGIN block in UI.pm"); | ||||
19 | 1 | 1µs | $Foswiki::cfg{SwitchBoard} ||= {}; | ||
20 | |||||
21 | # package - perl package that contains the method for this request | ||||
22 | # function - name of the function in package | ||||
23 | # context - hash of context vars to define | ||||
24 | # allow - hash of HTTP methods to allow (all others are denied) | ||||
25 | # deny - hash of HTTP methods that are denied (all others are allowed) | ||||
26 | # 'deny' is not tested if 'allow' is defined | ||||
27 | |||||
28 | # The switchboard can contain entries either as hashes or as arrays. | ||||
29 | # The array format specifies [0] package, [1] function, [2] context | ||||
30 | # and should be used when declaring scripts from plugins that must work | ||||
31 | # with Foswiki 1.0.0 and 1.0.4. | ||||
32 | |||||
33 | 1 | 7µs | $Foswiki::cfg{SwitchBoard}{attach} = { | ||
34 | package => 'Foswiki::UI::Attach', | ||||
35 | function => 'attach', | ||||
36 | context => { attach => 1 }, | ||||
37 | }; | ||||
38 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{changes} = { | ||
39 | package => 'Foswiki::UI::Changes', | ||||
40 | function => 'changes', | ||||
41 | context => { changes => 1 }, | ||||
42 | }; | ||||
43 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{edit} = { | ||
44 | package => 'Foswiki::UI::Edit', | ||||
45 | function => 'edit', | ||||
46 | context => { edit => 1 }, | ||||
47 | }; | ||||
48 | 1 | 3µs | $Foswiki::cfg{SwitchBoard}{login} = { | ||
49 | package => undef, | ||||
50 | function => 'logon', | ||||
51 | context => { ( login => 1, logon => 1 ) }, | ||||
52 | }; | ||||
53 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{logon} = { | ||
54 | package => undef, | ||||
55 | function => 'logon', | ||||
56 | context => { ( login => 1, logon => 1 ) }, | ||||
57 | }; | ||||
58 | 1 | 3µs | $Foswiki::cfg{SwitchBoard}{manage} = { | ||
59 | package => 'Foswiki::UI::Manage', | ||||
60 | function => 'manage', | ||||
61 | context => { manage => 1 }, | ||||
62 | allow => { POST => 1 }, | ||||
63 | }; | ||||
64 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{oops} = { | ||
65 | package => 'Foswiki::UI::Oops', | ||||
66 | function => 'oops_cgi', | ||||
67 | context => { oops => 1 }, | ||||
68 | }; | ||||
69 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{preview} = { | ||
70 | package => 'Foswiki::UI::Preview', | ||||
71 | function => 'preview', | ||||
72 | context => { preview => 1 }, | ||||
73 | }; | ||||
74 | 1 | 500ns | $Foswiki::cfg{SwitchBoard}{previewauth} = | ||
75 | $Foswiki::cfg{SwitchBoard}{preview}; | ||||
76 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{rdiff} = { | ||
77 | package => 'Foswiki::UI::RDiff', | ||||
78 | function => 'diff', | ||||
79 | context => { diff => 1 }, | ||||
80 | }; | ||||
81 | 1 | 400ns | $Foswiki::cfg{SwitchBoard}{rdiffauth} = $Foswiki::cfg{SwitchBoard}{rdiff}; | ||
82 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{register} = { | ||
83 | package => 'Foswiki::UI::Register', | ||||
84 | function => 'register_cgi', | ||||
85 | context => { register => 1 }, | ||||
86 | |||||
87 | # method verify must allow GET; protect in Foswiki::UI::Register | ||||
88 | #allow => { POST => 1 }, | ||||
89 | }; | ||||
90 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{rename} = { | ||
91 | package => 'Foswiki::UI::Rename', | ||||
92 | function => 'rename', | ||||
93 | context => { rename => 1 }, | ||||
94 | |||||
95 | # Rename is 2 stage; protect in Foswiki::UI::Rename | ||||
96 | #allow => { POST => 1 }, | ||||
97 | }; | ||||
98 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{resetpasswd} = { | ||
99 | package => 'Foswiki::UI::Passwords', | ||||
100 | function => 'resetPassword', | ||||
101 | context => { resetpasswd => 1 }, | ||||
102 | allow => { POST => 1 }, | ||||
103 | }; | ||||
104 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{rest} = { | ||
105 | package => 'Foswiki::UI::Rest', | ||||
106 | function => 'rest', | ||||
107 | context => { rest => 1 }, | ||||
108 | }; | ||||
109 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{restauth} = $Foswiki::cfg{SwitchBoard}{rest}; | ||
110 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{save} = { | ||
111 | package => 'Foswiki::UI::Save', | ||||
112 | function => 'save', | ||||
113 | context => { save => 1 }, | ||||
114 | allow => { POST => 1 }, | ||||
115 | }; | ||||
116 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{search} = { | ||
117 | package => 'Foswiki::UI::Search', | ||||
118 | function => 'search', | ||||
119 | context => { search => 1 }, | ||||
120 | }; | ||||
121 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{statistics} = { | ||
122 | package => 'Foswiki::UI::Statistics', | ||||
123 | function => 'statistics', | ||||
124 | context => { statistics => 1 }, | ||||
125 | }; | ||||
126 | 1 | 2µs | $Foswiki::cfg{SwitchBoard}{upload} = { | ||
127 | package => 'Foswiki::UI::Upload', | ||||
128 | function => 'upload', | ||||
129 | context => { upload => 1 }, | ||||
130 | allow => { POST => 1 }, | ||||
131 | }; | ||||
132 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{viewfile} = { | ||
133 | package => 'Foswiki::UI::Viewfile', | ||||
134 | function => 'viewfile', | ||||
135 | context => { viewfile => 1 }, | ||||
136 | }; | ||||
137 | 1 | 500ns | $Foswiki::cfg{SwitchBoard}{viewfileauth} = | ||
138 | $Foswiki::cfg{SwitchBoard}{viewfile}; | ||||
139 | 1 | 1µs | $Foswiki::cfg{SwitchBoard}{view} = { | ||
140 | package => 'Foswiki::UI::View', | ||||
141 | function => 'view', | ||||
142 | context => { view => 1 }, | ||||
143 | }; | ||||
144 | 1 | 5µs | $Foswiki::cfg{SwitchBoard}{viewauth} = $Foswiki::cfg{SwitchBoard}{view}; | ||
145 | |||||
146 | #Monitor::MARK("End of BEGIN block in UI.pm"); | ||||
147 | 1 | 50µs | 1 | 45µs | } # spent 45µs making 1 call to Foswiki::UI::BEGIN@16 |
148 | |||||
149 | 2 | 30µs | 2 | 252µs | # spent 130µs (10+121) within Foswiki::UI::BEGIN@149 which was called:
# once (10µs+121µs) by main::BEGIN@23 at line 149 # spent 130µs making 1 call to Foswiki::UI::BEGIN@149
# spent 121µs making 1 call to Error::import |
150 | 2 | 23µs | 2 | 34µs | # spent 22µs (10+12) within Foswiki::UI::BEGIN@150 which was called:
# once (10µs+12µs) by main::BEGIN@23 at line 150 # spent 22µs making 1 call to Foswiki::UI::BEGIN@150
# spent 12µs making 1 call to Assert::import |
151 | 2 | 18µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@151 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 151 # spent 3µs making 1 call to Foswiki::UI::BEGIN@151 |
152 | |||||
153 | 2 | 16µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@153 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 153 # spent 3µs making 1 call to Foswiki::UI::BEGIN@153 |
154 | 2 | 17µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@154 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 154 # spent 3µs making 1 call to Foswiki::UI::BEGIN@154 |
155 | 2 | 17µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@155 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 155 # spent 3µs making 1 call to Foswiki::UI::BEGIN@155 |
156 | 2 | 17µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@156 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 156 # spent 3µs making 1 call to Foswiki::UI::BEGIN@156 |
157 | 2 | 93µs | 1 | 262µs | # spent 262µs (221+42) within Foswiki::UI::BEGIN@157 which was called:
# once (221µs+42µs) by main::BEGIN@23 at line 157 # spent 262µs making 1 call to Foswiki::UI::BEGIN@157 |
158 | 2 | 17µs | 1 | 4µs | # spent 4µs within Foswiki::UI::BEGIN@158 which was called:
# once (4µs+0s) by main::BEGIN@23 at line 158 # spent 4µs making 1 call to Foswiki::UI::BEGIN@158 |
159 | 2 | 16µs | 1 | 3µs | # spent 3µs within Foswiki::UI::BEGIN@159 which was called:
# once (3µs+0s) by main::BEGIN@23 at line 159 # spent 3µs making 1 call to Foswiki::UI::BEGIN@159 |
160 | 2 | 101µs | 1 | 1.25ms | # spent 1.25ms (1.14+108µs) within Foswiki::UI::BEGIN@160 which was called:
# once (1.14ms+108µs) by main::BEGIN@23 at line 160 # spent 1.25ms making 1 call to Foswiki::UI::BEGIN@160 |
161 | |||||
162 | # Used to lazily load UI handler modules | ||||
163 | 1 | 900ns | our %isInitialized = (); | ||
164 | |||||
165 | 2 | 1.61ms | 2 | 66µs | # spent 38µs (9+29) within Foswiki::UI::BEGIN@165 which was called:
# once (9µs+29µs) by main::BEGIN@23 at line 165 # spent 38µs making 1 call to Foswiki::UI::BEGIN@165
# spent 29µs making 1 call to constant::import |
166 | |||||
167 | =begin TML | ||||
168 | |||||
169 | ---++ StaticMethod handleRequest($req) -> $res | ||||
170 | |||||
171 | Main coordinator of request-process-response cycle. | ||||
172 | |||||
173 | =cut | ||||
174 | |||||
175 | # spent 61.4s (79µs+61.4) within Foswiki::UI::handleRequest which was called:
# once (79µs+61.4s) by Foswiki::Engine::CLI::run at line 53 of /var/www/foswiki11/lib/Foswiki/Engine/CLI.pm | ||||
176 | 1 | 300ns | my $req = shift; | ||
177 | |||||
178 | 1 | 100ns | my $res; | ||
179 | 1 | 2µs | 1 | 2µs | my $dispatcher = $Foswiki::cfg{SwitchBoard}{ $req->action() }; # spent 2µs making 1 call to Foswiki::Request::action |
180 | 1 | 200ns | unless ( defined $dispatcher ) { | ||
181 | $res = new Foswiki::Response(); | ||||
182 | $res->header( -type => 'text/html', -status => '404' ); | ||||
183 | my $html = CGI::start_html('404 Not Found'); | ||||
184 | $html .= CGI::h1( {}, 'Not Found' ); | ||||
185 | $html .= CGI::p( {}, | ||||
186 | "The requested URL " | ||||
187 | . $req->uri | ||||
188 | . " was not found on this server." ); | ||||
189 | $html .= CGI::end_html(); | ||||
190 | $res->print($html); | ||||
191 | return $res; | ||||
192 | } | ||||
193 | |||||
194 | 1 | 700ns | if ( ref($dispatcher) eq 'ARRAY' ) { | ||
195 | |||||
196 | # Old-style array entry in switchboard from a plugin | ||||
197 | my @array = @$dispatcher; | ||||
198 | $dispatcher = { | ||||
199 | package => $array[0], | ||||
200 | function => $array[1], | ||||
201 | context => $array[2], | ||||
202 | }; | ||||
203 | } | ||||
204 | |||||
205 | 1 | 1µs | if ( $dispatcher->{package} && !$isInitialized{ $dispatcher->{package} } ) { | ||
206 | 1 | 38µs | eval qq(use $dispatcher->{package}); # spent 98µs executing statements in string eval # includes 1.96ms spent executing 1 call to 1 sub defined therein. | ||
207 | 1 | 200ns | die $@ if $@; | ||
208 | 1 | 2µs | $isInitialized{ $dispatcher->{package} } = 1; | ||
209 | } | ||||
210 | |||||
211 | 1 | 200ns | my $sub; | ||
212 | 1 | 800ns | $sub = $dispatcher->{package} . '::' if $dispatcher->{package}; | ||
213 | 1 | 300ns | $sub .= $dispatcher->{function}; | ||
214 | |||||
215 | # Get the params cache from the path | ||||
216 | 1 | 2µs | 1 | 21µs | my $cache = $req->param('foswiki_redirect_cache'); # spent 21µs making 1 call to Foswiki::Request::param |
217 | 1 | 100ns | if ( defined $cache ) { | ||
218 | $req->delete('foswiki_redirect_cache'); | ||||
219 | } | ||||
220 | |||||
221 | # If the path specifies a cache path, use that. It's arbitrary | ||||
222 | # as to which takes precedence (param or path) because we should | ||||
223 | # never have both at once. | ||||
224 | 1 | 3µs | 1 | 4µs | my $path_info = $req->path_info(); # spent 4µs making 1 call to Foswiki::Request::pathInfo |
225 | 1 | 500ns | if ( $path_info =~ s#/foswiki_redirect_cache/([a-f0-9]{32})## ) { | ||
226 | $cache = $1; | ||||
227 | $req->path_info($path_info); | ||||
228 | } | ||||
229 | |||||
230 | 1 | 200ns | if ( defined $cache && $cache =~ /^([a-f0-9]{32})$/ ) { | ||
231 | require Foswiki::Request::Cache; | ||||
232 | |||||
233 | # implicit untaint required, because $cache may be used in a filename. | ||||
234 | # Note that the cache serialises the method and path_info, which | ||||
235 | # will be restored. | ||||
236 | Foswiki::Request::Cache->new()->load( $1, $req ); | ||||
237 | } | ||||
238 | |||||
239 | if (TRACE_REQUEST) { | ||||
240 | print STDERR "INCOMING " | ||||
241 | . $req->method() . " " | ||||
242 | . $req->url . " -> " | ||||
243 | . $sub . "\n"; | ||||
244 | print STDERR "validation_key: " | ||||
245 | . ( $req->param('validation_key') || 'no key' ) . "\n"; | ||||
246 | |||||
247 | #require Data::Dumper; | ||||
248 | #print STDERR Data::Dumper->Dump([$req]); | ||||
249 | } | ||||
250 | |||||
251 | 1 | 5µs | 1 | 2µs | if ( UNIVERSAL::isa( $Foswiki::engine, 'Foswiki::Engine::CLI' ) ) { # spent 2µs making 1 call to UNIVERSAL::isa |
252 | $dispatcher->{context}->{command_line} = 1; | ||||
253 | } | ||||
254 | elsif ( | ||||
255 | defined $req->method() | ||||
256 | && ( | ||||
257 | ( | ||||
258 | defined $dispatcher->{allow} | ||||
259 | && !$dispatcher->{allow}->{ uc( $req->method() ) } | ||||
260 | ) | ||||
261 | || ( defined $dispatcher->{deny} | ||||
262 | && $dispatcher->{deny}->{ uc( $req->method() ) } ) | ||||
263 | ) | ||||
264 | ) | ||||
265 | { | ||||
266 | $res = new Foswiki::Response(); | ||||
267 | $res->header( -type => 'text/html', -status => '405' ); | ||||
268 | $res->print( 'Bad Request: ' | ||||
269 | . uc( $req->method() ) | ||||
270 | . ' denied for ' | ||||
271 | . $req->action() ); | ||||
272 | return $res; | ||||
273 | } | ||||
274 | 1 | 6µs | 1 | 61.4s | $res = _execute( $req, \&$sub, %{ $dispatcher->{context} } ); # spent 61.4s making 1 call to Foswiki::UI::_execute |
275 | 1 | 8µs | return $res; | ||
276 | } | ||||
277 | |||||
278 | =begin TML | ||||
279 | |||||
280 | ---++ StaticMethod _execute($req, $sub, %initialContext) -> $res | ||||
281 | |||||
282 | Creates a Foswiki session object with %initalContext and calls | ||||
283 | $sub method. Returns the Foswiki::Response object. | ||||
284 | |||||
285 | =cut | ||||
286 | |||||
287 | # spent 61.4s (178µs+61.4) within Foswiki::UI::_execute which was called:
# once (178µs+61.4s) by Foswiki::UI::handleRequest at line 274 | ||||
288 | 1 | 2µs | my ( $req, $sub, %initialContext ) = @_; | ||
289 | |||||
290 | 1 | 100ns | my $session; | ||
291 | 1 | 100ns | my $res; | ||
292 | |||||
293 | # If we get a known exception from new Foswiki(), then it must have | ||||
294 | # come from one of the plugin handlers, which are initialised at this | ||||
295 | # time (initPlugin, earlyInitPlugin for example). In this case the | ||||
296 | # setup of the Foswiki object is pretty much complete; we can safely | ||||
297 | # recover it from $Foswiki::Plugins::SESSION and clean it up. | ||||
298 | # Error::Simple and EngineException indicate something more | ||||
299 | # basic, however, that we can't clean up. | ||||
300 | # spent 61.3s (45µs+61.3) within Foswiki::UI::__ANON__[/var/www/foswiki11/lib/Foswiki/UI.pm:318] which was called:
# once (45µs+61.3s) by Error::subs::try at line 419 of Error.pm | ||||
301 | |||||
302 | # DO NOT pass in $req->remoteUser here (even though it appears to be right) | ||||
303 | # because it may occlude the login manager. Exception is when running in | ||||
304 | # CLI environment. | ||||
305 | |||||
306 | 1 | 7µs | 2 | 1.72s | $session = new Foswiki( # spent 1.72s making 1 call to Foswiki::new
# spent 2µs making 1 call to Foswiki::Request::remoteUser |
307 | ( defined $ENV{GATEWAY_INTERFACE} || defined $ENV{MOD_PERL} ) | ||||
308 | ? undef | ||||
309 | : $req->remoteUser(), | ||||
310 | $req, \%initialContext | ||||
311 | ); | ||||
312 | |||||
313 | 1 | 800ns | $res = $session->{response}; | ||
314 | 1 | 15µs | 1 | 7µs | unless ( defined $res->status() && $res->status() =~ /^\s*3\d\d/ ) { # spent 7µs making 1 call to Foswiki::Response::status |
315 | 1 | 11µs | 2 | 24µs | $session->getLoginManager()->checkAccess(); # spent 17µs making 1 call to Foswiki::LoginManager::checkAccess
# spent 6µs making 1 call to Foswiki::getLoginManager |
316 | 1 | 7µs | 1 | 59.6s | &$sub($session); # spent 59.6s making 1 call to Foswiki::UI::View::view |
317 | } | ||||
318 | } | ||||
319 | catch Foswiki::ValidationException with { | ||||
320 | my $e = shift; | ||||
321 | |||||
322 | $session ||= $Foswiki::Plugins::SESSION; | ||||
323 | $res = $session->{response} if $session; | ||||
324 | $res ||= new Foswiki::Response(); | ||||
325 | |||||
326 | my $query = $session->{request}; | ||||
327 | |||||
328 | # Cache the original query, so we can complete if if it is | ||||
329 | # confirmed | ||||
330 | require Foswiki::Request::Cache; | ||||
331 | my $uid = Foswiki::Request::Cache->new()->save($query); | ||||
332 | |||||
333 | print STDERR "ValidationException: redirect with $uid\n" | ||||
334 | if DEBUG; | ||||
335 | |||||
336 | # We use the login script for validation because it already | ||||
337 | # has the correct criteria in httpd.conf for Apache login. | ||||
338 | # URL is absolute as required by | ||||
339 | # http://tools.ietf.org/html/rfc2616#section-14.30 | ||||
340 | my $url = $session->getScriptUrl( | ||||
341 | 1, 'login', | ||||
342 | $session->{webName}, $session->{topicName}, | ||||
343 | foswikiloginaction => 'validate', | ||||
344 | foswikioriginalquery => $uid | ||||
345 | ); | ||||
346 | |||||
347 | $session->redirect($url); # no passthrough | ||||
348 | } | ||||
349 | catch Foswiki::AccessControlException with { | ||||
350 | my $e = shift; | ||||
351 | |||||
352 | $session ||= $Foswiki::Plugins::SESSION; | ||||
353 | $res = $session->{response} if $session; | ||||
354 | $res ||= new Foswiki::Response(); | ||||
355 | |||||
356 | unless ( $session->getLoginManager()->forceAuthentication() ) { | ||||
357 | |||||
358 | # Login manager did not want to authenticate, perhaps because | ||||
359 | # we are already authenticated. | ||||
360 | my $exception = new Foswiki::OopsException( | ||||
361 | 'accessdenied', | ||||
362 | status => 403, | ||||
363 | web => $e->{web}, | ||||
364 | topic => $e->{topic}, | ||||
365 | def => 'topic_access', | ||||
366 | params => [ $e->{mode}, $e->{reason} ] | ||||
367 | ); | ||||
368 | |||||
369 | $exception->generate($session); | ||||
370 | } | ||||
371 | } | ||||
372 | catch Foswiki::OopsException with { | ||||
373 | my $e = shift; | ||||
374 | |||||
375 | $session ||= $Foswiki::Plugins::SESSION; | ||||
376 | $res = $session->{response} if $session; | ||||
377 | $res ||= new Foswiki::Response(); | ||||
378 | |||||
379 | $e->generate($session); | ||||
380 | } | ||||
381 | catch Foswiki::EngineException with { | ||||
382 | my $e = shift; | ||||
383 | my $res = $e->{response}; | ||||
384 | unless ( defined $res ) { | ||||
385 | $res = new Foswiki::Response(); | ||||
386 | $res->header( -type => 'text/html', -status => $e->{status} ); | ||||
387 | my $html = CGI::start_html( $e->{status} . ' Bad Request' ); | ||||
388 | $html .= CGI::h1( {}, 'Bad Request' ); | ||||
389 | $html .= CGI::p( {}, $e->{reason} ); | ||||
390 | $html .= CGI::end_html(); | ||||
391 | $res->print($html); | ||||
392 | } | ||||
393 | $Foswiki::engine->finalizeError( $res, $session->{request} ); | ||||
394 | return $e->{status}; | ||||
395 | } | ||||
396 | catch Error::Simple with { | ||||
397 | |||||
398 | # Most usually a 'die' | ||||
399 | my $e = shift; | ||||
400 | |||||
401 | $session ||= $Foswiki::Plugins::SESSION; | ||||
402 | $res = $session->{response} if $session; | ||||
403 | $res ||= new Foswiki::Response(); | ||||
404 | |||||
405 | $res->header( -type => 'text/plain' ) | ||||
406 | unless $res->outputHasStarted(); | ||||
407 | if (DEBUG) { | ||||
408 | |||||
409 | # output the full message and stacktrace to the browser | ||||
410 | $res->print( $e->stringify() ); | ||||
411 | } | ||||
412 | else { | ||||
413 | my $mess = $e->stringify(); | ||||
414 | print STDERR $mess; | ||||
415 | $session->logger->log( 'warning', $mess ) if $session; | ||||
416 | |||||
417 | # tell the browser where to look for more help | ||||
418 | my $text = | ||||
419 | 'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.' | ||||
420 | . "\n\n"; | ||||
421 | $mess =~ s/ at .*$//s; | ||||
422 | |||||
423 | # cut out pathnames from public announcement | ||||
424 | $mess =~ s#/[\w./]+#path#g unless DEBUG; | ||||
425 | $text .= $mess; | ||||
426 | $res->print($text); | ||||
427 | } | ||||
428 | } | ||||
429 | otherwise { | ||||
430 | |||||
431 | # Aargh! Should never get here | ||||
432 | $res = new Foswiki::Response; | ||||
433 | $res->header( -type => 'text/plain' ); | ||||
434 | $res->print("Unspecified error"); | ||||
435 | 1 | 99µs | 12 | 61.3s | }; # spent 61.3s making 1 call to Error::subs::try
# spent 12µs making 5 calls to Error::catch, avg 2µs/call
# spent 4µs making 5 calls to Error::subs::with, avg 860ns/call
# spent 3µs making 1 call to Error::subs::otherwise |
436 | 1 | 5µs | 1 | 12.5ms | $session->finish() if $session; # spent 12.5ms making 1 call to Foswiki::finish |
437 | |||||
438 | 1 | 57µs | return $res; | ||
439 | } | ||||
440 | |||||
441 | =begin TML | ||||
442 | |||||
443 | ---++ StaticMethod logon($session) | ||||
444 | |||||
445 | Handler for "logon" action. | ||||
446 | * =$session= is a Foswiki session object | ||||
447 | |||||
448 | =cut | ||||
449 | |||||
450 | sub logon { | ||||
451 | my $session = shift; | ||||
452 | |||||
453 | my $action = $session->{request}->param('foswikiloginaction'); | ||||
454 | $session->{request}->delete('foswikiloginaction'); | ||||
455 | |||||
456 | if ( defined $action && $action eq 'validate' ) { | ||||
457 | Foswiki::Validation::validate($session); | ||||
458 | } | ||||
459 | else { | ||||
460 | $session->getLoginManager()->login( $session->{request}, $session ); | ||||
461 | } | ||||
462 | } | ||||
463 | |||||
464 | =begin TML | ||||
465 | |||||
466 | ---++ StaticMethod checkWebExists( $session, $web, $op ) | ||||
467 | |||||
468 | Check if the web exists. If it doesn't, will throw an oops exception. | ||||
469 | $op is the user operation being performed. | ||||
470 | |||||
471 | =cut | ||||
472 | |||||
473 | # spent 90µs (15+74) within Foswiki::UI::checkWebExists which was called:
# once (15µs+74µs) by Foswiki::UI::View::view at line 99 of /var/www/foswiki11/lib/Foswiki/UI/View.pm | ||||
474 | 1 | 1µs | my ( $session, $webName, $op ) = @_; | ||
475 | 1 | 2µs | 1 | 2µs | ASSERT( $session->isa('Foswiki') ) if DEBUG; # spent 2µs making 1 call to Assert::ASSERTS_OFF |
476 | |||||
477 | 1 | 500ns | unless ($webName) { | ||
478 | throw Foswiki::OopsException( | ||||
479 | 'accessdenied', | ||||
480 | status => 404, | ||||
481 | def => 'bad_web_name', | ||||
482 | web => $webName, | ||||
483 | topic => $Foswiki::cfg{WebPrefsTopicName}, | ||||
484 | params => [$op] | ||||
485 | ); | ||||
486 | } | ||||
487 | |||||
488 | 1 | 7µs | 1 | 73µs | unless ( $session->webExists($webName) ) { # spent 73µs making 1 call to Foswiki::webExists |
489 | throw Foswiki::OopsException( | ||||
490 | 'accessdenied', | ||||
491 | status => 404, | ||||
492 | def => 'no_such_web', | ||||
493 | web => $webName, | ||||
494 | topic => $Foswiki::cfg{WebPrefsTopicName}, | ||||
495 | params => [$op] | ||||
496 | ); | ||||
497 | } | ||||
498 | } | ||||
499 | |||||
500 | =begin TML | ||||
501 | |||||
502 | ---++ StaticMethod topicExists( $session, $web, $topic, $op ) => boolean | ||||
503 | |||||
504 | Check if the given topic exists, throwing an OopsException | ||||
505 | if it doesn't. $op is the user operation being performed. | ||||
506 | |||||
507 | =cut | ||||
508 | |||||
509 | sub checkTopicExists { | ||||
510 | my ( $session, $web, $topic, $op ) = @_; | ||||
511 | ASSERT( $session->isa('Foswiki') ) if DEBUG; | ||||
512 | |||||
513 | unless ( $session->topicExists( $web, $topic ) ) { | ||||
514 | throw Foswiki::OopsException( | ||||
515 | 'accessdenied', | ||||
516 | status => 404, | ||||
517 | def => 'no_such_topic', | ||||
518 | web => $web, | ||||
519 | topic => $topic, | ||||
520 | params => [$op] | ||||
521 | ); | ||||
522 | } | ||||
523 | } | ||||
524 | |||||
525 | =begin TML | ||||
526 | |||||
527 | ---++ StaticMethod checkAccess( $session, $mode, $topicObject ) | ||||
528 | |||||
529 | Check if the given mode of access by the given user to the given | ||||
530 | web.topic is permissible, throwing a Foswiki::OopsException if not. | ||||
531 | |||||
532 | =cut | ||||
533 | |||||
534 | # spent 946µs (13+933) within Foswiki::UI::checkAccess which was called:
# once (13µs+933µs) by Foswiki::UI::View::view at line 126 of /var/www/foswiki11/lib/Foswiki/UI/View.pm | ||||
535 | 1 | 1µs | my ( $session, $mode, $topicObject ) = @_; | ||
536 | 1 | 1µs | 1 | 700ns | ASSERT( $session->isa('Foswiki') ) if DEBUG; # spent 700ns making 1 call to Assert::ASSERTS_OFF |
537 | |||||
538 | 1 | 7µs | 1 | 932µs | unless ( $topicObject->haveAccess($mode) ) { # spent 932µs making 1 call to Foswiki::Meta::haveAccess |
539 | throw Foswiki::AccessControlException( $mode, $session->{user}, | ||||
540 | $topicObject->web, $topicObject->topic, $Foswiki::Meta::reason ); | ||||
541 | } | ||||
542 | } | ||||
543 | |||||
544 | =begin TML | ||||
545 | |||||
546 | ---++ StaticMethod checkValidationKey( $session ) | ||||
547 | |||||
548 | Check the validation key for the given action. Throws an exception | ||||
549 | if the validation key isn't valid (handled in _execute(), above) | ||||
550 | * =$session= - the current session object | ||||
551 | |||||
552 | See Foswiki::Validation for more information. | ||||
553 | |||||
554 | =cut | ||||
555 | |||||
556 | sub checkValidationKey { | ||||
557 | my ($session) = @_; | ||||
558 | |||||
559 | # If validation is disabled, do nothing | ||||
560 | return if ( $Foswiki::cfg{Validation}{Method} eq 'none' ); | ||||
561 | |||||
562 | # No point in command-line mode | ||||
563 | return if $session->inContext('command_line'); | ||||
564 | |||||
565 | # Check the nonce before we do anything else | ||||
566 | my $nonce = $session->{request}->param('validation_key'); | ||||
567 | $session->{request}->delete('validation_key'); | ||||
568 | if ( !defined($nonce) | ||||
569 | || !Foswiki::Validation::isValidNonce( $session->getCGISession(), | ||||
570 | $nonce ) ) | ||||
571 | { | ||||
572 | throw Foswiki::ValidationException( $session->{request}->action() ); | ||||
573 | } | ||||
574 | if ( defined($nonce) ) { | ||||
575 | |||||
576 | # Expire the nonce. If the user tries to use it again, they will | ||||
577 | # be prompted. | ||||
578 | Foswiki::Validation::expireValidationKeys( $session->getCGISession(), | ||||
579 | $Foswiki::cfg{Validation}{ExpireKeyOnUse} ? $nonce : undef ); | ||||
580 | } | ||||
581 | } | ||||
582 | |||||
583 | =begin TML | ||||
584 | |||||
585 | ---++ StaticMethod run( $method, %context ) | ||||
586 | |||||
587 | Supported for bin scripts that were written for Foswiki < 1.0. The parameters | ||||
588 | are a function reference to the UI method to call and initial context. | ||||
589 | |||||
590 | In Foswiki >= 1.0 it should be replaced by a Config.spec entry such as: | ||||
591 | |||||
592 | # **PERL H** | ||||
593 | # Bin script registration - do not modify | ||||
594 | $Foswiki::cfg{SwitchBoard}{publish} = [ "Foswiki::Contrib::Publish", "publish", { publishing => 1 } ]; | ||||
595 | |||||
596 | =cut | ||||
597 | |||||
598 | sub run { | ||||
599 | my ( $method, %context ) = @_; | ||||
600 | |||||
601 | if ( UNIVERSAL::isa( $Foswiki::engine, 'Foswiki::Engine::CLI' ) ) { | ||||
602 | $context{command_line} = 1; | ||||
603 | } | ||||
604 | _execute( Foswiki::Request->new(), $method, %context ); | ||||
605 | } | ||||
606 | |||||
607 | 1 | 3µs | 1; | ||
608 | __END__ |