| Filename | /usr/local/lib/perl5/site_perl/CGI/Carp.pm |
| Statements | Executed 55 statements in 2.27ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.46ms | 7.94ms | CGI::Carp::BEGIN@321 |
| 3 | 3 | 3 | 54µs | 118µs | CGI::Carp::import |
| 1 | 1 | 1 | 14µs | 27µs | CGI::Carp::BEGIN@314 |
| 1 | 1 | 1 | 8µs | 8µs | CGI::Carp::BEGIN@316 |
| 1 | 1 | 1 | 1µs | 1µs | CGI::Carp::__ANON__ (xsub) |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::_longmess |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::_warn |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::carp |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::carpout |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::cluck |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::confess |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::croak |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::die |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::fatalsToBrowser |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::id |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::ineval |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::realdie |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::realwarn |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_die_handler |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_message |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_progname |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::stamp |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::to_filehandle |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::warn |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::warningsToBrowser |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package CGI::Carp; | ||||
| 2 | |||||
| 3 | 1 | 1µs | my $appease_cpants_kwalitee = q/ | ||
| 4 | use strict; | ||||
| 5 | use warnings; | ||||
| 6 | #/; | ||||
| 7 | |||||
| 8 | =head1 NAME | ||||
| 9 | |||||
| 10 | B<CGI::Carp> - CGI routines for writing to the HTTPD (or other) error log | ||||
| 11 | |||||
| 12 | =head1 SYNOPSIS | ||||
| 13 | |||||
| 14 | use CGI::Carp; | ||||
| 15 | |||||
| 16 | croak "We're outta here!"; | ||||
| 17 | confess "It was my fault: $!"; | ||||
| 18 | carp "It was your fault!"; | ||||
| 19 | warn "I'm confused"; | ||||
| 20 | die "I'm dying.\n"; | ||||
| 21 | |||||
| 22 | use CGI::Carp qw(cluck); | ||||
| 23 | cluck "I wouldn't do that if I were you"; | ||||
| 24 | |||||
| 25 | use CGI::Carp qw(fatalsToBrowser); | ||||
| 26 | die "Fatal error messages are now sent to browser"; | ||||
| 27 | |||||
| 28 | =head1 DESCRIPTION | ||||
| 29 | |||||
| 30 | CGI scripts have a nasty habit of leaving warning messages in the error | ||||
| 31 | logs that are neither time stamped nor fully identified. Tracking down | ||||
| 32 | the script that caused the error is a pain. This fixes that. Replace | ||||
| 33 | the usual | ||||
| 34 | |||||
| 35 | use Carp; | ||||
| 36 | |||||
| 37 | with | ||||
| 38 | |||||
| 39 | use CGI::Carp | ||||
| 40 | |||||
| 41 | The standard warn(), die (), croak(), confess() and carp() calls will | ||||
| 42 | be replaced with functions that write time-stamped messages to the | ||||
| 43 | HTTP server error log. | ||||
| 44 | |||||
| 45 | For example: | ||||
| 46 | |||||
| 47 | [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3. | ||||
| 48 | [Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied. | ||||
| 49 | [Fri Nov 17 21:40:43 1995] test.pl: I'm dying. | ||||
| 50 | |||||
| 51 | =head1 REDIRECTING ERROR MESSAGES | ||||
| 52 | |||||
| 53 | By default, error messages are sent to STDERR. Most HTTPD servers | ||||
| 54 | direct STDERR to the server's error log. Some applications may wish | ||||
| 55 | to keep private error logs, distinct from the server's error log, or | ||||
| 56 | they may wish to direct error messages to STDOUT so that the browser | ||||
| 57 | will receive them. | ||||
| 58 | |||||
| 59 | The C<carpout()> function is provided for this purpose. Since | ||||
| 60 | carpout() is not exported by default, you must import it explicitly by | ||||
| 61 | saying | ||||
| 62 | |||||
| 63 | use CGI::Carp qw(carpout); | ||||
| 64 | |||||
| 65 | The carpout() function requires one argument, a reference to an open | ||||
| 66 | filehandle for writing errors. It should be called in a C<BEGIN> | ||||
| 67 | block at the top of the CGI application so that compiler errors will | ||||
| 68 | be caught. Example: | ||||
| 69 | |||||
| 70 | BEGIN { | ||||
| 71 | use CGI::Carp qw(carpout); | ||||
| 72 | open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or | ||||
| 73 | die("Unable to open mycgi-log: $!\n"); | ||||
| 74 | carpout(LOG); | ||||
| 75 | } | ||||
| 76 | |||||
| 77 | carpout() does not handle file locking on the log for you at this | ||||
| 78 | point. Also, note that carpout() does not work with in-memory file | ||||
| 79 | handles, although a patch would be welcome to address that. | ||||
| 80 | |||||
| 81 | The real STDERR is not closed -- it is moved to CGI::Carp::SAVEERR. | ||||
| 82 | Some servers, when dealing with CGI scripts, close their connection to | ||||
| 83 | the browser when the script closes STDOUT and STDERR. | ||||
| 84 | CGI::Carp::SAVEERR is there to prevent this from happening | ||||
| 85 | prematurely. | ||||
| 86 | |||||
| 87 | You can pass filehandles to carpout() in a variety of ways. The "correct" | ||||
| 88 | way according to Tom Christiansen is to pass a reference to a filehandle | ||||
| 89 | GLOB: | ||||
| 90 | |||||
| 91 | carpout(\*LOG); | ||||
| 92 | |||||
| 93 | This looks weird to mere mortals however, so the following syntaxes are | ||||
| 94 | accepted as well: | ||||
| 95 | |||||
| 96 | carpout(LOG); | ||||
| 97 | carpout(main::LOG); | ||||
| 98 | carpout(main'LOG); | ||||
| 99 | carpout(\LOG); | ||||
| 100 | carpout(\'main::LOG'); | ||||
| 101 | |||||
| 102 | ... and so on | ||||
| 103 | |||||
| 104 | FileHandle and other objects work as well. | ||||
| 105 | |||||
| 106 | Use of carpout() is not great for performance, so it is recommended | ||||
| 107 | for debugging purposes or for moderate-use applications. A future | ||||
| 108 | version of this module may delay redirecting STDERR until one of the | ||||
| 109 | CGI::Carp methods is called to prevent the performance hit. | ||||
| 110 | |||||
| 111 | =head1 MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW | ||||
| 112 | |||||
| 113 | If you want to send fatal (die, confess) errors to the browser, import | ||||
| 114 | the special "fatalsToBrowser" subroutine: | ||||
| 115 | |||||
| 116 | use CGI::Carp qw(fatalsToBrowser); | ||||
| 117 | die "Bad error here"; | ||||
| 118 | |||||
| 119 | Fatal errors will now be echoed to the browser as well as to the log. | ||||
| 120 | CGI::Carp arranges to send a minimal HTTP header to the browser so | ||||
| 121 | that even errors that occur in the early compile phase will be seen. | ||||
| 122 | Nonfatal errors will still be directed to the log file only (unless | ||||
| 123 | redirected with carpout). | ||||
| 124 | |||||
| 125 | Note that fatalsToBrowser may B<not> work well with mod_perl version 2.0 | ||||
| 126 | and higher. | ||||
| 127 | |||||
| 128 | =head2 Changing the default message | ||||
| 129 | |||||
| 130 | By default, the software error message is followed by a note to | ||||
| 131 | contact the Webmaster by e-mail with the time and date of the error. | ||||
| 132 | If this message is not to your liking, you can change it using the | ||||
| 133 | set_message() routine. This is not imported by default; you should | ||||
| 134 | import it on the use() line: | ||||
| 135 | |||||
| 136 | use CGI::Carp qw(fatalsToBrowser set_message); | ||||
| 137 | set_message("It's not a bug, it's a feature!"); | ||||
| 138 | |||||
| 139 | You may also pass in a code reference in order to create a custom | ||||
| 140 | error message. At run time, your code will be called with the text | ||||
| 141 | of the error message that caused the script to die. Example: | ||||
| 142 | |||||
| 143 | use CGI::Carp qw(fatalsToBrowser set_message); | ||||
| 144 | BEGIN { | ||||
| 145 | sub handle_errors { | ||||
| 146 | my $msg = shift; | ||||
| 147 | print "<h1>Oh gosh</h1>"; | ||||
| 148 | print "<p>Got an error: $msg</p>"; | ||||
| 149 | } | ||||
| 150 | set_message(\&handle_errors); | ||||
| 151 | } | ||||
| 152 | |||||
| 153 | In order to correctly intercept compile-time errors, you should call | ||||
| 154 | set_message() from within a BEGIN{} block. | ||||
| 155 | |||||
| 156 | =head1 DOING MORE THAN PRINTING A MESSAGE IN THE EVENT OF PERL ERRORS | ||||
| 157 | |||||
| 158 | If fatalsToBrowser in conjunction with set_message does not provide | ||||
| 159 | you with all of the functionality you need, you can go one step | ||||
| 160 | further by specifying a function to be executed any time a script | ||||
| 161 | calls "die", has a syntax error, or dies unexpectedly at runtime | ||||
| 162 | with a line like "undef->explode();". | ||||
| 163 | |||||
| 164 | use CGI::Carp qw(set_die_handler); | ||||
| 165 | BEGIN { | ||||
| 166 | sub handle_errors { | ||||
| 167 | my $msg = shift; | ||||
| 168 | print "content-type: text/html\n\n"; | ||||
| 169 | print "<h1>Oh gosh</h1>"; | ||||
| 170 | print "<p>Got an error: $msg</p>"; | ||||
| 171 | |||||
| 172 | #proceed to send an email to a system administrator, | ||||
| 173 | #write a detailed message to the browser and/or a log, | ||||
| 174 | #etc.... | ||||
| 175 | } | ||||
| 176 | set_die_handler(\&handle_errors); | ||||
| 177 | } | ||||
| 178 | |||||
| 179 | Notice that if you use set_die_handler(), you must handle sending | ||||
| 180 | HTML headers to the browser yourself if you are printing a message. | ||||
| 181 | |||||
| 182 | If you use set_die_handler(), you will most likely interfere with | ||||
| 183 | the behavior of fatalsToBrowser, so you must use this or that, not | ||||
| 184 | both. | ||||
| 185 | |||||
| 186 | Using set_die_handler() sets SIG{__DIE__} (as does fatalsToBrowser), | ||||
| 187 | and there is only one SIG{__DIE__}. This means that if you are | ||||
| 188 | attempting to set SIG{__DIE__} yourself, you may interfere with | ||||
| 189 | this module's functionality, or this module may interfere with | ||||
| 190 | your module's functionality. | ||||
| 191 | |||||
| 192 | =head1 SUPPRESSING PERL ERRORS APPEARING IN THE BROWSER WINDOW | ||||
| 193 | |||||
| 194 | A problem sometimes encountered when using fatalsToBrowser is | ||||
| 195 | when a C<die()> is done inside an C<eval> body or expression. | ||||
| 196 | Even though the | ||||
| 197 | fatalsToBrower support takes precautions to avoid this, | ||||
| 198 | you still may get the error message printed to STDOUT. | ||||
| 199 | This may have some undesirable effects when the purpose of doing the | ||||
| 200 | eval is to determine which of several algorithms is to be used. | ||||
| 201 | |||||
| 202 | By setting C<$CGI::Carp::TO_BROWSER> to 0 you can suppress printing | ||||
| 203 | the C<die> messages but without all of the complexity of using | ||||
| 204 | C<set_die_handler>. You can localize this effect to inside C<eval> | ||||
| 205 | bodies if this is desirable: For example: | ||||
| 206 | |||||
| 207 | eval { | ||||
| 208 | local $CGI::Carp::TO_BROWSER = 0; | ||||
| 209 | die "Fatal error messages not sent browser" | ||||
| 210 | } | ||||
| 211 | # $@ will contain error message | ||||
| 212 | |||||
| 213 | |||||
| 214 | =head1 MAKING WARNINGS APPEAR AS HTML COMMENTS | ||||
| 215 | |||||
| 216 | It is also possible to make non-fatal errors appear as HTML comments | ||||
| 217 | embedded in the output of your program. To enable this feature, | ||||
| 218 | export the new "warningsToBrowser" subroutine. Since sending warnings | ||||
| 219 | to the browser before the HTTP headers have been sent would cause an | ||||
| 220 | error, any warnings are stored in an internal buffer until you call | ||||
| 221 | the warningsToBrowser() subroutine with a true argument: | ||||
| 222 | |||||
| 223 | use CGI::Carp qw(fatalsToBrowser warningsToBrowser); | ||||
| 224 | use CGI qw(:standard); | ||||
| 225 | print header(); | ||||
| 226 | warningsToBrowser(1); | ||||
| 227 | |||||
| 228 | You may also give a false argument to warningsToBrowser() to prevent | ||||
| 229 | warnings from being sent to the browser while you are printing some | ||||
| 230 | content where HTML comments are not allowed: | ||||
| 231 | |||||
| 232 | warningsToBrowser(0); # disable warnings | ||||
| 233 | print "<script type=\"text/javascript\"><!--\n"; | ||||
| 234 | print_some_javascript_code(); | ||||
| 235 | print "//--></script>\n"; | ||||
| 236 | warningsToBrowser(1); # re-enable warnings | ||||
| 237 | |||||
| 238 | Note: In this respect warningsToBrowser() differs fundamentally from | ||||
| 239 | fatalsToBrowser(), which you should never call yourself! | ||||
| 240 | |||||
| 241 | =head1 OVERRIDING THE NAME OF THE PROGRAM | ||||
| 242 | |||||
| 243 | CGI::Carp includes the name of the program that generated the error or | ||||
| 244 | warning in the messages written to the log and the browser window. | ||||
| 245 | Sometimes, Perl can get confused about what the actual name of the | ||||
| 246 | executed program was. In these cases, you can override the program | ||||
| 247 | name that CGI::Carp will use for all messages. | ||||
| 248 | |||||
| 249 | The quick way to do that is to tell CGI::Carp the name of the program | ||||
| 250 | in its use statement. You can do that by adding | ||||
| 251 | "name=cgi_carp_log_name" to your "use" statement. For example: | ||||
| 252 | |||||
| 253 | use CGI::Carp qw(name=cgi_carp_log_name); | ||||
| 254 | |||||
| 255 | . If you want to change the program name partway through the program, | ||||
| 256 | you can use the C<set_progname()> function instead. It is not | ||||
| 257 | exported by default, you must import it explicitly by saying | ||||
| 258 | |||||
| 259 | use CGI::Carp qw(set_progname); | ||||
| 260 | |||||
| 261 | Once you've done that, you can change the logged name of the program | ||||
| 262 | at any time by calling | ||||
| 263 | |||||
| 264 | set_progname(new_program_name); | ||||
| 265 | |||||
| 266 | You can set the program back to the default by calling | ||||
| 267 | |||||
| 268 | set_progname(undef); | ||||
| 269 | |||||
| 270 | Note that this override doesn't happen until after the program has | ||||
| 271 | compiled, so any compile-time errors will still show up with the | ||||
| 272 | non-overridden program name | ||||
| 273 | |||||
| 274 | =head1 TURNING OFF TIMESTAMPS IN MESSAGES | ||||
| 275 | |||||
| 276 | If your web server automatically adds a timestamp to each log line, | ||||
| 277 | you may not need CGI::Carp to add its own. You can disable timestamping | ||||
| 278 | by importing "noTimestamp": | ||||
| 279 | |||||
| 280 | use CGI::Carp qw(noTimestamp); | ||||
| 281 | |||||
| 282 | Alternatively you can set C<$CGI::Carp::NO_TIMESTAMP> to 1. | ||||
| 283 | |||||
| 284 | Note that the name of the program is still automatically included in | ||||
| 285 | the message. | ||||
| 286 | |||||
| 287 | =head1 GETTING THE FULL PATH OF THE SCRIPT IN MESSAGES | ||||
| 288 | |||||
| 289 | Set C<$CGI::Carp::FULL_PATH> to 1. | ||||
| 290 | |||||
| 291 | =head1 AUTHOR INFORMATION | ||||
| 292 | |||||
| 293 | The CGI.pm distribution is copyright 1995-2007, Lincoln D. Stein. It is | ||||
| 294 | distributed under the Artistic License 2.0. It is currently | ||||
| 295 | maintained by Lee Johnson with help from many contributors. | ||||
| 296 | |||||
| 297 | Address bug reports and comments to: https://github.com/leejo/CGI.pm/issues | ||||
| 298 | |||||
| 299 | The original bug tracker can be found at: https://rt.cpan.org/Public/Dist/Display.html?Queue=CGI.pm | ||||
| 300 | |||||
| 301 | When sending bug reports, please provide the version of CGI.pm, the version of | ||||
| 302 | Perl, the name and version of your Web server, and the name and version of the | ||||
| 303 | operating system you are using. If the problem is even remotely browser | ||||
| 304 | dependent, please provide information about the affected browsers as well. | ||||
| 305 | |||||
| 306 | =head1 SEE ALSO | ||||
| 307 | |||||
| 308 | L<Carp>, L<CGI::Base>, L<CGI::BasePlus>, L<CGI::Request>, | ||||
| 309 | L<CGI::MiniSvr>, L<CGI::Form>, L<CGI::Response>. | ||||
| 310 | |||||
| 311 | =cut | ||||
| 312 | |||||
| 313 | 1 | 9µs | require 5.000; | ||
| 314 | 2 | 59µs | 2 | 40µs | # spent 27µs (14+13) within CGI::Carp::BEGIN@314 which was called:
# once (14µs+13µs) by main::BEGIN@8 at line 314 # spent 27µs making 1 call to CGI::Carp::BEGIN@314
# spent 13µs making 1 call to Exporter::import |
| 315 | #use Carp; | ||||
| 316 | # spent 8µs within CGI::Carp::BEGIN@316 which was called:
# once (8µs+0s) by main::BEGIN@8 at line 319 | ||||
| 317 | 1 | 800ns | require Carp; | ||
| 318 | 1 | 7µs | *CORE::GLOBAL::die = \&CGI::Carp::die; | ||
| 319 | 1 | 22µs | 1 | 8µs | } # spent 8µs making 1 call to CGI::Carp::BEGIN@316 |
| 320 | |||||
| 321 | 2 | 2.01ms | 2 | 7.94ms | # spent 7.94ms (2.46+5.48) within CGI::Carp::BEGIN@321 which was called:
# once (2.46ms+5.48ms) by main::BEGIN@8 at line 321 # spent 7.94ms making 1 call to CGI::Carp::BEGIN@321
# spent 1µs making 1 call to CGI::Carp::__ANON__ |
| 322 | |||||
| 323 | 1 | 7µs | @ISA = qw(Exporter); | ||
| 324 | 1 | 900ns | @EXPORT = qw(confess croak carp); | ||
| 325 | 1 | 1µs | @EXPORT_OK = qw(carpout fatalsToBrowser warningsToBrowser wrap noTimestamp set_message set_die_handler set_progname cluck ^name= die); | ||
| 326 | |||||
| 327 | 1 | 9µs | $main::SIG{__WARN__}=\&CGI::Carp::warn; | ||
| 328 | |||||
| 329 | 1 | 400ns | $CGI::Carp::VERSION = '4.60'; | ||
| 330 | 1 | 400ns | $CGI::Carp::CUSTOM_MSG = undef; | ||
| 331 | 1 | 400ns | $CGI::Carp::DIE_HANDLER = undef; | ||
| 332 | 1 | 300ns | $CGI::Carp::TO_BROWSER = 1; | ||
| 333 | 1 | 300ns | $CGI::Carp::NO_TIMESTAMP= 0; | ||
| 334 | 1 | 300ns | $CGI::Carp::FULL_PATH = 0; | ||
| 335 | |||||
| 336 | # fancy import routine detects and handles 'errorWrap' specially. | ||||
| 337 | # spent 118µs (54+65) within CGI::Carp::import which was called 3 times, avg 40µs/call:
# once (16µs+27µs) by main::BEGIN@8 at line 8 of /aoa_test/cron/dbsetup.pl
# once (22µs+19µs) by main::BEGIN@8.2 at line 8 of /aoa_test/cron/db/mysql.pl
# once (17µs+19µs) by main::BEGIN@14 at line 14 of /aoa_test/cron/utils/utils.pl | ||||
| 338 | 3 | 3µs | my $pkg = shift; | ||
| 339 | 3 | 1µs | my(%routines); | ||
| 340 | my(@name); | ||||
| 341 | 3 | 3µs | if (@name=grep(/^name=/,@_)) | ||
| 342 | { | ||||
| 343 | my($n) = (split(/=/,$name[0]))[1]; | ||||
| 344 | set_progname($n); | ||||
| 345 | @_=grep(!/^name=/,@_); | ||||
| 346 | } | ||||
| 347 | |||||
| 348 | 3 | 12µs | grep($routines{$_}++,@_,@EXPORT); | ||
| 349 | 3 | 3µs | $WRAP++ if $routines{'fatalsToBrowser'} || $routines{'wrap'}; | ||
| 350 | 3 | 1µs | $WARN++ if $routines{'warningsToBrowser'}; | ||
| 351 | 3 | 2µs | my($oldlevel) = $Exporter::ExportLevel; | ||
| 352 | 3 | 1µs | $Exporter::ExportLevel = 1; | ||
| 353 | 3 | 80µs | 3 | 65µs | Exporter::import($pkg,keys %routines); # spent 65µs making 3 calls to Exporter::import, avg 22µs/call |
| 354 | 3 | 2µs | $Exporter::ExportLevel = $oldlevel; | ||
| 355 | 3 | 2µs | $main::SIG{__DIE__} =\&CGI::Carp::die if $routines{'fatalsToBrowser'}; | ||
| 356 | 3 | 19µs | $CGI::Carp::NO_TIMESTAMP = 1 if $routines{'noTimestamp'}; | ||
| 357 | } | ||||
| 358 | |||||
| 359 | # These are the originals | ||||
| 360 | sub realwarn { CORE::warn(@_); } | ||||
| 361 | sub realdie { CORE::die(@_); } | ||||
| 362 | |||||
| 363 | sub id { | ||||
| 364 | my $level = shift; | ||||
| 365 | my($pack,$file,$line,$sub) = caller($level); | ||||
| 366 | my($dev,$dirs,$id) = File::Spec->splitpath($file); | ||||
| 367 | return ($file,$line,$id); | ||||
| 368 | } | ||||
| 369 | |||||
| 370 | sub stamp { | ||||
| 371 | my $frame = 0; | ||||
| 372 | my ($id,$pack,$file,$dev,$dirs); | ||||
| 373 | if (defined($CGI::Carp::PROGNAME)) { | ||||
| 374 | $id = $CGI::Carp::PROGNAME; | ||||
| 375 | } else { | ||||
| 376 | do { | ||||
| 377 | $id = $file; | ||||
| 378 | ($pack,$file) = caller($frame++); | ||||
| 379 | } until !$file; | ||||
| 380 | } | ||||
| 381 | if (! $CGI::Carp::FULL_PATH) { | ||||
| 382 | ($dev,$dirs,$id) = File::Spec->splitpath($id); | ||||
| 383 | } | ||||
| 384 | return "$id: " if $CGI::Carp::NO_TIMESTAMP; | ||||
| 385 | my $time = scalar(localtime); | ||||
| 386 | return "[$time] $id: "; | ||||
| 387 | } | ||||
| 388 | |||||
| 389 | sub set_progname { | ||||
| 390 | $CGI::Carp::PROGNAME = shift; | ||||
| 391 | return $CGI::Carp::PROGNAME; | ||||
| 392 | } | ||||
| 393 | |||||
| 394 | |||||
| 395 | sub warn { | ||||
| 396 | my $message = shift; | ||||
| 397 | my($file,$line,$id) = id(1); | ||||
| 398 | $message .= " at $file line $line.\n" unless $message=~/\n$/; | ||||
| 399 | _warn($message) if $WARN; | ||||
| 400 | my $stamp = stamp; | ||||
| 401 | $message=~s/^/$stamp/gm; | ||||
| 402 | realwarn $message; | ||||
| 403 | } | ||||
| 404 | |||||
| 405 | sub _warn { | ||||
| 406 | my $msg = shift; | ||||
| 407 | if ($EMIT_WARNINGS) { | ||||
| 408 | # We need to mangle the message a bit to make it a valid HTML | ||||
| 409 | # comment. This is done by substituting similar-looking ISO | ||||
| 410 | # 8859-1 characters for <, > and -. This is a hack. | ||||
| 411 | $msg =~ tr/<>-/\253\273\255/; | ||||
| 412 | chomp $msg; | ||||
| 413 | print STDOUT "<!-- warning: $msg -->\n"; | ||||
| 414 | } else { | ||||
| 415 | push @WARNINGS, $msg; | ||||
| 416 | } | ||||
| 417 | } | ||||
| 418 | |||||
| 419 | |||||
| 420 | # The mod_perl package Apache::Registry loads CGI programs by calling | ||||
| 421 | # eval. These evals don't count when looking at the stack backtrace. | ||||
| 422 | sub _longmess { | ||||
| 423 | my $message = Carp::longmess(); | ||||
| 424 | $message =~ s,eval[^\n]+(ModPerl|Apache)/(?:Registry|Dispatch)\w*\.pm.*,,s | ||||
| 425 | if exists $ENV{MOD_PERL}; | ||||
| 426 | return $message; | ||||
| 427 | } | ||||
| 428 | |||||
| 429 | sub ineval { | ||||
| 430 | (exists $ENV{MOD_PERL} ? 0 : $^S) || _longmess() =~ /eval [\{\']/m | ||||
| 431 | } | ||||
| 432 | |||||
| 433 | sub die { | ||||
| 434 | # if no argument is passed, propagate $@ like | ||||
| 435 | # the real die | ||||
| 436 | my ($arg,@rest) = @_ ? @_ | ||||
| 437 | : $@ ? "$@\t...propagated" | ||||
| 438 | : "Died" | ||||
| 439 | ; | ||||
| 440 | |||||
| 441 | &$DIE_HANDLER($arg,@rest) if $DIE_HANDLER; | ||||
| 442 | |||||
| 443 | # the "$arg" is done on purpose! | ||||
| 444 | # if called as die( $object, 'string' ), | ||||
| 445 | # all is stringified, just like with | ||||
| 446 | # the real 'die' | ||||
| 447 | $arg = join '' => "$arg", @rest if @rest; | ||||
| 448 | |||||
| 449 | my($file,$line,$id) = id(1); | ||||
| 450 | |||||
| 451 | $arg .= " at $file line $line.\n" unless ref $arg or $arg=~/\n$/; | ||||
| 452 | |||||
| 453 | realdie $arg if ineval(); | ||||
| 454 | &fatalsToBrowser($arg) if ($WRAP and $CGI::Carp::TO_BROWSER); | ||||
| 455 | |||||
| 456 | $arg=~s/^/ stamp() /gme if $arg =~ /\n$/ or not exists $ENV{MOD_PERL}; | ||||
| 457 | |||||
| 458 | $arg .= "\n" unless $arg =~ /\n$/; | ||||
| 459 | |||||
| 460 | realdie $arg; | ||||
| 461 | } | ||||
| 462 | |||||
| 463 | sub set_message { | ||||
| 464 | $CGI::Carp::CUSTOM_MSG = shift; | ||||
| 465 | return $CGI::Carp::CUSTOM_MSG; | ||||
| 466 | } | ||||
| 467 | |||||
| 468 | sub set_die_handler { | ||||
| 469 | |||||
| 470 | my ($handler) = shift; | ||||
| 471 | |||||
| 472 | #setting SIG{__DIE__} here is necessary to catch runtime | ||||
| 473 | #errors which are not called by literally saying "die", | ||||
| 474 | #such as the line "undef->explode();". however, doing this | ||||
| 475 | #will interfere with fatalsToBrowser, which also sets | ||||
| 476 | #SIG{__DIE__} in the import() function above (or the | ||||
| 477 | #import() function above may interfere with this). for | ||||
| 478 | #this reason, you should choose to either set the die | ||||
| 479 | #handler here, or use fatalsToBrowser, not both. | ||||
| 480 | $main::SIG{__DIE__} = $handler; | ||||
| 481 | |||||
| 482 | $CGI::Carp::DIE_HANDLER = $handler; | ||||
| 483 | |||||
| 484 | return $CGI::Carp::DIE_HANDLER; | ||||
| 485 | } | ||||
| 486 | |||||
| 487 | sub confess { CGI::Carp::die Carp::longmess @_; } | ||||
| 488 | sub croak { CGI::Carp::die Carp::shortmess @_; } | ||||
| 489 | sub carp { CGI::Carp::warn Carp::shortmess @_; } | ||||
| 490 | sub cluck { CGI::Carp::warn Carp::longmess @_; } | ||||
| 491 | |||||
| 492 | # We have to be ready to accept a filehandle as a reference | ||||
| 493 | # or a string. | ||||
| 494 | sub carpout { | ||||
| 495 | my($in) = @_; | ||||
| 496 | my($no) = fileno(to_filehandle($in)); | ||||
| 497 | realdie("Invalid filehandle $in\n") unless defined $no; | ||||
| 498 | |||||
| 499 | open(SAVEERR, ">&STDERR"); | ||||
| 500 | open(STDERR, ">&$no") or | ||||
| 501 | ( print SAVEERR "Unable to redirect >&$no: $!\n" and exit(1) ); | ||||
| 502 | } | ||||
| 503 | |||||
| 504 | sub warningsToBrowser { | ||||
| 505 | $EMIT_WARNINGS = @_ ? shift : 1; | ||||
| 506 | _warn(shift @WARNINGS) while $EMIT_WARNINGS and @WARNINGS; | ||||
| 507 | } | ||||
| 508 | |||||
| 509 | # headers | ||||
| 510 | sub fatalsToBrowser { | ||||
| 511 | my $msg = shift; | ||||
| 512 | |||||
| 513 | $msg = "$msg" if ref $msg; | ||||
| 514 | |||||
| 515 | $msg=~s/&/&/g; | ||||
| 516 | $msg=~s/>/>/g; | ||||
| 517 | $msg=~s/</</g; | ||||
| 518 | $msg=~s/"/"/g; | ||||
| 519 | |||||
| 520 | my($wm) = $ENV{SERVER_ADMIN} ? | ||||
| 521 | qq[the webmaster (<a href="mailto:$ENV{SERVER_ADMIN}">$ENV{SERVER_ADMIN}</a>)] : | ||||
| 522 | "this site's webmaster"; | ||||
| 523 | my ($outer_message) = <<END; | ||||
| 524 | For help, please send mail to $wm, giving this error message | ||||
| 525 | and the time and date of the error. | ||||
| 526 | END | ||||
| 527 | ; | ||||
| 528 | my $mod_perl = exists $ENV{MOD_PERL}; | ||||
| 529 | |||||
| 530 | if ($CUSTOM_MSG) { | ||||
| 531 | if (ref($CUSTOM_MSG) eq 'CODE') { | ||||
| 532 | print STDOUT "Content-type: text/html\n\n" | ||||
| 533 | unless $mod_perl; | ||||
| 534 | eval { | ||||
| 535 | &$CUSTOM_MSG($msg); # nicer to perl 5.003 users | ||||
| 536 | }; | ||||
| 537 | if ($@) { print STDERR qq(error while executing the error handler: $@); } | ||||
| 538 | |||||
| 539 | return; | ||||
| 540 | } else { | ||||
| 541 | $outer_message = $CUSTOM_MSG; | ||||
| 542 | } | ||||
| 543 | } | ||||
| 544 | |||||
| 545 | my $mess = <<END; | ||||
| 546 | <h1>Software error:</h1> | ||||
| 547 | <pre>$msg</pre> | ||||
| 548 | <p> | ||||
| 549 | $outer_message | ||||
| 550 | </p> | ||||
| 551 | END | ||||
| 552 | ; | ||||
| 553 | |||||
| 554 | if ($mod_perl) { | ||||
| 555 | my $r; | ||||
| 556 | if ($ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { | ||||
| 557 | $mod_perl = 2; | ||||
| 558 | require Apache2::RequestRec; | ||||
| 559 | require Apache2::RequestIO; | ||||
| 560 | require Apache2::RequestUtil; | ||||
| 561 | require APR::Pool; | ||||
| 562 | require ModPerl::Util; | ||||
| 563 | require Apache2::Response; | ||||
| 564 | $r = Apache2::RequestUtil->request; | ||||
| 565 | } | ||||
| 566 | else { | ||||
| 567 | $r = Apache->request; | ||||
| 568 | } | ||||
| 569 | # If bytes have already been sent, then | ||||
| 570 | # we print the message out directly. | ||||
| 571 | # Otherwise we make a custom error | ||||
| 572 | # handler to produce the doc for us. | ||||
| 573 | if ($r->bytes_sent) { | ||||
| 574 | $r->print($mess); | ||||
| 575 | $mod_perl == 2 ? ModPerl::Util::exit(0) : $r->exit; | ||||
| 576 | } else { | ||||
| 577 | # MSIE won't display a custom 500 response unless it is >512 bytes! | ||||
| 578 | if (defined($ENV{HTTP_USER_AGENT}) && $ENV{HTTP_USER_AGENT} =~ /MSIE/) { | ||||
| 579 | $mess = "<!-- " . (' ' x 513) . " -->\n$mess"; | ||||
| 580 | } | ||||
| 581 | $r->custom_response(500,$mess); | ||||
| 582 | } | ||||
| 583 | } else { | ||||
| 584 | my $bytes_written = eval{tell STDOUT}; | ||||
| 585 | if (defined $bytes_written && $bytes_written > 0) { | ||||
| 586 | print STDOUT $mess; | ||||
| 587 | } | ||||
| 588 | else { | ||||
| 589 | print STDOUT "Status: 500\n"; | ||||
| 590 | print STDOUT "Content-type: text/html\n\n"; | ||||
| 591 | # MSIE won't display a custom 500 response unless it is >512 bytes! | ||||
| 592 | if (defined($ENV{HTTP_USER_AGENT}) && $ENV{HTTP_USER_AGENT} =~ /MSIE/) { | ||||
| 593 | $mess = "<!-- " . (' ' x 513) . " -->\n$mess"; | ||||
| 594 | } | ||||
| 595 | print STDOUT $mess; | ||||
| 596 | } | ||||
| 597 | } | ||||
| 598 | |||||
| 599 | warningsToBrowser(1); # emit warnings before dying | ||||
| 600 | } | ||||
| 601 | |||||
| 602 | # Cut and paste from CGI.pm so that we don't have the overhead of | ||||
| 603 | # always loading the entire CGI module. | ||||
| 604 | sub to_filehandle { | ||||
| 605 | my $thingy = shift; | ||||
| 606 | return undef unless $thingy; | ||||
| 607 | return $thingy if UNIVERSAL::isa($thingy,'GLOB'); | ||||
| 608 | return $thingy if UNIVERSAL::isa($thingy,'FileHandle'); | ||||
| 609 | if (!ref($thingy)) { | ||||
| 610 | my $caller = 1; | ||||
| 611 | while (my $package = caller($caller++)) { | ||||
| 612 | my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy"; | ||||
| 613 | return $tmp if defined(fileno($tmp)); | ||||
| 614 | } | ||||
| 615 | } | ||||
| 616 | return undef; | ||||
| 617 | } | ||||
| 618 | |||||
| 619 | 1 | 7µs | 1; | ||
# spent 1µs within CGI::Carp::__ANON__ which was called:
# once (1µs+0s) by CGI::Carp::BEGIN@321 at line 321 |