first commit
This commit is contained in:
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
||||
|
||||
use Duplicator\Libs\Snap\SnapURL;
|
||||
|
||||
/**
|
||||
* A stub for returning an object
|
||||
*/
|
||||
class DUPX_API_REQUEST
|
||||
{
|
||||
/** @var array{operation:string,process_time:string} */
|
||||
public $report = ['operation' => '', 'process_time' => ''];
|
||||
/** @var mixed */
|
||||
public $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A stub for returning an object error response from a failed request
|
||||
*/
|
||||
class DUPX_API_ERROR
|
||||
{
|
||||
/** @var string */
|
||||
public $request = '';
|
||||
/** @var string */
|
||||
public $message = '';
|
||||
/** @var string */
|
||||
public $exception = '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The DUPX_API_ROUTE object is a routable object that the DUPX_API_SERVER
|
||||
* uses to help convert methods to routable service calls.
|
||||
*
|
||||
* In order for a classes method to become routeable the following route
|
||||
* tag must be delcated in the comments section of the method in the format
|
||||
* below with {} brackets around that name of the actual paramter.
|
||||
*
|
||||
* <route template="/category/example_method/{param1}/{param2}/{list*}/" type="request">
|
||||
*
|
||||
* TEMPLATE ATTRIBUTE:
|
||||
* When called via an http request the paramter name should be substituted
|
||||
* with the actual value for the parameter such as
|
||||
*
|
||||
* /category/example_method/1/test/a,b,c/
|
||||
*
|
||||
* Supported parameter types:
|
||||
* {param1} = string type
|
||||
* example: /test/ or /1/
|
||||
*
|
||||
* {list*} = array type
|
||||
* example: /1,2,3/ or /a,b,c/
|
||||
*
|
||||
* TYPE ATTRIBUTE:
|
||||
* The attribute type="request" is used to determine where the request values
|
||||
* are retrived from. The default is "request" meaning it looks for:
|
||||
* PATH, GET, POST in that order. If you want the request to only look
|
||||
* for GET requets then set the attribute to type="get"
|
||||
*/
|
||||
class DUPX_API_ROUTE
|
||||
{
|
||||
/** @var string */
|
||||
public $template = '';
|
||||
/** @var string */
|
||||
public $type = '';
|
||||
/** @var string */
|
||||
public $operation = '';
|
||||
/** @var array<string,mixed> */
|
||||
public $params = [];
|
||||
/** @var string */
|
||||
public $class_method = '';
|
||||
/** @var string */
|
||||
public $class_name = '';
|
||||
/** @var ?object */
|
||||
public $class_instance;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The DUPX_API_SERVER object is used to listen for and process
|
||||
* routable template calls. The root for this api stack starts with
|
||||
* https://website.com/dup-installer/api/router.php/cpnl/create_token/
|
||||
*
|
||||
* This will display the GUI for the api and is the starting point
|
||||
* for processing api requets.
|
||||
*
|
||||
* <code>
|
||||
* //Register API Engine
|
||||
* $API_SERVER = new DUPX_API_SERVER();
|
||||
* $API_SERVER->add_controller(new MyClass());
|
||||
* $API_SERVER->process_request();
|
||||
* </code>
|
||||
*/
|
||||
class DUPX_API_Server
|
||||
{
|
||||
/** @var object[] */
|
||||
public $controllers = [];
|
||||
public $uri_found;
|
||||
public $uri_match;
|
||||
public $args_in = [];
|
||||
public $args_map = [];
|
||||
public $exe_route;
|
||||
public $api_enabled = false;
|
||||
|
||||
/**
|
||||
* Called to begin listening to all requests made through the router.php request.
|
||||
* If the inbound request is found it will process the service request.
|
||||
*
|
||||
* @param bool $debug Turn debugging on/off
|
||||
*
|
||||
* An example of a request URL is:
|
||||
* //localhost/dup-installer/api/router.php/cpnl/create_token/{host}/{user}/{pass}/
|
||||
*/
|
||||
public function process_request($debug = false): void
|
||||
{
|
||||
$url_route = $this->get_active_url_route();
|
||||
$this->exe_route = $this->find_controller($url_route);
|
||||
|
||||
//API process: Invalid route requested
|
||||
if (!$this->exe_route) {
|
||||
/* TODO: Find clean way to provide validation message
|
||||
$url = urldecode($url_route);
|
||||
$log = "WARNING: Unable to find a matching controller at this route:<br/>\n {$url}<br/>\n";
|
||||
$log .= "Be sure that all controllers are properly using a <route> directive";
|
||||
echo $log; */
|
||||
return;
|
||||
}
|
||||
|
||||
$this->uri_found = $url_route;
|
||||
$this->uri_match = $this->exe_route->operation;
|
||||
$this->args_map = $this->process_args();
|
||||
|
||||
if ($debug) {
|
||||
$this->debug_info();
|
||||
}
|
||||
|
||||
$api_request = new DUPX_API_REQUEST();
|
||||
|
||||
try {
|
||||
$time_start = microtime(true);
|
||||
$rfl_method = new ReflectionMethod($this->exe_route->class_name, $this->exe_route->class_method);
|
||||
$result = $rfl_method->invokeArgs($this->exe_route->class_instance, $this->args_map);
|
||||
$result = (DUPX_U::isJSON($result)) ? json_decode($result) : $result;
|
||||
|
||||
//Return results as JSON
|
||||
$api_request->report['process_time'] = microtime(true) - $time_start;
|
||||
$api_request->report['operation'] = $this->exe_route->operation;
|
||||
$api_request->result = $result;
|
||||
|
||||
if (!headers_sent()) {
|
||||
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||
header("Pragma: no-cache");
|
||||
header('Content-Type: application/json');
|
||||
}
|
||||
|
||||
echo json_encode($api_request);
|
||||
exit;
|
||||
}
|
||||
catch (Exception $ex) {
|
||||
$err = new DUPX_API_ERROR();
|
||||
$err->request = $this->exe_route->class_method;
|
||||
$err->message = $ex->getMessage();
|
||||
$err->exception = $ex->__toString();
|
||||
echo json_encode($err);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display debug info about an inbound service request
|
||||
*/
|
||||
public function debug_info(): void
|
||||
{
|
||||
echo '<pre>';
|
||||
echo 'FOUND: '.$this->uri_found.'<br/>';
|
||||
echo 'MATCHED: '.$this->uri_match.'<br/>';
|
||||
echo 'INPUTS:';
|
||||
DUPX_U::dump($this->args_in);
|
||||
echo 'INPUT MAP:';
|
||||
DUPX_U::dump($this->args_map);
|
||||
DUPX_U::dump($this->exe_route, true);
|
||||
echo '<br/> RESULT: <br/>';
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller classes are the heart of the web services. Add a controller
|
||||
* to allow service methods to be exposed via the /api/router.php
|
||||
* Example of controller class is: class.cpnl.ctrl.php
|
||||
*/
|
||||
public function add_controller($class): bool
|
||||
{
|
||||
$rfl = new ReflectionClass($class);
|
||||
$cls_name = $rfl->getName();
|
||||
$cls_methods = $rfl->getMethods();
|
||||
|
||||
if (in_array($cls_name, $this->controllers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($cls_methods as $m) {
|
||||
$comments = $m->getDocComment();
|
||||
$route_elm = $this->get_tag_attributes('route', $comments);
|
||||
if ($route_elm != null) {
|
||||
$route = new DUPX_API_ROUTE();
|
||||
$route->type = $route_elm['type'] ?? 'request';
|
||||
$route->template = $route_elm['template'] ?? '';
|
||||
|
||||
//Check for duplicate operation
|
||||
if ($this->find_controller($route->operation)) {
|
||||
throw new Exception("Duplicate route tag operation '{$route->operation}'! See tag <route tempalte='{$route->template}' > in class {$cls_name}");
|
||||
}
|
||||
|
||||
$route->operation = $this->get_operation($route_elm['template']);
|
||||
$route->params = $this->get_params($route->template, $route->operation);
|
||||
$route->class_method = $m->getName();
|
||||
$route->class_instance = $class;
|
||||
$route->class_name = $cls_name;
|
||||
$this->controllers[] = $route;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the uri defined template args
|
||||
* with the inbound args, PATH, GET, POST
|
||||
*/
|
||||
private function process_args()
|
||||
{
|
||||
$args_map = [];
|
||||
$params = empty($this->exe_route->params) ? null : $this->exe_route->params;
|
||||
if ($params == null) {
|
||||
return $args_map;
|
||||
}
|
||||
$args_map = $params;
|
||||
$args_map = array_map(fn($n) => null, $args_map);
|
||||
|
||||
// <route template="/cpnl/is_active/{cpnl-host}/{arg1}/{list*}" type="request">
|
||||
//REQUEST: Post, Get, Path
|
||||
//PATH: Path
|
||||
//GET: Get
|
||||
//POST: Post
|
||||
$uri_params = substr($this->uri_found, strlen($this->uri_match));
|
||||
$this->args_in['PATH'] = array_filter(explode("/", preg_replace('/\?.*/', '', $uri_params)));
|
||||
$this->args_in['GET'] = $_GET;
|
||||
$this->args_in['POST'] = $_POST;
|
||||
|
||||
switch (strtoupper($this->exe_route->type)) {
|
||||
case 'POST' : $args_map = array_merge($args_map, $this->args_in['POST']);
|
||||
break;
|
||||
case 'GET' : $args_map = array_merge($args_map, $this->args_in['GET']);
|
||||
break;
|
||||
case 'PATH' : $args_map = $this->args_map_merge($args_map);
|
||||
break;
|
||||
default :
|
||||
$args_map = array_merge($args_map, $this->args_in['POST']);
|
||||
$args_map = array_merge($args_map, $this->args_in['GET']);
|
||||
$args_map = $this->args_map_merge($args_map);
|
||||
}
|
||||
|
||||
//Only returned the params defined
|
||||
$length = count($this->exe_route->params);
|
||||
$args_map = array_slice($args_map, 0, $length);
|
||||
|
||||
return array_map('urldecode', $args_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creats the args map needed for the final args results
|
||||
*/
|
||||
private function args_map_merge(array $args_map): array
|
||||
{
|
||||
$keys = array_keys($args_map);
|
||||
foreach ($this->args_in['PATH'] as $k => $v) {
|
||||
$args_map[$keys[$k]] = $v;
|
||||
}
|
||||
return $args_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will look through all of the registerd controllers
|
||||
* and find the correct controller based on the request
|
||||
*/
|
||||
private function find_controller($template)
|
||||
{
|
||||
if (empty($this->controllers)) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->controllers as $controller) {
|
||||
if (strstr($template, (string) $controller->operation)) {
|
||||
return $controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameters from a uri template
|
||||
* example: "/cpnl/is_active/{host}?s=1"
|
||||
* returns: array('host' => '', 's' => 1);
|
||||
* @return 'list'[]|'string'[]
|
||||
*/
|
||||
private function get_params($template, ?string $operation): array
|
||||
{
|
||||
$paths = str_replace($operation, '', $template);
|
||||
$paths = array_filter(explode("/", $paths));
|
||||
$params = [];
|
||||
foreach ($paths as $p) {
|
||||
$type = strpos($p, '*') ? 'list' : 'string';
|
||||
$name = $type == 'list' ? trim($p, '{*}') : trim($p, '{}');
|
||||
$params[$name] = $type;
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base operation portion of a template
|
||||
* example: "http://site.com/instatller.php/cpnl/is_active/1/category/a,b,c"
|
||||
* returns: "/cpnl/is_active/host?s=1"
|
||||
*/
|
||||
private function get_active_url_route(): string
|
||||
{
|
||||
$file = 'router.php';
|
||||
$url_path = strstr(SnapURL::getCurrentUrl(true, true), $file);
|
||||
return str_replace($file, '', $url_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base operation portion of a template
|
||||
* example: "/cpnl/is_active/host?s=1"
|
||||
* returns: "/cpnl/is_active/"
|
||||
*/
|
||||
private function get_operation($template): ?string
|
||||
{
|
||||
$routes = explode("/", $template);
|
||||
$ops = [];
|
||||
|
||||
if ($routes == false) {
|
||||
return null;
|
||||
}
|
||||
//remove parameters
|
||||
foreach ($routes as $r) {
|
||||
if (preg_match("/^[a-zA-Z0-9_\-]+$/", $r)) {
|
||||
$ops[] = $r;
|
||||
}
|
||||
}
|
||||
return '/'.implode('/', $ops).'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a tag element in a string and parses its attributes
|
||||
* example: Finds <route> element and returns its attributes
|
||||
*/
|
||||
private function get_tag_attributes(string $element_name, $string)
|
||||
{
|
||||
if ($string == false) {
|
||||
return;
|
||||
}
|
||||
// Grab the string of attr inside an element tag.
|
||||
$found = preg_match('#<'.$element_name.'\s+([^>]+(?:"|\'))\s?/?>#', $string, $matches);
|
||||
if ($found == 1) {
|
||||
// Match attr-name attribute-value pairs.
|
||||
$attr_array = [];
|
||||
$attr_string = $matches[1];
|
||||
$found = preg_match_all('#([^\s=]+)\s*=\s*(\'[^<\']*\'|"[^<"]*")#', $attr_string, $matches, PREG_SET_ORDER);
|
||||
if ($found != 0) {
|
||||
// Create an associative array that matches attr names to attr values.
|
||||
foreach ($matches as $att) {
|
||||
$attr_array[$att[1]] = substr($att[2], 1, -1);
|
||||
}
|
||||
return $attr_array;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
||||
//This class is called through both the router.php and main.installer.php
|
||||
//Full Path: {DUPX_INIT}/api/
|
||||
require_once("class.cpnl.base.php");
|
||||
/**
|
||||
* Class used to store cPanel host information
|
||||
* */
|
||||
class DUPX_cPanelHost
|
||||
{
|
||||
/** @var string */
|
||||
public $url = '';
|
||||
/** @var string */
|
||||
public $host = '';
|
||||
/** @var string */
|
||||
public $scheme = '';
|
||||
/** @var int */
|
||||
public $port = 0;
|
||||
/** @var string */
|
||||
public $user = '';
|
||||
/** @var string */
|
||||
public $pass = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper Class for cPanel API
|
||||
*
|
||||
* <routable> */
|
||||
class DUPX_cPanel_Controller
|
||||
{
|
||||
/** @var ?CPNL_API */
|
||||
private $api;
|
||||
|
||||
/**
|
||||
* Creates a security token to access the cPanel calls
|
||||
* @param string $host The cPanel host name can be full url or just domain name
|
||||
* https://mysite.com:2083, https://mysite.com, mysite.com
|
||||
* @param string $user A valid cPanel user name
|
||||
* @param string $pass A valid cPanel user password
|
||||
* @return string A base64 encoded string of the input params
|
||||
*
|
||||
* <route template="/cpnl/create_token/{host}/{user}/{pass}/">
|
||||
*/
|
||||
public function create_token($host, $user, $pass): string
|
||||
{
|
||||
if (substr($host, 0, 4) !== 'http') {
|
||||
$host = 'https://' . $host;
|
||||
}
|
||||
|
||||
$url = parse_url($host);
|
||||
$host = $url['host'] ?? null;
|
||||
if (is_null($host)) {
|
||||
throw new Exception('The create_token operation requires a valid host parameter');
|
||||
}
|
||||
if (!$user) {
|
||||
throw new Exception('The create_token operation requires a valid user parameter');
|
||||
}
|
||||
if (!$pass) {
|
||||
throw new Exception('The create_token operation requires a valid password parameter');
|
||||
}
|
||||
|
||||
$scheme = $url['scheme'] ?? 'https';
|
||||
$port = $url['port'] ?? '2083';
|
||||
return base64_encode("{$scheme},{$host},{$port},{$user},{$pass}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the host information about this cpanel server
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @return DUPX_cPanelHost A DUPX_cPanelHost object
|
||||
*
|
||||
* <route template="/cpnl/get_host/{token}/">
|
||||
*/
|
||||
public function get_host($token): \DUPX_cPanelHost
|
||||
{
|
||||
$host = new DUPX_cPanelHost();
|
||||
$creds = explode(",", base64_decode($token));
|
||||
if (!isset($creds[1])) {
|
||||
throw new Exception("Invalid hostname detected for get_host with token: $token");
|
||||
}
|
||||
|
||||
$host->scheme = $creds[0];
|
||||
$host->host = $creds[1];
|
||||
$host->port = (int) $creds[2];
|
||||
$host->user = $creds[3];
|
||||
$host->pass = $creds[4];
|
||||
$host->url = "{$host->scheme}://{$host->host}:{$host->port}";
|
||||
return $host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setup data needed for validating and show DB information
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @return array $data['valid_host'] Is the url a valid cpanel URL
|
||||
* $data['valid_user'] Is the user a valid cpanel user
|
||||
* $data['is_prefix_on'] Does the cpanel use a DB prefix
|
||||
* $data['dbinfo'] A list of databases and info
|
||||
* $data['dbusers'] A list of database users
|
||||
*
|
||||
* <route template="/cpnl/get_setup_data/{token}/">
|
||||
*/
|
||||
public function get_setup_data($token): array
|
||||
{
|
||||
$data = [];
|
||||
$host = $this->connect($token);
|
||||
$data['valid_host'] = false;
|
||||
$data['valid_user'] = false;
|
||||
$data['is_prefix_on'] = false;
|
||||
$data['dbinfo'] = null;
|
||||
$data['dbusers'] = null;
|
||||
try {
|
||||
$data = [];
|
||||
$host = $this->connect($token);
|
||||
$data['valid_host'] = $this->is_host_active($host->url);
|
||||
$data['is_prefix_on'] = $this->is_prefix_on($token);
|
||||
//Try two calls just in case
|
||||
$obj = json_decode($this->api->api2_query($host->user, "Contactus", "isenabled"));
|
||||
if (isset($obj->cpanelresult->func)) {
|
||||
$data['valid_user'] = true;
|
||||
} else {
|
||||
$obj = json_decode($this->api->api2_query($host->user, "Email", "accountname"));
|
||||
if (isset($obj->cpanelresult->func)) {
|
||||
$data['valid_user'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//DB NAMES/USRERS
|
||||
$obj = json_decode($this->api->api2_query($host->user, "MysqlFE", "getalldbsinfo"));
|
||||
$obj_dbs = $obj->cpanelresult->data ?? null;
|
||||
$data['dbinfo'] = ($obj_dbs != null && count($obj_dbs) >= 1) ? $obj_dbs : null;
|
||||
$obj = json_decode($this->api->api2_query($host->user, "MysqlFE", "listusers"));
|
||||
$obj_dbusers = $obj->cpanelresult->data ?? null;
|
||||
$data['dbusers'] = ($obj_dbusers != null && count($obj_dbusers) >= 1) ? $obj_dbusers : null;
|
||||
return $data;
|
||||
} catch (Exception $ex) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists the databases for the specified cpanel account
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/list_dbs/{token}/">
|
||||
*/
|
||||
public function list_dbs($token)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error listing databases. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "listdbs");
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
$data['status'] = isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1;
|
||||
if (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a database via the cPanel API
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbname The name of database to create
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/create_db/{token}/{dbname}">
|
||||
*/
|
||||
public function create_db($token, $dbname)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error creating database '{$dbname}'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['db'] = $dbname;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "createdb", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
$data['status'] = isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1;
|
||||
if (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a database via the cPanel API
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbname The name of database to delete
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/delete_db/{token}/{dbname}">
|
||||
*/
|
||||
public function delete_db($token, $dbname)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error deleting database '{$dbname}'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['db'] = $dbname;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "deletedb", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
$data['status'] = isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1;
|
||||
if (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a database user via the cPanel API
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbuser The name of database user to create
|
||||
* @param string $dbpass The database password to create for the user
|
||||
*
|
||||
* @return array<string,mixed> $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/create_db_user/{token}/{dbuser}/{dbpass}">
|
||||
*/
|
||||
public function create_db_user($token, $dbuser, $dbpass)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error creating database user '{$dbuser}'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['dbuser'] = $dbuser;
|
||||
$args['password'] = $dbpass;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "createdbuser", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
if (isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1) {
|
||||
$data['status'] = true;
|
||||
}
|
||||
if (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a database user via the cPanel API
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbuser The name of database user to delete
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/delete_db_user/{token}/{dbuser}">
|
||||
*/
|
||||
public function delete_db_user($token, $dbuser)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error deleting database user '{$dbuser}'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['dbuser'] = $dbuser;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "deletedbuser", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
if (isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1) {
|
||||
$data['status'] = true;
|
||||
}
|
||||
if (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assigns a user to a database via the cPanel API with ALL privileges
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbname The name of a valid database
|
||||
* @param string $dbuser The user to add to the database
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/assign_db_user/{token}/{dbname}/{dbuser}">
|
||||
*/
|
||||
public function assign_db_user($token, $dbname, $dbuser)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Unable to retrieve error status from cPanel API'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['privileges'] = 'ALL PRIVILEGES';
|
||||
$args['db'] = $dbname;
|
||||
$args['dbuser'] = $dbuser;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "setdbuserprivileges", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
//On some APIs this method returns error = 1 even when result = 1. It seems that the result = 1 is more
|
||||
//accurate for success detection so that will be the primary driver for success
|
||||
if (isset($obj->cpanelresult->event->result) && $obj->cpanelresult->event->result == 1) {
|
||||
$data['status'] = true;
|
||||
} elseif (property_exists($obj->cpanelresult, 'error')) {
|
||||
$data['status'] = $obj->cpanelresult->error;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the user in the database specified
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
* @param string $dbname The name of a valid database
|
||||
* @param string $dbuser A database user
|
||||
* @return array $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* <route template="/cpnl/is_user_in_db/{token}/{dbname}/{dbuser}">
|
||||
*/
|
||||
public function is_user_in_db($token, $dbname, $dbuser)
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data['status'] = "Error determining if '{$dbuser}' can access database '{$dbname}'. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$args = [];
|
||||
$args['db'] = $dbname;
|
||||
$json = $this->api->api2_query($host->user, "MysqlFE", "listusersindb", $args);
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
$data['status'] = false;
|
||||
foreach ($obj->cpanelresult->data as $database_pair) {
|
||||
if ($database_pair->user == $dbuser) {
|
||||
$data['status'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data['status'] = 'Could not retrieve list of users in database.';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does cpanel require the database to have a prefix
|
||||
* <route template="/cpnl/is_prefix_on/{token}">
|
||||
* Return
|
||||
* $data['status'] True/False or an error message.
|
||||
* $data['cpnl_api'] The cpanel API result
|
||||
*
|
||||
* @param string $token The authtoken used to access cpanel
|
||||
*
|
||||
* @return array{status:bool|string,cpnl_api:object}
|
||||
*/
|
||||
public function is_prefix_on($token): array
|
||||
{
|
||||
// Returns true/false or message on error
|
||||
$data = [];
|
||||
$data['status'] = "Error determining if database prefix name is enabled. See the log for more details.";
|
||||
$data['cpnl_api'] = null;
|
||||
$host = $this->connect($token);
|
||||
$json = $this->api->api2_query($host->user, "DBmap", "status");
|
||||
if ($json !== false) {
|
||||
$obj = json_decode($json);
|
||||
$data['cpnl_api'] = $obj;
|
||||
$data['status'] = isset($obj->cpanelresult->data) ? "Error calling DBmap" : $obj->cpanelresult->data[0]->prefix == 1;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the cPanel API
|
||||
*
|
||||
* @param string $token A valid token
|
||||
* @return DUPX_cPanelHost A DUPX_cPanelHost object
|
||||
*/
|
||||
public function connect($token)
|
||||
{
|
||||
$host = $this->get_host($token);
|
||||
if (!$host->host || !$host->user || !$host->pass) {
|
||||
throw new Exception('DUPX_cPanel->connect invalid token provided.');
|
||||
}
|
||||
|
||||
//Call to cPanel XMLAPI Client Class see /classes/_libs.php
|
||||
$this->api = new CPNL_API($host->host);
|
||||
$this->api->password_auth($host->user, $host->pass);
|
||||
$this->api->set_protocol($host->scheme);
|
||||
$this->api->set_port($host->port);
|
||||
$this->api->set_output("json");
|
||||
$this->api->set_debug(false);
|
||||
return $host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the cPanel API is availble for use
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool True if this host supports the json api
|
||||
*
|
||||
* //https://mysite.com:2083/json-api/
|
||||
*/
|
||||
private function is_host_active($url): bool
|
||||
{
|
||||
$route = '/json-api/';
|
||||
$url = (!strpos($url, $route)) ? "{$url}/json-api/" : $url;
|
||||
$response = DUPX_HTTP::get($url);
|
||||
$json = json_decode($response);
|
||||
if (isset($json->cpanelresult)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
//Start at router for all api requets
|
||||
header('Location: router.php') ;
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
if (!defined('DUPXABSPATH')) {
|
||||
define('DUPXABSPATH', __DIR__);
|
||||
}
|
||||
|
||||
use Duplicator\Installer\Core\Bootstrap;
|
||||
|
||||
define('DUPX_VERSION', '4.5.25.2');
|
||||
define('DUPX_INIT', str_replace('\\', '/', dirname(__DIR__)));
|
||||
define('DUPX_ROOT', preg_match('/^[\\\\\/]?$/', dirname(DUPX_INIT)) ? '/' : dirname(DUPX_INIT));
|
||||
|
||||
require_once(DUPX_INIT . '/src/Utils/Autoloader.php');
|
||||
Duplicator\Installer\Utils\Autoloader::register();
|
||||
/**
|
||||
* init constants and include
|
||||
*/
|
||||
Bootstrap::init(2);
|
||||
|
||||
require_once('class.api.php');
|
||||
require_once('class.cpnl.base.php');
|
||||
require_once('class.cpnl.ctrl.php');
|
||||
|
||||
//Register API Engine - If it processes the current route it spits out JSON and exits the process
|
||||
$API_Server = new DUPX_API_Server();
|
||||
$API_Server->add_controller(new DUPX_cPanel_Controller());
|
||||
$API_Server->process_request(false);
|
||||
|
||||
dupxTplRender('api/front', [
|
||||
'apiControllers' => $API_Server->controllers,
|
||||
'dupVersion' => DUPX_ArchiveConfig::getInstance()->version_dup
|
||||
]);
|
||||
Reference in New Issue
Block a user