Compare commits

...

9 Commits

Author SHA1 Message Date
malle-pietje
aefbbdc5e1 API client class v1.1.75
- updated docblocks to be less USG-specific
- removed content-length header from the logout method, reported by @Olivier6767
- added notes to reflect successful tests with UDR running latest Pre-Release version of the UniFi controller (version 6.5.52)
- added checks in specific cases when using trim() to prevent PHP 8 from throwing an error when the variable is null, submitted by @djchen
2021-12-18 12:00:56 +01:00
malle-pietje
fbfd6a8246 API client class v1.1.74
- minor refactoring
- fixed minor typos
- updated README to reflect limited visibility when using read-only administrator accounts, reported by @KetchupBomb and @NickDunas
2021-11-08 10:30:22 +01:00
malle-pietje
310abc43b5 API client class v1.1.73
- minor spacing changes based on Scrutinizer feedback
- updated create_wlan() method/function to work with the new way of assigning a VLAN which now requires passing the _id value
of the VLAN, reported by @BeneReuthlinger
- merged #132, README update, contributed by @pauloboc
- merged #133, adds edit_client_name() method, contributed by @pauloboc
2021-10-23 11:14:25 +02:00
malle-pietje
01eafb516a Merge branch 'master' of github.com:Art-of-WiFi/UniFi-API-client
merge #133
2021-10-23 10:34:46 +02:00
Paulo Ferreira
c3c44d61e4 Add method rename client (#133)
* Update Client.php

Add method rename client

* Update README.md
2021-10-23 10:34:39 +02:00
malle-pietje
2e7b556d8e Merge branch 'master' of github.com:Art-of-WiFi/UniFi-API-client
merged #132
2021-10-23 10:32:41 +02:00
malle-pietje
e7e1540df4 - minor spacing changes based on Scrutinizer feedback
- updated create_wlan() method/function to work with the new way of assigning a VLAN which now requires passing the _id value
of the VLAN, reported by @BeneReuthlinger
2021-10-23 10:32:20 +02:00
Paulo Ferreira
adb98a3c8e Update README.md (#132)
Fix parameters separations
2021-10-22 17:35:05 +02:00
malle-pietje
9cca43557c API client class v1.1.72
- added property $request_timeout to control the cURL option CURLOPT_TIMEOUT, contributed by @mreho
- added setter and getter for $request_timeout, contributed by @mreho
- changed default value for the cURL option CURLOPT_HTTP_VERSION to CURL_HTTP_VERSION_1_1:
    - as of cURL version 7.62.0 the default value is CURL_HTTP_VERSION_2TLS which may cause issues
    - https://curl.se/libcurl/c/CURLOPT_HTTP_VERSION.html
- added property for $curl_http_version to hold the value for CURLOPT_HTTP_VERSION
- added setter and getter for $curl_http_version
- switched to using a constant to hold the class version
- updated the README file
2021-10-19 10:39:17 +02:00
4 changed files with 351 additions and 252 deletions

121
README.md
View File

@@ -1,44 +1,51 @@
## UniFi Controller API client class
A PHP class that provides access to Ubiquiti's [**UniFi Network Controller**](https://unifi-network.ui.com/) API,
versions 4.X.X, 5.X.X and 6.X.X of the UniFi Network Controller software are supported (version 6.3.51 has been
confirmed to work) as well as UniFi OS-based controllers (version 5.12.59 has been confirmed to work). This class is
used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser).
A PHP class that provides access to Ubiquiti's [**UniFi Network Controller**](https://unifi-network.ui.com/) API.
UniFi Network Controller software versions 4.X.X, 5.X.X and 6.X.X are supported as well as UniFi OS-based controllers (version 6.5.55 has been confirmed to work).
This class is used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser).
The package can be installed manually or by using
composer/[packagist](https://packagist.org/packages/art-of-wifi/unifi-api-client) for easy inclusion in your projects.
composer/[packagist](https://packagist.org/packages/art-of-wifi/unifi-api-client) for
easy inclusion in your projects.
## Requirements
- a server with PHP, version 5.5.0 or higher, and the PHP cURL module installed (tested on Apache 2.4 with PHP Version
5.6.1 and cURL 7.42.1 and with PHP 7.2.24 and cURL 7.58.0)
- direct network connectivity between this server and the host and port (normally TCP port 8443) where the UniFi
Controller is running
- you must use **local accounts**, not UniFi Cloud accounts, to access the UniFi Controller API through this class
- a server with:
- PHP 5.5.0 or higher
- PHP json and PHP cURL modules
- tested on Apache 2.4 with PHP 5.6.1 and cURL 7.42.1 and with PHP 7.4.9 and cURL 7.68.0
- direct network connectivity between this server and the host and port (normally TCP port 8443 or port 443 for
UniFi OS) where the UniFi Controller is running
- you must use **accounts with local access**, not pure UniFi Cloud accounts, to access the UniFi Controller API through
this class
## UniFi OS Support
Support for UniFi OS-based controllers (UniFi Dream Machine Pro or Cloud Key Gen2/Cloud Key Gen2 Plus with firmware
version 2.0.24 or higher) has been added as of version 1.1.47. The class automatically detects UniFi OS devices and
adjusts URLs and several functions/methods accordingly. If your own code applies strict validation of the URL that is
passed to the constructor, please adapt your logic to allow URLs without a port suffix when dealing with a UniFi
OS-based controller.
Support for UniFi OS-based controllers (UniFi Dream Router, UniFi Dream Machine, UniFi Dream Machine Pro
or Cloud Key Gen2/Cloud Key Gen2 Plus with firmware version 2.0.24 or higher) has
been added as of version 1.1.47. The class automatically detects UniFi OS devices and
adjusts URLs and several functions/methods accordingly. If your own code implements strict
validation of the URL that is passed to the constructor, please adapt your logic to
allow URLs without a port suffix or with port 443 when dealing with a UniFi OS-based
controller.
Please test all methods you plan on using thoroughly before using the API Client with UniFi OS devices in a production
environment.
Please test all methods you plan on using thoroughly before using the API Client with
UniFi OS devices in a production environment.
## Installation
Use [Composer](#composer), [Git](#git) or simply [Download the Release](#download-the-release) to install the API client
class.
Use [Composer](#composer), [Git](#git) or simply [Download the Release](#download-the-release) to install the
API client class.
### Composer
The preferred installation method is through [composer](https://getcomposer.org). Follow
these [installation instructions](https://getcomposer.org/doc/00-intro.md) if you do not already have composer
installed.
The preferred installation method is through [composer](https://getcomposer.org).
Follow these [installation instructions](https://getcomposer.org/doc/00-intro.md) if you don't have composer
installed already.
Once composer is installed, simply execute this command from the shell in your project directory:
Once composer is installed, simply execute this command from the shell in your project
directory:
```sh
composer require art-of-wifi/unifi-api-client
@@ -77,7 +84,7 @@ require_once 'path/to/src/Client.php';
### Download the Release
If you prefer not to use composer or git,
simply [download the package](https://github.com/Art-of-WiFi/UniFi-API-client/archive/master.zip), uncompress the zip
simply [download the package](https://github.com/Art-of-WiFi/UniFi-API-client/archive/master.zip), unpack the zip
file, then include the file containing the class in your code like so:
```php
@@ -115,16 +122,21 @@ own PHP code.
`jl3z2shm` is the short site "name" and the value to assign to $site_id.
2. The last optional parameter that is passed to the constructor in the above example (`true`), enables validation of
2. The 6th optional parameter that is passed to the constructor in the above example (`true`), enables validation of
the controller's SSL certificate which is otherwise **disabled** by default. It is **highly recommended** to enable
this feature in production environments where you have a valid SSL cert installed on the UniFi Controller that is
associated with the FQDN in the `controller_url` parameter. This option was added with API client version 1.1.16.
3. Using an administrator account (`$controller_user` in the above example) with **read-only** permissions can limit
visibility on certain collection/object properties. See this [issue](https://github.com/Art-of-WiFi/UniFi-API-client/issues/129)
and this [issue](https://github.com/Art-of-WiFi/UniFi-API-browser/issues/94) for an example where the WPA2 password
isn't accessible for **read-only** administrator accounts.
## Functions/methods supported
The class currently supports the following functions/methods to GET/POST/PUT/DELETE data through the UniFi Controller
API. Please refer to the comments in the source code for more details on the functions/methods and their respective
parameters.
The class currently supports the following functions/methods to GET/POST/PUT/DELETE data
through the UniFi Controller API. Please refer to the comments in the source code for
more details on each of the functions/methods and their respective parameters.
- login()
- logout()
@@ -134,10 +146,10 @@ parameters.
- authorize_guest()
- block_sta()
- cancel_rolling_upgrade()
- cmd_stat()
- count_alarms()
- check_controller_update()
- check_firmware_update()
- cmd_stat()
- count_alarms()
- create_apgroup() (supported with controller versions 6.0.X and higher)
- create_dynamicdns()
- create_firewallgroup()
@@ -161,6 +173,7 @@ parameters.
- disable_ap()
- edit_apgroup() (supported with controller versions 6.0.X and higher)
- edit_client_fixedip()
- edit_client_name()
- edit_firewallgroup()
- edit_usergroup()
- extend_guest_validity()
@@ -177,8 +190,8 @@ parameters.
- list_country_codes()
- list_current_channels()
- list_dashboard()
- list_devices()
- list_device_name_mappings()
- list_devices()
- list_dpi_stats()
- list_dynamicdns()
- list_events()
@@ -259,24 +272,24 @@ parameters.
- stat_daily_gateway() (supported on controller version 5.7.X and higher)
- stat_daily_site()
- stat_daily_user() (supported on controller version 5.7.X and higher)
- stat_full_status()
- stat_hourly_aps()
- stat_hourly_gateway() (supported on controller version 5.7.X and higher)
- stat_hourly_site()
- stat_hourly_user() (supported on controller version 5.7.X and higher)
- stat_ips_events() (supported on controller version 5.9.10 and higher)
- stat_monthly_aps()
- stat_monthly_gateway()
- stat_monthly_site()
- stat_monthly_user()
- stat_payment()
- stat_sessions()
- stat_sites()
- stat_speedtest_results()
- stat_sta_sessions_latest()
- stat_status()
- stat_full_status()
- stat_sysinfo()
- stat_voucher()
- stat_monthly_aps()
- stat_monthly_gateway()
- stat_monthly_site()
- stat_monthly_user()
- unauthorize_guest()
- unblock_sta()
- unset_locate_ap() (deprecated but still available as alias)
@@ -286,38 +299,44 @@ parameters.
Other functions, getters/setters:
- get_class_version()
- get_connection_timeout()
- get_cookie() (renamed from getcookie(), deprecated but still available, use get_cookies() instead)
- get_cookies()
- get_curl_connection_timeout()
- get_curl_http_version()
- get_curl_method()
- get_curl_request_timeout()
- get_curl_request_timeout()
- get_curl_ssl_verify_host()
- get_curl_ssl_verify_peer()
- get_debug()
- get_is_unifi_os()
- get_last_error_message()
- get_last_results_raw()
- get_request_method()
- get_site()
- get_ssl_verify_host()
- get_ssl_verify_peer()
- set_connection_timeout()
- set_cookies()
- set_curl_http_version()
- set_curl_request_timeout()
- set_curl_ssl_verify_host()
- set_curl_ssl_verify_peer()
- set_debug()
- set_is_unifi_os()
- set_request_method()
- set_request_timeout()
- set_site()
- set_ssl_verify_host()
- set_ssl_verify_peer()
## Need help or have suggestions?
There is still work to be done to add functionality and further improve the usability of this class, so all
suggestions/comments are welcome. Please use the
GitHub [issue list](https://github.com/Art-of-WiFi/UniFi-API-client/issues) or the Ubiquiti Community
forums (https://community.ubnt.com/t5/UniFi-Wireless/PHP-class-to-access-the-UniFi-controller-API-updates-and/td-p/1512870)
There is still work to be done to add functionality and further improve the usability of
this class, so all suggestions/comments are welcome. Please use the GitHub
[issue list](https://github.com/Art-of-WiFi/UniFi-API-client/issues) or the Ubiquiti
Community forums (https://community.ubnt.com/t5/UniFi-Wireless/PHP-class-to-access-the-UniFi-controller-API-updates-and/td-p/1512870)
to share your suggestions and questions.
## Contribute
If you would like to contribute code (improvements), please open an issue and include your code there or else create a
pull request.
If you would like to contribute code (improvements), please open an issue and include
your code there or else create a pull request.
## Credits
@@ -328,9 +347,9 @@ This class is based on the initial work by the following developers:
and the API as published by Ubiquiti:
- https://dl.ui.com/unifi/6.2.26/unifi_sh_api
- https://dl.ui.com/unifi/6.5.55/unifi_sh_api
## Important Disclaimer
Many of the functions in this API client class are not officially supported by Ubiquiti and as such, may not be
supported in future versions of the UniFi Controller API.
Many of the functions in this API client class are not officially supported by Ubiquiti
and as such, may not be supported in future versions of the UniFi Controller API.

View File

@@ -16,7 +16,7 @@
{
"name": "Art of WiFi",
"email": "info@artofowifi.net",
"homepage": "http://artofwifi.net"
"homepage": "https://artofwifi.net"
}
],
"require": {

View File

@@ -29,24 +29,25 @@ $ch = curl_init();
if (is_resource($ch) || is_object($ch)) {
/**
* If we have a resource or object (for PHP > 8.0), we proceed and set the required cURL options
*/
curl_setopt($ch, CURLOPT_URL, $controllerurl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
/**
* This cURL option can have a value of 0-6
*
* NOTES:
* The cURL option CURLOPT_SSLVERSION can have a value of 0-6
* see this URL for more details:
* http://php.net/manual/en/function.curl-setopt.php
* 0 is the default value and is used by the PHP API client class
*/
curl_setopt($ch, CURLOPT_SSLVERSION, 0);
$curl_options = [
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_URL => $controllerurl,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_VERBOSE => true,
CURLOPT_SSLVERSION => 0,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
];
/**
* Be more verbose
*/
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt_array($ch, $curl_options);
/**
* $results contains the output as returned by the cURL request,

View File

@@ -13,7 +13,7 @@ namespace UniFi_API;
*
* @package UniFi_Controller_API_Client_Class
* @author Art of WiFi <info@artofwifi.net>
* @version Release: 1.1.71
* @version Release: 1.1.75
* @license This class is subject to the MIT license that is bundled with this package in the file LICENSE.md
* @example This directory in the package repository contains a collection of examples:
* https://github.com/Art-of-WiFi/UniFi-API-client/tree/master/examples
@@ -22,26 +22,31 @@ class Client
{
/**
* private and protected properties
*
* NOTE:
* do not modify the values here, instead use the constructor or the getter and setter functions/methods
*/
private $class_version = '1.1.71';
const CLASS_VERSION = '1.1.75';
protected $baseurl = 'https://127.0.0.1:8443';
protected $user = '';
protected $password = '';
protected $site = 'default';
protected $version = '6.0.43';
protected $version = '6.2.26';
protected $debug = false;
protected $ssl_verify_peer = false;
protected $ssl_verify_host = false;
protected $is_loggedin = false;
protected $is_logged_in = false;
protected $is_unifi_os = false;
protected $exec_retries = 0;
protected $cookies = '';
protected $headers = [];
protected $method = 'GET';
protected $methods_allowed = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
protected $connect_timeout = 10;
protected $last_results_raw = null;
protected $last_error_message = null;
protected $curl_ssl_verify_peer = false;
protected $curl_ssl_verify_host = false;
protected $curl_http_version = CURL_HTTP_VERSION_1_1;
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;
/**
* Construct an instance of the UniFi API client class
@@ -55,7 +60,7 @@ class Client
* @param string $version optional, the version number of the controller
* @param bool $ssl_verify optional, whether to validate the controller's SSL certificate or not, a value of true
* is recommended for production environments to prevent potential MitM attacks, default
* value (false) disables validation of the controller certificate
* value (false) disables validation of the controller's SSL certificate
*/
public function __construct($user, $password, $baseurl = '', $site = '', $version = '', $ssl_verify = false)
{
@@ -80,9 +85,9 @@ class Client
$this->version = trim($version);
}
if ((boolean)$ssl_verify === true) {
$this->ssl_verify_peer = true;
$this->ssl_verify_host = 2;
if ((bool) $ssl_verify === true) {
$this->curl_ssl_verify_peer = true;
$this->curl_ssl_verify_host = 2;
}
}
@@ -104,7 +109,7 @@ class Client
/**
* log out, if needed
*/
if ($this->is_loggedin) {
if ($this->is_logged_in) {
$this->logout();
}
}
@@ -112,25 +117,23 @@ class Client
/**
* Login to the UniFi controller
*
* @return bool returns true upon success
* @return bool|int returns true upon success, false or HTTP status upon error
*/
public function login()
{
/**
* skip the login process if already logged in
*/
if ($this->is_loggedin === true) {
return true;
if ($this->update_unificookie()) {
$this->is_logged_in = true;
}
if ($this->update_unificookie()) {
$this->is_loggedin = true;
if ($this->is_logged_in === true) {
return true;
}
/**
* check whether this is a "regular" controller or one based on UniFi OS,
* prepare cURL and options
* prepare cURL and options to check whether this is a "regular" controller or one based on UniFi OS
*/
if (!($ch = $this->get_curl_handle())) {
return false;
@@ -214,8 +217,8 @@ class Client
* check the HTTP response code
*/
if ($http_code >= 200 && $http_code < 400) {
$this->is_loggedin = true;
return $this->is_loggedin;
$this->is_logged_in = true;
return $this->is_logged_in;
}
return false;
@@ -241,10 +244,9 @@ class Client
];
/**
* constuct HTTP request headers as required
* construct the HTTP request headers as required
*/
$this->headers = [
'content-length: 0',
$this->curl_headers = [
'Expect:',
];
@@ -256,7 +258,7 @@ class Client
$this->create_x_csrf_token_header();
}
$curl_options[CURLOPT_HTTPHEADER] = $this->headers;
$curl_options[CURLOPT_HTTPHEADER] = $this->curl_headers;
$curl_options[CURLOPT_URL] = $this->baseurl . $logout_path;
curl_setopt_array($ch, $curl_options);
@@ -273,7 +275,7 @@ class Client
curl_close($ch);
$this->is_loggedin = false;
$this->is_logged_in = false;
$this->cookies = '';
return true;
}
@@ -796,7 +798,7 @@ class Client
* - this function/method is only supported on controller versions 5.5.* and later
* - make sure that the retention policy for 5 minutes stats is set to the correct value in
* the controller settings
* - requires a USG
* - requires a UniFi gateway
*
* @param int $start optional, Unix timestamp in milliseconds
* @param int $end optional, Unix timestamp in milliseconds
@@ -820,7 +822,7 @@ class Client
*
* NOTES:
* - defaults to the past 7*24 hours
* - requires a USG
* - requires a UniFi gateway
*
* @param int $start optional, Unix timestamp in milliseconds
* @param int $end optional, Unix timestamp in milliseconds
@@ -844,7 +846,7 @@ class Client
*
* NOTES:
* - defaults to the past 52 weeks (52*7*24 hours)
* - requires a USG
* - requires a UniFi gateway
*
* @param int $start optional, Unix timestamp in milliseconds
* @param int $end optional, Unix timestamp in milliseconds
@@ -868,7 +870,7 @@ class Client
*
* NOTES:
* - defaults to the past 52 weeks (52*7*24 hours)
* - requires a USG
* - requires a UniFi gateway
*
* @param int $start optional, Unix timestamp in milliseconds
* @param int $end optional, Unix timestamp in milliseconds
@@ -892,7 +894,7 @@ class Client
*
* NOTES:
* - defaults to the past 24 hours
* - requires a USG
* - requires a UniFi gateway
*
* @param int $start optional, Unix timestamp in milliseconds
* @param int $end optional, Unix timestamp in milliseconds
@@ -906,13 +908,12 @@ class Client
return $this->fetch_results('/api/s/' . $this->site . '/stat/report/archive.speedtest', $payload);
}
/**
* Fetch IPS/IDS events
*
* NOTES:
* - defaults to the past 24 hours
* - requires a USG
* - requires a UniFi gateway
* - supported in UniFi controller versions 5.9.X and higher
*
* @param int $start optional, Unix timestamp in milliseconds
@@ -1036,13 +1037,17 @@ class Client
*/
public function list_clients($client_mac = null)
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/sta/' . strtolower(trim($client_mac)));
if (is_string($client_mac)) {
$client_mac = strtolower(trim($client_mac));
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/sta/' . $client_mac);
}
/**
* Fetch details for a single client device
*
* @param string $client_mac optional, client device MAC address
* @param string $client_mac client device MAC address
* @return array returns an object with the client device information
*/
public function stat_client($client_mac)
@@ -1053,23 +1058,23 @@ class Client
/**
* Assign client device to another group
*
* @param string $user_id id of the user device to be modified
* @param string $group_id id of the user group to assign user to
* @param string $client_id _id value of the client device to be modified
* @param string $group_id _id value of the user group to assign client device to
* @return bool returns true upon success
*/
public function set_usergroup($user_id, $group_id)
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($user_id), $payload);
return $this->fetch_results_boolean('/api/s/' . $this->site . '/upd/user/' . trim($client_id), $payload);
}
/**
* Update client fixedip (using REST)
* Update client device fixed IP address (using REST)
*
* @param string $client_id _id value for the client
* @param bool $use_fixedip determines whether use_fixedip is true or false
* @param string $client_id _id value for the client device
* @param bool $use_fixedip determines whether to enable the fixed IP address or not
* @param string $network_id optional, _id value for the network where the ip belongs to
* @param string $fixed_ip optional, IP address, value of client's fixed_ip field
* @param string $fixed_ip optional, IP address, value of client device's fixed_ip field
* @return array|false returns an array containing a single object with attributes of the updated client on success
*/
public function edit_client_fixedip($client_id, $use_fixedip, $network_id = null, $fixed_ip = null)
@@ -1078,7 +1083,7 @@ class Client
return false;
}
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = [
'_id' => $client_id,
'use_fixedip' => $use_fixedip,
@@ -1097,6 +1102,28 @@ class Client
return $this->fetch_results('/api/s/' . $this->site . '/rest/user/' . trim($client_id), $payload);
}
/**
* Update client device name (using REST)
*
* @param string $client_id _id value for the client device
* @param string $name name of the client
* @return array|false returns an array containing a single object with attributes of the updated client on success
*/
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);
}
/**
* Fetch user groups
*
@@ -1138,7 +1165,7 @@ class Client
*/
public function edit_usergroup($group_id, $site_id, $group_name, $group_dn = -1, $group_up = -1)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'name' => $group_name,
@@ -1157,7 +1184,7 @@ class Client
*/
public function delete_usergroup($group_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/usergroup/' . trim($group_id));
}
@@ -1196,7 +1223,7 @@ class Client
*/
public function edit_apgroup($group_id, $group_name, $device_macs)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'attr_no_delete' => false,
@@ -1214,7 +1241,7 @@ class Client
*/
public function delete_apgroup($group_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/v2/api/site/' . $this->site . '/apgroups/' . trim($group_id));
}
@@ -1268,7 +1295,7 @@ class Client
return false;
}
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = [
'_id' => $group_id,
'name' => $group_name,
@@ -1287,7 +1314,7 @@ class Client
*/
public function delete_firewallgroup($group_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/firewallgroup/' . trim($group_id));
}
@@ -1353,7 +1380,11 @@ class Client
*/
public function list_devices($device_mac = null)
{
return $this->fetch_results('/api/s/' . $this->site . '/stat/device/' . strtolower(trim($device_mac)));
if (is_string($device_mac)) {
$device_mac = strtolower(trim($device_mac));
}
return $this->fetch_results('/api/s/' . $this->site . '/stat/device/' . $device_mac);
}
/**
@@ -1396,7 +1427,7 @@ class Client
* NOTES:
* this is an experimental function, please do not use unless you know exactly what you're doing
*
* @return bool|array|string URL from where the backup file can be downloaded once generated, false upon failure
* @return array|bool URL from where the backup file can be downloaded once generated, false upon failure
*/
public function generate_backup()
{
@@ -1489,7 +1520,7 @@ class Client
*/
public function set_site_country($country_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/country/' . trim($country_id),
$payload);
}
@@ -1500,7 +1531,7 @@ class Client
* @param string $locale_id _id value of the locale section
* @param object|array $payload stdClass object or associative array containing the configuration to apply to the
* site, must be a (partial) object/array structured in the same manner as is
* returned by list_settings() for section with the the "locale" key. Valid
* returned by list_settings() for section with the "locale" key. Valid
* timezones can be obtained in Javascript as explained here:
* https://stackoverflow.com/questions/38399465/how-to-get-list-of-all-timezones-in-javascript
* or in PHP using timezone_identifiers_list(). Do not include the _id property, it
@@ -1509,7 +1540,7 @@ class Client
*/
public function set_site_locale($locale_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/locale/' . trim($locale_id),
$payload);
}
@@ -1526,7 +1557,7 @@ class Client
*/
public function set_site_snmp($snmp_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/snmp/' . trim($snmp_id), $payload);
}
@@ -1542,7 +1573,7 @@ class Client
*/
public function set_site_mgmt($mgmt_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/mgmt/' . trim($mgmt_id), $payload);
}
@@ -1559,7 +1590,7 @@ class Client
*/
public function set_site_guest_access($guest_access_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/guest_access/' . trim($guest_access_id),
$payload);
}
@@ -1576,7 +1607,7 @@ class Client
*/
public function set_site_ntp($ntp_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/ntp/' . trim($ntp_id), $payload);
}
@@ -1593,7 +1624,7 @@ class Client
*/
public function set_site_connectivity($connectivity_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/setting/connectivity/' . trim($connectivity_id),
$payload);
}
@@ -1684,13 +1715,13 @@ class Client
*
* @param string $admin_id _id value of the admin user to assign, can be obtained using the
* list_all_admins() method/function
* @param bool $readonly optional, whether or not the new admin has readonly
* @param bool $readonly optional, whether the new admin has readonly
* permissions, default value is false which gives the new admin
* Administrator permissions
* @param bool $device_adopt optional, whether or not the new admin has permissions to
* @param bool $device_adopt optional, whether the new admin has permissions to
* adopt devices, default value is false. With versions < 5.9.X this only applies
* when readonly is true.
* @param bool $device_restart optional, whether or not the new admin has permissions to
* @param bool $device_restart optional, whether the new admin has permissions to
* restart devices, default value is false. With versions < 5.9.X this only applies
* when readonly is true.
* @return bool true on success
@@ -1736,7 +1767,7 @@ class Client
}
/**
* Fetch wlan_groups
* Fetch WLAN groups
*
* @return array containing known wlan_groups
*/
@@ -1799,7 +1830,7 @@ class Client
/**
* Fetch self
*
* @return array containing information about the logged in user
* @return array containing information about the logged-in user
*/
public function list_self()
{
@@ -1841,7 +1872,7 @@ class Client
public function create_hotspotop($name, $x_password, $note = null)
{
$payload = ['name' => $name, 'x_password' => $x_password];
if (!isset($note)) {
if (is_string($note)) {
$payload['note'] = trim($note);
}
@@ -1889,7 +1920,7 @@ class Client
'quota' => intval($quota),
];
if (!is_null($note)) {
if (is_string($note)) {
$payload['note'] = trim($note);
}
@@ -1969,7 +2000,7 @@ class Client
$payload = ['type' => $type];
if (is_array($cat_filter) && $type == 'by_app') {
if (is_array($cat_filter) && $type === 'by_app') {
$payload['cats'] = $cat_filter;
}
@@ -2144,7 +2175,7 @@ class Client
return false;
}
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = ['disabled' => $disable];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($ap_id), $payload);
}
@@ -2167,7 +2198,7 @@ class Client
return false;
}
$this->method = 'PUT';
$this->curl_method = 'PUT';
$payload = ['led_override' => $override_mode];
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($device_id), $payload);
}
@@ -2453,7 +2484,7 @@ class Client
*/
public function set_dynamicdns($dynamicdns_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/dynamicdns/' . trim($dynamicdns_id),
$payload);
}
@@ -2494,7 +2525,7 @@ class Client
*/
public function set_networksettings_base($network_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/networkconf/' . trim($network_id),
$payload);
}
@@ -2507,7 +2538,7 @@ class Client
*/
public function delete_network($network_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/networkconf/' . trim($network_id));
}
@@ -2524,7 +2555,7 @@ class Client
}
/**
* Create a wlan
* Create a WLAN
*
* @param string $name SSID
* @param string $x_passphrase new pre-shared key, minimal length is 8 characters, maximum length is 63,
@@ -2537,8 +2568,9 @@ class Client
* @param string $security optional, security type (open, wep, wpapsk, wpaeap)
* @param string $wpa_mode optional, wpa mode (wpa, wpa2, ..)
* @param string $wpa_enc optional, encryption (auto, ccmp)
* @param boolean $vlan_enabled optional, enable/disable vlan for this wlan
* @param int $vlan optional, vlan id
* @param boolean $vlan_enabled optional, enable/disable VLAN for this wlan (is ignored as of 1.1.73)
* @param string $vlan_id optional, "_id" value of the VLAN to assign to this WLAN, can be found using
* list_networkconf()
* @param boolean $uapsd_enabled optional, enable/disable Unscheduled Automatic Power Save Delivery
* @param boolean $schedule_enabled optional, enable/disable wlan schedule
* @param array $schedule optional, schedule rules
@@ -2557,35 +2589,34 @@ class Client
$security = 'open',
$wpa_mode = 'wpa2',
$wpa_enc = 'ccmp',
$vlan_enabled = false,
$vlan = null,
$vlan_enabled = null,
$vlan_id = null,
$uapsd_enabled = false,
$schedule_enabled = false,
$schedule = [],
$ap_group_ids = null
) {
$payload = [
'name' => $name,
'usergroup_id' => $usergroup_id,
'wlangroup_id' => $wlangroup_id,
'name' => trim($name),
'usergroup_id' => trim($usergroup_id),
'wlangroup_id' => trim($wlangroup_id),
'enabled' => $enabled,
'hide_ssid' => $hide_ssid,
'is_guest' => $is_guest,
'security' => $security,
'wpa_mode' => $wpa_mode,
'wpa_enc' => $wpa_enc,
'vlan_enabled' => $vlan_enabled,
'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) && $vlan_enabled) {
$payload['vlan'] = $vlan;
if (!empty($vlan_id)) {
$payload['networkconf_id'] = $vlan_id;
}
if (!empty($x_passphrase) && $security !== 'open') {
$payload['x_passphrase'] = $x_passphrase;
$payload['x_passphrase'] = trim($x_passphrase);
}
if (!empty($ap_group_ids) && is_array($ap_group_ids)) {
@@ -2600,14 +2631,13 @@ class Client
*
* @param string $wlan_id the "_id" value for the WLAN which can be found with the list_wlanconf() function
* @param object|array $payload stdClass object or associative array containing the configuration to apply to the
* wlan, must be a
* (partial) object/array structured in the same manner as is returned by
* list_wlanconf() for the wlan.
* wlan, must be a (partial) object/array structured in the same manner as is returned
* by list_wlanconf() for the wlan.
* @return bool true on success
*/
public function set_wlansettings_base($wlan_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/wlanconf/' . trim($wlan_id), $payload);
}
@@ -2625,7 +2655,7 @@ class Client
$payload = [];
$payload['x_passphrase'] = trim($x_passphrase);
if (!empty($name)) {
if (is_string($name)) {
$payload['name'] = trim($name);
}
@@ -2658,7 +2688,7 @@ class Client
*/
public function delete_wlan($wlan_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/wlanconf/' . trim($wlan_id));
}
@@ -2914,7 +2944,7 @@ class Client
*/
public function set_device_settings_base($device_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/device/' . trim($device_id), $payload);
}
@@ -3027,7 +3057,7 @@ class Client
*/
public function set_radius_account_base($account_id, $payload)
{
$this->method = 'PUT';
$this->curl_method = 'PUT';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/account/' . trim($account_id), $payload);
}
@@ -3042,7 +3072,7 @@ class Client
*/
public function delete_radius_account($account_id)
{
$this->method = 'DELETE';
$this->curl_method = 'DELETE';
return $this->fetch_results_boolean('/api/s/' . $this->site . '/rest/account/' . trim($account_id));
}
@@ -3123,7 +3153,7 @@ class Client
*/
public function custom_api_request($path, $method = 'GET', $payload = null, $return = 'array')
{
if (!in_array($method, $this->methods_allowed)) {
if (!in_array($method, $this->curl_methods_allowed)) {
return false;
}
@@ -3131,7 +3161,7 @@ class Client
return false;
}
$this->method = $method;
$this->curl_method = $method;
if ($return === 'array') {
return $this->fetch_results($path, $payload);
@@ -3148,10 +3178,10 @@ class Client
****************************************************************/
/**
* Fetch access points and other devices under management of the controller (USW and/or USG devices)
* Fetch access points and other devices under management of the controller (USW, USG, and/or UnIfi OS consoles)
*
* NOTE:
* changed function/method name to fit it's purpose
* changed function/method name to fit its purpose
*
* @param string $device_mac optional, the MAC address of a single device for which the call must be made
* @return array containing known device objects (or a single device when using the <device_mac> parameter)
@@ -3369,7 +3399,7 @@ class Client
*/
public function get_class_version()
{
return $this->class_version;
return self::CLASS_VERSION;
}
/**
@@ -3387,25 +3417,25 @@ class Client
*
* @return string request type
*/
public function get_method()
public function get_curl_method()
{
return $this->method;
return $this->curl_method;
}
/**
* Set request method
*
* @param string $method a valid HTTP request method
* @param string $curl_method a valid HTTP request method
* @return bool whether request was successful or not
*/
public function set_method($method)
public function set_curl_method($curl_method)
{
if (!in_array($method, $this->methods_allowed)) {
if (!in_array($curl_method, $this->curl_methods_allowed)) {
return false;
}
$this->method = $method;
$this->curl_method = $curl_method;
return true;
}
@@ -3417,9 +3447,9 @@ class Client
*
* @return bool value of private property $ssl_verify_peer (cURL option CURLOPT_SSL_VERIFYPEER)
*/
public function get_ssl_verify_peer()
public function get_curl_ssl_verify_peer()
{
return $this->ssl_verify_peer;
return $this->curl_ssl_verify_peer;
}
/**
@@ -3427,15 +3457,15 @@ class Client
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
*
* @param int|bool $ssl_verify_peer should be 0/false or 1/true
* @param int|bool $curl_ssl_verify_peer should be 0/false or 1/true
*/
public function set_ssl_verify_peer($ssl_verify_peer)
public function set_curl_ssl_verify_peer($curl_ssl_verify_peer)
{
if (!in_array($ssl_verify_peer, [0, false, 1, true])) {
if (!in_array($curl_ssl_verify_peer, [0, false, 1, true])) {
return false;
}
$this->ssl_verify_peer = $ssl_verify_peer;
$this->curl_ssl_verify_peer = $curl_ssl_verify_peer;
return true;
}
@@ -3447,9 +3477,9 @@ class Client
*
* @return bool value of private property $ssl_verify_peer (cURL option CURLOPT_SSL_VERIFYHOST)
*/
public function get_ssl_verify_host()
public function get_curl_ssl_verify_host()
{
return $this->ssl_verify_host;
return $this->curl_ssl_verify_host;
}
/**
@@ -3457,15 +3487,15 @@ class Client
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
*
* @param int|bool $ssl_verify_host should be 0/false or 2
* @param int|bool $curl_ssl_verify_host should be 0/false or 2
*/
public function set_ssl_verify_host($ssl_verify_host)
public function set_curl_ssl_verify_host($curl_ssl_verify_host)
{
if (!in_array($ssl_verify_host, [0, false, 2])) {
if (!in_array($curl_ssl_verify_host, [0, false, 2])) {
return false;
}
$this->ssl_verify_host = $ssl_verify_host;
$this->curl_ssl_verify_host = $curl_ssl_verify_host;
return true;
}
@@ -3504,17 +3534,64 @@ class Client
*/
public function set_connection_timeout($timeout)
{
$this->connect_timeout = $timeout;
$this->curl_connect_timeout = $timeout;
}
/**
* Get current value of the private property $connect_timeout
*
* @return int current value if $connect_timeout
* @return int current value of $connect_timeout
*/
public function get_connection_timeout()
{
return $this->connect_timeout;
return $this->curl_connect_timeout;
}
/**
* Set value for the private property $request_timeout
*
* @param int $timeout new value for $request_timeout in seconds
*/
public function set_curl_request_timeout($timeout)
{
$this->curl_request_timeout = $timeout;
}
/**
* Get current value of the private property $request_timeout
*
* @return int current value of $request_timeout
*/
public function get_curl_request_timeout()
{
return $this->curl_request_timeout;
}
/**
* Set value for the private property $curl_http_version
*
* NOTES:
* - as of cURL version 7.62.0 the default value is CURL_HTTP_VERSION_2TLS which may cause issues
* - the default value used in this class is CURL_HTTP_VERSION_1_1
* - https://curl.se/libcurl/c/CURLOPT_HTTP_VERSION.html
*
* @param int $http_version new value for $curl_http_version, can be CURL_HTTP_VERSION_1_1 int(2)
* or CURL_HTTP_VERSION_2TLS int(4)
*/
public function set_curl_http_version($http_version)
{
$this->curl_http_version = $http_version;
}
/**
* Get current value of the private property $curl_http_version
*
* @return int current value of $request_timeout, can be CURL_HTTP_VERSION_1_1 int(2) or
* CURL_HTTP_VERSION_2TLS int(4)
*/
public function get_curl_http_version()
{
return $this->curl_http_version;
}
/****************************************************************
@@ -3539,7 +3616,7 @@ class Client
/**
* guard clause to check if logged in when needed
*/
if ($login_required && !$this->is_loggedin) {
if ($login_required && !$this->is_logged_in) {
return false;
}
@@ -3746,7 +3823,7 @@ class Client
return;
}
$this->headers[] = 'x-csrf-token: ' . json_decode(base64_decode($jwt_components[1]))->csrfToken;
$this->curl_headers[] = 'x-csrf-token: ' . json_decode(base64_decode($jwt_components[1]))->csrfToken;
}
}
@@ -3767,7 +3844,7 @@ class Client
foreach ($cookie_crumbs as $cookie_crumb) {
if (strpos($cookie_crumb, 'unifises') !== false) {
$this->cookies = $cookie_crumb;
$this->is_loggedin = true;
$this->is_logged_in = true;
$this->is_unifi_os = false;
break;
@@ -3775,7 +3852,7 @@ class Client
if (strpos($cookie_crumb, 'TOKEN') !== false) {
$this->cookies = $cookie_crumb;
$this->is_loggedin = true;
$this->is_logged_in = true;
$this->is_unifi_os = true;
break;
@@ -3792,12 +3869,12 @@ class Client
*
* @param string $path path for the request
* @param object|array $payload optional, payload to pass with the request
* @return bool|array|string response returned by the controller API, false upon error
* @return bool|string response returned by the controller API, false upon error
*/
protected function exec_curl($path, $payload = null)
{
if (!in_array($this->method, $this->methods_allowed)) {
trigger_error('an invalid HTTP request type was used: ' . $this->method);
if (!in_array($this->curl_method, $this->curl_methods_allowed)) {
trigger_error('an invalid HTTP request type was used: ' . $this->curl_method);
return false;
}
@@ -3806,7 +3883,7 @@ class Client
return false;
}
$this->headers = [];
$this->curl_headers = [];
$url = $this->baseurl . $path;
if ($this->is_unifi_os) {
@@ -3828,7 +3905,7 @@ class Client
/**
* add empty Expect header to prevent cURL from injecting an "Expect: 100-continue" header
*/
$this->headers = [
$this->curl_headers = [
'content-type: application/json',
'Expect:',
];
@@ -3837,12 +3914,12 @@ class Client
* should not use GET (the default request type) or DELETE when passing a payload,
* switch to POST instead
*/
if ($this->method === 'GET' || $this->method === 'DELETE') {
$this->method = 'POST';
if ($this->curl_method === 'GET' || $this->curl_method === 'DELETE') {
$this->curl_method = 'POST';
}
}
switch ($this->method) {
switch ($this->curl_method) {
case 'POST':
$curl_options[CURLOPT_POST] = true;
break;
@@ -3857,12 +3934,12 @@ class Client
break;
}
if ($this->is_unifi_os && $this->method !== 'GET') {
if ($this->is_unifi_os && $this->curl_method !== 'GET') {
$this->create_x_csrf_token_header();
}
if (count($this->headers) > 0) {
$curl_options[CURLOPT_HTTPHEADER] = $this->headers;
if (count($this->curl_headers) > 0) {
$curl_options[CURLOPT_HTTPHEADER] = $this->curl_headers;
}
curl_setopt_array($ch, $curl_options);
@@ -3876,7 +3953,7 @@ class Client
}
/**
* fetch the HTTP response code
* get the HTTP response code
*/
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
@@ -3884,12 +3961,12 @@ class Client
* an HTTP response code 401 (Unauthorized) indicates the Cookie/Token has expired in which case
* re-login is required
*/
if ($http_code == 401) {
if ($http_code === 401) {
if ($this->debug) {
error_log(__FUNCTION__ . ': needed to reconnect to UniFi controller');
}
if ($this->exec_retries == 0) {
if ($this->exec_retries === 0) {
/**
* explicitly clear the expired Cookie/Token, update other properties and log out before logging in again
*/
@@ -3897,7 +3974,7 @@ class Client
$_SESSION['unificookie'] = '';
}
$this->is_loggedin = false;
$this->is_logged_in = false;
$this->cookies = '';
$this->exec_retries++;
curl_close($ch);
@@ -3910,7 +3987,7 @@ class Client
/**
* when re-login was successful, simply execute the same cURL request again
*/
if ($this->is_loggedin) {
if ($this->is_logged_in) {
if ($this->debug) {
error_log(__FUNCTION__ . ': re-logged in, calling exec_curl again');
}
@@ -3948,14 +4025,14 @@ class Client
/**
* set method back to default value, just in case
*/
$this->method = 'GET';
$this->curl_method = 'GET';
return $response;
}
/**
* Create and return a new cURL handle
*
* @return object|bool|resource cURL handle (object or resource) upon success, false upon failure
* @return object|resource|bool cURL handle (object or resource) upon success, false upon failure
*/
protected function get_curl_handle()
{
@@ -3963,9 +4040,11 @@ class Client
if (is_object($ch) || is_resource($ch)) {
$curl_options = [
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_SSL_VERIFYPEER => $this->ssl_verify_peer,
CURLOPT_SSL_VERIFYHOST => $this->ssl_verify_host,
CURLOPT_CONNECTTIMEOUT => $this->connect_timeout,
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'],