Der alte Code fuegt fast ueberall Zeilen ein, ohne alle NOT-NULL-Spalten zu
setzen; der nicht strikte Modus hat dann '', 0 oder ein Nulldatum
eingesetzt. Diese Werte stehen jetzt als DEFAULT im Schema. Weggelassene
Spalten verhalten sich damit wie bisher, ungueltige Werte, zu lange Texte
und falsche Verweise lehnt der strikte Modus weiterhin ab.
Das Migrationsskript meldet Spalten, die in der Quelle fehlen und ueber den
Standardwert gefuellt werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
isLocal() hielt jede Adresse aus 192.168.147.* fuer lokal. Das ist das
Docker-Netz auf dem NAS: Anfragen ueber den Docker- oder einen Reverse
Proxy tragen dessen Adresse und waeren damit als lokal durchgegangen
(Passwort-Login und Passkey-Freigabe von aussen). Der IPv6-Vergleich per
explode(":") scheiterte ausserdem an komprimierten Adressen.
- lokale Netze stehen als CIDR-Liste $lokale_netze in der externen Config
- ipImNetz() vergleicht IPv4/IPv6 korrekt per inet_pton, inkl. ::ffff:-Form
- Anfragen mit Proxy-Headern gelten nie als lokal
- ohne Konfiguration nur noch dasselbe IPv6-/64 wie der Server, kein IPv4
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
update/migration-utf8mb4.php kopiert eine Instanz-Datenbank in eine neue
Datenbank mit update/schema.sql. Jeder Textwert wird einzeln eingeordnet
(korrekt, doppelt, mehrfach kodiert, unklar) und nur repariert, wenn die
Rueckfuehrung ueber MySQLs latin1-Abbildung eindeutig ist. Die Quelle bleibt
unveraendert.
- "pruefen" liest nur und gibt einen Bericht aus
- "migrieren <ziel>" legt das Ziel an, kopiert im strikten Modus, fuellt
fehlende Spalten und NULL in Pflichtfeldern mit Leerwerten, prueft die
Fremdschluessel und meldet verwaiste Verweise
Getestet gegen Dummy-Daten im alten Schema (778 doppelt, 28 mehrfach,
180 korrekt, 24 gemischt: alle Werte wie erwartet) und gegen das
abweichende ingwa-Schema.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Grundlage ist die Struktur der kunden-Datenbank. project und work kommen
aus ingwa, weil der Code sie fuer das Projekte-Modul braucht, sie in kunden
aber fehlen. Die Sicherungskopien altlasten_backup* sind nicht enthalten.
Tabellen, Spalten, Schluessel und Fremdschluessel sind sonst unveraendert,
nur Zeichensatz und Sortierung sind einheitlich utf8mb4_unicode_ci.
.gitignore laesst update/schema.sql als einzige .sql-Datei zu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- incs/db.php: db_verbinden() setzt utf8mb4, strikten sql_mode und schaltet
die mysqli-Exceptions von PHP 8.1+ ab, damit die bestehenden
"or error(mysqli_error())"-Pruefungen weiter greifen.
- db_abfrage/db_zeilen/db_zeile/db_wert mit ?-Platzhaltern
(mysqli_execute_query, PHP 8.2).
- Alle neun kopierten mysqli_connect/select_db-Stellen nutzen jetzt
db_verbinden().
Nur zusammen mit der auf utf8mb4 migrierten Datenbank einsetzbar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SMTP-Passwoerter (mail_attachment), der MySQL-Zugang von stats.php und die
Schluessel fuer OpenWeatherMap und Aeris standen im Klartext im Code. Sie
kommen jetzt aus der externen Config ($smtp_konten, $stats_mysql_*,
$openweathermap_appid, $aeris_client_*). rebuild-settings.php legt die
Eintraege bei der Ersteinrichtung leer an.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Instanz:
- $instanz in der externen Config bestimmt INSTANZ, UPLOADS_PATH und
SESSION_NAME. Der Verzeichnisname waehlt nur noch die Config-Datei aus
und ist Fallback, solange $instanz fehlt.
- savePDF() schreibt nicht mehr fest nach DOCUMENT_ROOT."kunden", sondern
in das Verzeichnis, das es auch aufraeumt. .gitkeep wird nicht mehr
mitgeloescht.
Sicherheit:
- index.php?action=setup war ohne Login auch bei gueltiger Config
erreichbar. rebuild-settings.php schrieb $_POST ungeprueft als PHP-Code
in die Config (Codeausfuehrung, sofern die Datei schreibbar war).
- Setup nur noch ohne gueltige Config, firststart.php und
rebuild-settings.php pruefen das zusaetzlich selbst.
- Config-Werte werden per var_export() maskiert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>