# Selima Website Content Management System # HTTP.pm: The various HTTP status processors. # Copyright (c) 2003-2018 imacat. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Author: imacat # First written: 2003-03-26 package Selima::HTTP; use 5.008; use strict; use warnings; use base qw(Exporter); use vars qw(@EXPORT @EXPORT_OK); BEGIN { @EXPORT = qw(); push @EXPORT, qw(http_204 http_301 http_303 http_304 http_307); push @EXPORT, qw(http_400 http_403 http_404 http_405 http_410 http_413 http_500 http_503); @EXPORT_OK = @EXPORT; # Prototype declaration sub need_302(); sub get_custom_status_message($); sub shall_mail_error(); sub http_204(); sub http_301($); sub http_303($); sub http_304(); sub http_307($); sub http_400(;$); sub http_403(;$); sub http_404(); sub http_405(@); sub http_410(); sub http_413(); sub http_500($); sub http_503(;$); } use CGI qw(header); use Encode qw(encode); use HTTP::Date qw(time2str); use IO::NestedCapture qw(CAPTURE_STDOUT); BEGIN { if (exists $ENV{"MOD_PERL_API_VERSION"} && $ENV{"MOD_PERL_API_VERSION"} >= 2) { require Apache2::Connection; require Apache2::Response; } } use Selima::A2HTML; use Selima::AbsURI; use Selima::AltLang; use Selima::DataVars qw(:env :input :l10n :lastmod :lninfo :output :requri :siteconf); use Selima::DecForm; use Selima::Format; use Selima::GeoIP; use Selima::GetLang; use Selima::Logging; use Selima::LogIn; use Selima::Page2Rel; use Selima::PageFunc; use Selima::ShortCut; use Selima::Unicode; use Selima::XFileIO; use Selima::XHTML; use Selima::Mail; BEGIN { # Only import this when mod_perl. if ($IS_MODPERL) { if ($IS_MP2) { require Apache2::Const; import Apache2::Const qw(:methods); } else { require Apache::Constants; import Apache::Constants qw(:methods); } # Otherwise, set to dummy values to get around strict checking } else { require constant; import constant M_OPTIONS => 0; import constant M_GET => 0; import constant M_HEAD => 0; import constant M_POST => 0; import constant M_PUT => 0; import constant M_DELETE => 0; import constant M_TRACE => 0; import constant M_CONNECT => 0; } } # need_302: Is this browser capable of HTTP 303 and HTTP 307? # Currently only older Netscape without Gecko (version <= 4.xx) # is known of this problem. # Return: # false: Standard behavior to send HTTP 303 or 307. # true: Browser lacks the capability of redirecting # HTTP 303 and 307. Send HTTP 302 instead. sub need_302() { local ($_, %_); # User-Agent not sent, default to the standard behavior. return 0 unless exists $ENV{"HTTP_USER_AGENT"}; $_ = $ENV{"HTTP_USER_AGENT"}; # Not Mozilla/Netscape series return 0 unless /^Mozilla\//; # Mozilla/Netscape compatible return 0 if /\bcompatible\b/; # Mozilla/Netscape with Gecko (version > 4) return 0 if /\bGecko\b/; # Mozilla/Netscape without Gecko (version <= 4) return 1; } # get_custom_status_message: Obtain the custom status message sub get_custom_status_message($) { local ($_, %_); my ($html, $status, $langfile, $charset); $status = $_[0]; $langfile = getlang(LN_FILENAME); # Find language specific error message first if (-e ($_ = "$DOC_ROOT/errors/$status.html.$langfile.xhtml")) { $html = xfread $_; } elsif (-e ($_ = "$DOC_ROOT/errors/$status.html.$langfile")) { $html = xfread $_; } elsif (-e ($_ = "$DOC_ROOT/$langfile/errors/$status.html.xhtml")) { $html = xfread $_; } elsif (-e ($_ = "$DOC_ROOT/$langfile/errors/$status.html")) { $html = xfread $_; } elsif (-e ($_ = "$DOC_ROOT/errors/$status.html.xhtml")) { $html = xfread $_; } elsif (-e ($_ = "$DOC_ROOT/errors/$status.html")) { $html = xfread $_; } # Not found return if !defined $html; # Reserve the character set $charset = getlang(LN_CHARSET); $html = hcref_decode($charset, $html); $charset = h($charset); $html =~ s/(?<=\bencoding=")$charset(?=")//; $html =~ s/(?<=\bcontent="text\/html; charset=)$charset(?=")//; $html =~ s/(?<=\bcontent="application\/xhtml\+xml; charset=)$charset(?=")//; $html =~ s/(?<=\btype="hidden" name="charset" value=")$charset(?=" \/>)//g; $html =~ s/(?<=\baccept-charset=")$charset(?=")//g; return $html; } # shall_mail_error: Should we mail the error to the webmaster sub shall_mail_error() { local ($_, %_); # Return "no" if not CGI return 0 if !$IS_CGI; # Return "no" if inside our intranet $_ = $IS_MODPERL? ($IS_MP2? Apache2::RequestUtil->request->connection->remote_ip: Apache->request->connection->remote_ip): $ENV{"REMOTE_ADDR"}; return 0 if /^10\.0\.0\./ || $_ eq "127.0.0.1"; # Default to yes return 1; } # http_204: HTTP/1.1 204 No Content sub http_204() { local ($_, %_); my ($html, $r, $type, %h); # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Only output headers to the CGI interface if ($IS_CGI) { $type = defined $CONTENT_TYPE? $CONTENT_TYPE: xhtml_content_type; # The mod_perl way if ($IS_MODPERL) { $r->status(204); $r->headers_out->set("Content-Length"=>0); $r->content_languages([getlang LN_NAME]) if $type =~ /^text\//; # Client cache if (defined $LAST_MODIFIED) { if (defined get_login_sn) { $r->headers_out->set("Cache-Control"=>"private"); } else { $r->headers_out->set("Cache-Control"=>"public"); } $r->headers_out->set("Last-Modified"=>time2str($LAST_MODIFIED)); } else { $r->headers_out->set("Cache-Control"=>"no-cache"); } # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->headers_out->set("Vary"=>"accept-language,cookie"); } $r->headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { # Output the status message %h = ( -status=>"204 No Content", -Content_Length=>0); $h{"-Content_Language"} = getlang LN_NAME if $type =~ /^text\//; # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } # Client cache if (defined $LAST_MODIFIED) { if (defined get_login_sn) { $h{"-Cache_Control"} = "private"; } else { $h{"-Cache_Control"} = "public"; } $h{"-Last_Modified"} = time2str($LAST_MODIFIED); } else { $h{"-Cache_Control"} = "no-cache"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); } } # No need to return exit; } # http_301: HTTP/1.1 301 Moved Permanently sub http_301($) { local ($_, %_); my ($html, $r, $type, %h, $url); $url = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Make URL absolute $url = absuri $url; # Obtain the status message $html = get_custom_status_message(301); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 301 Moved Permanently

301 Moved Permanently

You should refer to the new location.

EOT } # Replace the page content $html =~ s/\$url/h($url)/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(301, $html); $r->status(301); $r->err_headers_out->set("Location"=>$url); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"301 Moved Permanently", -type=>$type, -Location=>$url, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # No need to return exit; } # http_303: HTTP/1.1 303 See Others sub http_303($) { local ($_, %_); my ($html, $r, $type, %h, $url); $url = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Make URL absolute $url = absuri $url; # Obtain the status message $html = get_custom_status_message(303); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 303 See Others

303 See Others

Please follow this location.

EOT } # Replace the page content $html =~ s/\$url/h($url)/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); if (need_302) { $r->custom_response(302, $html); $r->status(302); } else { $r->custom_response(303, $html); $r->status(303); } $r->err_headers_out->set("Location"=>$url); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"303 See Others", -type=>$type, -Location=>$url, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); $h{"-status"} = "302 Found" if need_302; # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # No need to return exit; } # http_304: HTTP/1.1 304 Not Modified sub http_304() { local ($_, %_); my ($html, $r, $type, %h); # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Only output headers to the CGI interface # See HTTP/1.1 sec 10.3.5 for appropriate headers to send if ($IS_CGI) { # The mod_perl way # We must do it in the mod_perl way, since the CGI.pm sends an # excess line break under mod_perl, which breaks the HTTP/304 # response for the browser. if ($IS_MODPERL) { $r->status(304); $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # We must send them $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)) if @ALL_LINGUAS > 1; # Ordinary CGI } else { $type = (defined $CONTENT_TYPE? $CONTENT_TYPE: xhtml_content_type) . "; charset=" . getlang(LN_CHARSET); # Output the status message %h = ( -status=>"304 Not Modified"); $h{"-Content_Location"} = altlang getlang, page_param if @ALL_LINGUAS > 1; # Avoid the bug of Apache/CGI that always send the content type # even with HTTP/304 $h{"-type"} = $type; $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # No need to return exit; } # http_307: HTTP/1.1 307 Temporary Redirect sub http_307($) { local ($_, %_); my ($html, $r, $type, %h, $url); $url = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Make URL absolute $url = absuri $url; # Obtain the status message $html = get_custom_status_message(307); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 307 Temporary Redirect

307 Temporary Redirect

Please refer to the following location.

EOT } # Replace the page content $html =~ s/\$url/h($url)/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); if (need_302) { $r->custom_response(302, $html); $r->status(302); } else { $r->custom_response(307, $html); $r->status(307); } $r->err_headers_out->set("Location"=>$url); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"307 Temporary Redirect", -type=>$type, -Location=>$url, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); $h{"-status"} = "302 Found" if need_302; # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # No need to return exit; } # http_400: HTTP/1.1 400 Bad Request # 0 to disable error page output sub http_400(;$) { local ($_, %_); my ($html, $r, $type, %h); my $errmsg; $errmsg = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(400) unless defined $errmsg && $errmsg eq "0"; # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 400 Bad Request

400 Bad Request

Sorry, the server cannot understand what you are asking for.

EOT } # Replace the page content $html =~ s//defined $errmsg && $errmsg ne "0"? "

" . h(F_($errmsg)) . "<\/p>": ""/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(400, $html); $r->status(400); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"400 Bad Request", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log if (!defined $errmsg) { log_error "Bad Request: $REQUEST_URI"; } elsif ($errmsg eq "0") { if ($IS_MODPERL) { $_ = $r->the_request; } else { $_ = $ENV{"REQUEST_METHOD"} . " " . $ENV{"REQUEST_URI"} . " " . $ENV{"SERVER_PROTOCOL"}; } log_error "Invalid URI in request $_"; } else { log_error "Bad Request: $REQUEST_URI: $errmsg"; } # No need to return exit 400 if !$IS_CGI; exit; } # http_403: HTTP/1.1 403 Forbidden sub http_403(;$) { local ($_, %_); my ($html, $r, $type, %h); my $errmsg; $errmsg = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(403) unless defined $errmsg && $errmsg eq "0"; # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 403 Forbidden

403 Forbidden

You are not allowed to enter here.

EOT } # Replace the page content $html =~ s//defined $errmsg && $errmsg ne "0"? "

" . h(F_($errmsg)) . "<\/p>": ""/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(403, $html); $r->status(403); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"403 Forbidden", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log if (!defined $errmsg) { log_error "Forbidden: $REQUEST_URI"; } elsif ($errmsg eq "0") { if ($IS_MODPERL) { $_ = $r->the_request; } else { $_ = $ENV{"REQUEST_METHOD"} . " " . $ENV{"REQUEST_URI"} . " " . $ENV{"SERVER_PROTOCOL"}; } log_error "Suspicious bad robot: $_"; } else { log_error "Forbidden: $REQUEST_URI: $errmsg"; } # No need to return exit 403 if !$IS_CGI; exit; } # http_404: HTTP/1.1 404 Not Found sub http_404() { local ($_, %_); my ($html, $r, $type, %h); # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(404); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 404 Not Found

404 Not Found

The document you requested was not found.

EOT } # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(404, $html); $r->status(404); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"404 Not Found", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log log_error "Not Found: $REQUEST_URI"; # No need to return exit 404 if !$IS_CGI; exit; } # http_405: HTTP/1.1 405 Method Not Allowed sub http_405(@) { local ($_, %_); my ($html, $r, $type, %h, @allowed); @allowed = @_; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(405); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 405 Method Not Allowed

405 Method Not Allowed

You should use the following methods: \$allowed.

EOT } # Replace the page content $html =~ s/\$allowed/join(", ", map "" . h($_) . "<\/samp>", @allowed)/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { my $allowed_b; $allowed_b = 0; foreach (@allowed) { if ($_ eq "OPTIONS") { $allowed_b |= (1 << M_OPTIONS); } elsif ($_ eq "GET") { $allowed_b |= (1 << M_GET); # M_HEAD is not defined in Apache. It is implied by M_GET. #} elsif ($_ eq "HEAD") { # $allowed_b |= (1 << M_HEAD); } elsif ($_ eq "POST") { $allowed_b |= (1 << M_POST); } elsif ($_ eq "PUT") { $allowed_b |= (1 << M_PUT); } elsif ($_ eq "DELETE") { $allowed_b |= (1 << M_DELETE); } elsif ($_ eq "TRACE") { $allowed_b |= (1 << M_TRACE); } elsif ($_ eq "CONNECT") { $allowed_b |= (1 << M_CONNECT); } } # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(405, $html); $r->status(405); $r->allowed($allowed_b); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"405 Method Not Allowed", -type=>$type, -Allow=>join(", ", @allowed), -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log $_ = $IS_MODPERL? $r->method: $ENV{"REQUEST_METHOD"}; log_error "$_: Method Not Allowed (" . join(", ", @allowed) . "): $REQUEST_URI\n"; # No need to return exit 405 if !$IS_CGI; exit; } # http_410: HTTP 410 Gone sub http_410() { local ($_, %_); my ($html, $r, $type, %h); # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(410); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 410 Gone

410 Gone

Sorry, this page is removed permanently, and there is no forwarding address available. Please remove your bookmarks, and stop referring to this page any more. Thanks.

EOT } # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(410, $html); $r->status(410); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"410 Gone", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log log_error "Gone: $REQUEST_URI"; # No need to return exit 410 if !$IS_CGI; exit; } # http_413: HTTP/1.1 413 Request Entity Too Large sub http_413() { local ($_, %_); my ($html, $r, $type, %h); # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(413); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 413 Request Entity Too Large

413 Request Entity Too Large

The server refuses to process your large submitted data.

EOT } # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(413, $html); $r->status(413); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"413 Request Entity Too Large", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log log_error "Request Entity Too Large: $REQUEST_URI"; # No need to return exit 413 if !$IS_CGI; exit; } # http_500: HTTP/1.1 500 Internet Server Error sub http_500($) { local ($_, %_); my ($html, $r, $type, %h); my ($errmsg, @callers, $remote); $errmsg = $_[0]; # Find out our context for (my $i = 0, @callers = qw(); (@_ = caller $i) > 0; $i++) { # Avoid recursive calls # Not possible. $SIG{"__DIE__"} is disabled during itself. # Context after Apache::Registry is not meaningful last if $_[1] =~ /\/Apache\/Registry\.pm$/; # Skip if in eval(). # Apache handler() eval() is not trapped for it is at Apache::Registry # and is skipped by the above rule. return if $_[3] eq "(eval)"; push @callers, [@_]; } # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; $remote = $IS_MODPERL? $r->connection->remote_ip: $ENV{"REMOTE_ADDR"}; # Variables in the status message $errmsg =~ s/ at \S+ line \d+\.\n//; # Obtain the status message $html = get_custom_status_message(500); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 500 Internel Server Error

500 Internel Server Error

EOT } # Replace the page content $html =~ s// "
\n" . a2html($errmsg) . "<\/samp>
\n" . join("
\n", map "at " . h($$_[1]) . "<\/samp> line " . h($$_[2]), @callers) . ".\n<\/div>"/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(500, $html); $r->status(500); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"500 Internel Server Error", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Mail the webmaster on this error if (shall_mail_error) { my ($mail, $webmaster, $site, $body, $reqline, $reqhdrs, $form); # Get the webmaster address to notify to if (defined $WEBMASTER) { $webmaster = $WEBMASTER; } elsif (exists $ENV{"SERVER_ADMIN"}) { $webmaster = $ENV{"SERVER_ADMIN"}; } else { $webmaster = "webmaster\@" . $ENV{"SERVER_NAME"}; } # Get the site name $site = defined $SITENAME_ABBR? $SITENAME_ABBR: defined $PACKAGE? $PACKAGE: $REQUEST_HOST; # The request string if ($IS_MODPERL) { $r->as_string =~ /^([^\n]+)\n((?:[^\n]+\n)*).+?$/s; ($reqline, $reqhdrs) = ($1, $2); $reqhdrs =~ s/^(.+)$/* $1/gm; } else { $reqline = sprintf "%s %s%s %s", $ENV{"REQUEST_METHOD"}, $ROOT_DIFF, $REQUEST_URI, $ENV{"SERVER_PROTOCOL"}; %_ = qw(); foreach my $key (grep /^HTTP_/, keys %ENV) { $_ = $key; s/^HTTP_//; s/_/-/g; s/(\w)(\w+)/$1 . lc $2/ge; $_{$_} = $ENV{$key}; } $reqhdrs = join "", map "* $_: $_{$_}\n", sort keys %_; } $body = ""; # Basic information $_ = << "EOT"; [%s] HTTP 500 Server Error Report %s ============================== * Time: %s * URI: %s * Request: %s * Error Message: %s %s. EOT $body = sprintf $_, $site, fmtdate, fmttime, $REQUEST_FULLURI, $reqline, $errmsg, join("\n", map " at $$_[1] line $$_[2]", @callers); # Client headers $body .= "Client Headers:\n$reqhdrs\n"; # POSTed form if (($IS_MODPERL? $r->method: $ENV{"REQUEST_METHOD"}) eq "POST") { $body .= "POST form:\n"; if (exists $USER_INPUT{"POST_RAW"}) { $form = $USER_INPUT{"POST_RAW"}; } else { $form = new CGI; } $body .= join "", map "* $_: " . $form->param($_) . "\n", sort $form->param; $body .= "\n"; } # CGI metavariables - refer to CGI 1.1 @_ = qw(AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE); $body .= "CGI Metavariables:\n"; $body .= join "", map "* $_: $ENV{$_}\n", grep exists $ENV{$_}, @_; $body .= "\n"; # Other information $body .= "Other information:\n"; if (defined get_login_sn) { $_ = ""; $_ .= "* User ID.: " . get_login_id . "\n"; $_ .= "* User name: " . get_login_name . "\n"; $_ .= "* User S/N: " . get_login_sn . "\n"; $_ .= "* User groups: " . join(" ", get_login_groups) . "\n"; $body .= encode("UTF-8", $_); } else { $body .= "* User ID.: (not logged in)\n"; } $body .= "* Client country: " . country_lookup . "\n"; $body .= "\n"; # Compose and send the mail $mail = new Selima::Mail; $mail->from("HTTP.pm\@" . $ENV{"SERVER_NAME"}, "$site Website"); $mail->to($webmaster, "$site Webmaster"); $mail->subject(sprintf("[%s] HTTP 500 Server Error Report %s", $site, fmtdate)); $mail->body($body); $mail->send; } # Log the error message to the server error log log_error("$errmsg " . join(" ", map "at $$_[1] line $$_[2]", @callers) . "."); # No need to return exit 500 if !$IS_CGI; exit; } # http_503: HTTP/1.1 503 Service Unavailable sub http_503(;$) { local ($_, %_); my ($html, $r, $type, %h); my $errmsg; $errmsg = $_[0]; # Obtain the Apache mod_perl request $r = $IS_MP2? Apache2::RequestUtil->request: Apache->request if $IS_MODPERL; # Clear the STDOUT buffer IO::NestedCapture->stop(CAPTURE_STDOUT) while exists IO::NestedCapture->instance->{"STDOUT_current"} && @{IO::NestedCapture->instance->{"STDOUT_current"}} > 0; # Skip content auto-output $NO_AUTO_OUTPUT = 1; # Obtain the status message $html = get_custom_status_message(503); # Fall back to a simplest default if (!defined $html) { $html = << "EOT"; 503 Service Unavailable

503 Service Unavailable

Sorry, our service is currently not available. Please come back later.

EOT } # Replace the page content $html =~ s//defined $errmsg? "

" . h($errmsg) . "<\/p>": ""/ge; # Convert the URLs to relative $html = page2rel $html, $REQUEST_PATH; # Encode the e-mail at-signs (@) $html =~ s/@/@/g; # Decode the e-mail at-signs (@) of spamtrap $html =~ s/spamtrap@/spamtrap@/g; # Only output headers to the CGI interface if ($IS_CGI) { # The mod_perl way if ($IS_MODPERL) { # Error documents can only be output as ISO-8859-1 under mod_perl. # It is hardcoded into Apache http_protocol.c ap_send_error_response(). # See http://www.geocrawler.com/mail/msg.php3?msg_id=6288656 $html = page_encode($html, "ISO-8859-1"); $r->custom_response(503, $html); $r->status(503); $r->err_headers_out->set("Content-Language"=>getlang LN_NAME); $r->err_headers_out->set("Content-Length"=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $r->method ne "POST" && $r->method ne "PUT" && !defined $GET->param("lang")) { $r->err_headers_out->set("Content-Location"=>altlang(getlang, page_param)); $r->err_headers_out->set("Vary"=>"accept-language,cookie"); } $r->err_headers_out->add("Set-Cookie"=>$_) foreach values %NEWCOOKIES; # Ordinary CGI } else { $html = page_encode($html, getlang(LN_CHARSET)); $type = xhtml_content_type . "; charset=" . getlang(LN_CHARSET); %h = ( -status=>"503 Service Unavailable", -type=>$type, -Content_Language=>getlang(LN_NAME), -Content_Length=>length $html); # Content negotiation, see HTTP/1.1 section 13.6 if ( @ALL_LINGUAS > 1 && $ENV{"REQUEST_METHOD"} ne "POST" && $ENV{"REQUEST_METHOD"} ne "PUT" && !defined $GET->param("lang")) { $h{"-Content_Location"} = altlang getlang, page_param; $h{"-Vary"} = "accept-language,cookie"; } $h{"-cookie"} = [values %NEWCOOKIES]; print header(%h); print $html if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Output the content directly as a console application } else { print page_encode($html, getlang(LN_CHARSET)) if $ENV{"REQUEST_METHOD"} ne "HEAD"; } # Log the error message to the server error log # No logging due to maintainance # No need to return exit 503 if !$IS_CGI; exit; } return 1;