~ubuntu-branches/ubuntu/intrepid/bugzilla/intrepid

« back to all changes in this revision

Viewing changes to Bugzilla/Error.pm

  • Committer: Bazaar Package Importer
  • Author(s): Raphael Bossek
  • Date: 2008-06-27 22:34:34 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080627223434-0ib57vstn43bb4a3
Tags: 3.0.4.1-1
* Update of French, Russian and German translations. (closes: #488251)
* Added Bulgarian and Belarusian translations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- Mode: perl; indent-tabs-mode: nil -*-
2
 
#
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/
7
 
#
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.
12
 
#
13
 
# The Original Code is the Bugzilla Bug Tracking System.
14
 
#
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
18
 
# Rights Reserved.
19
 
#
20
 
# Contributor(s): Bradley Baetz <bbaetz@acm.org>
21
 
#                 Marc Schumann <wurblzap@gmail.com>
22
 
#                 Frédéric Buclin <LpSolit@gmail.com>
23
 
 
24
 
package Bugzilla::Error;
25
 
 
26
 
use strict;
27
 
use base qw(Exporter);
28
 
 
29
 
@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
30
 
 
31
 
use Bugzilla::Constants;
32
 
use Bugzilla::WebService::Constants;
33
 
use Bugzilla::Util;
34
 
use Date::Format;
35
 
 
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!
38
 
sub _in_eval {
39
 
    my $in_eval = 0;
40
 
    for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
41
 
        last if $sub =~ /^ModPerl/;
42
 
        $in_eval = 1 if $sub =~ /^\(eval\)/;
43
 
    }
44
 
    return $in_eval;
45
 
}
46
 
 
47
 
sub _throw_error {
48
 
    my ($name, $error, $vars) = @_;
49
 
 
50
 
    $vars ||= {};
51
 
 
52
 
    $vars->{error} = $error;
53
 
 
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();
59
 
 
60
 
    my $datadir = bz_locations()->{'datadir'};
61
 
    # If a writable $datadir/errorlog exists, log error details there.
62
 
    if (-w "$datadir/errorlog") {
63
 
        require Data::Dumper;
64
 
        my $mesg = "";
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;
71
 
        $mesg .= "\n";
72
 
        my %params = Bugzilla->cgi->Vars;
73
 
        $Data::Dumper::Useqq = 1;
74
 
        for my $param (sort keys %params) {
75
 
            my $val = $params{$param};
76
 
            # obscure passwords
77
 
            $val = "*****" if $param =~ /password/i;
78
 
            # limit line length
79
 
            $val =~ s/^(.{512}).*$/$1\[CHOP\]/;
80
 
            $mesg .= "[$$] " . Data::Dumper->Dump([$val],["param($param)"]);
81
 
        }
82
 
        for my $var (sort keys %ENV) {
83
 
            my $val = $ENV{$var};
84
 
            $val = "*****" if $val =~ /password|http_pass/i;
85
 
            $mesg .= "[$$] " . Data::Dumper->Dump([$val],["env($var)"]);
86
 
        }
87
 
        open(ERRORLOGFID, ">>$datadir/errorlog");
88
 
        print ERRORLOGFID "$mesg\n";
89
 
        close ERRORLOGFID;
90
 
    }
91
 
 
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());
97
 
    }
98
 
    else {
99
 
        my $message;
100
 
        $template->process($name, $vars, \$message)
101
 
          || ThrowTemplateError($template->error());
102
 
        if (Bugzilla->error_mode == ERROR_MODE_DIE) {
103
 
            die("$message\n");
104
 
        }
105
 
        elsif (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) {
106
 
            my $code = WS_ERROR_CODE->{$error};
107
 
            if (!$code) {
108
 
                $code = ERROR_UNKNOWN_FATAL if $name =~ /code/i;
109
 
                $code = ERROR_UNKNOWN_TRANSIENT if $name =~ /user/i;
110
 
            }
111
 
            die SOAP::Fault->faultcode($code)->faultstring($message);
112
 
        }
113
 
    }
114
 
    exit;
115
 
}
116
 
 
117
 
sub ThrowUserError {
118
 
    _throw_error("global/user-error.html.tmpl", @_);
119
 
}
120
 
 
121
 
sub ThrowCodeError {
122
 
    _throw_error("global/code-error.html.tmpl", @_);
123
 
}
124
 
 
125
 
sub ThrowTemplateError {
126
 
    my ($template_err) = @_;
127
 
 
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);
131
 
 
132
 
    my $vars = {};
133
 
    if (Bugzilla->error_mode == ERROR_MODE_DIE) {
134
 
        die("error: template error: $template_err");
135
 
    }
136
 
 
137
 
    $vars->{'template_error_msg'} = $template_err;
138
 
    $vars->{'error'} = "template_error";
139
 
 
140
 
    my $template = Bugzilla->template;
141
 
 
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());
148
 
        print <<END;
149
 
        <tt>
150
 
          <p>
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.
154
 
          </p>
155
 
          <script type="text/javascript"> <!--
156
 
          document.write("<p>URL: " + 
157
 
                          document.location.href.replace(/&/g,"&amp;")
158
 
                                                .replace(/</g,"&lt;")
159
 
                                                .replace(/>/g,"&gt;") + "</p>");
160
 
          // -->
161
 
          </script>
162
 
          <p>Template->process() failed twice.<br>
163
 
          First error: $error<br>
164
 
          Second error: $error2</p>
165
 
        </tt>
166
 
END
167
 
    }
168
 
    exit;
169
 
}
170
 
 
171
 
1;
172
 
 
173
 
__END__
174
 
 
175
 
=head1 NAME
176
 
 
177
 
Bugzilla::Error - Error handling utilities for Bugzilla
178
 
 
179
 
=head1 SYNOPSIS
180
 
 
181
 
  use Bugzilla::Error;
182
 
 
183
 
  ThrowUserError("error_tag",
184
 
                 { foo => 'bar' });
185
 
 
186
 
=head1 DESCRIPTION
187
 
 
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.
191
 
 
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
194
 
the underlying DB.
195
 
 
196
 
=head1 FUNCTIONS
197
 
 
198
 
=over 4
199
 
 
200
 
=item C<ThrowUserError>
201
 
 
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.
206
 
 
207
 
=item C<ThrowCodeError>
208
 
 
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.
212
 
 
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.
218
 
 
219
 
=item C<ThrowTemplateError>
220
 
 
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.
225
 
 
226
 
=back
227
 
 
228
 
=head1 SEE ALSO
229
 
 
230
 
L<Bugzilla|Bugzilla>