266 lines
9.9 KiB
Groff
266 lines
9.9 KiB
Groff
=== modified file 'Bugzilla/Bug.pm'
|
|
--- Bugzilla/Bug.pm 2010-04-06 03:21:50 +0000
|
|
+++ Bugzilla/Bug.pm 2010-07-21 15:58:46 +0000
|
|
@@ -3044,6 +3044,14 @@
|
|
"SELECT bug_id FROM bugs WHERE alias = ?", undef, $alias);
|
|
}
|
|
|
|
+sub get_test_case_count {
|
|
+ my $self = shift;
|
|
+ my $dbh = Bugzilla->dbh;
|
|
+ my $row_count = $dbh->selectall_arrayref(
|
|
+ "SELECT DISTINCT case_id FROM test_case_bugs WHERE bug_id = ?",
|
|
+ undef, $self->bug_id);
|
|
+ return scalar @$row_count;
|
|
+}
|
|
#####################################################################
|
|
# Subroutines
|
|
#####################################################################
|
|
|
|
=== modified file 'Bugzilla/Constants.pm'
|
|
--- Bugzilla/Constants.pm 2010-04-13 04:53:30 +0000
|
|
+++ Bugzilla/Constants.pm 2010-07-21 15:58:46 +0000
|
|
@@ -140,6 +140,7 @@
|
|
ERROR_MODE_WEBPAGE
|
|
ERROR_MODE_DIE
|
|
ERROR_MODE_DIE_SOAP_FAULT
|
|
+ ERROR_MODE_AJAX
|
|
ERROR_MODE_JSON_RPC
|
|
|
|
INSTALLATION_MODE_INTERACTIVE
|
|
@@ -420,6 +421,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_AJAX => 4;
|
|
use constant ERROR_MODE_JSON_RPC => 3;
|
|
|
|
# The various modes that checksetup.pl can run in.
|
|
|
|
=== modified file 'Bugzilla/Error.pm'
|
|
--- Bugzilla/Error.pm 2010-04-01 01:06:03 +0000
|
|
+++ Bugzilla/Error.pm 2010-07-21 15:58:46 +0000
|
|
@@ -32,6 +32,7 @@
|
|
use Bugzilla::WebService::Constants;
|
|
use Bugzilla::Util;
|
|
use Date::Format;
|
|
+use JSON;
|
|
|
|
# We cannot use $^S to detect if we are in an eval(), because mod_perl
|
|
# already eval'uates everything, so $^S = 1 in all cases under mod_perl!
|
|
@@ -135,6 +136,16 @@
|
|
$server->response($server->error_response_header);
|
|
}
|
|
}
|
|
+ elsif (Bugzilla->error_mode == ERROR_MODE_AJAX) {
|
|
+ # JSON can't handle strings across lines.
|
|
+ $message =~ s/\n/ /gm;
|
|
+ my $err;
|
|
+ $err->{'success'} = JSON::false;
|
|
+ $err->{'error'} = $error;
|
|
+ $err->{'message'} = $message;
|
|
+ my $json = new JSON;
|
|
+ print $json->encode($err);
|
|
+ }
|
|
}
|
|
exit;
|
|
}
|
|
|
|
=== modified file 'Bugzilla/Install/Filesystem.pm'
|
|
--- Bugzilla/Install/Filesystem.pm 2010-02-20 20:08:38 +0000
|
|
+++ Bugzilla/Install/Filesystem.pm 2010-07-21 15:58:46 +0000
|
|
@@ -122,6 +122,7 @@
|
|
'runtests.pl' => { perms => $owner_executable },
|
|
'testserver.pl' => { perms => $ws_executable },
|
|
'whine.pl' => { perms => $ws_executable },
|
|
+ 'tr_importxml.pl' => { perms => $ws_executable },
|
|
'customfield.pl' => { perms => $owner_executable },
|
|
'email_in.pl' => { perms => $ws_executable },
|
|
'sanitycheck.pl' => { perms => $ws_executable },
|
|
|
|
=== modified file 'Bugzilla/Search.pm'
|
|
--- Bugzilla/Search.pm 2010-03-29 21:17:54 +0000
|
|
+++ Bugzilla/Search.pm 2010-07-21 15:58:46 +0000
|
|
@@ -274,6 +274,12 @@
|
|
push(@supptables, "LEFT JOIN longdescs AS ldtime " .
|
|
"ON ldtime.bug_id = bugs.bug_id");
|
|
}
|
|
+ ### Testopia ###
|
|
+ if (grep($_ eq 'test_cases', @fields)){
|
|
+ push(@supptables, "LEFT JOIN test_case_bugs AS tcb " .
|
|
+ "ON bugs.bug_id = tcb.bug_id ");
|
|
+ }
|
|
+ ### end Testopia ###
|
|
|
|
if (grep($_ eq 'flagtypes.name', @fields)) {
|
|
push(@supptables, "LEFT JOIN flags ON flags.bug_id = bugs.bug_id AND attach_id IS NULL");
|
|
|
|
=== modified file 'Bugzilla/User.pm'
|
|
--- Bugzilla/User.pm 2010-02-18 00:16:31 +0000
|
|
+++ Bugzilla/User.pm 2010-07-21 15:58:46 +0000
|
|
@@ -361,6 +361,16 @@
|
|
return $self->{queries_available};
|
|
}
|
|
|
|
+sub testopia_queries {
|
|
+ my $self = shift;
|
|
+ my $dbh = Bugzilla->dbh;
|
|
+ my $ref = $dbh->selectall_arrayref(
|
|
+ "SELECT name, query FROM test_named_queries
|
|
+ WHERE userid = ? AND isvisible = 1",
|
|
+ {'Slice' =>{}}, $self->id);
|
|
+ return $ref;
|
|
+}
|
|
+
|
|
sub settings {
|
|
my ($self) = @_;
|
|
|
|
@@ -688,16 +698,23 @@
|
|
my $class_restricted = Bugzilla->params->{'useclassification'} && $class_id;
|
|
|
|
if (!defined $self->{selectable_products}) {
|
|
- my $query = "SELECT id " .
|
|
+ my $query = "(SELECT id, name AS pname " .
|
|
" FROM products " .
|
|
"LEFT JOIN group_control_map " .
|
|
"ON group_control_map.product_id = products.id " .
|
|
" AND group_control_map.membercontrol = " . CONTROLMAPMANDATORY .
|
|
" AND group_id NOT IN(" . $self->groups_as_string . ") " .
|
|
- " WHERE group_id IS NULL " .
|
|
- "ORDER BY name";
|
|
-
|
|
- my $prod_ids = Bugzilla->dbh->selectcol_arrayref($query);
|
|
+ " WHERE group_id IS NULL) " ;
|
|
+
|
|
+ $query .= "UNION (SELECT id, tr_products.name AS pname FROM products AS tr_products ".
|
|
+ "INNER JOIN test_plans ON tr_products.id = test_plans.product_id ".
|
|
+ "INNER JOIN test_plan_permissions ON test_plan_permissions.plan_id = test_plans.plan_id ".
|
|
+ "WHERE test_plan_permissions.userid = ?)";
|
|
+
|
|
+ $query .= " ORDER BY pname ";
|
|
+
|
|
+ my $prod_ids = Bugzilla->dbh->selectcol_arrayref($query,undef,$self->id);
|
|
+
|
|
$self->{selectable_products} = Bugzilla::Product->new_from_list($prod_ids);
|
|
}
|
|
|
|
@@ -990,6 +1007,33 @@
|
|
$group_delete->execute($id, $group, GRANT_REGEXP) if $present;
|
|
}
|
|
}
|
|
+ # Now do the same for Testopia test plans.
|
|
+ $sth = $dbh->prepare("SELECT test_plan_permissions_regexp.plan_id,
|
|
+ user_regexp, test_plan_permissions_regexp.permissions,
|
|
+ test_plan_permissions.plan_id
|
|
+ FROM test_plan_permissions_regexp
|
|
+ LEFT JOIN test_plan_permissions
|
|
+ ON test_plan_permissions_regexp.plan_id = test_plan_permissions.plan_id
|
|
+ AND test_plan_permissions.userid = ?
|
|
+ AND test_plan_permissions.grant_type = ?");
|
|
+
|
|
+ $sth->execute($id, GRANT_REGEXP);
|
|
+ my $plan_insert = $dbh->prepare(q{INSERT INTO test_plan_permissions
|
|
+ (userid, plan_id, permissions, grant_type)
|
|
+ VALUES (?, ?, ?, ?)});
|
|
+ my $plan_delete = $dbh->prepare(q{DELETE FROM test_plan_permissions
|
|
+ WHERE userid = ?
|
|
+ AND plan_id = ?
|
|
+ AND grant_type = ?});
|
|
+
|
|
+ while (my ($planid, $regexp, $perms, $present) = $sth->fetchrow_array()) {
|
|
+ if (($regexp ne '') && ($self->{login} =~ m/$regexp/i)) {
|
|
+ $plan_insert->execute($id, $planid, $perms, GRANT_REGEXP) unless $present;
|
|
+ } else {
|
|
+ $plan_delete->execute($id, $planid, GRANT_REGEXP) if $present;
|
|
+ }
|
|
+ }
|
|
+
|
|
}
|
|
|
|
sub product_responsibilities {
|
|
|
|
=== modified file 'Bugzilla/WebService/Server/XMLRPC.pm'
|
|
--- Bugzilla/WebService/Server/XMLRPC.pm 2010-03-10 20:53:01 +0000
|
|
+++ Bugzilla/WebService/Server/XMLRPC.pm 2010-07-21 15:58:46 +0000
|
|
@@ -78,7 +78,10 @@
|
|
$som->{_bz_do_taint} = 1;
|
|
}
|
|
bless $som, 'Bugzilla::XMLRPC::SOM';
|
|
- Bugzilla->input_params($som->paramsin || {});
|
|
+ my $params = $som->paramsin;
|
|
+ # This allows positional parameters for Testopia.
|
|
+ $params = {} if ref $params ne 'HASH';
|
|
+ Bugzilla->input_params($params);
|
|
return $som;
|
|
}
|
|
|
|
@@ -149,13 +152,15 @@
|
|
|
|
sub paramsin {
|
|
my $self = shift;
|
|
- return $self->{bz_params_in} if $self->{bz_params_in};
|
|
- my $params = $self->SUPER::paramsin(@_);
|
|
- if ($self->{_bz_do_taint}) {
|
|
- taint_data($params);
|
|
+ if (!$self->{bz_params_in}) {
|
|
+ my @params = $self->SUPER::paramsin(@_);
|
|
+ if ($self->{_bz_do_taint}) {
|
|
+ taint_data(@params);
|
|
+ }
|
|
+ $self->{bz_params_in} = \@params;
|
|
}
|
|
- $self->{bz_params_in} = $params;
|
|
- return $self->{bz_params_in};
|
|
+ my $params = $self->{bz_params_in};
|
|
+ return wantarray ? @$params : $params->[0];
|
|
}
|
|
|
|
1;
|
|
|
|
=== modified file 'Bugzilla/WebService/Util.pm'
|
|
--- Bugzilla/WebService/Util.pm 2009-11-09 18:27:52 +0000
|
|
+++ Bugzilla/WebService/Util.pm 2010-07-21 15:58:46 +0000
|
|
@@ -52,13 +52,13 @@
|
|
}
|
|
|
|
sub taint_data {
|
|
- my $params = shift;
|
|
- return if !$params;
|
|
+ my @params = @_;
|
|
+ return if !@params;
|
|
# Though this is a private function, it hasn't changed since 2004 and
|
|
# should be safe to use, and prevents us from having to write it ourselves
|
|
# or require another module to do it.
|
|
- Test::Taint::_deeply_traverse(\&_delete_bad_keys, $params);
|
|
- Test::Taint::taint_deeply($params);
|
|
+ Test::Taint::_deeply_traverse(\&_delete_bad_keys, \@params);
|
|
+ Test::Taint::taint_deeply(\@params);
|
|
}
|
|
|
|
sub _delete_bad_keys {
|
|
@@ -79,6 +79,11 @@
|
|
|
|
sub validate {
|
|
my ($self, $params, @keys) = @_;
|
|
+
|
|
+ # If $params is defined but not a reference, then we weren't
|
|
+ # sent any parameters at all, and we're getting @keys where
|
|
+ # $params should be.
|
|
+ return ($self, undef) if (defined $params and !ref $params);
|
|
|
|
# If @keys is not empty then we convert any named
|
|
# parameters that have scalar values to arrayrefs
|
|
|
|
=== modified file 'template/en/default/global/setting-descs.none.tmpl'
|
|
--- template/en/default/global/setting-descs.none.tmpl 2009-08-19 21:40:07 +0000
|
|
+++ template/en/default/global/setting-descs.none.tmpl 2010-07-21 15:58:46 +0000
|
|
@@ -40,6 +40,7 @@
|
|
"never" => "Never",
|
|
"cc_unless_role" => "Only if I have no role on them",
|
|
"lang" => "Language used in email",
|
|
+ "view_testopia" => "View the Testopia links",
|
|
"quote_replies" => "Quote the associated comment when you click on its reply link",
|
|
"quoted_reply" => "Quote the full comment",
|
|
"simple_reply" => "Reference the comment number only",
|
|
|