#!/usr/bin/perl -w
#
#
# Dieses Programm erlaubt es, einen Kalender ueber das Web zu pflegen, 
# in den eine ueberschaubare Anzahl von Leuten Ihre Anwesenheit 
# eintragen. Sinn: Abteilungsuebersicht 'wer ist da' oder 'wo isser denn'
#
# Es wird MySQL benoetigt. Ausserdem ein aktuelles Perl bzw ein aktuelles 
# Modul CGI:Carp. Falls nicht vorhanden, kann die Zeile mit dem Import
# des Moduls CGI::Carp qw(fatalsToBrowser warningsToBrowser) geloescht werden.
# Dann werden evtl. Fehler aber nicht mehr im Browser angezeigt.
# ............................................................................
#  Hubert Quint sagt:
#     Add_Delta_YM($sy,$sm,$sd,0,1) habe ich durch
#     Add_Delta_YMD($sy,$sm,$sd,0,1,0) ersetzt, bei Suse 7.3 und 
#     dem aelteren Date-Calc gibt es diese Funktion nicht.
#     Und noch eine Anpassung der Zeile
#     print "<pre>" . Calendar(Add_Delta_YMD($sy,$sm,$sd,0,1,0));
#     in
#     print "<pre>" . Calendar( (Add_Delta_YMD($sy,$sm,$sd,0,1,0))[0,1] );
#     und ebenso fuer den Monat +2.
#     Damit laeuft das Script auch auf aelteren Installationen.
# ............................................................................
#
# Das Programm ist frei weiterverwendbar unter den folgenden Bedingungen:
# - Bei Veraenderungen bleibt mein Name erhalten
# - Bei Produktionseinsatz erhalte ich eine kurze EMail, wo das Programm
#   eingesetzt wird.
#
# Die Benutzung des Programmes geschieht natuerlich auf eigene Gefahr.
#
# Installation:
# - Script nach cgi-bin kopieren
# - Datenbank weristda in mysql anlegen
# - User weristda in mysql anlegen, mit select, insert, update, delete-Recht in DB weristda
# - Tabellen nach weristda.dump anlegen (mysql -p -u root < weristda.dump)
# - Fehlende Perlmodule installieren (z.B. Date::Calc)
# - Optional:
#   - cgi-bin passwortschuetzen via AuthConfig in Apache
#   - Fuer jeden potentiellen User per htpasswd einen eigenen Account anlegen, Datei z.B. /srv/www/passwd
#   - .htaccess im Verzeichnis mit diesem Programm anlegen wie folgt:
#         AuthName WERISTDA
#         AuthType Basic
#         AuthUserFile /srv/www/passwd
#         require user misc syth (... usw fuer alle user, die eingetragen sind)
#
#   - Vorteil: Usernamen tauchen in der Logtabelle auf
#   - Vorteil: Ein User kann nur seine eigenen Termine anlegen/aendern
#   - Vorteil: Die Userverwaltung kann auf einen User beschraenkt werden
#
# Dieses Script editieren und die Punkte bei "Konfiguration ab hier" anpassen.
#
# Script per Webbrowser als $usereditallow aufrufen und User in weristda eintragen.
#
# Achtung: Von Zeit zu Zeit Tabellengroesse ueberpruefen und alte Termine sowie
#  alte Logeintraege loeschen.
# 
# Bemerkung: Die Farben koennen eine Anpassung vertragen. Das Programm wurde auf einem TFT erstellt (Notebook), wo die
# Farben gut aussehen. Auf CRTs sind sie zu grell. Tip: Suche nach "bgcolor" in diesem Script. 

use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use CGI qw(:standard);
use DBI;
use Date::Calc qw(:all);
use strict;

# -------------Konfiguration ab hier---------------------------------

my $dbuser = "account";
my $dbpassword = "passwort";
my $dbhost = "localhost";
my $db = "weristda";
my $dbport = "3306";

my $eigeneurl='/cgi-bin/weristda/weristda.pl';
my $anzeigeintervall=28;   # In diesem Intervall erfolgt die Anzeige
my $maxfolgetermine=35;    # Maximale Anzahl von Folgeterminen

my $loglevel=1;            # 2=maximal, 1=nur Aenderungen auf Tabellen, 0=nichts wird mitgeschrieben
                           # Achtung: Die logs werden in der Tabelle log mitgeschrieben,
                           # diese muss ab und zu manuell gereinigt werden!

my $usereditallow="name des benutzers, der die userverwaltung benutzen darf";

# --------------bis hier---------------------------------------------

my $version = '1.1, 4/03, Michael@Schaarwaechter.de';
my %userid;
my %username;
my $query = new CGI;   
my $startparam="";
delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)}; # Pfad sicher machen
Language(3);  # Deutsche Sprache einstellen
my $remote_user=$query->remote_user || "-"; # Achtung: "-" wird unten mehrfach abgeprueft, nicht aendern!


# -------------------------
sub logentry {
   # Erstellt Eintrag in Logdatei,m abhaengig vom Loglevel
   my ($level,$action)=@_;

   return if ($loglevel < $level);

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
      insert into log (wer,was) values (?,?)
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   $sth->execute($query->remote_host().", ".$remote_user,$action) or die "Can't execute statement: $DBI::errstr";
   $dbh->disconnect;
 
}
# -------------------------
sub ausgabestart {
   print $query->header;
   print $query->start_html(-title=>"WerIstDa",
                            -bgcolor=>"#FFFFCA"); # Hintergrundfarbe der Seite
#   print "<h1>WerIstDa? Die Abteilungs-Zeit-Planung.</h1>";
   # warningsToBrowser(1);
}
# -------------------------
sub ausgabeende {

   print "<BR><HR>\n";
   print "<table border=1>";
   print "<tr><td colspan=2>Informationen &uuml;ber den Client</td></tr>";
   print "<tr><td>Remote Host</td><td>".$query->remote_host()."</td></tr>";
#   print "<tr><td>Referer</td><td>".$query->referer()."</td></tr>";
   print "<tr><td>User Agent</td><td>".$query->user_agent(),"</td></tr>";
   print "</table>";
   print "<P>Erzeugt von weristda.pl, Version $version <br>" ;
   print "<a href=\"mailto:Michael.Schaarwaechter\@ub.uni-dortmund.de\">Michael Schaarw&auml;chter</a>";
   print "</P>\n";
   print $query->end_html;
}
# ----------------------------------------------------------------------
sub feiertag {
   # Gibt fuer ein Datum den Namen des Feiertages oder leer zurueck
   my ($y,$m,$d) = @_;


   return "Neujahr"             if ( ($m == 1 ) and ($d == 1 ) );
   return "Silvester"           if ( ($m == 12) and ($d == 31) );
   return "Tag der Arbeit"      if ( ($m == 5 ) and ($d == 1 ) );
   return "Tag der Einheit"     if ( ($m == 10) and ($d == 3 ) );
   return "Allerheiligen"       if ( ($m == 11) and ($d == 1 ) );
   return "Heiligabend"         if ( ($m == 12) and ($d == 24) );
   return "1. Weihnachtstag"    if ( ($m == 12) and ($d == 25) );
   return "2. Weihnachtstag"    if ( ($m == 12) and ($d == 26) );

   my ($ey,$em,$ed) = Easter_Sunday($y);

   return "Ostersonntag"        if ( Delta_Days($ey,$em,$ed,$y,$m,$d) == 0 );
   return "Ostermontag"         if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,1),$y,$m,$d) == 0 );
#   return "(Rosenmontag)"       if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-48),$y,$m,$d) == 0); 
#   return "(Karneval)"          if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-47),$y,$m,$d) == 0); 
#   return "(Weiberfastnacht)"   if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-52),$y,$m,$d) == 0);
#   return "(Aschermittwoch)"    if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-46),$y,$m,$d) == 0);
   return "Palmsonntag"         if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-7),$y,$m,$d) == 0);
   return "Karfreitag"          if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,-2),$y,$m,$d) == 0);
   return "Christi Himmelf."    if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,39),$y,$m,$d) == 0);
   return "Pfingstsonntag"      if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,49),$y,$m,$d) == 0);
   return "Pfingstmontag"       if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,50),$y,$m,$d) == 0);
   return "Fronleichnam"        if ( Delta_Days(Add_Delta_Days($ey,$em,$ed,60),$y,$m,$d) == 0);

   return "";
}
# ----------------------------------------------------------------------
sub userverwaltung {


   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                  select * from user order by account
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   my $rc = $sth->execute or die "Can't execute statement: $DBI::errstr";

   print "<h1>Userverwaltung</h1>\n";
   print qq#<h2><a href="$eigeneurl?$startparam">Zur&uuml;ck zum Kalender</a></h2><hr>\n#;

   print "<table border=1>";
   print "<tr><th>ID</th><th>Account</th><th>Vorname</th><th>Name</th><th>Bemerkung</th><th>Gel&ouml;scht</th><th>Aktion</th></tr>\n";
   while ( my ($id,$account,$name,$vorname,$bemerkung,$geloescht) = $sth->fetchrow_array) {
      print qq#<form action="$eigeneurl" method="get">\n#;
      print qq#<input type="hidden" name="userverwaltung" value="aendern">#;
      print qq#<input type="hidden" name="id" value="$id">#;
      print "<tr>";
      print "<td>$id</td>";
      print qq#<td><input type="text" value="$account" name="account" size="6"></td>#;
      print qq#<td><input type="text" value="$vorname" name="vorname" size="15"></td>#;
      print qq#<td><input type="text" value="$name" name="name" size="20"></td>#;
      print "<td valign=top><textarea name=\"bemerkung\" cols=\"30\" rows=\"1\">$bemerkung</textarea></td>"; 
      print "<td>Ja</td>" if ($geloescht);
      print "<td>-</td>" if (not $geloescht);

      print "<td>";
      print qq#<input name="btng" type="submit" value="&Auml;ndern">\n#;
      print qq#&nbsp;&nbsp;<a href="$eigeneurl?userverwaltung=entloesche&id=$id&$startparam">Account entl&ouml;schen</a># if ($geloescht);
      print qq#&nbsp;&nbsp;<a href="$eigeneurl?userverwaltung=loesche&id=$id&$startparam">Account l&ouml;schen</a># if (not $geloescht);
      print "</form>";
      print "</td>";
      print "</tr> \n";
   }
   my ($start1,$start2)=split(/=/,$startparam);
   print qq#<form action="$eigeneurl" method="get">\n#;
   print qq#<input type="hidden" name="userverwaltung" value="zufuegen">#;
   print qq#<input type="hidden" name="$start1" value="$start2">#;
   print "<tr>";
   print "<tr><td colspan=7></td></tr>";
   print "<td><font color=\"red\">Neu</font></td>";
   print qq#<td><input type="text" value="Account" name="account" size="7"></td>#;
   print qq#<td><input type="text" value="Vorname" name="vorname" size="15"></td>#;
   print qq#<td><input type="text" value="Name" name="name" size="20"></td>#;
   print "<td valign=top><textarea name=\"bemerkung\" cols=\"30\" rows=\"1\"></textarea></td>";
   print "<td>&nbsp;</td>";
   print "<td>";
   print qq#<input name="btng" type="submit" value="Zuf&uuml;gen">\n#;
   print "</form>";
   print "</table>\n";

   $dbh->disconnect;

   print <<"USERVINFO";
<h2><font color=\"red\">Achtung!</font></h2>
Einmal angelegte User k&ouml;nnen mit diesem Programm nur als gel&ouml;scht <i>markiert</i> werden!<br>
Als gel&ouml;scht markierte User tauchen im Kalender nicht auf, ihre Termine werden nicht angezeigt. Dies kann per 'Entl&ouml;schen'
wieder r&uuml;ckg&auml;ngig gemacht werden.<br>
<font color=\"red\">Bitte die Userverwaltung mit Vorsicht benutzen, ein einmal angelegter User kann mit diesem Interface nicht wieder 
gel&ouml;scht werden!!</font><br>\n
<b>Neue User anlegen:</b> Die Felder Account, Vorname und Name in der unteresten Tabellenzeile f&uuml;llen und dann auf Zuf&uuml;gen klicken.\n
USERVINFO
&logentry(2,"Userverwaltung aufgerufen");
}
# ----------------------------------------------------------------------
sub userzufuegen {
   my ($account,$name,$vorname,$bemerkung)=@_;


   return qq#<h2><font color="red"> User zuf&uuml;gen nicht erlaubt! Bitte $usereditallow fragen!</font></h2>#
      if (($remote_user ne $usereditallow) and ($remote_user ne "-"));
   return qq#<h2><font color="red"> Bitte die Defaulttexte in den Eingabefeldern l&ouml;schen! </font></h2># 
      if ($account=~m/Account/ or $vorname=~m/Vorname/ or $name=~m/Name/);

   return qq#<h2><font color="red"> Bitte Account eintragen!</font></h2>#
      if ($account eq "");   
   return qq#<h2><font color="red"> Bitte Name eintragen!</font></h2>#
      if ($name eq "");
   return qq#<h2><font color="red"> Bitte Vorname eintragen!</font></h2>#
      if ($vorname eq "");

   return qq#<h2><font color="red"> $account schon vorhanden!</font></h2># if ($userid{$account});
   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
      insert into user (account,name,vorname,bemerkung) values (?,?,?,?)
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   $sth->execute($account,$name,$vorname,$bemerkung) or die "Can't execute statement: $DBI::errstr";
   $dbh->disconnect;
   &logentry(1,"User zugefuegt: $account,$name,$vorname,$bemerkung");
   return qq#<h2><font color="red">$account zugef&uuml;gt!</font></h2>\n#;
}
# ----------------------------------------------------------------------
sub userloeschen {
   my ($loeschen,$id) = @_;

   return qq#<h2><font color="red"> User l&ouml;schen nicht erlaubt! Bitte $usereditallow fragen!</font></h2>#
      if (($remote_user ne $usereditallow) and ($remote_user ne "-"));

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   
   my $sth = $dbh->prepare( q{
         update user set deleted=? where id=?
                          } ) 
         or die "Can't prepare statement: $DBI::errstr";
   $sth->execute($loeschen,$id) or die "Can't execute statement: $DBI::errstr";
   $dbh->disconnect;
   &logentry(1,"User geloescht: $id, $username{$id}") if ($loeschen);
   &logentry(1,"User entloescht: $id, $username{$id}") if (not $loeschen);
   return qq#<h2><font color="red">Account mit der ID $id als gel&ouml;scht markiert</font></h2>\n# if ($loeschen);
   return qq#<h2><font color="red">Account mit der ID $id entl&ouml;scht</font></h2>\n# if (not $loeschen);

}
# ----------------------------------------------------------------------
sub useraendern {
   my ($id,$account,$name,$vorname,$bemerkung)=@_;

   return qq#<h2><font color="red"> User &auml;ndern nicht erlaubt! Bitte $usereditallow fragen!</font></h2>#
      if (($remote_user ne $usereditallow) and ($remote_user ne "-"));

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";

   my $sth = $dbh->prepare( q{
         update user set account=?,name=?,vorname=?,bemerkung=? where id=?
                          } )
         or die "Can't prepare statement: $DBI::errstr";
   $sth->execute($account,$name,$vorname,$bemerkung,$id) or die "Can't execute statement: $DBI::errstr";
   $dbh->disconnect;
   &logentry(1,"User geaendert: $id, $account,$name,$vorname,$bemerkung");
   return qq#<h2><font color="red">Account mit der ID $id ge&auml;ndert.</font></h2>\n#
}
# ----------------------------------------------------------------------
sub holealleuser {
   # liefert die Namen aller User, speichert in globalem Hash %user;
   
   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                  select * from user
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   my $rc = $sth->execute or die "Can't execute statement: $DBI::errstr";
 
   while ( my ($id,$account,$name,$vorname,$bemerkung,$deleted) = $sth->fetchrow_array) {
      $userid{$account} = $id if (not $deleted);
      $username{$id} = $account if (not $deleted);
   }
   $dbh->disconnect;
}
# ----------------------------------------------------------------------
sub terminausgabe {
   # Gibt zu einem Termin und einem User den vollen Eintrag aus, erlaubt edit und loeschen
   my ($id,$datum)=@_;
   my ($zeitstempel,$start,$ende,$folgeid,$wo,$text);

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                 select zeitstempel,start,ende,folgeid,wo,text from termine where user_id=? and start=? 
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   my $rc = $sth->execute($id,$datum) or die "Can't execute statement: $DBI::errstr";
   ($zeitstempel,$start,$ende,$folgeid,$wo,$text) = $sth->fetchrow_array;
   if ($rc == 0) {
      ($zeitstempel,$start,$ende,$folgeid,$wo,$text) = ("Neu",$datum,$datum,int (rand (time())),"Ort","");
   }
   $sth->finish;
   $dbh->disconnect;

   my ($y,$m,$d)=split(/-/,$datum);
   my ($sy,$sm,$sd)=split(/-/,$start);
   my ($ey,$em,$ed)=split(/-/,$ende);
   my ($start1,$start2)=split(/=/,$startparam);

   print "<h1>Terminausgabe f&uuml;r $username{$id} am $d.$m.$y</h1>\n";
   print qq#<h2><a href="$eigeneurl?$startparam">Zur&uuml;ck zum Kalender</a></h2>\n#;
   print <<"TERMININFO";
<p>
<b>Termin f&uuml;r diesen Tag:</b> Nur das Feld 'Wo/Was' f&uuml;llen und ggf. die Bemerkung.<br>
<b>Termine f&uuml;r mehrere Tage, z.B. Urlaub:</b> Auch das Feld 'Endedatum' f&uuml;llen.<br>
Es wird dann 
f&uuml;r jeden Tag zwischen Start- und Endedatum inkl. jeweils ein Termin angelegt. Diese Termine erhalten wie alle
anderen eine eindeutige ID, bei Terminen &uuml;ber mehrere Tage alle dieselbe ID. Es werden nur maximal $maxfolgetermine Folgetermine 
angelegt!<br>
L&ouml;scht man einen Termin, der &uuml;ber mehrere Tage geht, werden automatisch <b>alle</b>
dazugeh&ouml;rigen Termine mitgel&ouml;scht!<br>
<br>
Pro Tag und User gibt es nur einen m&ouml;glichen Termin. Grund: Dieses Programm dient der Abteilungs-Planung und nicht der pers&ouml;nlichen
Terminplanung. Nat&uuml;rlich kann man einen Termin auch so bezeichnen, dass er ersichtlich z.B. nur f&uuml;r einen halben Tag gilt, etwa
'teilw.' als Ort und im Bemerkungsfeld 'Zahnarzttermin ab 12 Uhr' oder so aehnlich.
<br>
<br><font color=\"red\">Achtung: Bitte nur die <b>eigenen</b> Termine editieren!!!</font>
</p>
TERMININFO

   print "<table border=1>\n";
   print <<"EOHTML";
         <tr>
         <th>Interne ID</th>
         <th>Zuletzt ge&auml;ndert</th>
         <th>Datum</th>
         <th>Endedatum</th>
         <th>Wo/Was?</th>
         <th>Bemerkung</th>
         <th>Aktion</th>
         </tr>

         <form action=\"$eigeneurl" method=\"get\">
         <input type=\"hidden\" name=\"termin\" value=\"eintragen\">
         <input type=\"hidden\" name=\"$start1\" value=\"$start2\">
         <input type=\"hidden\" name=\"id\" value=\"$id\">
         <input type=\"hidden\" name=\"datum\" value=\"$datum\">
         <input type=\"hidden\" name=\"folgeid\" value=\"$folgeid\">
         <input type=\"hidden\" name=\"zeitstempel\" value=\"$zeitstempel\">
EOHTML
   print "<input type=\"hidden\" name=\"startdatum\" value=\"$sd.$sm.$sy\">" if (not $zeitstempel eq "Neu");
   print "<input type=\"hidden\" name=\"endedatum\" value=\"$ed.$em.$ey\">"   if (not $zeitstempel eq "Neu");
   print "<tr>"; 
   print "<td valign=top>$folgeid</td>";
   print "<td valign=top>$zeitstempel</td>";
   if ($zeitstempel eq "Neu") {
      print "<td valign=top><input type=\"text\" name=\"startdatum\" size=\"10\" maxlength=\"10\" value=\"$sd.$sm.$sy\"></td>";
      print "<td valign=top><input type=\"text\" name=\"endedatum\" size=\"10\" maxlength=\"10\" value=\"$ed.$em.$ey\"><br><br>";
      print "<select name=\"werktags\" size=\"1\">\n";
      print "<option>Werktags</option>\n";
      print "<option>Alle Tage</option>\n";
      print "</select>\n";
      print "</td>\n";
   } else {
      print "<td valign=top>$sd.$sm.$sy</td>";
      print "<td valign=top>$ed.$em.$ey</td>";
   }
   my $buttontext;
   if ($zeitstempel eq "Neu") {$buttontext="Eintragen"} else {$buttontext="&Auml;ndern"}
   
   print "<td valign=top><input type=\"text\" name=\"wo\" size=\"12\" maxlength=\"12\" value=\"$wo\"></td>";
   print "<td valign=top><textarea name=\"text\" cols=\"40\" rows=\"7\">$text</textarea></td>";
   print "<td valign=top><input name=\"button\" type=\"submit\" value=\"$buttontext\">";
   print "<br><input name=\"button\" type=\"submit\" value=\"Loeschen\">" if (not $zeitstempel eq "Neu");
   print "<td></tr>";

   print "</table>\n";

   print "<table border=1>\n";
   print "<tr><td>\n";
   print "<pre>".Calendar($sy,$sm);
   print "</pre>";
   print "</td><td>";
   print "<pre>" . Calendar(Add_Delta_YM($sy,$sm,$sd,0,1));
   print "</pre>";
   print "</td><td>";
   print "<pre>" . Calendar(Add_Delta_YM($sy,$sm,$sd,0,2));
   print "</pre>";
   print "</td>";
   print "</tr>";
   print "</table>\n";

   &logentry(2,"Terminausgabe: $id,$datum,$zeitstempel,$start,$ende,$folgeid,$wo,$text");
}
# ----------------------------------------------------------------------
sub terminloeschen {
   # Loescht einen Termin
   my ($id,$datum,$startdatum,$endedatum,$folgeid) = @_;

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                 delete from termine where user_id=? and folgeid=?
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   my $rc = $sth->execute($id,$folgeid) or die "Can't execute statement: $DBI::errstr";
   $dbh->disconnect;
   &logentry(1,"Termin geloescht: $id,$datum,$startdatum,$endedatum,$folgeid");
   return qq#<h2><font color="red">Termin mit der ID $folgeid f&uuml;r $username{$id} gel&ouml;scht!</font></h2>\n#
}
# ----------------------------------------------------------------------
sub termineintragen {
   # Prueft Parameter auf Richtigkeit und traegt ggf Termin ein.
   # Rueckgabe: Auszugebener String
   my ($id,$datum,$startdatum,$endedatum,$wo,$text,$folgeid,$zeitstempel,$werktags)=@_;
   my $change=1;
   my $message="";
   $werktags=0 if ($werktags eq "Alle Tage");
   $werktags=1 if ($werktags eq "Werktags");
   my ($sd,$sm,$sy) = split(/\./,$startdatum);
   my ($ed,$em,$ey) = split(/\./,$endedatum);  
 
   return qq#<h2><font color="red">Bitte Ort eingeben!</font></h2>\n# if ($wo eq "Ort" or length($wo)==0); 
   return qq#<h2><font color="red">Bitte korrekte Bemerkung eingeben!</font></h2>\n# if ($text eq "Bemerkung");
   return qq#<h2><font color="red">Das Start-Datum $startdatum ist nicht korrekt!</font></h2>\n# if (not check_date($sy,$sm,$sd)); 
   return qq#<h2><font color="red">Das Ende-Datum $endedatum ist nicht korrekt!</font></h2>\n# if (not check_date($ey,$em,$ed)); 

   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                 select zeitstempel,start,ende,folgeid,wo,text from termine where user_id=? and start=?
                          } )
   or die "Can't prepare statement: $DBI::errstr";
   my $rc = $sth->execute($id,$datum) or die "Can't execute statement: $DBI::errstr";
   $change = 0 if ($rc==0);   # Satz ist neu

#   $dbh->disconnect;

#   $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
#      or die "Could not connect: $DBI::errstr\n";

   if (not $change) {   # Satz nicht vorhanden, anlegen
      my @laufdatum=($sy,$sm,$sd);
      my $counter=0;
      while (Delta_Days((@laufdatum),$ey,$em,$ed) >= 0 ) {
         if ((not $werktags) or (not &feiertag((@laufdatum)) and Day_of_Week((@laufdatum))<6)) {
            my $sth = $dbh->prepare( q{
                       insert into termine (user_id,start,ende,folgeid,wo,text) values (?,?,?,?,?,?)
                                      } )
               or die "Can't prepare statement: $DBI::errstr";
            my $rc = $sth->execute($id,"$laufdatum[0]-$laufdatum[1]-$laufdatum[2]","$ey-$em-$ed",$folgeid,$wo,$text) 
               or die "Can't execute statement: $DBI::errstr";
            $message.="$laufdatum[2].$laufdatum[1].$laufdatum[0] ok.<br>\n";
            $counter++;
            last if ($counter > $maxfolgetermine);
         }
         (@laufdatum) = Add_Delta_Days((@laufdatum),1);
      }
   } else {  # Satz vorhanden, muss geaendert werden
      my $sth = $dbh->prepare( q{
                 update termine set wo=?,text=? where user_id=? and folgeid=?
                                } )
         or die "Can't prepare statement: $DBI::errstr";
      my $rc = $sth->execute($wo,$text,$id,$folgeid)
         or die "Can't execute statement: $DBI::errstr";
      $message="Termin ge&auml;ndert!";
   }
   $sth->finish;
   $dbh->disconnect;
   &logentry(1,"Termin eingetragen: $id,$datum,$startdatum,$endedatum,$wo,$text,$folgeid,$zeitstempel,$werktags");
   return qq#<h3><font color="red">$message</font></h3>\n#;
}
# ----------------------------------------------------------------------
sub termine {
   # liefert die Termine in html-ausgabe mit Links fuer geg. Datum
   my ($y,$m,$d,$farbe)=@_;

   my $return="";
   my $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost;port=$dbport",$dbuser,$dbpassword)
   or die "Could not connect: $DBI::errstr\n";
   my $sth = $dbh->prepare( q{
                  select wo from termine where start=? and user_id=?
                          } )
   or die "Can't prepare statement: $DBI::errstr";

   my $abfragedatum="$y-$m-$d";
   foreach my $u (sort keys %userid) {
      my $rc = $sth->execute($abfragedatum,$userid{$u}) or die "Can't execute statement: $DBI::errstr";
      my $wo;
      if (($u eq $remote_user) or ("-" eq $remote_user)) {
         $wo=qq#<a href="$eigeneurl?termin=show&id=$userid{$u}&datum=$y-$m-$d&$startparam">+</a>#;
      } else {
         $wo='&nbsp;'
      }
      my $color=$farbe;
      if ($rc>0) {
         $color=qq{ bgcolor="#FF0000"}; # Farbe fuer Daten=Tabellenzellen mit Termin
         ($wo) = $sth->fetchrow_array;
         $wo=qq#<a href="$eigeneurl?termin=show&id=$userid{$u}&datum=$y-$m-$d&$startparam">$wo</a>#;
      }
      $return.=qq#<td align=center $color>$wo</td>#;
   }

   $sth->finish;
   $dbh->disconnect;
   return $return;
}
# ----------------------------------------------------------------------
sub kalender {
   # Ausgabe in html. Parameter: Startdatum Endedatum

   my ($sy,$sm,$sd,$ey,$em,$ed)=@_;

   my @sdp=Add_Delta_Days($sy,$sm,$sd,14);
   my @sdm=Add_Delta_Days($sy,$sm,$sd,-14);
   my @sdp2=Add_Delta_Days($sy,$sm,$sd,28);
   my @sdm2=Add_Delta_Days($sy,$sm,$sd,-28);
   my @sdt=Today;

   # Beginn oberer Block

   print "<h1>Kalender";
   print " ($remote_user)" if ($remote_user ne "-");
   print "</h1>\n";
   
   print "<table border=1>\n";
   print "<tr><td>";

   print "<table border=1>\n";
   print "<tr><td colspan=3><b>Springe zu ...</b></td></tr>\n";
   
   print "<tr>";
   print qq#<td><a href="$eigeneurl?start=$sdt[0]-$sdt[1]-$sdt[2]">heute ($sdt[2].$sdt[1].$sdt[0])</a></td>#;
   print qq#<td><a href="$eigeneurl?start=$sdp[0]-$sdp[1]-$sdp[2]">+2 Wo. ($sdp[2].$sdp[1].$sdp[0])</a></td>#;
   print qq#<td><a href="$eigeneurl?start=$sdm[0]-$sdm[1]-$sdm[2]">-2 Wo. ($sdm[2].$sdm[1].$sdm[0])</a></td>#;
   print "</tr><tr>\n";
   print qq#<td>#;
   print qq#<form action=$eigeneurl method="get">#;
   print qq#<select name="start">#;
   foreach my $month( -3 .. 12 ) {
      my @datum=(Add_Delta_YM($sy,$sm,$sd,0,$month));
      print qq#<option value="$datum[0]-$datum[1]-$datum[2]">$datum[2].$datum[1].$datum[0]</option>\n#
   }
   print "</select>";
   print qq#<input type="submit" name="navig" value="Los!" />#;
   print "</form>";

   print "</td>";
   print qq#<td><a href="$eigeneurl?start=$sdp2[0]-$sdp2[1]-$sdp2[2]">+4 Wo. ($sdp2[2].$sdp2[1].$sdp2[0])</a></td>#;
   print qq#<td><a href="$eigeneurl?start=$sdm2[0]-$sdm2[1]-$sdm2[2]">-4 Wo. ($sdm2[2].$sdm2[1].$sdm2[0])</a></td>#;
   print "</tr>\n";

   print "</table>\n";

   print "</td><td>\n";  # Spaltenwechsel oberer Block
   
   print qq#<a href="$eigeneurl?userverwaltung=1&$startparam">Userverwaltung</a>#;

   print "</table>\n";

   # Ende oberer Block   

   print "<hr>\n";

   # Beginn Datumstabelle

   print <<"KALINFO";
<b>Klick auf ein Datum:</b> Dieses Datum zum ersten angezeigten machen.<br>
<b>Klick auf ein '+' zu einem Datum und einem User:</b> Termin f&uuml;r diesen User an diesem Datum und ggf. folgenden Tagen zuf&uuml;gen.<br>
<b>Klick auf einen Text zu einem Datum/User:</b> Bemerkung zu diesem Termin einsehen und Ort/Bemerkung ggf editieren.<br>
KALINFO

   my $thfarbe="bgcolor=\"#FFEA00\""; # Farbe des Tabellenheaders
   my ($kw,$ky) = Week_of_Year($sy,$sm,$sd);
   my @tableheader = ("<tr><td colspan=20>","</td></tr><tr $thfarbe><th>Tag</th><th>Datum</th><th>&nbsp;</th>");
   foreach my $key(sort keys %userid) {
      $tableheader[1] .= "<th>&nbsp;&nbsp;$key&nbsp;&nbsp;</th>";
   }
   $tableheader[1] .= "</tr>\n";

   my @laufdatum=($sy,$sm,$sd);
   my $farbe;
   print "<table border=1>\n"; 
   print $tableheader[0]."$kw. KW $ky".$tableheader[1] if (Day_of_Week(@laufdatum) > 1 );
   while  (Delta_Days((@laufdatum),$ey,$em,$ed) > 0 ) {
      SWITCH: {
         if (Delta_Days((@laufdatum),Today) == 0 ) {$farbe = "bgcolor=\"#EE7777\"";last SWITCH} # Farbe eines normalen Tages
         if ( Day_of_Week(@laufdatum) > 5  )             {$farbe = "bgcolor=\"#53FF1A\"";last SWITCH} # Farbe fuer Wochenenden
         if (&feiertag(@laufdatum))                      {$farbe = "bgcolor=\"#80FFFF\"";last SWITCH} # Farbe fuer Feiertage
         $farbe = " "
      }
      if (Day_of_Week(@laufdatum) == 1 ) {
         ($kw,$ky) = Week_of_Year((@laufdatum));
         print $tableheader[0]."$kw. KW $ky".$tableheader[1];
      }

      print "<tr>" .
             "<td $farbe>" . 
             &Day_of_Week_Abbreviation(&Day_of_Week(@laufdatum)) .
             "</td><td $farbe>" .
             qq#<a href="$eigeneurl?start=$laufdatum[0]-$laufdatum[1]-$laufdatum[2]">$laufdatum[2].$laufdatum[1].$laufdatum[0]</a># .
             "</td><td $farbe>" .
             &feiertag(@laufdatum) .
             "</td>" .
             &termine(@laufdatum, $farbe) .   # &termine liefert die <td> und </td> mit
             "</tr>\n";
      
      @laufdatum=Add_Delta_Days(@laufdatum,1);
   }
 
   print "</table>\n";
   &logentry(2,"Kalender aufgerufen: $sy-$sm-$sd, $ey-$em-$ed");
}
# ----------------------------------------------------------------------
sub testfeiertage {
   my @start=(2003,1,1);

   foreach my $d (0..365) {
      my @datum=Add_Delta_Days(@start,$d);
      print &Day_of_Week_Abbreviation(&Day_of_Week(@datum)).", $datum[0]-$datum[1]-$datum[2]  ".&feiertag(@datum)."\n";
   }
}
# ----------------------------------------------------------------------


# &testfeiertage; exit;

&holealleuser;
&ausgabestart;

my @start;
my @ende;
if (defined $query->param("start")) {
   @start=split(/-/,$query->param("start"));
   $startparam="start=".$query->param("start");
} else {
   @start=Today 
}

if (defined $query->param("ende")) {
   @ende=split(/-/,$query->param("ende"));
} else {
   @ende=Add_Delta_Days(@start,$anzeigeintervall)
}

if (defined $query->param("userverwaltung")) {
   if ($query->param("userverwaltung") eq "zufuegen") {
      print &userzufuegen($query->param("account"),$query->param("name"),$query->param("vorname"),$query->param("bemerkung"));
   }
   if ($query->param("userverwaltung") eq "loesche") {
      print &userloeschen(1, $query->param("id"));
   }
   if ($query->param("userverwaltung") eq "entloesche") {
      print &userloeschen(0, $query->param("id"));
   }
   if ($query->param("userverwaltung") eq "aendern") {
      print &useraendern($query->param("id"),$query->param("account"),$query->param("name"),$query->param("vorname"),
                $query->param("bemerkung"));
   }
   &userverwaltung;
   &ausgabeende;
   exit;
}
if (defined $query->param("termin")) {
# termin=show&id=$userid{$u}&datum=$y-$m-$d&$startparam
# ($id,$datum,$startdatum,$endedatum,$wo,$text,$folgeid,$zeitstempel)
   if ($query->param("termin") eq "eintragen"  and $query->param("button") eq "Loeschen") {
      if (($remote_user ne $username{$query->param("id")}) and ($remote_user ne "-")) {
         print qq#<h2><font color="red"> Termin f&uuml;r #.$username{$query->param("id")}." l&ouml;schen nicht erlaubt!</font></h2>\n";
      } else {
         print &terminloeschen(
               $query->param("id"),
               $query->param("datum"),
               $query->param("startdatum"),
               $query->param("endedatum"),
               $query->param("folgeid"),
               );
      }
      &kalender(@start,@ende);
      &ausgabeende;
      exit;
   } else {
      if ($query->param("termin") eq "show") {
      
      }
      if ($query->param("termin") eq "eintragen") {
         if (($remote_user ne $username{$query->param("id")}) and ($remote_user ne "-")) {
            print qq#<h2><font color="red"> Termin f&uuml;r #.$username{$query->param("id")}." eintragen/&auml;ndern nicht erlaubt!</font></h2>\n";
         } else {   
            print &termineintragen(
                  $query->param("id"),
                  $query->param("datum"),
                  $query->param("startdatum"),
                  $query->param("endedatum"),
                  $query->param("wo"),
                  $query->param("text"),
                  $query->param("folgeid"),
                  $query->param("zeitstempel"),
                  $query->param("werktags")
                  );
         }
      }
      &terminausgabe($query->param("id"),$query->param("datum"));
   
      &ausgabeende;
      exit;
   }
}
&kalender(@start,@ende);
&ausgabeende;

