0, 'path' => '/', 'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', 'httponly' => true, 'samesite' => 'Strict']); session_name('plugin_site_admin'); session_start(); $cfg = site_config(); $error = null; $message = null; function admin_csrf(): string { return $_SESSION['csrf'] ??= bin2hex(random_bytes(24)); } function admin_check_csrf(): bool { return hash_equals($_SESSION['csrf'] ?? '', (string) ($_POST['csrf'] ?? '')); } /** Höchstens 5 Fehlversuche pro IP in 15 Minuten. */ function admin_throttled(bool $record = false): bool { $file = site_storage() . '/login_attempts.json'; $data = is_file($file) ? (json_decode((string) file_get_contents($file), true) ?: []) : []; $ip = $_SERVER['REMOTE_ADDR'] ?? '?'; $now = time(); $data[$ip] = array_values(array_filter($data[$ip] ?? [], fn($t) => $t > $now - 900)); if ($record) { $data[$ip][] = $now; file_put_contents($file, json_encode($data), LOCK_EX); } return count($data[$ip]) >= 5; } $loggedIn = !empty($_SESSION['admin']); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; if ($action === 'login') { if ($cfg['admin_password_hash'] === '') { $error = 'Die Verwaltung ist nicht eingerichtet: In config.php fehlt admin_password_hash.'; } elseif (admin_throttled()) { $error = 'Zu viele Fehlversuche. Bitte in 15 Minuten erneut versuchen.'; } elseif (hash_equals((string) $cfg['admin_user'], (string) ($_POST['user'] ?? '')) && password_verify((string) ($_POST['password'] ?? ''), (string) $cfg['admin_password_hash'])) { session_regenerate_id(true); $_SESSION['admin'] = true; header('Location: admin.php'); exit; } else { admin_throttled(true); usleep(400000); $error = 'Benutzername oder Passwort ist falsch.'; } } elseif (!$loggedIn || !admin_check_csrf()) { http_response_code(403); $error = 'Ungültige Anfrage. Bitte neu anmelden.'; $loggedIn = false; } elseif ($action === 'logout') { session_destroy(); header('Location: admin.php'); exit; } elseif ($action === 'publish') { $zip = $_FILES['package'] ?? []; if (($zip['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { $error = 'Upload-Fehler (Code ' . ($zip['error'] ?? '?') . '). Prüft upload_max_filesize und post_max_size.'; } elseif (strtolower(pathinfo((string) $zip['name'], PATHINFO_EXTENSION)) !== 'zip') { $error = 'Bitte eine ZIP-Datei hochladen.'; } else { $prev = $_FILES['preview'] ?? []; $hasPreview = ($prev['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_OK; $res = site_publish((string) ($_POST['type'] ?? ''), $zip['tmp_name'], $_POST, $hasPreview ? $prev['tmp_name'] : null, $hasPreview ? (string) $prev['name'] : null); if ($res['ok']) $message = "Veröffentlicht: {$res['slug']} {$res['version']} (" . ($res['signed'] ? 'signiert' : 'NICHT signiert, kein Signierschlüssel eingerichtet') . ').'; else $error = $res['error']; } } elseif ($action === 'delete') { $message = site_delete_version((int) ($_POST['id'] ?? 0)) ? 'Version entfernt.' : null; $error = $message ? null : 'Version nicht gefunden.'; } } site_header('Verwaltung'); ?>

Verwaltung

Einstellungen für DeskHub (offizieller Katalog)

Diesen Inhalt in includes/catalog_defaults.php von DeskHub einsetzen, bevor ihr ein Release baut. Dann installieren eure Kunden Plugins nur aus diesem Katalog, und nur signierte.

Es ist noch kein Signierschlüssel eingerichtet (php einrichten.php). Ohne Schlüssel ist der geprüfte Modus nicht nutzbar.

Neues Paket veröffentlichen

Nur für Themes (bei Plugins steht alles in der plugin.json)

Veröffentlichte Pakete

'Plugins', 'theme' => 'Themes'] as $t => $label): $items = site_items($t); ?>

Noch keine.

Downloads signiert' : 'nicht signiert' ?>