Kunden und Adressen auf Prepared Statements umgebaut

incs/saveNchange.php neu geschrieben: Adressen, Telefonnummern, Kontakte,
Notizen und Konten laufen ueber db_abfrage() mit Platzhaltern, mehrschrittiges
Speichern in einer Transaktion. Weil sich die Speicherfunktionen gegenseitig
aufrufen, klammern beginneSpeichern()/beendeSpeichern() die Verschachtelung;
incs/rechnung.php nutzt sie ebenfalls.

Kunden- und Lieferantenseiten waren zwei fast gleiche Kopien und teilen sich
jetzt partnerAddSeite(), partnerChangeSeite() und partnerShowDaten().

Dabei behoben:
- SQL-Injektion ueber die Suchbegriffe der Kunden-, Lieferanten-, Adress-,
  Kommissions- und Projektsuche sowie ueber die Artikel-Autovervollstaendigung
- gespeichertes XSS: Notizen (nl2br escapt nicht), Bankname, Dokumenttyp,
  Namen und Adressen in allen Trefferlisten
- sites/liefershow.php war unter PHP 8 ein Fatal ($kdnres.id)
- "Telefonnummer loeschen" im Kundenbereich lief in einen Fatal, die Nummern
  einer geloeschten Adresse blieben stehen (Spalte hiess adress_id statt
  adresse_id, mysql_fetch_assoc gibt es nicht mehr)
- Geburtstag ohne Jahr wurde im Formular verschluckt, die IBAN kam beim
  Bearbeiten aus $_GET statt aus dem Konto
- die Versionskette eines Kunden brach nach einem Schritt ab
- Kommissionsadressen speicherten die Ortsangabe der Adresse statt der des
  Telefonformulars und einen Adresstyp als Telefontyp
- Blaettern in den Trefferlisten: ohne ORDER BY konnte dieselbe Zeile zweimal
  oder gar nicht erscheinen; ajax_searchadress() bekam die Seite nicht
- Hauptadresse laesst sich nicht mehr loeschen, Kundendaten nicht mehr ueber
  die Lieferantenseite (und umgekehrt)
- ajax/auto/* baute JSON von Hand zusammen, ein Anfuehrungszeichen im Ort
  machte die Liste unbrauchbar

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 19:47:01 +02:00
co-authored by Claude Opus 5
parent 3f7d070d7f
commit 3dfbf1c9c7
40 changed files with 1706 additions and 2194 deletions
+13 -48
View File
@@ -1,36 +1,10 @@
<?php
require_once("saveNchange.php");
/* ---------------------------------------------------------------------
* Hilfsfunktionen für Formularwerte
* ------------------------------------------------------------------ */
/* Getrimmter Text aus $_POST, fehlend oder kein Text ergibt "" */
function formularText($name)
{
return isset($_POST[$name]) && is_string($_POST[$name]) ? trim($_POST[$name]) : "";
}
/*
* Zahl aus $_POST in deutscher Schreibweise. Steht ein Komma darin, ist es
* der Dezimaltrenner und Punkte sind Tausendertrenner ("1.234,50"). Ohne
* Komma gilt ein Punkt als Dezimaltrenner ("12.50", so liefert ihn die
* Artikel-Autovervollständigung). Leere oder ungültige Eingaben werden 0 -
* so hat sie der frühere, nicht strikte Modus gespeichert.
* Rechnungen, Angebote, Lieferscheine und Briefe. Die Hilfsfunktionen für
* Formularwerte (formularText(), formularZahl(), formularGanzzahl()) stehen
* in saveNchange.php, weil beide Module sie brauchen.
*/
function formularZahl($name)
{
$wert = str_replace(" ", "", formularText($name));
if(str_contains($wert, ","))
$wert = str_replace(array(".", ","), array("", "."), $wert);
return is_numeric($wert) ? $wert : "0";
}
/* Ganzzahl aus $_POST, gerundet wie MariaDB beim Speichern */
function formularGanzzahl($name)
{
return (int)round((float)formularZahl($name));
}
require_once("saveNchange.php");
/* Die zwölf Ankreuzfelder für den Adressblock als 0/1-Zeichenkette */
function formularAdressfelder()
@@ -423,7 +397,7 @@ function saveRechnung($dbconn,$update)
// Alles oder nichts: bricht ein Schritt ab, bleibt keine halbe Rechnung
// zurück. Der Entwurf in tmp_rechnung bleibt dann erhalten.
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
$err = 0;
if($update)
@@ -536,13 +510,9 @@ function saveRechnung($dbconn,$update)
if(!$err)
$err = loescheEntwurf($dbconn, $type);
if(!$err)
beendeSpeichern($dbconn, $err);
if($err)
{
mysqli_commit($dbconn);
}
else
{
mysqli_rollback($dbconn);
$err = error("Es ist ein Fehler beim Speichern aufgetreten, <br />
Ihre Rechnung ist aber noch vorhanden, <br />
Bitte gehen Sie <a href='?action=rechnungadd&type=$type'>zurück zum Rechnungsformular</a> <br />
@@ -598,7 +568,7 @@ function saveTmpRechnung($dbconn, $nurAktive)
);
$set = implode(", ", array_map(function($spalte) { return "`$spalte` = ?"; }, array_keys($felder)));
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
$err = 0;
$progressid = db_wert($dbconn, "SELECT id FROM tmp_rechnung WHERE user_id = ? AND typ_id = ? ORDER BY id LIMIT 1", array($_SESSION["user"], $type));
if($progressid === false)
@@ -649,17 +619,14 @@ function saveTmpRechnung($dbconn, $nurAktive)
$i++;
}
if($err)
mysqli_rollback($dbconn);
else
mysqli_commit($dbconn);
beendeSpeichern($dbconn, $err);
return array($progressid, $err);
}
function delRechnung($dbconn,$id)
{
$err = 0;
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
db_abfrage($dbconn, "DELETE FROM artikel_rechn WHERE rech_id = ?", array($id)) or $err = error("Fehler beim löschen der Artikel-Rechnung Beziehung <br />".mysqli_error($dbconn));
if(!$err)
db_abfrage($dbconn, "DELETE FROM artikel_eigensch WHERE rech_id = ?", array($id)) or $err = error("Fehler beim löschen der Artikel-Eigenschaften Beziehung <br />".mysqli_error($dbconn));
@@ -667,8 +634,7 @@ function delRechnung($dbconn,$id)
db_abfrage($dbconn, "DELETE FROM rechnung WHERE id = ? LIMIT 1", array($id)) or $err = error("Fehler beim löschen der Rechnung <br />".mysqli_error($dbconn));
if(!$err)
$err = saveLog($dbconn, db_sql_text($dbconn, "DELETE FROM rechnung WHERE id = ? LIMIT 1", array($id))." [rechnung DEL]", "", "löschen");
$err ? mysqli_rollback($dbconn) : mysqli_commit($dbconn);
return $err;
return beendeSpeichern($dbconn, $err);
}
/* Storno setzen (1) oder zurücknehmen (0) */
@@ -717,7 +683,7 @@ function copyRech($dbconn,$id,$adrid)
if($partnerid === false)
return error("Fehler beim ermitteln der Adressdaten <br />".mysqli_error($dbconn));
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
list($rechnr, $err) = neueRechnungsnummer($dbconn, $res["typ_id"]);
if(!$err)
{
@@ -746,8 +712,7 @@ function copyRech($dbconn,$id,$adrid)
if(!$err)
$err = saveLog($dbconn, db_sql_text($dbconn, $sql, array($rechid, $id))." [rechnung copy]", "DELETE FROM artikel_eigensch WHERE rech_id = $rechid", "anlegen");
}
$err ? mysqli_rollback($dbconn) : mysqli_commit($dbconn);
return $err;
return beendeSpeichern($dbconn, $err);
}
function calculateRechnungsSum($dbconn, $rechid, $inclmwst)