first commit
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
require_once __DIR__ . '/../class/db-functions.php';
|
||||
|
||||
$db = DBHandlerSelect::getInstance()->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());
|
||||
}
|
||||
Reference in New Issue
Block a user