Skip to content

Commit 46f9308

Browse files
author
Roël Couwenberg
authored
Initial commit
1 parent d5bc33e commit 46f9308

2 files changed

Lines changed: 247 additions & 0 deletions

File tree

DirectApi.php

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
<?php
2+
3+
namespace Avametix;
4+
5+
/**
6+
* DirectApi class
7+
*
8+
* @author Roël Couwenberg
9+
* @package Avametix\DirectApi
10+
*/
11+
class DirectApi
12+
{
13+
private string $host;
14+
private int $port;
15+
private string $protocol;
16+
private array $usernames;
17+
private string $password;
18+
19+
/**
20+
* Construct new DirectApi instance
21+
*
22+
* Using a given DirectAdmin installation location, username(s), password and optionally a port create a new DirectApi
23+
* instance to communicate with the DirectAdmin installation at this location.
24+
*
25+
* @access public
26+
* @param string $host The hostname for the DirectAdmin installation, e.g. "client.avametix.xyz"
27+
* @param string $usernames The username or usernames used to log into the installation with, e.g. "admin" or "admin|user"
28+
* @param string $password The password used to log in to the installation
29+
* @param string $protocol The protocol to use with the installation, e.g. "http" or "https"
30+
* @param int $port The port to use with the installation, e.g. 2222
31+
*/
32+
public function __construct(string $host, string $usernames, string $password, ?string $protocol = "http", ?int $port = 2222) {
33+
$this->host = $host;
34+
$this->port = $port;
35+
$this->protocol = $protocol;
36+
$this->usernames = explode("|", $usernames);
37+
$this->password = $password;
38+
}
39+
40+
/**
41+
* Get usernames as string
42+
*
43+
* Parses the known usernames as a string in order to be used in DirectAdmin requests.
44+
*
45+
* @access private
46+
* @return string
47+
*/
48+
private function username() {
49+
return implode("|", $this->usernames);
50+
}
51+
52+
/**
53+
* Change or add second username
54+
*
55+
* These usernames may be used to authenticate DirectAdmin requests.
56+
*
57+
* @access public
58+
* @param string $username New username
59+
*/
60+
public function login_as(string $username) {
61+
$this->usernames[1] = $username;
62+
}
63+
64+
/**
65+
* Removes second username.
66+
*
67+
* @access public
68+
*/
69+
public function logout() {
70+
$this->usernames = array_splice($this->usernames, 1);
71+
}
72+
73+
/**
74+
* Make a get request to the DirectAdmin API
75+
*
76+
* Adds the DirectAdmin API prefix to an internal GET request.
77+
*
78+
* @access public
79+
* @param string $command The DirectAdmin API command to execute
80+
* @param ?array $data The data to transmit with the DirectAdmin API request
81+
* @return array The parsed data
82+
*/
83+
public function get_api(string $command, ?array $data = null) {
84+
return $this->get("/CMD_API_$command", $data);
85+
}
86+
87+
/**
88+
* Make a post request to the DirectAdmin API
89+
*
90+
* Adds the DirectAdmin API prefix to an internal POST request.
91+
*
92+
* @access public
93+
* @param string $command The DirectAdmin API command to execute
94+
* @param array $data The data to transmit with the DirectAdmin API request
95+
* @return array The parsed data
96+
*/
97+
public function post_api(string $command, array $data) {
98+
return $this->post("/CMD_API_$command", $data);
99+
}
100+
101+
/**
102+
* Decodes an input as a list
103+
*
104+
* Creates an array of all returned values in input.
105+
*
106+
* @access protected
107+
* @param string $input The string to parse to a list
108+
* @return array The parsed list
109+
*/
110+
protected function decode_list(string $input) {
111+
$a = explode('&', urldecode($input));
112+
$values = Array();
113+
114+
$i=0;
115+
foreach ($a as $v)
116+
{
117+
$values[$i++] = substr(strstr($v, '='), 1);
118+
}
119+
120+
return $values;
121+
}
122+
123+
/**
124+
* Decodes an input as a dictionary
125+
*
126+
* Creates a dictionary of all returned key/value pairs in input.
127+
*
128+
* @access protected
129+
* @param string $input The string to parse to a dictionary
130+
* @return array The parsed dictionary
131+
*/
132+
protected function decode_array(string $input) {
133+
$a = explode('&', urldecode($input));
134+
$values = Array();
135+
136+
$i=0;
137+
foreach ($a as $v)
138+
{
139+
$values[substr($v, 0, strpos($v, '='))] = substr(strstr($v, '='), 1);
140+
}
141+
142+
return $values;
143+
}
144+
145+
/**
146+
* Chooses whether to parse an input as a list or dictionary
147+
*
148+
* Sends input to either decode_list or decode_array
149+
*
150+
* @access private
151+
* @param string $input The string to choose for
152+
* @return array The parsed result
153+
*/
154+
private function parse_result(string $input) {
155+
if (str_contains($input, "list[]"))
156+
return $this->decode_list($input);
157+
158+
return $this->decode_array($input);
159+
}
160+
161+
/**
162+
* Sends a get request
163+
*
164+
* Uses destination and data to create a get request to the specified server and returns the parsed result
165+
*
166+
* @access private
167+
* @param string $destination The page the request should go to
168+
* @param ?array $data The data to send with the request
169+
* @return object The parsed result
170+
*/
171+
private function get(string $destination, ?array $data = null) {
172+
// Combine already set variables to create a valid endpoint
173+
$url = $this->protocol . "://" . $this->host . ":" . $this->port . $destination;
174+
175+
// Add data to GET request if data is set
176+
if (!is_null($data) && isset($data))
177+
$url .= "?" . http_build_query($data);
178+
179+
// Set correct headers
180+
$options = array(
181+
'http' => array(
182+
'header' => "Content-type: application/x-www-form-urlencoded\r\nAuthorization: Basic " . base64_encode($this->username() . ":" . $this->password) . "\r\n",
183+
'method' => 'GET',
184+
'content' => ''
185+
)
186+
);
187+
188+
// Create context and get contents from request
189+
$context = stream_context_create($options);
190+
$result = file_get_contents($url, false, $context);
191+
192+
// Return false if request is invalid, else return the parsed result
193+
if ($result === FALSE) {
194+
return false;
195+
}
196+
197+
return $this->parse_result($result);
198+
}
199+
200+
/**
201+
* Sends a post request
202+
*
203+
* Uses destination and data to create a post request to the specified server and returns the parsed result
204+
*
205+
* @access private
206+
* @param string $destination The page the request should go to
207+
* @param ?array $data The data to send with the request
208+
* @return object The parsed result
209+
*/
210+
private function post(string $destination, $data) {
211+
// Combine already set variables to create a valid endpoint
212+
$url = $this->protocol . "://" . $this->host . ":" . $this->port . $destination;
213+
214+
foreach ($data as $key => $value) {
215+
$data[$key] = str_replace("|password|", $this->password, $value);
216+
}
217+
218+
// Set correct headers
219+
$options = array(
220+
'http' => array(
221+
'header' => "Content-type: application/x-www-form-urlencoded\r\nAuthorization: Basic " . base64_encode($this->username() . ":" . $this->password) . "\r\n",
222+
'method' => 'POST',
223+
'content' => http_build_query($data)
224+
)
225+
);
226+
227+
// Create context and get contents from request
228+
$context = stream_context_create($options);
229+
$result = file_get_contents($url, false, $context);
230+
231+
// Return false if request is invalid, else return the parsed result
232+
if ($result === FALSE) {
233+
return false;
234+
}
235+
236+
return $this->parse_result($result);
237+
}
238+
}
239+
240+
// EOF

composer.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "avametix/directapi",
3+
"description": "An API wrapper for the DirectAdmin API",
4+
"require": {
5+
"php": ">=7.1.0"
6+
}
7+
}

0 commit comments

Comments
 (0)