50
use base qw(Bugzilla::Object Exporter);
50
use base qw(Bugzilla::Object Exporter);
51
@Bugzilla::Bug::EXPORT = qw(
51
@Bugzilla::Bug::EXPORT = qw(
52
bug_alias_to_id ValidateBugID
52
bug_alias_to_id
53
RemoveVotes CheckIfVotedConfirmed
53
RemoveVotes CheckIfVotedConfirmed
54
LogActivityEntry
54
LogActivityEntry
55
editable_bug_fields
55
editable_bug_fields
1091
my @bug_ids = split(/[\s,]+/, $deps_in{$type});
1091
my @bug_ids = split(/[\s,]+/, $deps_in{$type});
1092
# Eliminate nulls.
1092
# Eliminate nulls.
1093
@bug_ids = grep {$_} @bug_ids;
1093
@bug_ids = grep {$_} @bug_ids;
1094
# We do Validate up here to make sure all aliases are converted to IDs.
1094
# We do this up here to make sure all aliases are converted to IDs.
1095
ValidateBugID($_, $type) foreach @bug_ids;
1095
@bug_ids = map { $invocant->check($_, $type)->id } @bug_ids;
1097
my @check_access = @bug_ids;
1097
my @check_access = @bug_ids;
1098
# When we're updating a bug, only added or removed bug_ids are
1098
# When we're updating a bug, only added or removed bug_ids are
1115
my $user = Bugzilla->user;
1115
my $user = Bugzilla->user;
1116
foreach my $modified_id (@check_access) {
1116
foreach my $modified_id (@check_access) {
1117
ValidateBugID($modified_id);
1117
my $delta_bug = $invocant->check($modified_id);
1118
# Under strict isolation, you can't modify a bug if you can't
1118
# Under strict isolation, you can't modify a bug if you can't
1119
# edit it, even if you can see it.
1119
# edit it, even if you can see it.
1120
if (Bugzilla->params->{"strict_isolation"}) {
1120
if (Bugzilla->params->{"strict_isolation"}) {
1121
my $delta_bug = new Bugzilla::Bug($modified_id);
1122
if (!$user->can_edit_product($delta_bug->{'product_id'})) {
1121
if (!$user->can_edit_product($delta_bug->{'product_id'})) {
1123
ThrowUserError("illegal_change_deps", {field => $type});
1122
ThrowUserError("illegal_change_deps", {field => $type});
1142
$dupe_of = trim($dupe_of);
1141
$dupe_of = trim($dupe_of);
1143
$dupe_of || ThrowCodeError('undefined_field', { field => 'dup_id' });
1142
$dupe_of || ThrowCodeError('undefined_field', { field => 'dup_id' });
1144
# Make sure we can change the original bug (issue A on bug 96085)
1143
# Make sure we can change the original bug (issue A on bug 96085)
1145
ValidateBugID($dupe_of, 'dup_id');
1144
my $dupe_of_bug = $self->check($dupe_of, 'dup_id');
1147
# Make sure a loop isn't created when marking this bug
1146
# Make sure a loop isn't created when marking this bug
1148
# as duplicate.
1147
# as duplicate.
1174
# Should we add the reporter to the CC list of the new bug?
1173
# Should we add the reporter to the CC list of the new bug?
1175
# If he can see the bug...
1174
# If he can see the bug...
1176
if ($self->reporter->can_see_bug($dupe_of)) {
1175
if ($self->reporter->can_see_bug($dupe_of)) {
1177
my $dupe_of_bug = new Bugzilla::Bug($dupe_of);
1178
# We only add him if he's not the reporter of the other bug.
1176
# We only add him if he's not the reporter of the other bug.
1179
$self->{_add_dup_cc} = 1
1177
$self->{_add_dup_cc} = 1
1180
if $dupe_of_bug->reporter->id != $self->reporter->id;
1178
if $dupe_of_bug->reporter->id != $self->reporter->id;
1199
my $vars = {};
1197
my $vars = {};
1200
my $template = Bugzilla->template;
1198
my $template = Bugzilla->template;
1201
# Ask the user what they want to do about the reporter.
1199
# Ask the user what they want to do about the reporter.
1202
$vars->{'cclist_accessible'} = $dbh->selectrow_array(
1200
$vars->{'cclist_accessible'} = $dupe_of_bug->cclist_accessible;
1203
q{SELECT cclist_accessible FROM bugs WHERE bug_id = ?},
1205
$vars->{'original_bug_id'} = $dupe_of;
1201
$vars->{'original_bug_id'} = $dupe_of;
1206
$vars->{'duplicate_bug_id'} = $self->id;
1202
$vars->{'duplicate_bug_id'} = $self->id;
1207
print $cgi->header();
1203
print $cgi->header();
123
my @return;
123
my @return;
124
foreach my $bug_id (@$ids) {
124
foreach my $bug_id (@$ids) {
125
my %item;
125
my %item;
126
ValidateBugID($bug_id);
126
my $bug = Bugzilla::Bug->check($bug_id);
128
my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id);
129
my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id);
129
$item{$bug_id} = [];
130
$item{$bug_id} = [];
155
# alias is returned in case users passes a mixture of ids and aliases
156
# alias is returned in case users passes a mixture of ids and aliases
156
# then they get to know which bug activity relates to which value
157
# then they get to know which bug activity relates to which value
157
# they passed
158
# they passed
158
my $bug = new Bugzilla::Bug($bug_id);
159
if (Bugzilla->params->{'usebugaliases'}) {
159
if (Bugzilla->params->{'usebugaliases'}) {
160
$item{alias} = type('string')->value($bug->alias);
160
$item{alias} = type('string')->value($bug->alias);
165
|| ThrowUserError("invalid_attach_id", { attach_id => $attach_id });
165
|| ThrowUserError("invalid_attach_id", { attach_id => $attach_id });
167
# Make sure the user is authorized to access this attachment's bug.
167
# Make sure the user is authorized to access this attachment's bug.
168
ValidateBugID($attachment->bug_id);
168
Bugzilla::Bug->check($attachment->bug_id);
169
if ($attachment->isprivate && $user->id != $attachment->attacher->id && !$user->is_insider) {
169
if ($attachment->isprivate && $user->id != $attachment->attacher->id
170
&& !$user->is_insider)
170
ThrowUserError('auth_failure', {action => 'access',
172
ThrowUserError('auth_failure', {action => 'access',
171
object => 'attachment'});
173
object => 'attachment'});
281
# HTML page.
283
# HTML page.
282
sub viewall {
284
sub viewall {
283
# Retrieve and validate parameters
285
# Retrieve and validate parameters
284
my $bugid = $cgi->param('bugid');
286
my $bug = Bugzilla::Bug->check(scalar $cgi->param('bugid'));
285
ValidateBugID($bugid);
287
my $bugid = $bug->id;
286
my $bug = new Bugzilla::Bug($bugid);
288
my $attachments = Bugzilla::Attachment->get_attachments_by_bug($bugid);
289
my $attachments = Bugzilla::Attachment->get_attachments_by_bug($bugid);
301
# Display a form for entering a new attachment.
302
# Display a form for entering a new attachment.
302
sub enter {
303
sub enter {
303
# Retrieve and validate parameters
304
# Retrieve and validate parameters
304
my $bugid = $cgi->param('bugid');
305
my $bug = Bugzilla::Bug->check(scalar $cgi->param('bugid'));
305
ValidateBugID($bugid);
306
my $bugid = $bug->id;
306
validateCanChangeBug($bugid);
307
validateCanChangeBug($bugid);
307
my $dbh = Bugzilla->dbh;
308
my $dbh = Bugzilla->dbh;
308
my $user = Bugzilla->user;
309
my $user = Bugzilla->user;
310
my $bug = new Bugzilla::Bug($bugid, $user->id);
311
# Retrieve the attachments the user can edit from the database and write
311
# Retrieve the attachments the user can edit from the database and write
312
# them into an array of hashes where each hash represents one attachment.
312
# them into an array of hashes where each hash represents one attachment.
313
my $canEdit = "";
313
my $canEdit = "";
344
$dbh->bz_start_transaction;
344
$dbh->bz_start_transaction;
346
# Retrieve and validate parameters
346
# Retrieve and validate parameters
347
my $bugid = $cgi->param('bugid');
347
my $bug = Bugzilla::Bug->check(scalar $cgi->param('bugid'));
348
ValidateBugID($bugid);
348
my $bugid = $bug->id;
349
validateCanChangeBug($bugid);
349
validateCanChangeBug($bugid);
350
my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
350
my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
376
my $bug = new Bugzilla::Bug($bugid);
377
my $attachment =
376
my $attachment =
378
Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR, $bug, $user,
377
Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR, $bug, $user,
379
$timestamp, $vars);
378
$timestamp, $vars);
112
# Create a list of objects for all bugs being modified in this request.
112
# Create a list of objects for all bugs being modified in this request.
113
my @bug_objects;
113
my @bug_objects;
114
if (defined $cgi->param('id')) {
114
if (defined $cgi->param('id')) {
115
my $id = $cgi->param('id');
115
my $bug = Bugzilla::Bug->check(scalar $cgi->param('id'));
116
ValidateBugID($id);
116
$cgi->param('id', $bug->id);
117
117
push(@bug_objects, $bug);
118
# Store the validated, and detainted id back in the cgi data, as
119
# lots of later code will need it, and will obtain it from there
120
$cgi->param('id', $id);
121
push(@bug_objects, new Bugzilla::Bug($id));
122
} else {
118
} else {
124
foreach my $i ($cgi->param()) {
119
foreach my $i ($cgi->param()) {
125
if ($i =~ /^id_([1-9][0-9]*)/) {
120
if ($i =~ /^id_([1-9][0-9]*)/) {
126
my $id = $1;
121
my $id = $1;
127
ValidateBugID($id);
122
push(@bug_objects, Bugzilla::Bug->check($id));
131
@bug_objects = @{Bugzilla::Bug->new_from_list(\@ids)};
134
# Make sure there are bugs to process.
127
# Make sure there are bugs to process.
44
# Make sure the bug ID is a positive integer representing an existing
44
# Make sure the bug ID is a positive integer representing an existing
45
# bug that the user is authorized to access.
45
# bug that the user is authorized to access.
46
my $bug_id = $cgi->param('id');
46
my $id = $cgi->param('id');
47
ValidateBugID($bug_id);
47
my $bug = Bugzilla::Bug->check($id);
49
###############################################################################
49
###############################################################################
50
# End Data/Security Validation
50
# End Data/Security Validation
51
###############################################################################
51
###############################################################################
53
($vars->{'operations'}, $vars->{'incomplete_data'}) =
53
($vars->{'operations'}, $vars->{'incomplete_data'}) =
54
Bugzilla::Bug::GetBugActivity($bug_id);
54
Bugzilla::Bug::GetBugActivity($bug->id);
56
$vars->{'bug'} = new Bugzilla::Bug($bug_id);
56
$vars->{'bug'} = $bug;
58
print $cgi->header();
58
print $cgi->header();
58
if ($single) {
58
if ($single) {
59
my $id = $cgi->param('id');
59
my $id = $cgi->param('id');
60
# Its a bit silly to do the validation twice - that functionality should
60
push @bugs, Bugzilla::Bug->check($id);
61
# probably move into Bug.pm at some point
63
push @bugs, new Bugzilla::Bug($id);
64
if (defined $cgi->param('mark')) {
61
if (defined $cgi->param('mark')) {
65
foreach my $range (split ',', $cgi->param('mark')) {
62
foreach my $range (split ',', $cgi->param('mark')) {
66
if ($range =~ /^(\d+)-(\d+)$/) {
63
if ($range =~ /^(\d+)-(\d+)$/) {
50
# Make sure the bug ID is a positive integer representing an existing
50
# Make sure the bug ID is a positive integer representing an existing
51
# bug that the user is authorized to access.
51
# bug that the user is authorized to access.
52
my $id = $cgi->param('id') || ThrowUserError('improper_bug_id_field_value');
52
my $bug = Bugzilla::Bug->check(scalar $cgi->param('id'));
53
ValidateBugID($id);
53
my $id = $bug->id;
54
my $current_bug = new Bugzilla::Bug($id);
56
local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0;
55
local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0;
68
# Generate the tree of bugs that this bug depends on and a list of IDs
67
# Generate the tree of bugs that this bug depends on and a list of IDs
69
# appearing in the tree.
68
# appearing in the tree.
70
my $dependson_tree = { $id => $current_bug };
69
my $dependson_tree = { $id => $bug };
71
my $dependson_ids = {};
70
my $dependson_ids = {};
72
GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids);
71
GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids);
73
$vars->{'dependson_tree'} = $dependson_tree;
72
$vars->{'dependson_tree'} = $dependson_tree;
76
# Generate the tree of bugs that this bug blocks and a list of IDs
75
# Generate the tree of bugs that this bug blocks and a list of IDs
77
# appearing in the tree.
76
# appearing in the tree.
78
my $blocked_tree = { $id => $current_bug };
77
my $blocked_tree = { $id => $bug };
79
my $blocked_ids = {};
78
my $blocked_ids = {};
80
GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids);
79
GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids);
81
$vars->{'blocked_tree'} = $blocked_tree;
80
$vars->{'blocked_tree'} = $blocked_tree;
251
object => "timetracking_summaries"});
251
object => "timetracking_summaries"});
253
my @ids = split(",", $cgi->param('id'));
253
my @ids = split(",", $cgi->param('id'));
254
map { ValidateBugID($_) } @ids;
254
@ids = map { Bugzilla::Bug->check($_)->id } @ids;
255
scalar(@ids) || ThrowUserError('no_bugs_chosen', {action => 'view'});
255
scalar(@ids) || ThrowUserError('no_bugs_chosen', {action => 'view'});
257
my $group_by = $cgi->param('group_by') || "number";
257
my $group_by = $cgi->param('group_by') || "number";
67
# Make sure the bug ID is a positive integer representing an existing
67
# Make sure the bug ID is a positive integer representing an existing
68
# bug that the user is authorized to access.
68
# bug that the user is authorized to access.
70
ValidateBugID($bug_id) if defined $bug_id;
70
if (defined $bug_id) {
71
my $bug = Bugzilla::Bug->check($bug_id);
72
################################################################################
75
################################################################################
73
# End Data/Security Validation
76
# End Data/Security Validation
247
# Call ValidateBugID on each bug ID to make sure it is a positive
250
# Call check() on each bug ID to make sure it is a positive
248
# integer representing an existing bug that the user is authorized
251
# integer representing an existing bug that the user is authorized
249
# to access, and make sure the number of votes submitted is also
252
# to access, and make sure the number of votes submitted is also
250
# a non-negative integer (a series of digits not preceded by a
253
# a non-negative integer (a series of digits not preceded by a
251
# minus sign).
254
# minus sign).
252
my %votes;
255
my %votes;
253
foreach my $id (@buglist) {
256
foreach my $id (@buglist) {
254
ValidateBugID($id);
257
my $bug = Bugzilla::Bug->check($id);
255
$votes{$id} = $cgi->param($id);
259
$votes{$id} = $cgi->param($id);
256
detaint_natural($votes{$id})
260
detaint_natural($votes{$id})
257
|| ThrowUserError("votes_must_be_nonnegative");
261
|| ThrowUserError("votes_must_be_nonnegative");