hat, // kannst du das nutzen, falls kein $GLOBALS['lang'] gesetzt ist: if (empty($lang) && !empty($_POST['lang'])) { $lang = substr((string)$_POST['lang'], 0, 2); } // Minimal-Validierung if ( $email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL) || $password === '' ) { flash_set('error', 'Bitte E-Mail-Adresse und Passwort eingeben.', 'login'); header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth'); exit; } /* --------------------------------------------------------- USER LADEN --------------------------------------------------------- */ try { $stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email LIMIT 1'); $stmt->execute([':email' => $email]); $user = $stmt->fetch(PDO::FETCH_ASSOC); } catch (Throwable $e) { // DB-Fehler → generische Meldung flash_set('error', 'Es ist ein Fehler beim Login aufgetreten. Bitte versuche es später erneut.', 'login'); header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth'); exit; } if (!$user) { flash_set('error', 'E-Mail oder Passwort ist falsch.', 'login'); header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth'); exit; } /* --------------------------------------------------------- ACCOUNT GESPERRT? --------------------------------------------------------- */ if (!empty($user['is_locked'])) { flash_set('error', 'Dein Konto ist gesperrt. Bitte kontaktiere den Support.', 'login'); header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth'); exit; } /* --------------------------------------------------------- PASSWORT PRÜFEN --------------------------------------------------------- */ if (!password_verify($password, $user['password_hash'])) { // Fehlversuche hochzählen try { $failed = (int)($user['failed_logins'] ?? 0) + 1; $lock = 0; if ($failed >= 5) { $lock = 1; } $upd = $pdo->prepare('UPDATE users SET failed_logins = :failed, is_locked = :locked WHERE id = :id'); $upd->execute([ ':failed' => $failed, ':locked' => $lock, ':id' => $user['id'], ]); } catch (Throwable $e) { // Nicht kritisch, Meldung reicht } $msg = 'E-Mail oder Passwort ist falsch.'; if (($user['failed_logins'] ?? 0) + 1 >= 5) { $msg = 'Zu viele Fehlversuche. Dein Konto wurde vorübergehend gesperrt.'; } flash_set('error', $msg, 'login'); header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth'); exit; } /* --------------------------------------------------------- PASSWORT KORREKT → FAILED_LOGINS RESET + LAST_LOGIN --------------------------------------------------------- */ try { $upd = $pdo->prepare('UPDATE users SET failed_logins = 0, last_login_at = NOW() WHERE id = :id'); $upd->execute([':id' => $user['id']]); } catch (Throwable $e) { // Nicht kritisch für den Nutzer } /* --------------------------------------------------------- SESSION FÜLLEN --------------------------------------------------------- */ $firstName = $user['first_name'] ?? ''; $lastName = $user['last_name'] ?? ''; $initials = ''; if ($firstName !== '') { $initials .= mb_substr($firstName, 0, 1); } if ($lastName !== '') { $initials .= mb_substr($lastName, 0, 1); } if ($initials === '') { $initials = mb_substr($user['username'] ?? $user['email'], 0, 2); } $initials = mb_strtoupper($initials); $_SESSION['user'] = [ 'id' => $user['id'], 'email' => $user['email'], 'username' => $user['username'], 'first_name' => $user['first_name'], 'last_name' => $user['last_name'], 'plan' => $user['plan'] ?? 'free', 'initials' => $initials, ]; /* --------------------------------------------------------- FLASH & SMART REDIRECT --------------------------------------------------------- */ flash_set('success', 'Willkommen zurück, ' . ($user['first_name'] ?: 'User') . '!', 'login'); // redirect normalisieren $redirect = trim((string)($redirect ?? '')); // Flag: sollen wir stattdessen aufs Dashboard? $goDashboard = false; // 1) redirect leer → Dashboard if ($redirect === '') { $goDashboard = true; } // 2) redirect zeigt auf /login → Dashboard (Endlosschleife vermeiden) if (!$goDashboard && preg_match('#^/login(/|\?|$)#i', $redirect)) { $goDashboard = true; } // 3) redirect ist keine interne URL → Dashboard (Sicherheit!) if (!$goDashboard && strpos($redirect, '/') !== 0) { $goDashboard = true; } // 4) Finales Ziel bestimmen if ($goDashboard) { // Immer Dashboard-Seite $target = '/dashboard/?lang=' . urlencode($lang); } else { // Internes Ziel, Sprache anhängen falls noch nicht vorhanden if (strpos($redirect, 'lang=') === false) { $sep = (strpos($redirect, '?') === false) ? '?' : '&'; $redirect = $redirect . $sep . 'lang=' . urlencode($lang); } $target = $redirect; } header('Location: ' . $target); exit;