#!/usr/bin/perl
use strict;
use warnings;
use CGI;

# nur fuer den Test!
use CGI::Carp qw(fatalsToBrowser);

$| = 1;

# ......................................................................
# ....................... Configuration section ........................
# ......................................................................

# Anzahl Fundstellen/Bildschirmseite
my $ITEMSPERPAGE = 20;

# Maximlalzahl der angezeigten Fundstellen
my $MAXPAGES = 15;

# maximale Laenge der Ausgabe je Item in Zeichen
my $MAXLEN = 400;

# Pfad zur Index-Datei
my $index = '/opt/www/swish/skripten_index';

# swish-e executable
my $SWISHE = "/usr/bin/swish-e";

# ......................................................................
# ................................. end ................................
# ......................................................................

# Zeitlimit setzen, falls das Programm haengen sollte
$SIG{'ALRM'} =\&alarm_handle;
alarm(300);

# neues CGI-Objekt erzeugen
my $cgi = new CGI;

# Skript-URL ermitteln
my $script_url = "$ENV{'SCRIPT_NAME'}";

# Parameter aus dem Formular holen
my $suche = $cgi->param('suche');
my $seite = $cgi->param('seite');

# Parameter "entgiften"
$suche = '' unless($suche);
$seite = 1 unless ($seite);
$seite =~ s/[^0-9]//;
$seite = $MAXPAGES if ($seite >$MAXPAGES);

# Unerwuenschte Zeichen entfernen
$suche =~ s/[^\s\w\-\(\)äöüÄÖÜß]+//g;
my @wordlist = split(/\s+/,$suche);

# Vorspann
print $cgi->header;
print $cgi->start_html(-title => 'Suchen');

# Formular ausgeben ...
print_form($suche,$seite);
# ... und den Swish-E fragen
if (defined  $cgi->param('suche'))
  { search($suche, $seite, $index); }
# Seitenende
print $cgi->end_html();


sub search # ($suche, $seite, $db)
  {
  # Suchfunktion
  my ($suchbegriff, $seite, $db) = @_;
  # Notbremse
  return unless $suchbegriff && $db;
  # Anzahl Seiten begrenzen
  $seite = ($seite > $MAXPAGES) ? $MAXPAGES : $seite;
  # Limit fuer Query erstellen - Eintraege pro Seite
  my $max = $MAXPAGES*$ITEMSPERPAGE;

  # Swish aufrufen
  my $swishcall = "$SWISHE -H0 -w '$suchbegriff' -b 1 " .
                   "-m $max -f $db -x '%r#%p#%t#%l#%d\n'";
  my @daten = `$swishcall`;

  # Zeilenanzahl der Datei festellen
  my $zeilen = scalar(@daten) - 1;
  # Start und Ende der aktuellen Ausgabeseite berechnen
  my $start = ($seite - 1) * $ITEMSPERPAGE + 1;
  $max = $zeilen - $start;
  $max = ($max > $ITEMSPERPAGE)? $start+$ITEMSPERPAGE : $start+$max;
  # Ergebnisausgabe
  if ($zeilen > 0)
    {
    # Navigationsleiste erstellen
    my $navigation = file_navi($zeilen, $seite, $ITEMSPERPAGE,
                               $suchbegriff, $db);
    print "<p><b>Suchbegriff: '$suchbegriff'</b>\n";
    print "$navigation<br>\n";

    # Zeilen des aktuellen Bereiches $start .. $max ausgeben
    my $i = $start;
    while ($i < $max)
      {
      # Kommantarzeilen, Leerzeilen, Fehlermeldungen ueberspringen
      next if ($daten[$i] =~ /^(#|\.|err: )/);
      next if ($daten[$i] =~ /^\s*$/);
      $i++;
      # Datenzeile zerlegen
      my($score, $path, $title, $size, $comment) = split(/#/,$daten[$i]);
      unless ($title)
        {
        $title = $path;
        $title =~ s|^.+/||;
        }
      # Scorewert von Promille auf Prozent umrechnen
      $score = int($score/10);
      # Score und Link ausgeben
      print "<b>$score% <a href=\"$path\">$title</a></b><br><small>\n";
      # Beschreibung ggf. kuerzen
      if (length($comment) > $MAXLEN)
        {
        my $pos = rindex($comment, " ", $MAXLEN);
        $comment = substr($comment, 0, $pos) . " ... ";
        }
      # Suchbegriff in der Beschreibung fett machen
      $comment =~ s/$suchbegriff/<b>$suchbegriff<\/b>/g;
      # Beschreibung ausgeben
      print "$comment<br>\n";
      # URL und Groesse ausgeben
      print "<font color=\"#008000\">$path - $size Bytes</font></small><p>\n";
      }
    print "$navigation<br>\n";
    }
  else
    { print "<b>Keine (weiteren) Daten gefunden!</b>\n";  }
  }


sub print_form # ($suchbegriff, $seite);
  {
  # Formularausgabe
  my ($suche,$seite) = @_;
  print qq~
    <p><b>Suche nach: </b>
    <form action="$script_url" method="GET">
    <input type="text"   name="suche"  value="$suche">
    <input type="hidden" name="seite"  value="1">
    <input type="submit" name="action" value="Suchen">
    </form></p>
    ~;
  }


sub file_navi # ($zeilen, $seite, $pro_seite, $suche, $db)
  {
  # Seitennavigation Navigantionsleiste erstellen
  my ($zeilen, $seite, $pro_seite, $suche, $db) = @_;
  my ($pag, $i);

  my $gesamtseiten = int(($zeilen - 1)/$pro_seite + 1);
  my $aktseite = $seite ? $seite : 1;
  # Suchbegriff wieder URL-codieren
  $suche =~ s/([^A-Za-z0-9 ])/sprintf("%%%02X", ord($1))/seg;
  $suche =~ s/ /+/g;
  # NAvigationslinks ausgeben
  my $navlnk = '<table align="center" bgcolor="#dddddd" cellspacing="2" '
               . 'cellpadding="2" border="0"><tr>' . "\n";
  if ($gesamtseiten != 1 && $zeilen)
    {
    if ($aktseite > 1)
      {
      # "<<"-Link ausgeben
      $pag = $aktseite - 1;
      $navlnk .=  qq~
      <td width="20" align="center">
       <a href="$script_url?seite=$pag&suche=$suche">&lt;&lt;</a>
      </td>
      ~;
      }
    for ($i = 1; $i <= $gesamtseiten; $i++)
      {
      if ($aktseite == $i)
        {
        # aktuelle Seite ohne Link
        $navlnk .= qq~
        <td width="20" align="center" bgcolor="#ddffdd"><b>$i</b></td>
        ~;
        }
      else
        {
        # Seiten davor und danach mit Link
        $navlnk .= qq~
        <td width="20" align="center">
         <a href="$script_url?seite=$i&suche=$suche">$i</a></td>
         ~;
        }
      }

    if ($aktseite < $gesamtseiten)
      {
      # ">>"-Link ausgeben
      $pag = $aktseite + 1;
      $navlnk .= qq~
      <td width="20">
        <a href="$script_url?seite=$pag&suche=$suche">&gt;&gt;</a>
      </td>
      ~;
      }
    $navlnk .= "\n</tr></table>\n";
    # Das ganze HTML als String zurueckgeben
    return $navlnk;
    }
  return "&nbsp;";
  }


sub alarm_handle
  # Timeout behandeln --> Programm beenden
  {
  alarm(0);
  exit 0;
  }
