- The installer only opens with a per-installation key that install.php creates and shows; the key is deleted with the first account. - Lock files keep .env, the database, backups and logs out of reach when a domain points at the project folder instead of public/. - Linked sections render by their own schema version, so an old section cannot carry unfiltered HTML into a newer page. - Editors no longer move, trash or change areas and post data of published pages; a scheduled publication goes live with the revision that was scheduled (migration 20261012000100). - Form stamps are bound to their form, IPv6 senders count per /64, and a flood per form or overall stops storing with a visible message. - The consent redirect rejects control characters, update targets must look like 1.2.3, and own CSS cannot reach outside its block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
1.4 KiB
PHP
40 lines
1.4 KiB
PHP
<?php
|
|
|
|
namespace App\Ops;
|
|
|
|
/**
|
|
* Sperrdateien, die dafür sorgen, dass nichts außer public/ über das Netz erreichbar ist - auch
|
|
* wenn die Domain versehentlich auf den Projektordner zeigt (ADR 116).
|
|
*
|
|
* Die meisten liegen im Release (bin/, config/, src/ …, vendor/ und der Projektstamm). Zwei
|
|
* entstehen erst auf dem Server: var/ gibt es im Archiv nicht, und die Datei im Projektstamm soll
|
|
* auch eine Installation bekommen, die von einer Fassung vor 1.30.0 aktualisiert wurde - deren
|
|
* Updater kannte sie noch nicht. Angelegt wird nur, was fehlt; eine eigene .htaccess des Betreibers
|
|
* im Projektstamm bleibt unberührt.
|
|
*/
|
|
final class Protection
|
|
{
|
|
private static bool $checked = false;
|
|
|
|
public static function ensure(string $root): void
|
|
{
|
|
if (self::$checked) {
|
|
return;
|
|
}
|
|
self::$checked = true;
|
|
$sperren = $root.'/config/schutz/sperren.htaccess';
|
|
$stamm = $root.'/config/schutz/stamm.htaccess';
|
|
foreach ([$root.'/var/.htaccess' => $sperren, $root.'/vendor/.htaccess' => $sperren, $root.'/.htaccess' => $stamm] as $ziel => $vorlage) {
|
|
if (!is_file($ziel) && is_dir(\dirname($ziel)) && is_file($vorlage)) {
|
|
@copy($vorlage, $ziel);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Für Tests: die nächste Anfrage prüft wieder. */
|
|
public static function reset(): void
|
|
{
|
|
self::$checked = false;
|
|
}
|
|
}
|