From ab47ae363dddbc35743572c62fae6350dcb7cf96 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Tue, 28 Feb 2006 17:04:00 +0000 Subject: [PATCH] * completly overhaul URL generating. Now things like debug or language options should get preserved on subsequent links * Move param handling from Search.pm to CGI.pm since that is more appropriate nowadays (some of the other stuff should really move to DB.pm, too) * be stricter about what is allowed after package name in URLs (only architecture really) so that we can avoid more false URL interpretation --- cgi-bin/dispatcher.pl | 40 +++-- lib/Packages/CGI.pm | 369 ++++++++++++++++++++++++++++++++++++++- lib/Packages/DoIndex.pm | 2 +- lib/Packages/DoSearch.pm | 25 ++- lib/Packages/DoShow.pm | 22 +-- lib/Packages/HTML.pm | 38 ++-- lib/Packages/Search.pm | 278 +---------------------------- 7 files changed, 434 insertions(+), 340 deletions(-) diff --git a/cgi-bin/dispatcher.pl b/cgi-bin/dispatcher.pl index 5ff3b67..22fc691 100755 --- a/cgi-bin/dispatcher.pl +++ b/cgi-bin/dispatcher.pl @@ -67,7 +67,7 @@ my $acc = I18N::AcceptLanguage->new(); my $http_lang = $acc->accepts( $input->http("Accept-Language"), \@LANGUAGES ) || 'en'; debug( "LANGUAGES=@LANGUAGES header=". - $input->http("Accept-Language"). + ($input->http("Accept-Language")||''). " http_lang=$http_lang", 2 ) if DEBUG; bindtextdomain ( 'pdo', $LOCALES ); textdomain( 'pdo' ); @@ -79,7 +79,10 @@ if (my $path = $input->path_info() || $input->param('PATH_INFO')) { push @components, 'index' if $path =~ m,/$,; - debug( "components[0]=$components[0]", 2 ) if DEBUG and @components>0; + my %LANGUAGES = map { $_ => 1 } @LANGUAGES; + if (@components > 0 and $LANGUAGES{$components[0]}) { + $input->param( 'lang', shift(@components) ); + } if (@components > 0 and $components[0] eq 'source') { shift @components; $input->param( 'source', 1 ); @@ -122,28 +125,29 @@ if (my $path = $input->path_info() || $input->param('PATH_INFO')) { } } - my @tmp; - foreach (@components) { - if ($SUITES{$_}) { + my (@pkg, $need_pkg); + foreach (reverse @components) { + $need_pkg = !@pkg + && ($what_to_do !~ /^(index|allpackages|newpkg)$/); + if (!$need_pkg && $SUITES{$_}) { set_param_once( $input, \%params_set, 'suite', $_); -#possible conflicts with package names -# } elsif (my $s = $SUITES_ALIAS{$_}) { -# set_param_once( $input, \%params_set, 'suite', $s); - } elsif ($SECTIONS{$_}) { + } elsif (!$need_pkg && (my $s = $SUITES_ALIAS{$_})) { + set_param_once( $input, \%params_set, 'suite', $s); + } elsif (!$need_pkg && $SECTIONS{$_}) { set_param_once( $input, \%params_set, 'section', $_); - } elsif ($ARCHIVES{$_}) { + } elsif (!$need_pkg && $ARCHIVES{$_}) { set_param_once( $input, \%params_set, 'archive', $_); - } elsif ($ARCHITECTURES{$_}) { - set_param_once( $input, \%params_set, 'arch', $_); - } elsif ($sections_descs{$_}) { + } elsif (!$need_pkg && $sections_descs{$_}) { set_param_once( $input, \%params_set, 'subsection', $_); - } elsif ($_ eq 'source') { + } elsif (!$need_pkg && ($_ eq 'source')) { set_param_once( $input, \%params_set, 'source', 1); + } elsif ($ARCHITECTURES{$_}) { + set_param_once( $input, \%params_set, 'arch', $_); } else { - push @tmp, $_; + push @pkg, $_; } } - @components = @tmp; + @components = @pkg; if (@components > 1) { fatal_error( sprintf( _g( "two or more packages specified (%s)" ), "@components" ) ); @@ -176,6 +180,7 @@ my %params_def = ( keywords => { default => undef, exact => { default => 0, match => '^(\w+)$', }, lang => { default => $http_lang, match => '^(\w+)$', }, source => { default => 0, match => '^(\d+)$', }, + debug => { default => 0, match => '^(\d+)$', }, searchon => { default => 'names', match => '^(\w+)$', }, section => { default => 'all', match => '^([\w-]+)$', alias => 'release', array => ',', @@ -191,7 +196,8 @@ my %params_def = ( keywords => { default => undef, mode => { default => undef, match => '^(\w+)$', }, ); my %opts; -my %params = Packages::Search::parse_params( $input, \%params_def, \%opts ); +my %params = Packages::CGI::parse_params( $input, \%params_def, \%opts ); +Packages::CGI::init_url( $input, \%params, \%opts ); my $locale = get_locale($opts{lang}); my $charset = get_charset($opts{lang}); diff --git a/lib/Packages/CGI.pm b/lib/Packages/CGI.pm index 66b442d..94986cb 100644 --- a/lib/Packages/CGI.pm +++ b/lib/Packages/CGI.pm @@ -1,10 +1,15 @@ package Packages::CGI; +use strict; +use warnings; + use Exporter; +use Packages::Config; + our @ISA = qw( Exporter ); our @EXPORT = qw( fatal_error error hint debug msg note print_errors print_hints print_debug print_msgs - print_notes DEBUG ); + print_notes DEBUG make_url make_search_url ); # define this to 0 in production mode use constant DEBUG => 1; @@ -81,4 +86,366 @@ sub print_notes { } } +our $USE_PAGED_MODE = 1; +use constant DEFAULT_PAGE => 1; +use constant DEFAULT_RES_PER_PAGE => 50; +our %page_params = ( page => { default => DEFAULT_PAGE, + match => '(\d+)' }, + number => { default => DEFAULT_RES_PER_PAGE, + match => '(\d+)' } ); + +sub parse_params { + my ( $cgi, $params_def, $opts ) = @_; + + my %params_ret = ( values => {}, errors => {} ); + my %params; + if ($USE_PAGED_MODE) { + debug( "Use PAGED_MODE", 2 ) if DEBUG; + %params = %$params_def; + foreach (keys %page_params) { + delete $params{$_}; + } + %params = ( %params, %page_params ); + } else { + %params = %$params_def; + } + + foreach my $param ( keys %params ) { + + debug( "Param $param", 2 ) if DEBUG; + + my $p_value_orig = $cgi->param($param); + + if (!defined($p_value_orig) + && defined $params_def->{$param}{alias} + && defined $cgi->param($params_def->{$param}{alias})) { + $p_value_orig = $cgi->param($params_def->{$param}{alias}); + debug( "Used alias $params_def->{$param}{alias}", + 2 ); + } + + my @p_value = ($p_value_orig); + + debug( "Value (Orig) ".($p_value_orig||""), 2 ) if DEBUG; + + if ($params_def->{$param}{array} && defined $p_value_orig) { + @p_value = split /$params_def->{$param}{array}/, $p_value_orig; + debug( "Value (Array Split) ". join('##',@p_value), 2 ) if DEBUG; + } + + if ($params_def->{$param}{match} && defined $p_value_orig) { + @p_value = map + { $_ =~ m/$params_def->{$param}{match}/; $_ = $1 } + @p_value; + } + @p_value = grep { defined $_ } @p_value; + + debug( "Value (Match) ". join('##',@p_value), 2 ) if DEBUG; + + unless (@p_value) { + if (defined $params{$param}{default}) { + @p_value = ($params{$param}{default}); + } else { + @p_value = undef; + $params_ret{errors}{$param} = "undef"; + next; + } + } + + debug( "Value (Default) ". join('##',@p_value), 2 ) if DEBUG; + my @p_value_no_replace = @p_value; + + if ($params{$param}{replace} && @p_value) { + foreach my $pattern (keys %{$params{$param}{replace}}) { + my @p_value_tmp = @p_value; + @p_value = (); + foreach (@p_value_tmp) { + if ($_ eq $pattern) { + my $replacement = $params{$param}{replace}{$_}; + if (ref $replacement) { + push @p_value, @$replacement; + } else { + push @p_value, $replacement; + } + } else { + push @p_value, $_; + } + } + } + } + + debug( "Value (Final) ". join('##',@p_value), 2 ) if DEBUG; + + if ($params_def->{$param}{array}) { + $params_ret{values}{$param} = { + orig => $p_value_orig, + no_replace => \@p_value_no_replace, + final => \@p_value, + }; + @{$params_def->{$param}{var}} = @p_value + if $params_def->{$param}{var}; + } else { + $params_ret{values}{$param} = { + orig => $p_value_orig, + no_replace => $p_value_no_replace[0], + final => $p_value[0], + }; + ${$params_def->{$param}{var}} = $p_value[0] + if $params_def->{$param}{var}; + } + $opts->{$param} = $params_ret{values}{$param}{final} if $opts; + } + + if ($USE_PAGED_MODE) { + $cgi->delete( "page" ); + $cgi->delete( "number" ); + } + + return %params_ret; +} + +sub start { + my $params = shift; + + my $page = $params->{values}{page}{final} + || DEFAULT_PAGE; + my $res_per_page = $params->{values}{number}{final} + || DEFAULT_RES_PER_PAGE; + + return 1 if $res_per_page =~ /^all$/i; + return $res_per_page * ($page - 1) + 1; +} + +sub end { + my $params = shift; + + use Data::Dumper; + debug( "end: ".Dumper($params) ) if DEBUG; + my $page = $params->{page} + || DEFAULT_PAGE; + my $res_per_page = $params->{number} + || DEFAULT_RES_PER_PAGE; + + return $page * $res_per_page; +} + +sub indexline { + my ($cgi, $params, $num_res) = @_; + + my $index_line = ""; + my $page = $params->{page} + || DEFAULT_PAGE; + my $res_per_page = $params->{number} + || DEFAULT_RES_PER_PAGE; + my $numpages = ceil($num_res / + $res_per_page); + for (my $i = 1; $i <= $numpages; $i++) { + if ($i == $page) { + $index_line .= $i; + } else { + $index_line .= "self_url). + "&page=$i&number=$res_per_page\">". + "$i"; + } + if ($i < $numpages) { + $index_line .= " | "; + } + } + return $index_line; +} + +sub nextlink { + my ($cgi, $params, $no_results ) = @_; + + my $page = $params->{page} + || DEFAULT_PAGE; + $page++; + my $res_per_page = $params->{number} + || DEFAULT_RES_PER_PAGE; + + if ((($page-1)*$res_per_page + 1) > $no_results) { + return ">>"; + } + + return "self_url). + "&page=$page&number=$res_per_page\">>>"; +} + +sub prevlink { + my ($cgi, $params ) = @_; + + my $page = $params->{page} + || DEFAULT_PAGE; + $page--; + if (!$page) { + return "<<"; + } + + my $res_per_page = $params->{number} + || DEFAULT_RES_PER_PAGE; + + return "self_url). + "&page=$page&number=$res_per_page\"><<"; +} + +sub resperpagelink { + my ($cgi, $params, $res_per_page ) = @_; + + my $page; + if ($res_per_page =~ /^all$/i) { + $page = 1; + } else { + $page = ceil(start( $params ) / $res_per_page); + } + + return "self_url). + "&page=$page&number=$res_per_page\">$res_per_page"; +} + +sub printindexline { + my ( $input, $no_results, $opts ) = @_; + + my $index_line; + if ($no_results > $opts->{number}) { + + $index_line = prevlink( $input, $opts)." | ". + indexline( $input, $opts, $no_results)." | ". + nextlink( $input, $opts, $no_results); + + print "

$index_line

"; + } +} + +#sub multipageheader { +# my ( $input, $no_results, $opts ) = @_; +# +# my ($start, $end); +# if ($opts->{number} =~ /^all$/i) { +# $start = 1; +# $end = $no_results; +# $opts->{number} = $no_results; +# $opts->{number_all}++; +# } else { +# $start = Packages::Search::start( $opts ); +# $end = Packages::Search::end( $opts ); +# 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( $input, $no_results, $opts ); +# +# if ($no_results > 100) { +# print "

Results per page: "; +# my @resperpagelinks; +# for (50, 100, 200) { +# if ($opts->{number} == $_) { +# push @resperpagelinks, $_; +# } else { +# push @resperpagelinks, resperpagelink($input,$opts,$_); +# } +# } +# if ($opts->{number_all}) { +# push @resperpagelinks, "all"; +# } else { +# push @resperpagelinks, resperpagelink($input, $opts, "all"); +# } +# print join( " | ", @resperpagelinks )."

"; +# } +# return ( $start, $end ); +#} + +our ( %url_params, %query_params ); + +sub init_url { + my ($input, $params, $opts) = @_; + + %url_params = (); + %query_params = (); + + if ($params->{values}{lang}{orig} && + (my $l = $params->{values}{lang}{no_replace})) { + $url_params{lang} = $l; + } + if ($params->{values}{source}{no_replace}) { + $url_params{source} = 'source'; + $query_params{source} = 1; + } + foreach my $p (qw(suite arch)) { + if ($params->{values}{$p}{orig} + && (ref $params->{values}{$p}{final} eq 'ARRAY') + && @{$params->{values}{$p}{final}}) { + if (@{$params->{values}{$p}{final}} == 1) { + $url_params{$p} = $params->{values}{$p}{final}[0]; + } else { + $url_params{$p} = + join(",",@{$params->{values}{$p}{no_replace}}); + } + } + } + foreach my $p (qw(format searchon mode exact debug)) { + if ($params->{values}{$p}{orig} + && (my $pv = $params->{values}{$p}{no_replace})) { + $url_params{$p} = $pv; + } + } + + use Data::Dumper; + debug( join("\n",Dumper(\%url_params,\%query_params)), 2 ) if DEBUG; +} + +sub make_url { + my ($add_path, $add_query, $override) = @_; + my (@path, @query_string) = ()x2; + $override ||= {}; + + push @path, $Packages::Config::ROOT; + foreach my $p (qw(lang source suite archive arch)) { + my $val = $url_params{$p}; + $val = $override->{$p} if exists $override->{$p}; + push @path, $val if $val; + } + foreach my $p (qw(format debug)) { + my $val = $url_params{$p}; + $val = $query_params{$p} if exists $query_params{$p}; + $val = $override->{$p} if exists $override->{$p}; + push @query_string, "$p=$val" if $val; + } + push @path, $add_path if $add_path; + push @query_string, $add_query if $add_query; + + my $path = join( '/', @path ); + my $query_string = join( '&', @query_string ); + + return "$path?$query_string"; +} + +sub make_search_url { + my ($add_path, $add_query, $override) = @_; + my (@path, @query_string) = ()x2; + $override ||= {}; + + push @path, $Packages::Config::SEARCH_URL + if $Packages::Config::SEARCH_URL; + foreach my $p (qw(lang source suite archive section subsection + exact mode searchon format debug)) { + my $val = $url_params{$p}; + $val = $query_params{$p} if exists $query_params{$p}; + $val = $override->{$p} if exists $override->{$p}; + push @query_string, "$p=$val" if $val; + } + push @path, $add_path if $add_path; + push @query_string, $add_query if $add_query; + + my $path = join( '/', @path ); + my $query_string = join( '&', @query_string ); + + return "$path?$query_string"; +} + 1; diff --git a/lib/Packages/DoIndex.pm b/lib/Packages/DoIndex.pm index b204d3d..8ca34f5 100644 --- a/lib/Packages/DoIndex.pm +++ b/lib/Packages/DoIndex.pm @@ -71,7 +71,7 @@ sub send_file { suite => 'all', section => 'all', exact => 1, - debug => $Packages::Search::debug, + debug => $Packages::CGI::debug, }, ); } diff --git a/lib/Packages/DoSearch.pm b/lib/Packages/DoSearch.pm index 0ff2e9b..a889ef5 100644 --- a/lib/Packages/DoSearch.pm +++ b/lib/Packages/DoSearch.pm @@ -39,10 +39,7 @@ sub do_search { # for URL construction my $keyword_esc = uri_escape( $keyword ); - my $suites_param = join ',', @{$params->{values}{suite}{no_replace}}; - my $sections_param = join ',', @{$params->{values}{section}{no_replace}}; - my $archs_param = join ',', @{$params->{values}{arch}{no_replace}}; - $opts->{common_params} = "suite=$suites_param§ion=$sections_param&keywords=$keyword_esc&searchon=$searchon&arch=$archs_param"; + $opts->{keywords_esc} = $keyword_esc; # for output my $keyword_enc = encode_entities $keyword || ''; @@ -134,7 +131,7 @@ sub do_search { if ($opts->{exact}) { hint( sprintf( _g( 'You have searched only for words exactly matching your keywords. You can try to search allowing subword matching.' ), - encode_entities("$SEARCH_URL?exact=0&$opts->{common_params}") ) ); + encode_entities(make_search_url('',"keywords=$keyword_esc",{exact => 0})) ) ); } } hint( sprintf( _g( 'You can try a different search on the Packages search page.' ), "$SEARCH_PAGE#search_packages" ) ); @@ -250,7 +247,7 @@ sub print_packages { } } elsif (@$pkgs_list) { $str .= "

".sprintf( _g( '%s results have not been displayed because you requested only exact matches.' ), - encode_entities("$SEARCH_URL?exact=0&$opts->{common_params}"), + encode_entities(make_search_url('',"keywords=$opts->{keyword_esc}",{exact => 0})), scalar @$pkgs_list )."

"; } $str .= ''; @@ -264,7 +261,7 @@ sub print_package { my $str = '

'.sprintf( _g( 'Package %s' ), $pkg ).'

'; $str .= '\n"; diff --git a/lib/Packages/DoShow.pm b/lib/Packages/DoShow.pm index 076e11f..6852c13 100644 --- a/lib/Packages/DoShow.pm +++ b/lib/Packages/DoShow.pm @@ -81,7 +81,7 @@ sub do_show { if ($suite eq $_) { $$menu .= "[ $_ ] "; } else { - $$menu .= "[ $_ ] "; + $$menu .= "[ $suite})."\">$_ ] "; } } $$menu .= '
'; @@ -147,16 +147,16 @@ sub do_show { # $short_desc = conv_desc( $lang, $short_desc ); my @menu = ( [ _g( "Distribution:" ), _g( "Overview over this suite" ), - "$ROOT/$suite/", + make_url("/",''), $suite ], [ _g( "Section:" ), _g( "All packages in this section" ), - "$ROOT/$suite/$subsection/", + make_url("$subsection/",''), $subsection ], ); my $source = $page->get_src('package'); push @menu, [ _g( "Source:" ), _g( "Source package building this package" ), - "$ROOT/$suite/source/$source", + make_url($source,'',{source=>'source'}), $source ] if $source; $$menu .= simple_menu( @menu ); @@ -171,7 +171,7 @@ sub do_show { $package_page .= title( $title ); if (my $provided_by = $page->{provided_by}) { - note( _g( "This is also a virtual package provided by ").join( ', ', map { "$_" } @$provided_by) ); + note( _g( "This is also a virtual package provided by ").join( ', ', map { "$_" } @$provided_by) ); } if ($suite eq "experimental") { @@ -228,7 +228,7 @@ sub do_show { $package_page .= ""._g( "Package Size").""._g("Installed Size").""._g("Files")."\n"; foreach my $a ( @archs ) { $package_page .= "\n"; - $package_page .= "$a\n"; $package_page .= "".$versions->{$a}."" if $multiple_versions; @@ -239,7 +239,7 @@ sub do_show { $package_page .= "\n"; if ( $suite ne "experimental" ) { $package_page .= sprintf( "["._g( "list of files" )."]\n", - "$ROOT/$suite/$encodedpkg/$a/filelist", $pkg ); + make_url("$encodedpkg/$a/filelist",''), $pkg ); } else { $package_page .= _g( "no current information" ); } @@ -262,11 +262,11 @@ sub do_show { $$menu .= simple_menu( [ _g( "Distribution:" ), _g( "Overview over this distribution" ), - "$ROOT/", + make_url('/',''), $suite ], [ _g( "Section:" ), _g( "All packages in this section" ), - "$ROOT/$suite/virtual/", + make_url("virtual/",''), 'virtual' ], ); @@ -304,11 +304,11 @@ sub do_show { $$menu .= simple_menu( [ _g( "Distribution:" ), _g( "Overview over this suite" ), - "$ROOT/$suite/", + make_url('/',''), $suite ], [ _g( "Section:" ), _g( "All packages in this section" ), - "$ROOT/$suite/$subsection/", + make_url("$subsection/",''), $subsection ], ); diff --git a/lib/Packages/HTML.pm b/lib/Packages/HTML.pm index eb38c72..fb16d2f 100644 --- a/lib/Packages/HTML.pm +++ b/lib/Packages/HTML.pm @@ -8,7 +8,7 @@ use URI::Escape; use HTML::Entities; use Locale::gettext; -use Packages::CGI (); +use Packages::CGI qw(make_url make_search_url); use Packages::Search qw( read_entry_simple ); use Packages::Config qw( :all ); @@ -89,7 +89,7 @@ sub pkg_list { my $short_desc = (read_entry_simple( $packages, $p, $opts->{h_archives}, $suite))->[-1]; if ( $short_desc ) { - $str .= "
$p
\n". + $str .= "
undef})."\">$p
\n". "\t
$short_desc
\n"; } else { $str .= "
$p
\n\t
"._g("Not available")."
\n"; @@ -127,11 +127,8 @@ sub pmoreinfo { my $src_dir = $page->get_src('directory'); if ($info{sourcedownload}) { my $files = $page->get_src( 'files' ); - my $path = (@{$opts->{archive}} >1) ? - $suite : - "$suite/$opts->{archive}[0]"; $str .= _g( "Source Package:" ); - $str .= " $source, ". + $str .= " 'source'})."\">$source, ". _g( "Download" ).":\n"; unless (defined($files) and @$files) { @@ -218,13 +215,11 @@ sub pmoreinfo { } sub dep_item { - my ( $link, $name, $info, $desc ) = @_; - my $post_link = ''; - if ($link) { - $link = ""; + my ( $suite, $name, $info, $desc ) = @_; + my ($link, $post_link) = ('', ''); + if ($suite) { + $link = "$suite})."\">"; $post_link = ''; - } else { - $link = ''; } if ($info) { $info = " $info"; @@ -241,12 +236,13 @@ sub dep_item { } # end dep_item sub provides_string { - my ($path, $entry,$also) = @_; - my @provided_by = split /\s/, $entry; + my ($suite, $entry, $also) = @_; + my %tmp = map { $_ => 1 } split /\s/, $entry; + my @provided_by = keys %tmp; # weed out duplicates my $short_desc = $also ? _g("also a virtual package provided by ") : _g("virtual package provided by "); if (@provided_by < 10) { - $short_desc .= join( ', ',map { "$_" } @provided_by); + $short_desc .= join( ', ',map { "$suite})."\">$_" } @provided_by); } else { $short_desc .= sprintf( _g("%s packages"), scalar(@provided_by)); } @@ -302,24 +298,24 @@ sub print_deps { my $short_desc = $entry->[-1]; my $arch = $entry->[3]; my $archive = $entry->[1]; - my $path = $entry->[2]; + my $p_suite = $entry->[2]; if ( $short_desc ) { if ( $is_old_pkgs ) { - push @res_pkgs, dep_item( "$ROOT/$path/$p_name", + push @res_pkgs, dep_item( $p_suite, $p_name, "$pkg_version$arch_str" ); } elsif (defined $entry->[1]) { $entries{$p_name} ||= $entry; $short_desc = encode_entities( $short_desc, "<>&\"" ); - $short_desc .= "
".provides_string( "$ROOT/$path", + $short_desc .= "
".provides_string( $p_suite, $entry->[0], 1 ) if defined $entry->[0]; - push @res_pkgs, dep_item( "$ROOT/$path/$p_name", + push @res_pkgs, dep_item( $p_suite, $p_name, "$pkg_version$arch_str", $short_desc ); } elsif (defined $entry->[0]) { - $short_desc = provides_string( "$ROOT/$path", + $short_desc = provides_string( $p_suite, $entry->[0] ); - push @res_pkgs, dep_item( "$ROOT/$path/$p_name", + push @res_pkgs, dep_item( $p_suite, $p_name, "$pkg_version$arch_str", $short_desc ); } } elsif ( $is_old_pkgs ) { diff --git a/lib/Packages/Search.pm b/lib/Packages/Search.pm index e863717..0bc157d 100644 --- a/lib/Packages/Search.pm +++ b/lib/Packages/Search.pm @@ -43,7 +43,6 @@ package Packages::Search; use strict; use warnings; -#use CGI (); use POSIX; use HTML::Entities; use DB_File; @@ -62,282 +61,8 @@ our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); our $VERSION = 0.01; -our $USE_PAGED_MODE = 1; -use constant DEFAULT_PAGE => 1; -use constant DEFAULT_RES_PER_PAGE => 50; -our %page_params = ( page => { default => DEFAULT_PAGE, - match => '(\d+)' }, - number => { default => DEFAULT_RES_PER_PAGE, - match => '(\d+)' } ); - our $too_many_hits = 0; -sub parse_params { - my ( $cgi, $params_def, $opts ) = @_; - - my %params_ret = ( values => {}, errors => {} ); - my %params; - if ($USE_PAGED_MODE) { - debug( "Use PAGED_MODE", 2 ) if DEBUG; - %params = %$params_def; - foreach (keys %page_params) { - delete $params{$_}; - } - %params = ( %params, %page_params ); - } else { - %params = %$params_def; - } - - foreach my $param ( keys %params ) { - - debug( "Param $param", 2 ) if DEBUG; - - my $p_value_orig = $cgi->param($param); - - if (!defined($p_value_orig) - && defined $params_def->{$param}{alias} - && defined $cgi->param($params_def->{$param}{alias})) { - $p_value_orig = $cgi->param($params_def->{$param}{alias}); - debug( "Used alias $params_def->{$param}{alias}", - 2 ); - } - - my @p_value = ($p_value_orig); - - debug( "Value (Orig) ".($p_value_orig||""), 2 ) if DEBUG; - - if ($params_def->{$param}{array} && defined $p_value_orig) { - @p_value = split /$params_def->{$param}{array}/, $p_value_orig; - debug( "Value (Array Split) ". join('##',@p_value), 2 ) if DEBUG; - } - - if ($params_def->{$param}{match} && defined $p_value_orig) { - @p_value = map - { $_ =~ m/$params_def->{$param}{match}/; $_ = $1 } - @p_value; - } - @p_value = grep { defined $_ } @p_value; - - debug( "Value (Match) ". join('##',@p_value), 2 ) if DEBUG; - - unless (@p_value) { - if (defined $params{$param}{default}) { - @p_value = ($params{$param}{default}); - } else { - @p_value = undef; - $params_ret{errors}{$param} = "undef"; - next; - } - } - - debug( "Value (Default) ". join('##',@p_value), 2 ) if DEBUG; - my @p_value_no_replace = @p_value; - - if ($params{$param}{replace} && @p_value) { - foreach my $pattern (keys %{$params{$param}{replace}}) { - my @p_value_tmp = @p_value; - @p_value = (); - foreach (@p_value_tmp) { - if ($_ eq $pattern) { - my $replacement = $params{$param}{replace}{$_}; - if (ref $replacement) { - push @p_value, @$replacement; - } else { - push @p_value, $replacement; - } - } else { - push @p_value, $_; - } - } - } - } - - debug( "Value (Final) ". join('##',@p_value), 2 ) if DEBUG; - - if ($params_def->{$param}{array}) { - $params_ret{values}{$param} = { - orig => $p_value_orig, - no_replace => \@p_value_no_replace, - final => \@p_value, - }; - @{$params_def->{$param}{var}} = @p_value - if $params_def->{$param}{var}; - } else { - $params_ret{values}{$param} = { - orig => $p_value_orig, - no_replace => $p_value_no_replace[0], - final => $p_value[0], - }; - ${$params_def->{$param}{var}} = $p_value[0] - if $params_def->{$param}{var}; - } - $opts->{$param} = $params_ret{values}{$param}{final} if $opts; - } - - if ($USE_PAGED_MODE) { - $cgi->delete( "page" ); - $cgi->delete( "number" ); - } - - return %params_ret; -} - -sub start { - my $params = shift; - - my $page = $params->{values}{page}{final} - || DEFAULT_PAGE; - my $res_per_page = $params->{values}{number}{final} - || DEFAULT_RES_PER_PAGE; - - return 1 if $res_per_page =~ /^all$/i; - return $res_per_page * ($page - 1) + 1; -} - -sub end { - my $params = shift; - - use Data::Dumper; - debug( "end: ".Dumper($params) ) if DEBUG; - my $page = $params->{page} - || DEFAULT_PAGE; - my $res_per_page = $params->{number} - || DEFAULT_RES_PER_PAGE; - - return $page * $res_per_page; -} - -sub indexline { - my ($cgi, $params, $num_res) = @_; - - my $index_line = ""; - my $page = $params->{page} - || DEFAULT_PAGE; - my $res_per_page = $params->{number} - || DEFAULT_RES_PER_PAGE; - my $numpages = ceil($num_res / - $res_per_page); - for (my $i = 1; $i <= $numpages; $i++) { - if ($i == $page) { - $index_line .= $i; - } else { - $index_line .= "self_url). - "&page=$i&number=$res_per_page\">". - "$i"; - } - if ($i < $numpages) { - $index_line .= " | "; - } - } - return $index_line; -} - -sub nextlink { - my ($cgi, $params, $no_results ) = @_; - - my $page = $params->{page} - || DEFAULT_PAGE; - $page++; - my $res_per_page = $params->{number} - || DEFAULT_RES_PER_PAGE; - - if ((($page-1)*$res_per_page + 1) > $no_results) { - return ">>"; - } - - return "self_url). - "&page=$page&number=$res_per_page\">>>"; -} - -sub prevlink { - my ($cgi, $params ) = @_; - - my $page = $params->{page} - || DEFAULT_PAGE; - $page--; - if (!$page) { - return "<<"; - } - - my $res_per_page = $params->{number} - || DEFAULT_RES_PER_PAGE; - - return "self_url). - "&page=$page&number=$res_per_page\"><<"; -} - -sub resperpagelink { - my ($cgi, $params, $res_per_page ) = @_; - - my $page; - if ($res_per_page =~ /^all$/i) { - $page = 1; - } else { - $page = ceil(start( $params ) / $res_per_page); - } - - return "self_url). - "&page=$page&number=$res_per_page\">$res_per_page"; -} - -sub printindexline { - my ( $input, $no_results, $opts ) = @_; - - my $index_line; - if ($no_results > $opts->{number}) { - - $index_line = prevlink( $input, $opts)." | ". - indexline( $input, $opts, $no_results)." | ". - nextlink( $input, $opts, $no_results); - - print "

$index_line

"; - } -} - -#sub multipageheader { -# my ( $input, $no_results, $opts ) = @_; -# -# my ($start, $end); -# if ($opts->{number} =~ /^all$/i) { -# $start = 1; -# $end = $no_results; -# $opts->{number} = $no_results; -# $opts->{number_all}++; -# } else { -# $start = Packages::Search::start( $opts ); -# $end = Packages::Search::end( $opts ); -# 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( $input, $no_results, $opts ); -# -# if ($no_results > 100) { -# print "

Results per page: "; -# my @resperpagelinks; -# for (50, 100, 200) { -# if ($opts->{number} == $_) { -# push @resperpagelinks, $_; -# } else { -# push @resperpagelinks, resperpagelink($input,$opts,$_); -# } -# } -# if ($opts->{number_all}) { -# push @resperpagelinks, "all"; -# } else { -# push @resperpagelinks, resperpagelink($input, $opts, "all"); -# } -# print join( " | ", @resperpagelinks )."

"; -# } -# return ( $start, $end ); -#} - sub read_entry_all { my ($hash, $key, $results, $non_results, $opts) = @_; my ($virt, $result) = split /\000/o, $hash->{$key} || "-\01-", 2; @@ -387,6 +112,7 @@ sub read_entry_simple { my %virt = split /\01/o, $virt; debug( "read_entry_simple: key=$key, archives=". join(" ",(keys %$archives)).", suite=$suite", 1) if DEBUG; + debug( "read_entry_simple: virt=".join(" ",(%virt)), 2) if DEBUG; # FIXME: not all of the 2^4=16 combinations of empty(results), # empty(virt{suite}), empty(fb_result), empty(virt{fb_suite}) are dealt # with correctly, but it's adequate enough for now @@ -399,7 +125,7 @@ sub read_entry_simple { if (my $fb_suite = $fallback_suites{$suite}) { my $fb_result = read_entry_simple( $hash, $key, $archives, $fb_suite ); my $fb_virt = shift(@$fb_result); - $virt{$suite} .= $fb_virt if $fb_virt; + $virt{$suite} .= $virt{$suite} ? " $fb_virt" : $fb_virt if $fb_virt; return [ $virt{$suite}, @$fb_result ] if @$fb_result; } return [ $virt{$suite} ]; -- 2.39.2