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:
@@ -98,12 +98,20 @@ Regeln für den Umbau:
|
||||
- **Suchabfragen** (`create*Qry()` in `incs/listfuncs.php`) liefern `array("all", "limited", "params")`. Aufrufer nutzen `db_abfrage($dbconn, $q["limited"], $q["params"])` und `zaehleTreffer()`. Die Suchbegriffe sind Platzhalterwerte, `%` und `_` darin bleiben absichtlich Jokerzeichen — so ist die Suche dokumentiert. In der Autovervollständigung (`ajax/auto/`) werden sie dagegen über `db_like_praefix()` entwertet.
|
||||
- **Werte aus der Datenbank sind kein HTML.** `GROUP_CONCAT` trennt mit einem Zeilenumbruch; zusammengebaut und escaped wird erst in `zeilenHtml()` bzw. `makenameline()`/`makeadressline()`/`maketelline()`.
|
||||
|
||||
Umgebaut: Login/Passkeys, Benutzereinstellungen, Änderungsprotokoll, Rechnungsmodul (`incs/rechnung.php`, `sites/rechnungadd.php`, `sites/umschlagshow.php`, `ajax/autosave.php`, `ajax/preview.php`, Rechnungssuche), Kunden und Lieferanten (`incs/saveNchange.php` samt `sites/kunden*.php`, `sites/liefer*.php`, Kunden-, Lieferanten-, Adress- und Kommissionssuche, `ajax/auto/`). Offen: Termine, Projekte, Zeiten, Benutzerverwaltung, `incs/makepdf.php`, `update/`.
|
||||
Umgebaut: Login/Passkeys, Benutzereinstellungen, Änderungsprotokoll, Rechnungsmodul (`incs/rechnung.php`, `sites/rechnungadd.php`, `sites/umschlagshow.php`, `ajax/autosave.php`, `ajax/preview.php`, Rechnungssuche), Kunden und Lieferanten (`incs/saveNchange.php` samt `sites/kunden*.php`, `sites/liefer*.php`, Kunden-, Lieferanten-, Adress- und Kommissionssuche, `ajax/auto/`), Termine (`incs/termin.php` samt `sites/termin*.php`, Terminliste, Terminzettel). Offen: Projekte, Zeiten, Benutzerverwaltung, der Rest von `incs/makepdf.php`, `update/`.
|
||||
|
||||
Prozedurales `mysqli`. `$dbconn` wird zusätzlich in `$_SESSION["dbconn"]` abgelegt, damit `incs/mysql_ecape_wrapper.php` eine globale Funktion `mysql_escape_string()` als Shim über diese Verbindung bereitstellen kann — ein Überbleibsel der `mysql_*`-Ära, das in altem Code noch aufgerufen wird.
|
||||
|
||||
SQL wird durchgehend per String-Verkettung gebaut. Escaping ist Handarbeit über `mysqli_real_escape_string($dbconn, …)` und muss bei jeder Änderung mitgedacht werden.
|
||||
|
||||
## Termine
|
||||
|
||||
Ein Termin über mehrere Tage ist eine **Reihe einzelner Zeilen** in `termin`, die alle dieselbe `main_id` tragen — die id der ersten Zeile. Der Kalender zeigt die Zeilen einzeln, die Terminliste fasst sie über `main_id` zusammen. Wird ein Termin auf mehrere Tage verlängert, wird die alte Reihe verworfen und neu angelegt; er bekommt dabei eine neue id.
|
||||
|
||||
Urlaub und Krankheit sind Termine ohne Kundenadresse. Ihre Typ-ids sind fest verdrahtet — `TERMTYP_URLAUB` = 0 und `TERMTYP_KRANKHEIT` = 5 in `incs/termin.php`; `incs/users.php` rechnet den Urlaubsanspruch über `typ = 0` aus und `templates/addtermin.tpl` blendet danach die Felder um. `termtyp` muss also eine Zeile mit der id 0 enthalten; beim Kopieren einer Datenbank braucht es dafür `NO_AUTO_VALUE_ON_ZERO`, sonst macht MariaDB eine 1 daraus.
|
||||
|
||||
Ganztägige Termine haben die Dauer `24:00:00` — die Terminliste unterscheidet die Registerkarten daran.
|
||||
|
||||
## Fallstricke
|
||||
|
||||
- **`smarty/` enthält Smarty 4.5.6** — der schlichte Verzeichnisname sagt nichts über die Version.
|
||||
@@ -111,6 +119,7 @@ SQL wird durchgehend per String-Verkettung gebaut. Escaping ist Handarbeit über
|
||||
- **PDF-Schriften nur über `PDF_SCHRIFT_SERIF` / `PDF_SCHRIFT_SANS`** (oben in `incs/makepdf.php`, FreeSerif/FreeSans). Die eingebauten PDF-Schriften Times/Helvetica können nur westeuropäische Zeichen; aus ř, ł, č würde ein „?“.
|
||||
- **`incs/font/` gehört zu pChart, nicht zu TCPDF.** Die TTFs dort werden von `stats.php` für die Diagramme geladen; TCPDF bringt seine Schriften in `incs/tcpdf/fonts/` selbst mit.
|
||||
- **`index.php` setzt `error_reporting(E_ERROR | E_PARSE)`.** Warnungen und Notices sind unterdrückt, und der Code verlässt sich darauf — nicht ohne Not hochdrehen, sonst überflutet es die Ausgabe.
|
||||
- **`templates/calendar_month.tpl` ist tot.** Kein Code bindet es ein, und unter PHP 8 läuft es in einen Fehler (`{$prevtermin = ""}` und danach `{$prevtermin.termtime}`).
|
||||
- **`templates_c/`, `ajax/templates_c/` und `temp/` müssen für den Webserver schreibbar sein.** Sie sind git-ignoriert und nur über `.gitkeep` im Repo vorhanden.
|
||||
- **`uploads_*/{notes,signs}` enthalten personenbezogene Kundendaten** (Rechnungen, Scans, Unterschriften) und sind bewusst git-ignoriert. Nie committen.
|
||||
- Zeilenenden werden über `.gitattributes` auf LF normalisiert.
|
||||
|
||||
Reference in New Issue
Block a user