Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/ncssl/source/src/Service/CpanelApi/Adapter/CliAdapter.php

<?php

namespace App\Service\CpanelApi\Adapter;

use App\Service\NcPlugin\CreateUserSessionException;
use App\Service\NcPlugin\PluginException;
use App\Service\Whm\TokenStorageInterface;

class CliAdapter implements AdapterInterface
{
    private array $curl = [];
    public static ?string $username = null;
    private array $accessHash = [];
    private array $server = [];

    public function __construct(
        private readonly TokenStorageInterface $tokenStorage
    ) {
    }

    /**
     * @param $module
     * @param $func
     * @param array $args
     * @return array
     * @throws CreateUserSessionException
     * @throws PluginException
     * @throws \JsonException
     */
    public function call($module, $func, array $args = []): array
    {
        if (!isset($this->curl[self::$username], $this->accessHash[self::$username])) {
            $this->init();
        }

        $url = $this->server[self::$username] . $this->accessHash[self::$username] . '/execute/' . $module . '/' . $func;

        curl_setopt($this->getCurlHandle(), CURLOPT_URL, $url);
        curl_setopt($this->getCurlHandle(), CURLOPT_POST, true);
        if (count($args) > 0) {
            curl_setopt($this->getCurlHandle(), CURLOPT_POSTFIELDS, $args);
        }
        $res_str = curl_exec($this->getCurlHandle());
        curl_setopt($this->getCurlHandle(), CURLOPT_POST, false);
        curl_setopt($this->getCurlHandle(), CURLOPT_POSTFIELDS, []);

        if ($res_str === false) {
            throw new PluginException('cURL error during CpApi call: ' . curl_error($this->curl[self::$username]) . ' [' . curl_errno($this->curl[self::$username]) . ']');
        }

        $result = json_decode($res_str, true, 512, JSON_THROW_ON_ERROR);

        return array('cpanelresult' => array('result' => $result));
    }

    /**
     * @param $module
     * @param $func
     * @param array $args
     * @return mixed
     * @throws CreateUserSessionException
     * @throws PluginException
     * @throws \JsonException
     */
    public function callApi2($module, $func, array $args = []): mixed
    {
        if (!isset($this->curl[self::$username], $this->accessHash[self::$username])) {
            $this->init();
        }

        $params = array(
            'cpanel_jsonapi_user' => self::$username,
            'cpanel_jsonapi_module' => $module,
            'cpanel_jsonapi_func' => $func,
            'cpanel_jsonapi_apiversion' => 2,
        );
        $params = array_merge($args, $params);

        $url = 'https://localhost:2083' . $this->accessHash[self::$username] . '/json-api/cpanel?' . http_build_query($params);
        curl_setopt($this->getCurlHandle(), CURLOPT_URL, $url);
        $res_str = curl_exec($this->getCurlHandle());

        if ($res_str === false) {
            throw new PluginException('cURL error during CpApi call: ' . curl_error($this->getCurlHandle()) . ' [' . curl_errno($this->getCurlHandle()) . ']');
        }

        return json_decode($res_str, true, 512, JSON_THROW_ON_ERROR);
    }

    public function setUsername(string $username): void
    {
        self::$username = $username;
    }

    /**
     * @throws CreateUserSessionException
     * @throws PluginException
     * @throws \JsonException
     */
    private function init(): void
    {
        if (!self::$username) {
            throw new PluginException('User was not detected for CLI request');
        }

        $this->init_curl();

        curl_setopt($this->getCurlHandle(), CURLOPT_URL, "http://localhost:2086/json-api/create_user_session?api.version=1&user=" . self::$username . "&service=cpaneld");
        curl_setopt($this->getCurlHandle(), CURLOPT_POST, true);
        curl_setopt($this->getCurlHandle(), CURLOPT_HTTPHEADER, [
            sprintf('Authorization: WHM wh:%s', $this->tokenStorage->get())
        ]);
        $res_str = curl_exec($this->getCurlHandle());
        curl_setopt($this->getCurlHandle(), CURLOPT_POST, false);
        curl_setopt($this->getCurlHandle(), CURLOPT_HTTPHEADER, []);

        $session_data = json_decode($res_str, false, 512, JSON_THROW_ON_ERROR);

        if ($session_data === null) {
            throw new PluginException('WHM-style authentication failed. Cannot decode response: ' . $res_str);
        }

        if ($session_data->metadata->result === 0) {
            throw new CreateUserSessionException('WHM-style authentication failed. Cannot get user security token: ' . $session_data->metadata->reason);
        }

        $this->accessHash[self::$username] = $session_data->data->cp_security_token;

        if (!preg_match('#^(.+?)/cpsess#', $session_data->data->url, $matches)) {
            throw new PluginException('Cannot parse UAPI server from session data');
        }

        $this->server[self::$username] = $matches[1];

        //Get cookies for UAPI
        curl_setopt($this->getCurlHandle(), CURLOPT_HTTPHEADER, []);
        curl_setopt($this->getCurlHandle(), CURLOPT_POST, false);
        curl_setopt($this->getCurlHandle(), CURLOPT_URL, $session_data->data->url);
        curl_exec($this->getCurlHandle());
    }

    private function getCurlHandle(): \CurlHandle
    {
        return $this->curl[self::$username] ?? $this->curl[self::$username] = curl_init();
    }

    private function init_curl(): void
    {
        curl_setopt($this->getCurlHandle(), CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this->getCurlHandle(), CURLOPT_COOKIEFILE, '/dev/null');
        curl_setopt($this->getCurlHandle(), CURLOPT_COOKIEJAR, '/dev/null');
        curl_setopt($this->getCurlHandle(), CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->getCurlHandle(), CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($this->getCurlHandle(), CURLOPT_TIMEOUT, 600); // 10 minutes
    }

    public function __destruct()
    {
        foreach ($this->curl as $ii => $curl) {
            curl_close($this->curl[$ii]);
        }
    }
}
Back to Directory File Manager