From d320ac0ee8de76512a87f5cbcf08350ae4ecc652 Mon Sep 17 00:00:00 2001 From: "lpsolit%gmail.com" <> Date: Fri, 6 May 2005 02:20:44 +0000 Subject: Bug 288663: The inclusion and exclusion lists behave incorrectly when a product or a component is called "Any" - Patch by Frédéric Buclin r=myk a=myk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editflagtypes.cgi | 91 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 27 deletions(-) (limited to 'editflagtypes.cgi') diff --git a/editflagtypes.cgi b/editflagtypes.cgi index ed80a0130..bdf0779b4 100755 --- a/editflagtypes.cgi +++ b/editflagtypes.cgi @@ -146,9 +146,11 @@ sub edit { # Otherwise set the target type (the minimal information about the type # that the template needs to know) from the URL parameter and default # the list of inclusions to all categories. - else { + else { + my %inclusions; + $inclusions{"__Any__:__Any__"} = "0:0"; $vars->{'type'} = { 'target_type' => scalar $cgi->param('target_type'), - 'inclusions' => ["__Any__:__Any__"] }; + 'inclusions' => \%inclusions }; } # Return the appropriate HTTP response headers. @@ -171,13 +173,13 @@ sub processCategoryChange { if ($categoryAction eq 'include') { validateProduct(); validateComponent(); - my $category = ($cgi->param('product') || "__Any__") . ":" . ($cgi->param('component') || "__Any__"); + my $category = ($product_id || 0) . ":" . ($component_id || 0); push(@inclusions, $category) unless grep($_ eq $category, @inclusions); } elsif ($categoryAction eq 'exclude') { validateProduct(); validateComponent(); - my $category = ($cgi->param('product') || "__Any__") . ":" . ($cgi->param('component') || "__Any__"); + my $category = ($product_id || 0) . ":" . ($component_id || 0); push(@exclusions, $category) unless grep($_ eq $category, @exclusions); } elsif ($categoryAction eq 'removeInclusion') { @@ -187,6 +189,11 @@ sub processCategoryChange { @exclusions = map(($_ eq $cgi->param('exclusion_to_remove') ? () : $_), @exclusions); } + # Convert the array @clusions('prod_ID:comp_ID') back to a hash of + # the form %clusions{'prod_name:comp_name'} = 'prod_ID:comp_ID' + my %inclusions = clusion_array_to_hash(\@inclusions); + my %exclusions = clusion_array_to_hash(\@exclusions); + # Get this installation's products and components. GetVersionTable(); @@ -199,8 +206,8 @@ sub processCategoryChange { $vars->{'action'} = $cgi->param('action'); my $type = {}; foreach my $key ($cgi->param()) { $type->{$key} = $cgi->param($key) } - $type->{'inclusions'} = \@inclusions; - $type->{'exclusions'} = \@exclusions; + $type->{'inclusions'} = \%inclusions; + $type->{'exclusions'} = \%exclusions; $vars->{'type'} = $type; # Return the appropriate HTTP response headers. @@ -211,6 +218,21 @@ sub processCategoryChange { || ThrowTemplateError($template->error()); } +# Convert the array @clusions('prod_ID:comp_ID') back to a hash of +# the form %clusions{'prod_name:comp_name'} = 'prod_ID:comp_ID' +sub clusion_array_to_hash { + my $array = shift; + my %hash; + foreach my $ids (@$array) { + trick_taint($ids); + my ($product_id, $component_id) = split(":", $ids); + my $product_name = get_product_name($product_id) || "__Any__"; + my $component_name = get_component_name($component_id) || "__Any__"; + $hash{"$product_name:$component_name"} = $ids; + } + return %hash; +} + sub insert { validateName(); validateDescription(); @@ -253,16 +275,7 @@ sub insert { $cgi->param('request_gid') . ")"); # Populate the list of inclusions/exclusions for this flag type. - foreach my $category_type ("inclusions", "exclusions") { - foreach my $category ($cgi->param($category_type)) { - my ($product, $component) = split(/:/, $category); - my $product_id = get_product_id($product) || "NULL"; - my $component_id = - get_component_id($product_id, $component) || "NULL"; - SendSQL("INSERT INTO flag$category_type (type_id, product_id, " . - "component_id) VALUES ($id, $product_id, $component_id)"); - } - } + validateAndSubmit($id); $dbh->bz_unlock_tables(); @@ -314,17 +327,7 @@ sub update { WHERE id = $id"); # Update the list of inclusions/exclusions for this flag type. - foreach my $category_type ("inclusions", "exclusions") { - SendSQL("DELETE FROM flag$category_type WHERE type_id = $id"); - foreach my $category ($cgi->param($category_type)) { - my ($product, $component) = split(/:/, $category); - my $product_id = get_product_id($product) || "NULL"; - my $component_id = - get_component_id($product_id, $component) || "NULL"; - SendSQL("INSERT INTO flag$category_type (type_id, product_id, " . - "component_id) VALUES ($id, $product_id, $component_id)"); - } - } + validateAndSubmit($id); $dbh->bz_unlock_tables(); @@ -558,3 +561,37 @@ sub validateGroups { $cgi->param($col, $gid); } } + +# At this point, values either come the DB itself or have been recently +# added by the user and have passed all validation tests. +# The only way to have invalid product/component combinations is to +# hack the URL. So we silently ignore them, if any. +sub validateAndSubmit ($) { + my ($id) = @_; + my $dbh = Bugzilla->dbh; + + foreach my $category_type ("inclusions", "exclusions") { + # Will be used several times below. + my $sth = $dbh->prepare("INSERT INTO flag$category_type " . + "(type_id, product_id, component_id) " . + "VALUES (?, ?, ?)"); + + $dbh->do("DELETE FROM flag$category_type WHERE type_id = ?", undef, $id); + foreach my $category ($cgi->param($category_type)) { + trick_taint($category); + my ($product_id, $component_id) = split(":", $category); + # The product does not exist. + next if ($product_id && !get_product_name($product_id)); + # A component was selected without a product being selected. + next if (!$product_id && $component_id); + # The component does not belong to this product. + next if ($component_id + && !$dbh->selectrow_array("SELECT id FROM components + WHERE id = ? AND product_id = ?", + undef, ($component_id, $product_id))); + $product_id ||= undef; + $component_id ||= undef; + $sth->execute($id, $product_id, $component_id); + } + } +} -- cgit v1.2.3-24-g4f1b