X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=cgi%2Fcommon.pl;h=05b8941ac7f84f8a2d2e07b9556ba9c6cabf577c;hb=62cac6b6d596b6f29286adf2e6781405f9fd04e9;hp=4ab1cc423ed0666d0abfa5c6bf5f51dfd9e87f29;hpb=58865d12b2557d93e684c550e8f1de6aa377dc24;p=debbugs.git diff --git a/cgi/common.pl b/cgi/common.pl index 4ab1cc4..05b8941 100644 --- a/cgi/common.pl +++ b/cgi/common.pl @@ -3,17 +3,29 @@ use DB_File; use Fcntl qw/O_RDONLY/; use Mail::Address; -use MLDBM qw/DB_File/; +use MLDBM qw(DB_File Storable); use POSIX qw/ceil/; +use URI::Escape; + +use Debbugs::Config qw(:globals :text); $config_path = '/etc/debbugs'; $lib_path = '/usr/lib/debbugs'; -require "$lib_path/errorlib"; +#require "$lib_path/errorlib"; +use Debbugs::Packages qw(:versions :mapping); use Debbugs::Versions; +use Debbugs::MIME qw(decode_rfc1522); +use Debbugs::Common qw(:util); +use Debbugs::Status qw(:status :read :versions); +use Debbugs::CGI qw(:all); +use Debbugs::Bugs qw(count_bugs); $MLDBM::RemoveTaint = 1; +my %common_bugusertags; +my $common_mindays = 0; +my $common_maxdays = -1; my $common_archive = 0; my $common_repeatmerged = 1; my %common_include = (); @@ -21,6 +33,8 @@ my %common_exclude = (); my $common_raw_sort = 0; my $common_bug_reverse = 0; +my $common_leet_urls = 0; + my %common_reverse = ( 'pending' => 0, 'severity' => 0, @@ -46,6 +60,7 @@ sub contains_field_match { sub detect_user_agent { my $userAgent = $ENV{HTTP_USER_AGENT}; + return { 'name' => 'unknown' } unless defined $userAgent; return { 'name' => 'links' } if ( $userAgent =~ m,^ELinks,); return { 'name' => 'lynx' } if ( $userAgent =~ m,^Lynx,); return { 'name' => 'wget' } if ( $userAgent =~ m,^Wget,); @@ -53,6 +68,7 @@ sub detect_user_agent { return { 'name' => 'ie' } if ( $userAgent =~ m,^.*MSIE.*,); return { 'name' => 'unknown' }; } + my %field_match = ( 'subject' => \&contains_field_match, 'tags' => sub { @@ -72,7 +88,7 @@ my %field_match = ( my @common_grouping = ( 'severity', 'pending' ); my %common_grouping_order = ( 'pending' => [ qw( pending forwarded pending-fixed fixed done absent ) ], - 'severity' => \@debbugs::gSeverityList, + 'severity' => \@gSeverityList, ); my %common_grouping_display = ( 'pending' => 'Status', @@ -87,7 +103,7 @@ my %common_headers = ( "forwarded" => "forwarded to upstream software authors", "absent" => "not applicable to this version", }, - 'severity' => \%debbugs::gSeverityDisplay, + 'severity' => \%gSeverityDisplay, ); my $common_version; @@ -95,6 +111,8 @@ my $common_dist; my $common_arch; my $debug = 0; +my $use_bug_idx = 0; +my %bugidx; sub array_option($) { my ($val) = @_; @@ -127,6 +145,17 @@ sub filter_option($$\%) { sub set_option { my ($opt, $val) = @_; + if ($opt eq "use-bug-idx") { + $use_bug_idx = $val; + if ( $val ) { + $common_headers{pending}{open} = $common_headers{pending}{pending}; + my $bugidx = tie %bugidx, MLDBM => "$gSpoolDir/realtime/bug.idx", O_RDONLY + or quitcgi( "$0: can't open $gSpoolDir/realtime/bug.idx ($!)\n" ); + $bugidx->RemoveTaint(1); + } else { + untie %bugidx; + } + } if ($opt =~ m/^show_list_(foot|head)er$/) { $common{$opt} = $val; } if ($opt eq "archive") { $common_archive = $val; } if ($opt eq "repeatmerged") { $common_repeatmerged = $val; } @@ -155,19 +184,37 @@ sub set_option { if ($opt eq "version") { $common_version = $val; } if ($opt eq "dist") { $common_dist = $val; } if ($opt eq "arch") { $common_arch = $val; } + if ($opt eq "maxdays") { $common_maxdays = $val; } + if ($opt eq "mindays") { $common_mindays = $val; } + if ($opt eq "bugusertags") { %common_bugusertags = %{$val}; } } sub readparse { - my ($in, $key, $val, %ret); + my ($key, $val, %ret); + my $in = ""; + if ($#ARGV >= 0) { + $in .= ";" . join("&", map { s/&/%26/g; s/;/%3b/g; $_ } @ARGV); + } if (defined $ENV{"QUERY_STRING"} && $ENV{"QUERY_STRING"} ne "") { - $in=$ENV{QUERY_STRING}; - } elsif(defined $ENV{"REQUEST_METHOD"} - && $ENV{"REQUEST_METHOD"} eq "POST") + $in .= ";" . $ENV{QUERY_STRING}; + } + if (defined $ENV{"REQUEST_METHOD"} && $ENV{"REQUEST_METHOD"} eq "POST" + && defined $ENV{"CONTENT_TYPE"} + && $ENV{"CONTENT_TYPE"} eq "application/x-www-form-urlencoded") { - read(STDIN,$in,$ENV{CONTENT_LENGTH}); - } else { - return; + my $inx; + read(STDIN,$inx,$ENV{CONTENT_LENGTH}); + $in .= ";" . $inx; + } + return unless ($in ne ""); + + if (defined $ENV{"HTTP_COOKIE"}) { + my $x = $ENV{"HTTP_COOKIE"}; + $x =~ s/;\s+/;/g; + $in = "$x;$in"; } + $in =~ s/&/;/g; + $in =~ s/;;+/;/g; $in =~ s/^;//; $in =~ s/;$//; foreach (split(/[&;]/,$in)) { s/\+/ /g; ($key, $val) = split(/=/,$_,2); @@ -181,83 +228,35 @@ sub readparse { } $ret{$key}=$val; } -$debug = 1 if (defined $ret{"debug"} && $ret{"debug"} eq "aj"); - return %ret; -} -sub quitcgi { - my $msg = shift; - print "Content-Type: text/html\n\n"; - print "Error\n"; - print "An error occurred. Dammit.\n"; - print "Error was: $msg.\n"; - print "\n"; - exit 0; -} +$debug = 1 if (defined $ret{"debug"} && $ret{"debug"} eq "aj"); -#sub abort { -# my $msg = shift; -# my $Archive = $common_archive ? "archive" : ""; -# print header . start_html("Sorry"); -# print "Sorry bug #$msg doesn't seem to be in the $Archive database.\n"; -# print end_html; -# exit 0; -#} - -# Split a package string from the status file into a list of package names. -sub splitpackages { - my $pkgs = shift; - return unless defined $pkgs; - return map lc, split /[ \t?,()]+/, $pkgs; -} + $common_leet_urls = 1 + if (defined $ret{"leeturls"} && $ret{"leeturls"} eq "yes"); -my %_parsedaddrs; -sub getparsedaddrs { - my $addr = shift; - return () unless defined $addr; - return @{$_parsedaddrs{$addr}} if exists $_parsedaddrs{$addr}; - @{$_parsedaddrs{$addr}} = Mail::Address->parse($addr); - return @{$_parsedaddrs{$addr}}; + return %ret; } # Generate a comma-separated list of HTML links to each package given in # $pkgs. $pkgs may be empty, in which case an empty string is returned, or # it may be a comma-separated list of package names. sub htmlpackagelinks { - my $pkgs = shift; - return unless defined $pkgs and $pkgs ne ''; - my $strong = shift; - my @pkglist = splitpackages($pkgs); - - my $openstrong = $strong ? '' : ''; - my $closestrong = $strong ? '' : ''; - - return 'Package' . (@pkglist > 1 ? 's' : '') . ': ' . - join(', ', - map { - '' . - $openstrong . htmlsanit($_) . $closestrong . '' - } @pkglist - ) . ";\n"; + return htmlize_packagelinks(@_); +} + +# Generate a comma-separated list of HTML links to each address given in +# $addresses, which should be a comma-separated list of RFC822 addresses. +# $urlfunc should be a reference to a function like mainturl or submitterurl +# which returns the URL for each individual address. +sub htmladdresslinks { + htmlize_addresslinks(@_); } # Generate a comma-separated list of HTML links to each maintainer given in # $maints, which should be a comma-separated list of RFC822 addresses. sub htmlmaintlinks { my ($prefixfunc, $maints) = @_; - if (defined $maints and $maints ne '') { - my @maintaddrs = getparsedaddrs($maints); - my $prefix = (ref $prefixfunc) ? $prefixfunc->(scalar @maintaddrs) - : $prefixfunc; - return $prefix . - join ', ', map { sprintf '%s', - mainturl($_->address), - htmlsanit($_->format) || '(unknown)' - } @maintaddrs; - } else { - my $prefix = (ref $prefixfunc) ? $prefixfunc->(1) : $prefixfunc; - return sprintf '%s(unknown)', $prefix, mainturl(''); - } + return htmladdresslinks($prefixfunc, \&mainturl, $maints); } sub htmlindexentry { @@ -282,16 +281,34 @@ sub htmlindexentrystatus { } $result .= htmlpackagelinks($status{"package"}, 1); + + my $showversions = ''; + if (@{$status{found_versions}}) { + my @found = @{$status{found_versions}}; + local $_; + s{/}{ } foreach @found; + $showversions .= join ', ', map htmlsanit($_), @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; + } + $result .= " ($showversions)" if length $showversions; + $result .= ";\n"; + $result .= $showseverity; - $result .= "Reported by: " . htmlsanit($status{originator}) . ""; + $result .= htmladdresslinks("Reported by: ", \&submitterurl, + $status{originator}); $result .= ";\nOwned by: " . htmlsanit($status{owner}) if length $status{owner}; $result .= ";\nTags: " . htmlsanit(join(", ", sort(split(/\s+/, $status{tags})))) . "" if (length($status{tags})); - my @merged= split(/ /,$status{mergedwith}); my $mseparator= ";\nmerged with "; for my $m (@merged) { @@ -299,24 +316,9 @@ sub htmlindexentrystatus { $mseparator= ", "; } - if (@{$status{found_versions}}) { - $result .= ";\nfound in "; - $result .= (@{$status{found_versions}} == 1) ? 'version ' - : 'versions '; - $result .= join ', ', map htmlsanit($_), @{$status{found_versions}}; - } - - if (@{$status{fixed_versions}}) { - $result .= ";\nfixed in "; - $result .= (@{$status{fixed_versions}} == 1) ? 'version ' - : 'versions '; - $result .= join ', ', map htmlsanit($_), @{$status{fixed_versions}}; - if (length($status{done})) { - $result .= ' by ' . htmlsanit($status{done}); - } - } elsif (length($status{done})) { + if (length($status{done})) { $result .= ";\nDone: " . htmlsanit($status{done}); - $days = ceil($debbugs::gRemoveAge - -M buglog($status{id})); + $days = ceil($gRemoveAge - -M buglog($status{id})); if ($days >= 0) { $result .= ";\nWill be archived:" . ( $days == 0 ? " today" : $days == 1 ? " in $days day" : " in $days days" ); } else { @@ -359,52 +361,39 @@ sub htmlindexentrystatus { sub urlargs { my $args = ''; - $args .= "&archive=yes" if $common_archive; - $args .= "&repeatmerged=no" unless $common_repeatmerged; - $args .= "&version=$common_version" if defined $common_version; - $args .= "&dist=$common_dist" if defined $common_dist; - $args .= "&arch=$common_arch" if defined $common_arch; + $args .= ";archive=yes" if $common_archive; + $args .= ";repeatmerged=no" unless $common_repeatmerged; + $args .= ";mindays=${common_mindays}" unless $common_mindays == 0; + $args .= ";maxdays=${common_maxdays}" unless $common_maxdays == -1; + $args .= ";version=$common_version" if defined $common_version; + $args .= ";dist=$common_dist" if defined $common_dist; + $args .= ";arch=$common_arch" if defined $common_arch; return $args; } -sub submitterurl { - my $ref = shift || ""; - my $params = "submitter=" . emailfromrfc822($ref); - $params .= urlargs(); - return urlsanit("pkgreport.cgi" . "?" . $params); -} - -sub mainturl { - my $ref = shift || ""; - my $params = "maint=" . emailfromrfc822($ref); - $params .= urlargs(); - return urlsanit("pkgreport.cgi" . "?" . $params); -} - -sub pkgurl { - my $ref = shift; - my $params = "pkg=$ref"; - $params .= urlargs(); - return urlsanit("pkgreport.cgi" . "?" . "$params"); -} - -sub srcurl { - my $ref = shift; - my $params = "src=$ref"; - $params .= urlargs(); - return urlsanit("pkgreport.cgi" . "?" . "$params"); -} +sub pkgurl { pkg_url(pkg => $_[0] || ""); } +sub srcurl { pkg_url(src => $_[0] || ""); } +sub tagurl { pkg_url(tag => $_[0] || ""); } -sub tagurl { +sub pkg_etc_url { my $ref = shift; - my $params = "tag=$ref"; - $params .= urlargs(); - return urlsanit("pkgreport.cgi" . "?" . "$params"); + my $code = shift; + if ($common_leet_urls) { + $code = "package" if ($code eq "pkg"); + $code = "source" if ($code eq "src"); + return urlsanit("/x/$code/$ref"); + } else { + my $addurlargs = shift || 1; + my $params = "$code=$ref"; + $params .= urlargs() if $addurlargs; + return urlsanit("pkgreport.cgi" . "?" . $params); + } } sub urlsanit { my $url = shift; $url =~ s/%/%25/g; + $url =~ s/#/%23/g; $url =~ s/\+/%2b/g; my %saniarray = ('<','lt', '>','gt', '&','amp', '"','quot'); $url =~ s/([<>&"])/\&$saniarray{$1};/g; @@ -418,53 +407,54 @@ sub htmlsanit { return $in; } -sub maybelink { - my $in = shift; - if ($in =~ /^[a-zA-Z0-9+.-]+:/) { # RFC 1738 scheme - return qq{} . htmlsanit($in) . ''; - } else { - return htmlsanit($in); - } -} - sub bugurl { my $ref = shift; my $params = "bug=$ref"; - foreach my $val (@_) { - $params .= "\&msg=$1" if ($val =~ /^msg=([0-9]+)/); - $params .= "\&archive=yes" if (!$common_archive && $val =~ /^archive.*$/); - } - $params .= "&archive=yes" if ($common_archive); - $params .= "&repeatmerged=no" unless ($common_repeatmerged); + my $filename = ''; - return urlsanit("bugreport.cgi" . "?" . "$params"); -} + if ($common_leet_urls) { + my $msg = ""; + my $mbox = ""; + my $att = ""; + foreach my $val (@_) { + $mbox = "/mbox" if ($val eq "mbox"); + $msg = "/$1" if ($val =~ /^msg=([0-9]+)/); + $att = "/$1" if ($val =~ /^att=([0-9]+)/); + $filename = "/$1" if ($val =~ /^filename=(.*)$/); + } + my $ext = ""; + if ($mbox ne "") { + $ext = $mbox; + } elsif ($att ne "") { + $ext = "$att$filename"; + } + return urlsanit("/x/$ref$msg$ext"); + } else { + foreach my $val (@_) { + $params .= ";mbox=yes" if ($val eq "mbox"); + $params .= ";msg=$1" if ($val =~ /^msg=([0-9]+)/); + $params .= ";att=$1" if ($val =~ /^att=([0-9]+)/); + $filename = $1 if ($val =~ /^filename=(.*)$/); + $params .= ";archive=yes" if (!$common_archive && $val =~ /^archive.*$/); + } + $params .= ";archive=yes" if ($common_archive); + $params .= ";repeatmerged=no" unless ($common_repeatmerged); -sub dlurl { - my $ref = shift; - my $params = "bug=$ref"; - my $filename = ''; - foreach my $val (@_) { - $params .= "\&$1=$2" if ($val =~ /^(msg|att)=([0-9]+)/); - $filename = $1 if ($val =~ /^filename=(.*)$/); - } - $params .= "&archive=yes" if ($common_archive); - my $pathinfo = ''; - $pathinfo = "/$filename" if $filename ne ''; + my $pathinfo = ''; + $pathinfo = '/'.uri_escape($filename) if $filename ne ''; - return urlsanit("bugreport.cgi$pathinfo?$params"); + return urlsanit("bugreport.cgi" . $pathinfo . "?" . $params); + } } -sub mboxurl { - my $ref = shift; - return urlsanit("bugreport.cgi" . "?" . "bug=$ref&mbox=yes"); -} +sub dlurl { bugurl(@_); } +sub mboxurl { return bugurl($ref, "mbox"); } sub allbugs { return @{getbugs(sub { 1 })}; } -sub bugmatches(\%\%) { +sub bugmatches { my ($hash, $status) = @_; foreach my $key( keys( %$hash ) ) { my $value = $hash->{$key}; @@ -473,16 +463,19 @@ sub bugmatches(\%\%) { } return 0; } -sub bugfilter($%) { - my ($bug, %status) = @_; - our (%seenmerged); - if (%common_include) { - return 1 if (!bugmatches(%common_include, %status)); +sub bugfilter { + my ($bug, $status,$seen_merged,$common_include,$common_exclude,$repeat_merged,) = @_; + #our (%seenmerged); + if ($common_include) { + return 1 if (!bugmatches($common_include, $status)); } - if (%common_exclude) { - return 1 if (bugmatches(%common_exclude, %status)); + if ($common_exclude) { + return 1 if (bugmatches($common_exclude, $status)); } my @merged = sort {$a<=>$b} $bug, split(/ /, $status{mergedwith}); + my $daysold = int((time - $status{date}) / 86400); # seconds to days + return 1 unless ($common_mindays <= $daysold); + return 1 unless ($common_maxdays == -1 || $daysold <= $common_maxdays); return 1 unless ($common_repeatmerged || !$seenmerged{$merged[0]}); $seenmerged{$merged[0]} = 1; return 0; @@ -495,7 +488,8 @@ sub htmlizebugs { my @status = (); my %count; - my ($header, $footer); + my $header = ''; + my $footer = ''; if (@bugs == 0) { return "

No reports found!

\n"; @@ -587,33 +581,15 @@ sub htmlizebugs { } $result = $header . $result if ( $common{show_list_header} ); - $result .= $debbugs::gHTMLExpireNote if $gRemoveAge and $anydone; + $result .= $gHTMLExpireNote if $gRemoveAge and $anydone; $result .= "
" . $footer if ( $common{show_list_footer} ); return $result; } sub countbugs { - my $bugfunc = shift; - if ($common_archive) { - open I, "<$debbugs::gSpoolDir/index.archive" - or &quitcgi("$debbugs::gSpoolDir/index.archive: $!"); - } else { - open I, "<$debbugs::gSpoolDir/index.db" - or &quitcgi("$debbugs::gSpoolDir/index.db: $!"); - } - - my %count = (); - while() - { - if (m/^(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+\[\s*([^]]*)\s*\]\s+(\w+)\s+(.*)$/) { - my @x = $bugfunc->(pkg => $1, bug => $2, status => $4, - submitter => $5, severity => $6, tags => $7); - local $_; - $count{$_}++ foreach @x; - } - } - close I; - return %count; + return count_bugs(function=>shift, + archive => $commonarchive, + ); } sub getbugs { @@ -622,28 +598,35 @@ sub getbugs { my @result = (); - if (!$common_archive && defined $opt && - -e "$debbugs::gSpoolDir/by-$opt.idx") - { + my $fastidx; + if (!defined $opt) { + # leave $fastidx undefined; + } elsif (!$common_archive) { + $fastidx = "$gSpoolDir/by-$opt.idx"; + } else { + $fastidx = "$gSpoolDir/by-$opt-arc.idx"; + } + + if (defined $fastidx && -e $fastidx) { my %lookup; print STDERR "optimized\n" if ($debug); - tie %lookup, DB_File => "$debbugs::gSpoolDir/by-$opt.idx", O_RDONLY - or die "$0: can't open $debbugs::gSpoolDir/by-$opt.idx ($!)\n"; + tie %lookup, MLDBM => $fastidx, O_RDONLY + or die "$0: can't open $fastidx ($!)\n"; while ($key = shift) { my $bugs = $lookup{$key}; if (defined $bugs) { - push @result, (unpack 'N*', $bugs); + push @result, keys %{$bugs}; } } untie %lookup; print STDERR "done optimized\n" if ($debug); } else { if ( $common_archive ) { - open I, "<$debbugs::gSpoolDir/index.archive" - or &quitcgi("$debbugs::gSpoolDir/index.archive: $!"); + open I, "<$gSpoolDir/index.archive" + or &quitcgi("$gSpoolDir/index.archive: $!"); } else { - open I, "<$debbugs::gSpoolDir/index.db" - or &quitcgi("$debbugs::gSpoolDir/index.db: $!"); + open I, "<$gSpoolDir/index.db" + or &quitcgi("$gSpoolDir/index.db: $!"); } while() { if (m/^(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+\[\s*([^]]*)\s*\]\s+(\w+)\s+(.*)$/) { @@ -685,194 +668,35 @@ sub maintencoded { return $encoded; } -my $_maintainer; -sub getmaintainers { - return $_maintainer if $_maintainer; - my %maintainer; - - open(MM,"$gMaintainerFile") or &quitcgi("open $gMaintainerFile: $!"); - while() { - next unless m/^(\S+)\s+(\S.*\S)\s*$/; - ($a,$b)=($1,$2); - $a =~ y/A-Z/a-z/; - $maintainer{$a}= $b; - } - close(MM); - if (defined $gMaintainerFileOverride) { - open(MM,"$gMaintainerFileOverride") or &quitcgi("open $gMaintainerFileOverride: $!"); - while() { - next unless m/^(\S+)\s+(\S.*\S)\s*$/; - ($a,$b)=($1,$2); - $a =~ y/A-Z/a-z/; - $maintainer{$a}= $b; - } - close(MM); - } - $_maintainer = \%maintainer; - return $_maintainer; -} - -my $_pkgsrc; -my $_pkgcomponent; -sub getpkgsrc { - return $_pkgsrc if $_pkgsrc; - return {} unless defined $gPackageSource; - my %pkgsrc; - my %pkgcomponent; - - open(MM,"$gPackageSource") or &quitcgi("open $gPackageSource: $!"); - while() { - next unless m/^(\S+)\s+(\S+)\s+(\S.*\S)\s*$/; - ($a,$b,$c)=($1,$2,$3); - $a =~ y/A-Z/a-z/; - $pkgsrc{$a}= $c; - $pkgcomponent{$a}= $b; - } - close(MM); - $_pkgsrc = \%pkgsrc; - $_pkgcomponent = \%pkgcomponent; - return $_pkgsrc; -} - -sub getpkgcomponent { - return $_pkgcomponent if $_pkgcomponent; - getpkgsrc(); - return $_pkgcomponent; -} - -my $_pseudodesc; -sub getpseudodesc { - return $_pseudodesc if $_pseudodesc; - my %pseudodesc; - - open(PSEUDO, "< $gPseudoDescFile") or &quitcgi("open $gPseudoDescFile: $!"); - while() { - next unless m/^(\S+)\s+(\S.*\S)\s*$/; - $pseudodesc{lc $1} = $2; - } - close(PSEUDO); - $_pseudodesc = \%pseudodesc; - return $_pseudodesc; -} sub getbugstatus { - my $bugnum = shift; - - my %status; - - my $location = getbuglocation( $bugnum, 'summary' ); - return {} if ( !$location ); - %status = %{ readbug( $bugnum, $location ) }; - $status{ id } = $bugnum; - - $status{found_versions} = []; - $status{fixed_versions} = []; - if (defined $gVersionBugsDir and - (defined $common_version or defined $common_dist)) { - my $bughash = get_hashname($bugnum); - if (open BUGVER, "< $gVersionBugsDir/$bughash/$bugnum.versions") { - local $_; - while () { - if (/^Found-in: (.*)/i) { - $status{found_versions} = [split ' ', $1]; - } elsif (/^Fixed-in: (.*)/i) { - $status{fixed_versions} = [split ' ', $1]; - } - } - close BUGVER; - } - } - - $status{tags} = $status{keywords}; - my %tags = map { $_ => 1 } split ' ', $status{tags}; - - $status{"package"} =~ s/\s*$//; - $status{"package"} = 'unknown' if ($status{"package"} eq ''); - $status{"severity"} = 'normal' if ($status{"severity"} eq ''); + my ($bug) = @_; + return get_bug_status(bug => $bug, + $use_bug_idx?(bug_index => \%bugidx):(), + usertags => \%common_bugusertags, + (defined $common_dist)?(dist => $common_dist):(), + (defined $common_version)?(version => $common_version):(), + (defined $common_arch)?(arch => $common_arch):(), + ); +} - $status{"pending"} = 'pending'; - $status{"pending"} = 'forwarded' if (length($status{"forwarded"})); - $status{"pending"} = 'pending-fixed' if ($tags{pending}); - $status{"pending"} = 'fixed' if ($tags{fixed}); +sub getversiondesc { + my $pkg = shift; - my $version; if (defined $common_version) { - $version = $common_version; + return "version $common_version"; } elsif (defined $common_dist) { - $version = getversion($status{package}, $common_dist, $common_arch); - } - - if (defined $version) { - my $buggy = buggyversion($bugnum, $version, \%status); - if ($buggy eq 'absent') { - $status{"pending"} = 'absent'; - } elsif ($buggy eq 'fixed') { - $status{"pending"} = 'done'; + my @distvers = getversions($pkg, $common_dist, $common_arch); + @distvers = sort @distvers; + local $" = ', '; + if (@distvers > 1) { + return "versions @distvers"; + } elsif (@distvers == 1) { + return "version @distvers"; } } - - if (length($status{done}) and - (not defined $version or not @{$status{fixed_versions}})) { - $status{"pending"} = 'done'; - } - - return \%status; -} - -sub getsrcpkgs { - my $src = shift; - return () if !$src; - my %pkgsrc = %{getpkgsrc()}; - my @pkgs; - foreach ( keys %pkgsrc ) { - push @pkgs, $_ if $pkgsrc{$_} eq $src; - } - return @pkgs; -} - -sub buglog { - my $bugnum = shift; - my $location = getbuglocation($bugnum, 'log'); - return undef unless defined $location; - return getbugcomponent($bugnum, 'log', $location); -} - -my %_versionobj; -sub buggyversion { - my ($bug, $ver, $status) = @_; - return '' unless defined $gVersionPackagesDir; - my $src = getpkgsrc()->{$status->{package}}; - $src = $status->{package} unless defined $src; - - my $tree; - if (exists $_versionobj{$src}) { - $tree = $_versionobj{$src}; - } else { - $tree = Debbugs::Versions->new(\&DpkgVer::vercmp); - if (open VERFILE, "< $gVersionPackagesDir/$src") { - $tree->load(\*VERFILE); - close VERFILE; - } - $_versionobj{$src} = $tree; - } - - return $tree->buggy($ver, $status->{found_versions}, - $status->{fixed_versions}); -} - -my %_versions; -sub getversion { - my ($pkg, $dist, $arch) = @_; - return undef unless defined $gVersionIndex; - $dist = 'unstable' unless defined $dist; - $arch = 'i386' unless defined $arch; - - unless (tied %_versions) { - tie %_versions, 'MLDBM', $gVersionIndex, O_RDONLY - or die "can't open versions index: $!"; - } - return $_versions{$pkg}{$dist}{$arch}; + return undef; } 1;