From b76d883fbede75f3f45f1273375e2f4b0b8d0f5a Mon Sep 17 00:00:00 2001
From: Moirtz Wagner
Date: Thu, 17 Sep 2026 11:18:29 +0200
Subject: [PATCH] Rechnungen: Betraege mit Tausenderpunkt, XSS in Templates und
Suche
- formularZahl(): steht ein Komma im Betrag, sind Punkte Tausendertrenner
("1.234,50" -> 1234.50, vorher 1.23); ohne Komma bleibt der Punkt
Dezimaltrenner wie bei der Artikel-Autovervollstaendigung ("12.50").
- Rechnungs-Templates (addrechnung, mailrechnung, changeadr, copyrech,
umschlagshow, rechshow) geben alle Daten mit |escape aus; Werte aus der
URL (id, type, newtype) als int.
- Rechnungssuche: Artikelnamen werden escaped statt als HTML ausgegeben
(Trennung per Zeilenumbruch in SQL, artikelListeHtml() in PHP).
- Suchbegriffe kommen per encodeURIComponent als UTF-8, utf8_encode()
entfaellt; vorher gingen Zeichen ausserhalb von Latin-1 verloren.
Co-Authored-By: Claude Opus 5
---
ajax/searchkdnrech.php | 9 +-
ajax/searchrech.php | 9 +-
incs/listfuncs.php | 14 +-
incs/rechnung.php | 11 +-
js/ajaxlists.js | 4 +-
sites/rechnungadd.php | 10 +-
templates/addrechnung.tpl | 256 ++++++++++++++++++-------------------
templates/changeadr.tpl | 6 +-
templates/copyrech.tpl | 6 +-
templates/mailrechnung.tpl | 64 +++++-----
templates/rechshow.tpl | 4 +-
templates/umschlagshow.tpl | 32 ++---
12 files changed, 219 insertions(+), 206 deletions(-)
diff --git a/ajax/searchkdnrech.php b/ajax/searchkdnrech.php
index d976098..64b5897 100644
--- a/ajax/searchkdnrech.php
+++ b/ajax/searchkdnrech.php
@@ -16,7 +16,8 @@ if(!isset($err))
if(!isset($_GET["link"])){
$_GET["link"] ="";
}
- $fulltag = utf8_encode($_GET["search"]);
+ // kommt per encodeURIComponent bereits als UTF-8
+ $fulltag = isset($_GET["search"]) && is_string($_GET["search"]) ? $_GET["search"] : "";
$src = explode(" ",$fulltag);
$combiner = $_GET["link"];
if($combiner != "AND" && $combiner != "OR")
@@ -87,14 +88,14 @@ if(!isset($err))
if($res["storno"] == 1){
$listlines[] = array("".$res["drechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
$actions
);
}
else{
$listlines[] = array("".$res["drechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
$actions
);
}
@@ -151,7 +152,7 @@ if(!isset($err))
{
$speciallines[] = array("".$res["rechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
"");
}
$headings = array("Nummer","Datum","Artikel","Aktion");
diff --git a/ajax/searchrech.php b/ajax/searchrech.php
index 91abca1..5b8b938 100644
--- a/ajax/searchrech.php
+++ b/ajax/searchrech.php
@@ -22,7 +22,8 @@ if(!isset($err))
if(!isset($_GET["kdnid"])){
$_GET["kdnid"]="";
}
- $fulltag = utf8_encode($_GET["search"]);
+ // kommt per encodeURIComponent bereits als UTF-8
+ $fulltag = isset($_GET["search"]) && is_string($_GET["search"]) ? $_GET["search"] : "";
$src = explode(" ",$fulltag);
$combiner = $_GET["link"];
if($combiner != "AND" && $combiner != "OR")
@@ -82,14 +83,14 @@ if(!isset($err))
if($res["storno"] == 1){
$listlines[] = array("".$res["drechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
$actions
);
}
else{
$listlines[] = array("".$res["drechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
$actions
);
}
@@ -142,7 +143,7 @@ if(!isset($err))
{
$speciallines[] = array("".$res["rechnr"]."",
$res["date"],
- $res["artikel"],
+ artikelListeHtml($res["artikel"]),
"");
}
$headings = array("Nummer","Datum","Artikel","Aktion");
diff --git a/incs/listfuncs.php b/incs/listfuncs.php
index 7cc7ce5..30d2fe7 100644
--- a/incs/listfuncs.php
+++ b/incs/listfuncs.php
@@ -195,7 +195,7 @@ function createKdnRechQry($page,$pagesize,$src,$combiner,$id,$typ,$sks=0)
$query = "SELECT rechnung.$docnr AS rechnr,
rechnung.id,
DATE_FORMAT(rechnung.datetime, '%d.%m.%Y') AS date,
- GROUP_CONCAT(CONCAT(artikel.bezeichn, ' (', artikel_rechn.wanr, ')') SEPARATOR '
') AS artikel,
+ GROUP_CONCAT(CONCAT(artikel.bezeichn, ' (', artikel_rechn.wanr, ')') SEPARATOR '\n') AS artikel,
adresse_id,
storno,
rechnung.typ_id
@@ -216,7 +216,7 @@ function createKdnRechQry($page,$pagesize,$src,$combiner,$id,$typ,$sks=0)
$query = "SELECT rechnung.$docnr AS rechnr,
rechnung.id,
DATE_FORMAT(rechnung.datetime, '%d.%m.%Y') AS date,
- GROUP_CONCAT(CONCAT(artikelsks.bezeichn1, ' ', artikelsks.bezeichn2) SEPARATOR '
') AS artikel,
+ GROUP_CONCAT(CONCAT(artikelsks.bezeichn1, ' ', artikelsks.bezeichn2) SEPARATOR '\n') AS artikel,
adresse_id,
rechnung.typ_id
FROM rechnung
@@ -304,7 +304,7 @@ function createRechQry($page,$pagesize,$src,$combiner,$sks=0)
rechnung.$docnr AS rechnr,
rechnung.id,
DATE_FORMAT(rechnung.datetime, '%d.%m.%Y') AS date,
- GROUP_CONCAT(CONCAT(artikel.bezeichn, ' (', artikel_rechn.wanr, ')') SEPARATOR '
') AS artikel,
+ GROUP_CONCAT(CONCAT(artikel.bezeichn, ' (', artikel_rechn.wanr, ')') SEPARATOR '\n') AS artikel,
adresse_id,
storno,
rechnung.typ_id
@@ -328,7 +328,7 @@ function createRechQry($page,$pagesize,$src,$combiner,$sks=0)
rechnung.$docnr AS rechnr,
rechnung.id,
DATE_FORMAT(rechnung.datetime, '%d.%m.%Y') AS date,
- GROUP_CONCAT(CONCAT(artikelsks.bezeichn1, ' ', artikelsks.bezeichn2) SEPARATOR '
') AS artikel,
+ GROUP_CONCAT(CONCAT(artikelsks.bezeichn1, ' ', artikelsks.bezeichn2) SEPARATOR '\n') AS artikel,
adresse_id,
storno = 0,
rechnung.typ_id
@@ -461,6 +461,12 @@ function createMsgQry($page,$pagesize,$src,$combiner,$user)
return $ret;
}
+/* Artikelliste aus createRechQry()/createKdnRechQry() als escaptes HTML, eine Zeile je Artikel */
+function artikelListeHtml($artikel)
+{
+ return implode("
", array_map("htmlspecialchars", explode("\n", (string)$artikel)));
+}
+
function displayPages($pagesize,$currpage,$numentries,$refreshfunc,$ad_params = "")
{
echo "Seite: ";
diff --git a/incs/rechnung.php b/incs/rechnung.php
index 4a32ea9..9dcebc8 100644
--- a/incs/rechnung.php
+++ b/incs/rechnung.php
@@ -12,12 +12,17 @@ function formularText($name)
}
/*
- * Zahl aus $_POST, Komma als Dezimaltrenner. Leere oder ungültige Eingaben
- * werden 0 - so hat sie der frühere, nicht strikte Modus gespeichert.
+ * 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.
*/
function formularZahl($name)
{
- $wert = str_replace(",", ".", formularText($name));
+ $wert = str_replace(" ", "", formularText($name));
+ if(str_contains($wert, ","))
+ $wert = str_replace(array(".", ","), array("", "."), $wert);
return is_numeric($wert) ? $wert : "0";
}
diff --git a/js/ajaxlists.js b/js/ajaxlists.js
index c6bef86..cc5826a 100644
--- a/js/ajaxlists.js
+++ b/js/ajaxlists.js
@@ -146,7 +146,7 @@ function ajax_searchkdnrech(page,skspage,typ,kdnid)
search_in_progress = 1;
document.getElementById("rechlist-"+typ).innerHTML = "
";
//document.getElementById("kdnsrc_src").disabled = true;
- search = escape(document.getElementById("src_rech-"+typ).value);
+ search = encodeURIComponent(document.getElementById("src_rech-"+typ).value);
var url = "ajax/searchkdnrech.php?page=" + page + "&skspage=" + skspage + "&search=" + search+"&typ=" + typ + "&kdnid=" + kdnid;
@@ -200,7 +200,7 @@ function ajax_searchrech(page,skspage)
search_in_progress = 1;
document.getElementById("rechlist").innerHTML = "
";
//document.getElementById("kdnsrc_src").disabled = true;
- search = escape(document.getElementById("src_rech").value);
+ search = encodeURIComponent(document.getElementById("src_rech").value);
var url = "ajax/searchrech.php?page=" + page + "&skspage=" + skspage + "&search=" + search;
diff --git a/sites/rechnungadd.php b/sites/rechnungadd.php
index 58bcc2b..83f03f1 100644
--- a/sites/rechnungadd.php
+++ b/sites/rechnungadd.php
@@ -17,7 +17,7 @@ elseif($_GET["changeadr"] == 1 && $_GET["id"])
if(!$_GET["adrid"])
{
$smarty->assign("felder",array("all"=>"Name, Adresse, Kd.Nr.","kdnr"=>"Kundennummer","name"=>"Name und Firma","str"=>"Straße","plz"=>"PLZ","ort"=>"Ort","tel"=>"Tel","kont"=>"Kontakt"));
- $smarty->assign("rechid",$_GET["id"]);
+ $smarty->assign("rechid",(int)$_GET["id"]);
$smarty->display("changeadr.tpl");
}
else
@@ -32,7 +32,7 @@ elseif($_GET["copy"] == 1 && $_GET["id"])
if(!$_GET["adrid"])
{
$smarty->assign("felder",array("all"=>"Name, Adresse, Kd.Nr.","kdnr"=>"Kundennummer","name"=>"Name und Firma","str"=>"Straße","plz"=>"PLZ","ort"=>"Ort","tel"=>"Tel","kont"=>"Kontakt"));
- $smarty->assign("rechid",$_GET["id"]);
+ $smarty->assign("rechid",(int)$_GET["id"]);
$smarty->display("copyrech.tpl");
}
else
@@ -141,7 +141,7 @@ else
}
else
{
- $smarty->assign("loadrech",$_GET["id"]);
+ $smarty->assign("loadrech",(int)$_GET["id"]);
$rechnung=makerechnungsarray($dbconn, $_GET["id"], 0);
$kommission=makeadressarray($dbconn, $rechnung["kommission"]);
$smarty->assign("rechnung",$rechnung);
@@ -156,8 +156,8 @@ else
$smarty->assign("artikel",makeartikelarray($dbconn, $_GET["draft"], 1));
}
- $smarty->assign("type",$_GET["type"]);
- $smarty->assign("newtype",$_GET["newtype"]);
+ $smarty->assign("type",(int)$_GET["type"]);
+ $smarty->assign("newtype",(int)$_GET["newtype"]);
$kdnres=makeadressarray($dbconn, $_GET["adressid"]);
diff --git a/templates/addrechnung.tpl b/templates/addrechnung.tpl
index 8b84bfa..11a24b0 100644
--- a/templates/addrechnung.tpl
+++ b/templates/addrechnung.tpl
@@ -23,72 +23,72 @@
{elseif $type == 6}
{$typename="Mahnung"}
{/if}
-{$typename} {$headstr}:
-
{/if}
{if $type == 1}
{if $smarty.session.firma == "Wagner Markisen"}
-
+
{else}
-
+
{/if}
{/if}
{if $type == 1}
{else}
@@ -264,30 +264,30 @@
{/if}
{if $type == 3}
-
-
-
+
+
+
{else}
-
-
-
+
+
+
{/if}
{if $art.art.pagebreak}
-
-
+
+
{else}
-
-
+
+
{/if}
-
- |
-
-
- {html_options values=$einhids output=$einhs selected="{$art.art.einheit_id}"}
+
+
+ {html_options values=$einhids output=$einhs selected="{$art.art.einheit_id|escape}"}
-
+
- %
-
+ %
+
|
{else}
+
diff --git a/templates/copyrech.tpl b/templates/copyrech.tpl
index b320852..1f1fea6 100644
--- a/templates/copyrech.tpl
+++ b/templates/copyrech.tpl
@@ -3,8 +3,8 @@
-
+
diff --git a/templates/mailrechnung.tpl b/templates/mailrechnung.tpl
index 3cc7275..5dba58f 100644
--- a/templates/mailrechnung.tpl
+++ b/templates/mailrechnung.tpl
@@ -15,11 +15,11 @@
{elseif $type == 5}
{$typename="Brief"}
{/if}
-{$typename} {$headstr}:
-