1
# -*- Mode: perl; indent-tabs-mode: nil -*-
3
# The contents of this file are subject to the Mozilla Public
4
# License Version 1.1 (the "License"); you may not use this file
5
# except in compliance with the License. You may obtain a copy of
6
# the License at http://www.mozilla.org/MPL/
8
# Software distributed under the License is distributed on an "AS
9
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
# implied. See the License for the specific language governing
11
# rights and limitations under the License.
13
# The Original Code is the Bugzilla Bug Tracking System.
15
# The Initial Developer of the Original Code is Netscape Communications
16
# Corporation. Portions created by Netscape are
17
# Copyright (C) 1998 Netscape Communications Corporation. All
20
# Contributor(s): Bradley Baetz <bbaetz@acm.org>
21
# Marc Schumann <wurblzap@gmail.com>
22
# Frédéric Buclin <LpSolit@gmail.com>
24
package Bugzilla::Error;
27
use base qw(Exporter);
29
@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
31
use Bugzilla::Constants;
32
use Bugzilla::WebService::Constants;
36
# We cannot use $^S to detect if we are in an eval(), because mod_perl
37
# already eval'uates everything, so $^S = 1 in all cases under mod_perl!
40
for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
41
last if $sub =~ /^ModPerl/;
42
$in_eval = 1 if $sub =~ /^\(eval\)/;
48
my ($name, $error, $vars) = @_;
52
$vars->{error} = $error;
54
# Make sure any locked tables are unlocked
55
# and the transaction is rolled back (if supported)
56
# If we are within an eval(), do not unlock tables as we are
57
# eval'uating some test on purpose.
58
Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT) unless _in_eval();
60
my $datadir = bz_locations()->{'datadir'};
61
# If a writable $datadir/errorlog exists, log error details there.
62
if (-w "$datadir/errorlog") {
65
for (1..75) { $mesg .= "-"; };
66
$mesg .= "\n[$$] " . time2str("%D %H:%M:%S ", time());
67
$mesg .= "$name $error ";
68
$mesg .= "$ENV{REMOTE_ADDR} " if $ENV{REMOTE_ADDR};
69
$mesg .= Bugzilla->user->login;
70
$mesg .= (' actually ' . Bugzilla->sudoer->login) if Bugzilla->sudoer;
72
my %params = Bugzilla->cgi->Vars;
73
$Data::Dumper::Useqq = 1;
74
for my $param (sort keys %params) {
75
my $val = $params{$param};
77
$val = "*****" if $param =~ /password/i;
79
$val =~ s/^(.{512}).*$/$1\[CHOP\]/;
80
$mesg .= "[$$] " . Data::Dumper->Dump([$val],["param($param)"]);
82
for my $var (sort keys %ENV) {
84
$val = "*****" if $val =~ /password|http_pass/i;
85
$mesg .= "[$$] " . Data::Dumper->Dump([$val],["env($var)"]);
87
open(ERRORLOGFID, ">>$datadir/errorlog");
88
print ERRORLOGFID "$mesg\n";
92
my $template = Bugzilla->template;
93
if (Bugzilla->error_mode == ERROR_MODE_WEBPAGE) {
94
print Bugzilla->cgi->header();
95
$template->process($name, $vars)
96
|| ThrowTemplateError($template->error());
100
$template->process($name, $vars, \$message)
101
|| ThrowTemplateError($template->error());
102
if (Bugzilla->error_mode == ERROR_MODE_DIE) {
105
elsif (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) {
106
my $code = WS_ERROR_CODE->{$error};
108
$code = ERROR_UNKNOWN_FATAL if $name =~ /code/i;
109
$code = ERROR_UNKNOWN_TRANSIENT if $name =~ /user/i;
111
die SOAP::Fault->faultcode($code)->faultstring($message);
118
_throw_error("global/user-error.html.tmpl", @_);
122
_throw_error("global/code-error.html.tmpl", @_);
125
sub ThrowTemplateError {
126
my ($template_err) = @_;
128
# Make sure any locked tables are unlocked
129
# and the transaction is rolled back (if supported)
130
Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT);
133
if (Bugzilla->error_mode == ERROR_MODE_DIE) {
134
die("error: template error: $template_err");
137
$vars->{'template_error_msg'} = $template_err;
138
$vars->{'error'} = "template_error";
140
my $template = Bugzilla->template;
142
# Try a template first; but if this one fails too, fall back
143
# on plain old print statements.
144
if (!$template->process("global/code-error.html.tmpl", $vars)) {
145
my $maintainer = Bugzilla->params->{'maintainer'};
146
my $error = html_quote($vars->{'template_error_msg'});
147
my $error2 = html_quote($template->error());
151
Bugzilla has suffered an internal error. Please save this page and
152
send it to $maintainer with details of what you were doing at the
153
time this message appeared.
155
<script type="text/javascript"> <!--
156
document.write("<p>URL: " +
157
document.location.href.replace(/&/g,"&")
158
.replace(/</g,"<")
159
.replace(/>/g,">") + "</p>");
162
<p>Template->process() failed twice.<br>
163
First error: $error<br>
164
Second error: $error2</p>
177
Bugzilla::Error - Error handling utilities for Bugzilla
183
ThrowUserError("error_tag",
188
Various places throughout the Bugzilla codebase need to report errors to the
189
user. The C<Throw*Error> family of functions allow this to be done in a
190
generic and localizable manner.
192
These functions automatically unlock the database tables, if there were any
193
locked. They will also roll back the transaction, if it is supported by
200
=item C<ThrowUserError>
202
This function takes an error tag as the first argument, and an optional hashref
203
of variables as a second argument. These are used by the
204
I<global/user-error.html.tmpl> template to format the error, using the passed
205
in variables as required.
207
=item C<ThrowCodeError>
209
This function is used when an internal check detects an error of some sort.
210
This usually indicates a bug in Bugzilla, although it can occur if the user
211
manually constructs urls without correct parameters.
213
This function's behaviour is similar to C<ThrowUserError>, except that the
214
template used to display errors is I<global/code-error.html.tmpl>. In addition
215
if the hashref used as the optional second argument contains a key I<variables>
216
then the contents of the hashref (which is expected to be another hashref) will
217
be displayed after the error message, as a debugging aid.
219
=item C<ThrowTemplateError>
221
This function should only be called if a C<template-<gt>process()> fails.
222
It tries another template first, because often one template being
223
broken or missing doesn't mean that they all are. But it falls back to
224
a print statement as a last-ditch error.