X-Git-Url: https://git.deb.at/?p=deb%2Fpackages.git;a=blobdiff_plain;f=cgi-bin%2Fsearch_packages.pl;h=25b0e132ea0874a862b3dee434442982b55155a8;hp=4e2225ca25114b8f650ca68e666143078b79b84b;hb=f49363dc272472174dd57c663c2688c33af927cd;hpb=7ca948e9df320aa1785beda7bfcf927cf676af43 diff --git a/cgi-bin/search_packages.pl b/cgi-bin/search_packages.pl index 4e2225c..25b0e13 100755 --- a/cgi-bin/search_packages.pl +++ b/cgi-bin/search_packages.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -wT -# +# $Id$ # search_packages.pl -- CGI interface to the Packages files on packages.debian.org # # Copyright (C) 1998 James Treacy @@ -20,111 +20,133 @@ use HTML::Entities; use DB_File; use Benchmark; -use lib "../lib"; - use Deb::Versions; +use Packages::CGI; use Packages::Search qw( :all ); use Packages::HTML (); -my $thisscript = "search_packages.pl"; -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; +&Packages::CGI::reset; $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; +my $tet0 = new Benchmark; # use this to disable debugging in production mode completly my $debug_allowed = 1; my $debug = $debug_allowed && $input->param("debug"); -$Search::Param::debug = 1 if $debug > 1; +$debug = 0 if !defined($debug) || $debug !~ /^\d+$/o; +$Packages::CGI::debug = $debug; -# If you want, just print out a list of all of the variables and exit. -print $input->header if $debug; -# print $input->dump; -# exit; +# read the configuration +our $config_read_time ||= 0; +our $db_read_time ||= 0; +our $topdir; +our $ROOT; +our @SUITES; +our @SECTIONS; +our @ARCHITECTURES; + +# FIXME: move to own module +my $modtime = (stat( "../config.sh" ))[9]; +if ($modtime > $config_read_time) { + if (!open (C, '<', "../config.sh")) { + error( "Internal Error: Cannot open configuration file." ); + } + while () { + chomp; + $topdir = $1 if /^\s*topdir="?([^\"]*)"?\s*$/o; + $ROOT = $1 if /^\s*root="?([^\"]*)"?\s*$/o; + $Packages::HTML::HOME = $1 if /^\s*home="?([^\"]*)"?\s*$/o; + $Packages::HTML::SEARCH_CGI = $1 if /^\s*searchcgi="?([^\"]*)"?\s*$/o; + $Packages::HTML::SEARCH_PAGE = $1 if /^\s*searchpage="?([^\"]*)"?\s*$/o; + $Packages::HTML::WEBMASTER_MAIL = $1 if /^\s*webmaster="?([^\"]*)"?\s*$/o; + $Packages::HTML::CONTACT_MAIL = $1 if /^\s*contact="?([^\"]*)"?\s*$/o; + @SUITES = split(/\s+/, $1) if /^\s*suites="?([^\"]*)"?\s*$/o; + @SECTIONS = split(/\s+/, $1) if /^\s*sections="?([^\"]*)"?\s*$/o; + @ARCHITECTURES = split(/\s+/, $1) if /^\s*architectures="?([^\"]*)"?\s*$/o; + } + close (C); + debug( "read config ($modtime > $config_read_time)" ); + $config_read_time = $modtime; +} +my $DBDIR = $topdir . "/files/db"; +my $thisscript = $Packages::HTML::SEARCH_CGI; if (my $path = $input->param('path')) { my @components = map { lc $_ } split /\//, $path; + my %SUITES = map { $_ => 1 } @SUITES; + my %SECTIONS = map { $_ => 1 } @SECTIONS; + my %ARCHITECTURES = map { $_ => 1 } @ARCHITECTURES; + foreach (@components) { if ($SUITES{$_}) { $input->param('suite', $_); } elsif ($SECTIONS{$_}) { $input->param('section', $_); - } elsif ($ARCHIVES{$_}) { - $input->param('archive', $_); }elsif ($ARCHITECTURES{$_}) { $input->param('arch', $_); } } } -my %params_def = ( keywords => { default => undef, match => '^\s*([-+\@\w\/.:]+)\s*$' }, +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+)$' }, + case => { default => 'insensitive', match => '^(\w+)$', + var => \$case }, 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+)$' }, + 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'; - if ($format eq 'html') { print $input->header; -} elsif ($format eq 'xml') { -# print $input->header( -type=>'application/rdf+xml' ); - print $input->header( -type=>'text/plain' ); } if ($params{errors}{keywords}) { - print "Error: keyword not valid or missing" if $format eq 'html'; - exit 0; + fatal_error( "keyword not valid or missing" ); +} elsif (length($keyword) < 2) { + fatal_error( "keyword too short (keywords need to have at least two characters)" ); } -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}}; @@ -132,132 +154,70 @@ my $sections_param = join ',', @{$params{values}{section}{no_replace}}; my $archs_param = join ',', @{$params{values}{arch}{no_replace}}; # for output -my $keyword_enc = encode_entities $keyword; +my $keyword_enc = encode_entities $keyword || ''; my $searchon_enc = encode_entities $searchon; my $suites_enc = encode_entities join ', ', @{$params{values}{suite}{no_replace}}; my $sections_enc = encode_entities join ', ', @{$params{values}{section}{no_replace}}; 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, - }, - ); -} - -# 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; -} -while () { - $topdir = $1 if (/^\s*topdir="?(.*)"?\s*$/); -} -close (C); - -my $DBDIR = $topdir . "/files/db"; -my $search_on_sources = 0; +debug( "Parameter evaluation took ".timestr($petd) ); my $st0 = new Benchmark; my @results; -if ($searchon eq 'sourcenames') { - $search_on_sources = 1; -} -my %suites = map { $_ => 1 } @suites; -my %sections = map { $_ => 1 } @sections; -my %archs = map { $_ => 1 } @archs; - -print "DEBUG: suites=@suites, sections=@sections, archs=@archs
" if $debug > 2; - -if ($searchon eq 'names') { - - $keyword = lc $keyword unless $case_bool; - - my $obj = tie my %packages, 'DB_File', "$DBDIR/packages_small.db", O_RDONLY, 0666, $DB_BTREE - or die "couldn't tie DB $DBDIR/packages_small.db: $!"; - - if ($exact) { - my $result = $packages{$keyword}; - foreach (split /\000/, $result) { - my @data = split ( /\s/, $_, 7 ); - print "DEBUG: Considering entry ".join( ':', @data)."
" if $debug > 2; - if ($suites{$data[0]} && ($archs{$data[1]} || $data[1] eq 'all') - && $sections{$data[2]}) { - print "DEBUG: Using entry ".join( ':', @data)."
" if $debug > 2; - push @results, [ $keyword, @data ]; - } - } - } else { - while (my ($pkg, $result) = each %packages) { - #what's faster? I can't really see a difference - (index($pkg, $keyword) >= 0) or next; - #$pkg =~ /\Q$keyword\E/ or next; - foreach (split /\000/, $packages{$pkg}) { - my @data = split ( /\s/, $_, 7 ); - print "DEBUG: Considering entry ".join( ':', @data)."
" if $debug > 2; - if ($suites{$data[0]} && ($archs{$data[1]} || $data[1] eq 'all') - && $sections{$data[2]}) { - print "DEBUG: Using entry ".join( ':', @data)."
" if $debug > 2; - push @results, [ $pkg , @data ]; - } - } - } +our ($obj, $s_obj, $p_obj, $sp_obj, + %packages, %sources, %postf, %spostf, %src2bin, %did2pkg ); + +unless (@Packages::CGI::fatal_errors) { + + my $dbmodtime = (stat("$DBDIR/packages_small.db"))[9]; + if ($dbmodtime > $db_read_time) { + $obj = tie %packages, 'DB_File', "$DBDIR/packages_small.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/packages_small.db: $!"; + $s_obj = tie %sources, 'DB_File', "$DBDIR/sources_small.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/sources_small.db: $!"; + $p_obj = tie %postf, 'DB_File', "$DBDIR/package_postfixes.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie postfix db $DBDIR/package_postfixes.db: $!"; + $sp_obj = tie %spostf, 'DB_File', "$DBDIR/source_postfixes.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie postfix db $DBDIR/source_postfixes.db: $!"; + tie %src2bin, 'DB_File', "$DBDIR/sources_packages.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't open $DBDIR/sources_packages.db: $!"; + tie %did2pkg, 'DB_File', "$DBDIR/descriptions_packages.db", + O_RDONLY, 0666, $DB_BTREE + or die "couldn't tie DB $DBDIR/descriptions_packages.db: $!"; + + debug( "tied databases ($dbmodtime > $db_read_time)" ); + $db_read_time = $dbmodtime; } -} elsif ($searchon eq 'sourcenames') { - - $keyword = lc $keyword unless $case_bool; - - my $obj = tie my %packages, 'DB_File', "$DBDIR/sources_small.db", O_RDONLY, 0666, $DB_BTREE - or die "couldn't tie DB $DBDIR/sources_small.db: $!"; - - if ($exact) { - my $result = $packages{$keyword}; - foreach (split /\000/, $result) { - my @data = split ( /\s/, $_, 5 ); - print "DEBUG: Considering entry ".join( ':', @data)."
" if $debug > 2; - if ($suites{$data[0]} && $sections{$data[1]}) { - print "DEBUG: Using entry ".join( ':', @data)."
" if $debug > 2; - push @results, [ $keyword, @data ]; - } - } + + if ($searchon eq 'names') { + push @results, @{ do_names_search( $keyword, \%packages, + $p_obj, + \&read_entry, \%opts ) }; + } elsif ($searchon eq 'sourcenames') { + push @results, @{ do_names_search( $keyword, \%sources, + $sp_obj, + \&read_src_entry, \%opts ) }; } else { - while (my ($pkg, $result) = each %packages) { - #what's faster? I can't really see a difference - (index($pkg, $keyword) >= 0) or next; - #$pkg =~ /\Q$keyword\E/ or next; - foreach (split /\000/, $packages{$pkg}) { - my @data = split ( /\s/, $_, 5 ); - print "DEBUG: Considering entry ".join( ':', @data)."
" if $debug > 2; - if ($suites{$data[0]} && $sections{$data[1]}) { - print "DEBUG: Using entry ".join( ':', @data)."
" if $debug > 2; - push @results, [ $pkg , @data ]; - } - } - } + push @results, @{ do_names_search( $keyword, \%packages, + $p_obj, + \&read_entry, \%opts ) }; + push @results, @{ do_fulltext_search( $keyword, "$DBDIR/descriptions.txt", + \%did2pkg, + \%packages, + \&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" @@ -267,16 +227,20 @@ if ($format eq 'html') { my $arch_wording = $archs_enc eq 'any' ? "all architectures" : "architecture(s) $archs_enc"; if (($searchon eq "names") || ($searchon eq 'sourcenames')) { - my $source_wording = $search_on_sources ? "source " : ""; + my $source_wording = ( $searchon eq 'sourcenames' ) ? "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 (!@results) { +if ($Packages::Search::too_many_hits) { + error( "Your search was too wide so we will only display exact matches. At least $Packages::Search::too_many_hits results have been omitted and will not be displayed. Please consider using a longer keyword or more keywords." ); +} + +if (!@Packages::CGI::fatal_errors && !@results) { if ($format eq 'html') { my $keyword_esc = uri_escape( $keyword ); my $printed = 0; @@ -284,257 +248,160 @@ 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 ". + ( ( $searchon eq 'sourcenames' ) ? "" : " 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.

"; + $printed++; + 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.

"; + $printed++; + 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( ( $printed ? "Or you" : "You" )." can try a different search on the Packages search page." ); + } - exit; } -my (%pkgs, %sect, %part, %desc, %binaries); - -unless ($search_on_sources) { - 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'; +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 => $debug, + }, + ); +print_msgs(); +print_errors(); +print_hints(); +print_debug(); +if (@results) { + my (%pkgs, %sect, %part, %desc, %binaries); + + unless ($opts{searchon} eq 'sourcenames') { + foreach (@results) { + my ($pkg_t, $suite, $arch, $section, $subsection, + $priority, $version, $desc) = @$_; - $desc{$package}{$suite}{$version} = $desc; - - } + my ($pkg) = $pkg_t =~ m/^(.+)/; # untaint + $pkgs{$pkg}{$suite}{$version}{$arch} = 1; + $sect{$pkg}{$suite}{$version} = $subsection; + $part{$pkg}{$suite}{$version} = $section + unless $section eq 'main'; + + $desc{$pkg}{$suite}{$version} = $desc; + } - if ($format eq 'html') { - my ($start, $end) = multipageheader( scalar keys %pkgs ); - my $count = 0; + if ($opts{format} eq 'html') { + my ($start, $end) = multipageheader( $input, scalar keys %pkgs, \%opts ); + 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 my $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 ]; + foreach my $pkg (sort keys %pkgs) { + $count++; + next if $count < $start or $count > $end; + printf "

Package %s

\n", $pkg; + print "\n"; } } + } else { + foreach (@results) { + my ($pkg, $suite, $section, $subsection, $priority, + $version) = @$_; - print $rdf->serialise(@triples); - } -} else { - foreach (@results) { - my ($package, $suite, $section, $subsection, $priority, - $version, $binaries) = @$_; - - $pkgs{$package}{$suite} = $version; - $sect{$package}{$suite}{source} = $subsection; - $part{$package}{$suite}{source} = $section unless $section eq 'main'; + $pkgs{$pkg}{$suite} = $version; + $sect{$pkg}{$suite}{source} = $subsection; + $part{$pkg}{$suite}{source} = $section + unless $section eq 'main'; - $binaries{$package}{$suite} = [ sort split( /\s*,\s*/, $binaries ) ]; - } + $binaries{$pkg}{$suite} = find_binaries( $pkg, $suite, \%src2bin ); + } - 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 "

Source package %s

\n", $pkg; - print "\n"; } } - print $rdf->serialise(@triples); - } -} - -if ($format eq 'html') { - &printindexline( scalar keys %pkgs ); - &printfooter; -} - -exit; - -sub printindexline { - my $no_results = shift; - - my $index_line; - if ($no_results > $results_per_page) { - - $index_line = prevlink($input,\%params)." | ". - indexline( $input, \%params, $no_results)." | ". - nextlink($input,\%params, $no_results); - - print "

$index_line

"; - } -} - -sub multipageheader { - my $no_results = shift; - - my ($start, $end); - if ($results_per_page =~ /^all$/i) { - $start = 1; - $end = $no_results; - $results_per_page = $no_results; - } else { - $start = Packages::Search::start( \%params ); - $end = Packages::Search::end( \%params ); - if ($end > $no_results) { $end = $no_results; } - } - - print "

Found $no_results matching packages,"; - if ($end == $start) { - print " displaying package $end.

"; - } else { - print " displaying packages $start to $end.

"; - } - - printindexline( $no_results ); - - if ($no_results > 100) { - print "

Results per page: "; - my @resperpagelinks; - for (50, 100, 200) { - if ($results_per_page == $_) { - push @resperpagelinks, $_; - } else { - push @resperpagelinks, resperpagelink($input,\%params,$_); - } - } - if ($params{values}{number}{final} =~ /^all$/i) { - push @resperpagelinks, "all"; - } else { - push @resperpagelinks, resperpagelink($input, \%params,"all"); - } - print join( " | ", @resperpagelinks )."

"; } - return ( $start, $end ); + printindexline( $input, scalar keys %pkgs, \%opts ); } +#print_results(\@results, \%opts) if @results;; +my $tet1 = new Benchmark; +my $tetd = timediff($tet1, $tet0); +print "Total page evaluation took ".timestr($petd)."
" + if $debug_allowed; -sub printfooter { -print < - -
-

Packages search page

+my $trailer = Packages::HTML::trailer( $ROOT ); +$trailer =~ s/LAST_MODIFIED_DATE/gmtime()/e; #FIXME +print $trailer; - -END - -print $input->end_html; -} +# vim: ts=8 sw=4