Commit afbc5586 authored by Per Cederqvist's avatar Per Cederqvist

Imported Bugzilla 3.7.3.

parent 36df5f8c
bound_location = bzr://bzr.mozilla.org/bugzilla/trunk/
bound_location = bzr://bzr.mozilla.org/bugzilla/4.0/
bound = True
7278 mkanat@bugzilla.org-20100706023555-l002tduyv4cf3m5m
7374 mkanat@bugzilla.org-20100806020703-h9auojrm6rtappjx
d12:bugzilla-1.355:cvs-1:terrynetscape.com-19980919115213-xkf0bm7hfvqeonjv12:bugzilla-2.055:cvs-1:terrynetscape.com-19980919130220-yyqg7cvetc4u27ev12:bugzilla-2.155:cvs-1:terrynetscape.com-19980919130815-hd94xua1heind9j413:bugzilla-2.1259:cvs-1:justdavesyndicomm.com-20010428023227-ol731cbzd0glvmso13:bugzilla-2.1359:cvs-1:justdavesyndicomm.com-20010428023620-119xajd3nhymuwds13:bugzilla-2.1459:cvs-1:justdavesyndicomm.com-20010830025213-pdnst2v3s3ex7ie013:bugzilla-2.1559:cvs-1:justdavesyndicomm.com-20010830044150-u287d06r0kqgyr3116:bugzilla-2.16rc159:cvs-1:justdavesyndicomm.com-20020509121930-skl1a3txbhat7lsz13:bugzilla-2.1759:cvs-1:justdavesyndicomm.com-20020511054700-tt437wzefamz9hvh15:bugzilla-2.17.159:cvs-1:justdavesyndicomm.com-20021109095922-nf3yviuff8629beo15:bugzilla-2.17.259:cvs-1:justdavesyndicomm.com-20021213193307-a9xknaet23zfj0av15:bugzilla-2.17.354:cvs-1:preedsigkill.com-20030103020409-t93lvpm9dt52eemn15:bugzilla-2.17.459:cvs-1:justdavesyndicomm.com-20030425050235-dfjx4uw2k9uy5t2r15:bugzilla-2.17.559:cvs-1:justdavesyndicomm.com-20031103113336-9wd9arv5bn6ea2fl15:bugzilla-2.17.659:cvs-1:justdavesyndicomm.com-20031110115638-zhiqa0u4xvspbzd115:bugzilla-2.17.759:cvs-1:justdavesyndicomm.com-20040303153543-rml0piewwlds25kq16:bugzilla-2.18rc158:cvs-1:justdavebugzilla.org-20040710220137-l17tsd0erfq6n1hp13:bugzilla-2.1956:cvs-1:jouniheikniemi.net-20040712005327-r1h42adxxvqin0ve15:bugzilla-2.19.158:cvs-1:justdavebugzilla.org-20041025144345-61494x108e37u6mp15:bugzilla-2.19.254:cvs-1:jakebugzilla.org-20050115194151-latmir4q2j3i0y2s15:bugzilla-2.19.353:cvs-1:mkanatkerio.com-20050512095104-fbiuqga5754y0uvq12:bugzilla-2.255:cvs-1:terrynetscape.com-19990211061152-xnol0mx2dxttxsxe16:bugzilla-2.20rc153:cvs-1:mkanatkerio.com-20050708124935-3jybt11awxwhzoaw15:bugzilla-2.21.153:cvs-1:mkanatkerio.com-20051001053552-pwb2mmob3o6qy1lq16:bugzilla-2.22rc153:cvs-1:mkanatkerio.com-20060221144757-83btrv1h6lupz7uz13:bugzilla-2.2353:cvs-1:mkanatkerio.com-20060221163312-1uxx2qnl8pfl54jl15:bugzilla-2.23.156:cvs-1:mkanatbugzilla.org-20060423094223-gnvvjsj2iy5rdhm715:bugzilla-2.23.256:cvs-1:mkanatbugzilla.org-20060710062924-wlhmsh27c8sb392115:bugzilla-2.23.356:cvs-1:mkanatbugzilla.org-20061015153415-x0uatuyjbbgf38t915:bugzilla-2.23.456:cvs-1:mkanatbugzilla.org-20070203071038-gbzf9vw4jiwfrfv412:bugzilla-2.355:cvs-1:terrynetscape.com-19990211061203-jt3e9ugcy78nis9f12:bugzilla-2.454:cvs-1:terrymozilla.org-19990501024225-3rzuwyzrie8olxyt12:bugzilla-2.554:cvs-1:terrymozilla.org-19990501024243-vl159d4szp4pue3k12:bugzilla-2.654:cvs-1:terrymozilla.org-19990831060222-roqvvbgqqxb1gria12:bugzilla-2.754:cvs-1:terrymozilla.org-19990831060252-ns4uvors39vqdomx12:bugzilla-2.854:cvs-1:terrymozilla.org-19991119235628-265ba6tg1rt646bp12:bugzilla-2.954:cvs-1:terrymozilla.org-19991119235700-ymk2rkj97d5qw2c312:bugzilla-3.156:cvs-1:mkanatbugzilla.org-20070226142137-1p56eyld0pr5bk9u14:bugzilla-3.1.156:cvs-1:mkanatbugzilla.org-20080404114815-robklj5xq3jy6dwz14:bugzilla-3.1.256:cvs-1:mkanatbugzilla.org-20070919044036-p0gzuvj4bk0ppeqe14:bugzilla-3.1.356:cvs-1:jocurisofthome.net-20080404114753-dmlkekr6evwbp3y314:bugzilla-3.1.456:cvs-1:mkanatbugzilla.org-20080505065243-jf8skvj9q72baui812:bugzilla-3.356:cvs-1:mkanatbugzilla.org-20080521010050-q28y4sk4sck7jmbh14:bugzilla-3.3.156:cvs-1:mkanatbugzilla.org-20090106073441-1mv6wgm8qklg35r614:bugzilla-3.3.256:cvs-1:mkanatbugzilla.org-20090202232733-k1stws1htew6k0j314:bugzilla-3.3.356:cvs-1:mkanatbugzilla.org-20090203100346-dm6k3pgoarpyp7g514:bugzilla-3.3.456:cvs-1:mkanatbugzilla.org-20090330234934-2ehn2qx3udn40r7r12:bugzilla-3.556:cvs-1:mkanatbugzilla.org-20090330234934-2ehn2qx3udn40r7r14:bugzilla-3.5.156:cvs-1:mkanatbugzilla.org-20091105122647-foor2xgx2agf7oba14:bugzilla-3.5.256:cvs-1:mkanatbugzilla.org-20091119021426-aowuz3a41qo2s7y014:bugzilla-3.5.351:mkanat@bugzilla.org-20100201220140-j2ew9rv9arznu2fk14:bugzilla-3.7.151:mkanat@bugzilla.org-20100624204240-d24ov96ew4bpnc0214:bugzilla-3.7.251:mkanat@bugzilla.org-20100706023555-l002tduyv4cf3m5me
\ No newline at end of file
d12:bugzilla-1.355:cvs-1:terrynetscape.com-19980919115213-xkf0bm7hfvqeonjv12:bugzilla-2.055:cvs-1:terrynetscape.com-19980919130220-yyqg7cvetc4u27ev12:bugzilla-2.155:cvs-1:terrynetscape.com-19980919130815-hd94xua1heind9j413:bugzilla-2.1259:cvs-1:justdavesyndicomm.com-20010428023227-ol731cbzd0glvmso13:bugzilla-2.1359:cvs-1:justdavesyndicomm.com-20010428023620-119xajd3nhymuwds13:bugzilla-2.1459:cvs-1:justdavesyndicomm.com-20010830025213-pdnst2v3s3ex7ie013:bugzilla-2.1559:cvs-1:justdavesyndicomm.com-20010830044150-u287d06r0kqgyr3116:bugzilla-2.16rc159:cvs-1:justdavesyndicomm.com-20020509121930-skl1a3txbhat7lsz13:bugzilla-2.1759:cvs-1:justdavesyndicomm.com-20020511054700-tt437wzefamz9hvh15:bugzilla-2.17.159:cvs-1:justdavesyndicomm.com-20021109095922-nf3yviuff8629beo15:bugzilla-2.17.259:cvs-1:justdavesyndicomm.com-20021213193307-a9xknaet23zfj0av15:bugzilla-2.17.354:cvs-1:preedsigkill.com-20030103020409-t93lvpm9dt52eemn15:bugzilla-2.17.459:cvs-1:justdavesyndicomm.com-20030425050235-dfjx4uw2k9uy5t2r15:bugzilla-2.17.559:cvs-1:justdavesyndicomm.com-20031103113336-9wd9arv5bn6ea2fl15:bugzilla-2.17.659:cvs-1:justdavesyndicomm.com-20031110115638-zhiqa0u4xvspbzd115:bugzilla-2.17.759:cvs-1:justdavesyndicomm.com-20040303153543-rml0piewwlds25kq16:bugzilla-2.18rc158:cvs-1:justdavebugzilla.org-20040710220137-l17tsd0erfq6n1hp13:bugzilla-2.1956:cvs-1:jouniheikniemi.net-20040712005327-r1h42adxxvqin0ve15:bugzilla-2.19.158:cvs-1:justdavebugzilla.org-20041025144345-61494x108e37u6mp15:bugzilla-2.19.254:cvs-1:jakebugzilla.org-20050115194151-latmir4q2j3i0y2s15:bugzilla-2.19.353:cvs-1:mkanatkerio.com-20050512095104-fbiuqga5754y0uvq12:bugzilla-2.255:cvs-1:terrynetscape.com-19990211061152-xnol0mx2dxttxsxe16:bugzilla-2.20rc153:cvs-1:mkanatkerio.com-20050708124935-3jybt11awxwhzoaw15:bugzilla-2.21.153:cvs-1:mkanatkerio.com-20051001053552-pwb2mmob3o6qy1lq16:bugzilla-2.22rc153:cvs-1:mkanatkerio.com-20060221144757-83btrv1h6lupz7uz13:bugzilla-2.2353:cvs-1:mkanatkerio.com-20060221163312-1uxx2qnl8pfl54jl15:bugzilla-2.23.156:cvs-1:mkanatbugzilla.org-20060423094223-gnvvjsj2iy5rdhm715:bugzilla-2.23.256:cvs-1:mkanatbugzilla.org-20060710062924-wlhmsh27c8sb392115:bugzilla-2.23.356:cvs-1:mkanatbugzilla.org-20061015153415-x0uatuyjbbgf38t915:bugzilla-2.23.456:cvs-1:mkanatbugzilla.org-20070203071038-gbzf9vw4jiwfrfv412:bugzilla-2.355:cvs-1:terrynetscape.com-19990211061203-jt3e9ugcy78nis9f12:bugzilla-2.454:cvs-1:terrymozilla.org-19990501024225-3rzuwyzrie8olxyt12:bugzilla-2.554:cvs-1:terrymozilla.org-19990501024243-vl159d4szp4pue3k12:bugzilla-2.654:cvs-1:terrymozilla.org-19990831060222-roqvvbgqqxb1gria12:bugzilla-2.754:cvs-1:terrymozilla.org-19990831060252-ns4uvors39vqdomx12:bugzilla-2.854:cvs-1:terrymozilla.org-19991119235628-265ba6tg1rt646bp12:bugzilla-2.954:cvs-1:terrymozilla.org-19991119235700-ymk2rkj97d5qw2c312:bugzilla-3.156:cvs-1:mkanatbugzilla.org-20070226142137-1p56eyld0pr5bk9u14:bugzilla-3.1.156:cvs-1:mkanatbugzilla.org-20080404114815-robklj5xq3jy6dwz14:bugzilla-3.1.256:cvs-1:mkanatbugzilla.org-20070919044036-p0gzuvj4bk0ppeqe14:bugzilla-3.1.356:cvs-1:jocurisofthome.net-20080404114753-dmlkekr6evwbp3y314:bugzilla-3.1.456:cvs-1:mkanatbugzilla.org-20080505065243-jf8skvj9q72baui812:bugzilla-3.356:cvs-1:mkanatbugzilla.org-20080521010050-q28y4sk4sck7jmbh14:bugzilla-3.3.156:cvs-1:mkanatbugzilla.org-20090106073441-1mv6wgm8qklg35r614:bugzilla-3.3.256:cvs-1:mkanatbugzilla.org-20090202232733-k1stws1htew6k0j314:bugzilla-3.3.356:cvs-1:mkanatbugzilla.org-20090203100346-dm6k3pgoarpyp7g514:bugzilla-3.3.456:cvs-1:mkanatbugzilla.org-20090330234934-2ehn2qx3udn40r7r12:bugzilla-3.556:cvs-1:mkanatbugzilla.org-20090330234934-2ehn2qx3udn40r7r14:bugzilla-3.5.156:cvs-1:mkanatbugzilla.org-20091105122647-foor2xgx2agf7oba14:bugzilla-3.5.256:cvs-1:mkanatbugzilla.org-20091119021426-aowuz3a41qo2s7y014:bugzilla-3.5.351:mkanat@bugzilla.org-20100201220140-j2ew9rv9arznu2fk14:bugzilla-3.7.151:mkanat@bugzilla.org-20100624204240-d24ov96ew4bpnc0214:bugzilla-3.7.251:mkanat@bugzilla.org-20100706023555-l002tduyv4cf3m5m14:bugzilla-3.7.351:mkanat@bugzilla.org-20100806020703-h9auojrm6rtappjxe
\ No newline at end of file
No preview for this file type
BZR merge-modified list format 1
file_id: bugzillaguide.xml-20080404000536-q652ye0jg2i1-19
hash: b4665ffe1a78a0cf86bd8e5c885d7bc2f1426e10
B+Tree Graph Index 2
node_ref_lists=1
key_elements=1
len=1
row_lengths=1
x} PVAhPl+cDa%,&jZ|F2ZjK$(E-mR)s(^R-hԐ ݖ7˓(
\ No newline at end of file
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=0
row_lengths=
......@@ -2,3 +2,14 @@
<FilesMatch ^(.*\.pm|.*\.pl|.*localconfig.*)$>
deny from all
</FilesMatch>
<FilesMatch (\.js|\.css)$>
ExpiresActive On
# According to RFC 2616, "1 year in the future" means "never expire".
# We change the name of the file's URL whenever its modification date
# changes, so browsers can cache any individual JS or CSS URL forever.
# However, since all JS and CSS URLs involve a ? in them (for the changing
# name) we have to explicitly set an Expires header or browsers won't
# *ever* cache them.
ExpiresDefault "now plus 1 years"
Header append Cache-Control "public"
</FilesMatch>
......@@ -51,10 +51,12 @@ use Bugzilla::Error;
use Bugzilla::Util;
use Bugzilla::Field;
use Bugzilla::Flag;
use Bugzilla::Token;
use File::Basename;
use File::Spec::Functions;
use DateTime::TimeZone;
use Date::Parse;
use Safe;
#####################################################################
......@@ -341,24 +343,37 @@ sub login {
# 3: There must be a valid value in the 'sudo' cookie
# 4: A Bugzilla::User object must exist for the given cookie value
# 5: That user must NOT be in the 'bz_sudo_protect' group
my $sudo_cookie = $class->cgi->cookie('sudo');
detaint_natural($sudo_cookie) if defined($sudo_cookie);
my $sudo_target;
$sudo_target = new Bugzilla::User($sudo_cookie) if defined($sudo_cookie);
if (defined($authenticated_user) &&
$authenticated_user->in_group('bz_sudoers') &&
defined($sudo_cookie) &&
defined($sudo_target) &&
!($sudo_target->in_group('bz_sudo_protect'))
)
{
$class->set_user($sudo_target);
$class->request_cache->{sudoer} = $authenticated_user;
# And make sure that both users have the same Auth object,
# since we never call Auth::login for the sudo target.
$sudo_target->set_authorizer($authenticated_user->authorizer);
my $token = $class->cgi->cookie('sudo');
if (defined $authenticated_user && $token) {
my ($user_id, $date, $sudo_target_id) = Bugzilla::Token::GetTokenData($token);
if (!$user_id
|| $user_id != $authenticated_user->id
|| !detaint_natural($sudo_target_id)
|| (time() - str2time($date) > MAX_SUDO_TOKEN_AGE))
{
$class->cgi->remove_cookie('sudo');
ThrowUserError('sudo_invalid_cookie');
}
my $sudo_target = new Bugzilla::User($sudo_target_id);
if ($authenticated_user->in_group('bz_sudoers')
&& defined $sudo_target
&& !$sudo_target->in_group('bz_sudo_protect'))
{
$class->set_user($sudo_target);
$class->request_cache->{sudoer} = $authenticated_user;
# And make sure that both users have the same Auth object,
# since we never call Auth::login for the sudo target.
$sudo_target->set_authorizer($authenticated_user->authorizer);
# NOTE: If you want to do any special logging, do it here.
# NOTE: If you want to do any special logging, do it here.
}
else {
delete_token($token);
$class->cgi->remove_cookie('sudo');
ThrowUserError('sudo_illegal_action', { sudoer => $authenticated_user,
target_user => $sudo_target });
}
}
else {
$class->set_user($authenticated_user);
......@@ -463,6 +478,9 @@ sub usage_mode {
elsif ($newval == USAGE_MODE_EMAIL) {
$class->error_mode(ERROR_MODE_DIE);
}
elsif ($newval == USAGE_MODE_TEST) {
$class->error_mode(ERROR_MODE_TEST);
}
else {
ThrowCodeError('usage_mode_invalid',
{'invalid_usage_mode', $newval});
......
......@@ -880,6 +880,8 @@ sub create {
close AH;
}
$attachment->{bug} = $bug;
# Return the new attachment object.
return $attachment;
}
......
......@@ -50,7 +50,7 @@ use Bugzilla::Status;
use Bugzilla::Comment;
use List::MoreUtils qw(firstidx uniq);
use List::Util qw(min first);
use List::Util qw(min max first);
use Storable qw(dclone);
use URI;
use URI::QueryParam;
......@@ -265,8 +265,14 @@ use constant MAX_LINE_LENGTH => 254;
# of Bugzilla. (These are the field names that the WebService and email_in.pl
# use.)
use constant FIELD_MAP => {
blocks => 'blocked',
is_confirmed => 'everconfirmed',
cc_accessible => 'cclist_accessible',
creation_time => 'creation_ts',
creator => 'reporter',
description => 'comment',
depends_on => 'dependson',
dupe_of => 'dup_id',
id => 'bug_id',
last_change_time => 'delta_ts',
platform => 'rep_platform',
......@@ -977,7 +983,9 @@ sub update {
old_bug => $old_bug });
# If any change occurred, refresh the timestamp of the bug.
if (scalar(keys %$changes) || $self->{added_comments}) {
if (scalar(keys %$changes) || $self->{added_comments}
|| $self->{comment_isprivate})
{
$dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
undef, ($delta_ts, $self->id));
$self->{delta_ts} = $delta_ts;
......@@ -990,7 +998,8 @@ sub update {
# back, this change will *not* be rolled back. As we expect rollbacks
# to be extremely rare, that is OK for us.
$self->_sync_fulltext()
if $self->{added_comments} || $changes->{short_desc};
if $self->{added_comments} || $changes->{short_desc}
|| $self->{comment_isprivate};
# Remove obsolete internal variables.
delete $self->{'_old_assigned_to'};
......@@ -1648,10 +1657,8 @@ sub _check_product {
}
# Check that the product exists and that the user
# is allowed to enter bugs into this product.
Bugzilla->user->can_enter_product($name, THROW_ERROR);
# can_enter_product already does everything that check_product
# would do for us, so we don't need to use it.
return new Bugzilla::Product({ name => $name });
my $product = Bugzilla->user->can_enter_product($name, THROW_ERROR);
return $product;
}
sub _check_priority {
......@@ -2624,7 +2631,7 @@ sub add_comment {
# later in set_all. But if they haven't, this keeps remaining_time
# up-to-date.
if ($params->{work_time}) {
$self->set_remaining_time($self->remaining_time - $params->{work_time});
$self->set_remaining_time(max($self->remaining_time - $params->{work_time}, 0));
}
# So we really want to comment. Make sure we are allowed to do so.
......@@ -3204,6 +3211,17 @@ sub comments {
return \@comments;
}
# This is needed by xt/search.t.
sub percentage_complete {
my $self = shift;
return undef if $self->{'error'} || !Bugzilla->user->is_timetracker;
my $remaining = $self->remaining_time;
my $actual = $self->actual_time;
my $total = $remaining + $actual;
return undef if $total == 0;
return 100 * ($actual / $total);
}
sub product {
my ($self) = @_;
return $self->{product} if exists $self->{product};
......@@ -3697,19 +3715,19 @@ sub LogActivityEntry {
# Convert WebService API and email_in.pl field names to internal DB field
# names.
sub map_fields {
my ($params) = @_;
my ($params, $except) = @_;
my %field_values;
foreach my $field (keys %$params) {
my $field_name = FIELD_MAP->{$field} || $field;
my $field_name;
if ($except->{$field}) {
$field_name = $field;
}
else {
$field_name = FIELD_MAP->{$field} || $field;
}
$field_values{$field_name} = $params->{$field};
}
# This protects the WebService Bug.search method.
unless (Bugzilla->user->is_timetracker) {
delete @field_values{qw(estimated_time remaining_time deadline)};
}
return \%field_values;
}
......
......@@ -525,10 +525,10 @@ sub sendMail {
$value = $value->name;
}
elsif ($name eq 'estimated_time') {
$value = format_time_decimal($value);
$value = ($value == 0) ? 0 : format_time_decimal($value);
}
elsif ($name eq 'deadline') {
$value = time2str("%Y-%m-%d", str2time($value));
$value = time2str("%Y-%m-%d", str2time($value)) if $value;
}
# If there isn't anything to show, don't include this header.
......
......@@ -308,6 +308,9 @@ sub param {
if (!scalar(@result)
&& $self->request_method && $self->request_method eq 'POST')
{
# Some servers fail to set the QUERY_STRING parameter, which
# causes undef issues
$ENV{'QUERY_STRING'} = '' unless exists $ENV{'QUERY_STRING'};
@result = $self->SUPER::url_param(@_);
}
......
......@@ -112,8 +112,6 @@ use File::Basename;
GLOBAL_EVENTS
EVT_FLAG_REQUESTED EVT_REQUESTED_FLAG
FULLTEXT_BUGLIST_LIMIT
ADMIN_GROUP_NAME
PER_PRODUCT_PRIVILEGES
......@@ -141,11 +139,13 @@ use File::Basename;
USAGE_MODE_XMLRPC
USAGE_MODE_EMAIL
USAGE_MODE_JSON
USAGE_MODE_TEST
ERROR_MODE_WEBPAGE
ERROR_MODE_DIE
ERROR_MODE_DIE_SOAP_FAULT
ERROR_MODE_JSON_RPC
ERROR_MODE_TEST
COLOR_ERROR
......@@ -159,6 +159,7 @@ use File::Basename;
MAX_TOKEN_AGE
MAX_LOGINCOOKIE_AGE
MAX_SUDO_TOKEN_AGE
MAX_LOGIN_ATTEMPTS
LOGIN_LOCKOUT_INTERVAL
MAX_STS_AGE
......@@ -168,6 +169,7 @@ use File::Basename;
MIN_SMALLINT
MAX_SMALLINT
MAX_INT_32
MAX_LEN_QUERY_NAME
MAX_CLASSIFICATION_SIZE
......@@ -195,7 +197,7 @@ use File::Basename;
# CONSTANTS
#
# Bugzilla version
use constant BUGZILLA_VERSION => "3.7.2";
use constant BUGZILLA_VERSION => "3.7.3";
# These are unique values that are unlikely to match a string or a number,
# to be used in criteria for match() functions and other things. They start
......@@ -366,10 +368,6 @@ use constant EVT_REQUESTED_FLAG => 101; # I have requested a flag
use constant GLOBAL_EVENTS => EVT_FLAG_REQUESTED, EVT_REQUESTED_FLAG;
# Number of bugs to return in a buglist when performing
# a fulltext search.
use constant FULLTEXT_BUGLIST_LIMIT => 200;
# Default administration group name.
use constant ADMIN_GROUP_NAME => 'admin';
......@@ -418,6 +416,8 @@ use constant TIMETRACKING_FIELDS =>
use constant MAX_TOKEN_AGE => 3;
# How many days a logincookie will remain valid if not used.
use constant MAX_LOGINCOOKIE_AGE => 30;
# How many seconds (default is 6 hours) a sudo cookie remains valid.
use constant MAX_SUDO_TOKEN_AGE => 21600;
# Maximum failed logins to lock account for this IP
use constant MAX_LOGIN_ATTEMPTS => 5;
......@@ -457,6 +457,7 @@ use constant USAGE_MODE_CMDLINE => 1;
use constant USAGE_MODE_XMLRPC => 2;
use constant USAGE_MODE_EMAIL => 3;
use constant USAGE_MODE_JSON => 4;
use constant USAGE_MODE_TEST => 5;
# Error modes. Default set by Bugzilla->usage_mode (so ERROR_MODE_WEBPAGE
# usually). Use with Bugzilla->error_mode.
......@@ -464,6 +465,7 @@ use constant ERROR_MODE_WEBPAGE => 0;
use constant ERROR_MODE_DIE => 1;
use constant ERROR_MODE_DIE_SOAP_FAULT => 2;
use constant ERROR_MODE_JSON_RPC => 3;
use constant ERROR_MODE_TEST => 4;
# The ANSI colors of messages that command-line scripts use
use constant COLOR_ERROR => 'red';
......@@ -511,6 +513,7 @@ use constant ROOT_USER => ON_WINDOWS ? 'Administrator' : 'root';
use constant MIN_SMALLINT => -32768;
use constant MAX_SMALLINT => 32767;
use constant MAX_INT_32 => 2147483647;
# The longest that a saved search name can be.
use constant MAX_LEN_QUERY_NAME => 64;
......
......@@ -368,15 +368,28 @@ sub sql_fulltext_search {
# make the string lowercase to do case insensitive search
my $lower_text = lc($text);
# split the text we search for into separate words
my @words = split(/\s+/, $lower_text);
# split the text we're searching for into separate words. As a hack
# to allow quicksearch to work, if the field starts and ends with
# a double-quote, then we don't split it into words. We can't use
# Text::ParseWords here because it gets very confused by unbalanced
# quotes, which breaks searches like "don't try this" (because of the
# unbalanced single-quote in "don't").
my @words;
if ($lower_text =~ /^"/ and $lower_text =~ /"$/) {
$lower_text =~ s/^"//;
$lower_text =~ s/"$//;
@words = ($lower_text);
}
else {
@words = split(/\s+/, $lower_text);
}
# surround the words with wildcards and SQL quotes so we can use them
# in LIKE search clauses
@words = map($self->quote("%$_%"), @words);
@words = map($self->quote("\%$_\%"), @words);
# untaint words, since they are safe to use now that we've quoted them
map(trick_taint($_), @words);
trick_taint($_) foreach @words;
# turn the words into a set of LIKE search clauses
@words = map("LOWER($column) LIKE $_", @words);
......@@ -688,7 +701,8 @@ sub bz_add_table {
sub _bz_add_table_raw {
my ($self, $name) = @_;
my @statements = $self->_bz_schema->get_table_ddl($name);
print "Adding new table $name ...\n" unless i_am_cgi();
print "Adding new table $name ...\n"
if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
$self->do($_) foreach (@statements);
}
......@@ -770,8 +784,14 @@ sub bz_drop_fk {
print get_text('install_fk_drop',
{ table => $table, column => $column, fk => $def })
. "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
my @sql = $self->_bz_real_schema->get_drop_fk_sql($table,$column,$def);
$self->do($_) foreach @sql;
my @statements =
$self->_bz_real_schema->get_drop_fk_sql($table,$column,$def);
foreach my $sql (@statements) {
# Because this is a deletion, we don't want to die hard if
# we fail because of some local customization. If something
# is already gone, that's fine with us!
eval { $self->do($sql); } or warn "Failed SQL: [$sql] Error: $@";
}
delete $col_def->{REFERENCES};
$self->_bz_real_schema->set_column($table, $column, $col_def);
$self->_bz_store_real_schema;
......
......@@ -126,12 +126,15 @@ sub bz_last_key {
}
sub sql_group_concat {
my ($self, $column, $separator) = @_;
my $sep_sql;
if ($separator) {
$sep_sql = " SEPARATOR $separator";
my ($self, $column, $separator, $sort) = @_;
$separator = $self->quote(', ') if !defined $separator;
$sort = 1 if !defined $sort;
if ($sort) {
my $sort_order = $column;
$sort_order =~ s/^DISTINCT\s+//i;
$column = "$column ORDER BY $sort_order";
}
return "GROUP_CONCAT($column$sep_sql)";
return "GROUP_CONCAT($column SEPARATOR $separator)";
}
sub sql_regexp {
......
......@@ -119,7 +119,7 @@ sub bz_explain {
sub sql_group_concat {
my ($self, $text, $separator) = @_;
$separator ||= "','";
$separator = $self->quote(', ') if !defined $separator;
return "group_concat(T_CLOB_DELIM($text, $separator))";
}
......
......@@ -98,9 +98,14 @@ sub bz_last_key {
}
sub sql_group_concat {
my ($self, $text, $separator) = @_;
$separator ||= "','";
return "array_to_string(array_accum($text), $separator)";
my ($self, $text, $separator, $sort) = @_;
$sort = 1 if !defined $sort;
$separator = $self->quote(', ') if !defined $separator;
my $sql = "array_accum($text)";
if ($sort) {
$sql = "array_sort($sql)";
}
return "array_to_string($sql, $separator)";
}
sub sql_istring {
......@@ -224,6 +229,20 @@ sub bz_setup_database {
)");
}
$self->do(<<'END');
CREATE OR REPLACE FUNCTION array_sort(ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
IMMUTABLE STRICT
AS $$
SELECT ARRAY(
SELECT $1[s.i] AS each_item
FROM
generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
ORDER BY each_item
);
$$;
END
# PostgreSQL doesn't like having *any* index on the thetext
# field, because it can't have index data longer than 2770
# characters on that field.
......
......@@ -136,9 +136,10 @@ sub _get_alter_type_sql {
if ($type =~ /serial/i && $old_def->{TYPE} !~ /serial/i) {
die("You cannot specify a DEFAULT on a SERIAL-type column.")
if $new_def->{DEFAULT};
$type =~ s/serial/integer/i;
}
$type =~ s/\bserial\b/integer/i;
# On Pg, you don't need UNIQUE if you're a PK--it creates
# two identical indexes otherwise.
$type =~ s/unique//i if $new_def->{PRIMARYKEY};
......
......@@ -33,6 +33,7 @@ use Bugzilla::WebService::Constants;
use Bugzilla::Util;
use Carp;
use Data::Dumper;
use Date::Format;
# We cannot use $^S to detect if we are in an eval(), because mod_perl
......@@ -102,6 +103,12 @@ sub _throw_error {
$template->process($name, $vars)
|| ThrowTemplateError($template->error());
}
# There are some tests that throw and catch a lot of errors,
# and calling $template->process over and over for those errors
# is too slow. So instead, we just "die" with a dump of the arguments.
elsif (Bugzilla->error_mode == ERROR_MODE_TEST) {
die Dumper($vars);
}
else {
my $message;
$template->process($name, $vars, \$message)
......
......@@ -214,9 +214,9 @@ use constant DEFAULT_FIELDS => (
{name => 'target_milestone', desc => 'Target Milestone',
buglist => 1},