From 772f6a911585f940363fe0b591b951443406fc66 Mon Sep 17 00:00:00 2001 From: Don Armstrong Date: Sat, 21 Feb 2015 11:25:37 -0800 Subject: [PATCH] allow arbitrarily complex boolean operations in usercategories selection statements --- Debbugs/CGI/Pkgreport.pm | 73 ++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/Debbugs/CGI/Pkgreport.pm b/Debbugs/CGI/Pkgreport.pm index 77b5516..696a9e0 100644 --- a/Debbugs/CGI/Pkgreport.pm +++ b/Debbugs/CGI/Pkgreport.pm @@ -458,40 +458,55 @@ sub pkg_htmlizebugs { return $result; } +sub parse_order_statement_into_boolean { + my ($statement,$status,$tags) = @_; + + if (not defined $tags) { + $tags = {map { $_, 1 } split / /, $status->{"tags"} + } + if defined $status->{"tags"}; + + } + # replace all + with && + $statement =~ s/\+/&&/g; + # replace all , with || + $statement =~ s/,/||/g; + $statement =~ s{(?[^\&\|\=]+)=(?[^\&\|\=]+)} + { + my $ok = 0; + if ($+{field} eq 'tag') { + $ok = 1 if defined $tags->{$+{value}}; + } else { + $ok = 1 if defined $status->{$+{field}} and + $status->{$+{field}} eq $+{value}; + } + $ok; + }exg; + # check that the parsed statement is just valid boolean statements + if ($statement =~ /^([01\(\)\&\|]+)$/) { + return eval "$statement"; + } else { + # this is an invalid boolean statement + return 0; + } +} + sub get_bug_order_index { my $order = shift; my $status = shift; - my $pos = -1; - - my %tags = (); - %tags = map { $_, 1 } split / /, $status->{"tags"} - if defined $status->{"tags"}; - + my $pos = 0; + my $tags = {map { $_, 1 } split / /, $status->{"tags"} + } + if defined $status->{"tags"}; for my $el (@${order}) { - $pos++; - my $match = 1; - my $first_field = 1; # true if no previous fields have been - # checked - while ($el =~ /(?^|\+|,)(?[^=]+)=(?[^=,\+]+)/g) { - my ($j,$f,$v) = @+{qw(joiner field value)}; - my $isokay = 0; - $isokay = 1 if (defined $status->{$f} and $v eq $status->{$f}); - $isokay = 1 if ($f eq "tag" && defined $tags{$v}); - if (defined $j and $j eq ',') { - $match ||= $isokay; - } else { - $match &&= $isokay; - } - $first_field = 0; - } - # if there is a match, or if there were no fields to check, - # this usertag matched. - if ($match || $first_field) { - return $pos; - last; - } + if (not length $el or + parse_order_statement_into_boolean($el,$status,$tags) + ) { + return $pos; + } + $pos++; } - return $pos + 1; + return $pos; } # sets: my @names; my @prior; my @title; my @order; -- 2.39.2