many improvements
This commit is contained in:
143
reservations.php
Normal file
143
reservations.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/* ========= Session & Bootstrap ========= */
|
||||
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
|
||||
session_set_cookie_params([
|
||||
'lifetime'=>0,'path'=>'/','secure'=>$secure,'httponly'=>true,'samesite'=>'Lax',
|
||||
]);
|
||||
session_name('WLISTSESSID');
|
||||
session_start();
|
||||
umask(0022); // neue Dateien: 0644, Ordner: 0755
|
||||
|
||||
require_once __DIR__ . '/config/config.php';
|
||||
|
||||
/* ===== Debug Toggle (wie item.php) ===== */
|
||||
if (!empty($app_debug)) {
|
||||
ini_set('display_errors','1'); ini_set('display_startup_errors','1'); ini_set('log_errors','1');
|
||||
if (!is_dir(__DIR__.'/logs')) { @mkdir(__DIR__.'/logs',0750,true); }
|
||||
ini_set('error_log', __DIR__.'/logs/php-error.log'); error_reporting(E_ALL);
|
||||
} else {
|
||||
ini_set('display_errors','0'); ini_set('display_startup_errors','0'); ini_set('log_errors','1');
|
||||
if (!is_dir(__DIR__.'/logs')) { @mkdir(__DIR__.'/logs',0750,true); }
|
||||
ini_set('error_log', __DIR__.'/logs/php-error.log'); error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
/* ============= Helpers ============= */
|
||||
function fail(string $msg, int $code=400): void {
|
||||
http_response_code($code);
|
||||
// kleine Flash-Message für index.php
|
||||
$_SESSION['flash'] = ['msg'=>$msg,'type'=> ($code>=400?'danger':'success')];
|
||||
safe_redirect_back();
|
||||
}
|
||||
function db(): mysqli {
|
||||
global $servername, $username, $password, $db;
|
||||
$conn = new mysqli($servername, $username, $password, $db);
|
||||
if ($conn->connect_error) fail('Interner Fehler (DB)', 500);
|
||||
$conn->set_charset('utf8mb4');
|
||||
return $conn;
|
||||
}
|
||||
function require_csrf(): void {
|
||||
$t = (string)($_POST['csrf'] ?? '');
|
||||
if (empty($_SESSION['csrf']) || !hash_equals($_SESSION['csrf'], $t)) {
|
||||
fail('Ungültiges CSRF-Token', 403);
|
||||
}
|
||||
}
|
||||
function e(string $s): string { return htmlspecialchars($s, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); }
|
||||
function safe_redirect_back(): void {
|
||||
$ref = (string)($_SERVER['HTTP_REFERER'] ?? '');
|
||||
if ($ref === '' || stripos($ref, 'http') !== 0) {
|
||||
$host = $_SERVER['HTTP_HOST'] ?? '';
|
||||
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||
header('Location: '.$scheme.'://'.$host.'/', true, 303);
|
||||
} else {
|
||||
header('Location: '.$ref, true, 303);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/* ============= Controller ============= */
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
fail('Methode nicht erlaubt', 405);
|
||||
}
|
||||
require_csrf();
|
||||
|
||||
$wishId = (int)($_POST['wishid'] ?? -1);
|
||||
$pw = (string)($_POST['WishPassword'] ?? '');
|
||||
$reservedstat = (int)($_POST['reservedstat'] ?? 0); // 0 = setzen, 1 = aufheben
|
||||
|
||||
if ($wishId <= 0) fail('Ungültige Wunsch-ID', 400);
|
||||
if ($pw === '') fail('Passwort erforderlich', 400);
|
||||
|
||||
$conn = db();
|
||||
|
||||
/* --- qty des Wunsch + bestehende Reservierungen zählen --- */
|
||||
$qty = 1;
|
||||
$stmt = $conn->prepare('SELECT qty FROM wishes WHERE ID = ?');
|
||||
$stmt->bind_param('i', $wishId);
|
||||
$stmt->execute();
|
||||
$res = $stmt->get_result();
|
||||
if (!$res || !($row = $res->fetch_assoc())) {
|
||||
$stmt->close(); $conn->close(); fail('Wunsch nicht gefunden', 404);
|
||||
}
|
||||
$qty = max(1, (int)$row['qty']);
|
||||
$stmt->close();
|
||||
|
||||
/* Existierende Reservierungen zählen */
|
||||
$cnt = 0;
|
||||
$stmt = $conn->prepare('SELECT COUNT(*) AS c FROM wishes_reservations WHERE wish_id = ?');
|
||||
$stmt->bind_param('i',$wishId);
|
||||
$stmt->execute();
|
||||
$res = $stmt->get_result();
|
||||
if ($res && ($row = $res->fetch_assoc())) $cnt = (int)$row['c'];
|
||||
$stmt->close();
|
||||
|
||||
/* --- Operationen --- */
|
||||
if ($reservedstat === 0) {
|
||||
// setzen
|
||||
if ($cnt >= $qty) {
|
||||
$conn->close();
|
||||
fail('Für diesen Wunsch sind bereits alle Exemplare reserviert.', 409);
|
||||
}
|
||||
$hash = password_hash($pw, PASSWORD_BCRYPT);
|
||||
$ins = $conn->prepare('INSERT INTO wishes_reservations (wish_id, pass_hash, created_at) VALUES (?, ?, NOW())');
|
||||
$ins->bind_param('is', $wishId, $hash);
|
||||
if (!$ins->execute()) {
|
||||
$ins->close(); $conn->close();
|
||||
fail('Reservierung fehlgeschlagen', 500);
|
||||
}
|
||||
$ins->close();
|
||||
$conn->close();
|
||||
$_SESSION['flash'] = ['msg'=>'Reservierung eingetragen','type'=>'success'];
|
||||
safe_redirect_back();
|
||||
|
||||
} else {
|
||||
// aufheben: passenden Hash suchen und genau einen Eintrag löschen
|
||||
$sel = $conn->prepare('SELECT id, pass_hash FROM wishes_reservations WHERE wish_id = ?');
|
||||
$sel->bind_param('i',$wishId);
|
||||
$sel->execute();
|
||||
$res = $sel->get_result();
|
||||
|
||||
$deleted = false;
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
$rid = (int)$row['id'];
|
||||
$rhash= (string)$row['pass_hash'];
|
||||
if (password_verify($pw, $rhash)) {
|
||||
$del = $conn->prepare('DELETE FROM wishes_reservations WHERE id = ? LIMIT 1');
|
||||
$del->bind_param('i', $rid);
|
||||
$deleted = $del->execute();
|
||||
$del->close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sel->close();
|
||||
$conn->close();
|
||||
|
||||
if ($deleted) {
|
||||
$_SESSION['flash'] = ['msg'=>'Reservierung aufgehoben','type'=>'success'];
|
||||
} else {
|
||||
$_SESSION['flash'] = ['msg'=>'Kein passender Reservierungseintrag gefunden (Passwort korrekt?)','type'=>'warning'];
|
||||
}
|
||||
safe_redirect_back();
|
||||
}
|
Reference in New Issue
Block a user