aboutsummaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/Bug.pm14
-rw-r--r--Bugzilla/BugMail.pm4
-rw-r--r--Bugzilla/CGI.pm5
-rw-r--r--Bugzilla/Component.pm5
-rw-r--r--Bugzilla/DB/Schema/Mysql.pm2
-rw-r--r--Bugzilla/MIME.pm17
-rw-r--r--Bugzilla/Search.pm3
-rw-r--r--Bugzilla/Template.pm23
-rw-r--r--Bugzilla/Util.pm4
-rw-r--r--Bugzilla/WebService/Bug.pm4
-rw-r--r--Bugzilla/WebService/Constants.pm2
-rw-r--r--Bugzilla/WebService/Util.pm12
12 files changed, 51 insertions, 44 deletions
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
index 34bf95ff7..8b4493f85 100644
--- a/Bugzilla/Bug.pm
+++ b/Bugzilla/Bug.pm
@@ -305,15 +305,15 @@ sub new {
my $param = shift;
# Remove leading "#" mark if we've just been passed an id.
- if (!ref $param && $param =~ /^#(\d+)$/) {
+ if (!ref $param && $param =~ /^#([0-9]+)$/) {
$param = $1;
}
# If we get something that looks like a word (not a number),
# make it the "name" param.
if (!defined $param
- || (!ref($param) && $param !~ /^\d+$/)
- || (ref($param) && $param->{id} !~ /^\d+$/))
+ || (!ref($param) && $param !~ /^[0-9]+$/)
+ || (ref($param) && $param->{id} !~ /^[0-9]+$/))
{
if ($param) {
my $alias = ref($param) ? $param->{id} : $param;
@@ -556,15 +556,15 @@ sub _extract_bug_ids {
my $s = $comment->already_wrapped ? qr/\s/ : qr/\h/;
my $text = $comment->body;
# Full bug links
- push @bug_ids, $text =~ /\b$urlbase_re\Qshow_bug.cgi?id=\E(\d+)(?:\#c\d+)?/g;
+ push @bug_ids, $text =~ /\b$urlbase_re\Qshow_bug.cgi?id=\E([0-9]+)(?:\#c[0-9]+)?/g;
# bug X
- my $bug_re = qr/\Q$bug_word\E$s*\#?$s*(\d+)/i;
+ my $bug_re = qr/\Q$bug_word\E$s*\#?$s*([0-9]+)/i;
push @bug_ids, $text =~ /\b$bug_re/g;
# bugs X, Y, Z
- my $bugs_re = qr/\Q$bugs_word\E$s*\#?$s*(\d+)(?:$s*,$s*\#?$s*(\d+))+/i;
+ my $bugs_re = qr/\Q$bugs_word\E$s*\#?$s*([0-9]+)(?:$s*,$s*\#?$s*([0-9]+))+/i;
push @bug_ids, $text =~ /\b$bugs_re/g;
# Old duplicate markers
- push @bug_ids, $text =~ /(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ )(\d+)(?=\ \*\*\*\Z)/;
+ push @bug_ids, $text =~ /(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ )([0-9]+)(?=\ \*\*\*\Z)/;
}
# Make sure to filter invalid bug IDs.
@bug_ids = grep { $_ < MAX_INT_32 } @bug_ids;
diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm
index d4a1597ab..110a1ffaf 100644
--- a/Bugzilla/BugMail.pm
+++ b/Bugzilla/BugMail.pm
@@ -169,8 +169,8 @@ sub Send {
}
if ($change->{field_name} eq 'dependson' || $change->{field_name} eq 'blocked') {
- push @referenced_bug_ids, split(/[\s,]+/, $change->{old});
- push @referenced_bug_ids, split(/[\s,]+/, $change->{new});
+ push @referenced_bug_ids, split(/[\s,]+/, $change->{old} // '');
+ push @referenced_bug_ids, split(/[\s,]+/, $change->{new} // '');
}
}
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm
index 0b8a48697..44c089a20 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -66,7 +66,7 @@ sub new {
# else we will be redirected outside Bugzilla.
my $script_name = $self->script_name;
$path_info =~ s/^\Q$script_name\E//;
- if ($path_info) {
+ if ($script_name && $path_info) {
print $self->redirect($self->url(-path => 0, -query => 1));
}
}
@@ -283,7 +283,7 @@ sub close_standby_message {
print $self->multipart_end();
print $self->multipart_start(-type => $contenttype);
}
- else {
+ elsif (!$self->{_header_done}) {
print $self->header($contenttype);
}
}
@@ -356,6 +356,7 @@ sub header {
Bugzilla::Hook::process('cgi_headers',
{ cgi => $self, headers => \%headers }
);
+ $self->{_header_done} = 1;
return $self->SUPER::header(%headers) || "";
}
diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm
index 9bc0a4493..d5a6ece5d 100644
--- a/Bugzilla/Component.pm
+++ b/Bugzilla/Component.pm
@@ -148,7 +148,8 @@ sub remove_from_db {
$dbh->bz_start_transaction();
# Products must have at least one component.
- if (scalar(@{$self->product->components}) == 1) {
+ my @components = @{ $self->product->components };
+ if (scalar(@components) == 1) {
ThrowUserError('component_is_last', { comp => $self });
}
@@ -165,6 +166,8 @@ sub remove_from_db {
ThrowUserError('component_has_bugs', {nb => $self->bug_count});
}
}
+ # Update the list of components in the product object.
+ $self->product->{components} = [grep { $_->id != $self->id } @components];
$self->SUPER::remove_from_db();
$dbh->bz_commit_transaction();
diff --git a/Bugzilla/DB/Schema/Mysql.pm b/Bugzilla/DB/Schema/Mysql.pm
index 0195fcb06..7ff8ade9f 100644
--- a/Bugzilla/DB/Schema/Mysql.pm
+++ b/Bugzilla/DB/Schema/Mysql.pm
@@ -316,7 +316,7 @@ sub column_info_to_column {
$default = 0 if $default =~ /^0\.0+$/;
# If we're not a number, we're a string and need to be
# quoted.
- $default = $dbh->quote($default) if !($default =~ /^(-)?(\d+)(.\d+)?$/);
+ $default = $dbh->quote($default) if !($default =~ /^(-)?([0-9]+)(\.[0-9]+)?$/);
$column->{DEFAULT} = $default;
}
}
diff --git a/Bugzilla/MIME.pm b/Bugzilla/MIME.pm
index 7b5843a78..8c6c141bb 100644
--- a/Bugzilla/MIME.pm
+++ b/Bugzilla/MIME.pm
@@ -13,9 +13,6 @@ use warnings;
use parent qw(Email::MIME);
-use Encode qw(encode);
-use Encode::MIME::Header;
-
sub new {
my ($class, $msg) = @_;
state $use_utf8 = Bugzilla->params->{'utf8'};
@@ -79,20 +76,12 @@ sub as_string {
# MIME-Version must be set otherwise some mailsystems ignore the charset
$self->header_set('MIME-Version', '1.0') if !$self->header('MIME-Version');
- # Encode the headers correctly in quoted-printable
+ # Encode the headers correctly.
foreach my $header ($self->header_names) {
my @values = $self->header($header);
- # We don't recode headers that happen multiple times.
- next if scalar(@values) > 1;
- if (my $value = $values[0]) {
- utf8::decode($value) unless $use_utf8 && utf8::is_utf8($value);
-
- # avoid excessive line wrapping done by Encode.
- local $Encode::Encoding{'MIME-Q'}->{'bpl'} = 998;
+ map { utf8::decode($_) if defined($_) && !utf8::is_utf8($_) } @values;
- my $encoded = encode('MIME-Q', $value);
- $self->header_set($header, $encoded);
- }
+ $self->header_str_set($header, @values);
}
# Ensure the character-set and encoding is set correctly on single part
diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm
index 0785a7e67..646f949f5 100644
--- a/Bugzilla/Search.pm
+++ b/Bugzilla/Search.pm
@@ -1628,7 +1628,8 @@ sub _special_parse_email {
my $email = trim($params->{"email$id"});
next if !$email;
my $type = $params->{"emailtype$id"} || 'anyexact';
- $type = "anyexact" if $type eq "exact";
+ # for backward compatibility
+ $type = "equals" if $type eq "exact";
my $or_clause = new Bugzilla::Search::Clause('OR');
foreach my $field (qw(assigned_to reporter cc qa_contact)) {
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index ce027171b..41b9265c6 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -232,7 +232,7 @@ sub quoteUrls {
~<a href=\"mailto:$2\">$1$2</a>~igx;
# attachment links
- $text =~ s~\b(attachment$s*\#?$s*(\d+)(?:$s+\[details\])?)
+ $text =~ s~\b(attachment$s*\#?$s*([0-9]+)(?:$s+\[details\])?)
~($things[$count++] = get_attachment_link($2, $1, $user)) &&
("\x{FDD2}" . ($count-1) . "\x{FDD3}")
~egmxi;
@@ -245,9 +245,9 @@ sub quoteUrls {
# Also, we can't use $bug_re?$comment_re? because that will match the
# empty string
my $bug_word = template_var('terms')->{bug};
- my $bug_re = qr/\Q$bug_word\E$s*\#?$s*(\d+)/i;
+ my $bug_re = qr/\Q$bug_word\E$s*\#?$s*([0-9]+)/i;
my $comment_word = template_var('terms')->{comment};
- my $comment_re = qr/(?:\Q$comment_word\E|comment)$s*\#?$s*(\d+)/i;
+ my $comment_re = qr/(?:\Q$comment_word\E|comment)$s*\#?$s*([0-9]+)/i;
$text =~ s~\b($bug_re(?:$s*,?$s*$comment_re)?|$comment_re)
~ # We have several choices. $1 here is the link, and $2-4 are set
# depending on which part matched
@@ -261,29 +261,29 @@ sub quoteUrls {
my $bugs_word = template_var('terms')->{bugs};
my $bugs_re = qr/\Q$bugs_word\E$s*\#?$s*
- \d+(?:$s*,$s*\#?$s*\d+)+/ix;
+ [0-9]+(?:$s*,$s*\#?$s*[0-9]+)+/ix;
$text =~ s{($bugs_re)}{
my $match = $1;
- $match =~ s/((?:#$s*)?(\d+))/get_bug_link($2, $1);/eg;
+ $match =~ s/((?:#$s*)?([0-9]+))/get_bug_link($2, $1);/eg;
$match;
}eg;
my $comments_word = template_var('terms')->{comments};
my $comments_re = qr/(?:comments|\Q$comments_word\E)$s*\#?$s*
- \d+(?:$s*,$s*\#?$s*\d+)+/ix;
+ [0-9]+(?:$s*,$s*\#?$s*[0-9]+)+/ix;
$text =~ s{($comments_re)}{
my $match = $1;
- $match =~ s|((?:#$s*)?(\d+))|<a href="$current_bugurl#c$2">$1</a>|g;
+ $match =~ s|((?:#$s*)?([0-9]+))|<a href="$current_bugurl#c$2">$1</a>|g;
$match;
}eg;
# Old duplicate markers. These don't use $bug_word because they are old
# and were never customizable.
$text =~ s~(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ )
- (\d+)
+ ([0-9]+)
(?=\ \*\*\*\Z)
~get_bug_link($1, $1, { user => $user })
~egmx;
@@ -865,12 +865,13 @@ sub create {
},
# In CSV, quotes are doubled, and any value containing a quote or a
- # comma is enclosed in quotes. If a field starts with an equals
- # sign, it is proceed by a space.
+ # comma is enclosed in quotes.
+ # If a field starts with either "=", "+", "-" or "@", it is preceded
+ # by a space to prevent stupid formula execution from Excel & co.
csv => sub
{
my ($var) = @_;
- $var = ' ' . $var if substr($var, 0, 1) eq '=';
+ $var = ' ' . $var if $var =~ /^[+=@-]/;
# backslash is not special to CSV, but it can be used to confuse some browsers...
# so we do not allow it to happen. We only do this for logged-in users.
$var =~ s/\\/\x{FF3C}/g if Bugzilla->user->id;
diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm
index 037b38648..bbf4261ca 100644
--- a/Bugzilla/Util.pm
+++ b/Bugzilla/Util.pm
@@ -49,13 +49,13 @@ sub trick_taint {
}
sub detaint_natural {
- my $match = $_[0] =~ /^(\d+)$/;
+ my $match = $_[0] =~ /^([0-9]+)$/;
$_[0] = $match ? int($1) : undef;
return (defined($_[0]));
}
sub detaint_signed {
- my $match = $_[0] =~ /^([-+]?\d+)$/;
+ my $match = $_[0] =~ /^([-+]?[0-9]+)$/;
# The "int()" call removes any leading plus sign.
$_[0] = $match ? int($1) : undef;
return (defined($_[0]));
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm
index c99651201..b07d3cb01 100644
--- a/Bugzilla/WebService/Bug.pm
+++ b/Bugzilla/WebService/Bug.pm
@@ -1133,6 +1133,10 @@ sub update_comment_tags {
{ function => 'Bug.update_comment_tags',
param => 'comment_id' });
+ ThrowCodeError('param_integer_required', { function => 'Bug.update_comment_tags',
+ param => 'comment_id' })
+ unless $comment_id =~ /^[0-9]+$/;
+
my $comment = Bugzilla::Comment->new($comment_id)
|| return [];
$comment->bug->check_is_visible();
diff --git a/Bugzilla/WebService/Constants.pm b/Bugzilla/WebService/Constants.pm
index 0bdd3517e..557a996f8 100644
--- a/Bugzilla/WebService/Constants.pm
+++ b/Bugzilla/WebService/Constants.pm
@@ -67,6 +67,8 @@ use constant WS_ERROR_CODE => {
number_too_large => 54,
number_too_small => 55,
illegal_date => 56,
+ param_integer_required => 57,
+ param_scalar_array_required => 58,
# Bug errors usually occupy the 100-200 range.
improper_bug_id_field_value => 100,
bug_id_does_not_exist => 101,
diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm
index 26a6ebbb0..a879c0e0d 100644
--- a/Bugzilla/WebService/Util.pm
+++ b/Bugzilla/WebService/Util.pm
@@ -16,6 +16,7 @@ use Bugzilla::FlagType;
use Bugzilla::Error;
use Storable qw(dclone);
+use List::MoreUtils qw(any none);
use parent qw(Exporter);
@@ -220,14 +221,19 @@ sub validate {
# $params should be.
return ($self, undef) if (defined $params and !ref $params);
+ my @id_params = qw(ids comment_ids);
# If @keys is not empty then we convert any named
# parameters that have scalar values to arrayrefs
# that match.
foreach my $key (@keys) {
if (exists $params->{$key}) {
- $params->{$key} = ref $params->{$key}
- ? $params->{$key}
- : [ $params->{$key} ];
+ $params->{$key} = [ $params->{$key} ] unless ref $params->{$key};
+
+ if (any { $key eq $_ } @id_params) {
+ my $ids = $params->{$key};
+ ThrowCodeError('param_scalar_array_required', { param => $key })
+ unless ref($ids) eq 'ARRAY' && none { ref $_ } @$ids;
+ }
}
}