diff --git a/modules/servers/VirtFusionDirect/admin.php b/modules/servers/VirtFusionDirect/admin.php index 5083d41..7270cba 100644 --- a/modules/servers/VirtFusionDirect/admin.php +++ b/modules/servers/VirtFusionDirect/admin.php @@ -26,17 +26,17 @@ switch ($vf->validateAction(true)) { $whmcsService = Database::getWhmcsService((int)$_GET['serviceID']); if (!$whmcsService) { - $vf->output(['success' => false, 'errors' => 'Service not found.'], true, true, 200); + $vf->output(['success' => false, 'errors' => 'Service not found.'], true, true, 404); } if ($whmcsService->domainstatus == 'Pending' || $whmcsService->domainstatus == 'Terminated' || $whmcsService->domainstatus == 'Cancelled' || $whmcsService->domainstatus == 'Fraud') { - $vf->output(['success' => false, 'errors' => 'Server is not Active, Suspended or Completed. Not fetching remote data.'], true, true, 200); + $vf->output(['success' => false, 'errors' => 'Server is not Active, Suspended or Completed. Not fetching remote data.'], true, true, 400); } $data = $vf->fetchServerData((int)$_GET['serviceID']); if (!$data) { - $vf->output(['success' => false, 'errors' => 'No data returned from VirtFusion.'], true, true, 200); + $vf->output(['success' => false, 'errors' => 'No data returned from VirtFusion.'], true, true, 502); } @@ -58,12 +58,21 @@ switch ($vf->validateAction(true)) { $service = Database::getSystemService((int)$_GET['serviceID']); if (!$service) { - $vf->output(['success' => false, 'errors' => 'Service not found'], true, true, 200); + $vf->output(['success' => false, 'errors' => 'Service not found'], true, true, 404); } $whmcsService = Database::getWhmcsService((int)$_GET['serviceID']); + if (!$whmcsService) { + $vf->output(['success' => false, 'errors' => 'WHMCS service not found'], true, true, 404); + } + $cp = $vf->getCP($whmcsService->server); + + if (!$cp) { + $vf->output(['success' => false, 'errors' => 'Control server not found'], true, true, 500); + } + $request = $vf->initCurl($cp['token']); $data = $request->get($cp['url'] . '/users/' . $whmcsService->userid . '/byExtRelation'); @@ -72,7 +81,7 @@ switch ($vf->validateAction(true)) { $vf->output(['success' => true, 'url' => $cp['base_url'], 'user' => json_decode($data, true)['data']], true, true, 200); } - $vf->output(['success' => false, 'errors' => 'Received HTTP code ' . $request->getRequestInfo('http_code')], true, true, 200); + $vf->output(['success' => false, 'errors' => 'Received HTTP code ' . $request->getRequestInfo('http_code')], true, true, 502); } break; @@ -80,6 +89,5 @@ switch ($vf->validateAction(true)) { default: /** No valid action was specified **/ - $vf->output(['success' => false, 'errors' => 'invalid action'], true, true, 200); + $vf->output(['success' => false, 'errors' => 'invalid action'], true, true, 400); } - diff --git a/modules/servers/VirtFusionDirect/hooks.php b/modules/servers/VirtFusionDirect/hooks.php index a08d861..93e3a04 100644 --- a/modules/servers/VirtFusionDirect/hooks.php +++ b/modules/servers/VirtFusionDirect/hooks.php @@ -207,7 +207,7 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) { }); "; - } catch (\Exception $e) { + } catch (\Throwable $e) { // Silently fail - don't break the checkout page return null; } diff --git a/modules/servers/VirtFusionDirect/lib/ConfigureService.php b/modules/servers/VirtFusionDirect/lib/ConfigureService.php index 3f5d433..4c68f38 100644 --- a/modules/servers/VirtFusionDirect/lib/ConfigureService.php +++ b/modules/servers/VirtFusionDirect/lib/ConfigureService.php @@ -26,6 +26,8 @@ class ConfigureService extends Module */ public function fetchPackageId(string $packageName): ?int { + if (!$this->cp) return null; + $request = $this->initCurl($this->cp['token']); $response = $request->get( @@ -70,6 +72,8 @@ class ConfigureService extends Module return null; } + if (!$this->cp) return null; + $request = $this->initCurl($this->cp['token']); $response = $request->get( @@ -90,10 +94,14 @@ class ConfigureService extends Module return null; } + if (!$this->cp) return null; + $request = $this->initCurl($this->cp['token']); $vfUser = $this->getVFUserDetails($user['id']); + if (!$vfUser) return null; + $response = $request->get( sprintf("%s/ssh_keys/user/%d", $this->cp['url'], $vfUser['id']) ); @@ -108,6 +116,8 @@ class ConfigureService extends Module */ public function getVFUserDetails(int $id): ?array { + if (!$this->cp) return null; + $request = $this->initCurl($this->cp['token']); $response = $this->decodeResponseFromJson($request->get( @@ -124,30 +134,35 @@ class ConfigureService extends Module */ public function initServerBuild(int $id, array $vars): bool { + if (!$this->cp) return false; + $request = $this->initCurl($this->cp['token']); // Generate a random 8 character hostname $hostname = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 8); $inputData = [ - "operatingSystemId" => $vars['customfields']['Initial Operating System'], + "operatingSystemId" => $vars['customfields']['Initial Operating System'] ?? null, "name" => $hostname, "sshKeys" => [ - $vars['customfields']['Initial SSH Key'] + $vars['customfields']['Initial SSH Key'] ?? null ], 'email' => true ]; - if (empty($vars['customfields']['Initial SSH Key'])) { + if (empty($vars['customfields']['Initial SSH Key'] ?? null)) { unset($inputData['sshKeys']); } $request->addOption(CURLOPT_POSTFIELDS, json_encode($inputData)); - $request->post( + $response = $request->post( sprintf("%s/servers/%d/build", $this->cp['url'], $id) ); - return true; + $httpCode = $request->getRequestInfo('http_code'); + Log::insert(__FUNCTION__, $request->getRequestInfo(), $response); + + return ($httpCode == 200 || $httpCode == 201); } -} \ No newline at end of file +} diff --git a/modules/servers/VirtFusionDirect/lib/Curl.php b/modules/servers/VirtFusionDirect/lib/Curl.php index fe537d6..5e904f6 100644 --- a/modules/servers/VirtFusionDirect/lib/Curl.php +++ b/modules/servers/VirtFusionDirect/lib/Curl.php @@ -77,7 +77,7 @@ class Curl { if ($url === null) { if (!isset($this->customOptions[CURLOPT_URL]) || empty($this->customOptions[CURLOPT_URL])) { - exit('empty url'); + throw new \RuntimeException('Curl: empty URL provided'); } } $this->addOption(CURLOPT_CUSTOMREQUEST, $method); diff --git a/modules/servers/VirtFusionDirect/lib/Module.php b/modules/servers/VirtFusionDirect/lib/Module.php index 66f5e21..ca7fc37 100644 --- a/modules/servers/VirtFusionDirect/lib/Module.php +++ b/modules/servers/VirtFusionDirect/lib/Module.php @@ -66,8 +66,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/users/' . (int) $whmcsService->userid . '/serverAuthenticationTokens/' . (int) $service->server_id); @@ -124,7 +127,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id); @@ -156,7 +163,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/power/' . $action); @@ -191,7 +202,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $buildData = [ @@ -236,7 +251,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['name' => $newName])); @@ -263,7 +282,10 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; $product = \WHMCS\Database\Capsule::table('tblproducts')->where('id', $whmcsService->packageid)->first(); if (!$product || !$product->configoption2) { @@ -322,7 +344,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id . '/firewall/' . $interface); @@ -350,7 +376,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/firewall/' . $interface . '/enable'); @@ -379,7 +409,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/firewall/' . $interface . '/disable'); @@ -422,7 +456,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['rulesets' => $rulesetIds])); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/firewall/' . $interface . '/rules'); @@ -463,7 +501,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['rulesets' => []])); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/firewall/' . $interface . '/rules'); @@ -506,7 +548,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/ipv4'); @@ -539,7 +585,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['address' => $ipAddress])); $data = $request->delete($cp['url'] . '/servers/' . (int) $service->server_id . '/ipv4'); @@ -567,7 +617,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/ipv6'); @@ -600,7 +654,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['subnet' => $subnet])); $data = $request->delete($cp['url'] . '/servers/' . (int) $service->server_id . '/ipv6'); @@ -635,7 +693,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode(['planId' => $planId])); @@ -672,7 +734,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id . '/vnc'); @@ -714,7 +780,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $request->addOption(CURLOPT_POSTFIELDS, json_encode([$resource => $value])); $data = $request->put($cp['url'] . '/servers/' . (int) $service->server_id . '/modify/' . $resource); @@ -780,7 +850,11 @@ class Module if ($service) { $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/users/' . $clientID . '/byExtRelation/resetPassword'); diff --git a/modules/servers/VirtFusionDirect/lib/ModuleFunctions.php b/modules/servers/VirtFusionDirect/lib/ModuleFunctions.php index 85a80e5..1bab6ff 100644 --- a/modules/servers/VirtFusionDirect/lib/ModuleFunctions.php +++ b/modules/servers/VirtFusionDirect/lib/ModuleFunctions.php @@ -183,7 +183,11 @@ class ModuleFunctions extends Module if ($service) { $whmcsService = Database::getWhmcsService($params['serviceid']); + if (!$whmcsService) return 'WHMCS service record not found.'; + $cp = $this->getCP($whmcsService->server); + if (!$cp) return 'No control server found.'; + $request = $this->initCurl($cp['token']); $data = $request->put($cp['url'] . '/servers/' . (int) $service->server_id . '/package/' . (int) $params['configoption2']); $data = json_decode($data); @@ -224,8 +228,10 @@ class ModuleFunctions extends Module if ($service) { $whmcsService = Database::getWhmcsService($params['serviceid']); + if (!$whmcsService) return 'WHMCS service record not found.'; $cp = $this->getCP($whmcsService->server); + if (!$cp) return 'No control server found.'; $request = $this->initCurl($cp['token']); $data = $request->delete($cp['url'] . '/servers/' . (int) $service->server_id); @@ -275,8 +281,11 @@ class ModuleFunctions extends Module if ($service) { $whmcsService = Database::getWhmcsService($params['serviceid']); + if (!$whmcsService) return 'WHMCS service record not found.'; $cp = $this->getCP($whmcsService->server); + if (!$cp) return 'No control server found.'; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/suspend'); $data = json_decode($data); @@ -319,8 +328,11 @@ class ModuleFunctions extends Module if ($service) { $whmcsService = Database::getWhmcsService($params['serviceid']); + if (!$whmcsService) return 'WHMCS service record not found.'; $cp = $this->getCP($whmcsService->server); + if (!$cp) return 'No control server found.'; + $request = $this->initCurl($cp['token']); $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id); $data = json_decode($data); @@ -349,8 +361,11 @@ class ModuleFunctions extends Module if ($service) { $whmcsService = Database::getWhmcsService($params['serviceid']); + if (!$whmcsService) return 'WHMCS service record not found.'; $cp = $this->getCP($whmcsService->server); + if (!$cp) return 'No control server found.'; + $request = $this->initCurl($cp['token']); $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/unsuspend'); $data = json_decode($data); diff --git a/modules/servers/VirtFusionDirect/lib/ServerResource.php b/modules/servers/VirtFusionDirect/lib/ServerResource.php index a5e1e81..d30fa29 100644 --- a/modules/servers/VirtFusionDirect/lib/ServerResource.php +++ b/modules/servers/VirtFusionDirect/lib/ServerResource.php @@ -56,14 +56,14 @@ class ServerResource $data['primaryNetwork']['mac'] = $server['network']['interfaces'][0]['mac']; } - if (count($server['network']['interfaces'][0]['ipv4'])) { + if (isset($server['network']['interfaces'][0]['ipv4']) && count($server['network']['interfaces'][0]['ipv4'])) { $data['primaryNetwork']['ipv4'] = []; foreach ($server['network']['interfaces'][0]['ipv4'] as $ip) { $data['primaryNetwork']['ipv4'][] = $ip['address']; } } - if (count($server['network']['interfaces'][0]['ipv6'])) { + if (isset($server['network']['interfaces'][0]['ipv6']) && count($server['network']['interfaces'][0]['ipv6'])) { $data['primaryNetwork']['ipv6'] = []; foreach ($server['network']['interfaces'][0]['ipv6'] as $ip) { $data['primaryNetwork']['ipv6'][] = $ip['subnet'] . '/' . $ip['cidr']; diff --git a/modules/servers/VirtFusionDirect/templates/js/module.js b/modules/servers/VirtFusionDirect/templates/js/module.js index a7fe4da..4f41a44 100644 --- a/modules/servers/VirtFusionDirect/templates/js/module.js +++ b/modules/servers/VirtFusionDirect/templates/js/module.js @@ -466,6 +466,9 @@ function vfOpenVnc(serviceId, systemUrl) { spinner.show(); alertDiv.hide(); + // Open window immediately in click context to avoid popup blockers + var vncWindow = window.open("", "_blank"); + $.ajax({ type: "GET", dataType: "json", @@ -474,25 +477,28 @@ function vfOpenVnc(serviceId, systemUrl) { if (response.success && response.data) { var data = response.data.data || response.data; if (data.url) { - window.open(data.url, "_blank"); + vncWindow.location.href = data.url; } else if (data.host && data.port) { // Build noVNC URL if available var vncUrl = "https://" + data.host + ":" + data.port; if (data.token) { vncUrl += "?token=" + encodeURIComponent(data.token); } - window.open(vncUrl, "_blank"); + vncWindow.location.href = vncUrl; } else { + vncWindow.close(); alertDiv.removeClass("alert-danger").addClass("alert-success"); alertDiv.text("VNC session is ready. Check your VirtFusion control panel for access."); alertDiv.show(); } } else { + vncWindow.close(); alertDiv.removeClass("alert-success").addClass("alert-danger"); alertDiv.text(response.errors || "VNC console is not available."); alertDiv.show(); } }).fail(function () { + vncWindow.close(); alertDiv.removeClass("alert-success").addClass("alert-danger"); alertDiv.text("An error occurred. The server may be powered off."); alertDiv.show();