1 |
wakaba |
1.1 |
|
2 |
|
|
=head1 NAME |
3 |
|
|
|
4 |
|
|
SuikaWiki::Output::CGICarp --- SuikaWiki : CGI::Carp modification to |
5 |
|
|
return 500 status code |
6 |
|
|
|
7 |
|
|
=head1 DESCRIPTION |
8 |
|
|
|
9 |
|
|
At the time of writing, latest version of CGI::Carp (1.27) |
10 |
|
|
does not output error dying message with 500 (Internal Server Error) |
11 |
|
|
HTTP status code unless it is working on mod_perl. |
12 |
|
|
|
13 |
|
|
This module overrides some of CGI::Carp functions to return 500 status |
14 |
|
|
code. Users of this module should take attention whether later revision |
15 |
|
|
of CGI::Carp provides improved version of CGI outputing methods. |
16 |
|
|
|
17 |
|
|
This module is part of SuikaWiki. |
18 |
|
|
|
19 |
|
|
=cut |
20 |
|
|
|
21 |
|
|
package SuikaWiki::Output::CGICarp; |
22 |
|
|
require CGI::Carp; # 1.27 |
23 |
|
|
use strict; |
24 |
|
|
our $VERSION = do{my @r=(q$Revision: 1.4 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; |
25 |
|
|
our $CUSTOM_REASON_TEXT = 'Internal CGI Script Error'; |
26 |
|
|
our $CUSTOM_STATUS_CODE = 500; |
27 |
|
|
|
28 |
|
|
=head1 OPTIONS |
29 |
|
|
|
30 |
|
|
=over 4 |
31 |
|
|
|
32 |
|
|
=item $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT (Default : Internal CGI Script Error) |
33 |
|
|
|
34 |
|
|
Short description of error status. This string should contains only |
35 |
|
|
printable ASCII characters (including SPACE) for interoperability |
36 |
|
|
and line break characters (CR and LF) MUST NOT be used. |
37 |
|
|
|
38 |
|
|
=item $SuikaWiki::Output::CGICarp::CUSTOM_STATUS_CODE (Default : 500) |
39 |
|
|
|
40 |
|
|
Three digit status code defined by HTTP specifications. |
41 |
|
|
|
42 |
|
|
=back |
43 |
|
|
|
44 |
|
|
=cut |
45 |
|
|
|
46 |
|
|
package CGI::Carp; |
47 |
|
|
our $CUSTOM_MSG; |
48 |
|
|
sub fatalsToBrowser { |
49 |
|
|
my($msg) = @_; |
50 |
|
|
$msg=~s/&/&/g; |
51 |
|
|
$msg=~s/>/>/g; |
52 |
|
|
$msg=~s/</</g; |
53 |
|
|
$msg=~s/\"/"/g; |
54 |
|
|
my($wm) = $main::ENV{SERVER_ADMIN} ? |
55 |
|
|
qq[the webmaster <<a href="mailto:$main::ENV{SERVER_ADMIN}">$main::ENV{SERVER_ADMIN}</a>>] : |
56 |
|
|
"this site's webmaster"; |
57 |
|
|
my ($outer_message) = <<END; |
58 |
|
|
For help, please send mail to $wm, giving this error message |
59 |
|
|
and the time and date of the error. |
60 |
|
|
END |
61 |
|
|
; |
62 |
|
|
my $mod_perl = exists $main::ENV{MOD_PERL}; |
63 |
|
|
|
64 |
|
|
warningsToBrowser(1); # emit warnings before dying |
65 |
|
|
|
66 |
|
|
if ($CUSTOM_MSG) { |
67 |
|
|
if (ref($CUSTOM_MSG) eq 'CODE') { |
68 |
|
|
my $bytes_written = eval{tell STDOUT}; |
69 |
|
|
unless (defined $bytes_written && $bytes_written > 0) { |
70 |
|
|
print STDOUT "Status: @{[$SuikaWiki::Output::CGICarp::CUSTOM_STATUS_CODE+0]} $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT\n"; |
71 |
|
|
print STDOUT "Content-type: text/html; charset=iso-8859-1\n\n"; |
72 |
|
|
} |
73 |
|
|
&$CUSTOM_MSG($msg); # nicer to perl 5.003 users |
74 |
|
|
return; |
75 |
|
|
} else { |
76 |
|
|
$outer_message = $CUSTOM_MSG; |
77 |
|
|
} |
78 |
|
|
} |
79 |
|
|
|
80 |
|
|
my $mess = <<END; |
81 |
|
|
<h1>Software error:</h1> |
82 |
|
|
<pre>$msg</pre> |
83 |
|
|
<p> |
84 |
|
|
$outer_message |
85 |
|
|
</p> |
86 |
|
|
END |
87 |
|
|
; |
88 |
|
|
|
89 |
|
|
if ($mod_perl) { |
90 |
|
|
require mod_perl; |
91 |
|
|
if ($mod_perl::VERSION >= 1.99) { |
92 |
|
|
$mod_perl = 2; |
93 |
|
|
require Apache::RequestRec; |
94 |
|
|
require Apache::RequestIO; |
95 |
|
|
require Apache::RequestUtil; |
96 |
|
|
require APR::Pool; |
97 |
|
|
require ModPerl::Util; |
98 |
|
|
require Apache::Response; |
99 |
|
|
} |
100 |
|
|
my $r = Apache->request; |
101 |
|
|
# If bytes have already been sent, then |
102 |
|
|
# we print the message out directly. |
103 |
|
|
# Otherwise we make a custom error |
104 |
|
|
# handler to produce the doc for us. |
105 |
|
|
if ($r->bytes_sent) { |
106 |
|
|
$r->print($mess); |
107 |
|
|
$mod_perl == 2 ? ModPerl::Util::exit(0) : $r->exit; |
108 |
|
|
} else { |
109 |
|
|
# MSIE won't display a custom 500 response unless it is >512 bytes! |
110 |
|
|
if ($main::ENV{HTTP_USER_AGENT} =~ /MSIE/) { |
111 |
|
|
$mess = "<!-- " . (' ' x 513) . " -->\n$mess"; |
112 |
|
|
} |
113 |
|
|
$r->custom_response($SuikaWiki::Output::CGICarp::CUSTOM_STATUS_CODE+0,$mess); |
114 |
|
|
} |
115 |
|
|
} else { |
116 |
|
|
my $bytes_written = eval{tell STDOUT}; |
117 |
|
|
if (defined $bytes_written && $bytes_written > 0) { |
118 |
|
|
print STDOUT $mess; |
119 |
|
|
} else { |
120 |
|
|
print STDOUT "Status: @{[$SuikaWiki::Output::CGICarp::CUSTOM_STATUS_CODE+0]} $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT\n"; |
121 |
|
|
print STDOUT "Content-type: text/html; charset=iso-8859-1\n\n"; |
122 |
|
|
print STDOUT $mess; |
123 |
|
|
} |
124 |
|
|
} |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
=head1 EXAMPLE |
128 |
|
|
|
129 |
|
|
use CGI::Carp qw/fatalsToBrowser/; |
130 |
|
|
require SuikaWiki::Output::CGICarp; |
131 |
|
|
|
132 |
|
|
die 'Something wrong'; |
133 |
|
|
|
134 |
|
|
=head1 LICENSE |
135 |
|
|
|
136 |
|
|
Copyright 2003-2004 Wakaba <w@suika.fam.cx> |
137 |
|
|
|
138 |
|
|
This program is free software; you can redistribute it and/or |
139 |
|
|
modify it under the same terms as Perl itself. |
140 |
|
|
|
141 |
|
|
=cut |
142 |
|
|
|
143 |
|
|
1; # $Date: 2004/01/17 09:18:38 $ |