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