Termine auf Prepared Statements umgebaut

Kalender, Terminliste, Terminformular und Terminzettel laufen ueber
db_abfrage() mit Platzhaltern; das Anlegen einer mehrtaegigen Terminreihe
liegt in einer Transaktion. Die Logik steckt jetzt in incs/termin.php,
sites/termin*.php rufen sie nur noch auf.

Dabei behoben:
- SQL-Injektion ueber die Suchbegriffe der Terminliste, ueber die
  Mehrfachauswahl (Ankreuzfelder del<N>/erl<N> gingen roh in DELETE bzw.
  UPDATE), ueber die Wiedervorlage-Tage (INTERVAL $folgedays DAY) und ueber
  ?action=terminshow&id=... in maketerminarray(), maketerminadresse(),
  maketelnrn() und makegooglestring()
- gespeichertes XSS: Beschreibung, Notiz, Termintyp, Ort, Kundenname und
  Mitarbeiterfarbe im Kalender, in der Terminliste und im Formular
- "or $err=error(...)" stand innerhalb des Abfrage-Strings, dadurch wurden
  die Nebenzeilen einer Terminreihe beim Loeschen nie entfernt
- die Abfrage zum Folgetermin las eine Spalte typ_id, die es in termin nicht
  gibt; Typ und Wiedervorlage fehlten deshalb beim Bearbeiten
- ein Folgetermin wurde mit termtime='' und termdauer='' angelegt, ein
  Termin ohne Folgetermin mit followed_by='' - im strikten Modus Fehler
- ein Termin ohne Datum landete auf dem 01.01.1970 und gab dabei
  "NICHTTERMINIERT!!" mitten in die Seite aus
- die Ueberschneidungspruefung verglich ab dem zweiten Tag gegen das Ende
  des ersten Tages
- eine unbekannte Registerkarte der Terminliste ergab ein leeres WHERE und
  damit einen SQL-Fehler; jetzt gilt die Standardansicht
- terminshow.php pruefte den Typ mit = statt ==
- der Kalender haengt nicht mehr an der Locale de_DE (strftime)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-22 00:04:38 +02:00
co-authored by Claude Opus 5
parent 3dfbf1c9c7
commit 490c4f12a4
12 changed files with 986 additions and 950 deletions
+14 -137
View File
@@ -1,148 +1,25 @@
<?php
require_once("incs/users.php");
$_SESSION["camefrom"] = "termin&show=".$_GET["show"]."&page=".$_GET["page"];
require_once "incs/termin.php";
require_once "incs/users.php";
if($_GET["show"] == "list")
$seite = parameterGanzzahl("page");
$_SESSION["camefrom"] = "termin&show=".(isset($_GET["show"]) && $_GET["show"] == "list" ? "list" : "")."&page=".$seite;
if(isset($_GET["show"]) && $_GET["show"] == "list")
{
$smarty->assign("heading","Terminliste");
if($_GET["tabs"])
$smarty->assign("tabs",$_GET["tabs"]);
else
$smarty->assign("tabs",$_SESSION["termtyp"]);
$smarty->assign("heading", "Terminliste");
$smarty->assign("tabs", parameterGanzzahl("tabs") ?: ($_SESSION["termtyp"] ?? 1));
$smarty->display("heading.tpl");
$smarty->display("termlist.tpl");
}
else
else
{
$smarty->assign("heading","Termine");
$smarty->assign("heading", "Termine");
$smarty->display("heading.tpl");
//$colors = array("#f00","#0c0","#ff0","#90c","#0bb","#066","#09f","#f60","#00f","#f09");
//$weather = GetWeather();
//$smarty->assign("weather",$weather);
$start = $_GET["page"]*8 - 1;
$end = $_GET["page"]*8 + 7;
for($i=$start; $i<$end; $i++)
{
$qry = mysqli_query($dbconn,"SELECT user.vname,user.nname, user.color,
case MAX(zeiten.gehen)
when MAX(zeiten.kommen) then 0
else 1 end AS complete
FROM user
LEFT JOIN zeiten ON user.id = zeiten.ma_id
WHERE DATE_FORMAT(kommen,'%Y%m%d') = '".date("Ymd",strtotime("+".$i." days"))."'
GROUP BY user.id ORDER BY user.nname ASC") or $err=error("fehler beim ermitteln der anwesenden Mitarbeiter<br />".mysqli_error($dbconn));
$ma_check=array();
while($res=mysqli_fetch_assoc($qry))
{
$ma_check[] = $res;
}
$qry = mysqli_query($dbconn,"SELECT termin.id,termtyp.typ, termin.head, termtime, termdauer, user, user2, user3, user4, done, partner_id, termin.id, main_id, str, ort, ortsteil, plz, hnr, adresse.vname as vname, adresse.nname as nname,
user.vname as uservname, user.nname as usernname,
user2.vname as uservname2, user2.nname as usernname2,
user3.vname as uservname3, user3.nname as usernname3,
user4.vname as uservname4, user4.nname as usernname4,
firma, vname2, nname2
FROM termin
LEFT JOIN termtyp ON termin.typ = termtyp.id
LEFT JOIN adresse ON termin.adresse_id = adresse.id
LEFT JOIN partner ON adresse.partner_id = partner.id
LEFT JOIN strasse ON adresse.str_id = strasse.id
LEFT JOIN ort ON strasse.ort_id = ort.id
LEFT JOIN user ON termin.user = user.id
LEFT JOIN user AS user2 ON termin.user2 = user2.id
LEFT JOIN user AS user3 ON termin.user3 = user3.id
LEFT JOIN user AS user4 ON termin.user4 = user4.id
WHERE DATE_FORMAT(termtime,'%Y%m%d') = '".date("Ymd",strtotime("+".$i." days"))."' AND termdauer > '12:00:00'
ORDER BY termtime ASC") or $err=error("fehler beim ermitteln der termine<br />".mysqli_error($dbconn));
$fulldaytermine=array();
while($res=mysqli_fetch_assoc($qry))
{
$fulldaytermine[] = $res;
}
$termine=array();
if($_SESSION["firma"] == "Ingenieurbüro Wagner"){
$qry = mysqli_query($dbconn,"SELECT work.id, project.id AS projectid, work.bezeichn AS head, work.rechn AS done, project.name AS projectname, work.datetime AS termtime, work.std AS termdauer, project.changeuser AS user, project.partner_id,
adresse.vname as vname, adresse.nname as nname, adresse.firma AS firma
FROM work
LEFT JOIN project ON work.project_id = project.id
LEFT JOIN partner ON project.partner_id = partner.id
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN user ON work.changeuser = user.id
WHERE adresse.typ_id = 1 AND DATE_FORMAT(work.datetime,'%Y%m%d') = '".date("Ymd",strtotime("+".$i." days"))."'
ORDER BY work.datetime ASC") or $err=error("fehler beim ermitteln der termine<br />".mysqli_error($dbconn));
while($res=mysqli_fetch_assoc($qry))
{
$termine[] = $res;
}
}
$qry = mysqli_query($dbconn,"SELECT termin.id,termtyp.typ, termin.head, termtime, termdauer, user, user2, user3, user4, done, partner_id, termin.id, main_id, str, ort, ortsteil, plz, hnr, adresse.vname as vname, adresse.nname as nname,
user.vname as uservname, user.nname as usernname,
user2.vname as uservname2, user2.nname as usernname2,
user3.vname as uservname3, user3.nname as usernname3,
user4.vname as uservname4, user4.nname as usernname4,
firma, vname2, nname2
FROM termin
LEFT JOIN termtyp ON termin.typ = termtyp.id
LEFT JOIN adresse ON termin.adresse_id = adresse.id
LEFT JOIN partner ON adresse.partner_id = partner.id
LEFT JOIN strasse ON adresse.str_id = strasse.id
LEFT JOIN ort ON strasse.ort_id = ort.id
LEFT JOIN user ON termin.user = user.id
LEFT JOIN user AS user2 ON termin.user2 = user2.id
LEFT JOIN user AS user3 ON termin.user3 = user3.id
LEFT JOIN user AS user4 ON termin.user4 = user4.id
WHERE DATE_FORMAT(termtime,'%Y%m%d') = '".date("Ymd",strtotime("+".$i." days"))."' AND termdauer < '12:00:00'
ORDER BY termtime ASC") or $err=error("fehler beim ermitteln der termine<br />".mysqli_error($dbconn));
while($res=mysqli_fetch_assoc($qry))
{
$termine[] = $res;
}
$feiertag = feiertag_bayern(idate("d",strtotime("+".$i." days")),idate("m",strtotime("+".$i." days")),idate("Y",strtotime("+".$i." days")));
if($feiertag){
$weekdays[]=array( "weekday"=>date("d.m.Y",strtotime("+".$i." days"))."<br/>",
"date"=>strftime("%Y%m%d",strtotime("+".$i." days")),
"termine"=>$termine,
"fulldaytermine"=>$fulldaytermine,
"numfulldaytermine" => 0,
"ma_check"=>$ma_check,
"feiertag" => $feiertag
);
}
else{
$weekdays[]=array( "weekday"=>strftime("%A",strtotime("+".$i." days"))."<br/>".date("d.m.Y",strtotime("+".$i." days")),
"date"=>strftime("%Y%m%d",strtotime("+".$i." days")),
"termine"=>$termine,
"fulldaytermine"=>$fulldaytermine,
"numfulldaytermine" => 0,
"ma_check"=>$ma_check,
"feiertag" => ""
);
}
}
$smarty->assign("page",$_GET["page"]);
$smarty->assign("weekdays",$weekdays);
$qry=mysqli_query($dbconn,"SELECT id, vname, nname, color FROM user WHERE blocked = 0 AND nick != 'ALL'");
while($res=mysqli_fetch_assoc($qry))
{
//$res["color"] = $colors[$res["id"]];
$res["openvacation"] = urlaub_remaining($dbconn, $res["id"]);
$users[$res["id"]] = $res;
}
$smarty->assign("users",$users);
$smarty->assign("page", $seite);
$smarty->assign("weekdays", kalenderTage($dbconn, $seite));
$smarty->assign("users", kalenderBenutzer($dbconn));
$smarty->display("calendar.tpl");
}
?>