Commit Graph
7 Commits
Author SHA1 Message Date
adminandClaude Opus 5 2779f505df Termine: mehrtaegige Termine behalten beim Aendern ihre id
Bisher wurde eine mehrtaegige Terminreihe beim Speichern komplett geloescht
und neu angelegt, der Termin bekam also jedes Mal eine neue id. Jetzt bleibt
der Hauptsatz stehen und wird aktualisiert; nur die Folgetage werden neu
angelegt. Damit bleiben Verweise auf die id gueltig (Drucken, Links,
Aenderungsprotokoll), und Anlegen und Aendern laufen ueber denselben Weg.

terminHauptsatz() loest jede Zeilen-id auf ihre Reihe auf, so dass auch der
Einstieg ueber eine Nebenzeile oder ueber Altdaten ohne main_id funktioniert;
loescheTerminreihe() und setzeTerminErledigt() nutzen das ebenfalls.

templates/calendar_month.tpl entfernt: kein Code band die Monatsansicht ein,
und unter PHP 8 lief sie in einen Fehler.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 08:05:27 +02:00
adminandClaude Opus 5 490c4f12a4 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>
2026-09-22 00:04:38 +02:00
adminandClaude Opus 5 3dfbf1c9c7 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>
2026-09-21 19:47:01 +02:00
adminandClaude Opus 5 8fe43d6802 Rechnungen: Anrede beim Bearbeiten, lokale Testumgebung, BOMs
Beim Test der Oberflaeche im Browser gefunden:

- addrechnung.tpl fragte die gespeicherte Anrede als $rechnung.anr1 ab
  (die Daten heissen anrede1) und gab sie ohne Klammern aus. Beim
  Bearbeiten von Angeboten/Briefen erschien deshalb immer die
  Standard-Anrede, eine geaenderte ging beim erneuten Speichern verloren.
- |escape innerhalb von {if}-Bedingungen wieder entfernt (dort ohne
  Wirkung, gehoert nicht dorthin).
- UTF-8-BOM aus sechs Dateien entfernt; makepdf.php gab es auf jeder
  Rechnungsseite vor dem HTML aus.
- makeImageFromPDF() loeschte bei der Aufraeumrunde auch .gitkeep;
  Pfade fuer convert per escapeshellarg().
- constants.php: Instanzname auch unter Windows (getcwd() mit
  Backslashes) korrekt; KV_CONFIG_PATH als Config-Pfad fuer lokale Tests.

Im Browser getestet (lokaler PHP-Webserver, migrierte Testdatenbank):
Login mit Sonderzeichen-Passwort, Entwurf automatisch speichern und
laden, Rechnung mit Umlauten/Anfuehrungszeichen/HTML im Artikelnamen und
Komma-Betraegen speichern, Anzeige als PDF (Original und Kopie),
Kundensuche nach Dokumenten mit Umlaut, Artikelnamen escaped, Storno,
Kopie auf andere Adresse, Umschlag, Angebot mit eigener Anrede anlegen und
wieder bearbeiten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 11:27:27 +02:00
adminandClaude Opus 5 b76d883fbe 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 <noreply@anthropic.com>
2026-09-17 11:18:29 +02:00
adminandClaude Opus 5 6306bfba17 Login und Passkeys auf Prepared Statements umgebaut
- sites/start.php: ein Query statt zwei, Passwortvergleich per hash_equals
  in PHP statt im SQL, Updates per id. Die Eingaben gehen nicht mehr durch
  htmlspecialchars(): Passwoerter werden beim Anlegen roh gehasht, mit
  & < > " ' konnte man sich deshalb bisher nie anmelden.
- getUserSetting/updateUserSetting mit Platzhaltern; behoben: INSERT-Zweig
  rief mysqli_real_escape_string ohne Verbindung auf (Fatal Error),
  $mysqli_error als Variable, ungewolltes echo "update". Aufrufer escapen
  nicht mehr vor (sonst doppelt), settings.php: Tippfehler
  mysqi_real_escape_string beim Speichern von show_sks behoben, style nur
  als Dateiname ohne Pfad.
- authServer.php, addKey.php, userkeys.php, checkAdduser(): Platzhalter.
  Passkey-INSERT setzt lastAuth/authKey (Pflichtfelder im strikten Modus).
  addKey nur als reine Ziffern, sonst passte "12345678xyz" per Typumwandlung.
- checkLogin() entfernt: nirgends aufgerufen, fragte die nicht existierende
  Tabelle users ab.
- userkeys.tpl: Passkey-Name escaped.

Getestet gegen die migrierte Testdatenbank im strikten Modus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 10:24:17 +02:00
adminandClaude Opus 5 e2124220e5 Initialer Commit: Kundenverwaltung (PHP/Smarty)
Bestehende Codebasis als Ausgangsstand aufgenommen.

- .gitignore: Kundendaten (uploads_*), Smarty-Compile-Cache
  (templates_c), Laufzeit-Temp und Datenbank-Dumps ausgeschlossen;
  Verzeichnisstruktur ueber .gitkeep erhalten
- .gitattributes: Zeilenenden normalisiert (LF im Repo),
  Binaerformate markiert
- db-backup.php: MySQL-Zugangsdaten kommen jetzt wie im Rest der
  Anwendung aus der externen Konfiguration statt hartkodiert aus der
  Datei; Passwort wird ueber eine temporaere Optionsdatei statt per
  Kommandozeile uebergeben, Fehler von mysqldump/gzip werden gemeldet,
  Aufraeumen aelterer Backups berechnet Jahr und Monat konsistent

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 16:41:18 +02:00