blib/lib/AxKit2/Client.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 13 | 15 | 86.6 |
branch | n/a | ||
condition | n/a | ||
subroutine | 5 | 5 | 100.0 |
pod | n/a | ||
total | 18 | 20 | 90.0 |
line | stmt | bran | cond | sub | pod | time | code | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | # Copyright 2001-2006 The Apache Software Foundation | |||||||||||||
2 | # | |||||||||||||
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |||||||||||||
4 | # you may not use this file except in compliance with the License. | |||||||||||||
5 | # You may obtain a copy of the License at | |||||||||||||
6 | # | |||||||||||||
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |||||||||||||
8 | # | |||||||||||||
9 | # Unless required by applicable law or agreed to in writing, software | |||||||||||||
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |||||||||||||
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||||||||||
12 | # See the License for the specific language governing permissions and | |||||||||||||
13 | # limitations under the License. | |||||||||||||
14 | # | |||||||||||||
15 | ||||||||||||||
16 | package AxKit2::Client; | |||||||||||||
17 | ||||||||||||||
18 | 9 | 9 | 54 | use strict; | ||||||||||
9 | 29 | |||||||||||||
9 | 339 | |||||||||||||
19 | 9 | 9 | 50 | use warnings; | ||||||||||
9 | 15 | |||||||||||||
9 | 278 | |||||||||||||
20 | ||||||||||||||
21 | 9 | 9 | 4996 | use AxKit2::Plugin; | ||||||||||
9 | 30 | |||||||||||||
9 | 269 | |||||||||||||
22 | 9 | 9 | 65 | use AxKit2::Constants; | ||||||||||
9 | 18 | |||||||||||||
9 | 1157 | |||||||||||||
23 | 9 | 9 | 6377 | use AxKit2::Processor; | ||||||||||
0 | ||||||||||||||
0 | ||||||||||||||
24 | use AxKit2::Utils qw(xml_escape); | |||||||||||||
25 | use Carp qw(croak); | |||||||||||||
26 | ||||||||||||||
27 | our %PLUGINS; | |||||||||||||
28 | ||||||||||||||
29 | sub load_plugin { | |||||||||||||
30 | my ($class, $conf, $plugin) = @_; | |||||||||||||
31 | ||||||||||||||
32 | my $package; | |||||||||||||
33 | ||||||||||||||
34 | if ($plugin =~ m/::/) { | |||||||||||||
35 | # "full" package plugin (My::Plugin) | |||||||||||||
36 | $package = $plugin; | |||||||||||||
37 | $package =~ s/[^_a-z0-9:]+//gi; | |||||||||||||
38 | my $eval = qq[require $package;\n] | |||||||||||||
39 | .qq[sub ${plugin}::plugin_name { '$plugin' }] | |||||||||||||
40 | .qq[sub ${plugin}::hook_name { shift->{_hook}; }]; | |||||||||||||
41 | $eval =~ m/(.*)/s; | |||||||||||||
42 | $eval = $1; | |||||||||||||
43 | eval $eval; | |||||||||||||
44 | die "Failed loading $package - eval $@" if $@; | |||||||||||||
45 | $class->log(LOGDEBUG, "Loaded Plugin $package"); | |||||||||||||
46 | } | |||||||||||||
47 | else { | |||||||||||||
48 | ||||||||||||||
49 | my $dir = $conf->plugin_dir || "./plugins"; | |||||||||||||
50 | ||||||||||||||
51 | my $plugin_name = plugin_to_name($plugin); | |||||||||||||
52 | $package = "AxKit2::Plugin::$plugin_name"; | |||||||||||||
53 | ||||||||||||||
54 | # don't reload plugins if they are already loaded | |||||||||||||
55 | unless ( defined &{"${package}::plugin_name"} ) { | |||||||||||||
56 | AxKit2::Plugin->_compile($plugin_name, | |||||||||||||
57 | $package, "$dir/$plugin"); | |||||||||||||
58 | } | |||||||||||||
59 | } | |||||||||||||
60 | ||||||||||||||
61 | return if $PLUGINS{$plugin}; | |||||||||||||
62 | ||||||||||||||
63 | my $plug = $package->new(); | |||||||||||||
64 | $PLUGINS{$plugin} = $plug; | |||||||||||||
65 | $plug->_register(); | |||||||||||||
66 | } | |||||||||||||
67 | ||||||||||||||
68 | sub plugin_to_name { | |||||||||||||
69 | my $plugin = shift; | |||||||||||||
70 | ||||||||||||||
71 | my $plugin_name = $plugin; | |||||||||||||
72 | ||||||||||||||
73 | # Escape everything into valid perl identifiers | |||||||||||||
74 | $plugin_name =~ s/([^A-Za-z0-9_\/])/sprintf("_%2x",unpack("C",$1))/eg; | |||||||||||||
75 | ||||||||||||||
76 | # second pass cares for slashes and words starting with a digit | |||||||||||||
77 | $plugin_name =~ s{ | |||||||||||||
78 | (/+) # directory | |||||||||||||
79 | (\d?) # package's first character | |||||||||||||
80 | }[ | |||||||||||||
81 | "::" . (length $2 ? sprintf("_%2x",unpack("C",$2)) : "") | |||||||||||||
82 | ]egx; | |||||||||||||
83 | ||||||||||||||
84 | ||||||||||||||
85 | return $plugin_name; | |||||||||||||
86 | } | |||||||||||||
87 | ||||||||||||||
88 | sub plugin_instance { | |||||||||||||
89 | my $plugin = shift; | |||||||||||||
90 | return $PLUGINS{$plugin}; | |||||||||||||
91 | } | |||||||||||||
92 | ||||||||||||||
93 | sub config { | |||||||||||||
94 | # should be subclassed - clients get a server config | |||||||||||||
95 | AxKit2::Config->global; | |||||||||||||
96 | } | |||||||||||||
97 | ||||||||||||||
98 | sub run_hooks { | |||||||||||||
99 | my ($self, $hook) = (shift, shift); | |||||||||||||
100 | ||||||||||||||
101 | my $conf = $self->config(); | |||||||||||||
102 | ||||||||||||||
103 | if (my $cached_hooks = $conf->cached_hooks($hook)) { | |||||||||||||
104 | return $self->_run_hooks($conf, $hook, [@_], $cached_hooks, 0); | |||||||||||||
105 | } | |||||||||||||
106 | ||||||||||||||
107 | my @hooks; | |||||||||||||
108 | for my $plugin ($conf->plugins) { | |||||||||||||
109 | my $plug = $PLUGINS{$plugin} || next; | |||||||||||||
110 | push @hooks, map { [$plugin, $plug, $_] } $plug->hooks($hook); | |||||||||||||
111 | } | |||||||||||||
112 | ||||||||||||||
113 | $conf->cached_hooks($hook, \@hooks); | |||||||||||||
114 | $self->_run_hooks($conf, $hook, [@_], \@hooks, 0); | |||||||||||||
115 | } | |||||||||||||
116 | ||||||||||||||
117 | sub finish_continuation { | |||||||||||||
118 | my ($self) = @_; | |||||||||||||
119 | my $todo = $self->{continuation} || croak "No continuation in progress"; | |||||||||||||
120 | $self->continue_read(); | |||||||||||||
121 | $self->{continuation} = undef; | |||||||||||||
122 | my $hook = shift @$todo; | |||||||||||||
123 | my $args = shift @$todo; | |||||||||||||
124 | my $pos = shift @$todo; | |||||||||||||
125 | my $conf = $self->config; | |||||||||||||
126 | my $hooks = $conf->cached_hooks($hook); | |||||||||||||
127 | $self->_run_hooks($conf, $hook, $args, $hooks, $pos+1); | |||||||||||||
128 | } | |||||||||||||
129 | ||||||||||||||
130 | sub _run_hooks { | |||||||||||||
131 | my $self = shift; | |||||||||||||
132 | my ($conf, $hook, $args, $hooks, $pos) = @_; | |||||||||||||
133 | ||||||||||||||
134 | my $last_hook = $#$hooks; | |||||||||||||
135 | ||||||||||||||
136 | my @r; | |||||||||||||
137 | if ($pos <= $last_hook) { | |||||||||||||
138 | for my $idx ($pos .. $last_hook) { | |||||||||||||
139 | my $info = $hooks->[$idx]; | |||||||||||||
140 | my ($plugin, $plug, $h) = @$info; | |||||||||||||
141 | # $self->log(LOGDEBUG, "$plugin ($idx) running hook $hook") unless $hook eq 'logging'; | |||||||||||||
142 | eval { @r = $plug->$h($self, $conf, @$args) }; | |||||||||||||
143 | if ($@) { | |||||||||||||
144 | my $err = $@; | |||||||||||||
145 | $self->log(LOGERROR, "FATAL PLUGIN ERROR: $err"); | |||||||||||||
146 | $self->hook_error($err) unless $hook eq 'error'; | |||||||||||||
147 | return DONE; | |||||||||||||
148 | } | |||||||||||||
149 | next unless @r; | |||||||||||||
150 | if (!defined $r[0]) { | |||||||||||||
151 | print "r0 not defined in hook $hook\[$idx]\n"; | |||||||||||||
152 | } | |||||||||||||
153 | if ($r[0] == CONTINUATION) { | |||||||||||||
154 | $self->pause_read(); | |||||||||||||
155 | $self->{continuation} = [$hook, $args, $idx]; | |||||||||||||
156 | } | |||||||||||||
157 | last unless $r[0] == DECLINED; | |||||||||||||
158 | } | |||||||||||||
159 | } | |||||||||||||
160 | ||||||||||||||
161 | $r[0] = DECLINED if not defined $r[0]; | |||||||||||||
162 | if ($r[0] != CONTINUATION) { | |||||||||||||
163 | my $responder = "hook_${hook}_end"; | |||||||||||||
164 | if (my $meth = $self->can($responder)) { | |||||||||||||
165 | return $meth->($self, $r[0], $r[1], @$args); | |||||||||||||
166 | } | |||||||||||||
167 | } | |||||||||||||
168 | return @r; | |||||||||||||
169 | } | |||||||||||||
170 | ||||||||||||||
171 | sub log { | |||||||||||||
172 | my $self = shift; | |||||||||||||
173 | $self->run_hooks('logging', @_); | |||||||||||||
174 | } | |||||||||||||
175 | ||||||||||||||
176 | sub hook_connect { | |||||||||||||
177 | my $self = shift; | |||||||||||||
178 | $self->run_hooks('connect'); | |||||||||||||
179 | } | |||||||||||||
180 | ||||||||||||||
181 | sub hook_connect_end { | |||||||||||||
182 | my $self = shift; | |||||||||||||
183 | my ($ret, $out) = @_; | |||||||||||||
184 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
185 | # success | |||||||||||||
186 | $self->run_hooks('pre_request'); | |||||||||||||
187 | } | |||||||||||||
188 | else { | |||||||||||||
189 | $self->close("connect hook closing"); | |||||||||||||
190 | return; | |||||||||||||
191 | } | |||||||||||||
192 | } | |||||||||||||
193 | ||||||||||||||
194 | sub hook_pre_request { | |||||||||||||
195 | my $self = shift; | |||||||||||||
196 | $self->run_hooks('pre_request'); | |||||||||||||
197 | } | |||||||||||||
198 | ||||||||||||||
199 | sub hook_pre_request_end { | |||||||||||||
200 | my $self = shift; | |||||||||||||
201 | my ($ret, $out) = @_; | |||||||||||||
202 | # TODO: Manage $ret | |||||||||||||
203 | return; | |||||||||||||
204 | } | |||||||||||||
205 | ||||||||||||||
206 | sub hook_body_data { | |||||||||||||
207 | my $self = shift; | |||||||||||||
208 | $self->run_hooks('body_data', @_); | |||||||||||||
209 | } | |||||||||||||
210 | ||||||||||||||
211 | sub hook_body_data_end { | |||||||||||||
212 | my ($self, $ret) = @_; | |||||||||||||
213 | if ($ret == DECLINED || $ret == DONE) { | |||||||||||||
214 | return $self->process_request(); | |||||||||||||
215 | } | |||||||||||||
216 | elsif ($ret == OK) { | |||||||||||||
217 | return 1; | |||||||||||||
218 | } | |||||||||||||
219 | else { | |||||||||||||
220 | $self->default_error_out($ret); | |||||||||||||
221 | } | |||||||||||||
222 | } | |||||||||||||
223 | ||||||||||||||
224 | sub hook_write_body_data { | |||||||||||||
225 | my $self = shift; | |||||||||||||
226 | my ($ret) = $self->run_hooks('write_body_data'); | |||||||||||||
227 | if ($ret == CONTINUATION) { | |||||||||||||
228 | die "Continuations not supported on write_body_data"; | |||||||||||||
229 | } | |||||||||||||
230 | elsif ($ret == DECLINED || $ret == DONE) { | |||||||||||||
231 | return; | |||||||||||||
232 | } | |||||||||||||
233 | elsif ($ret == OK) { | |||||||||||||
234 | return 1; | |||||||||||||
235 | } | |||||||||||||
236 | else { | |||||||||||||
237 | $self->default_error_out($ret); | |||||||||||||
238 | } | |||||||||||||
239 | } | |||||||||||||
240 | ||||||||||||||
241 | sub hook_post_read_request { | |||||||||||||
242 | my $self = shift; | |||||||||||||
243 | $self->run_hooks('post_read_request', @_); | |||||||||||||
244 | } | |||||||||||||
245 | ||||||||||||||
246 | sub hook_post_read_request_end { | |||||||||||||
247 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
248 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
249 | if ($hd->request_method =~ /GET|HEAD/) { | |||||||||||||
250 | return $self->process_request; | |||||||||||||
251 | } | |||||||||||||
252 | return; | |||||||||||||
253 | } | |||||||||||||
254 | elsif ($ret == DONE) { | |||||||||||||
255 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
256 | } | |||||||||||||
257 | else { | |||||||||||||
258 | $self->default_error_out($ret); | |||||||||||||
259 | } | |||||||||||||
260 | } | |||||||||||||
261 | ||||||||||||||
262 | sub hook_uri_translation { | |||||||||||||
263 | my ($self, $hd, $uri) = @_; | |||||||||||||
264 | $self->run_hooks('uri_translation', $hd, $uri); | |||||||||||||
265 | } | |||||||||||||
266 | ||||||||||||||
267 | sub hook_uri_translation_end { | |||||||||||||
268 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
269 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
270 | return $self->run_hooks('mime_map', $hd, $hd->filename); | |||||||||||||
271 | } | |||||||||||||
272 | elsif ($ret == DONE) { | |||||||||||||
273 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
274 | } | |||||||||||||
275 | else { | |||||||||||||
276 | $self->default_error_out($ret); | |||||||||||||
277 | } | |||||||||||||
278 | } | |||||||||||||
279 | ||||||||||||||
280 | sub hook_mime_map_end { | |||||||||||||
281 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
282 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
283 | return $self->run_hooks('access_control', $hd); | |||||||||||||
284 | } | |||||||||||||
285 | elsif ($ret == DONE) { | |||||||||||||
286 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
287 | } | |||||||||||||
288 | else { | |||||||||||||
289 | $self->default_error_out($ret); | |||||||||||||
290 | } | |||||||||||||
291 | } | |||||||||||||
292 | ||||||||||||||
293 | sub hook_access_control_end { | |||||||||||||
294 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
295 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
296 | return $self->run_hooks('authentication', $hd); | |||||||||||||
297 | } | |||||||||||||
298 | elsif ($ret == DONE) { | |||||||||||||
299 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
300 | } | |||||||||||||
301 | else { | |||||||||||||
302 | $self->default_error_out($ret); | |||||||||||||
303 | } | |||||||||||||
304 | } | |||||||||||||
305 | ||||||||||||||
306 | sub hook_authentication_end { | |||||||||||||
307 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
308 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
309 | return $self->run_hooks('authorization', $hd); | |||||||||||||
310 | } | |||||||||||||
311 | elsif ($ret == DONE) { | |||||||||||||
312 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
313 | } | |||||||||||||
314 | else { | |||||||||||||
315 | $self->default_error_out($ret); | |||||||||||||
316 | } | |||||||||||||
317 | } | |||||||||||||
318 | ||||||||||||||
319 | sub hook_authorization_end { | |||||||||||||
320 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
321 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
322 | return $self->run_hooks('fixup', $hd); | |||||||||||||
323 | } | |||||||||||||
324 | elsif ($ret == DONE) { | |||||||||||||
325 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
326 | } | |||||||||||||
327 | else { | |||||||||||||
328 | $self->default_error_out($ret); | |||||||||||||
329 | } | |||||||||||||
330 | } | |||||||||||||
331 | ||||||||||||||
332 | sub hook_fixup_end { | |||||||||||||
333 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
334 | if ($ret == DECLINED || $ret == OK) { | |||||||||||||
335 | return $self->run_hooks( | |||||||||||||
336 | 'xmlresponse', | |||||||||||||
337 | AxKit2::Processor->new($self, $hd->filename), | |||||||||||||
338 | $hd); | |||||||||||||
339 | } | |||||||||||||
340 | elsif ($ret == DONE) { | |||||||||||||
341 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
342 | } | |||||||||||||
343 | else { | |||||||||||||
344 | $self->default_error_out($ret); | |||||||||||||
345 | } | |||||||||||||
346 | } | |||||||||||||
347 | ||||||||||||||
348 | sub hook_xmlresponse_end { | |||||||||||||
349 | my ($self, $ret, $out, $input, $hd) = @_; | |||||||||||||
350 | if ($ret == DECLINED) { | |||||||||||||
351 | return $self->run_hooks('response', $hd); | |||||||||||||
352 | } | |||||||||||||
353 | elsif ($ret == DONE) { | |||||||||||||
354 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
355 | } | |||||||||||||
356 | elsif ($ret == OK) { | |||||||||||||
357 | $out->output() if $out; | |||||||||||||
358 | $self->write(sub { $self->http_response_sent($self->headers_out->response_code) }); | |||||||||||||
359 | } | |||||||||||||
360 | else { | |||||||||||||
361 | $self->default_error_out($ret); | |||||||||||||
362 | } | |||||||||||||
363 | } | |||||||||||||
364 | ||||||||||||||
365 | sub hook_response_end { | |||||||||||||
366 | my ($self, $ret, $out, $hd) = @_; | |||||||||||||
367 | if ($ret == DECLINED) { | |||||||||||||
368 | $self->default_error_out(NOT_FOUND); | |||||||||||||
369 | } | |||||||||||||
370 | elsif ($ret == OK || $ret == DONE) { | |||||||||||||
371 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
372 | } | |||||||||||||
373 | else { | |||||||||||||
374 | $self->default_error_out($ret); | |||||||||||||
375 | } | |||||||||||||
376 | ||||||||||||||
377 | } | |||||||||||||
378 | ||||||||||||||
379 | sub hook_response_sent { | |||||||||||||
380 | my $self = shift; | |||||||||||||
381 | $self->run_hooks('response_sent', @_); | |||||||||||||
382 | } | |||||||||||||
383 | ||||||||||||||
384 | sub hook_response_sent_end { | |||||||||||||
385 | my ($self, $ret, $out, $code) = @_; | |||||||||||||
386 | if ($ret == DONE) { | |||||||||||||
387 | $self->close("plugin decided not to keep connection open"); | |||||||||||||
388 | } | |||||||||||||
389 | elsif ($ret == DECLINED || $ret == OK) { | |||||||||||||
390 | return $self->http_response_sent; | |||||||||||||
391 | } | |||||||||||||
392 | else { | |||||||||||||
393 | $self->default_error_out($ret); | |||||||||||||
394 | } | |||||||||||||
395 | } | |||||||||||||
396 | ||||||||||||||
397 | sub hook_error { | |||||||||||||
398 | my $self = shift; | |||||||||||||
399 | $self->headers_out->code(SERVER_ERROR); | |||||||||||||
400 | $self->run_hooks('error', @_); | |||||||||||||
401 | } | |||||||||||||
402 | ||||||||||||||
403 | sub hook_error_end { | |||||||||||||
404 | my ($self, $ret) = @_; | |||||||||||||
405 | if ($ret == DECLINED) { | |||||||||||||
406 | $self->default_error_out(SERVER_ERROR); | |||||||||||||
407 | } | |||||||||||||
408 | elsif ($ret == OK || $ret == DONE) { | |||||||||||||
409 | # we assume some hook handled the error | |||||||||||||
410 | } | |||||||||||||
411 | else { | |||||||||||||
412 | $self->default_error_out($ret); | |||||||||||||
413 | } | |||||||||||||
414 | } | |||||||||||||
415 | ||||||||||||||
416 | # stolen shamelessly from httpd-2.2.2/modules/http/http_protocol.c | |||||||||||||
417 | sub default_error_out { | |||||||||||||
418 | my ($self, $code, $extras) = @_; | |||||||||||||
419 | $extras = '' unless defined $extras; | |||||||||||||
420 | ||||||||||||||
421 | $self->initialize_response; | |||||||||||||
422 | ||||||||||||||
423 | $self->headers_out->code($code); | |||||||||||||
424 | ||||||||||||||
425 | if ($code == NOT_MODIFIED) { | |||||||||||||
426 | $self->send_http_headers; | |||||||||||||
427 | $self->write(sub { $self->hook_response_sent($self->headers_out->response_code) }); | |||||||||||||
428 | # The 304 response MUST NOT contain a message-body | |||||||||||||
429 | return; | |||||||||||||
430 | } | |||||||||||||
431 | ||||||||||||||
432 | $self->headers_out->header('Content-Type', 'text/html'); | |||||||||||||
433 | $self->headers_out->header('Connection', 'close'); | |||||||||||||
434 | $self->send_http_headers; | |||||||||||||
435 | ||||||||||||||
436 | $self->write("\n" . | |||||||||||||
437 | "\n" . | |||||||||||||
438 | " |
|||||||||||||
439 | "\n" . | |||||||||||||
440 | "".$self->headers_out->http_code_english."\n" |
|||||||||||||
441 | ); | |||||||||||||
442 | ||||||||||||||
443 | if ($code == REDIRECT) { | |||||||||||||
444 | my $new_uri = $self->headers_out->header('Location') | |||||||||||||
445 | || die "No Location header set for REDIRECT"; | |||||||||||||
446 | $self->write('The document has moved 447 | xml_escape($new_uri) . "\">here. \n"); |
||||||||||||
448 | } | |||||||||||||
449 | elsif ($code == BAD_REQUEST) { | |||||||||||||
450 | $self->write(" Your browser sent a request that this server could not understand. |
|||||||||||||
451 | xml_escape($extras)."\n"); | |||||||||||||
452 | } | |||||||||||||
453 | elsif ($code == UNAUTHORIZED) { | |||||||||||||
454 | $self->write(" This server could not verify that you\n" . |
|||||||||||||
455 | "are authorized to access the document\n" . | |||||||||||||
456 | "requested. Either you supplied the wrong\n" . | |||||||||||||
457 | "credentials (e.g., bad password), or your\n" . | |||||||||||||
458 | "browser doesn't understand how to supply\n" . | |||||||||||||
459 | "the credentials required.\n"); | |||||||||||||
460 | } | |||||||||||||
461 | elsif ($code == FORBIDDEN) { | |||||||||||||
462 | $self->write(" You don't have permission to access " . |
|||||||||||||
463 | xml_escape($self->headers_in->uri) . | |||||||||||||
464 | "\non this server.\n"); | |||||||||||||
465 | } | |||||||||||||
466 | elsif ($code == NOT_FOUND) { | |||||||||||||
467 | $self->write(" The requested URL " . |
|||||||||||||
468 | xml_escape($self->headers_in->uri) . | |||||||||||||
469 | " was not found on this server.\n"); | |||||||||||||
470 | } | |||||||||||||
471 | elsif ($code == SERVICE_UNAVAILABLE) { | |||||||||||||
472 | $self->write(" The server is temporarily unable to service your\n" . |
|||||||||||||
473 | "request due to maintenance downtime or capacity\n" . | |||||||||||||
474 | "problems. Please try again later.\n"); | |||||||||||||
475 | } | |||||||||||||
476 | else { | |||||||||||||
477 | $self->write("The server encountered an internal error or \n" . | |||||||||||||
478 | "misconfiguration and was unable to complete \n" . | |||||||||||||
479 | "your request. \n" . |
|||||||||||||
480 | "More information about this error may be available\n" . | |||||||||||||
481 | "in the server error log. \n"); |
|||||||||||||
482 | } | |||||||||||||
483 | ||||||||||||||
484 | $self->write(< | |||||||||||||
485 | |
|||||||||||||
486 |