# If we get here, then we've run out of options, which shouldn't happen
ThrowCodeError("authres_unhandled", { authres => $authres,
- type => $type, });
+ type => $type });
}
# This auth style allows the user to log out.
# (allow negatives, though, so people can back out errors in time reporting)
if ($time !~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/) {
ThrowUserError("number_not_numeric",
- {field => "$field", num => "$time"},
- "abort");
+ {field => "$field", num => "$time"});
}
# Only the "work_time" field is allowed to contain a negative value.
if ( ($time < 0) && ($field ne "work_time") ) {
ThrowUserError("number_too_small",
- {field => "$field", num => "$time", min_num => "0"},
- "abort");
+ {field => "$field", num => "$time", min_num => "0"});
}
if ($time > 99999.99) {
ThrowUserError("number_too_large",
- {field => "$field", num => "$time", max_num => "99999.99"},
- "abort");
+ {field => "$field", num => "$time", max_num => "99999.99"});
}
}
use Date::Format;
sub _throw_error {
- my ($name, $error, $vars, $unlock_tables) = @_;
+ my ($name, $error, $vars) = @_;
$vars ||= {};
$vars->{error} = $error;
- Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT) if $unlock_tables;
+ # Make sure any locked tables are unlocked
+ # and the transaction is rolled back (if supported)
+ Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT);
# If a writable data/errorlog exists, log error details there.
if (-w "data/errorlog") {
sub ThrowTemplateError {
my ($template_err) = @_;
+ # Make sure any locked tables are unlocked
+ # and the transaction is rolled back (if supported)
+ Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT);
+
my $vars = {};
if (Bugzilla->batch) {
die("error: template error: $template_err");
ThrowUserError("error_tag",
{ foo => 'bar' });
- # supplying "abort" to ensure tables are unlocked
- ThrowUserError("another_error_tag",
- { foo => 'bar' }, 'abort');
-
=head1 DESCRIPTION
Various places throughout the Bugzilla codebase need to report errors to the
user. The C<Throw*Error> family of functions allow this to be done in a
generic and localisable manner.
+These functions automatically unlock the database tables, if there were any
+locked. They will also roll back the transaction, if it is supported by
+the underlying DB.
+
=head1 FUNCTIONS
=over 4
I<global/user-error.html.tmpl> template to format the error, using the passed
in variables as required.
-An optional third argument may be supplied. If present, the error
-handling code will unlock the database tables: it is a Bugzilla standard
-to provide the string "abort" as the argument value. In the long term,
-this 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.
$field = $fieldname;
}
- ThrowCodeError("illegal_field", { field => $field }, "abort");
+ ThrowCodeError("illegal_field", { field => $field });
}
}
my ($addr) = (@_);
my $match = Param('emailregexp');
if ($addr !~ /$match/ || $addr =~ /[\\\(\)<>&,;:"\[\] \t\r\n]/) {
- ThrowUserError("illegal_email_address", { addr => $addr }, 'abort');
+ ThrowUserError("illegal_email_address", { addr => $addr });
}
}
if ($classification ne $classificationold) {
unless ($classification) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError("classification_not_specified")
}
if (TestClassification($classification)) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError("classification_already_exists", { name => $classification });
}
$sth = $dbh->prepare("UPDATE classifications
# do we have a product?
unless ($prod) {
- ThrowUserError('product_not_specified');
+ ThrowUserError('product_not_specified');
exit;
}
if ($description ne $descriptionold) {
unless ($description) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('component_blank_description',
{'name' => $componentold});
exit;
my $initialownerid = login_to_id($initialowner);
unless ($initialownerid) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('component_need_valid_initialowner',
{'name' => $componentold});
exit;
if (Param('useqacontact') && $initialqacontact ne $initialqacontactold) {
my $initialqacontactid = login_to_id($initialqacontact);
if (!$initialqacontactid && $initialqacontact ne '') {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('component_need_valid_initialqacontact',
{'name' => $componentold});
exit;
if ($component ne $componentold) {
unless ($component) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('component_must_have_a_name',
{'name' => $componentold});
exit;
}
if (TestComponent($product, $component)) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('component_already_exists',
{'name' => $component});
exit;
# do we have a product?
unless ($product) {
- &::ThrowUserError('product_not_specified');
+ ThrowUserError('product_not_specified');
exit;
}
# Does it exist in the DB?
unless (TestProduct $product) {
- &::ThrowUserError('product_doesnt_exist',
- {'product' => $product});
+ ThrowUserError('product_doesnt_exist',
+ {'product' => $product});
exit;
}
}
my $stored_sortkey = $sortkey;
if ($sortkey != $sortkeyold) {
if (!detaint_natural($sortkey)) {
-
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('milestone_sortkey_invalid',
{'name' => $milestone,
'sortkey' => $stored_sortkey});
-
exit;
}
if ($milestone ne $milestoneold) {
unless ($milestone) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('milestone_blank_name');
exit;
}
if (TestMilestone($product, $milestone)) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('milestone_already_exists',
{'name' => $milestone,
'product' => $product});
canSeeUser($otherUserID)
|| ThrowUserError('auth_failure', {reason => "not_visible",
action => "modify",
- object => "user"},
- 'abort');
+ object => "user"});
# Cleanups
my $login = trim($cgi->param('login') || '');
if ($login ne $loginold) {
# Validate, then trick_taint.
- $login || ThrowUserError('user_login_required', undef, 'abort');
+ $login || ThrowUserError('user_login_required');
CheckEmailSyntax($login);
is_available_username($login) || ThrowUserError('account_exists',
- {'email' => $login},
- 'abort');
+ {'email' => $login});
trick_taint($login);
push(@changedFields, 'login_name');
push(@values, $login);
'whine_events WRITE');
Param('allowuserdeletion')
- || ThrowUserError('users_deletion_disabled', undef, 'abort');
+ || ThrowUserError('users_deletion_disabled');
$editusers || ThrowUserError('auth_failure',
{group => "editusers",
action => "delete",
- object => "users"},
- 'abort');
+ object => "users"});
canSeeUser($otherUserID) || ThrowUserError('auth_failure',
{reason => "not_visible",
action => "delete",
- object => "user"},
- 'abort');
+ object => "user"});
productResponsibilities($otherUserID)
- && ThrowUserError('user_has_responsibility', undef, 'abort');
+ && ThrowUserError('user_has_responsibility');
Bugzilla->logout_user_by_id($otherUserID);
if ($version ne $versionold) {
unless ($version) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('version_blank_name');
exit;
}
if (TestVersion($product,$version)) {
- $dbh->bz_unlock_tables(UNLOCK_ABORT);
ThrowUserError('version_already_exists',
{'name' => $version,
'product' => $product});
-
exit;
}
SendSQL("UPDATE bugs
my ($password, $matchpassword) = @_;
if (length($password) < 3) {
- ThrowUserError("password_too_short", undef, 'abort');
+ ThrowUserError("password_too_short");
} elsif (length($password) > 16) {
- ThrowUserError("password_too_long", undef, 'abort');
+ ThrowUserError("password_too_long");
} elsif ((defined $matchpassword) && ($password ne $matchpassword)) {
- ThrowUserError("passwords_dont_match", undef, 'abort');
+ ThrowUserError("passwords_dont_match");
}
}
return $result;
}
- ThrowUserError("invalid_username",
- { name => $name }, "abort");
+ ThrowUserError("invalid_username", { name => $name });
}
sub get_classification_id {
}
ThrowUserError("dependency_loop_multi",
- { both => $both },
- "abort");
+ { both => $both });
}
}
my $tmp = $me;
if ($::FORM{$b}) {
my $v = substr($b, 4);
$v =~ /^(\d+)$/
- || ThrowCodeError("group_id_invalid", undef, "abort");
+ || ThrowCodeError("group_id_invalid");
if (!GroupIsActive($v)) {
# Prevent the user from adding the bug to an inactive group.
# Should only happen if there is a bug in Bugzilla or the user
# hacked the "enter bug" form since otherwise the UI
# for adding the bug to the group won't appear on that form.
$vars->{'bit'} = $v;
- ThrowCodeError("inactive_group", undef, "abort");
+ ThrowCodeError("inactive_group");
}
SendSQL("SELECT user_id FROM user_group_map
WHERE user_id = $::userid
if (UserInGroup(Param('timetrackinggroup'))) {
my $wk_time = $::FORM{'work_time'};
if ($::FORM{'comment'} =~ /^\s*$/ && $wk_time && $wk_time != 0) {
- ThrowUserError('comment_required', undef, "abort");
+ ThrowUserError('comment_required');
}
}
$vars->{'newvalue'} = $::FORM{'product'};
$vars->{'field'} = 'product';
$vars->{'privs'} = $PrivilegesRequired;
- ThrowUserError("illegal_change", $vars, "abort");
+ ThrowUserError("illegal_change", $vars);
}
CheckFormField(\%::FORM, 'product', \@::legal_product);
$vars->{'field'} = $col;
}
$vars->{'privs'} = $PrivilegesRequired;
- ThrowUserError("illegal_change", $vars, "abort");
+ ThrowUserError("illegal_change", $vars);
}
}
$vars->{'newvalue'} = "no keywords";
$vars->{'field'} = "keywords";
$vars->{'privs'} = $PrivilegesRequired;
- ThrowUserError("illegal_change", $vars, "abort");
+ ThrowUserError("illegal_change", $vars);
}
$oldhash{'product'} = get_product_name($oldhash{'product_id'});
if (!CanEditProductId($oldhash{'product_id'})) {
ThrowUserError("product_edit_denied",
- { product => $oldhash{'product'} }, "abort");
+ { product => $oldhash{'product'} });
}
if (defined $::FORM{'product'}
&& $::FORM{'product'} ne $oldhash{'product'}
&& !CanEnterProduct($::FORM{'product'})) {
ThrowUserError("entry_access_denied",
- { product => $::FORM{'product'} }, "abort");
+ { product => $::FORM{'product'} });
}
if ($requiremilestone) {
# musthavemilestoneonaccept applies only if at least two
# if musthavemilestoneonaccept == 1, then the target
# milestone must be different from the default one.
if ($value eq $defaultmilestone) {
- ThrowUserError("milestone_required", { bug_id => $id }, "abort");
+ ThrowUserError("milestone_required", { bug_id => $id });
}
}
}
next if $i eq "";
if ($id eq $i) {
- ThrowUserError("dependency_loop_single", undef, "abort");
+ ThrowUserError("dependency_loop_single");
}
if (!exists $seen{$i}) {
push(@{$deptree{$target}}, $i);
}
ThrowUserError("dependency_loop_multi",
- { both => $both },
- "abort");
+ { both => $both });
}
}
my $tmp = $me;
shift @oldlist;
} else {
if ($oldlist[0] != $newlist[0]) {
+ $dbh->bz_unlock_tables(UNLOCK_ABORT);
die "Error in list comparing code";
}
shift @oldlist;