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
0 commit comments