X-Git-Url: https://git.deb.at/?a=blobdiff_plain;ds=sidebyside;f=cgi-bin%2Fsearch_packages.pl;h=da41da04cd7950306e85a179c301b8b563f5262e;hb=68f4ac9132dd489ef93927f1453122be66ea75d5;hp=bc51c30f66c3ce0fbc0e479dca8ea1f5f28cbba7;hpb=e41d34b008ea4b4ad09b5eea457d7523c7ef2fa3;p=deb%2Fpackages.git diff --git a/cgi-bin/search_packages.pl b/cgi-bin/search_packages.pl index bc51c30..da41da0 100755 --- a/cgi-bin/search_packages.pl +++ b/cgi-bin/search_packages.pl @@ -1,20 +1,19 @@ #!/usr/bin/perl -wT -# +# $Id$ # search_packages.pl -- CGI interface to the Packages files on packages.debian.org # # Copyright (C) 1998 James Treacy # Copyright (C) 2000, 2001 Josip Rodin # Copyright (C) 2001 Adam Heath # Copyright (C) 2004 Martin Schulze -# Copyright (C) 2004 Frank Lichtenheld +# Copyright (C) 2004-2006 Frank Lichtenheld # # use is allowed under the terms of the GNU Public License (GPL) # see http://www.fsf.org/copyleft/gpl.html for a copy of the license -require 5.001; use strict; use CGI qw( -oldstyle_urls ); -#use CGI::Carp qw( fatalsToBrowser ); +use CGI::Carp qw( fatalsToBrowser ); use POSIX; use URI::Escape; use HTML::Entities; @@ -27,58 +26,94 @@ use Deb::Versions; use Packages::Search qw( :all ); use Packages::HTML (); -my $thisscript = "search_packages.pl"; -my $use_grep = 1; +my $thisscript = $Packages::HTML::SEARCH_CGI; my $HOME = "http://www.debian.org"; my $ROOT = ""; my $SEARCHPAGE = "http://packages.debian.org/"; my @SUITES = qw( oldstable stable testing unstable experimental ); -my @DISTS = @SUITES; my @SECTIONS = qw( main contrib non-free ); my @ARCHIVES = qw( us security installer ); my @ARCHITECTURES = qw( alpha amd64 arm hppa hurd-i386 i386 ia64 kfreebsd-i386 mips mipsel powerpc s390 sparc ); +my %SUITES = map { $_ => 1 } @SUITES; +my %SECTIONS = map { $_ => 1 } @SECTIONS; +my %ARCHIVES = map { $_ => 1 } @ARCHIVES; +my %ARCHITECTURES = map { $_ => 1 } @ARCHITECTURES; $ENV{PATH} = "/bin:/usr/bin"; # Read in all the variables set by the form -my $input = new CGI; +my $input; +if ($ARGV[0] && ($ARGV[0] eq 'php')) { + $input = new CGI(\*STDIN); +} else { + $input = new CGI; +} my $pet0 = new Benchmark; # use this to disable debugging in production mode completly -my $debug_allowed = 0; +my $debug_allowed = 1; my $debug = $debug_allowed && $input->param("debug"); -$Search::Param::debug = 1 if $debug > 1; +$debug = 0 if not defined($debug); +#$Packages::Search::debug = 1 if $debug > 1; # If you want, just print out a list of all of the variables and exit. -print $input->header if $debug; +#print $input->header if $debug; # print $input->dump; # exit; -my %params_def = ( keywords => { default => undef, match => '^\s*([-+\@\w\/.:]+)\s*$' }, +if (my $path = $input->param('path')) { + my @components = map { lc $_ } split /\//, $path; + + foreach (@components) { + if ($SUITES{$_}) { + $input->param('suite', $_); + } elsif ($SECTIONS{$_}) { + $input->param('section', $_); + } elsif ($ARCHIVES{$_}) { + $input->param('archive', $_); + }elsif ($ARCHITECTURES{$_}) { + $input->param('arch', $_); + } + } +} + +my ( $format, $keyword, $case, $subword, $exact, $searchon, + @suites, @sections, @archs ); + +my %params_def = ( keywords => { default => undef, + match => '^\s*([-+\@\w\/.:]+)\s*$', + var => \$keyword }, suite => { default => 'stable', match => '^(\w+)$', alias => 'version', array => ',', + var => \@suites, replace => { all => \@SUITES } }, - case => { default => 'insensitive', match => '^(\w+)$' }, - official => { default => 0, match => '^(\w+)$' }, - use_cache => { default => 1, match => '^(\w+)$' }, - subword => { default => 0, match => '^(\w+)$' }, - exact => { default => undef, match => '^(\w+)$' }, - searchon => { default => 'all', match => '^(\w+)$' }, + case => { default => 'insensitive', match => '^(\w+)$', + var => \$case }, +# official => { default => 0, match => '^(\w+)$' }, +# use_cache => { default => 1, match => '^(\w+)$' }, + subword => { default => 0, match => '^(\w+)$', + var => \$subword }, + exact => { default => undef, match => '^(\w+)$', + var => \$exact }, + searchon => { default => 'all', match => '^(\w+)$', + var => \$searchon }, section => { default => 'all', match => '^([\w-]+)$', alias => 'release', array => ',', + var => \@sections, replace => { all => \@SECTIONS } }, arch => { default => 'any', match => '^(\w+)$', - array => ',', replace => + array => ',', var => \@archs, replace => { any => \@ARCHITECTURES } }, archive => { default => 'all', match => '^(\w+)$', array => ',', replace => { all => \@ARCHIVES } }, - format => { default => 'html', match => '^(\w+)$' }, + format => { default => 'html', match => '^(\w+)$', + var => \$format }, ); -my %params = Packages::Search::parse_params( $input, \%params_def ); +my %opts; +my %params = Packages::Search::parse_params( $input, \%params_def, \%opts ); -my $format = $params{values}{format}{final}; #XXX: Don't use alternative output formats yet $format = 'html'; @@ -89,24 +124,61 @@ if ($format eq 'html') { print $input->header( -type=>'text/plain' ); } +my (@errors, @debug, @msgs, @hints); +sub error { + push @errors, $_[0]; +} +sub hint { + push @hints, $_[0]; +} +sub debug { + my $lvl = $_[1] || 0; + push(@debug, $_[0]) if $debug > $lvl; +} +sub msg { + push @msgs, $_[0]; +} +sub print_errors { + return unless @errors; + print '
'; + foreach (@errors) { + print "

$_

"; + } + print '
'; +} +sub print_debug { + return unless $debug && @debug; + print '
'; + print '

Debugging:

';
+    foreach (@debug) {
+	print "$_\n";
+    }
+    print '
'; + +} +sub print_hints { + return unless @hints; + print '
'; + foreach (@hints) { + print "

$_

"; + } + print '
'; +} +sub print_msgs { + foreach (@msgs) { + print "

$_

"; + } +} + if ($params{errors}{keywords}) { - print "Error: keyword not valid or missing" if $format eq 'html'; - exit 0; + error( "Error: keyword not valid or missing" ); } -my $keyword = $params{values}{keywords}{final}; -my @suites = @{$params{values}{suite}{final}}; -my $official = $params{values}{official}{final}; -my $use_cache = $params{values}{use_cache}{final}; -my $case = $params{values}{case}{final}; + my $case_bool = ( $case !~ /insensitive/ ); -my $subword = $params{values}{subword}{final}; -my $exact = $params{values}{exact}{final}; $exact = !$subword unless defined $exact; -my $searchon = $params{values}{searchon}{final}; -my @sections = @{$params{values}{section}{final}}; -my @archs = @{$params{values}{arch}{final}}; -my $page = $params{values}{page}{final}; -my $results_per_page = $params{values}{number}{final}; +$opts{h_suites} = { map { $_ => 1 } @suites }; +$opts{h_sections} = { map { $_ => 1 } @sections }; +$opts{h_archs} = { map { $_ => 1 } @archs }; # for URL construction my $suites_param = join ',', @{$params{values}{suite}{no_replace}}; @@ -121,209 +193,205 @@ my $sections_enc = encode_entities join ', ', @{$params{values}{section}{no_repl my $archs_enc = encode_entities join ', ', @{$params{values}{arch}{no_replace}}; my $pet1 = new Benchmark; my $petd = timediff($pet1, $pet0); -print "DEBUG: Parameter evaluation took ".timestr($petd)."
" if $debug; - -if ($format eq 'html') { -print Packages::HTML::header( title => 'Package Search Results' , - lang => 'en', - title_tag => 'Debian Package Search Results', - print_title_above => 1, - print_search_field => 'packages', - search_field_values => { - keywords => $keyword_enc, - searchon => $searchon, - arch => $archs_enc, - suite => $suites_enc, - section => $sections_enc, - subword => $subword, - exact => $exact, - case => $case, - }, - ); -} +debug( "Parameter evaluation took ".timestr($petd) ); # read the configuration my $topdir; if (!open (C, "../config.sh")) { - print "\nInternal Error: Cannot open configuration file.\n\n" if $format eq 'html'; - exit 0; + error( "Internal Error: Cannot open configuration file." ); } while () { - $topdir = $1 if (/^\s*topdir="?(.*)"?\s*$/); + $topdir = $1 if /^\s*topdir="?(.*)"?\s*$/; + $ROOT = $1 if /^\s*root="?(.*)"?\s*$/; } close (C); -my $FLATDIR = $topdir . "/files/flat"; +my $DBDIR = $topdir . "/files/db"; my $search_on_sources = 0; -my %descr; -my %sections; +my $st0 = new Benchmark; +my @results; +my $too_many_hits; +if ($searchon eq 'sourcenames') { + $search_on_sources = 1; +} -sub find_desc -{ - my $pkg = shift; - my $suite = shift; - my $part = shift; - my $descr = ''; +sub print_header { + print Packages::HTML::header( title => 'Package Search Results' , + lang => 'en', + title_tag => 'Debian Package Search Results', + print_title_above => 1, + print_search_field => 'packages', + search_field_values => { + keywords => $keyword_enc, + searchon => $searchon, + arch => $archs_enc, + suite => $suites_enc, + section => $sections_enc, + subword => $subword, + exact => $exact, + case => $case, + }, + ); +} - unless (exists $descr{$suite}{$part}) { - $descr{$suite}{$part} = {}; - tie %{$descr{$suite}{$part}}, 'DB_File', "$FLATDIR/$suite/$part/Description", O_RDONLY - or return "Error while loading descriptions database: $!"; +sub read_entry { + my ($hash, $key, $results, $opts) = @_; + my $result = $hash->{$key} || ''; + foreach (split /\000/, $result) { + my @data = split ( /\s/, $_, 7 ); + debug( "Considering entry ".join( ':', @data), 2); + if ($opts->{h_suites}{$data[0]} + && ($opts->{h_archs}{$data[1]} || $data[1] eq 'all') + && $opts->{h_sections}{$data[2]}) { + debug( "Using entry ".join( ':', @data), 2); + push @$results, [ $key, @data ]; + } } - - return $descr{$suite}{$part}{$pkg}; } - -sub find_section -{ - my $pkg = shift; - my $suite = shift; - my $part = shift; - my $section = ''; - - unless (exists $sections{$suite}{$part}) { - $sections{$suite}{$part} = {}; - tie %{$sections{$suite}{$part}}, 'DB_File', "$FLATDIR/$suite/$part/Section", O_RDONLY - or return undef; +sub read_src_entry { + my ($hash, $key, $results, $opts) = @_; + my $result = $hash->{$key} || ''; + foreach (split /\000/, $result) { + my @data = split ( /\s/, $_, 5 ); + debug( "Considering entry ".join( ':', @data), 2); + if ($opts->{h_suites}{$data[0]} && $opts->{h_sections}{$data[1]}) { + debug( "Using entry ".join( ':', @data), 2); + push @$results, [ $key, @data ]; + } } - - return $sections{$suite}{$part}{$pkg}; } +sub do_names_search { + my ($keyword, $file, $postfix_file, $read_entry, $opts) = @_; + my @results; -my $st0 = new Benchmark; -tie my %cache, 'DB_File', "$topdir/files/search.cache/search.cache", O_RDWR|O_CREAT or $use_cache = 0; -my $cached; -my @results; -my $cache_key = $keyword.$exact.$subword.$searchon.$suites_param.$sections_param.$archs_param; -if ($searchon eq 'sourcenames') { - $search_on_sources = 1; -} -if ($use_cache && ($cached = $cache{$cache_key})) { - @results = split /\n/, $cached; - print "DEBUG: Used cached results
$cached
" if $debug; -} else { - my $searchkeyword = $keyword; - my $grep_searchkeyword = $keyword; - $searchkeyword =~ s/[.]/\\./; - if (($searchon eq 'names') || ($searchon eq 'sourcenames')) { - # asserting that all package names are lower case - $searchkeyword = lc($searchkeyword) unless $case_bool; - $case_bool = 1; - $grep_searchkeyword = "^[^ ]*$searchkeyword" unless $exact; - $searchkeyword = "^\\S*$searchkeyword" unless $exact; - } else { - $grep_searchkeyword = "\\(^$searchkeyword\\b\\|\\b$searchkeyword\\b\\)" - if $subword != 1; - $searchkeyword = "\\b$searchkeyword\\b" - if $subword != 1; - } + $keyword = lc $keyword unless $opts->{case_bool}; -# FIXME -# check if the Packages files are there -#my @files = glob ("$fdir/$file"); -#if ($#files == -1) { -# XXX has to be updated for new architectures -# if ($format eq 'html') { -# if (($version eq "stable" and $arch =~ /^(hurd|sh)$/) -# || ($version eq "oldstable" and $arch =~ /^amd64$/)) { -# print "Error: the $arch architecture didn't exist in $version.
\n" -# ."Please go back and choose a different distribution.\n"; -# } else { -# print "Error: Packages/Sources file not found.
\n" -# ."If the problem persists, please inform $ENV{SERVER_ADMIN}.\n"; -# printf "

$file

"; -# } -# &printfooter; -# } -# exit; -#} - - my @files; - foreach my $s (@suites) { - foreach my $sec (@sections) { - foreach my $a (@archs) { - foreach my $archive (@ARCHIVES) { - if (($searchon eq 'names' or $searchon eq 'sourcenames') - and $exact) { - my ( %packages, $file ); - if ($search_on_sources) { - $file = "$FLATDIR/$s/$sec/Sources.$archive.db"; - } else { - $file = "$FLATDIR/$s/$sec/Packages-$a.$archive.db"; - } - if (-f $file) { - print "DEBUG: Use file $file
" - if $debug > 1; - - tie %packages, 'DB_File', $file, O_RDONLY - or die "Couldn't open packages file $file: $!"; - - if (my $data = $packages{$searchkeyword}) { - print "DEBUG: Found result $data
" - if $debug > 1; - push @results, "$file:$data"; - } - } - } else { - my $file; - if ($search_on_sources) { - $file = "$FLATDIR/$s/$sec/Sources.$archive"; - } else { - $file = "$FLATDIR/$s/$sec/Packages-$a.$archive"; - } - if (-f $file) { - print "DEBUG: Use file $file
" - if $debug > 1; - - # use_grep is currently way faster, though - # I can't pinpoint exactly why, yet - # most probably the perl regexes are - # slow compared to the simpler grep - # regexes - unless ($use_grep) { - open my $pkg_fh, '<', $file - or die "Couldn't open packages file $file: $!"; - - foreach (<$pkg_fh>) { - if (/$searchkeyword/o) { - print "DEBUG: Found result $_
" - if $debug > 1; - - push @results, "$file:$_"; - } - } - } else { - push @files, $file; - } - } - } + my $obj = tie my %packages, 'DB_File', "$DBDIR/$file", O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/$file: $!"; + + if ($opts->{exact}) { + &$read_entry( \%packages, $keyword, \@results, $opts ); + } else { + my ($key, $prefixes) = ($keyword, ''); + my %pkgs; + my $p_obj = tie my %pref, 'DB_File', "$DBDIR/$postfix_file", O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie postfix db $DBDIR/$postfix_file: $!"; + $p_obj->seq( $key, $prefixes, R_CURSOR ); + while (index($key, $keyword) >= 0) { + if ($prefixes =~ /^\001(\d+)/o) { + $too_many_hits += $1; + } else { + foreach (split /\000/o, $prefixes) { + $_ = '' if $_ eq '^'; + debug( "add word $_$key", 2); + $pkgs{$_.$key}++; } } + last if $p_obj->seq( $key, $prefixes, R_NEXT ) != 0; + last if $too_many_hits or keys %pkgs >= 100; + } + + my $no_results = keys %pkgs; + if ($too_many_hits || ($no_results >= 100)) { + $too_many_hits += $no_results; + %pkgs = ( $keyword => 1 ); + } + foreach my $pkg (sort keys %pkgs) { + &$read_entry( \%packages, $pkg, \@results, $opts ); + } + } + return \@results; +} +sub do_fulltext_search { + my ($keword, $file, $mapping, $lookup, $read_entry, $opts) = @_; + my @results; + + my @lines; + my $regex; + if ($opts->{case_bool}) { + if ($opts->{exact}) { + $regex = qr/\b\Q$keyword\E\b/o; + } else { + $regex = qr/\Q$keyword\E/o; + } + } else { + if ($opts->{exact}) { + $regex = qr/\b\Q$keyword\E\b/io; + } else { + $regex = qr/\Q$keyword\E/io; } } - if ($use_grep) { - if (@files) { - my @grep = ( 'grep', '-H' ); - push @grep, '-i' unless $case_bool; - push @grep, $grep_searchkeyword; - push @grep, @files; - - print "DEBUG: starting grep command '". - substr("@grep",0,100)."[...]'
" if $debug; - open my $grep_out, '-|', @grep or - die "grep failed: $!"; - @results = <$grep_out>; + open DESC, '<', "$DBDIR/$file" + or die "couldn't open $DBDIR/$file: $!"; + while () { + $_ =~ $regex or next; + debug( "Matched line $.", 2); + push @lines, $.; + } + close DESC; + + tie my %packages, 'DB_File', "$DBDIR/$lookup", O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/$lookup: $!"; + tie my %did2pkg, 'DB_File', "$DBDIR/$mapping", O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/$mapping: $!"; + + my %tmp_results; + foreach my $l (@lines) { + my $result = $did2pkg{$l}; + foreach (split /\000/o, $result) { + my @data = split /\s/, $_, 3; + next unless $opts->{h_archs}{$data[2]}; + $tmp_results{$data[0]}++; } } - - $cache{$cache_key} = join "", @results; + foreach my $pkg (keys %tmp_results) { + &$read_entry( \%packages, $pkg, \@results, $opts ); + } + return \@results; +} + +sub find_binaries { + my ($pkg, $suite) = @_; + + tie my %src2bin, 'DB_File', "$DBDIR/sources_packages.db", O_RDONLY, 0666, $DB_BTREE + or die "couldn't open $DBDIR/sources_packages.db: $!"; + + my $bins = $src2bin{$pkg} || ''; + my %bins; + foreach (split /\000/o, $bins) { + my @data = split /\s/, $_, 4; + + if ($data[0] eq $suite) { + $bins{$data[1]}++; + } + } + + return [ keys %bins ]; +} + +if ($searchon eq 'names') { + push @results, @{ do_names_search( $keyword, 'packages_small.db', + 'package_postfixes.db', + \&read_entry, \%opts ) }; +} elsif ($searchon eq 'sourcenames') { + push @results, @{ do_names_search( $keyword, 'sources_small.db', + 'source_postfixes.db', + \&read_src_entry, \%opts ) }; +} else { + push @results, @{ do_names_search( $keyword, 'packages_small.db', + 'package_postfixes.db', + \&read_entry, \%opts ) }; + push @results, @{ do_fulltext_search( $keyword, 'descriptions.txt', + 'descriptions_packages.db', + 'packages_small.db', + \&read_entry, \%opts ) }; } my $st1 = new Benchmark; my $std = timediff($st1, $st0); -print "DEBUG: Search took ".timestr($std)."
" if $debug; +debug( "Search took ".timestr($std) ); if ($format eq 'html') { my $suite_wording = $suites_enc eq "all" ? "all suites" @@ -335,13 +403,17 @@ if ($format eq 'html') { if (($searchon eq "names") || ($searchon eq 'sourcenames')) { my $source_wording = $search_on_sources ? "source " : ""; my $exact_wording = $exact ? "named" : "that names contain"; - print "

You have searched for ${source_wording}packages $exact_wording $keyword_enc in $suite_wording, $section_wording, and $arch_wording.

"; + msg( "You have searched for ${source_wording}packages $exact_wording $keyword_enc in $suite_wording, $section_wording, and $arch_wording." ); } else { my $exact_wording = $exact ? "" : " (including subword matching)"; - print "

You have searched for $keyword_enc in packages names and descriptions in $suite_wording, $section_wording, and $arch_wording$exact_wording.

"; + msg( "You have searched for $keyword_enc in packages names and descriptions in $suite_wording, $section_wording, and $arch_wording$exact_wording." ); } } +if ($too_many_hits) { + error( "Your search was too wide so we will only display exact matches. At least $too_many_hits results have been omitted and will not be displayed. Please consider using a longer keyword or more keywords." ); +} + if (!@results) { if ($format eq 'html') { my $keyword_esc = uri_escape( $keyword ); @@ -350,68 +422,64 @@ if (!@results) { if (($suites_enc eq 'all') && ($archs_enc eq 'any') && ($sections_enc eq 'all')) { - print "

Can't find that package.

\n"; + error( "Can't find that package." ); } else { - print "

Can't find that package, at least not in that suite ". - ( $search_on_sources ? "" : " and on that architecture" ). - ".

\n"; + error( "Can't find that package, at least not in that suite ". + ( $search_on_sources ? "" : " and on that architecture" ) ) } if ($exact) { - $printed = 1; - print "

You have searched only for exact matches of the package name. You can try to search for package names that contain your search string.

"; + hint( "You have searched only for exact matches of the package name. You can try to search for package names that contain your search string." ); } } else { if (($suites_enc eq 'all') && ($archs_enc eq 'any') && ($sections_enc eq 'all')) { - print "

Can't find that string.

\n"; + error( "Can't find that string." ); } else { - print "

Can't find that string, at least not in that suite ($suites_enc, section $sections_enc) and on that architecture ($archs_enc).

\n"; + error( "Can't find that string, at least not in that suite ($suites_enc, section $sections_enc) and on that architecture ($archs_enc)." ); } unless ($subword) { - $printed = 1; - print "

You have searched only for words exactly matching your keywords. You can try to search allowing subword matching.

"; + hint( "You have searched only for words exactly matching your keywords. You can try to search allowing subword matching." ); } } - print "

".( $printed ? "Or you" : "You" )." can try a different search on the Packages search page.

"; - - &printfooter; + hint( ( @hints ? "Or you" : "You" )." can try a different search on the Packages search page." ); + } - exit; } +print_header; +print_msgs; +print_errors; +print_hints; +print_debug; + my (%pkgs, %sect, %part, %desc, %binaries); -my (@colon, $package, $pkg_t, $section, $ver, $arch, $foo, $binaries); unless ($search_on_sources) { - foreach my $line (@results) { - @colon = split (/:/, $line); - ($pkg_t, $section, $ver, $arch, $foo) = split (/ /, $#colon >1 ? $colon[1].":".$colon[2]:$colon[1], 5); - $section =~ s,^(non-free|contrib)/,,; - $section =~ s,^non-US.*$,non-US,,; - my ($dist,$part,undef) = $colon[0] =~ m,.*/([^/]+)/([^/]+)/Packages-([^\.]+)\.,; #$1=stable, $2=main, $3=alpha - - ($package) = $pkg_t =~ m/^(.+)/; # untaint - $pkgs{$package}{$dist}{$ver}{$arch} = 1; - $sect{$package}{$dist}{$ver} = $section; - $part{$package}{$dist}{$ver} = $part unless $part eq 'main'; - - $desc{$package}{$dist}{$ver} = find_desc ($package, $dist, $part) if (! exists $desc{$package}{$dist}{$ver}); - + foreach (@results) { + my ($pkg_t, $suite, $arch, $section, $subsection, + $priority, $version, $desc) = @$_; + + my ($package) = $pkg_t =~ m/^(.+)/; # untaint + $pkgs{$package}{$suite}{$version}{$arch} = 1; + $sect{$package}{$suite}{$version} = $subsection; + $part{$package}{$suite}{$version} = $section unless $section eq 'main'; + + $desc{$package}{$suite}{$version} = $desc; } if ($format eq 'html') { my ($start, $end) = multipageheader( scalar keys %pkgs ); my $count = 0; - + foreach my $pkg (sort keys %pkgs) { $count++; next if $count < $start or $count > $end; printf "

Package %s

\n", $pkg; print "\n"; } - } elsif ($format eq 'xml') { - require RDF::Simple::Serialiser; - my $rdf = new RDF::Simple::Serialiser; - $rdf->addns( debpkg => 'http://packages.debian.org/xml/01-debian-packages-rdf' ); - my @triples; - foreach my $pkg (sort keys %pkgs) { - foreach $ver (@DISTS) { - if (exists $pkgs{$pkg}{$ver}) { - my @versions = version_sort keys %{$pkgs{$pkg}{$ver}}; - foreach my $version (@versions) { - my $id = "$ROOT/$ver/$sect{$pkg}{$ver}{$version}/$pkg/$version"; - push @triples, [ $id, 'debpkg:package', $pkg ]; - push @triples, [ $id, 'debpkg:version', $version ]; - push @triples, [ $id, 'debpkg:section', $sect{$pkg}{$ver}{$version}, ]; - push @triples, [ $id, 'debpkg:suite', $ver ]; - push @triples, [ $id, 'debpkg:shortdesc', $desc{$pkg}{$ver}{$version} ]; - push @triples, [ $id, 'debpkg:part', $part{$pkg}{$ver}{$version} || 'main' ]; - foreach my $arch (sort keys %{$pkgs{$pkg}{$ver}{$version}}) { - push @triples, [ $id, 'debpkg:architecture', $arch ]; - } - } - } - } - } - - print $rdf->serialise(@triples); } } else { - foreach my $line (@results) { - chomp($line); - @colon = split (/:/, $line); - ($package, $section, $ver, $binaries) = split (/ /, $#colon >1 ? $colon[1].":".$colon[2]:$colon[1], 4); - $section =~ s,^(non-free|contrib)/,,; - $section =~ s,^non-US.*$,non-US,,; - $colon[0] =~ m,.*/([^/]+)/([^/]+)/Sources\.,; #$1=stable, $2=main + foreach (@results) { + my ($package, $suite, $section, $subsection, $priority, + $version) = @$_; - my ($suite, $part) = ($1, $2); - $pkgs{$package}{$suite} = $ver; - $sect{$package}{$suite}{source} = $section; - $part{$package}{$suite}{source} = $part unless $part eq 'main'; - - $binaries{$package}{$suite} = [ sort split( /\s*,\s*/, $binaries ) ]; + $pkgs{$package}{$suite} = $version; + $sect{$package}{$suite}{source} = $subsection; + $part{$package}{$suite}{source} = $section unless $section eq 'main'; + $binaries{$package}{$suite} = find_binaries( $package, $suite ); } if ($format eq 'html') { @@ -484,7 +520,7 @@ unless ($search_on_sources) { next if ($count < $start) or ($count > $end); printf "

Source package %s

\n", $pkg; print "\n"; } - } elsif ($format eq 'xml') { - require RDF::Simple::Serialiser; - my $rdf = new RDF::Simple::Serialiser; - $rdf->addns( debpkg => 'http://packages.debian.org/xml/01-debian-packages-rdf' ); - my @triples; - foreach my $pkg (sort keys %pkgs) { - foreach $ver (@DISTS) { - if (exists $pkgs{$pkg}{$ver}) { - my $id = "$ROOT/$ver/source/$pkg"; - - push @triples, [ $id, 'debpkg:package', $pkg ]; - push @triples, [ $id, 'debpkg:type', 'source' ]; - push @triples, [ $id, 'debpkg:section', $sect{$pkg}{$ver}{source} ]; - push @triples, [ $id, 'debpkg:version', $pkgs{$pkg}{$ver} ]; - push @triples, [ $id, 'debpkg:part', $part{$pkg}{$ver}{source} || 'main' ]; - - foreach my $bp (@{$binaries{$pkg}{$ver}}) { - push @triples, [ $id, 'debpkg:binary', $bp ]; - } - } - } - } - print $rdf->serialise(@triples); } } @@ -549,9 +555,11 @@ sub printindexline { my $no_results = shift; my $index_line; - if ($no_results > $results_per_page) { + if ($no_results > $opts{number}) { - $index_line = prevlink($input,\%params)." | ".indexline( $input, \%params, $no_results)." | ".nextlink($input,\%params, $no_results); + $index_line = prevlink($input,\%params)." | ". + indexline( $input, \%params, $no_results)." | ". + nextlink($input,\%params, $no_results); print "

$index_line

"; } @@ -561,10 +569,10 @@ sub multipageheader { my $no_results = shift; my ($start, $end); - if ($results_per_page =~ /^all$/i) { + if ($opts{number} =~ /^all$/i) { $start = 1; $end = $no_results; - $results_per_page = $no_results; + $opts{number} = $no_results; } else { $start = Packages::Search::start( \%params ); $end = Packages::Search::end( \%params ); @@ -584,7 +592,7 @@ sub multipageheader { print "

Results per page: "; my @resperpagelinks; for (50, 100, 200) { - if ($results_per_page == $_) { + if ($opts{number} == $_) { push @resperpagelinks, $_; } else { push @resperpagelinks, resperpagelink($input,\%params,$_); @@ -610,5 +618,11 @@ print < END +my $pete = new Benchmark; +my $petd = timediff($pete, $pet0); +print "Total page evaluation took ".timestr($petd)."
" + if $debug_allowed; print $input->end_html; } + +# vim: ts=8 sw=4