LXR Cross Referencer Git repo
Brought to you by:
ajlittoz
#!/usr/bin/perl -T # $Id: search,v 1.28 2004/10/18 20:22:57 brondsem Exp $ # search -- Freetext search # # Arne Georg Gleditsch <argggh@ifi.uio.no> # Per Kristian Gjermshus <pergj@ifi.uio.no> # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ###################################################################### $CVSID = '$Id: search,v 1.28 2004/10/18 20:22:57 brondsem Exp $ '; use strict; use lib '.'; # for Local.pm use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" }; # if LXR modules are in ./lib use LXR::Common qw(:html); use LXR::Config; my $maxhits = 1000; sub varinputs { my $templ = shift; my $ret = ''; foreach ($config->allvariables) { if ($config->variable($_) ne $config->vardefault($_)) { $ret .= expandtemplate( $templ, ( variable => sub { $_ }, value => sub { $config->variable($_) }, ) ); } } return $ret; } sub filename_matches { my ($filetext, $advanced, $casesensitive, $file) = @_; if ($advanced) { if ($casesensitive) { if ($file =~ /$filetext/) { return 1; } } elsif ($file =~ /$filetext/i) { return 1; } } else { if ($casesensitive) { if (index($file, $filetext) != -1) { return 1; } } elsif (index(lc($file), lc($filetext)) != -1) { return 1; } } return 0; } sub glimpsesearch { my ($searchtext, $filetext, $advanced, $casesensitive) = @_; $ENV{'PATH'} = '/bin:/usr/local/bin:/usr/bin:/usr/sbin'; unless (open(GLIMPSE, "-|")) { open(STDERR, ">&STDOUT"); $! = ''; exec($config->glimpsebin, "-i", "-H" . $config->glimpsedir . "/" . $release, '-y', '-n', $searchtext); print("Glimpse subprocess died unexpextedly: $!\n"); exit; } my $numlines = 0; my @glimpselines = (); while (<GLIMPSE>) { $numlines++; push(@glimpselines, $_); if ($numlines >= $maxhits) { last; } } close(GLIMPSE); my $retval = $? >> 8; # The manpage for glimpse says that it returns 2 on syntax errors or # inaccessible files. It seems this is not the case. # We will have to work around it for the time being. if ($retval == 0) { my @ret; my $sourceroot = $config->sourceroot . '/' . $release . '/'; my $i = 0; foreach my $glimpseline (@glimpselines) { last if ($i > $maxhits); $glimpseline =~ s/$sourceroot//; my ($file, $line, $text) = $glimpseline =~ /(.*?):\s*(\d+)\s*:(.*)/; next if $filetext and !filename_matches($filetext, $advanced, $casesensitive, $file); $text =~ s/&/&/g; $text =~ s/</</g; $text =~ s/>/>/g; push @ret, [ $file, $line, $text ]; } continue { $i++; } return @ret; } elsif ($retval == 1) { my $glimpsebin = $config->glimpsebin; my $glimpseresponse = join("<br>", @glimpselines); my $glimpseresponse =~ s/$glimpsebin/Reason/; my $glimpseresponse =~ s/glimpse: error in searching index//; print("<b>Search failed</b><br>\n$glimpseresponse"); return; } else { print("Unexpected returnvalue $retval from Glimpse\n"); return; } } sub swishsearch { my ($searchtext, $filetext, $advanced, $casesensitive) = @_; if (!-e $config->swishdir . "/" . $release . ".index") { print "<p align='center'><i>Version '$release' has not been indexed and is unavailable for searching.</i></p>"; return; } $ENV{'PATH'} = '/bin:/usr/local/bin:/usr/bin:/usr/sbin'; unless (open(SWISH, "-|")) { exec($config->swishbin, "-f", $config->swishdir . "/" . $release . ".index", "-w", "'(" . $searchtext . ")'"); open(STDERR, ">&STDOUT"); print(STDERR "Couldn't exec " . $config->swishbin . ": $!\n"); kill(9, $$); } my @result = grep { not /^[\#\.]/ } <SWISH>; close(SWISH); my $retval = $?; my @ret; if ($retval == 0) { my $numlines = 0; foreach my $hit (@result) { print $hit, "<br>\n" if $hit =~ $hit =~ /No such file or directory/; # feeble attempt to print possible errors (e.g. incomplete LD_LIBRARY_PATH causes linking errors) next if $hit =~ /^err:/; # skip; only 'no results' errors happen with return value 0 my ($score, $file) = $hit =~ /^(\d+) \/(.+) "(.+)" \d+/; next if $filetext and !filename_matches($filetext, $advanced, $casesensitive, $file); push @ret, [ $file, $score ]; $numlines++; last if ($numlines >= $maxhits); } return @ret; } else { print("<b><font color='red'>Search failed: internal error</font></b><br>\n@result"); return; } } sub printresults { my $templ = shift; my @results = @_; my $ret = ''; foreach (@results) { # filename, glimpse and swish-e searches provide different data for each result if (!ref) { my $file = $_; $ret .= expandtemplate( $templ, ( text => sub { return '' }, fileref => sub { fileref("$file", "find-file", "/$file") }, ) ); } elsif ($config->glimpsebin) { my (@params) = @$_; my $file = $params[0]; my $line = $params[1]; my $text = $params[2]; $ret .= expandtemplate( $templ, ( text => sub { return $text }, fileref => sub { fileref("$file, line $line", "find-file", "/$file", $line) }, ) ); } else { my (@params) = @$_; my $file = $params[0]; my $score = $params[1]; $ret .= expandtemplate( $templ, ( text => sub { return $score }, fileref => sub { fileref("$file", "find-file", "/$file") }, ) ); } } return $ret; } sub search { my $templ; if ($config->htmlsearch) { unless (open(TEMPL, $config->htmlsearch)) { warning("Template " . $config->htmlsearch . " does not exist."); } else { local ($/) = undef; $templ = <TEMPL>; close(TEMPL); } } else { die "'htmlsearch' template not configured"; } my $searchtext = $HTTP->{'param'}->{'string'}; my $filetext = $HTTP->{'param'}->{'filestring'}; my $advanced = $HTTP->{'param'}->{'advanced'}; my $casesensitive = $HTTP->{'param'}->{'casesensitive'}; my @results; if ($searchtext ne "") { if ($config->glimpsebin) { @results = glimpsesearch($searchtext, $filetext, $advanced, $casesensitive); } elsif ($config->swishbin and $config->swishdir) { @results = swishsearch($searchtext, $filetext, $advanced, $casesensitive); } else { warning("No freetext search engine configured."); } } elsif ($filetext ne "") { my $FILELISTING; if ($config->swishdir and $config->swishbin) { unless ($FILELISTING = new IO::File($config->swishdir . "/$release.filenames")) { &warning( "Version '$release' has not been indexed and is unavailable for searching<br>Could not open " . $config->swishdir . "/$release.filenames."); return; } } elsif ($config->glimpsedir and $config->glimpsebin) { unless ($FILELISTING = new IO::File($config->glimpsedir . "/" . $release . "/.glimpse_filenames")) { &warning( "Version '$release' has not been indexed and is unavailable for searching<br>Could not open " . $config->glimpsedir . "/$release/.glimpse_filenames."); return; } } else { warning( "Freetext search engine required for file search, and no freetext search engine is configured" ); return; } my $sourceroot = $config->sourceroot . '/' . $release . '/'; while (<$FILELISTING>) { chomp; s/^$sourceroot//; push @results, $_ if filename_matches($filetext, $advanced, $casesensitive, $_); } close($FILELISTING); } print expandtemplate( $templ, ( variables => sub { varinputs(@_) }, searchtext => sub { return $searchtext }, searchtext_escaped => sub { $_ = $searchtext; s/\"/"/g; return $_; }, filetext_escaped => sub { $_ = $filetext; s/\"/"/g; return $_; }, advancedchecked => sub { return $advanced ? "checked" : "" }, casesensitivechecked => sub { return $casesensitive ? "checked" : "" }, maxhits_message => sub { return @results == $maxhits ? "<b>Too many hits, displaying first $maxhits</b><br>" : ""; }, results => sub { printresults(@_, @results) }, resultcount => sub { return scalar @results }, ) ); } httpinit; &makeheader('search'); &search; &makefooter('search'); httpclean;