Commit fa943f51 authored by Per Cederqvist's avatar Per Cederqvist

Imported Bugzilla 4.0.

parent afbc5586
bound_location = bzr://bzr.mozilla.org/bugzilla/4.0/
bound = True
Bazaar Branch Format 7 (needs bzr 1.6)
Bazaar-NG Branch Reference Format 1
7374 mkanat@bugzilla.org-20100806020703-h9auojrm6rtappjx
bzr://bzr.mozilla.org/bugzilla/4.0/
\ 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
Bazaar repository format 2a (needs bzr 1.16 or later)
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=
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=0
row_lengths=
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=2
row_lengths=1
x+1"GG0G;ԝ\6Hy%,K%`'7s
UUJΓp M
\ No newline at end of file
......@@ -2,14 +2,24 @@
<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>
<IfModule mod_expires.c>
<IfModule mod_headers.c>
<IfModule mod_env.c>
<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>
# This lets Bugzilla know that we are properly sending Cache-Control
# and Expires headers for CSS and JS files.
SetEnv BZ_CACHE_CONTROL 1
</IfModule>
</IfModule>
</IfModule>
......@@ -111,6 +111,10 @@ use constant VALIDATORS => {
store_in_file => \&_check_store_in_file,
};
use constant VALIDATOR_DEPENDENCIES => {
mimetype => ['ispatch', 'isurl'],
};
use constant UPDATE_VALIDATORS => {
filename => \&_check_filename,
isobsolete => \&Bugzilla::Object::check_boolean,
......@@ -523,9 +527,16 @@ sub _check_bug {
}
sub _check_content_type {
my ($invocant, $content_type) = @_;
my ($invocant, $content_type, undef, $params) = @_;
my ($is_url, $is_patch) = @$params{qw(isurl ispatch)};
if (ref $invocant) {
$is_url = $invocant->isurl;
$is_patch = $invocant->ispatch;
}
$content_type = 'text/plain' if (ref $invocant && ($invocant->isurl || $invocant->ispatch));
$content_type = 'text/plain' if ($is_url || $is_patch);
$content_type = trim($content_type);
my $legal_types = join('|', LEGAL_CONTENT_TYPES);
if (!$content_type or $content_type !~ /^($legal_types)\/.+$/) {
ThrowUserError("invalid_content_type", { contenttype => $content_type });
......
......@@ -146,12 +146,22 @@ sub _handle_login_result {
my $fail_code = $result->{failure};
if (!$fail_code) {
if ($self->{_info_getter}->{successful}->requires_persistence) {
# We don't persist logins over GET requests in the WebService,
# because the persistance information can't be re-used again.
# (See Bugzilla::WebService::Server::JSONRPC for more info.)
if ($self->{_info_getter}->{successful}->requires_persistence
and !Bugzilla->request_cache->{auth_no_automatic_login})
{
$self->{_persister}->persist_login($user);
}
}
elsif ($fail_code == AUTH_ERROR) {
ThrowCodeError($result->{error}, $result->{details});
if ($result->{user_error}) {
ThrowUserError($result->{user_error}, $result->{details});
}
else {
ThrowCodeError($result->{error}, $result->{details});
}
}
elsif ($fail_code == AUTH_NODATA) {
$self->{_info_getter}->fail_nodata($self)
......
......@@ -74,6 +74,12 @@ sub check_credentials {
};
}
# Force the user to type a longer password if it's too short.
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
return { failure => AUTH_ERROR, user_error => 'password_current_too_short',
details => { locked_user => $user } };
}
# The user's credentials are okay, so delete any outstanding
# password tokens or login failures they may have generated.
Bugzilla::Token::DeletePasswordTokens($user->id, "user_logged_in");
......
......@@ -125,7 +125,7 @@ sub VALIDATORS {
bug_status => \&_check_bug_status,
cc => \&_check_cc,
comment => \&_check_comment,
commentprivacy => \&_check_commentprivacy,
comment_is_private => \&_check_comment_is_private,
component => \&_check_component,
deadline => \&_check_deadline,
dup_id => \&_check_dup_id,
......@@ -266,14 +266,17 @@ use constant MAX_LINE_LENGTH => 254;
# use.)
use constant FIELD_MAP => {
blocks => 'blocked',
is_confirmed => 'everconfirmed',
cc_accessible => 'cclist_accessible',
commentprivacy => 'comment_is_private',
creation_time => 'creation_ts',
creator => 'reporter',
description => 'comment',
depends_on => 'dependson',
dupe_of => 'dup_id',
id => 'bug_id',
is_confirmed => 'everconfirmed',
is_cc_accessible => 'cclist_accessible',
is_creator_accessible => 'reporter_accessible',
last_change_time => 'delta_ts',
platform => 'rep_platform',
severity => 'bug_severity',
......@@ -610,9 +613,9 @@ sub create {
my $depends_on = delete $params->{dependson};
my $blocked = delete $params->{blocked};
my $keywords = delete $params->{keywords};
my ($comment, $privacy) = ($params->{comment}, $params->{commentprivacy});
my ($comment, $privacy) = ($params->{comment}, $params->{comment_is_private});
delete $params->{comment};
delete $params->{commentprivacy};
delete $params->{comment_is_private};
# We don't want the bug to appear in the system until it's correctly
# protected by groups.
......@@ -1138,7 +1141,7 @@ sub send_changes {
? $changes->{cc}->[0] : '';
my %forced = (
cc => [split(/[\s,]+/, $old_cc)],
cc => [split(/[,;]+/, $old_cc)],
owner => $old_own,
qacontact => $old_qa,
changer => $user,
......@@ -1375,10 +1378,11 @@ sub _check_cc {
return [map {$_->id} @{$component->initial_cc}] unless $ccs;
# Allow comma-separated input as well as arrayrefs.
$ccs = [split(/[\s,]+/, $ccs)] if !ref $ccs;
$ccs = [split(/[,;]+/, $ccs)] if !ref $ccs;
my %cc_ids;
foreach my $person (@$ccs) {
$person = trim($person);
next unless $person;
my $id = login_to_id($person, THROW_ERROR);
$cc_ids{$id} = 1;
......@@ -1404,7 +1408,7 @@ sub _check_comment {
return $comment;
}
sub _check_commentprivacy {
sub _check_comment_is_private {
my ($invocant, $comment_privacy) = @_;
if ($comment_privacy && !Bugzilla->user->is_insider) {
ThrowUserError('user_not_insider');
......@@ -1432,12 +1436,14 @@ sub _check_component {
sub _check_deadline {
my ($invocant, $date) = @_;
# Check time-tracking permissions.
# deadline() returns '' instead of undef if no deadline is set.
my $current = ref $invocant ? ($invocant->deadline || undef) : undef;
return $current unless Bugzilla->user->is_timetracker;
# When filing bugs, we're forgiving and just return undef if
# the user isn't a timetracker. When updating bugs, check_can_change_field
# controls permissions, so we don't want to check them here.
if (!ref $invocant and !Bugzilla->user->is_timetracker) {
return undef;
}
# Validate entered deadline
$date = trim($date);
return undef if !$date;
......@@ -1460,7 +1466,7 @@ sub _check_dependencies {
my %deps_in = (dependson => $depends_on || '', blocked => $blocks || '');
foreach my $type qw(dependson blocked) {
foreach my $type (qw(dependson blocked)) {
my @bug_ids = ref($deps_in{$type})
? @{$deps_in{$type}}
: split(/[\s,]+/, $deps_in{$type});
......@@ -1640,8 +1646,7 @@ sub _check_keywords {
my %keywords;
foreach my $keyword (@$keyword_array) {
next unless $keyword;
my $obj = new Bugzilla::Keyword({ name => $keyword });
ThrowUserError("unknown_keyword", { keyword => $keyword }) if !$obj;
my $obj = Bugzilla::Keyword->check($keyword);
$keywords{$obj->id} = $obj;
}
return [values %keywords];
......@@ -1742,13 +1747,14 @@ sub _check_resolution {
# Check noresolveonopenblockers.
if (Bugzilla->params->{"noresolveonopenblockers"}
&& $resolution eq 'FIXED'
&& (!$self->resolution || $resolution ne $self->resolution))
&& (!$self->resolution || $resolution ne $self->resolution)
&& scalar @{$self->dependson})
{
my @dependencies = CountOpenDependencies($self->id);
if (@dependencies) {
my $dep_bugs = Bugzilla::Bug->new_from_list($self->dependson);
my $count_open = grep { $_->isopened } @$dep_bugs;
if ($count_open) {
ThrowUserError("still_unresolved_bugs",
{ dependencies => \@dependencies,
dependency_count => scalar @dependencies });
{ bug_id => $self->id, dep_count => $count_open });
}
}
......@@ -1771,6 +1777,10 @@ sub _check_short_desc {
if (!defined $short_desc || $short_desc eq '') {
ThrowUserError("require_summary");
}
if (length($short_desc) > MAX_FREETEXT_LENGTH) {
ThrowUserError('freetext_too_long',
{ field => 'short_desc', text => $short_desc });
}
return $short_desc;
}
......@@ -1863,11 +1873,12 @@ sub _check_target_milestone {
sub _check_time {
my ($invocant, $time, $field) = @_;
my $current = 0;
if (ref $invocant && $field ne 'work_time') {
$current = $invocant->$field;
# When filing bugs, we're forgiving and just return 0 if
# the user isn't a timetracker. When updating bugs, check_can_change_field
# controls permissions, so we don't want to check them here.
if (!ref $invocant and !Bugzilla->user->is_timetracker) {
return 0;
}
return $current unless Bugzilla->user->is_timetracker;
$time = trim($time) || 0;
ValidateTime($time, $field);
......@@ -1885,7 +1896,15 @@ sub _check_version {
}
sub _check_work_time {
return $_[0]->_check_time($_[1], 'work_time');
my ($self, $input) = @_;
my $time = $self->_check_time($input, 'work_time');
# Because work_time isn't set by a set_ function, we need to
# do check_can_change_field here manually.
my $privs;
$self->check_can_change_field('work_time', 0, $time, \$privs)
|| ThrowUserError('illegal_change',
{ field => 'work_time', privs => $privs });
return $time;
}
# Custom Field Validators
......@@ -1942,11 +1961,12 @@ sub _check_datetime_field {
sub _check_default_field { return defined $_[1] ? trim($_[1]) : ''; }
sub _check_freetext_field {
my ($invocant, $text) = @_;
my ($invocant, $text, $field) = @_;
$text = (defined $text) ? trim($text) : '';
if (length($text) > MAX_FREETEXT_LENGTH) {
ThrowUserError('freetext_too_long', { text => $text });
ThrowUserError('freetext_too_long',
{ field => $field, text => $text });
}
return $text;
}
......@@ -2223,7 +2243,6 @@ sub reset_assigned_to {
sub set_cclist_accessible { $_[0]->set('cclist_accessible', $_[1]); }
sub set_comment_is_private {
my ($self, $comment_id, $isprivate) = @_;
return unless Bugzilla->user->is_insider;
# We also allow people to pass in a hash of comment ids to update.
if (ref $comment_id) {
......@@ -2239,6 +2258,7 @@ sub set_comment_is_private {
$isprivate = $isprivate ? 1 : 0;
if ($isprivate != $comment->is_private) {
ThrowUserError('user_not_insider') if !Bugzilla->user->is_insider;
$self->{comment_isprivate} ||= {};
$self->{comment_isprivate}->{$comment_id} = $isprivate;
}
......@@ -2562,7 +2582,13 @@ sub set_bug_status {
else {
# We do this here so that we can make sure closed statuses have
# resolutions.
my $resolution = delete $params->{resolution} || $self->resolution;
my $resolution = $self->resolution;
# We need to check "defined" to prevent people from passing
# a blank resolution in the WebService, which would otherwise fail
# silently.
if (defined $params->{resolution}) {
$resolution = delete $params->{resolution};
}
$self->set_resolution($resolution, $params);
# Changing between closed statuses zeros the remaining time.
......@@ -2619,7 +2645,7 @@ sub add_comment {
}
if (exists $params->{isprivate}) {
$params->{isprivate} =
$self->_check_commentprivacy($params->{isprivate});
$self->_check_comment_is_private($params->{isprivate});
}
# XXX We really should check extra_data, too.
......@@ -2779,6 +2805,11 @@ sub add_see_also {
my ($self, $input) = @_;
$input = trim($input);
if (!$input) {
ThrowCodeError('param_required',
{ function => 'add_see_also', param => '$input' });
}
# We assume that the URL is an HTTP URL if there is no (something)://
# in front.
my $uri = new URI($input);
......@@ -2792,6 +2823,15 @@ sub add_see_also {
ThrowUserError('bug_url_invalid', { url => $input, reason => 'http' });
}
# This stops the following edge cases from being accepted:
# * show_bug.cgi?id=1
# * /show_bug.cgi?id=1
# * http:///show_bug.cgi?id=1
if (!$uri->authority or $uri->path !~ m{/}) {
ThrowUserError('bug_url_invalid',
{ url => $input, reason => 'path_only' });
}
my $result;
# Launchpad URLs
if ($uri->authority =~ /launchpad.net$/) {
......@@ -3731,32 +3771,6 @@ sub map_fields {
return \%field_values;
}
# CountOpenDependencies counts the number of open dependent bugs for a
# list of bugs and returns a list of bug_id's and their dependency count
# It takes one parameter:
# - A list of bug numbers whose dependencies are to be checked
sub CountOpenDependencies {
my (@bug_list) = @_;
my @dependencies;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare(
"SELECT blocked, COUNT(bug_status) " .
"FROM bugs, dependencies " .
"WHERE " . $dbh->sql_in('blocked', \@bug_list) .
"AND bug_id = dependson " .
"AND bug_status IN (" . join(', ', map {$dbh->quote($_)} BUG_STATE_OPEN) . ") " .
$dbh->sql_group_by('blocked'));
$sth->execute();
while (my ($bug_id, $dependencies) = $sth->fetchrow_array()) {
push(@dependencies, { bug_id => $bug_id,
dependencies => $dependencies });
}
return @dependencies;
}
################################################################################
# check_can_change_field() defines what users are allowed to change. You
# can add code here for site-specific policy changes, according to the
......@@ -3790,7 +3804,8 @@ sub check_can_change_field {
} elsif (trim($oldvalue) eq trim($newvalue)) {
return 1;
# numeric fields need to be compared using ==
} elsif (($field eq 'estimated_time' || $field eq 'remaining_time')
} elsif (($field eq 'estimated_time' || $field eq 'remaining_time'
|| $field eq 'work_time')
&& $oldvalue == $newvalue)
{
return 1;
......@@ -3825,7 +3840,7 @@ sub check_can_change_field {
# $PrivilegesRequired = PRIVILEGES_REQUIRED_EMPOWERED : an empowered user.
# Only users in the time-tracking group can change time-tracking fields.
if ( grep($_ eq $field, qw(deadline estimated_time remaining_time)) ) {
if ( grep($_ eq $field, TIMETRACKING_FIELDS) ) {
if (!$user->is_timetracker) {
$$PrivilegesRequired = PRIVILEGES_REQUIRED_EMPOWERED;
return 0;
......
......@@ -285,6 +285,8 @@ sub Send {
}
my $comments = $bug->comments({ after => $start, to => $end });
# Skip empty comments.
@$comments = grep { $_->type || $_->body =~ /\S/ } @$comments;
###########################################################################
# Start of email filtering code
......@@ -341,7 +343,8 @@ sub Send {
}
Bugzilla::Hook::process('bugmail_recipients',
{ bug => $bug, recipients => \%recipients });