| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client2/web31/web/slots/includes/ |
Upload File : |
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/functions.php';
function current_user(): ?array {
if (empty($_SESSION['user_id'])) {
return null;
}
static $cached = null;
if ($cached && (int)$cached['id'] === (int)$_SESSION['user_id']) {
return $cached;
}
$stmt = db()->prepare('SELECT * FROM users WHERE id = ? LIMIT 1');
$stmt->execute([(int)$_SESSION['user_id']]);
$user = $stmt->fetch();
if (!$user) {
logout_user();
return null;
}
$cached = $user;
return $cached;
}
function require_login(): array {
$user = current_user();
if (!$user) {
header('Location: login.php');
exit;
}
if ((int)($user['banned'] ?? 0) === 1) {
logout_user();
header('Location: login.php?banned=1');
exit;
}
return $user;
}
/** Ist der (aktuelle) Nutzer Administrator? */
function is_admin(?array $user = null): bool {
$user = $user ?? current_user();
if (!$user) {
return false;
}
$admins = app_config()['admins'] ?? [];
return in_array($user['username'], $admins, true);
}
function require_admin(): array {
$user = require_login();
if (!is_admin($user)) {
http_response_code(403);
exit('403 – Kein Zugriff auf den Administrationsbereich.');
}
return $user;
}
function login_user(array $user): void {
$_SESSION['user_id'] = (int)$user['id'];
$_SESSION['last_ping_ts'] = time();
db()->prepare('UPDATE users SET last_login_at = NOW(), last_seen_at = NOW() WHERE id = ?')->execute([(int)$user['id']]);
}
function logout_user(): void {
remember_clear();
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], (bool)$params['secure'], (bool)$params['httponly']);
}
session_destroy();
}
/* ============================================================
* "Angemeldet bleiben" – sichere Remember-Me-Tokens
* Cookie-Format: <selector>:<validator>. In der DB liegt nur der
* SHA-256-Hash des Validators; der Selektor adressiert die Zeile.
* ============================================================ */
const REMEMBER_COOKIE = 'rr_remember';
const REMEMBER_TTL = 2592000; // 30 Tage
/** Cookie-Pfad = App-Verzeichnis (z. B. /slots), damit das Cookie scoped bleibt. */
function remember_cookie_path(): string {
$dir = str_replace('\\', '/', dirname((string)($_SERVER['SCRIPT_NAME'] ?? '/')));
$dir = rtrim($dir, '/');
return $dir === '' ? '/' : $dir;
}
function remember_is_secure(): bool {
if (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off') return true;
if ((int)($_SERVER['SERVER_PORT'] ?? 0) === 443) return true;
return strtolower((string)($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '')) === 'https';
}
function remember_set_cookie(string $value, int $expires): void {
if (headers_sent()) return;
setcookie(REMEMBER_COOKIE, $value, [
'expires' => $expires,
'path' => remember_cookie_path(),
'secure' => remember_is_secure(),
'httponly' => true,
'samesite' => 'Lax',
]);
$_COOKIE[REMEMBER_COOKIE] = $value; // sofort konsistent im selben Request
}
function remember_clear_cookie(): void {
if (!headers_sent()) {
setcookie(REMEMBER_COOKIE, '', [
'expires' => time() - 42000,
'path' => remember_cookie_path(),
'secure' => remember_is_secure(),
'httponly' => true,
'samesite' => 'Lax',
]);
}
unset($_COOKIE[REMEMBER_COOKIE]);
}
/** Neues Remember-Token für einen Nutzer anlegen und Cookie setzen. */
function remember_create(int $userId): void {
if ($userId <= 0) return;
$selector = bin2hex(random_bytes(9)); // 18 Hex-Zeichen
$validator = bin2hex(random_bytes(32)); // 64 Hex-Zeichen
$expires = time() + REMEMBER_TTL;
$stmt = db()->prepare(
'INSERT INTO remember_tokens (user_id, selector, validator_hash, expires_at, created_at, last_used_at, user_agent)
VALUES (?, ?, ?, ?, NOW(), NOW(), ?)'
);
$stmt->execute([
$userId, $selector, hash('sha256', $validator), date('Y-m-d H:i:s', $expires),
mb_substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 255),
]);
remember_set_cookie($selector . ':' . $validator, $expires);
}
/** Validator rotieren (Selektor bleibt) – nach jeder erfolgreichen Auto-Anmeldung. */
function remember_rotate(int $tokenId, string $selector, int $userId): void {
$validator = bin2hex(random_bytes(32));
$expires = time() + REMEMBER_TTL;
db()->prepare('UPDATE remember_tokens SET validator_hash = ?, expires_at = ?, last_used_at = NOW() WHERE id = ?')
->execute([hash('sha256', $validator), date('Y-m-d H:i:s', $expires), $tokenId]);
remember_set_cookie($selector . ':' . $validator, $expires);
}
/** Aktuelles Remember-Token (per Cookie) löschen + Cookie entfernen. */
function remember_clear(): void {
$raw = (string)($_COOKIE[REMEMBER_COOKIE] ?? '');
if ($raw !== '' && strpos($raw, ':') !== false) {
list($selector) = explode(':', $raw, 2);
if ($selector !== '') {
db()->prepare('DELETE FROM remember_tokens WHERE selector = ?')->execute([$selector]);
}
}
remember_clear_cookie();
}
/** Beim Seitenaufruf: ohne Session, aber mit gültigem Remember-Cookie automatisch anmelden. */
function remember_attempt_login(): void {
if (!empty($_SESSION['user_id'])) return; // bereits angemeldet
$raw = (string)($_COOKIE[REMEMBER_COOKIE] ?? '');
if ($raw === '' || strpos($raw, ':') === false) return;
list($selector, $validator) = explode(':', $raw, 2);
if ($selector === '' || $validator === '') { remember_clear_cookie(); return; }
$stmt = db()->prepare('SELECT * FROM remember_tokens WHERE selector = ? LIMIT 1');
$stmt->execute([$selector]);
$tok = $stmt->fetch();
if (!$tok) { remember_clear_cookie(); return; }
if (strtotime((string)$tok['expires_at']) < time()) {
db()->prepare('DELETE FROM remember_tokens WHERE id = ?')->execute([(int)$tok['id']]);
remember_clear_cookie();
return;
}
// Konstante-Zeit-Vergleich; bei Nichtübereinstimmung evtl. Diebstahl → alle Tokens des Nutzers verwerfen.
if (!hash_equals((string)$tok['validator_hash'], hash('sha256', $validator))) {
db()->prepare('DELETE FROM remember_tokens WHERE user_id = ?')->execute([(int)$tok['user_id']]);
remember_clear_cookie();
return;
}
$u = db()->prepare('SELECT * FROM users WHERE id = ? LIMIT 1');
$u->execute([(int)$tok['user_id']]);
$user = $u->fetch();
if (!$user || (int)($user['banned'] ?? 0) === 1) {
db()->prepare('DELETE FROM remember_tokens WHERE id = ?')->execute([(int)$tok['id']]);
remember_clear_cookie();
return;
}
// Session herstellen (ohne login_user, um Token-Logik gebündelt zu halten)
$_SESSION['user_id'] = (int)$user['id'];
$_SESSION['last_ping_ts'] = time();
db()->prepare('UPDATE users SET last_login_at = NOW(), last_seen_at = NOW() WHERE id = ?')->execute([(int)$user['id']]);
remember_rotate((int)$tok['id'], $selector, (int)$user['id']);
}
/** Einfacher CSRF-Token für API-Posts. */
function csrf_token(): string {
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(random_bytes(16));
}
return $_SESSION['csrf'];
}
function csrf_verify(?string $token): bool {
return is_string($token) && !empty($_SESSION['csrf']) && hash_equals($_SESSION['csrf'], $token);
}
// Auto-Anmeldung per "Angemeldet bleiben"-Cookie (vor jeglicher Ausgabe, Cookies setzbar).
remember_attempt_login();