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

$| = 1;

# ----------- Beginn Konfiguration --------------
# Pfad zu den Manual pages
my $man_path = "/usr/share/man";
#   my $man_path = ".";

# Pfad zum man-Programm
my $man = "/usr/bin/man";

# ------------ Ende Konfiguration ---------------

# Global: Formulardaten
my %FORM = ();

ParseForm();

my $manpage = $FORM{'manpage'};
my $section = $FORM{'section'};

print "Content-type: text/html\n\n";

if (defined($FORM{'submit'}))
  {
  $manpage =~ s/^\s*(.*)\b\s*$/$1/;
  if ((!$manpage) || ($manpage !~ /^[\w\+\-]+$/))
    {
    Error ("500 UNIX Manual Page Gateway Error",
           "Fehler bei der Angabe der Manpage.");
    }
  $section = FindSection($section, $manpage);
  if (($section < 1) || ($section > 8))
    {
    Error ("500 UNIX Manual Page Gateway Error",
    "Document nicht gefunden: $FORM{'section'} - $manpage");
    }
  DisplayManpage($section, $manpage);
  }
else
  { ShowForm(); }


sub ShowForm
  {
  # Formular ausgeben
  print qq~
  <FORM ACTION="$ENV{'SCRIPT_NAME'}" METHOD="POST">
  <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="5">
  <TR>
  <TD VALIGN="TOP" ALIGN="LEFT">Maualseite:</TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="TEXT" NAME="manpage" VALUE="" SIZE="20">
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">Sektion:</TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="section" VALUE="" CHECKED>alle
  <INPUT TYPE="RADIO" NAME="section" VALUE="1">1
  <INPUT TYPE="RADIO" NAME="section" VALUE="2">2
  <INPUT TYPE="RADIO" NAME="section" VALUE="3">3
  <INPUT TYPE="RADIO" NAME="section" VALUE="4">4
  <INPUT TYPE="RADIO" NAME="section" VALUE="5">5
  <INPUT TYPE="RADIO" NAME="section" VALUE="6">6
  <INPUT TYPE="RADIO" NAME="section" VALUE="7">7
  <INPUT TYPE="RADIO" NAME="section" VALUE="8">8
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">&nbsp;</TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="SUBMIT" NAME="submit" VALUE=" Manualseite anzeigen ">
  </TD>
  </TR>
  </TABLE>
  </FORM>
  ~;
  }


sub FindSection # ($section, $manpage)
  {
  # gibt es die Manualseite ueberhaupt
  my ($section, $manpage) = @_;
  my ($loop, $dir, $file, $gzfile);
  my $tmp_section = 0;

  # keine Sektion angegeben, alle durchsuchen
  if ($section !~ /^\d+$/)
    {
    for $loop (1 .. 8)
      {
      $dir  = $man_path . '/man' . $loop;
      # die Datei kann entweder normal oder komprimiert (.gz)
      # vorliegen. Beides wird getestet.
      $file = $dir . '/' . $manpage . '.' . $loop;
      $gzfile = $file . '.gz';
      if (-f $file || -f $gzfile)
        {
        # gefunden, fertig
        $tmp_section = $loop;
        last;
        }
      }
    return ($tmp_section);
    }
  else
    {
    # das gleiche, bei angegebener Sektion
    $file = $man_path . '/man' . $section . '/' .
            $manpage . '.' . $section;
    $gzfile = $file . '.gz';
    $tmp_section = $section if (-f $file || -f $gzfile);
    return ($tmp_section);
    }
  }

sub DisplayManpage # ($section, $manpage)
  {
  # Manualseite anzeigen, aber etwas aufbereiten
  my ($file, $blank, $heading, $line);

  print qq~
   <HTML>
   <HEAD><TITLE>UNIX Manual Page Gateway</TITLE></HEAD>
   <BODY TEXT="#000000" BGCOLOR="#FFFFFF">
   <H2>UNIX Manual Page Gateway</H2>
   <HR>
   <PRE>
   ~;
  # wir lassen das Man-Kommando die Arbeit machen
  open (MANUAL, "$man $section $manpage |");
  $blank = 0;
  # Manualpage etwas aufbereiten
  while ($line = <MANUAL>)
    {
    chomp($line);
    # Kopf- und Fusszeilen ueberlesen
    next if (($line =~ /^$manpage\(\w+\)/i) or
             ($line =~ /\bLast change:/o));
    # Die Folge "Zeichen, Backspace, Zeichen" ersetzen
    # durch das Zeichen alleine
    $line =~ s/\S\010(\S)/$1/g;
    # Ueberschrift bearbeiten, wird H3
    if ($line =~ /^([A-Z0-9_ ]+)$/)
      {
      $heading = $1;
      print "<H3>", $heading, "</H3>", "\n";
      }
    elsif ($line =~ /^\s*$/)
      {
      # max. 2 Leerzeilen hintereinander ausgeben
      $blank++;
      print "$line\n" if ($blank < 2);
      }
    else
      {
      # normale Textzeile, "gefaehrliche" HTML-Tags umwandeln
      $blank = 0;
      $line =~ s/\&/&amp;/g;
      $line =~ s/</&lt;/g;
      $line =~ s/>/&gt;/g;
      # Die Folge "Underline, Backspace, Zeichen" ersetzen
      # durch Fettdruck
      if ($line =~ /_\010/)
        {
        $line =~ s/((_\010\S)+)/<B>$1<\/B>/g;
        $line =~ s/_\010//g;
        }
      # die bearbeitete Zeile ausgeben
      print "$line\n";;
      }
    }
  close (MANUAL);

  # HTML-Nachspann
  print qq~
   </PRE>
   <HR>
   </BODY>
   </HTML>
   ~;
  }


sub Error
  {
  # Fehlertext ausgeben
  my ($status, $message) = @_;

  print qq~
  <h3>$status</h3>
  <hr>$message<hr>
  </BODY>
  </HTML>
  ~;
  exit(1);
  }


sub ParseForm
    {
    my ($buffer, @pairs, $pair, $name, $value);
    # Read in text
    if ($ENV{'REQUEST_METHOD'} eq "POST")
      { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
    else
      { $buffer = $ENV{'QUERY_STRING'};  }
    @pairs = split(/&/, $buffer);
    foreach $pair (@pairs)
      {
      # Name-Wert-Paare trennen
      ($name, $value) = split(/=/, $pair);
      # Leerzeichen wieder einsetzen
      $value =~ tr/+/ /;
      # URL-codierte Zeichen (%xx) ersetzen
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      # im hash speichern
      if (defined $FORM{$name})    # vermutlich checkbox
        { $FORM{$name} = $FORM{$name} . ", " . $value; }
      else
        { $FORM{$name} = $value; }
      }
    }