X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=cgi%2Fpkgreport.cgi;h=c36f9f68b8623f8bc0b1b00c7fd6c040a5ff144a;hb=fac30aacb5b9a104a1216af15fc04e227f9ef447;hp=66b2e22d1601a4eb718ef6fc302b94e4a7cb1932;hpb=63323b2a2f1966937fd044843fc4891169f5882b;p=debbugs.git diff --git a/cgi/pkgreport.cgi b/cgi/pkgreport.cgi index 66b2e22..c36f9f6 100755 --- a/cgi/pkgreport.cgi +++ b/cgi/pkgreport.cgi @@ -1,20 +1,31 @@ #!/usr/bin/perl -wT +# This script is part of debbugs, and is released +# under the terms of the GPL version 2, or any later +# version at your option. +# See the file README and COPYING for more information. +# +# [Other people have contributed to this file; their copyrights should +# go here too.] +# Copyright 2004-2006 by Anthony Towns +# Copyright 2007 by Don Armstrong . + package debbugs; +use warnings; use strict; -use POSIX qw(strftime tzset nice); - -#require '/usr/lib/debbugs/errorlib'; -require './common.pl'; - -require '/etc/debbugs/config'; -require '/etc/debbugs/text'; +use POSIX qw(strftime nice); +use Debbugs::Config qw(:globals :text :config); use Debbugs::User; -my $cats = 5; +use Debbugs::CGI qw(version_url maint_decode); +use Debbugs::Common qw(getparsedaddrs :date make_list getmaintainers); +use Debbugs::Bugs qw(get_bugs bug_filter newest_bug); +use Debbugs::Packages qw(getsrcpkgs getpkgsrc get_versions); +use Debbugs::Status qw(:status); +use Debbugs::CGI qw(:all); -use vars qw($gPackagePages $gWebDomain); +use vars qw($gPackagePages $gWebDomain %gSeverityDisplay @gSeverityList); if (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq 'HEAD') { print "Content-Type: text/html; charset=utf-8\n\n"; @@ -23,10 +34,41 @@ if (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq 'HEAD') { nice(5); -my $userAgent = detect_user_agent(); -my %param = readparse(); +use CGI::Simple; +my $q = new CGI::Simple; + +our %param = cgi_parameters(query => $q, + single => [qw(ordering archive repeatmerged), + qw(bug-rev pend-rev sev-rev), + qw(maxdays mindays version), + qw(data which dist newest), + ], + default => {ordering => 'normal', + archive => 0, + repeatmerged => 1, + }, + ); + +# map from yes|no to 1|0 +for my $key (qw(repeatmerged bug-rev pend-rev sev-rev)) { + if (exists $param{$key}){ + if ($param{$key} =~ /^no$/i) { + $param{$key} = 0; + } + elsif ($param{$key}) { + $param{$key} = 1; + } + } +} + +if (lc($param{archive}) eq 'no') { + $param{archive} = 0; +} +elsif (lc($param{archive}) eq 'yes') { + $param{archive} = 1; +} + -my $repeatmerged = ($param{'repeatmerged'} || "yes") eq "yes"; my $archive = ($param{'archive'} || "no") eq "yes"; my $include = $param{'&include'} || $param{'include'} || ""; my $exclude = $param{'&exclude'} || $param{'exclude'} || ""; @@ -36,463 +78,423 @@ my $users = $param{'users'} || ""; my $ordering = $param{'ordering'}; my $raw_sort = ($param{'raw'} || "no") eq "yes"; my $old_view = ($param{'oldview'} || "no") eq "yes"; +my $age_sort = ($param{'age'} || "no") eq "yes"; unless (defined $ordering) { $ordering = "normal"; - $ordering = "old" if $old_view; + $ordering = "oldview" if $old_view; $ordering = "raw" if $raw_sort; + $ordering = 'age' if $age_sort; } +our ($bug_order) = $ordering =~ /(age(?:rev)?)/; +$bug_order = '' if not defined $bug_order; my $bug_rev = ($param{'bug-rev'} || "no") eq "yes"; my $pend_rev = ($param{'pend-rev'} || "no") eq "yes"; my $sev_rev = ($param{'sev-rev'} || "no") eq "yes"; -my $pend_exc = $param{'&pend-exc'} || $param{'pend-exc'} || ""; -my $pend_inc = $param{'&pend-inc'} || $param{'pend-inc'} || ""; -my $sev_exc = $param{'&sev-exc'} || $param{'sev-exc'} || ""; -my $sev_inc = $param{'&sev-inc'} || $param{'sev-inc'} || ""; + +my @inc_exc_mapping = ({name => 'pending', + incexc => 'include', + key => 'pend-inc', + }, + {name => 'pending', + incexc => 'exclude', + key => 'pend-exc', + }, + {name => 'severity', + incexc => 'include', + key => 'sev-inc', + }, + {name => 'severity', + incexc => 'exclude', + key => 'sev-exc', + }, + {name => 'subject', + incexc => 'include', + key => 'includesubj', + }, + {name => 'subject', + incexc => 'exclude', + key => 'excludesubj', + }, + ); +for my $incexcmap (@inc_exc_mapping) { + push @{$param{$incexcmap->{incexc}}}, map {"$incexcmap->{name}:$_"} + map{split /\s*,\s*/} make_list($param{$incexcmap->{key}}) + if exists $param{$incexcmap->{key}}; + delete $param{$incexcmap->{key}}; +} + my $maxdays = ($param{'maxdays'} || -1); my $mindays = ($param{'mindays'} || 0); my $version = $param{'version'} || undef; -my $dist = $param{'dist'} || undef; -my $arch = $param{'arch'} || undef; -my $show_list_header = ($param{'show_list_header'} || $userAgent->{'show_list_header'} || "yes" ) eq "yes"; -my $show_list_footer = ($param{'show_list_footer'} || $userAgent->{'show_list_footer'} || "yes" ) eq "yes"; - -my @p = ( - "pending:pending,forwarded,pending-fixed,fixed,done,absent", - "severity:critical,grave,serious,important,normal,minor,wishlist", - "pending=pending+tag=wontfix,pending=pending+tag=moreinfo,pending=pending+tag=patch,pending=pending+tag=confirmed,pending=pending"); -my @t = ( - "Outstanding,Forwarded,Pending Upload,Fixed in NMU,Resolved,From other Branch,Unknown Pending Status", - "Critical,Grave,Serious,Important,Normal,Minor,Wishlist,Unknown Severity", - "Will Not Fix,More information needed,Patch Available,Confirmed,Unclassified"); -my @o = ("0,1,2,3,4,5,6","0,1,2,3,4,5,6,7","2,3,4,1,0,5"); -my @n = ("Status", "Severity", "Classification"); - -if ($ordering eq "old") { - splice @p, 2, 1; - splice @t, 2, 1; - splice @o, 2, 1; - splice @n, 2, 1; -} -$o[0] = scalar reverse($o[0]) if ($pend_rev); -$o[1] = scalar reverse($o[1]) if ($sev_rev); - -if (!defined $param{"pri0"} && $ordering =~ m/^user(\d+)$/) { - my $id = $1; - my $l = 0; - if (defined $param{"cat${id}_users"}) { - $users .= "," . $param{"cat${id}_users"}; - } - while (defined $param{"cat${id}_nam$l"}) { - my ($n, $p, $t, $o) = - map { $param{"cat${id}_${_}$l"} || "" } - ("nam", "pri", "ttl", "ord"); - if ($p eq "") { - if ($n eq "status") { - ($p, $t, $o) = ($p[0], $t[0], $o[0]); - } elsif ($n eq "severity") { - ($p, $t, $o) = ($p[1], $t[1], $o[1]) - } else { - $ordering = "raw"; - last; - } - } - $param{"nam$l"} = $n; - $param{"pri$l"} = $p; - $param{"ttl$l"} = $t; - $param{"ord$l"} = $o; - $l++; - } -} -if (defined $param{"pri0"}) { - my $i = 0; - @p = (); @o = (); @t = (); @n = (); - while (defined $param{"pri$i"}) { - push @p, $param{"pri$i"}; - push @o, $param{"ord$i"} || ""; - push @t, $param{"ttl$i"} || ""; - push @n, $param{"nam$i"} || ""; - $i++; - } -} -for my $x (@p) { - next if "$x," =~ m/^(pending|severity|tag):(([*]|[a-z0-9.-]+),)+$/; - next if "$x," =~ m/^((pending|severity|tag)=([*]|[a-z0-9.-]+)[,+])+/; - quitcgi("Bad syntax in Priority: $x"); +# XXX Once the options/selection is rewritten, this should go away +my $dist = $param{dist} || undef; + +our %hidden = map { $_, 1 } qw(status severity classification); +our %cats = ( + "status" => [ { + "nam" => "Status", + "pri" => [map { "pending=$_" } + qw(pending forwarded pending-fixed fixed done absent)], + "ttl" => ["Outstanding","Forwarded","Pending Upload", + "Fixed in NMU","Resolved","From other Branch"], + "def" => "Unknown Pending Status", + "ord" => [0,1,2,3,4,5,6], + } ], + "severity" => [ { + "nam" => "Severity", + "pri" => [map { "severity=$_" } @gSeverityList], + "ttl" => [map { $gSeverityDisplay{$_} } @gSeverityList], + "def" => "Unknown Severity", + "ord" => [0..@gSeverityList], + } ], + "classification" => [ { + "nam" => "Classification", + "pri" => [qw(pending=pending+tag=wontfix + pending=pending+tag=moreinfo + pending=pending+tag=patch + pending=pending+tag=confirmed + pending=pending)], + "ttl" => ["Will Not Fix","More information needed", + "Patch Available","Confirmed"], + "def" => "Unclassified", + "ord" => [2,3,4,1,0,5], + } ], + "oldview" => [ qw(status severity) ], + "normal" => [ qw(status severity classification) ], +); + +my @select_key = (qw(submitter maint pkg package src usertag), + qw(status tag maintenc owner severity newest) + ); + +if (exists $param{which} and exists $param{data}) { + $param{$param{which}} = [exists $param{$param{which}}?(make_list($param{$param{which}})):(), + make_list($param{data}), + ]; + delete $param{which}; + delete $param{data}; } -my @names; my @prior; my @title; my @order; -for my $i (0..$#p) { - push @prior, [ make_order_list($p[$i]) ]; - if ($n[$i]) { - push @names, $n[$i]; - } elsif ($p[$i] =~ m/^([^:]+):/) { - push @names, $1; - } else { - push @names, "Bug attribute #" . (1+$i); - } - if ($o[$i]) { - push @order, [ split /,/, $o[$i] ]; - } else { - push @order, [ 0..$#{$prior[$i]} ]; - } - my @t = split /,/, $t[$i]; - push @t, map { toenglish($prior[$i]->[$_]) } ($#t+1)..($#{$prior[$i]}); - push @title, [@t]; +if (defined $param{maintenc}) { + $param{maint} = maint_decode($param{maintenc}); + delete $param{maintenc} } -sub toenglish { - my $expr = shift; - $expr =~ s/[+]/ and /g; - $expr =~ s/[a-z]+=//g; - return $expr; -} -{ - if (defined $param{'vt'}) { - my $vt = $param{'vt'}; - if ($vt eq "none") { $dist = undef; $arch = undef; $version = undef; } - if ($vt eq "bysuite") { - $version = undef; - $arch = undef if ($arch eq "any"); - } - if ($vt eq "bypkg" || $vt eq "bysrc") { $dist = undef; $arch = undef; } - } - if (defined $param{'includesubj'}) { - my $is = $param{'includesubj'}; - $include .= "," . join(",", map { "subj:$_" } (split /[\s,]+/, $is)); - } - if (defined $param{'excludesubj'}) { - my $es = $param{'excludesubj'}; - $exclude .= "," . join(",", map { "subj:$_" } (split /[\s,]+/, $es)); - } +if (not grep {exists $param{$_}} @select_key and exists $param{users}) { + $param{usertag} = [make_list($param{users})]; } +quitcgi("You have to choose something to select by") unless grep {exists $param{$_}} @select_key; -my %bugusertags; -my %ut; -for my $user (split /[\s*,]+/, $users) { - next unless ($user =~ m/..../); - Debbugs::User::read_usertags(\%ut, $user); +if (exists $param{pkg}) { + $param{package} = $param{pkg}; + delete $param{pkg}; } -my ($pkg, $src, $maint, $maintenc, $submitter, $severity, $status, $tag, $usertag); - -my %which = ( - 'pkg' => \$pkg, - 'src' => \$src, - 'maint' => \$maint, - 'maintenc' => \$maintenc, - 'submitter' => \$submitter, - 'severity' => \$severity, - 'tag' => \$tag, - 'usertag' => \$usertag, - ); -my @allowedEmpty = ( 'maint' ); - -my $found; -foreach ( keys %which ) { - $status = $param{'status'} || 'open' if /^severity$/; - if (($found = $param{$_})) { - ${ $which{$_} } = $found; - last; - } -} -if (!$found && !$archive) { - foreach ( @allowedEmpty ) { - if (exists($param{$_})) { - ${ $which{$_} } = ''; - $found = 1; - last; - } - } -} -if (!$found) { - my $which; - if (($which = $param{'which'})) { - if (grep( /^\Q$which\E$/, @allowedEmpty)) { - ${ $which{$which} } = $param{'data'}; - $found = 1; - } elsif (($found = $param{'data'})) { - ${ $which{$which} } = $found if (exists($which{$which})); - } - } +our %bugusertags; +our %ut; +for my $user (map {split /[\s*,\s*]+/} make_list($param{users}||[])) { + next unless length($user); + add_user($user); } -quitcgi("You have to choose something to select by") if (!$found); -if (defined $usertag) { +if (defined $param{usertag}) { my %select_ut = (); - my ($u, $t) = split /:/, $usertag, 2; + my ($u, $t) = split /:/, $param{usertag}, 2; Debbugs::User::read_usertags(\%select_ut, $u); unless (defined $t && $t ne "") { $t = join(",", keys(%select_ut)); } - Debbugs::User::read_usertags(\%ut, $u); - $tag = $t; -} - -for my $t (keys %ut) { - for my $b (@{$ut{$t}}) { - $bugusertags{$b} = [] unless defined $bugusertags{$b}; - push @{$bugusertags{$b}}, $t; - } + add_user($u); + push @{$param{tag}}, split /,/, $t; } my $Archived = $archive ? " Archived" : ""; -my $this = ""; +our $this = munge_url('pkgreport.cgi?', + %param, + ); my %indexentry; my %strings = (); -$ENV{"TZ"} = 'UTC'; -tzset(); - -my $dtime = strftime "%a, %e %b %Y %T UTC", localtime; +my $dtime = strftime "%a, %e %b %Y %T UTC", gmtime; my $tail_html = $debbugs::gHTMLTail; $tail_html = $debbugs::gHTMLTail; $tail_html =~ s/SUBSTITUTE_DTIME/$dtime/; -set_option("repeatmerged", $repeatmerged); -set_option("archive", $archive); -set_option("include", $include); -set_option("exclude", $exclude); -set_option("pend-exc", $pend_exc); -set_option("pend-inc", $pend_inc); -set_option("sev-exc", $sev_exc); -set_option("sev-inc", $sev_inc); -set_option("maxdays", $maxdays); -set_option("mindays", $mindays); -set_option("version", $version); -set_option("dist", $dist); -set_option("arch", $arch); -set_option("use-bug-idx", defined($param{'use-bug-idx'}) ? $param{'use-bug-idx'} : 0); -set_option("show_list_header", $show_list_header); -set_option("show_list_footer", $show_list_footer); -set_option("bugusertags", \%bugusertags); - -my $title; -my @bugs; -if (defined $pkg) { - $title = "package $pkg"; - if (defined $version) { - $title .= " (version $version)"; - } elsif (defined $dist) { - $title .= " in $dist"; - my $verdesc = getversiondesc($pkg); - $title .= " ($verdesc)" if defined $verdesc; - } - my @pkgs = split /,/, $pkg; - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if grep($try eq $_, @pkgs); - } - return 0; - }, 'package', @pkgs)}; -} elsif (defined $src) { - $title = "source $src"; - set_option('arch', 'source'); - if (defined $version) { - $title .= " (version $version)"; - } elsif (defined $dist) { - $title .= " in $dist"; - my $verdesc = getversiondesc($src); - $title .= " ($verdesc)" if defined $verdesc; - } - my @pkgs = (); - my @srcs = split /,/, $src; - foreach my $try (@srcs) { - push @pkgs, getsrcpkgs($try); - push @pkgs, $try if ( !grep(/^\Q$try\E$/, @pkgs) ); - } - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if grep($try eq $_, @pkgs); - } - return 0; - }, 'package', @pkgs)}; -} elsif (defined $maint) { - my %maintainers = %{getmaintainers()}; - $title = "maintainer $maint"; - $title .= " in $dist" if defined $dist; - if ($maint eq "") { - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if !getparsedaddrs($maintainers{$try}); - } - return 0; - })}; - } else { - my @maints = split /,/, $maint; - my @pkgs = (); - foreach my $try (@maints) { - foreach my $p (keys %maintainers) { - my @me = getparsedaddrs($maintainers{$p}); - push @pkgs, $p if grep { $_->address eq $try } @me; - } +our %seen_users; +sub add_user { + my $ut = \%ut; + my $u = shift; + + return if $seen_users{$u}; + $seen_users{$u} = 1; + + my $user = Debbugs::User::get_user($u); + + my %vis = map { $_, 1 } @{$user->{"visible_cats"}}; + for my $c (keys %{$user->{"categories"}}) { + $cats{$c} = $user->{"categories"}->{$c}; + $hidden{$c} = 1 unless defined $vis{$c}; } - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - my @me = getparsedaddrs($maintainers{$try}); - return 1 if grep { $_->address eq $maint } @me; - } - return 0; - }, 'package', @pkgs)}; - } -} elsif (defined $maintenc) { - my %maintainers = %{getmaintainers()}; - $title = "encoded maintainer $maintenc"; - $title .= " in $dist" if defined $dist; - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - my @me = getparsedaddrs($maintainers{$try}); - return 1 if grep { - maintencoded($_->address) eq $maintenc - } @me; - } - return 0; - })}; -} elsif (defined $submitter) { - $title = "submitter $submitter"; - $title .= " in $dist" if defined $dist; - my @submitters = split /,/, $submitter; - @bugs = @{getbugs(sub {my %d=@_; - my @se = getparsedaddrs($d{"submitter"} || ""); - foreach my $try (@submitters) { - return 1 if grep { $_->address eq $try } @se; - } - }, 'submitter-email', @submitters)}; -} elsif (defined($severity) && defined($status)) { - $title = "$status $severity bugs"; - $title .= " in $dist" if defined $dist; - my @severities = split /,/, $severity; - my @statuses = split /,/, $status; - @bugs = @{getbugs(sub {my %d=@_; - return (grep($d{"severity"} eq $_, @severities)) - && (grep($d{"status"} eq $_, @statuses)); - })}; -} elsif (defined($severity)) { - $title = "$severity bugs"; - $title .= " in $dist" if defined $dist; - my @severities = split /,/, $severity; - @bugs = @{getbugs(sub {my %d=@_; - return (grep($d{"severity"} eq $_, @severities)); - }, 'severity', @severities)}; -} elsif (defined($tag)) { - $title = "bugs tagged $tag"; - $title .= " in $dist" if defined $dist; - my @tags = split /,/, $tag; - my %bugs = (); - for my $t (@tags) { - for my $b (@{$ut{$t}}) { - $bugs{$b} = 1; - } - } - @bugs = @{getbugs(sub {my %d = @_; - return 1 if $bugs{$d{"bug"}}; - my %tags = map { $_ => 1 } split ' ', $d{"tags"}; - return grep(exists $tags{$_}, @tags); - })}; + + for my $t (keys %{$user->{"tags"}}) { + $ut->{$t} = [] unless defined $ut->{$t}; + push @{$ut->{$t}}, @{$user->{"tags"}->{$t}}; + } + + %bugusertags = (); + for my $t (keys %{$ut}) { + for my $b (@{$ut->{$t}}) { + $bugusertags{$b} = [] unless defined $bugusertags{$b}; + push @{$bugusertags{$b}}, $t; + } + } +# set_option("bugusertags", \%bugusertags); } +my @bugs; + +# addusers for source and binary packages being searched for +my $pkgsrc = getpkgsrc(); +my $srcpkg = getsrcpkgs(); +for my $package (# For binary packages, add the binary package + # and corresponding source package + make_list($param{package}||[]), + (map {defined $pkgsrc->{$_}?($pkgsrc->{$_}):()} + make_list($param{package}||[]), + ), + # For source packages, add the source package + # and corresponding binary packages + make_list($param{src}||[]), + (map {defined $srcpkg->{$_}?($srcpkg->{$_}):()} + make_list($param{src}||[]), + ), + ) { + next unless defined $package; + add_user($package.'@'.$config{usertag_package_domain}) + if defined $config{usertag_package_domain}; +} + + +# walk through the keys and make the right get_bugs query. + +my @search_key_order = (package => 'in package', + tag => 'tagged', + severity => 'with severity', + src => 'in source package', + maint => 'in packages maintained by', + submitter => 'submitted by', + owner => 'owned by', + status => 'with status', + ); +my %search_keys = @search_key_order; + +# Set the title sanely and clean up parameters +my @title; +while (my ($key,$value) = splice @search_key_order, 0, 2) { + next unless exists $param{$key}; + my @entries = (); + $param{$key} = [map {split /\s*,\s*/} make_list($param{$key})]; + for my $entry (make_list($param{$key})) { + my $extra = ''; + if (exists $param{dist} and ($key eq 'package' or $key eq 'src')) { + my @versions = get_versions(package => $entry, + (exists $param{dist}?(dist => $param{dist}):()), + (exists $param{arch}?(arch => $param{arch}):()), + ($key eq 'src'?(arch => q(source)):()), + ); + my $verdesc = join(', ',@versions); + $verdesc = 'version'.(@versions>1?'s ':' ').$verdesc; + $extra= " ($verdesc)" if @versions; + } + push @entries, $entry.$extra; + } + push @title,$value.' '.join(' or ', @entries); +} +my $title = $gBugs.' '.join(' and ', map {/ or /?"($_)":$_} @title); +@title = (); + +# we have to special case the maint="" search, unfortunatly. +if (defined $param{maint} and $param{maint} eq "") { + my %maintainers = %{getmaintainers()}; + @bugs = get_bugs(function => + sub {my %d=@_; + foreach my $try (splitpackages($d{"pkg"})) { + return 1 if !getparsedaddrs($maintainers{$try}); + } + return 0; + } + ); + $title = $gBugs.' in packages with no maintainer'; +} +elsif (defined $param{newest}) { + my $newest_bug = newest_bug(); + @bugs = ($newest_bug - $param{newest} + 1) .. $newest_bug; + $title = @bugs.' newest '.$gBugs; +} +else { + #yeah for magick! + @bugs = get_bugs((map {exists $param{$_}?($_,$param{$_}):()} + keys %search_keys, 'archive'), + usertags => \%ut, + ); +} + +if (defined $param{version}) { + $title .= " at version $param{version}"; +} +elsif (defined $param{dist}) { + $title .= " in $param{dist}"; +} + +$title = html_escape($title); + +my @names; my @prior; my @order; +determine_ordering(); + +# strip out duplicate bugs +my %bugs; +@bugs{@bugs} = @bugs; +@bugs = keys %bugs; + my $result = pkg_htmlizebugs(\@bugs); print "Content-Type: text/html; charset=utf-8\n\n"; print "\n"; print "\n" . - "$debbugs::gProject$Archived $debbugs::gBug report logs: $title\n" . - '' . + "$title -- $gProject$Archived $gBug report logs\n" . + qq() . "\n" . '' . "\n"; -print "

" . "$debbugs::gProject$Archived $debbugs::gBug report logs: $title" . +print "

" . "$gProject$Archived $gBug report logs: $title" . "

\n"; my $showresult = 1; -if (defined $pkg || defined $src) { - my $showpkg = (defined $pkg) ? $pkg : "source package $src"; - my %maintainers = %{getmaintainers()}; - my $maint = $pkg ? $maintainers{$pkg} : $maintainers{$src} ? $maintainers{$src} : undef; +my $pkg = $param{package} if defined $param{package}; +my $src = $param{src} if defined $param{src}; + +my $pseudodesc = getpseudodesc(); +if (defined $pseudodesc and defined $pkg and exists $pseudodesc->{$pkg}) { + delete $param{dist}; +} + +# output infomration about the packages + +for my $package (make_list($param{package}||[])) { + output_package_info('binary',$package); +} +for my $package (make_list($param{src}||[])) { + output_package_info('source',$package); +} + +sub output_package_info{ + my ($srcorbin,$package) = @_; + my $showpkg = html_escape($package); + my $maintainers = getmaintainers(); + my $maint = $maintainers->{$package}; if (defined $maint) { - print '

'; - print htmlmaintlinks(sub { $_[0] == 1 ? "Maintainer for $showpkg is " - : "Maintainers for $showpkg are " - }, - $maint); - print ".

\n"; + print '

'; + print htmlize_maintlinks(sub { $_[0] == 1 ? "Maintainer for $showpkg is " + : "Maintainers for $showpkg are " + }, + $maint); + print ".

\n"; } else { - print "

No maintainer for $showpkg. Please do not report new bugs against this package.

\n"; + print "

No maintainer for $showpkg. Please do not report new bugs against this package.

\n"; } - if (defined $maint or @bugs) { - my %pkgsrc = %{getpkgsrc()}; - my $srcforpkg; - if (defined $pkg) { - $srcforpkg = $pkgsrc{$pkg}; - defined $srcforpkg or $srcforpkg = $pkg; - } - my @pkgs = getsrcpkgs($pkg ? $srcforpkg : $src); - undef $srcforpkg unless @pkgs; - @pkgs = grep( !/^\Q$pkg\E$/, @pkgs ) if ( $pkg ); - if ( @pkgs ) { - @pkgs = sort @pkgs; - if ($pkg) { - print "

You may want to refer to the following packages that are part of the same source:\n"; - } else { - print "

You may want to refer to the following individual bug pages:\n"; - } - push @pkgs, $src if ( $src && !grep(/^\Q$src\E$/, @pkgs) ); - print join( ", ", map( "$_", @pkgs ) ); - print ".\n"; - } - my @references; - my $pseudodesc = getpseudodesc(); - if ($pkg and defined($pseudodesc) and exists($pseudodesc->{$pkg})) { - push @references, "to the list of other pseudo-packages"; - } else { - if ($pkg and defined $debbugs::gPackagePages) { - push @references, sprintf "to the %s package page", urlsanit("http://${debbugs::gPackagePages}/$pkg"), htmlsanit("$pkg"); - } - if (defined $debbugs::gSubscriptionDomain) { - my $ptslink = $pkg ? $srcforpkg : $src; - push @references, "to the Package Tracking System"; - } - # Only output this if the source listing is non-trivial. - if ($pkg and $srcforpkg and (@pkgs or $pkg ne $srcforpkg)) { - push @references, sprintf "to the source package %s's bug page", srcurl($srcforpkg), htmlsanit($srcforpkg); - } - } - if ($pkg) { - set_option("archive", !$archive); - push @references, sprintf "to the %s reports for %s", pkgurl($pkg), ($archive ? "active" : "archived"), htmlsanit($pkg); - set_option("archive", $archive); - } - if (@references) { - $references[$#references] = "or $references[$#references]" if @references > 1; - print "

You might like to refer ", join(", ", @references), ".

\n"; - } - print "

If you find a bug not listed here, please\n"; - printf "report it.

\n", - urlsanit("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}"); + my %pkgsrc = %{getpkgsrc()}; + my $srcforpkg = $package; + if ($srcorbin eq 'binary') { + $srcforpkg = $pkgsrc{$package}; + defined $srcforpkg or $srcforpkg = $package; + } + my @pkgs = getsrcpkgs($srcforpkg); + @pkgs = grep( !/^\Q$package\E$/, @pkgs ); + if ( @pkgs ) { + @pkgs = sort @pkgs; + if ($srcorbin eq 'binary') { + print "

You may want to refer to the following packages that are part of the same source:\n"; + } else { + print "

You may want to refer to the following individual bug pages:\n"; + } + #push @pkgs, $src if ( $src && !grep(/^\Q$src\E$/, @pkgs) ); + print join( ", ", map( "$_,src=>[],newest=>[])) . "\">$_", @pkgs ) ); + print ".\n"; + } + my @references; + my $pseudodesc = getpseudodesc(); + if ($package and defined($pseudodesc) and exists($pseudodesc->{$package})) { + push @references, "to the ". + "list of other pseudo-packages"; } else { - print "

There is no record of the " . - (defined($pkg) ? htmlsanit($pkg) . " package" - : htmlsanit($src) . " source package") . - ", and no bugs have been filed against it.

"; - $showresult = 0; + if ($package and defined $gPackagePages) { + push @references, sprintf "to the %s package page", + html_escape("http://${debbugs::gPackagePages}/$package"), html_escape("$package"); + } + if (defined $gSubscriptionDomain) { + my $ptslink = $package ? $srcforpkg : $src; + push @references, "to the Package Tracking System"; + } + # Only output this if the source listing is non-trivial. + if ($srcorbin eq 'binary' and $srcforpkg) { + push @references, sprintf "to the source package %s's bug page", html_escape(munge_url($this,src=>$srcforpkg,package=>[],newest=>[])), html_escape($srcforpkg); + } } -} elsif (defined $maint || defined $maintenc) { + if (@references) { + $references[$#references] = "or $references[$#references]" if @references > 1; + print "

You might like to refer ", join(", ", @references), ".

\n"; + } + if (defined $param{maint} || defined $param{maintenc}) { + print "

If you find a bug not listed here, please\n"; + printf "report it.

\n", + html_escape("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}"); + } + if (not $maint and not @bugs) { + print "

There is no record of the " . + ($srcorbin eq 'binary' ? html_escape($package) . " package" + : html_escape($src) . " source package"). + ", and no bugs have been filed against it.

"; + $showresult = 0; + } +} + +if (exists $param{maint} or exists $param{maintenc}) { print "

Note that maintainers may use different Maintainer fields for\n"; print "different packages, so there may be other reports filed under\n"; print "different addresses.\n"; -} elsif (defined $submitter) { +} +if (exists $param{submitter}) { print "

Note that people may use different email accounts for\n"; print "different bugs, so there may be other reports filed under\n"; print "different addresses.\n"; } +my $archive_links; +my @archive_links; +my %archive_values = (both => 'archived and unarchived', + 0 => 'not archived', + 1 => 'archived', + ); +while (my ($key,$value) = each %archive_values) { + next if $key eq lc($param{archive}); + push @archive_links, qq($value reports ); +} +print '

See the '.join (' or ',@archive_links)."

\n"; + print $result if $showresult; print pkg_javascript() . "\n"; @@ -517,28 +519,31 @@ print ""; print " " . pkg_htmlselectsuite(1,2,1) . " for " . pkg_htmlselectarch(1,2,2) . "\n"; if (defined $pkg) { - my $v = $version || ""; + my $v = html_escape($version) || ""; + my $pkgsane = html_escape($pkg); print ""; - print " $pkg version \n"; + print " $pkgsane version \n"; } elsif (defined $src) { - my $v = $version || ""; + my $v = html_escape($version) || ""; + my $srcsane = html_escape($src); print ""; - print " $src version \n"; + print " $srcsane version \n"; } print " \n"; -my $includetags = join(" ", grep { !m/^subj:/i } split /[\s,]+/, $include); -my $excludetags = join(" ", grep { !m/^subj:/i } split /[\s,]+/, $exclude); -my $includesubj = join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } split /[\s,]+/, $include); -my $excludesubj = join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } split /[\s,]+/, $exclude); +my $includetags = html_escape(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include)); +my $excludetags = html_escape(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude)); +my $includesubj = html_escape(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include)); +my $excludesubj = html_escape(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude)); my $vismindays = ($mindays == 0 ? "" : $mindays); my $vismaxdays = ($maxdays == -1 ? "" : $maxdays); -my $sel_rmy = ($repeatmerged ? " selected" : ""); -my $sel_rmn = ($repeatmerged ? "" : " selected"); +my $sel_rmy = ($param{repeatmerged} ? " selected" : ""); +my $sel_rmn = ($param{repeatmerged} ? "" : " selected"); my $sel_ordraw = ($ordering eq "raw" ? " selected" : ""); -my $sel_ordold = ($ordering eq "old" ? " selected" : ""); +my $sel_ordold = ($ordering eq "oldview" ? " selected" : ""); my $sel_ordnor = ($ordering eq "normal" ? " selected" : ""); +my $sel_ordage = ($ordering eq "age" ? " selected" : ""); my $chk_bugrev = ($bug_rev ? " checked" : ""); my $chk_pendrev = ($pend_rev ? " checked" : ""); @@ -560,22 +565,28 @@ print <Categorise bugs by \n"; -my $default = 1; -for my $i (1..$cats) { - my $name = get_cat_name($i); - unless (defined $name) { - $name = "(unused)"; - $default = $i if $default == 0; - } - printf "\n", - $i, ($default == $i ? " selected" : ""), $i, $name; -} -my $defusers = $param{"cat${default}_users"} || $users; -print "\n"; -print "Include usertags set by\n"; -print "\n"; -print " \n"; - -for my $level (0..3) { - my $hlevel = $level + 1; - my ($n, $s, $t, $o) = - map { $param{"cat${default}_${_}${level}"} || "" } - ("nam", "pri", "ttl", "ord"); - - print <Level$hlevel -Name -Sections -Titles -Ordering -  -EOF -} - -print <Commit new ordering -EOF - -print "\n"; - print "
\n"; print "

$tail_html"; @@ -691,28 +631,28 @@ sub pkg_htmlindexentrystatus { my $showversions = ''; if (@{$status{found_versions}}) { my @found = @{$status{found_versions}}; - local $_; - s{/}{ } foreach @found; - $showversions .= join ', ', map htmlsanit($_), @found; + $showversions .= join ', ', map {s{/}{ }; html_escape($_)} @found; } if (@{$status{fixed_versions}}) { $showversions .= '; ' if length $showversions; $showversions .= 'fixed: '; my @fixed = @{$status{fixed_versions}}; - local $_; - s{/}{ } foreach @fixed; - $showversions .= join ', ', map htmlsanit($_), @fixed; + $showversions .= join ', ', map {s{/}{ }; html_escape($_)} @fixed; } - $result .= " ($showversions)" if length $showversions; + $result .= ' ($showversions)} if length $showversions; $result .= ";\n"; $result .= $showseverity; $result .= pkg_htmladdresslinks("Reported by: ", \&submitterurl, $status{originator}); - $result .= ";\nOwned by: " . htmlsanit($status{owner}) + $result .= ";\nOwned by: " . html_escape($status{owner}) if length $status{owner}; $result .= ";\nTags: " - . htmlsanit(join(", ", sort(split(/\s+/, $status{tags})))) + . html_escape(join(", ", sort(split(/\s+/, $status{tags})))) . "" if (length($status{tags})); @@ -723,43 +663,52 @@ sub pkg_htmlindexentrystatus { $result .= buglinklist(";\nBlocks ", ", ", split(/ /,$status{blocks})); - my $days = 0; if (length($status{done})) { - $result .= "
Done: " . htmlsanit($status{done}); - $days = ceil($debbugs::gRemoveAge - -M buglog($status{id})); - if ($days >= 0) { - $result .= ";\nWill be archived" . ( $days == 0 ? " today" : $days == 1 ? " in $days day" : " in $days days" ) . ""; - } else { - $result .= ";\nArchived"; + $result .= "
Done: " . html_escape($status{done}); + my $days = bug_archiveable(bug => $status{id}, + status => \%status, + days_until => 1, + ); + if ($days >= 0 and defined $status{location} and $status{location} ne 'archive') { + $result .= ";\nCan be archived" . ( $days == 0 ? " today" : $days == 1 ? " in $days day" : " in $days days" ) . ""; } + elsif (defined $status{location} and $status{location} eq 'archived') { + $result .= ";\nArchived."; + } } unless (length($status{done})) { if (length($status{forwarded})) { $result .= ";\nForwarded to " - . maybelink($status{forwarded}); + . join(', ', + map {maybelink($_)} + split /[,\s]+/,$status{forwarded} + ); } - my $daysold = int((time - $status{date}) / 86400); # seconds to days - if ($daysold >= 7) { + # Check the age of the logfile + my ($days_last,$eng_last) = secs_to_english(time - $status{log_modified}); + my ($days,$eng) = secs_to_english(time - $status{date}); + + if ($days >= 7) { my $font = ""; my $efont = ""; - $font = "em" if ($daysold > 30); - $font = "strong" if ($daysold > 60); + $font = "em" if ($days > 30); + $font = "strong" if ($days > 60); $efont = "" if ($font); $font = "<$font>" if ($font); - my $yearsold = int($daysold / 365); - $daysold -= $yearsold * 365; - - $result .= ";\n $font"; - my @age; - push @age, "1 year" if ($yearsold == 1); - push @age, "$yearsold years" if ($yearsold > 1); - push @age, "1 day" if ($daysold == 1); - push @age, "$daysold days" if ($daysold > 1); - $result .= join(" and ", @age); - $result .= " old$efont"; + $result .= ";\n ${font}$eng old$efont"; } + if ($days_last > 7) { + my $font = ""; + my $efont = ""; + $font = "em" if ($days_last > 30); + $font = "strong" if ($days_last > 60); + $efont = "" if ($font); + $font = "<$font>" if ($font); + + $result .= ";\n ${font}Modified $eng_last ago$efont"; + } } $result .= "."; @@ -777,7 +726,7 @@ sub pkg_htmlizebugs { my $header = ''; my $footer = "

Summary

\n"; - my @dummy = ($debbugs::gRemoveAge); #, @debbugs::gSeverityList, @debbugs::gSeverityDisplay); #, $debbugs::gHTMLExpireNote); + my @dummy = ($gRemoveAge); #, @gSeverityList, @gSeverityDisplay); #, $gHTMLExpireNote); if (@bugs == 0) { return "

No reports found!

\n"; @@ -796,27 +745,59 @@ sub pkg_htmlizebugs { ); my %section = (); + # Make the include/exclude map + my %include; + my %exclude; + for my $include (make_list($param{include})) { + next unless defined $include; + my ($key,$value) = split /\s*:\s*/,$include,2; + next unless defined $value; + push @{$include{$key}}, split /\s*,\s*/, $value; + } + for my $exclude (make_list($param{exclude})) { + next unless defined $exclude; + my ($key,$value) = split /\s*:\s*/,$exclude,2; + next unless defined $value; + push @{$exclude{$key}}, split /\s*,\s*/, $value; + } foreach my $bug (@bugs) { - my %status = %{getbugstatus($bug)}; + my %status = %{get_bug_status(bug=>$bug, + (exists $param{dist}?(dist => $param{dist}):()), + bugusertags => \%bugusertags, + (exists $param{version}?(version => $param{version}):()), + (exists $param{arch}?(arch => $param{arch}):()), + )}; next unless %status; - next if bugfilter($bug, %status); - - my $html = sprintf "
  • #%d: %s\n
    ", - bugurl($bug), $bug, htmlsanit($status{subject}); + next if bug_filter(bug => $bug, + status => \%status, + (exists $param{repeatmerged}?(repeat_merged => $param{repeatmerged}):()), + seen_merged => \%seenmerged, + (keys %include ? (include => \%include):()), + (keys %exclude ? (exclude => \%exclude):()), + ); + + my $html = sprintf "
  • #%d: %s\n
    ", + bug_url($bug), $bug, html_escape($status{subject}); $html .= pkg_htmlindexentrystatus(\%status) . "\n"; - + push @status, [ $bug, \%status, $html ]; + } + if ($bug_order eq 'age') { + # MWHAHAHAHA + @status = sort {$a->[1]{log_modified} <=> $b->[1]{log_modified}} @status; + } + elsif ($bug_order eq 'agerev') { + @status = sort {$b->[1]{log_modified} <=> $a->[1]{log_modified}} @status; + } + for my $entry (@status) { my $key = ""; for my $i (0..$#prior) { - my $v = get_bug_order_index($prior[$i], \%status); - my $k = $prior[$i]->[$v]; + my $v = get_bug_order_index($prior[$i], $entry->[1]); $count{"g_${i}_${v}"}++; $key .= "_$v"; } - $section{$key} .= $html; + $section{$key} .= $entry->[2]; $count{"_$key"}++; - - push @status, [ $bug, \%status, $html ]; } my $result = ""; @@ -829,20 +810,21 @@ sub pkg_htmlizebugs { push @keys_in_order, "X"; while ((my $k = shift @keys_in_order) ne "X") { for my $k2 (@{$o}) { + $k2+=0; push @keys_in_order, "${k}_${k2}"; } } } - for ( my $i = 0; $i <= $#keys_in_order; $i++ ) { - my $order = $keys_in_order[ $i ]; + for my $order (@keys_in_order) { next unless defined $section{$order}; my @ttl = split /_/, $order; shift @ttl; my $title = $title[0]->[$ttl[0]] . " bugs"; if ($#ttl > 0) { $title .= " -- "; - $title .= join("; ", grep {$_ ne ""} + $title .= join("; ", grep {($_ || "") ne ""} map { $title[$_]->[$ttl[$_]] } 1..$#ttl); } + $title = html_escape($title); my $count = $count{"_$order"}; my $bugs = $count == 1 ? "bug" : "bugs"; @@ -896,27 +878,14 @@ sub pkg_htmlpackagelinks { return 'Package' . (@pkglist > 1 ? 's' : '') . ': ' . join(', ', map { - '' . - $openstrong . htmlsanit($_) . $closestrong . '' + '' . + $openstrong . html_escape($_) . $closestrong . '' } @pkglist ); } sub pkg_htmladdresslinks { - my ($prefixfunc, $urlfunc, $addresses) = @_; - if (defined $addresses and $addresses ne '') { - my @addrs = getparsedaddrs($addresses); - my $prefix = (ref $prefixfunc) ? $prefixfunc->(scalar @addrs) - : $prefixfunc; - return $prefix . - join ', ', map { sprintf '%s', - $urlfunc->($_->address), - htmlsanit($_->format) || '(unknown)' - } @addrs; - } else { - my $prefix = (ref $prefixfunc) ? $prefixfunc->(1) : $prefixfunc; - return sprintf '%s(unknown)', $prefix, $urlfunc->(''); - } + htmlize_addresslinks(@_,'submitter'); } sub pkg_javascript { @@ -925,7 +894,7 @@ sub pkg_javascript {