#!/usr/bin/perl # TmNetWiki version 0.4 (September 11, 2002) # Copyright (C) 2002 Adam Brate # # Based on the GPLed UseModWiki 0.92 # Copyright (C) 2000-2001 Clifford A. Adams # or # Based on the GPLed AtisWiki 0.3 (C) 1998 Markus Denker # # ...which was based on # the LGPLed CVWiki CVS-patches (C) 1997 Peter Merel # and The Original WikiWikiWeb (C) Ward Cunningham # (code reused with permission) # Email and ThinLine options by Jim Mahoney # # 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. # 59 Temple Place, Suite 330 # Boston, MA 02111-1307 USA package Wiki::search; use strict; # needs subs Wiki::template: GetHeader, GetCommonFooter # Wiki::utility: QuoteHtml # Wiki::index: PrintPageList # Wiki::translate: Ts # Wiki::page: OpenPage # Wiki::text: OpenText # needs consts $XSearchDisp use base 'Exporter'; use Wiki::consts; use Wiki::template; use Wiki::utility; use Wiki::index; use Wiki::translate; use Wiki::page; use Wiki::text; #if ($^V and $^V gt v5.6.0) { # our @EXPORT; #else { use vars qw(@EXPORT); #} @EXPORT = qw( DoSearch ); sub SearchTitleAndBody; sub SearchBody; sub PrintSearchResults; # This is a very simple search. I think it would be good if redirects # were recursively expanded. sub DoSearch { my ($string) = @_; if ($string eq '') { &DoIndex(); return; } print &GetHeader('', &QuoteHtml(Ts('Search for: %s', $string)), ''); print '
'; if ( $XSearchDisp ) { # managed by config file (?) &PrintSearchResults($string,&SearchTitleAndBody($string)) ; } else { &PrintPageList(&SearchTitleAndBody($string)); } # &PrintPageList(&SearchTitleAndBody($string)); print &GetCommonFooter(); } sub SearchTitleAndBody { my ($string) = @_; my ($name, $freeName, @found,@titlefound); foreach $name (&AllPagesList()) { my $found =0; &OpenPage($name); &OpenDefaultText(); if ($name =~ /$string/i) { push(@titlefound,$name); $found=1; } elsif ($FreeLinks && ($name =~ m/_/)) { $freeName = $name; $freeName =~ s/_/ /g; if ($freeName =~ /$string/i) { push(@titlefound, $name); $found = 1; } } if ($found == 0 && $Text{'text'} =~ /$string/i) { push(@found, $name); } } @found = (@titlefound,@found); return @found; } sub SearchBody { my ($string) = @_; my ($name, @found); foreach $name (&AllPagesList()) { &OpenPage($name); &OpenDefaultText(); if ($Text{'text'} =~ /$string/i){ push(@found, $name); } } return @found; } sub PrintSearchResults { my ( $searchstring, @results ) = @_ ; # inputs my ( $output ) ; my ( $name ) ; my ( $pageText ) ; my ( $t, $j, $jsnippet, $start, $end ) ; my ( $snippetlen, $maxsnippets ) = ( 100, 4 ) ; # these seem nice. print "\n

", ($#results + 1), " pages found:

"; foreach $name (@results) { # get the page, filter it, remove all tags (since we're presenting in # plaintext, not HTML, a la google(tm)). &OpenPage($name); &OpenDefaultText(); $pageText = &QuoteHtml($Text{'text'}); $pageText =~ s/$Consts->{FS}//g; # Remove separators (paranoia) $pageText =~ s/[\s]+/ /g; # Shrink whitespace $pageText =~ s/([-_=\\*\\.]){10,}/$1$1$1$1$1/g ; # e.g. shrink "----------" foreach $t (@HtmlPairs, "pre", "nowiki", "code" ) { $pageText =~ s/\<$t(\s[^<>]+?)?\>(.*?)\<\/$t\>/$2/gis; } foreach $t (@HtmlSingle) { $pageText =~ s/\<$t(\s[^<>]+?)?\>//gi; } # entry header $output = "\n\n" ; $output .= "... " if ($name =~ m|/|); $output .= "" . &GetPageLink($name) . "
\n" ; # show a snippet from the top of the document $j = index( $pageText, " ", $snippetlen ) ; # end on word boundary $output .= substr( $pageText, 0, $j ) . " ... " ; $pageText = substr( $pageText, $j ) ; # to avoid rematching # search for occurrences of searchstring $jsnippet = 0 ; while ( $jsnippet < $maxsnippets && $pageText =~ m/($searchstring)/i ) { # captures match as $1 $jsnippet++ ; # paranoid about looping if ( ($j = index( $pageText, $1 )) > -1 ) { # get index of match # get substr containing (start of) match, ending on word boundaries $start = index( $pageText, " ", $j-($snippetlen/2) ) ; $start = 0 if ( $start == -1 ) ; $end = index( $pageText, " ", $j+($snippetlen/2) ) ; $end = length( $pageText ) if ( $end == -1 ) ; $t = substr( $pageText, $start, $end-$start ) ; # highlight occurrences and tack on to output stream. $t =~ s/($searchstring)/\1<\/b>/gi ; $output .= $t . " ... " ; # truncate text to avoid rematching the same string. $pageText = substr( $pageText, $end ) ; } } # entry trailer $output .= "
" . int((length($pageText)/1024)+1) . "K - last updated " . &TimeToText($Section{ts}) . " by " . &GetAuthorLink( $Section{'host'}, $Section{'username'}, $Section{'id'} ) . "

" ; print $output ; } }