use Bugzilla::Config;
use Bugzilla::Constants;
+use Bugzilla::Error;
use Bugzilla::Util;
sub login {
# An error may have occurred with the login mechanism
if ($authres == AUTH_ERROR) {
- $::vars->{'authmethod'} = lc($authmethod);
- $::vars->{'userid'} = $userid;
- $::vars->{'auth_err_tag'} = $extra;
- $::vars->{'info'} = $info;
-
- &::ThrowCodeError("auth_err");
+ ThrowCodeError("auth_err",
+ { authmethod => lc($authmethod),
+ userid => $userid,
+ auth_err_tag => $extra,
+ info => $info
+ });
}
# We can load the page if the login was ok, or there was no data
'caneditaccount' => Bugzilla::Auth->can_edit,
}
)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
# This seems like as good as time as any to get rid of old
# crufty junk in the logincookies table. Get rid of any entry
# the password was just wrong. (This makes it harder for a cracker
# to find account names by brute force)
if ($authres == AUTH_LOGINFAILED) {
- &::ThrowUserError("invalid_username_or_password");
+ ThrowUserError("invalid_username_or_password");
}
# The account may be disabled
-expires => "Tue, 15-Sep-1998 21:49:00 GMT");
# and throw a user error
- &::ThrowUserError("account_disabled",
- {'disabled_reason' => $extra});
+ ThrowUserError("account_disabled",
+ {'disabled_reason' => $extra});
}
# If we get here, then we've run out of options, which shouldn't happen
- &::ThrowCodeError("authres_unhandled",
- { authres => $authres,
- type => $type,
- }
- );
+ ThrowCodeError("authres_unhandled",
+ { authres => $authres,
+ type => $type,
+ }
+ );
}
#
# Contributor(s): Bradley Baetz <bbaetz@acm.org>
-use strict;
-
package Bugzilla::Error;
+use strict;
use base qw(Exporter);
-@Bugzilla::Error::EXPORT = qw(ThrowUserError);
+@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
-sub ThrowUserError {
- my ($error, $vars, $unlock_tables) = @_;
+use Bugzilla::Config;
+use Bugzilla::Util;
+
+sub _throw_error {
+ my ($name, $error, $vars, $unlock_tables) = @_;
$vars ||= {};
print Bugzilla->cgi->header();
my $template = Bugzilla->template;
- $template->process("global/user-error.html.tmpl", $vars)
- || &::ThrowTemplateError($template->error());
+ $template->process($name, $vars)
+ || ThrowTemplateError($template->error());
exit;
}
+sub ThrowUserError {
+ _throw_error("global/user-error.html.tmpl", @_);
+}
+
+sub ThrowCodeError {
+ _throw_error("global/code-error.html.tmpl", @_);
+}
+
+sub ThrowTemplateError {
+ my ($template_err) = @_;
+
+ my $vars = {};
+
+ $vars->{'template_error_msg'} = $template_err;
+ $vars->{'error'} = "template_error";
+
+ my $template = Bugzilla->template;
+
+ # Try a template first; but if this one fails too, fall back
+ # on plain old print statements.
+ if (!$template->process("global/code-error.html.tmpl", $vars)) {
+ my $maintainer = Param('maintainer');
+ my $error = html_quote($vars->{'template_error_msg'});
+ my $error2 = html_quote($template->error());
+ print <<END;
+ <tt>
+ <p>
+ Bugzilla has suffered an internal error. Please save this page and
+ send it to $maintainer with details of what you were doing at the
+ time this message appeared.
+ </p>
+ <script type="text/javascript"> <!--
+ document.write("<p>URL: " + document.location + "</p>");
+ // -->
+ </script>
+ <p>Template->process() failed twice.<br>
+ First error: $error<br>
+ Second error: $error2</p>
+ </tt>
+END
+ }
+ exit;
+}
+
1;
__END__
argument will go away, to be replaced by transactional C<rollback> calls. There
is no timeframe for doing so, however.
+=item C<ThrowCodeError>
+
+This function is used when an internal check detects an error of some sort.
+This usually indicates a bug in Bugzilla, although it can occur if the user
+manually constructs urls without correct parameters.
+
+This function's behaviour is similar to C<ThrowUserError>, except that the
+template used to display errors is I<global/code-error.html.tmpl>. In addition
+if the hashref used as the optional second argument contains a key I<variables>
+then the contents of the hashref (which is expected to be another hashref) will
+be displayed after the error message, as a debugging aid.
+
+=item C<ThrowTemplateError>
+
+This function should only be called if a C<template-<gt>process()> fails.
+It tries another template first, because often one template being
+broken or missing doesn't mean that they all are. But it falls back to
+a print statement as a last-ditch error.
+
=back
=head1 SEE ALSO
# Make sure the flag exists.
my $flag = get($id);
- $flag || &::ThrowCodeError("flag_nonexistent", { id => $id });
+ $flag || ThrowCodeError("flag_nonexistent", { id => $id });
# Make sure the user chose a valid status.
grep($status eq $_, qw(X + - ?))
- || &::ThrowCodeError("flag_status_invalid",
- { id => $id , status => $status });
+ || ThrowCodeError("flag_status_invalid",
+ { id => $id, status => $status });
# Make sure the user didn't request the flag unless it's requestable.
if ($status eq '?' && !$flag->{type}->{is_requestable}) {
ThrowCodeError("flag_status_invalid",
- { id => $id , status => $status });
+ { id => $id, status => $status });
}
# Make sure the requestee is authorized to access the bug.
$::template->process($template_file, $::vars, \$message);
if (!$rv) {
Bugzilla->cgi->header();
- &::ThrowTemplateError($::template->error());
+ ThrowTemplateError($::template->error());
}
my $delivery_mode = Param("sendmailnow") ? "" : "-ODeliveryMode=deferred";
# Make sure the flag type exists.
my $flag_type = get($id);
$flag_type
- || &::ThrowCodeError("flag_type_nonexistent", { id => $id });
+ || ThrowCodeError("flag_type_nonexistent", { id => $id });
# Make sure the value of the field is a valid status.
grep($status eq $_, qw(X + - ?))
- || &::ThrowCodeError("flag_status_invalid",
- { id => $id , status => $status });
-
+ || ThrowCodeError("flag_status_invalid",
+ { id => $id , status => $status });
+
# Make sure the user didn't request the flag unless it's requestable.
if ($status eq '?' && !$flag_type->{is_requestable}) {
ThrowCodeError("flag_status_invalid",
# chart -1 is generated by other code above, not from the user-
# submitted form, so we'll blindly accept any values in chart -1
if ((!$chartfields{$f}) && ($chart != -1)) {
- &::ThrowCodeError("invalid_field_name", {field => $f});
+ ThrowCodeError("invalid_field_name", {field => $f});
}
# This is either from the internal chart (in which case we
}
else {
# This field and this type don't work together.
- $::vars->{'field'} = $params->param("field$chart-$row-$col");
- $::vars->{'type'} = $params->param("type$chart-$row-$col");
- &::ThrowCodeError("field_type_mismatch");
+ ThrowCodeError("field_type_mismatch",
+ { field => $params->param("field$chart-$row-$col"),
+ type => $params->param("type$chart-$row-$col"),
+ });
}
}
if (@orlist) {
package Token;
use Bugzilla::Config;
+use Bugzilla::Error;
use Date::Format;
my $message;
$template->process("account/email/change-old.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
$message = "";
$template->process("account/email/change-new.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
my $message = "";
$template->process("account/password/forgotten-password.txt.tmpl",
$vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
++$tries;
if ($tries > 100) {
- &::ThrowCodeError("token_generation_error");
+ ThrowCodeError("token_generation_error");
}
$token = &::GenerateRandomPassword();
my $message;
$template->process("account/cancel-token.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
package Bugzilla::User;
use Bugzilla::Config;
+use Bugzilla::Error;
use Bugzilla::Util;
################################################################################
}
else {
# bad argument
- $vars->{'argument'} = $fields->{$field}->{'type'};
- $vars->{'function'} = 'Bugzilla::User::match_field';
- &::ThrowCodeError('bad_arg');
+ ThrowCodeError('bad_arg',
+ { argument => $fields->{$field}->{'type'},
+ function => 'Bugzilla::User::match_field',
+ });
}
for my $query (@queries) {
print Bugzilla->cgi->header();
$::template->process("global/confirm-user-match.html.tmpl", $vars)
- || &::ThrowTemplateError($::template->error());
+ || ThrowTemplateError($::template->error());
exit;
SendSQL("SELECT description FROM fielddefs WHERE name=" . SqlQuote($fieldname));
my $result = FetchOneColumn();
+ my $field;
if ($result) {
- $vars->{'field'} = $result;
+ $field = $result;
}
else {
- $vars->{'field'} = $fieldname;
+ $field = $fieldname;
}
- ThrowCodeError("illegal_field", undef, "abort");
+ ThrowCodeError("illegal_field", { field => $field }, "abort");
}
}
) = @_;
if (!defined $formRef->{$fieldname}) {
- $vars->{'field'} = $fieldname;
- ThrowCodeError("undefined_field");
+ ThrowCodeError("undefined_field", { field => $fieldname });
}
}
|| ThrowTemplateError($::template->error());
}
-###############################################################################
-# Error handling
-#
-# If you are doing incremental output, set $vars->{'header_done'} once you've
-# done the header.
-#
-# You can call Throw*Error with extra template variables in one pass by using
-# the $extra_vars hash reference parameter:
-# ThrowUserError("some_tag", { bug_id => $bug_id, size => 127 });
-###############################################################################
-
-# For "this shouldn't happen"-type places in the code.
-# The contents of $extra_vars get printed out in the template - useful for
-# debugging info.
-sub ThrowCodeError {
- ($vars->{'error'}, my $extra_vars, my $unlock_tables) = (@_);
-
- SendSQL("UNLOCK TABLES") if $unlock_tables;
-
- # If we don't have this test here, then the %@extra_vars vivifies
- # the hashref, and then setting $vars->{'variables'} uses an empty hashref
- # so the error template prints out a bogus header for the empty hash
- if (defined $extra_vars) {
- # Copy the extra_vars into the vars hash
- foreach my $var (keys %$extra_vars) {
- $vars->{$var} = $extra_vars->{$var};
- }
-
- # We may one day log something to file here also.
- $vars->{'variables'} = $extra_vars;
- }
-
- print Bugzilla->cgi->header();
- $template->process("global/code-error.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
-
- exit;
-}
-
-# This function should only be called if a template->process() fails.
-# It tries another template first, because often one template being
-# broken or missing doesn't mean that they all are. But it falls back on
-# a print statement.
-# The Content-Type will already have been printed.
-sub ThrowTemplateError {
- ($vars->{'template_error_msg'}) = (@_);
- $vars->{'error'} = "template_error";
-
- # Try a template first; but if this one fails too, fall back
- # on plain old print statements.
- if (!$template->process("global/code-error.html.tmpl", $vars)) {
- my $maintainer = Param('maintainer');
- my $error = html_quote($vars->{'template_error_msg'});
- my $error2 = html_quote($template->error());
- print <<END;
- <tt>
- <p>
- Bugzilla has suffered an internal error. Please save this page and
- send it to $maintainer with details of what you were doing at the
- time this message appeared.
- </p>
- <script type="text/javascript"> <!--
- document.write("<p>URL: " + document.location + "</p>");
- // -->
- </script>
- <p>Template->process() failed twice.<br>
- First error: $error<br>
- Second error: $error2</p>
- </tt>
-END
- }
-
- exit;
-}
-
sub CheckIfVotedConfirmed {
my ($id, $who) = (@_);
SendSQL("SELECT bugs.votes, bugs.bug_status, products.votestoconfirm, " .
package Token;
use Bugzilla::Config;
+use Bugzilla::Error;
use Date::Format;
my $message;
$template->process("account/email/change-old.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
$message = "";
$template->process("account/email/change-new.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
my $message = "";
$template->process("account/password/forgotten-password.txt.tmpl",
$vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
++$tries;
if ($tries > 100) {
- &::ThrowCodeError("token_generation_error");
+ ThrowCodeError("token_generation_error");
}
$token = &::GenerateRandomPassword();
my $message;
$template->process("account/cancel-token.txt.tmpl", $vars, \$message)
- || &::ThrowTemplateError($template->error());
+ || ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
}
else
{
- ThrowCodeError("unknown_action");
+ ThrowCodeError("unknown_action", { action => $action });
}
exit;
}
else
{
- $vars->{'contenttypemethod'} = $::FORM{'contenttypemethod'};
- ThrowCodeError("illegal_content_type_method");
+ ThrowCodeError("illegal_content_type_method",
+ { contenttypemethod => $::FORM{'contenttypemethod'} });
}
if ( $::FORM{'contenttype'} !~ /^(application|audio|image|message|model|multipart|text|video)\/.+$/ )
# Make sure the attachment id is valid and the user has permissions to view
# the bug to which it is attached.
foreach my $attachid (@{$::MFORM{'obsolete'}}) {
- # my $vars after ThrowCodeError is updated to not use the global
- # vars hash
-
+ my $vars = {};
$vars->{'attach_id'} = $attachid;
detaint_natural($attachid)
- || ThrowCodeError("invalid_attach_id_to_obsolete");
+ || ThrowCodeError("invalid_attach_id_to_obsolete", $vars);
SendSQL("SELECT bug_id, isobsolete, description
FROM attachments WHERE attach_id = $attachid");
{
$vars->{'my_bug_id'} = $::FORM{'bugid'};
$vars->{'attach_bug_id'} = $bugid;
- ThrowCodeError("mismatched_bug_ids_on_obsolete");
+ ThrowCodeError("mismatched_bug_ids_on_obsolete", $vars);
}
if ( $isobsolete )
{
- ThrowCodeError("attachment_already_obsolete");
+ ThrowCodeError("attachment_already_obsolete", $vars);
}
# Check that the user can modify this attachment
# Accept an order fragment matching a column name, with
# asc|desc optionally following (to specify the direction)
if (!grep($fragment =~ /^\Q$_\E(\s+(asc|desc))?$/, @columnnames)) {
- $vars->{'fragment'} = $fragment;
+ my $vars = { fragment => $fragment };
if ($order_from_cookie) {
$cgi->send_cookie(-name => 'LASTORDER',
-expires => 'Tue, 15-Sep-1998 21:49:00 GMT');
- ThrowCodeError("invalid_column_name_cookie");
+ ThrowCodeError("invalid_column_name_cookie", $vars);
}
else {
- ThrowCodeError("invalid_column_name_form");
+ ThrowCodeError("invalid_column_name_form", $vars);
}
}
}
my $bug = new Bug($id, $::userid);
$vars->{'bug'} = $bug;
-ThrowCodeError("bug_error") if $bug->error;
+ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
$vars->{'sentmail'} = [];
last SWITCH;
};
-
- $vars->{'action'} = $::FORM{'knob'};
- ThrowCodeError("unknown_action");
+
+ ThrowCodeError("unknown_action", { action => $::FORM{'knob'} });
}
if ($next_bug) {
if (detaint_natural($next_bug) && CanSeeBug($next_bug, $::userid)) {
my $bug = new Bug($next_bug, $::userid);
- $vars->{'bug'} = $bug;
- ThrowCodeError("bug_error") if $bug->error;
+ ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
$template->process("bug/process/next.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
push(@criteria, "bugs.component_id = $component_id");
push(@excluded_columns, 'component') unless $::FORM{'do_union'};
}
- else { ThrowCodeError("unknown_component", { %::FORM }) }
+ else { ThrowCodeError("unknown_component", { component => $::FORM{component} }) }
}
}
- else { ThrowCodeError("unknown_product", { %::FORM }) }
+ else { ThrowCodeError("unknown_product", { product => $::FORM{product} }) }
}
# Filter results by flag types.
return if !defined($::FORM{'status'});
grep($::FORM{'status'} eq $_, qw(? +- + - all))
- || ThrowCodeError("flag_status_invalid", { status => $::FORM{'status'} });
+ || ThrowCodeError("flag_status_invalid",
+ { status => $::FORM{'status'} });
}
sub validateGroup {
[% error_message = BLOCK %]
[% IF error == "action_unrecognized" %]
- I don't recognize the value (<em>[% variables.action FILTER html %]</em>)
+ I don't recognize the value (<em>[% action FILTER html %]</em>)
of the <em>action</em> variable.
[% ELSIF error == "attachment_already_obsolete" %]
Charts will not work without the GD Perl module being installed.
Run checksetup.pl for installation instructions.
- [% ELSIF error == "group_bit_invalid" %]
- One of the group bits submitted was invalid.
-
[% ELSIF error == "illegal_content_type_method" %]
Your form submission got corrupted somehow. The <em>content
method</em> field, which specifies how the content type gets determined,
[% terms.bug %] [%+ my_bug_id FILTER html %].
[% ELSIF error == "flag_nonexistent" %]
- There is no flag with ID #[% variables.id FILTER html %].
+ There is no flag with ID #[% id FILTER html %].
[% ELSIF error == "flag_status_invalid" %]
- The flag status <em>[% variables.status FILTER html %]</em> is invalid.
+ The flag status <em>[% status FILTER html %]</em>
+ [% IF id %]
+ for flag ID #[% id FILTER html %]
+ [% END %]
+ is invalid.
[% ELSIF error == "flag_type_component_nonexistent" %]
- The component <em>[% variables.component FILTER html %]</em> does not exist
- in the product <em>[% variables.product FILTER html %]</em>.
+ The component <em>[% component FILTER html %]</em> does not exist
+ in the product <em>[% product FILTER html %]</em>.
[% ELSIF error == "flag_type_component_without_product" %]
A component was selected without a product being selected.
[% ELSIF error == "flag_type_id_invalid" %]
- The flag type ID <em>[% variables.id FILTER html %]</em> is not
+ The flag type ID <em>[% id FILTER html %]</em> is not
a positive integer.
[% ELSIF error == "flag_type_nonexistent" %]
- There is no flag type with the ID <em>[% variables.id FILTER html %]</em>.
+ There is no flag type with the ID <em>[% id FILTER html %]</em>.
[% ELSIF error == "flag_type_product_nonexistent" %]
- The product <em>[% variables.product FILTER html %]</em> does not exist.
+ The product <em>[% product FILTER html %]</em> does not exist.
[% ELSIF error == "flag_type_target_type_invalid" %]
The target type was neither <em>[% terms.bug %]</em> nor <em>attachment</em>
[% ELSIF error == "invalid_field_name" %]
Can't use [% field FILTER html %] as a field name.
- [% ELSIF error == "invalid_output_type" %]
- [% title = "Invalid Output Type" %]
- Invalid output type [% type FILTER html %].
-
[% ELSIF error == "missing_bug_id" %]
No [% terms.bug %] ID was given.
The group field <em>[% group FILTER html %]</em> is invalid.
[% ELSIF error == "report_axis_invalid" %]
- <em>[% variables.val FILTER html %]</em> is not a valid value for
- [%+ IF variables.fld == "x" %]the horizontal axis
- [%+ ELSIF variables.fld == "y" %]the vertical axis
- [%+ ELSIF variables.fld == "z" %]the multiple tables/images
+ <em>[% val FILTER html %]</em> is not a valid value for
+ [%+ IF fld == "x" %]the horizontal axis
+ [%+ ELSIF fld == "y" %]the vertical axis
+ [%+ ELSIF fld == "z" %]the multiple tables/images
[%+ ELSE %]a report axis[% END %] field.
[% ELSIF error == "token_generation_error" %]
[% ELSIF error == "unknown_component" %]
[% title = "Unknown Component" %]
- There is no component named <em>[% variables.component FILTER html %]</em>.
+ There is no component named <em>[% component FILTER html %]</em>.
[% ELSIF error == "unknown_product" %]
[% title = "Unknown Product" %]
- There is no product named <em>[% variables.product FILTER html %]</em>.
+ There is no product named <em>[% product FILTER html %]</em>.
[% ELSE %]
- [%# Give sensible error if error functions are used incorrectly.
- #%]
- You are using [% terms.Bugzilla %]'s ThrowCodeError() function incorrectly.
- You passed in the string '[% error FILTER html %]'. The correct use is to
- pass in a tag, and define that tag in the file code-error.html.tmpl.<br>
- <br>
- If you are a [% terms.Bugzilla %] end-user seeing this message, please save this
- page and send it to [% Param('maintainer') %].
+ [% title = "Internal error" %]
+ An internal error has occured, but [% terms.Bugzilla %] doesn't know
+ what <code>[% error FILTER html %]</code> means.
+
+ If you are a [% terms.Bugzilla %] end-user seeing this message, please save
+ this page and send it to [% Param('maintainer') %].
[% END %]
[% END %]
# If the action that the user wants to take (specified in the "a" form field)
# is none of the above listed actions, display an error telling the user
# that we do not understand what they would like to do.
- ThrowCodeError("unknown_action");
+ ThrowCodeError("unknown_action", { action => $::action });
}
exit;