Skip to content

Instantly share code, notes, and snippets.

@kishu27
Created May 26, 2023 23:13
Show Gist options
  • Save kishu27/65e73aa72534ff3784b845fba0639945 to your computer and use it in GitHub Desktop.
Save kishu27/65e73aa72534ff3784b845fba0639945 to your computer and use it in GitHub Desktop.
<?php
namespace UniFi_API;
class Client
{
const CLASS_VERSION = '1.1.80';
protected $baseurl = 'https://127.0.0.1:8443';
protected $user = '';
protected $password = '';
protected $site = 'default';
protected $version = '6.2.26';
protected $debug = false;
protected $is_logged_in = false;
protected $is_unifi_os = false;
protected $exec_retries = 0;
protected $cookies = '';
protected $last_results_raw = null;
protected $last_error_message = '';
protected $curl_ssl_verify_peer = false;
protected $curl_ssl_verify_host = false;
protected $curl_http_version = CURL_HTTP_VERSION_NONE;
protected $curl_headers = [];
protected $curl_method = 'GET';
protected $curl_methods_allowed = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
protected $curl_request_timeout = 30;
protected $curl_connect_timeout = 10;
public function __construct($user, $password, $baseurl = '', $site = '', $version = '', $ssl_verify = false)
{
if (!extension_loaded('curl')) {
trigger_error('The PHP curl extension is not loaded. Please correct this before proceeding!');
}
$this->user = trim($user);
$this->password = trim($password);
if (!empty($baseurl)) {
$this->check_base_url($baseurl);
$this->baseurl = trim($baseurl);
}
if (!empty($site)) {
$this->check_site($site);
$this->site = trim($site);
}
if (!empty($version)) {
$this->version = trim($version);
}
if ((bool) $ssl_verify === true) {
$this->curl_ssl_verify_peer = true;
$this->curl_ssl_verify_host = 2;
}
}
public function __destruct()
{
if (isset($_SESSION['unificookie'])) {
return;
}
if ($this->is_logged_in) {
$this->logout();
}
}
public function login()
{
if ($this->update_unificookie()) {
$this->is_logged_in = true;
}
if ($this->is_logged_in === true) {
return true;
}
if (!($ch = $this->get_curl_handle())) {
return false;
}
$curl_options = [
CURLOPT_URL => $this->baseurl . '/',
];
curl_setopt_array($ch, $curl_options);
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
trigger_error('cURL error: ' . curl_error($ch));
}
$curl_options = [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['username' => $this->user, 'password' => $this->password]),
CURLOPT_HTTPHEADER => [
'content-type: application/json',
'Expect:',
],
CURLOPT_REFERER => $this->baseurl . '/login',
CURLOPT_URL => $this->baseurl . '/api/login',
];
if ($http_code === 200) {
$this->is_unifi_os = true;
$curl_options[CURLOPT_URL] = $this->baseurl . '/api/auth/login';
}
curl_setopt_array($ch, $curl_options);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
trigger_error('cURL error: ' . curl_error($ch));
}
if ($this->debug) {
print PHP_EOL . '<pre>';
print PHP_EOL . '-----------LOGIN-------------' . PHP_EOL;
print_r(curl_getinfo($ch));
print PHP_EOL . '----------RESPONSE-----------' . PHP_EOL;
print $response;
print PHP_EOL . '-----------------------------' . PHP_EOL;
print '</pre>' . PHP_EOL;
}
if ($http_code === 400 || $http_code === 401) {
trigger_error("HTTP response status received: $http_code. Probably a controller login failure");
return $http_code;
}
curl_close($ch);
if ($http_code >= 200 && $http_code < 400) {
$this->is_logged_in = true;
return $this->is_logged_in;
}
return false;
}
public function logout()
{
if (!($ch = $this->get_curl_handle())) {
return false;
}
$curl_options = [
CURLOPT_HEADER => true,
CURLOPT_POST => true,
];
$this->curl_headers = [
'Expect:',
];
$logout_path = '/logout';
if ($this->is_unifi_os) {
$logout_path = '/api/auth/logout';
$curl_options[CURLOPT_CUSTOMREQUEST] = 'POST';
$this->create_x_csrf_token_header();
}
$curl_options[CURLOPT_HTTPHEADER] = $this->curl_headers;
$curl_options[CURLOPT_URL] = $this->baseurl . $logout_path;
curl_setopt_array($ch, $curl_options);
curl_exec($ch);
if (curl_errno($ch)) {
trigger_error('cURL error: ' . curl_error($ch));
return false;
}
curl_close($ch);
$this->is_logged_in = false;
$this->cookies = '';
return true;
}
public function authorize_guest($mac, $minutes, $up = null, $down = null, $megabytes = null, $ap_mac = null)
{
$payload = ['cmd' => 'authorize-guest', 'mac' => strtolower($mac), 'minutes' => intval($minutes)];
if (!empty($up)) {
$payload['up'] = intval($up);
}
if (!empty($down)) {
$payload['down'] = intval($down);
}
if (!empty($megabytes)) {
$payload['bytes'] = intval($megabytes);
}
if (!empty($ap_mac) && filter_var($ap_mac, FILTER_VALIDATE_MAC)) {
$payload['ap_mac'] = strtolower($ap_mac);
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function unauthorize_guest($mac)
{
$payload = ['cmd' => 'unauthorize-guest', 'mac' => strtolower($mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function reconnect_sta($mac)
{
$payload = ['cmd' => 'kick-sta', 'mac' => strtolower($mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function block_sta($mac)
{
$payload = ['cmd' => 'block-sta', 'mac' => strtolower($mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function unblock_sta($mac)
{
$payload = ['cmd' => 'unblock-sta', 'mac' => strtolower($mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function forget_sta($macs)
{
$payload = ['cmd' => 'forget-sta', 'macs' => array_map('strtolower', $macs)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stamgr', $payload);
}
public function create_user($mac, $user_group_id, $name = null, $note = null, $is_guest = null, $is_wired = null)
{
$new_user = ['mac' => strtolower($mac), 'usergroup_id' => $user_group_id];
if (!empty($name)) {
$new_user['name'] = $name;
}
if (!empty($note)) {
$new_user['note'] = $note;
}
if (!empty($is_guest) && is_bool($is_guest)) {
$new_user['is_guest'] = $is_guest;
}
if (!empty($is_wired) && is_bool($is_wired)) {
$new_user['is_wired'] = $is_wired;
}
$payload = ['objects' => [['data' => $new_user]]];
return $this->fetch_results('/api/s/' . $this->site . '/group/user', $payload);
}
public function set_sta_note($user_id, $note = '')
{
$payload = ['note' => $note];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/user/' . trim($user_id), $payload);
}
public function set_sta_name($user_id, $name = '')
{
$payload = ['name' => $name];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/user/' . trim($user_id), $payload);
}
public function stat_5minutes_site($start = null, $end = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (12 * 3600 * 1000) : intval($start);
$attribs = [
'bytes',
'wan-tx_bytes',
'wan-rx_bytes',
'wlan_bytes',
'num_sta',
'lan-num_sta',
'wlan-num_sta',
'time',
];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/5minutes.site', $payload);
}
public function stat_hourly_site($start = null, $end = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = [
'bytes',
'wan-tx_bytes',
'wan-rx_bytes',
'wlan_bytes',
'num_sta',
'lan-num_sta',
'wlan-num_sta',
'time',
];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/hourly.site', $payload);
}
public function stat_daily_site($start = null, $end = null)
{
$end = empty($end) ? (time() - (time() % 3600)) * 1000 : intval($end);
$start = empty($start) ? $end - (52 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = [
'bytes',
'wan-tx_bytes',
'wan-rx_bytes',
'wlan_bytes',
'num_sta',
'lan-num_sta',
'wlan-num_sta',
'time',
];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/daily.site', $payload);
}
public function stat_monthly_site($start = null, $end = null)
{
$end = empty($end) ? (time() - (time() % 3600)) * 1000 : intval($end);
$start = empty($start) ? $end - (52 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = [
'bytes',
'wan-tx_bytes',
'wan-rx_bytes',
'wlan_bytes',
'num_sta',
'lan-num_sta',
'wlan-num_sta',
'time',
];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/monthly.site', $payload);
}
public function stat_5minutes_aps($start = null, $end = null, $mac = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (12 * 3600 * 1000) : intval($start);
$attribs = ['bytes', 'num_sta', 'time'];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
if (!empty($mac)) {
$payload['mac'] = strtolower($mac);
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/5minutes.ap', $payload);
}
public function stat_hourly_aps($start = null, $end = null, $mac = null)
{
$end = empty($end) ? (time() * 1000) : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = ['bytes', 'num_sta', 'time'];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
if (!empty($mac)) {
$payload['mac'] = strtolower($mac);
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/hourly.ap', $payload);
}
public function stat_daily_aps($start = null, $end = null, $mac = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = ['bytes', 'num_sta', 'time'];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
if (!empty($mac)) {
$payload['mac'] = strtolower($mac);
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/daily.ap', $payload);
}
public function stat_monthly_aps($start = null, $end = null, $mac = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (52 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = ['bytes', 'num_sta', 'time'];
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
if (!empty($mac)) {
$payload['mac'] = strtolower($mac);
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/monthly.ap', $payload);
}
public function stat_5minutes_user($mac, $start = null, $end = null, $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (12 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/5minutes.user', $payload);
}
public function stat_hourly_user($mac, $start = null, $end = null, array $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/hourly.user', $payload);
}
public function stat_daily_user($mac, $start = null, $end = null, $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/daily.user', $payload);
}
public function stat_monthly_user($mac, $start = null, $end = null, $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (13 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/monthly.user', $payload);
}
public function stat_5minutes_gateway($start = null, $end = null, $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (12 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'mem', 'cpu', 'loadavg_5'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/5minutes.gw', $payload);
}
public function stat_hourly_gateway($start = null, $end = null, $attribs = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'mem', 'cpu', 'loadavg_5'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/hourly.gw', $payload);
}
public function stat_daily_gateway($start = null, $end = null, $attribs = null)
{
$end = empty($end) ? (time() - (time() % 3600)) * 1000 : intval($end);
$start = empty($start) ? $end - (52 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'mem', 'cpu', 'loadavg_5'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/daily.gw', $payload);
}
public function stat_monthly_gateway($start = null, $end = null, $attribs = null)
{
$end = empty($end) ? (time() - (time() % 3600)) * 1000 : intval($end);
$start = empty($start) ? $end - (52 * 7 * 24 * 3600 * 1000) : intval($start);
$attribs = empty($attribs) ? ['time', 'mem', 'cpu', 'loadavg_5'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/monthly.gw', $payload);
}
public function stat_speedtest_results($start = null, $end = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (24 * 3600 * 1000) : intval($start);
$payload = ['attrs' => ['xput_download', 'xput_upload', 'latency', 'time'], 'start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/archive.speedtest', $payload);
}
public function stat_ips_events($start = null, $end = null, $limit = null)
{
$end = empty($end) ? time() * 1000 : intval($end);
$start = empty($start) ? $end - (24 * 3600 * 1000) : intval($start);
$limit = empty($limit) ? 10000 : intval($limit);
$payload = ['start' => $start, 'end' => $end, '_limit' => $limit];
return $this->fetch_results('/api/s/' . $this->site . '/stat/ips/event', $payload);
}
public function stat_sessions($start = null, $end = null, $mac = null, $type = 'all')
{
if (!in_array($type, ['all', 'guest', 'user'])) {
return false;
}
$end = empty($end) ? time() : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600) : intval($start);
$payload = ['type' => $type, 'start' => $start, 'end' => $end];
if (!empty($mac)) {
$payload['mac'] = strtolower($mac);
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/session', $payload);
}
public function stat_sta_sessions_latest($mac, $limit = null)
{
$limit = empty($limit) ? 5 : intval($limit);
$payload = ['mac' => strtolower($mac), '_limit' => $limit, '_sort' => '-assoc_time'];
return $this->fetch_results('/api/s/' . $this->site . '/stat/session', $payload);
}
public function stat_auths($start = null, $end = null)
{
$end = empty($end) ? time() : intval($end);
$start = empty($start) ? $end - (7 * 24 * 3600) : intval($start);
$payload = ['start' => $start, 'end' => $end];
return $this->fetch_results('/api/s/' . $this->site . '/stat/authorization', $payload);
}
public function stat_allusers($historyhours = 8760)
{
$payload = ['type' => 'all', 'conn' => 'all', 'within' => intval($historyhours)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/alluser', $payload);
}
public function list_guests($within = 8760)
{
$payload = ['within' => intval($within)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/guest', $payload);
}
public function list_clients($client_mac = null)
{
if (is_string($client_mac)) {
$client_mac = strtolower(trim($client_mac));
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/sta/' . $client_mac);
}
public function stat_client($client_mac)
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/user/' . strtolower(trim($client_mac)));
}
public function set_usergroup($client_id, $group_id)
{
$payload = ['usergroup_id' => $group_id];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/user/' . trim($client_id), $payload);
}
public function edit_client_fixedip($client_id, $use_fixedip, $network_id = null, $fixed_ip = null)
{
if (!is_bool($use_fixedip)) {
return false;
}
$this->curl_method = 'PUT';
$payload = [
'_id' => $client_id,
'use_fixedip' => $use_fixedip,
];
if ($use_fixedip) {
if ($network_id) {
$payload['network_id'] = $network_id;
}
if ($fixed_ip) {
$payload['fixed_ip'] = $fixed_ip;
}
}
return $this->fetch_results('/api/s/' . $this->site . '/rest/user/' . trim($client_id), $payload);
}
public function edit_client_name($client_id, $name)
{
if (empty($name)) {
return false;
}
$this->curl_method = 'PUT';
$payload = [
'_id' => $client_id,
'name' => $name,
];
return $this->fetch_results('/api/s/' . $this->site . '/rest/user/' . trim($client_id), $payload);
}
public function list_usergroups()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/usergroup');
}
public function create_usergroup($group_name, $group_dn = -1, $group_up = -1)
{
$payload = [
'name' => $group_name,
'qos_rate_max_down' => intval($group_dn),
'qos_rate_max_up' => intval($group_up),
];
return $this->fetch_results('/api/s/' . $this->site . '/rest/usergroup', $payload);
}
public function edit_usergroup($group_id, $site_id, $group_name, $group_dn = -1, $group_up = -1)
{
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'name' => $group_name,
'qos_rate_max_down' => intval($group_dn),
'qos_rate_max_up' => intval($group_up),
'site_id' => $site_id,
];
return $this->fetch_results('/api/s/' . $this->site . '/rest/usergroup/' . trim($group_id), $payload);
}
public function delete_usergroup($group_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/usergroup/' . trim($group_id));
}
public function list_apgroups()
{
return $this->fetch_results('/v2/api/site/' . $this->site . '/apgroups');
}
public function create_apgroup($group_name, $device_macs = [])
{
$payload = ['device_macs' => $device_macs, 'name' => $group_name];
return $this->fetch_results('/v2/api/site/' . $this->site . '/apgroups', $payload);
}
public function edit_apgroup($group_id, $group_name, $device_macs)
{
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'attr_no_delete' => false,
'name' => $group_name,
'device_macs' => $device_macs,
];
return $this->fetch_results('/v2/api/site/' . $this->site . '/apgroups/' . trim($group_id), $payload);
}
public function delete_apgroup($group_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/v2/api/site/' . $this->site . '/apgroups/' . trim($group_id));
}
public function list_firewallgroups($group_id = '')
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/firewallgroup/' . trim($group_id));
}
public function create_firewallgroup($group_name, $group_type, $group_members = [])
{
if (!in_array($group_type, ['address-group', 'ipv6-address-group', 'port-group'])) {
return false;
}
$payload = ['name' => $group_name, 'group_type' => $group_type, 'group_members' => $group_members];
return $this->fetch_results('/api/s/' . $this->site . '/rest/firewallgroup', $payload);
}
public function edit_firewallgroup($group_id, $site_id, $group_name, $group_type, $group_members = [])
{
if (!in_array($group_type, ['address-group', 'ipv6-address-group', 'port-group'])) {
return false;
}
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'name' => $group_name,
'group_type' => $group_type,
'group_members' => $group_members,
'site_id' => $site_id,
];
return $this->fetch_results('/api/s/' . $this->site . '/rest/firewallgroup/' . trim($group_id), $payload);
}
public function delete_firewallgroup($group_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/firewallgroup/' . trim($group_id));
}
public function list_firewallrules()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/firewallrule');
}
public function list_routing($route_id = '')
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/routing/' . trim($route_id));
}
public function list_health()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/health');
}
public function list_dashboard($five_minutes = false)
{
$path_suffix = $five_minutes ? '?scale=5minutes' : null;
return $this->fetch_results('/api/s/' . $this->site . '/stat/dashboard' . $path_suffix);
}
public function list_users()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/user');
}
public function list_devices_basic()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/device-basic');
}
public function list_devices($device_mac = null)
{
if (is_string($device_mac)) {
$device_mac = strtolower(trim($device_mac));
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/device/' . $device_mac);
}
public function list_tags()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/tag');
}
public function list_rogueaps($within = 24)
{
$payload = ['within' => intval($within)];
return $this->fetch_results('/api/s/' . $this->site . '/stat/rogueap', $payload);
}
public function list_known_rogueaps()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/rogueknown');
}
public function generate_backup()
{
$payload = ['cmd' => 'backup'];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/backup', $payload);
}
public function list_backups()
{
$payload = ['cmd' => 'list-backups'];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/backup', $payload);
}
public function generate_backup_site()
{
$payload = ['cmd' => 'export-site'];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/backup', $payload);
}
public function list_sites()
{
return $this->fetch_results('/api/self/sites');
}
public function stat_sites()
{
return $this->fetch_results('/api/stat/sites');
}
public function create_site($description)
{
$payload = ['desc' => $description, 'cmd' => 'add-site'];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function delete_site($site_id)
{
$payload = ['site' => $site_id, 'cmd' => 'delete-site'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function set_site_name($site_name)
{
$payload = ['cmd' => 'update-site', 'desc' => $site_name];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function set_site_country($country_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/country/' . trim($country_id),
$payload);
}
public function set_site_locale($locale_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/locale/' . trim($locale_id),
$payload);
}
public function set_site_snmp($snmp_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/snmp/' . trim($snmp_id), $payload);
}
public function set_site_mgmt($mgmt_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/mgmt/' . trim($mgmt_id), $payload);
}
public function set_site_guest_access($guest_access_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/guest_access/' . trim($guest_access_id),
$payload);
}
public function set_site_ntp($ntp_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/ntp/' . trim($ntp_id), $payload);
}
public function set_site_connectivity($connectivity_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/connectivity/' . trim($connectivity_id),
$payload);
}
public function list_admins()
{
$payload = ['cmd' => 'get-admins'];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function list_all_admins()
{
return $this->fetch_results('/api/stat/admin');
}
public function invite_admin(
$name,
$email,
$enable_sso = true,
$readonly = false,
$device_adopt = false,
$device_restart = false
) {
$email = trim($email);
$email_valid = filter_var($email, FILTER_VALIDATE_EMAIL);
if (!$email_valid) {
trigger_error('The email address provided is invalid!');
return false;
}
$payload = [
'name' => trim($name),
'email' => $email,
'for_sso' => $enable_sso,
'cmd' => 'invite-admin',
'role' => 'admin',
'permissions' => [],
];
if ($readonly) {
$payload['role'] = 'readonly';
}
if ($device_adopt) {
$payload['permissions'][] = 'API_DEVICE_ADOPT';
}
if ($device_restart) {
$payload['permissions'][] = 'API_DEVICE_RESTART';
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function assign_existing_admin($admin_id, $readonly = false, $device_adopt = false, $device_restart = false)
{
$payload = [
'cmd' => 'grant-admin',
'admin' => trim($admin_id),
'role' => 'admin',
'permissions' => [],
];
if ($readonly) {
$payload['role'] = 'readonly';
}
if ($device_adopt) {
$payload['permissions'][] = 'API_DEVICE_ADOPT';
}
if ($device_restart) {
$payload['permissions'][] = 'API_DEVICE_RESTART';
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function revoke_admin($admin_id)
{
$payload = ['cmd' => 'revoke-admin', 'admin' => $admin_id];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function list_wlan_groups()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/wlangroup');
}
public function stat_sysinfo()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/sysinfo');
}
public function stat_status()
{
return $this->fetch_results_boolean('/status', null, false);
}
public function stat_full_status()
{
$this->fetch_results_boolean('/status', null, false);
return json_decode($this->get_last_results_raw());
}
public function list_device_name_mappings()
{
$this->fetch_results_boolean('/dl/firmware/bundles.json', null, false);
return json_decode($this->get_last_results_raw());
}
public function list_self()
{
return $this->fetch_results('/api/s/' . $this->site . '/self');
}
public function stat_voucher($create_time = null)
{
$payload = isset($create_time) ? ['create_time' => intval($create_time)] : [];
return $this->fetch_results('/api/s/' . $this->site . '/stat/voucher', $payload);
}
public function stat_payment($within = null)
{
$path_suffix = isset($within) ? '?within=' . intval($within) : '';
return $this->fetch_results('/api/s/' . $this->site . '/stat/payment' . $path_suffix);
}
public function create_hotspotop($name, $x_password, $note = '')
{
$payload = ['name' => $name, 'x_password' => $x_password];
if (!empty($note)) {
$payload['note'] = trim($note);
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/hotspotop', $payload);
}
public function list_hotspotop()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/hotspotop');
}
public function create_voucher(
$minutes,
$count = 1,
$quota = 0,
$note = '',
$up = null,
$down = null,
$megabytes = null
) {
$payload = [
'cmd' => 'create-voucher',
'expire' => intval($minutes),
'n' => intval($count),
'quota' => intval($quota),
];
if (!empty($note)) {
$payload['note'] = trim($note);
}
if (!is_null($up)) {
$payload['up'] = intval($up);
}
if (!is_null($down)) {
$payload['down'] = intval($down);
}
if (!is_null($megabytes)) {
$payload['bytes'] = intval($megabytes);
}
return $this->fetch_results('/api/s/' . $this->site . '/cmd/hotspot', $payload);
}
public function revoke_voucher($voucher_id)
{
$payload = ['_id' => $voucher_id, 'cmd' => 'delete-voucher'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/hotspot', $payload);
}
public function extend_guest_validity($guest_id)
{
$payload = ['_id' => $guest_id, 'cmd' => 'extend'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/hotspot', $payload);
}
public function list_portforward_stats()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/portforward');
}
public function list_dpi_stats()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/dpi');
}
public function list_dpi_stats_filtered($type = 'by_cat', array $cat_filter = null)
{
if (!in_array($type, ['by_cat', 'by_app'])) {
return false;
}
$payload = ['type' => $type];
if (is_array($cat_filter) && $type === 'by_app') {
$payload['cats'] = $cat_filter;
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/sitedpi', $payload);
}
public function list_current_channels()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/current-channel');
}
public function list_country_codes()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/ccode');
}
public function list_portforwarding()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/portforward');
}
public function list_portconf()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/portconf');
}
public function list_extension()
{
return $this->fetch_results('/api/s/' . $this->site . '/list/extension');
}
public function list_settings()
{
return $this->fetch_results('/api/s/' . $this->site . '/get/setting');
}
public function adopt_device($mac)
{
$payload = ['mac' => strtolower($mac), 'cmd' => 'adopt'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function advanced_adopt_device($mac, $ip, $username, $password, $url, $port = 22, $ssh_key_verify = true)
{
$payload = [
'cmd' => 'adv-adopt',
'mac' => strtolower($mac),
'ip' => $ip,
'username' => $username,
'password' => $password,
'url' => $url,
'port' => $port,
'sshKeyVerify' => $ssh_key_verify,
];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function restart_device($mac, $reboot_type = 'soft')
{
$payload = ['cmd' => 'restart', 'mac' => strtolower($mac)];
if (!empty($reboot_type) && in_array($reboot_type, ['soft', 'hard'])) {
$payload['reboot_type'] = strtolower($reboot_type);
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function force_provision($mac)
{
$payload = ['mac' => strtolower($mac), 'cmd' => 'force-provision'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function reboot_cloudkey()
{
$payload = ['cmd' => 'reboot'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/system', $payload);
}
public function disable_ap($ap_id, $disable)
{
if (!is_bool($disable)) {
return false;
}
$this->curl_method = 'PUT';
$payload = ['disabled' => $disable];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($ap_id), $payload);
}
public function led_override($device_id, $override_mode)
{
if (!in_array($override_mode, ['off', 'on', 'default'])) {
return false;
}
$this->curl_method = 'PUT';
$payload = ['led_override' => $override_mode];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($device_id), $payload);
}
public function locate_ap($mac, $enable)
{
if (!is_bool($enable)) {
return false;
}
$cmd = $enable ? 'set-locate' : 'unset-locate';
$payload = ['cmd' => $cmd, 'mac' => strtolower($mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function site_leds($enable)
{
if (!is_bool($enable)) {
return false;
}
$payload = ['led_enabled' => $enable];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/mgmt', $payload);
}
public function set_ap_radiosettings($ap_id, $radio, $channel, $ht, $tx_power_mode, $tx_power)
{
$payload = [
'radio_table' => [
'radio' => $radio,
'channel' => $channel,
'ht' => $ht,
'tx_power_mode' => $tx_power_mode,
'tx_power' => $tx_power,
],
];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/device/' . trim($ap_id), $payload);
}
public function set_ap_wlangroup($type_id, $device_id, $group_id)
{
if (!in_array($type_id, ['ng', 'na'])) {
return false;
}
$payload = [
'wlan_overrides' => [],
'wlangroup_id_' . $type_id => $group_id,
];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/device/' . trim($device_id), $payload);
}
public function set_guestlogin_settings(
$portal_enabled,
$portal_customized,
$redirect_enabled,
$redirect_url,
$x_password,
$expire_number,
$expire_unit,
$section_id
) {
$payload = [
'portal_enabled' => $portal_enabled,
'portal_customized' => $portal_customized,
'redirect_enabled' => $redirect_enabled,
'redirect_url' => $redirect_url,
'x_password' => $x_password,
'expire_number' => $expire_number,
'expire_unit' => $expire_unit,
'_id' => $section_id,
];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/guest_access/' . $section_id,
$payload);
}
public function set_guestlogin_settings_base($payload, $section_id = '')
{
if (!empty($section_id)) {
$section_id = '/' . $section_id;
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/guest_access' . $section_id,
$payload);
}
public function set_ips_settings_base($payload)
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/ips', $payload);
}
public function set_super_mgmt_settings_base($settings_id, $payload)
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/super_mgmt/' . trim($settings_id),
$payload);
}
public function set_super_smtp_settings_base($settings_id, $payload)
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/super_smtp/' . trim($settings_id),
$payload);
}
public function set_super_identity_settings_base($settings_id, $payload)
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/super_identity/' . trim($settings_id),
$payload);
}
public function rename_ap($ap_id, $apname)
{
$payload = ['name' => $apname];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/device/' . trim($ap_id), $payload);
}
public function move_device($mac, $site_id)
{
$payload = ['site' => $site_id, 'mac' => strtolower($mac), 'cmd' => 'move-device'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function delete_device($mac)
{
$payload = ['mac' => strtolower($mac), 'cmd' => 'delete-device'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/sitemgr', $payload);
}
public function list_dynamicdns()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/dynamicdns');
}
public function create_dynamicdns($payload)
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/dynamicdns', $payload);
}
public function set_dynamicdns($dynamicdns_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/dynamicdns/' . trim($dynamicdns_id),
$payload);
}
public function list_networkconf($network_id = '')
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/networkconf/' . trim($network_id));
}
public function create_network($payload)
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/networkconf', $payload);
}
public function set_networksettings_base($network_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/networkconf/' . trim($network_id),
$payload);
}
public function delete_network($network_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/networkconf/' . trim($network_id));
}
public function list_wlanconf($wlan_id = '')
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/wlanconf/' . trim($wlan_id));
}
public function create_wlan(
$name,
$x_passphrase,
$usergroup_id,
$wlangroup_id,
$enabled = true,
$hide_ssid = false,
$is_guest = false,
$security = 'open',
$wpa_mode = 'wpa2',
$wpa_enc = 'ccmp',
$vlan_enabled = null,
$vlan_id = null,
$uapsd_enabled = false,
$schedule_enabled = false,
$schedule = [],
$ap_group_ids = null
) {
$payload = [
'name' => trim($name),
'usergroup_id' => trim($usergroup_id),
'wlangroup_id' => trim($wlangroup_id),
'enabled' => $enabled,
'hide_ssid' => $hide_ssid,
'is_guest' => $is_guest,
'security' => trim($security),
'wpa_mode' => trim($wpa_mode),
'wpa_enc' => trim($wpa_enc),
'uapsd_enabled' => $uapsd_enabled,
'schedule_enabled' => $schedule_enabled,
'schedule' => $schedule,
];
if (!empty($vlan_id)) {
$payload['networkconf_id'] = $vlan_id;
}
if (!empty($x_passphrase) && $security !== 'open') {
$payload['x_passphrase'] = trim($x_passphrase);
}
if (!empty($ap_group_ids) && is_array($ap_group_ids)) {
$payload['ap_group_ids'] = $ap_group_ids;
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/add/wlanconf', $payload);
}
public function set_wlansettings_base($wlan_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/wlanconf/' . trim($wlan_id), $payload);
}
public function set_wlansettings($wlan_id, $x_passphrase, $name = '')
{
$payload = [];
$payload['x_passphrase'] = trim($x_passphrase);
if (!empty($name)) {
$payload['name'] = trim($name);
}
return $this->set_wlansettings_base($wlan_id, $payload);
}
public function disable_wlan($wlan_id, $disable)
{
if (!is_bool($disable)) {
return false;
}
$action = !$disable;
$payload = ['enabled' => $action];
return $this->set_wlansettings_base($wlan_id, $payload);
}
public function delete_wlan($wlan_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/wlanconf/' . trim($wlan_id));
}
public function set_wlan_mac_filter($wlan_id, $mac_filter_policy, $mac_filter_enabled, array $macs)
{
if (!is_bool($mac_filter_enabled)) {
return false;
}
if (!in_array($mac_filter_policy, ['allow', 'deny'])) {
return false;
}
$macs = array_map('strtolower', $macs);
$payload = [
'mac_filter_enabled' => (bool) $mac_filter_enabled,
'mac_filter_policy' => $mac_filter_policy,
'mac_filter_list' => $macs,
];
return $this->set_wlansettings_base($wlan_id, $payload);
}
public function list_events($historyhours = 720, $start = 0, $limit = 3000)
{
$payload = [
'_sort' => '-time',
'within' => intval($historyhours),
'type' => null,
'_start' => intval($start),
'_limit' => intval($limit),
];
return $this->fetch_results('/api/s/' . $this->site . '/stat/event', $payload);
}
public function list_alarms($payload = [])
{
return $this->fetch_results('/api/s/' . $this->site . '/list/alarm', $payload);
}
public function count_alarms($archived = null)
{
$path_suffix = $archived === false ? '?archived=false' : null;
return $this->fetch_results('/api/s/' . $this->site . '/cnt/alarm' . $path_suffix);
}
public function archive_alarm($alarm_id = '')
{
$payload = ['cmd' => 'archive-all-alarms'];
if (!empty($alarm_id)) {
$payload = ['_id' => $alarm_id, 'cmd' => 'archive-alarm'];
}
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/evtmgr', $payload);
}
public function check_controller_update()
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/fwupdate/latest-version');
}
public function check_firmware_update()
{
$payload = ['cmd' => 'check-firmware-update'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/productinfo', $payload);
}
public function upgrade_device($device_mac)
{
$payload = ['mac' => strtolower($device_mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr/upgrade', $payload);
}
public function upgrade_device_external($firmware_url, $device_mac)
{
$payload = ['url' => filter_var($firmware_url, FILTER_SANITIZE_URL), 'mac' => strtolower($device_mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr/upgrade-external', $payload);
}
public function start_rolling_upgrade()
{
$payload = ['cmd' => 'set-rollupgrade'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function cancel_rolling_upgrade()
{
$payload = ['cmd' => 'unset-rollupgrade'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function list_firmware($type = 'available')
{
if (!in_array($type, ['available', 'cached'])) {
return false;
}
$payload = ['cmd' => 'list-' . $type];
return $this->fetch_results('/api/s/' . $this->site . '/cmd/firmware', $payload);
}
public function power_cycle_switch_port($switch_mac, $port_idx)
{
$payload = ['mac' => strtolower($switch_mac), 'port_idx' => intval($port_idx), 'cmd' => 'power-cycle'];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function spectrum_scan($ap_mac)
{
$payload = ['cmd' => 'spectrum-scan', 'mac' => strtolower($ap_mac)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload);
}
public function spectrum_scan_state($ap_mac)
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/spectrum-scan/' . strtolower(trim($ap_mac)));
}
public function set_device_settings_base($device_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($device_id), $payload);
}
public function list_radius_profiles()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/radiusprofile');
}
public function list_radius_accounts()
{
return $this->fetch_results('/api/s/' . $this->site . '/rest/account');
}
public function create_radius_account($name, $x_password, $tunnel_type = null, $tunnel_medium_type = null, $vlan = null)
{
$tunnel_type_values = [null, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
$tunnel_medium_type_values = [null, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
if (!in_array($tunnel_type, $tunnel_type_values) || !in_array($tunnel_medium_type, $tunnel_medium_type_values) || ($tunnel_type xor $tunnel_medium_type)) {
return false;
}
$payload = [
'name' => $name,
'x_password' => $x_password,
];
if (!is_null($tunnel_type)) {
$payload['tunnel_type'] = (int) $tunnel_type;
}
if (!is_null($tunnel_medium_type)) {
$payload['tunnel_medium_type'] = (int) $tunnel_medium_type;
}
if (!is_null($vlan)) {
$payload['vlan'] = (string) $vlan;
}
return $this->fetch_results('/api/s/' . $this->site . '/rest/account', $payload);
}
public function set_radius_account_base($account_id, $payload)
{
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/account/' . trim($account_id), $payload);
}
public function delete_radius_account($account_id)
{
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/account/' . trim($account_id));
}
public function cmd_stat($command)
{
if ($command != 'reset-dpi') {
return false;
}
$payload = ['cmd' => trim($command)];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/stat', $payload);
}
public function set_element_adoption($enable)
{
if (!is_bool($enable)) {
return false;
}
$payload = ['enabled' => $enable];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/element_adopt', $payload);
}
public function list_device_states()
{
return [
0 => 'offline',
1 => 'connected',
2 => 'pending adoption',
4 => 'updating',
5 => 'provisioning',
6 => 'unreachable',
7 => 'adopting',
9 => 'adoption error',
10 => 'adoption failed',
11 => 'isolated',
];
}
public function custom_api_request($path, $method = 'GET', $payload = null, $return = 'array')
{
if (!in_array($method, $this->curl_methods_allowed)) {
return false;
}
if (strpos($path, '/') !== 0) {
return false;
}
$this->curl_method = $method;
if ($return === 'array') {
return $this->fetch_results($path, $payload);
} elseif ($return === 'boolean') {
return $this->fetch_results_boolean($path, $payload);
}
return false;
}
public function list_aps($device_mac = null)
{
trigger_error(
'Function list_aps() has been deprecated, use list_devices() instead.',
E_USER_DEPRECATED
);
return $this->list_devices($device_mac);
}
public function set_locate_ap($mac)
{
trigger_error(
'Function set_locate_ap() has been deprecated, use locate_ap() instead.',
E_USER_DEPRECATED
);
return $this->locate_ap($mac, true);
}
public function unset_locate_ap($mac)
{
trigger_error(
'Function unset_locate_ap() has been deprecated, use locate_ap() instead.',
E_USER_DEPRECATED
);
return $this->locate_ap($mac, false);
}
public function site_ledson()
{
trigger_error(
'Function site_ledson() has been deprecated, use site_leds() instead.',
E_USER_DEPRECATED
);
return $this->site_leds(true);
}
public function site_ledsoff()
{
trigger_error(
'Function site_ledsoff() has been deprecated, use site_leds() instead.',
E_USER_DEPRECATED
);
return $this->site_leds(false);
}
public function restart_ap($mac)
{
trigger_error(
'Function restart_ap() has been deprecated, use restart_device() instead.',
E_USER_DEPRECATED
);
return $this->restart_device($mac);
}
public function set_site($site)
{
$this->check_site($site);
$this->site = trim($site);
return $this->site;
}
public function get_site()
{
return $this->site;
}
public function set_debug($enable)
{
if ($enable === true || $enable === false) {
$this->debug = $enable;
return true;
}
trigger_error('Error: the parameter for set_debug() must be boolean');
return false;
}
public function get_debug()
{
return $this->debug;
}
public function get_last_results_raw($return_json = false)
{
if (!is_null($this->last_results_raw)) {
if ($return_json) {
return json_encode($this->last_results_raw, JSON_PRETTY_PRINT);
}
return $this->last_results_raw;
}
return false;
}
public function get_last_error_message()
{
return $this->last_error_message;
}
public function get_cookie()
{
return $this->cookies;
}
public function get_cookies()
{
return $this->cookies;
}
public function get_class_version()
{
return self::CLASS_VERSION;
}
public function set_cookies($cookies_value)
{
$this->cookies = $cookies_value;
}
public function get_curl_method()
{
return $this->curl_method;
}
public function set_curl_method($curl_method)
{
if (!in_array($curl_method, $this->curl_methods_allowed)) {
return false;
}
$this->curl_method = $curl_method;
return true;
}
public function get_curl_ssl_verify_peer()
{
return $this->curl_ssl_verify_peer;
}
public function set_curl_ssl_verify_peer($curl_ssl_verify_peer)
{
if (!in_array($curl_ssl_verify_peer, [0, false, 1, true])) {
return false;
}
$this->curl_ssl_verify_peer = $curl_ssl_verify_peer;
return true;
}
public function get_curl_ssl_verify_host()
{
return $this->curl_ssl_verify_host;
}
public function set_curl_ssl_verify_host($curl_ssl_verify_host)
{
if (!in_array($curl_ssl_verify_host, [0, false, 2])) {
return false;
}
$this->curl_ssl_verify_host = $curl_ssl_verify_host;
return true;
}
public function get_is_unifi_os()
{
return $this->is_unifi_os;
}
public function set_is_unifi_os($is_unifi_os)
{
if (!in_array($is_unifi_os, [0, false, 1, true])) {
return false;
}
$this->is_unifi_os = $is_unifi_os;
return true;
}
public function set_connection_timeout($timeout)
{
$this->curl_connect_timeout = $timeout;
}
public function get_connection_timeout()
{
return $this->curl_connect_timeout;
}
public function set_curl_request_timeout($timeout)
{
$this->curl_request_timeout = $timeout;
}
public function get_curl_request_timeout()
{
return $this->curl_request_timeout;
}
public function set_curl_http_version($http_version)
{
$this->curl_http_version = $http_version;
}
public function get_curl_http_version()
{
return $this->curl_http_version;
}
protected function fetch_results($path, $payload = null, $boolean = false, $login_required = true)
{
if ($login_required && !$this->is_logged_in) {
return false;
}
$this->last_results_raw = $this->exec_curl($path, $payload);
if (is_string($this->last_results_raw)) {
$response = json_decode($this->last_results_raw);
$this->catch_json_last_error();
if (isset($response->meta->rc)) {
if ($response->meta->rc === 'ok') {
$this->last_error_message = '';
if (is_array($response->data) && !$boolean) {
return $response->data;
}
return true;
} elseif ($response->meta->rc === 'error') {
if (isset($response->meta->msg)) {
$this->last_error_message = $response->meta->msg;
if ($this->debug) {
trigger_error('Debug: Last error message: ' . $this->last_error_message);
}
}
}
}
if (strpos($path, '/v2/api/') === 0) {
if (isset($response->errorCode)) {
if (isset($response->message)) {
$this->last_error_message = $response->message;
if ($this->debug) {
trigger_error('Debug: Last error message: ' . $this->last_error_message);
}
}
return false;
}
return $response;
}
}
return false;
}
protected function fetch_results_boolean($path, $payload = null, $login_required = true)
{
return $this->fetch_results($path, $payload, true, $login_required);
}
protected function catch_json_last_error()
{
if ($this->debug) {
$error = 'Unknown JSON error occurred';
switch (json_last_error()) {
case JSON_ERROR_NONE:
// JSON is valid, no error has occurred and return true early
return true;
case JSON_ERROR_DEPTH:
$error = 'The maximum stack depth has been exceeded';
break;
case JSON_ERROR_STATE_MISMATCH:
$error = 'Invalid or malformed JSON';
break;
case JSON_ERROR_CTRL_CHAR:
$error = 'Control character error, possibly incorrectly encoded';
break;
case JSON_ERROR_SYNTAX:
$error = 'Syntax error, malformed JSON';
break;
case JSON_ERROR_UTF8:
// PHP >= 5.3.3
$error = 'Malformed UTF-8 characters, possibly incorrectly encoded';
break;
case JSON_ERROR_RECURSION:
// PHP >= 5.5.0
$error = 'One or more recursive references in the value to be encoded';
break;
case JSON_ERROR_INF_OR_NAN:
// PHP >= 5.5.0
$error = 'One or more NAN or INF values in the value to be encoded';
break;
case JSON_ERROR_UNSUPPORTED_TYPE:
$error = 'A value of a type that cannot be encoded was given';
break;
}
if (defined('JSON_ERROR_INVALID_PROPERTY_NAME') && defined('JSON_ERROR_UTF16')) {
switch (json_last_error()) {
case JSON_ERROR_INVALID_PROPERTY_NAME:
$error = 'A property name that cannot be encoded was given';
break;
case JSON_ERROR_UTF16:
$error = 'Malformed UTF-16 characters, possibly incorrectly encoded';
break;
}
}
trigger_error('JSON decode error: ' . $error);
return false;
}
return true;
}
protected function check_base_url($baseurl)
{
if (!filter_var($baseurl, FILTER_VALIDATE_URL) || substr($baseurl, -1) === '/') {
trigger_error('The URL provided is incomplete, invalid or ends with a / character!');
return false;
}
return true;
}
protected function check_site($site)
{
if ($this->debug && preg_match("/\s/", $site)) {
trigger_error('The provided (short) site name may not contain any spaces');
return false;
}
return true;
}
protected function update_unificookie()
{
if (session_status() === PHP_SESSION_ACTIVE && isset($_SESSION['unificookie']) && !empty($_SESSION['unificookie'])) {
$this->cookies = $_SESSION['unificookie'];
if (strpos($this->cookies, 'TOKEN') !== false) {
$this->is_unifi_os = true;
}
return true;
}
return false;
}
protected function create_x_csrf_token_header()
{
if (!empty($this->cookies) && strpos($this->cookies, 'TOKEN') !== false) {
$cookie_bits = explode('=', $this->cookies);
if (empty($cookie_bits) || !array_key_exists(1, $cookie_bits)) {
return;
}
$jwt_components = explode('.', $cookie_bits[1]);
if (empty($jwt_components) || !array_key_exists(1, $jwt_components)) {
return;
}
$this->curl_headers[] = 'x-csrf-token: ' . json_decode(base64_decode($jwt_components[1]))->csrfToken;
}
}
protected function response_header_callback($ch, $header_line)
{
if (strpos($header_line, 'unifises') !== false || strpos($header_line, 'TOKEN') !== false) {
$cookie = trim(str_replace(['set-cookie: ', 'Set-Cookie: '], '', $header_line));
if (!empty($cookie)) {
$cookie_crumbs = explode(';', $cookie);
foreach ($cookie_crumbs as $cookie_crumb) {
if (strpos($cookie_crumb, 'unifises') !== false) {
$this->cookies = $cookie_crumb;
$this->is_logged_in = true;
$this->is_unifi_os = false;
break;
}
if (strpos($cookie_crumb, 'TOKEN') !== false) {
$this->cookies = $cookie_crumb;
$this->is_logged_in = true;
$this->is_unifi_os = true;
break;
}
}
}
}
return strlen($header_line);
}
protected function exec_curl($path, $payload = null)
{
if (!in_array($this->curl_method, $this->curl_methods_allowed)) {
trigger_error('an invalid HTTP request type was used: ' . $this->curl_method);
return false;
}
if (!($ch = $this->get_curl_handle())) {
trigger_error('get_curl_handle() did not return a resource');
return false;
}
$this->curl_headers = [];
$url = $this->baseurl . $path;
if ($this->is_unifi_os) {
$url = $this->baseurl . '/proxy/network' . $path;
}
$curl_options = [
CURLOPT_URL => $url,
];
$json_payload = '';
if (!empty($payload)) {
$json_payload = json_encode($payload, JSON_UNESCAPED_SLASHES);
$curl_options[CURLOPT_POSTFIELDS] = $json_payload;
$this->curl_headers = [
'content-type: application/json',
'Expect:',
];
if ($this->curl_method === 'GET' || $this->curl_method === 'DELETE') {
$this->curl_method = 'POST';
}
}
switch ($this->curl_method) {
case 'POST':
$curl_options[CURLOPT_POST] = true;
break;
case 'DELETE':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
break;
case 'PUT':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'PUT';
break;
case 'PATCH':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'PATCH';
break;
}
if ($this->is_unifi_os && $this->curl_method !== 'GET') {
$this->create_x_csrf_token_header();
}
if (count($this->curl_headers) > 0) {
$curl_options[CURLOPT_HTTPHEADER] = $this->curl_headers;
}
curl_setopt_array($ch, $curl_options);
$response = curl_exec($ch);
if (curl_errno($ch)) {
trigger_error('cURL error: ' . curl_error($ch));
}
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code === 401) {
if ($this->debug) {
error_log(__FUNCTION__ . ': needed to reconnect to UniFi controller');
}
if ($this->exec_retries === 0) {
if (isset($_SESSION['unificookie'])) {
$_SESSION['unificookie'] = '';
}
$this->is_logged_in = false;
$this->cookies = '';
$this->exec_retries++;
curl_close($ch);
$this->login();
if ($this->is_logged_in) {
if ($this->debug) {
error_log(__FUNCTION__ . ': re-logged in, calling exec_curl again');
}
return $this->exec_curl($path, $payload);
}
if ($this->debug) {
error_log(__FUNCTION__ . ': re-login failed');
}
}
return false;
}
if ($this->debug) {
print PHP_EOL . '<pre>';
print PHP_EOL . '---------cURL INFO-----------' . PHP_EOL;
print_r(curl_getinfo($ch));
print PHP_EOL . '-------URL & PAYLOAD---------' . PHP_EOL;
print $url . PHP_EOL;
if (empty($json_payload)) {
print 'empty payload';
}
print $json_payload;
print PHP_EOL . '----------RESPONSE-----------' . PHP_EOL;
print $response;
print PHP_EOL . '-----------------------------' . PHP_EOL;
print '</pre>' . PHP_EOL;
}
curl_close($ch);
$this->curl_method = 'GET';
return $response;
}
protected function get_curl_handle()
{
$ch = curl_init();
if (is_object($ch) || is_resource($ch)) {
$curl_options = [
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_HTTP_VERSION => $this->curl_http_version,
CURLOPT_SSL_VERIFYPEER => $this->curl_ssl_verify_peer,
CURLOPT_SSL_VERIFYHOST => $this->curl_ssl_verify_host,
CURLOPT_CONNECTTIMEOUT => $this->curl_connect_timeout,
CURLOPT_TIMEOUT => $this->curl_request_timeout,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_HEADERFUNCTION => [$this, 'response_header_callback'],
];
if ($this->debug) {
$curl_options[CURLOPT_VERBOSE] = true;
}
if (!empty($this->cookies)) {
$curl_options[CURLOPT_COOKIESESSION] = true;
$curl_options[CURLOPT_COOKIE] = $this->cookies;
}
curl_setopt_array($ch, $curl_options);
return $ch;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment