#!/usr/bin/perl
# 
#############################################################################
#
# Dieses CGI-Skript durchsucht den HTML-Dateibereich nach einem oder
# mehreren Suchbegriffen. Es werden nur Dateien mit den Endungen '.htm'
# bzw. '.html' beruecksichtigt.
#
# Es hat folgende Parameter
#
# 'searchvalue' = Suchbegriff(e), getrennt durch Leerzeichen
# 'type'        = all - UND-Verkn. / any - OR-Verkn.
# 'dirs'        = zu durchsuchende Verzeichnisse
# 'exdirs'      = auszusparende Verzeichnisse
#                 Jedes Verzeichnis bei 'dirs' und 'exdirs' muss mit "/" 
#                 beginnen; mehrere Verzeichnisse sind durch ";" zu trennen
#
# Generelles Problem: Jede HTML-Datei wird komplett in den Speicher gelesen
#############################################################################

use strict;

$|=1;

# Init Variable
my $BASE = $ENV{'DOCUMENT_ROOT'};
my $LOGFILE = $BASE . "/search.log";

my $listdirs = 0;
my $exdirs = 0;
my $numberreturned = 0;
my @directories = ();
my @excldirs = ();
my @search = ();
my $dir = '';

my %ein = ();                      # fuer Formulareingaben
my $input = '';
my $name = '';
my $value = '';

# Get the input
read(STDIN,$input,$ENV{CONTENT_LENGTH});

# Split the name-value pairs
foreach (split("&",$input)) {
  /(.*)=(.*)/;
  $name = $1;
  $value = $2;
  $value =~ s/\+/ /g;
  $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  $ein{$name}=$value;
  }

# Get Parameters
@search = split(/ /, $ein{'searchvalue'});
$numberreturned = 0;

$listdirs = 0;
if (defined($ein{'dirs'})) 
  { 
  @directories = split(/;/,$ein{'dirs'});
  $listdirs = 1;
  }

$exdirs = 0;
if (defined($ein{'exdirs'})) 
  {
  @excldirs = split(/;/,$ein{'exdirs'});
  $exdirs = 1;
  }

&WriteLog;

# Print HTML-Header
print "Content-type: text/html", "\r\n\r\n";
print "<HTHL>", "\n";
print "<HEAD><TITLE>Webserver-Suche</TITLE></HEAD>", "\n";
print "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000FF\" VLINK=\"#0000CC\" ALINK=\"#FF0000\">", "\n";
print "<FONT face=\"Arial,Helvetica,Geneva,Swiss,SunSans-Regular\">\n";
print "<H1 ALIGN=CENTER>Suchergebnis</H1>\n";

&Formular;

print "<UL>\n";
if ($listdirs) 
  { 
  foreach $dir (@directories) 
    { &CheckFiles($BASE."$dir"); }
  } 
else 
  { &CheckFiles($BASE); }
print "</UL>\n";

if ($numberreturned == 0) 
  { print "<P><B>Leider nichts gefunden!</B>\n"; } 
else 
  {
  print "<P><B>$numberreturned Fundstelle";
  if ($numberreturned != 1) { print "n"; };
  print "</B>\n";
  }
print "</FONT></BODY></HTML>\n";
exit(0);


sub Formular 
  {
  print "<FORM METHOD=\"post\" ACTION=\"/cgi-bin/such.pl\">\n";
  if (defined($ein{'background'})) { print "<INPUT TYPE=\"hidden\" NAME=\"body\" VALUE=\"$ein{'body'}\">\n"; }
  if (defined($ein{'dirs'})) { print "<INPUT TYPE=\"hidden\" NAME=\"dirs\" VALUE=\"$ein{'dirs'}\">\n"; }
  if (defined($ein{'exdirs'})) { print "<INPUT TYPE=\"hidden\" NAME=\"exdirs\" VALUE=\"$ein{'exdirs'}\">\n"; }
  print "Suchbegriff(e): ";
  print "<INPUT TYPE=\"text\" NAME=\"searchvalue\" VALUE=\"$ein{'searchvalue'}\">\n";
  print "Verkn\&uuml;pfung: ";
  print "<SELECT NAME=\"type\">\n";
  print "<OPTION VALUE=\"all\"";
  if ($ein{'type'} eq "all") { print " SELECTED"; }
  print ">alle \n";
  print "<OPTION VALUE=\"any\"";
  if ($ein{'type'} eq "any") { print " SELECTED"; }
  print ">mindestens einer \n";
  print "</SELECT> der Begriffe.\n";
  print "<INPUT TYPE=\"submit\" VALUE=\"Suchen\">\n";
  print "<INPUT TYPE=\"reset\" VALUE=\"Löschen\"></FORM>\n";
  print "<P>\n";
  }

sub WriteLog 
  {
  #write details of use to log file
  my $site = '';

  $site = $ENV{'REMOTE_ADDR'};
  if (defined($ENV{'REMOTE_HOST'}))
    { $site = $site . "(" . $ENV{'REMOTE_HOST'} . ")"; }
  if (-f $LOGFILE)
    { open(OUTFILE,">$LOGFILE") or return; }
  else
    { open(OUTFILE,">>$LOGFILE") or return; }
  flock(OUTFILE, 2); # exclusive lock
  print OUTFILE $ein{'searchvalue'}, ":", $ein{'type'}, ":";
  print OUTFILE localtime(time), ",", $site, "\n";
  flock(OUTFILE, 8); # unlock
  close(OUTFILE);
  }

sub CheckFiles 
  {
  # read files in directory, passed as first paramater
  my $path = '';
  my $fullFilename = '';
  my @files = ();
  my $line = '';
  my $title = '';
  my $header = '';
  my $search = '';
  my $tmp = '';
  my $tmpath = '';
  my $recurse = 0;
  my $found = 0;

  $path = shift;
  return unless (-d $path); 
  opendir(ROOT,$path) or return;
  @files = readdir(ROOT);
  closedir(ROOT);

  foreach (@files) 
    {
    next if /^\.|\.\.$/;

    $fullFilename = "$path/$_";

    if (-d $fullFilename) 
      {
      $recurse = 1;
      if ($exdirs) 
        {
        $tmp = $fullFilename;
        $tmp =~ s/$BASE//;
        foreach $tmpath (@excldirs) 
          {
          if ($tmp eq $tmpath) { $recurse = 0; last; }
          }
        }
      if ($recurse) { CheckFiles($fullFilename); }
      next;
      }

    if ($fullFilename =~ m/\.htm/i) 
      {
      open(FILE, $fullFilename) or return;
      $line = join(' ',<FILE>);    # Ganze Datei wird zu einer Zeile
      close(FILE);

      $line =~ s/\n//g;            # Newlines weg
      $line =~ s/&auml;/ä/g;       # Umlaute konvertieren
      $line =~ s/&ouml;/ö/g;
      $line =~ s/&uuml;/ü/g;
      $line =~ s/&Auml;/Ä/g;
      $line =~ s/&Ouml;/Ö/g;
      $line =~ s/&Uuml;/Ü/g;
      $line =~ s/&szlig;/ß/g;  


      $title = "No Title";
      if($line =~ m!<title>(.+)</title>!i) { $title = $1; };

      if ($ein{'type'} eq 'all' ) 
        {
        $found = 1;
        foreach $search (@search) 
          {
          if ($line !~ m/$search/i) { $found = 0; last; }
          }
        } 
      else # type = any 
        {
        $found = 0;
        foreach $search (@search) 
          {
          if ($line =~ m/$search/i) { $found = 1; last; }
          }
        }
    
      if ($found) 
        {
        $tmp = $fullFilename;
        $tmp =~ s/$BASE//;
        print "<LI><A HREF=\"$tmp\">$title</a>\n";
        $numberreturned++;
        }
      }
    }
  }

