Files
pcat/inc/admin_bootstrap.php

111 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/db.inc.php';
session_set_cookie_params([
'httponly' => true,
'samesite' => 'Strict',
'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
]);
ini_set('session.use_strict_mode', '1');
session_start();
header('Cache-Control: no-store');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('Referrer-Policy: no-referrer');
header('Permissions-Policy: camera=(), microphone=(), geolocation=()');
header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'");
function db(): PDO
{
global $dbConfig;
$dsn = sprintf('mysql:host=%s;port=%d;dbname=%s;charset=%s', $dbConfig['host'], $dbConfig['port'], $dbConfig['database'], $dbConfig['charset']);
return new PDO($dsn, $dbConfig['username'], $dbConfig['password'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
$pdo = db();
function requireAdmin(): void
{
global $pdo;
if (!isset($_SESSION['admin_id'])) {
http_response_code(403);
exit('Zugriff verweigert.');
}
$statement = $pdo->prepare('SELECT id FROM admin_users WHERE id = :id AND is_active = 1 LIMIT 1');
$statement->execute([':id' => (int) $_SESSION['admin_id']]);
if (!$statement->fetchColumn()) {
$_SESSION = [];
session_destroy();
http_response_code(403);
exit('Zugriff verweigert.');
}
}
function e(mixed $value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function csrf(): string
{
return $_SESSION['admin_csrf'] ??= bin2hex(random_bytes(32));
}
function verifyCsrf(): void
{
$token = $_POST['csrf_token'] ?? '';
if (!is_string($token) || !hash_equals(csrf(), $token)) {
http_response_code(403);
exit('Ungültige Anfrage.');
}
}
function postText(string $key, int $maxLength): string
{
$value = $_POST[$key] ?? '';
$value = is_string($value) ? trim($value) : '';
if (mb_strlen($value) > $maxLength) throw new InvalidArgumentException('Eingabe zu lang.');
return $value;
}
function validateIsbnField(string $value, string $label): ?string
{
$value = trim($value);
if ($value === '') {
return null;
}
if (!preg_match('/^97[89](?:-[0-9]+)+$/', $value)) {
throw new InvalidArgumentException($label . ' muss als ISBN-13 mit Bindestrichen eingegeben werden, zum Beispiel 978-3-16-148410-0.');
}
$digits = str_replace('-', '', $value);
if (strlen($digits) !== 13) {
throw new InvalidArgumentException($label . ' muss genau 13 Ziffern enthalten.');
}
$sum = 0;
for ($index = 0; $index < 12; $index++) {
$sum += (int) $digits[$index] * ($index % 2 === 0 ? 1 : 3);
}
$checkDigit = (10 - ($sum % 10)) % 10;
if ((int) $digits[12] !== $checkDigit) {
throw new InvalidArgumentException($label . ' enthält eine ungültige Prüfziffer.');
}
return $value;
}
function redirectAdmin(): never
{
header('Location: admin.php');
exit;
}