trim((string) ($_POST['username'] ?? '')), 'email' => trim((string) ($_POST['email'] ?? '')), ]; if (!csrf_verify($_POST['csrf_token'] ?? null)) { fail(['Neplatný nebo vypršelý formulář, zkus to prosím znovu.']); } // Honeypot: boti pole často vyplní. Předstíráme úspěch, aby se bot // nedozvěděl, že byl odhalen, ale žádná data se nezapíšou. if (honeypot_triggered()) { $_SESSION['flash_success'] = 'Účet byl úspěšně vytvořen. Nyní se můžeš přihlásit do hry.'; header('Location: registrace.php'); exit; } $ip = client_ip(); $rateLimiter = new RateLimiter(__DIR__ . '/../data/ratelimit.sqlite', ...array_values($config['rate_limit'])); if ($rateLimiter->tooManyAttempts($ip)) { fail(['Příliš mnoho pokusů o registraci z tvé IP adresy. Zkus to prosím později.'], $old); } $username = $old['username']; $email = $old['email']; $password = (string) ($_POST['password'] ?? ''); $passwordConfirm = (string) ($_POST['password_confirm'] ?? ''); $errors = []; $errors = array_merge($errors, validate_username($username, $config['rules'])); $errors = array_merge($errors, validate_email($email)); $errors = array_merge($errors, validate_password($password, $config['rules'])); if ($password !== $passwordConfirm) { $errors[] = 'Zadaná hesla se neshodují.'; } $turnstileSecret = $config['turnstile']['secret_key']; if ($turnstileSecret !== '') { $turnstileToken = (string) ($_POST['cf-turnstile-response'] ?? ''); if (!Turnstile::verify($turnstileToken, $turnstileSecret, $ip)) { $errors[] = 'Ověření „nejsem robot“ se nezdařilo, zkus to prosím znovu.'; } } if (!empty($errors)) { // Neúspěšný pokus se počítá do rate limitu, aby útočník nemohl // zkoušet donekonečna jen proto, že validace selhala. $rateLimiter->recordAttempt($ip); fail($errors, $old); } $pdo = Database::connection(); $stmt = $pdo->prepare('SELECT id FROM account WHERE username = :username'); $stmt->execute([':username' => strtoupper($username)]); if ($stmt->fetch() !== false) { $rateLimiter->recordAttempt($ip); fail(['Toto uživatelské jméno už je obsazené.'], $old); } $srp = Srp6::makeRegistrationData($username, $password); try { $insert = $pdo->prepare( 'INSERT INTO account (username, salt, verifier, email, reg_mail, joindate, last_ip) VALUES (:username, :salt, :verifier, :email, :reg_mail, NOW(), :last_ip)' ); $insert->execute([ ':username' => strtoupper($username), ':salt' => $srp['salt'], ':verifier' => $srp['verifier'], ':email' => $email, ':reg_mail' => $email, ':last_ip' => $ip, ]); } catch (PDOException $e) { $rateLimiter->recordAttempt($ip); if ($e->getCode() === '23000') { fail(['Toto uživatelské jméno už je obsazené.'], $old); } error_log('Registration insert failed: ' . $e->getMessage()); fail(['Registraci se nepodařilo dokončit, zkus to prosím později.'], $old); } $rateLimiter->recordAttempt($ip); $_SESSION['flash_success'] = 'Účet byl úspěšně vytvořen. Nyní se můžeš přihlásit do hry.'; unset($_SESSION['csrf_token']); header('Location: registrace.php'); exit;