|
@@ -123,6 +123,80 @@ function settingsGetBackupCapabilityLabel(array $capability): string
|
|
|
return !empty($capability["available"]) ? "bereit" : "nicht verfügbar";
|
|
return !empty($capability["available"]) ? "bereit" : "nicht verfügbar";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function settingsIsSuperAdmin(): bool
|
|
|
|
|
+{
|
|
|
|
|
+ return normalizeAdminUsername($_SESSION['admin_username'] ?? "") === "admin";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function settingsGetLocalConfigPath(): string
|
|
|
|
|
+{
|
|
|
|
|
+ return dirname(__DIR__) . "/config.php";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function settingsReadLocalConfig(): string
|
|
|
|
|
+{
|
|
|
|
|
+ $path = settingsGetLocalConfigPath();
|
|
|
|
|
+ if (!is_file($path) || !is_readable($path)) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $content = file_get_contents($path);
|
|
|
|
|
+ return $content === false ? "" : $content;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function settingsWriteLocalConfig(string $content): void
|
|
|
|
|
+{
|
|
|
|
|
+ $content = str_replace("\r\n", "\n", $content);
|
|
|
|
|
+
|
|
|
|
|
+ if (!str_starts_with(ltrim($content), "<?php")) {
|
|
|
|
|
+ throw new RuntimeException('Die Konfiguration muss mit "<?php" beginnen.');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $path = settingsGetLocalConfigPath();
|
|
|
|
|
+ $tmpFile = $path . ".tmp";
|
|
|
|
|
+
|
|
|
|
|
+ if (file_put_contents($tmpFile, $content, LOCK_EX) === false) {
|
|
|
|
|
+ throw new RuntimeException("Konfiguration konnte nicht geschrieben werden.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $output = [];
|
|
|
|
|
+ $exitCode = 0;
|
|
|
|
|
+ exec(
|
|
|
|
|
+ escapeshellarg(PHP_BINARY) . " -l " . escapeshellarg($tmpFile) . " 2>&1",
|
|
|
|
|
+ $output,
|
|
|
|
|
+ $exitCode,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if ($exitCode !== 0) {
|
|
|
|
|
+ @unlink($tmpFile);
|
|
|
|
|
+ throw new RuntimeException("PHP-Syntaxfehler: " . trim(implode("\n", $output)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $backupDir = DATA_DIR . "backups/config/";
|
|
|
|
|
+ if (!is_dir($backupDir) && !mkdir($backupDir, 02775, true) && !is_dir($backupDir)) {
|
|
|
|
|
+ @unlink($tmpFile);
|
|
|
|
|
+ throw new RuntimeException("Sicherungsverzeichnis konnte nicht angelegt werden.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (is_file($path)) {
|
|
|
|
|
+ $backupPath = $backupDir . "config-" . date("Ymd-His") . ".php.bak";
|
|
|
|
|
+ if (!copy($path, $backupPath)) {
|
|
|
|
|
+ @unlink($tmpFile);
|
|
|
|
|
+ throw new RuntimeException("Sicherung der bestehenden Konfiguration ist fehlgeschlagen.");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @chmod($tmpFile, 0664);
|
|
|
|
|
+ if (!rename($tmpFile, $path)) {
|
|
|
|
|
+ @unlink($tmpFile);
|
|
|
|
|
+ throw new RuntimeException("Konfiguration konnte nicht gespeichert werden.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (function_exists("opcache_invalidate")) {
|
|
|
|
|
+ opcache_invalidate($path, true);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function settingsFindBackupByFilename(string $filename): ?array
|
|
function settingsFindBackupByFilename(string $filename): ?array
|
|
|
{
|
|
{
|
|
|
if ($filename === "" || basename($filename) !== $filename) {
|
|
if ($filename === "" || basename($filename) !== $filename) {
|
|
@@ -172,6 +246,7 @@ if (empty($_SESSION['admin_logged_in'])) {
|
|
|
$pageTitle = "Einstellungen";
|
|
$pageTitle = "Einstellungen";
|
|
|
$message = "";
|
|
$message = "";
|
|
|
$messageType = "";
|
|
$messageType = "";
|
|
|
|
|
+$isSuperAdmin = settingsIsSuperAdmin();
|
|
|
|
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === "POST" && isset($_POST['save_settings'])) {
|
|
if ($_SERVER['REQUEST_METHOD'] === "POST" && isset($_POST['save_settings'])) {
|
|
|
// Validate CSRF token
|
|
// Validate CSRF token
|
|
@@ -231,12 +306,32 @@ if ($_SERVER['REQUEST_METHOD'] === "POST" && isset($_POST['save_settings'])) {
|
|
|
$messageType = "error";
|
|
$messageType = "error";
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+} elseif ($_SERVER['REQUEST_METHOD'] === "POST" && isset($_POST['save_local_config'])) {
|
|
|
|
|
+ if (!$isSuperAdmin) {
|
|
|
|
|
+ http_response_code(403);
|
|
|
|
|
+ $message = "Keine Berechtigung für diese Aktion.";
|
|
|
|
|
+ $messageType = "error";
|
|
|
|
|
+ } elseif (!validateCsrfToken($_POST['csrf_token'] ?? "")) {
|
|
|
|
|
+ $message = "Ungültiges Token. Bitte versuchen Sie es erneut.";
|
|
|
|
|
+ $messageType = "error";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ try {
|
|
|
|
|
+ settingsWriteLocalConfig((string) ($_POST['local_config_content'] ?? ""));
|
|
|
|
|
+ logAccess("Admin updated local config.php");
|
|
|
|
|
+ $message = "Lokale Konfiguration wurde gespeichert.";
|
|
|
|
|
+ $messageType = "success";
|
|
|
|
|
+ } catch (Throwable $exception) {
|
|
|
|
|
+ $message = "Konfiguration konnte nicht gespeichert werden: " . $exception->getMessage();
|
|
|
|
|
+ $messageType = "error";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
$settings = getSystemSettings();
|
|
$settings = getSystemSettings();
|
|
|
$updaterStatus = settingsGetUpdaterStatus();
|
|
$updaterStatus = settingsGetUpdaterStatus();
|
|
|
$backupCapabilities = backupRemoteCapabilities();
|
|
$backupCapabilities = backupRemoteCapabilities();
|
|
|
$backups = backupListBackups();
|
|
$backups = backupListBackups();
|
|
|
|
|
+$localConfigContent = $isSuperAdmin ? settingsReadLocalConfig() : "";
|
|
|
|
|
|
|
|
$bodyClass = "admin-page";
|
|
$bodyClass = "admin-page";
|
|
|
include __DIR__ . "/../includes/header.php";
|
|
include __DIR__ . "/../includes/header.php";
|
|
@@ -350,4 +445,22 @@ include __DIR__ . "/../includes/header.php";
|
|
|
<p><a href="updater.php" class="btn btn-secondary">Updater öffnen</a></p>
|
|
<p><a href="updater.php" class="btn btn-secondary">Updater öffnen</a></p>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+<?php if ($isSuperAdmin): ?>
|
|
|
|
|
+<div class="panel panel-lg mt-4">
|
|
|
|
|
+ <h3>Lokale Konfiguration</h3>
|
|
|
|
|
+ <p>Bearbeitet <code>config.php</code> direkt auf diesem Server. Diese Datei wird beim Update nicht überschrieben.</p>
|
|
|
|
|
+ <div class="alert alert-warning">Vor dem Speichern wird die PHP-Syntax geprüft und die vorherige Version automatisch gesichert. Fehlerhafte Änderungen können die gesamte Anwendung lahmlegen.</div>
|
|
|
|
|
+ <form method="POST">
|
|
|
|
|
+ <?php echo csrfField(); ?>
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="local_config_content">Inhalt von config.php</label>
|
|
|
|
|
+ <textarea id="local_config_content" name="local_config_content" rows="24" class="config-editor" spellcheck="false"><?php echo escape(
|
|
|
|
|
+ $localConfigContent,
|
|
|
|
|
+ ); ?></textarea>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <button type="submit" name="save_local_config" class="btn">Speichern</button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+</div>
|
|
|
|
|
+<?php endif; ?>
|
|
|
|
|
+
|
|
|
<?php include __DIR__ . "/../includes/footer.php"; ?>
|
|
<?php include __DIR__ . "/../includes/footer.php"; ?>
|