getConnection(); function jsonResponse(bool $success, string $message, array $extra = []): void { echo json_encode(array_merge([ 'success' => $success, 'message' => $message ], $extra)); exit; } function getCyberpanelEncryptionKey(): string { return hash('sha256', 'CHANGE_THIS_SECRET_KEY_FOR_CYBERPANEL_DASHBOARD'); } function decryptCyberpanelPassword(string $encryptedPassword): string { if ($encryptedPassword === '') { return ''; } $key = getCyberpanelEncryptionKey(); $decoded = base64_decode($encryptedPassword); if (!$decoded || strpos($decoded, '::') === false) { return ''; } [$ivBase64, $encrypted] = explode('::', $decoded, 2); $iv = base64_decode($ivBase64); if (!$iv) { return ''; } $decrypted = openssl_decrypt( $encrypted, 'AES-256-CBC', $key, 0, $iv ); return $decrypted ?: ''; } function callCyberPanelApi(string $panelUrl, string $endpoint, string $username, string $password, array $extraPayload = []): array { $apiUrl = rtrim($panelUrl, '/') . '/api/' . ltrim($endpoint, '/'); $payload = array_merge([ 'adminUser' => $username, 'adminPass' => $password ], $extraPayload); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $apiUrl, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json' ], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 25, CURLOPT_CONNECTTIMEOUT => 15, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false ]); $response = curl_exec($ch); $curlError = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($response === false || $curlError !== '') { return [ 'success' => false, 'endpoint' => $endpoint, 'http_code' => $httpCode, 'error' => $curlError, 'raw' => null, 'data' => null ]; } $decoded = json_decode($response, true); if (!is_array($decoded)) { return [ 'success' => false, 'endpoint' => $endpoint, 'http_code' => $httpCode, 'error' => 'Invalid JSON response', 'raw' => substr($response, 0, 1000), 'data' => null ]; } return [ 'success' => true, 'endpoint' => $endpoint, 'http_code' => $httpCode, 'error' => null, 'raw' => $response, 'data' => $decoded ]; } function extractPackages(array $data): array { /* * CyberPanel responses may vary between versions. * We support multiple possible structures. */ if (isset($data['data']) && is_array($data['data'])) { return $data['data']; } if (isset($data['packages']) && is_array($data['packages'])) { return $data['packages']; } if (isset($data['listPackages']) && is_array($data['listPackages'])) { return $data['listPackages']; } if (isset($data['packageList']) && is_array($data['packageList'])) { return $data['packageList']; } /* * Some CyberPanel versions may return associative keys directly. */ foreach ($data as $key => $value) { if (is_array($value)) { return $value; } } return []; } function getValue(array $item, array $keys, string $default = ''): string { foreach ($keys as $key) { if (isset($item[$key]) && $item[$key] !== '') { return (string)$item[$key]; } } return $default; } try { $serverId = isset($_POST['server_id']) ? (int)$_POST['server_id'] : 0; if ($serverId <= 0) { jsonResponse(false, 'Missing server ID.'); } $stmt = $db->prepare(" SELECT id, name, panel_url, username, password_encrypted, api_enabled FROM cyberpanel_servers WHERE id = :id LIMIT 1 "); $stmt->execute([ ':id' => $serverId ]); $server = $stmt->fetch(PDO::FETCH_ASSOC); if (!$server) { jsonResponse(false, 'Server not found.'); } if ((int)$server['api_enabled'] !== 1) { jsonResponse(false, 'API is disabled for this server.'); } $password = decryptCyberpanelPassword($server['password_encrypted']); if ($password === '') { jsonResponse(false, 'Saved password is empty or cannot be decrypted.'); } $versionResult = callCyberPanelApi( $server['panel_url'], 'cyberPanelVersion', $server['username'], $password ); $packagesResult = callCyberPanelApi( $server['panel_url'], 'listPackage', $server['username'], $password ); if (!$packagesResult['success']) { jsonResponse(false, 'Unable to load packages from CyberPanel API.', [ 'packages_result' => $packagesResult, 'version_result' => $versionResult ]); } $packages = extractPackages($packagesResult['data']); $db->prepare("DELETE FROM cyberpanel_packages WHERE server_id = :server_id") ->execute([':server_id' => $serverId]); $insert = $db->prepare(" INSERT INTO cyberpanel_packages ( server_id, package_name, disk_space, bandwidth, email_accounts, ftp_accounts, databases_count, domains_count, raw_json, last_sync ) VALUES ( :server_id, :package_name, :disk_space, :bandwidth, :email_accounts, :ftp_accounts, :databases_count, :domains_count, :raw_json, NOW() ) "); $inserted = 0; foreach ($packages as $package) { if (!is_array($package)) { continue; } $packageName = getValue($package, [ 'packageName', 'package_name', 'name', 'package' ], 'Unknown package'); $insert->execute([ ':server_id' => $serverId, ':package_name' => $packageName, ':disk_space' => getValue($package, ['diskSpace', 'disk_space', 'disk', 'space']), ':bandwidth' => getValue($package, ['bandwidth', 'bw']), ':email_accounts' => getValue($package, ['emailAccounts', 'email_accounts', 'emails']), ':ftp_accounts' => getValue($package, ['ftpAccounts', 'ftp_accounts', 'ftp']), ':databases_count' => getValue($package, ['dataBases', 'databases', 'databases_count', 'db']), ':domains_count' => getValue($package, ['domains', 'domains_count']), ':raw_json' => json_encode($package) ]); $inserted++; } $version = null; if ($versionResult['success']) { $versionData = $versionResult['data']; if (isset($versionData['version'])) { $version = (string)$versionData['version']; } elseif (isset($versionData['currentVersion'])) { $version = (string)$versionData['currentVersion']; } elseif (isset($versionData['cyberPanelVersion'])) { $version = (string)$versionData['cyberPanelVersion']; } } $updateServer = $db->prepare(" UPDATE cyberpanel_servers SET last_status = 'online', last_check = NOW(), cyberpanel_version = :cyberpanel_version, packages_count = :packages_count WHERE id = :server_id "); $updateServer->execute([ ':cyberpanel_version' => $version, ':packages_count' => $inserted, ':server_id' => $serverId ]); jsonResponse(true, 'Native CyberPanel API data synced successfully.', [ 'server_id' => $serverId, 'cyberpanel_version' => $version, 'packages_count' => $inserted, 'packages_raw_response' => $packagesResult['data'] ]); } catch (Throwable $e) { jsonResponse(false, 'Native API sync error: ' . $e->getMessage()); }