#!/usr/bin/perl
# tdsearch.cgi - searches all the text files in a directory and
# displays links to matching files as well as context of matching lines.
# This script is based partly on some example code by Larry Wall
# with additions by Gerry Smith <sfguu4658@agt.net>
# Copyright (C) 1996 Stephen Lines <spraxlo@ai.mit.edu>
# last update: June 4, 2005

require "ctime.pl";
require "FormData.pl";

######## change these values below for each particular instance ######

$admincommand = "C:admin";

$filelist    = "doclist.txt";

$sitetitle   = "Global Dialog";

$homelink        = "http://www.global-dialog.org/";
$homelinkstring  = "Global Dialog Home";

$mvdhomelink     = "http://www.global-dialog.org/mvd/";   # must end with /
$mvdhomelinkstring = "Global Dialog MVD";

$listlink        = "mvl.cgi?NextName=List";
$listlinkstring  = "List";

$bgcolor     = "#99CCCC";
$background  = "../graphics/web3.jpg";

############# change anything below at your own risk #######################

open(FILE,$filelist) || die("$0: couldn't open $filelist for reading($!)\n");
@array = <FILE>;
close(FILE);

foreach $line (@array){
chop($line);
($key,$value) = split(',',$line);
$Files2Names{$key} = $value;
}

$FileNum = 0;
foreach (sort(keys(%Files2Names))) {
  $ValidFiles[ $FileNum ] = $_;
  $ValidNames[ $FileNum ] = $NextName = $Files2Names{$_};
  $Names2Numbs{$NextName} = $FileNum++; # Used to validate names.
}

unless (defined($ENV{'SCRIPT_NAME'})) {   # this is only a test...
  $ENV{'SCRIPT_NAME'}    = $0;
  $ENV{'REQUEST_METHOD'} = 'GET';
  $ENV{'QUERY_STRING'}   = 'Query=Cologne&StripHTML=CHECKED';
  $ENV{'CONTENT_LENGTH'} = length($ENV{'QUERY_STRING'});
}

&getFormData(*Form);
$Context    =  $Form{'Context'}   || 1;
$Query      =  $Form{'Query'}     || '';
$RegExp     =  $Form{'RegExp'}    || '';  # Options default to "off"
$MatchCase  =  $Form{'MatchCase'} || '';
$WholeWord  =  $Form{'WholeWord'} || '';
$StripHTML  =  $Form{'StripHTML'} || 1;
$checkref   =  $Form{'checkref'}  || 0;

$submitfile = $Query;

if ($checkref){ 
  $StripHTML = "";
}

if($Query eq $admincommand){

print "Content-type: text/html\n\n";
print <<EOF;
<HTML>
<HEAD><TITLE> $sitetitle MVD Administration </TITLE></HEAD>
<BODY BGCOLOR=$bgcolor background=$background><CENTER>
<p><hr size=2><p>
<h1>$sitetitle MVD Administration</h1>
<H3>For $sitetitle MVD members</h3>
<font size=-1><a href="$homelink"> [ $homelinkstring ] </a></font><p>

<FORM METHOD=POST ACTION="mvladmin.cgi">
<p>
<a name=Form>
<table border=2 width=534 cellpadding=10 BGCOLOR=lightblue>
<tr valign=middle>
<td align=center valign=middle><b>Your Username</b><br>
<INPUT TYPE=TEXT SIZE=23 NAME="uname"><p>
<b>Your Password</b><br>
<INPUT TYPE=password SIZE=23 NAME="pword"><p></td>
<td align=center valign=middle>
<img src="../graphics/muddy.gif"><b><i><font size=+1>MVD</font></i></b><p>
<b>New Password</b><br>
<INPUT TYPE=password SIZE=23 NAME="opword"><p>
</td>
</tr>
<tr valign=middle>
<td align=center valign=middle><b>Entry as Title</b><br>
<INPUT TYPE=TEXT SIZE=23 NAME="title"><p></td>
<td align=center valign=middle><b>Entry as File</b><br>
<INPUT TYPE=TEXT SIZE=23 NAME="file"><p></td>
</tr>
</table>
<table border=2 width=534 cellpadding=10 BGCOLOR=gray>
<tr valign=middle>
<td align=center valign=middle>
<INPUT TYPE=SUBMIT NAME="Action" VALUE="Login"> &nbsp;&nbsp;
<INPUT TYPE=checkbox NAME="Public" VALUE="on"> Administration<p>
<INPUT TYPE=SUBMIT NAME="Action" VALUE="Change Password">
<input type=hidden name="private" value="true">
</td>
</tr>
<tr valign=middle>
<td align=center valign=middle BGCOLOR=lightgray>
<INPUT TYPE=RESET VALUE=" Reset All Input Boxes "><p></td>
</tr>
</table></form><p>
EOF

print <<EOFF;
<table border=0 width=500><td>
<small>
Here is a description of how to use this form. Note
that all the functions require you to fill in your username
(aka - member name) and your password. This is to prove you are
authorized to do what you are attempting.
<p>
<b>Login</b>.  When you fill in your username and password and then
press the "Login" button (and assuming the "Title" and "File"
fields are empty) you will be taken to your private file area where
you can view and edit any of your own non-public files. If you check
the "Administration" checkbox you will be taken to the administration
form where you will be able to view, edit or delete public mvd files
as well as perform other functions such as add, change or delete mvd
members. (You need to have administration privledges in order to access
that level. Not all mvd members have such privledges.)
<p><b>To change your password</b>. Fill in the "New Password" field and
press the "Change Password" button. The entry in that field will
replace your current password.
<p><b>To add or edit an entry</b>. Fill in either the "Entry as Title" 
or
the "Entry as File" field before you press the "Login" button. The 
entries
in this dadabase can be retrieved either by the entries's title or by 
the
name of it's html file. You can supply both fields and if a file isn't 
found
by filename or title one will be opened for editing and initialized with
those values for it's title and filename. You will then be able to enter
new values that define each entry. If a file is found by it's filename 
or
title it will be opened for editing to allow you to change it's values.
If you enter values in both fields the filename will be searched for 
first
and if found it will be loaded with it's proper title intact even if you 
have
a different one specified in the title field. If you are creating a new 
entry
it is best to just include a title and let the program choose an 
appropriate
filename.
</small>
</td></table>
<p><hr>
<a href="$homelink" target=_top> [ $homelinkstring ] </a>&nbsp;&nbsp;<a href="$mvdhomelink"> [ $mvdhomelinkstring ] </a>&nbsp;&nbsp;<a href="$listlink"> [ $listlinkstring ]  </a><hr><p></CENTER></BODY></HTML>
EOFF
exit;
}


print "Content-type: text/html\n\n";
if ($checkref){
print <<EOF;
<HTML><HEAD>
<TITLE>References to $Query</TITLE>
</HEAD><BODY BGCOLOR=$bgcolor background=$background>
<center>
<p><hr size=2><p>
<a name=totals>
<font size=+2>
References to <b>$Query</b> <br>at $sitetitle
</font>
<font size=-1>
<br>( use your browser's back button to return to $Query )<p>
<table width=430 cellpadding=0 border=0>
<td>
The files listed here, if any, either link to $Query or
else mention it within the document's text. Self-references
are not shown. 
</td>
</table>
</font>
</center>
<HR><p>
EOF
}
else {
print <<EOF;
<HTML><HEAD>
<TITLE>Search $sitetitle</TITLE>
</HEAD><BODY BGCOLOR=$bgcolor background=$background>
<center>
<p><hr size=2><p>
<font size=3>
<table width=700 cellpadding=0 border=0><td>
<FORM>
<center>
<a name=top>
<H2>Search $sitetitle</H2>
<INPUT TYPE=TEXT SIZE=55 MAXLENGTH=255 NAME="Query" VALUE="$Query"><br>
Regular Expressions:&nbsp;
<INPUT TYPE=CHECKBOX NAME=RegExp    VALUE=CHECKED $RegExp>&nbsp;&nbsp;
Match Case:
<INPUT TYPE=CHECKBOX NAME=MatchCase VALUE=CHECKED $MatchCase><br>
<INPUT TYPE=SUBMIT  VALUE=Submit>
<INPUT TYPE=RESET   VALUE=Reset><BR>
</FORM><BR></center>
<p><center><font size=-1>Scroll down for search results after you submit a query.</font></center>
<P>This simple search engine searches the documents on the $sitetitle part of this site for one string. A string is one
or more words. If more than one word is included in the query they will be treated
as a phrase and a match will occur only when those words are found together in the
way they were input. You can use regular expressions to do more sophisticated
searches. The output will include links to any matching entries, as well as the
matching lines and their contexts within the files.
<center><p><a href="regex.html"><font size=-1><i>How to use regular expressions.</i></font></a>
</center>
</td></table>
</center>
<HR><p>
EOF
}

if ($Query) { # Called with at least one argument; search for it.

    unless ($RegExp) { $Query =~ s/([\$()*+.?\[\\\]^{|}])/\\$1/g; }
    if ($WholeWord)  { $Query =  "\\b$Query\\b"; }

$Query =~ s/\//\\\//g;

    $matchOptions = $MatchCase ? 'o' : 'oi';
    $len          = $Context*2 + 1;
    $foundLines   = 0;
    $foundFiles   = 0;
    $skipfile = 0;

    # The following regular expression matches whole tags within
    # a line or partial tags that are broken by line endings.
    # In tags that straddle more the two lines, the middle lines
    # won't match this expression. (That's a feature, not a bug! ;-)
    $tags = '<[^>]*?(?:>|$)|(^|\G)[^<>]*?>'; # matches (partial) tags

    #chdir($txtdir);       # cd to the directory to keep it simple...
    opendir(DIR, ".");    # opendir is most portable on current dir (.)
    @txtFiles = grep( -T && 
!/\.(cgi|log|txt|pl|htaccess|htpasswd|dat|php3|php|bak)$/i && 
!/(index.html|form.html|insert.html|regex.html)/, readdir(DIR));
    closedir(DIR);

    print "<center><b>Search Results - Alphabetical by Title</b><br> <font size=-1>Click on the title to view that document.";    
    print " <a href=#totals> [ Goto Totals ] </a></font></center><p>";
if($checkref){    
  print "<center>\n";
}

    foreach $file (@txtFiles) {

  if(!$Files2Names{$file}) {$skip[$skipfile++] = $file; next;}
	open(FILE, $file) || do
            { print "Couldn't open file $file: $!\n"; next; };

        undef @keep;       # Re-initializing @keep is essential!
        for $j (0 .. $Context) {
            $keep[$Context - $j] = ''; # Add blank line before.
            $_ = <FILE>;               # Get next line from FILE.
            s/$tags//go if $StripHTML; # Remove whole and partial tags.
            $keep[$Context + $j] = $_ if $_; # Add next line after.
        }

       $StripHTML = 0 unless $StripHTML;
        eval <<ENDLOOP;                 # eval all code up to ENDLOOP.
        \$found = 0;
        while ( \$keep[$Context]) {
            if (\$keep[$Context] =~ /$Query/$matchOptions) {
                \$beg = \$. - $len;

                if (\$checkref){
                  if(\$file ne \$submitfile){
                    print "<A HREF=\\"mvl.cgi?NextName=\$file\\"><B>\$Files2Names{\$file}</B></A> : \$file<p>\n";
                    \$found++;                    
                  }                  
                }
                else {
                  print "<A HREF=\\"mvl.cgi?NextName=$file\\"><B>$Files2Names{$file}</B></A>";
                  \$found++;
                 
                  print ":\n";
                  foreach \$line (\@keep) {
                      if (\$line) {
                          unless ($StripHTML) {   # Can escape tags in
                            \$line =~ s/</&lt;/g; # output only, but must
                            \$line =~ s/>/&gt;/g; # handle < & > separately.
                          }
                          print \$line;
                      }
                  }
                  print "<p>\n";
                }

            }
            if (\$_) {
                \$_ =  <FILE>;         # Must strip all input or none:
                \$_ =~ s/$tags//go if ($StripHTML);
                 
                # s/<([^>]|\\n)*>//go; # doesn't work on single lines.
            }
            shift(\@keep);             # out with the oldest line
            push( \@keep, \$_);        # in with the new
        }
ENDLOOP
        die("$0: $@") if $@;            # $@ catches errors from eval.
        close(FILE);

	if ($found) {
            $foundLines += $found;
            $foundFiles++;
        }
    }
    if ($checkref){
      print "</center></PRE><a name=totals><center><B>Totals: ";
      if($foundFiles > 1){
        if($foundLines > 1){          
          print "$foundLines references in $foundFiles files, ";
        }
        elsif($foundLines eq 1){
          print "$foundLines reference in $foundFiles files, ";
        }
        else{
          print "No references found in any files, ";
        } 
      }
      elsif($foundFiles eq 1){
        if($foundLines > 1){          
          print "$foundLines references in $foundFiles file, ";
        }
        elsif($foundLines eq 1){
          print "$foundLines reference in $foundFiles file, ";
        }
        else{
          print "No references found in any files, ";
        }
      }
      else {
        print "No references found in any files, ";
      }  
    }
    else {
      print "</PRE><a name=totals><center><B>Totals: ";
      if($foundFiles > 1){
        if($foundLines > 1){          
          print "$foundLines matches in $foundFiles files, ";
        }
        elsif($foundLines eq 1){
          print "$foundLines match in $foundFiles files, ";
        }
        else{
          print "No matches found in any files, ";
        } 
      }
      elsif($foundFiles eq 1){
        if($foundLines > 1){          
          print "$foundLines matches in $foundFiles file, ";
        }
        elsif($foundLines eq 1){
          print "$foundLines match in $foundFiles file, ";
        }
        else{
          print "No matches found in any files, ";
        }
      }
      else {
        print "No matches found in any files, ";
      }
    }
    print "out of ", 0 + @txtFiles - $skipfile, " files searched.</B><a href=#top><font size=-1> [ Goto Top ] </a></font></center><p>\n"; }

print <<EF;
</FORM><center><hr><a href="$homelink" target=_top> [ $homelinkstring ] </a><hr>
<p></font></center></BODY></HTML>
EF
exit;
