]> git.deb.at Git - deb/packages.git/blobdiff - lib/Packages/DoSearchContents.pm
We welcome DoSearchContents.pm to the "multiple keywords" age
[deb/packages.git] / lib / Packages / DoSearchContents.pm
index b86f2390fb7f172bdbd2e04872d0ff703c8a276d..b8698cc3b592830a0add06d4e3284ba5ba4c67a2 100644 (file)
@@ -17,14 +17,14 @@ use Packages::Search qw( :all );
 use Packages::CGI;
 use Packages::DB;
 use Packages::Config qw( $DBDIR $SEARCH_URL $SEARCH_PAGE
-                        @SUITES @ARCHIVES $ROOT );
+                        @SUITES @ARCHIVES @ARCHITECTURES $ROOT );
 
 sub do_search_contents {
     my ($params, $opts, $html_header, $menu, $page_content) = @_;
 
     if ($params->{errors}{keywords}) {
        fatal_error( _g( "keyword not valid or missing" ) );
-    } elsif (length($opts->{keywords}) < 2) {
+    } elsif (grep { length($_) < 2 } @{$opts->{keywords}}) {
        fatal_error( _g( "keyword too short (keywords need to have at least two characters)" ) );
     }
     if ($params->{errors}{suite}) {
@@ -43,22 +43,20 @@ sub do_search_contents {
 
     $$menu = "";
     
-    my $keyword = $opts->{keywords};
-    my $searchon = $opts->{searchon};
-    my $exact = $opts->{exact};
+    my @keywords = @{$opts->{keywords}};
+    my $mode = $opts->{mode} || '';
     my $suite = $opts->{suite}[0];
     my $archive = $opts->{archive}[0] ||'';
     $Packages::Search::too_many_hits = 0;
 
     # for URL construction
-    my $keyword_esc = uri_escape( $keyword );
+    my $keyword_esc = uri_escape( "@keywords" );
     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}};
 
     # for output
-    my $keyword_enc = encode_entities $keyword || '';
-    my $searchon_enc = encode_entities $searchon;
+    my $keyword_enc = encode_entities "@keywords" || '';
     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}} ), '&<>"' );
@@ -70,33 +68,37 @@ sub do_search_contents {
 
        my $nres = 0;
 
-       my $kw = lc $keyword;
+       my $first_kw = lc shift @keywords;
        # full filename search is tricky
-       my $ffn = $searchon eq 'filenames';
+       my $ffn = $mode eq 'filename';
 
        my $reverses = tie my %reverses, 'DB_File', "$DBDIR/contents/reverse_$suite.db",
            O_RDONLY, 0666, $DB_BTREE
            or die "Failed opening reverse DB: $!";
 
        if ($ffn) {
-           open FILENAMES, '-|', 'fgrep', '--', $kw, "$DBDIR/contents/filenames_$suite.txt"
+           open FILENAMES, '-|', 'fgrep', '--', $first_kw, "$DBDIR/contents/filenames_$suite.txt"
                or die "Failed opening filename table: $!";
 
-           error( _g( "Exact and fullfilenamesearch don't go along" ) )
-               if $ffn and $exact;
-
+         FILENAME:
            while (<FILENAMES>) {
                chomp;
+               foreach my $kw (@keywords) {
+                   next FILENAME unless /\Q$kw\E/;
+               }
                &searchfile(\@results, reverse($_)."/", \$nres, $reverses);
                last if $Packages::Search::too_many_hits;
            }
            close FILENAMES or warn "fgrep error: $!\n";
        } else {
 
-           $kw = reverse $kw;
+           error(_g("The search mode you selected doesn't support more than one keyword."))
+               if @keywords;
+
+           my $kw = reverse $first_kw;
            
            # exact filename searching follows trivially:
-           $kw = "$kw/" if $exact;
+           $kw = "$kw/" if $mode eq 'exactfilename';
 
            &searchfile(\@results, $kw, \$nres, $reverses);
        }
@@ -114,26 +116,37 @@ sub do_search_contents {
        : sprintf(_g("section(s) <em>%s</em>"), $sections_enc );
     my $arch_wording = $archs_enc eq 'any' ? _g("all architectures")
        : sprintf(_g("architecture(s) <em>%s</em>"), $archs_enc );
-    my $wording = _g("filenames that contain");
-    if ($searchon eq 'contents') {
-       if ($opts->{exact}) {
-           $wording =  _g("files named");
-       } else {
-           $wording = _g("paths that end with");
-       }
+    my $wording = _g("paths that end with");
+    if ($mode eq 'filename') {
+       $wording =  _g("files named");
+    } elsif ($mode eq 'exactfilename') {
+       $wording = _g("filenames that contain");
     }
     msg( sprintf( _g("You have searched for %s <em>%s</em> in %s, %s, and %s." ),
                  $wording, $keyword_enc,
                  $suite_wording, $section_wording, $arch_wording ) );
 
+    if ($mode ne 'filename') {
+       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>'filename'}).
+             "\">"._g("Search within filenames")."</a>");
+    }
+    if ($mode ne 'exactfilename') {
+       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>'exactfilename'}).
+             "\">"._g("Search exact filename")."</a>");
+    }
+    if ($mode eq 'exactfilename' || $mode eq 'filename') {
+       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>undef}).
+             "\">"._g("Search for paths ending with")."</a>");
+    }
+
+    msg( _g("Search in other suite:")." ".
+        join( ' ', map { '[<a href="'.make_search_url('',"keywords=$keyword_esc",{suite=>$_}).
+                             "\">$_</a>]" } @SUITES ) );
+
     if ($Packages::Search::too_many_hits) {
        error( _g( "Your search was too wide so we will only display only the first about 100 matches. Please consider using a longer keyword or more keywords." ) );
     }
     
-    if (!@Packages::CGI::fatal_errors && !@results) {
-       error( _g( "Nothing found" ) );
-    }
-
     %$html_header = ( title => _g( 'Package Contents Search Results' ),
                      lang => $opts->{lang},
                      title_tag => _g( 'Debian Package Contents Search Results' ),
@@ -151,30 +164,47 @@ sub do_search_contents {
                      );
 
     $$page_content = '';
-    if (@results) {
-       my (%results,%archs);
-       foreach my $result (sort { $a->[0] cmp $b->[0] } @results) {
-           my $file = shift @$result;
-           my %pkgs;
-           foreach (@$result) {
-               my ($pkg, $arch) = split /:/, $_;
-               next unless $opts->{h_archs}{$arch};
-               $pkgs{$pkg}{$arch}++;
-               $archs{$arch}++ unless $arch eq 'all';
-           }
-           next unless keys %pkgs;
-           $results{$file} = \%pkgs;
+    my (%results,%archs);
+    foreach my $result (sort { $a->[0] cmp $b->[0] } @results) {
+       my $file = shift @$result;
+       my %pkgs;
+       foreach (@$result) {
+           my ($pkg, $arch) = split /:/, $_;
+           next unless $opts->{h_archs}{$arch};
+           $pkgs{$pkg}{$arch}++;
+           $archs{$arch}++ unless $arch eq 'all';
        }
-       my @all_archs = keys %archs;
-       debug( "all_archs = @all_archs", 1 ) if DEBUG;
+       next unless keys %pkgs;
+       $results{$file} = \%pkgs;
+    }
+    my @all_archs = keys %archs;
+    @all_archs = @ARCHITECTURES unless @all_archs;
+    debug( "all_archs = @all_archs", 1 ) if DEBUG;
+    msg(_g("Limit search to a specific architecture:")." ".
+       join( ' ', map { '[<a href="'.make_search_url('',"keywords=$keyword_esc",{arch=>$_}).
+                            "\">$_</a>]" } @all_archs ) )
+       unless (@{$opts->{arch}} == 1) || (@all_archs == 1);
+    msg(sprintf(_g('Search in <a href="%s">all architectures</a>'),
+               make_search_url('',"keywords=$keyword_esc",{arch=>undef})))
+       if @{$opts->{arch}} == 1;
+
+    if (!@Packages::CGI::fatal_errors && !keys(%results)) {
+       error( _g( "Nothing found" ) );
+    }
 
+    if (keys %results) {
        $$page_content .= "<p>".sprintf( _g( 'Found %s results' ),
-                                        scalar @results )."</p>";
+                                        scalar keys %results )."</p>";
        $$page_content .= '<div
        id="pcontentsres"><table><colgroup><col><col></colgroup><tr><th>'._g('File').'</th><th>'._g('Packages')
-           .'</th></tr>';
+           ."</th></tr>\n";
        foreach my $file (sort keys %results) {
-           $$page_content .= "<tr><td class=\"file\">/$file</td><td>";
+               my $file_enc = encode_entities($file);
+               foreach my $kw (@{$opts->{keywords}}) {
+                   my $kw_enc = encode_entities($kw);
+                   $file_enc =~ s#(\Q$kw_enc\E)#<span class="keyword">$1</span>#g;
+               }
+           $$page_content .= "<tr><td class=\"file\">/$file_enc</td><td>";
            my @pkgs;
            foreach my $pkg (sort keys %{$results{$file}}) {
                my $arch_str = '';
@@ -188,12 +218,12 @@ sub do_search_contents {
                            join(' ', grep { !$results{$file}{$pkg}{$_} } @all_archs).']';
                    }
                }
-               push @pkgs, "<a href=\"$ROOT/$suite/$pkg\">$pkg</a>$arch_str";
+               push @pkgs, "<a href=\"".make_url($pkg,'',{suite=>$suite})."\">$pkg</a>$arch_str";
            }
            $$page_content .= join( ", ", @pkgs);
-           $$page_content .= '</td>';
+           $$page_content .= "</td></tr>\n";
        }
-       $$page_content .= '<tr><th>'._g('File').'</th><th>'._g('Packages').'</th></tr>' if @results > 20;
+       $$page_content .= '<tr><th>'._g('File').'</th><th>'._g('Packages')."</th></tr>\n" if @results > 20;
        $$page_content .= '</table></div>';
     }
 } # sub do_search_contents