requireAdmin(); } echo "

System Test

"; // 1. PHP Version echo "

1. PHP Version

"; echo "PHP Version: " . phpversion() . "
"; // 2. Config.php vorhanden? echo "

2. Config.php Check

"; if (file_exists('config.php')) { echo "✓ config.php existiert
"; require_once 'config.php'; echo "✓ config.php geladen
"; echo "DB_HOST: " . DB_HOST . "
"; echo "DB_NAME: " . DB_NAME . "
"; } else { echo "✗ config.php nicht gefunden!
"; } // 3. Datenbankverbindung echo "

3. Datenbankverbindung

"; try { $pdo = new PDO( "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4", DB_USER, DB_PASS ); echo "✓ Datenbankverbindung erfolgreich
"; // Tabellen prüfen $tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN); echo "✓ Gefundene Tabellen: " . implode(", ", $tables) . "
"; } catch (PDOException $e) { echo "✗ Datenbankfehler: " . $e->getMessage() . "
"; } // 4. Includes prüfen echo "

4. Include-Dateien

"; $files = ['includes/Database.php', 'includes/Auth.php', 'includes/UniFiController.php']; foreach ($files as $file) { if (file_exists($file)) { echo "✓ $file existiert
"; try { require_once $file; echo "✓ $file geladen
"; } catch (Exception $e) { echo "✗ Fehler beim Laden von $file: " . $e->getMessage() . "
"; } } else { echo "✗ $file nicht gefunden!
"; } } // 5. Database-Klasse testen echo "

5. Database-Klasse

"; try { $db = Database::getInstance(); echo "✓ Database::getInstance() erfolgreich
"; $result = $db->fetchOne("SELECT COUNT(*) as count FROM users"); echo "✓ Anzahl Benutzer: " . $result['count'] . "
"; } catch (Exception $e) { echo "✗ Database-Fehler: " . $e->getMessage() . "
"; } // 6. Auth-Klasse testen echo "

6. Auth-Klasse

"; try { $auth = new Auth(); echo "✓ Auth-Klasse initialisiert
"; echo "Eingeloggt: " . ($auth->isLoggedIn() ? 'Ja' : 'Nein') . "
"; } catch (Exception $e) { echo "✗ Auth-Fehler: " . $e->getMessage() . "
"; } // 7. Session-Test echo "

7. Session

"; echo "Session Status: " . session_status() . " (1=disabled, 2=active)
"; echo "Session ID: " . session_id() . "
"; // 8. UniFi API Diagnose echo "

8. UniFi API Diagnose

"; try { $db2 = Database::getInstance(); $site = $db2->fetchOne("SELECT * FROM sites WHERE is_active = 1 ORDER BY id ASC LIMIT 1"); if (!$site) { echo "✗ Keine aktive Site in der Datenbank gefunden
"; } else { echo "Site: " . htmlspecialchars($site['name']) . "
"; echo "Controller URL: " . htmlspecialchars($site['unifi_controller_url']) . "
"; echo "Site ID: " . htmlspecialchars($site['site_id']) . "
"; echo "Username: " . htmlspecialchars($site['unifi_username']) . "
"; echo "
"; // --- Raw Login Test --- echo "Login-Test (raw cURL):
"; $cookieFile = tempnam(sys_get_temp_dir(), 'UNIFI_TEST_'); $csrfToken = null; $controllerUrl = rtrim($site['unifi_controller_url'], '/'); $ch = curl_init(); $responseHeaders = []; curl_setopt_array($ch, [ CURLOPT_URL => $controllerUrl . "/api/auth/login", CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ 'username' => $site['unifi_username'], 'password' => Crypto::decrypt($site['unifi_password']) ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_COOKIEJAR => $cookieFile, CURLOPT_COOKIEFILE => $cookieFile, CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_FOLLOWLOCATION => false, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Origin: ' . $controllerUrl, 'Referer: ' . $controllerUrl . '/login', ], CURLOPT_HEADERFUNCTION => function($ch, $header) use (&$csrfToken, &$responseHeaders) { $responseHeaders[] = rtrim($header); $parts = explode(':', $header, 2); if (count($parts) === 2 && strtolower(trim($parts[0])) === 'x-csrf-token') { $csrfToken = trim($parts[1]); } return strlen($header); } ]); $body = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlErr = curl_error($ch); $info = curl_getinfo($ch); curl_close($ch); if ($curlErr) { echo "✗ cURL Fehler: " . htmlspecialchars($curlErr) . "
"; } else { $icon = ($httpCode === 200) ? '✓' : '✗'; echo "$icon HTTP Code: $httpCode
"; echo "Effective URL: " . htmlspecialchars($info['url']) . "
"; } // Response headers echo "
Response-Header:
";
        foreach ($responseHeaders as $h) {
            if ($h !== '') echo htmlspecialchars($h) . "\n";
        }
        echo "
"; // CSRF token if ($csrfToken !== null) { echo "✓ X-CSRF-Token aus Header: " . htmlspecialchars($csrfToken) . "
"; } else { echo "✗ Kein X-CSRF-Token im Login-Response-Header gefunden
"; // Check cookie file fallback if (file_exists($cookieFile)) { $tokenFromCookie = null; foreach (file($cookieFile) as $line) { $line = trim($line); if ($line === '' || $line[0] === '#') continue; $parts = explode("\t", $line); if (count($parts) >= 7 && strtoupper($parts[5]) === 'TOKEN') { $tokenFromCookie = $parts[6]; } } if ($tokenFromCookie) { echo "✓ CSRF-Token aus Cookie-Datei (Fallback): " . htmlspecialchars($tokenFromCookie) . "
"; $csrfToken = $tokenFromCookie; } else { echo "✗ Auch kein TOKEN-Cookie in der Cookie-Datei gefunden
"; } } } // Response body echo "
Login Response Body:
";
        echo htmlspecialchars(substr($body, 0, 2000));
        echo "
"; // Cookie file contents if (file_exists($cookieFile)) { $cookieContents = file_get_contents($cookieFile); echo "Cookie-Datei:
";
            echo htmlspecialchars($cookieContents ?: '(leer — TOKEN hat Partitioned-Attribut, libcurl schreibt es nicht in die Jar-Datei)');
            echo "
"; } // Extract TOKEN from Set-Cookie header (the fix for Partitioned cookie issue) $tokenCookie = null; foreach ($responseHeaders as $h) { if (stripos($h, 'set-cookie:') === 0) { $cookieVal = trim(substr($h, strlen('set-cookie:'))); $cookieParts = explode(';', $cookieVal); $first = trim($cookieParts[0]); if (strpos($first, 'TOKEN=') === 0) { $tokenCookie = $first; } } } if ($tokenCookie) { echo "✓ TOKEN aus Set-Cookie-Header extrahiert: " . htmlspecialchars(substr($tokenCookie, 0, 40)) . "…
"; } else { echo "✗ TOKEN nicht in Set-Cookie-Header gefunden
"; } // --- API Test (only if login succeeded) --- if ($httpCode === 200) { echo "
API-Test (stat/voucher GET) — mit extrahiertem Cookie:
"; $apiHeaders = ['Content-Type: application/json']; if ($csrfToken !== null) { $apiHeaders[] = 'X-CSRF-Token: ' . $csrfToken; } $ch2 = curl_init(); $apiOpts = [ CURLOPT_URL => $controllerUrl . "/proxy/network/api/s/" . $site['site_id'] . "/stat/voucher", CURLOPT_HTTPGET => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_HTTPHEADER => $apiHeaders, ]; if ($tokenCookie !== null) { $apiOpts[CURLOPT_COOKIE] = $tokenCookie; } else { $apiOpts[CURLOPT_COOKIEFILE] = $cookieFile; } curl_setopt_array($ch2, $apiOpts); $apiBody = curl_exec($ch2); $apiCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE); $apiErr = curl_error($ch2); curl_close($ch2); if ($apiErr) { echo "✗ cURL Fehler: " . htmlspecialchars($apiErr) . "
"; } else { $icon2 = ($apiCode === 200) ? '✓' : '✗'; echo "$icon2 HTTP Code: $apiCode
"; } echo "API Response Body:
";
            echo htmlspecialchars(substr($apiBody, 0, 2000));
            echo "
"; } @unlink($cookieFile); } } catch (Exception $e) { echo "✗ Diagnose-Fehler: " . htmlspecialchars($e->getMessage()) . "
"; } echo "
"; echo "

✓ Test abgeschlossen

"; echo "

Zum Login | Zur Startseite

"; ?>