Compare commits

...

11 Commits

Author SHA1 Message Date
malle-pietje
9726378e3c bumped version to 1.1.101 2024-11-15 10:33:11 +01:00
malle-pietje
494375f8b5 - added a private property $cookies_created_at to store the timestamp when the cookies were created/updated.
- added a getter method get_cookies_created_at() to return the timestamp when the cookies were created/updated.
  This information can be useful to determine how old the cookies are.
- minor comments clean up
2024-11-15 10:31:10 +01:00
malle-pietje
3dbc24daca further tweaks 2024-11-04 13:43:57 +01:00
malle-pietje
93d1d8ec3f tweaked hyperlink 2024-11-04 13:38:18 +01:00
malle-pietje
b8620f7672 changed link to hyperlink 2024-11-04 13:37:01 +01:00
malle-pietje
1e2e709d4a inserted link to installation instructions 2024-11-04 13:34:41 +01:00
malle-pietje
472d2eaa68 restructured and updated supported versions info 2024-11-04 13:32:34 +01:00
malle-pietje
1522992e49 bumped version to 1.1.100
fixed incorrect return type for `create_voucher()`, reported by @pa-
2024-10-29 12:14:00 +01:00
malle-pietje
70f6a374e2 - added get_system_log() method to get data from the system logs, returns pages results
- minor formatting changes
2024-10-23 13:30:34 +02:00
malle-pietje
ff9e6f0225 merged #244 for a small change to the start_rolling_upgrade() method, contributed by @Jacobtims
minor additional change to allow changes to the payload of the `start_rolling_upgrade()` method
2024-10-17 16:41:45 +02:00
Jacob Timmerman
00a637dbc4 Add "uxg" to start_rolling_upgrade payload (#244)
* Fix payload start_rolling_upgrade method

* Add "uxg" to start_rolling_upgrade payload
2024-10-17 16:31:25 +02:00
2 changed files with 202 additions and 122 deletions

View File

@@ -2,16 +2,19 @@
A PHP class that provides access to Ubiquiti's [**UniFi Network Application**](https://unifi-network.ui.com/) API.
UniFi Network Application software versions 5.X.X, 6.X.X, 7.X.X, and 8.X.X (version **8.5.2** has been confirmed to
work) are supported as well as Network Applications on **UniFi OS-based consoles** (UniFi OS **4.0.20** 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.
easy inclusion in your projects. See the [installation instructions](#Installation) below for more details.
## Supported Versions
| Software | Versions |
|--------------------------------------|-----------------------------------------------------|
| UniFi Network Application/controller | 5.X.X, 6.X.X, 7.X.X, 8.X.X (**8.5.6 is confirmed**) |
| UniFi OS | 3.X, 4.X (**4.1.15 is confirmed**) |
## Requirements
@@ -29,17 +32,19 @@ easy inclusion in your projects.
## UniFi OS Support
Support for UniFi OS-based controllers has been added as of version 1.1.47. These devices have been verified to work:
Support for UniFi OS-based controllers has been added as of version 1.1.47. These devices/services have been verified
to work:
- UniFi Dream Router (UDR)
- UniFi Dream Machine (UDM)
- UniFi Dream Machine Pro (UDM PRO)
- UniFi Cloud Key Gen2 (UCK G2), firmware version 2.0.24 or higher
- UniFi Cloud Key Gen2 Plus (UCK G2 Plus), firmware version 2.0.24 or higher
- UniFi Cloud Console, details [here](https://help.ui.com/hc/en-us/articles/4415364143511)
- UniFi Express (UX)
- UniFi Dream Wall (UDW)
- UniFi Cloud Gateway Ultra (UCG-Ultra)
- UniFi CloudKey Enterprise (CK-Enterprise)
- UniFi Enterprise Fortress Gateway (EFG)
- Official UniFi Hosting, details [here](https://help.ui.com/hc/en-us/articles/4415364143511)
The class automatically detects UniFi OS consoles and adjusts the URLs and several functions/methods accordingly.

View File

@@ -20,7 +20,7 @@ namespace UniFi_API;
class Client
{
/** Constants. */
const CLASS_VERSION = '1.1.96';
const CLASS_VERSION = '1.1.101';
const CURL_METHODS_ALLOWED = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
const DEFAULT_CURL_METHOD = 'GET';
@@ -40,6 +40,7 @@ class Client
protected bool $is_unifi_os = false;
protected int $exec_retries = 0;
protected string $cookies = '';
protected int $cookies_created_at = 0;
protected $last_results_raw = null;
protected string $last_error_message = '';
protected bool $curl_ssl_verify_peer = false;
@@ -140,7 +141,7 @@ class Client
*/
public function login()
{
/** skip the login process if already logged in */
/** Skip the login process if already logged in. */
if ($this->update_unificookie()) {
$this->is_logged_in = true;
}
@@ -149,7 +150,7 @@ class Client
return true;
}
/** prepare cURL and options to check whether this is a "regular" controller or one based on UniFi OS */
/** Prepare cURL and options to check whether this is a "regular" controller or one based on UniFi OS. */
$ch = $this->get_curl_handle();
$curl_options = [
@@ -158,7 +159,7 @@ class Client
curl_setopt_array($ch, $curl_options);
/** execute the cURL request and get the HTTP response code */
/** Execute the cURL request and get the HTTP response code. */
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
@@ -167,7 +168,7 @@ class Client
trigger_error('cURL error: ' . curl_error($ch));
}
/** prepare the actual login */
/** Prepare the actual login. */
$curl_options = [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['username' => $this->user, 'password' => $this->password]),
@@ -176,7 +177,7 @@ class Client
CURLOPT_URL => $this->baseurl . '/api/login',
];
/** specific to UniFi OS-based controllers */
/** Specific to UniFi OS-based controllers. */
if ($http_code === 200) {
$this->is_unifi_os = true;
$curl_options[CURLOPT_URL] = $this->baseurl . '/api/auth/login';
@@ -184,7 +185,7 @@ class Client
curl_setopt_array($ch, $curl_options);
/** execute the cURL request and get the HTTP response code */
/** Execute the cURL request and get the HTTP response code. */
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
@@ -202,7 +203,7 @@ class Client
print '</pre>' . PHP_EOL;
}
/** based on the HTTP response code trigger an error */
/** Based on the HTTP response code trigger an error. */
if ($http_code >= 400) {
trigger_error("HTTP response status received: $http_code. Probably a controller login failure");
@@ -211,7 +212,7 @@ class Client
curl_close($ch);
/** check the HTTP response code */
/** Check the HTTP response code. */
if ($http_code >= 200) {
$this->is_logged_in = true;
@@ -228,7 +229,7 @@ class Client
*/
public function logout(): bool
{
/** prepare cURL and options */
/** Prepare cURL and options. */
$ch = $this->get_curl_handle();
$curl_options = [
@@ -250,7 +251,7 @@ class Client
curl_setopt_array($ch, $curl_options);
/** execute the cURL request to logout */
/** Execute the cURL request to logout. */
curl_exec($ch);
if (curl_errno($ch)) {
@@ -260,8 +261,9 @@ class Client
curl_close($ch);
$this->is_logged_in = false;
$this->cookies = '';
$this->is_logged_in = false;
$this->cookies = '';
$this->cookies_created_at = 0;
return true;
}
@@ -677,7 +679,7 @@ class Client
}
/**
* Fetch 5-minutes stats for a single user/client device.
* Fetch 5-minutes stats for a single user/client device or all user/client devices.
*
* @note - defaults to the past 12 hours
* - only supported with UniFi controller versions 5.8.X and higher
@@ -685,16 +687,16 @@ class Client
* the controller settings
* - make sure that "Clients Historical Data" has been enabled in the UniFi controller settings in the Maintenance
* section
* @param string $mac MAC address of the user/client device to return stats for
* @param string|null $mac optional, MAC address of the user/client device to return stats for
* @param int|null $start optional, Unix timestamp in milliseconds
* @param int|null $end optional, Unix timestamp in milliseconds
* @param array|null $attribs array containing attributes (strings) to be returned, valid values are:
* rx_bytes, tx_bytes, signal, rx_rate, tx_rate, rx_retries, tx_retries, rx_packets,
* tx_packets, satisfaction, wifi_tx_attempts
* default value is ['rx_bytes', 'tx_bytes']
* tx_packets, satisfaction, wifi_tx_attempts, 'duration'
* default value is ['rx_bytes', 'tx_bytes', 'time']
* @return array|bool returns an array of 5-minute stats objects
*/
public function stat_5minutes_user(string $mac, int $start = null, int $end = null, array $attribs = null)
public function stat_5minutes_user(string $mac = null, int $start = null, int $end = null, array $attribs = null)
{
$end = empty($end) ? time() * 1000 : $end;
$start = empty($start) ? $end - (12 * 3600 * 1000) : $start;
@@ -705,7 +707,7 @@ class Client
}
/**
* Fetch hourly stats for a single user/client device.
* Fetch hourly stats for a single user/client device or all user/client devices.
*
* @note - defaults to the past 7*24 hours
* - only supported with UniFi controller versions 5.8.X and higher
@@ -714,24 +716,28 @@ class Client
* - make sure that "Clients Historical Data" has been enabled in the UniFi controller settings in the Maintenance
* section
* @see stat_5minutes_user() for details on attribs
* @param string $mac MAC address of the user/client device to return stats fo
* @param string|null $mac optional, MAC address of the user/client device to return stats for
* @param int|null $start optional, Unix timestamp in milliseconds
* @param int|null $end optional, Unix timestamp in milliseconds
* @param array|null $attribs array containing attributes (strings) to be returned
* @return array|bool returns an array of hourly stats objects
*/
public function stat_hourly_user(string $mac, int $start = null, int $end = null, array $attribs = null)
public function stat_hourly_user(string $mac = null, int $start = null, int $end = null, array $attribs = null)
{
$end = empty($end) ? time() * 1000 : $end;
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : $start;
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
$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.user', $payload);
}
/**
* Fetch daily stats for a single user/client device.
* Fetch daily stats for a single user/client device or all user/client devices.
*
* @note - defaults to the past 7*24 hours
* - only supported with UniFi controller versions 5.8.X and higher
@@ -740,24 +746,28 @@ class Client
* - make sure that "Clients Historical Data" has been enabled in the UniFi controller settings in the Maintenance
* section
* @see stat_5minutes_user() for details on attribs
* @param string $mac MAC address of the user/client device to return stats for
* @param string|null $mac optional, MAC address of the user/client device to return stats for
* @param int|null $start optional, Unix timestamp in milliseconds
* @param int|null $end optional, Unix timestamp in milliseconds
* @param array|null $attribs array containing attributes (strings) to be returned
* @return array|bool returns an array of daily stats objects
*/
public function stat_daily_user(string $mac, int $start = null, int $end = null, array $attribs = null)
public function stat_daily_user(string $mac = null, int $start = null, int $end = null, array $attribs = null)
{
$end = empty($end) ? time() * 1000 : $end;
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : $start;
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
$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.user', $payload);
}
/**
* Fetch monthly stats for a single user/client device.
* Fetch monthly stats for a single user/client device or all user/client devices.
*
* @note - defaults to the past 13 weeks (52*7*24 hours)
* - only supported with UniFi controller versions 5.8.X and higher
@@ -765,19 +775,23 @@ class Client
* the controller settings
* - make sure that "Clients Historical Data" has been enabled in the UniFi controller settings in the Maintenance
* section
* @see stat_5minutes_user() for details on attribs
* @param string $mac MAC address of the user/client device to return stats for
* @param string|null $mac optional, MAC address of the user/client device to return stats for
* @param int|null $start optional, Unix timestamp in milliseconds
* @param int|null $end optional, Unix timestamp in milliseconds
* @param array|null $attribs array containing attributes (strings) to be returned
* @return array|bool returns an array of monthly stats objects
* @see stat_5minutes_user() for details on attribs
*/
public function stat_monthly_user(string $mac, int $start = null, int $end = null, array $attribs = null)
public function stat_monthly_user(string $mac = null, int $start = null, int $end = null, array $attribs = null)
{
$end = empty($end) ? time() * 1000 : $end;
$start = empty($start) ? $end - (13 * 7 * 24 * 3600 * 1000) : $start;
$attribs = empty($attribs) ? ['time', 'rx_bytes', 'tx_bytes'] : array_merge(['time'], $attribs);
$payload = ['attrs' => $attribs, 'start' => $start, 'end' => $end, 'mac' => strtolower($mac)];
$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.user', $payload);
}
@@ -2086,7 +2100,8 @@ class Client
* @param int|null $up upload speed limit in kbps
* @param int|null $down download speed limit in kbps
* @param int|null $megabytes data transfer limit in MB
* @return array containing a single object which contains the create_time(stamp) of the voucher(s) created
* @return array|bool containing a single object/array which contains the create_time(stamp) of the voucher(s)
* created, false upon failure
*/
public function create_voucher(
int $minutes,
@@ -2096,7 +2111,7 @@ class Client
int $up = null,
int $down = null,
int $megabytes = null
): array
)
{
$payload = [
'cmd' => 'create-voucher',
@@ -3107,13 +3122,14 @@ class Client
/**
* Start rolling upgrade.
*
* @note updates all UniFi devices to the latest firmware known to the controller in a
* @note upgrades all UniFi devices to the latest firmware known to the controller in a
* staggered/rolling fashion
* @param array $payload optional, array of device types to upgrade, default is all device types
* @return bool true upon success
*/
public function start_rolling_upgrade(): bool
public function start_rolling_upgrade(array $payload = ['uap', 'usw', 'ugw', 'uxg']): bool
{
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr/set-rollupgrade', ['uap', 'usw', 'ugw']);
return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr/set-rollupgrade', $payload);
}
/**
@@ -3364,6 +3380,63 @@ class Client
return $this->fetch_results_boolean('/api/s/' . $this->site . '/set/setting/element_adopt', $payload);
}
/**
* Fetch system log entries.
*
* @note - defaults to the past 7*24 hours
* - results are paged; use $page_number to iterate over pages and $page_size to set page size
* @param string $class optional, class of the system log entries to fetch, known valid values:
* 'device-alert', 'next-ai-alert', 'vpn-alert', 'admin-activity', 'update-alert',
* 'client-alert', 'threat-alert', 'triggers', default value is 'device-alert'
* @param ?int $start optional, start time in milliseconds since the Unix epoch
* @param ?int $end optional, end time in milliseconds since the Unix epoch
* @param int $page_number optional, page number to fetch, default value is 0 (first page)
* @param int $page_size optional, number of entries to fetch per page, default value is 100
* @param array $custom_payload optional, an array of additional parameters to pass with the request. Is merged
* with the default payload array constructed by this method using array_merge().
* @return array|bool array containing results from the selected system log section/class, false on error.
* The 'data' key in the returned array contains the actual system log entries.
* The returned array also contains the page number and size, and the total number of entries
* available.
*/
public function get_system_log(string $class = 'device-alert', int $start = null, int $end = null, int $page_number = 0, int $page_size = 100, array $custom_payload = [])
{
$end = empty($end) ? time() * 1000 : $end;
$start = empty($start) ? $end - (7 * 24 * 3600 * 1000) : $start;
$payload = [
'pageNumber' => $page_number,
'pageSize' => $page_size,
'timestampFrom' => $start,
'timestampTo' => $end,
];
switch ($class) {
case 'next-ai-alert':
$payload['nextAiCategory'] = ['CLIENT', 'DEVICE', 'INTERNET', 'VPN'];
break;
case 'admin-activity':
$payload['activity_keys'] = ['ACCESSED_NETWORK_WEB', 'ACCESSED_NETWORK_IOS', 'ACCESSED_NETWORK_ANDROID'];
$payload['change_keys'] = ['CLIENT', 'DEVICE', 'HOTSPOT', 'INTERNET', 'NETWORK', 'PROFILE', 'ROUTING', 'SECURITY', 'SYSTEM', 'VPN', 'WIFI'];
break;
case 'update-alert':
$payload['systemLogDeviceTypes'] = ['GATEWAYS', 'SWITCHES', 'ACCESS_POINT', 'SMART_POWER', 'BUILDING_TO_BUILDING_BRIDGES', 'UNIFI_LTE'];
break;
case 'client-alert':
$payload['clientType'] = ['GUEST', 'TELEPORT', 'VPN', 'WIRELESS', 'RADIUS', 'WIRED'];
$payload['guestAuthorizationMethod'] = ['FACEBOOK_SOCIAL_GATEWAY', 'FREE_TRIAL', 'GOOGLE_SOCIAL_GATEWAY', 'NONE', 'PASSWORD', 'PAYMENT', 'RADIUS', 'VOUCHER'];
break;
case 'threat-alert':
$payload['threatTypes'] = ['HONEYPOT', 'THREAT'];
break;
case 'triggers':
$payload['triggerTypes'] = ['TRAFFIC_RULE', 'TRAFFIC_ROUTE', 'FIREWALL_RULE'];
break;
}
return $this->fetch_results('/v2/api/site/' . $this->site . '/system-log/' . $class, array_merge($payload, $custom_payload));
}
/**
* List device states
*
@@ -3528,7 +3601,18 @@ class Client
****************************************************************/
/**
* Modify the private property $site
* Get the version of the Class.
*
* @return string semver compatible version of this class
* https://semver.org/
*/
public function get_class_version(): string
{
return self::CLASS_VERSION;
}
/**
* Modify the private property $site.
*
* @note this method is useful to switch between sites
* @param string $site must be the short site name of a site to which the
@@ -3544,7 +3628,7 @@ class Client
}
/**
* Get the private property $site
* Get the private property $site.
*
* @return string the current (short) site name
*/
@@ -3554,7 +3638,7 @@ class Client
}
/**
* Set debug mode
* Set debug mode.
*
* @param bool $enable true enables debug mode, false disables debug mode
* @return bool false when a non-boolean parameter was passed
@@ -3567,7 +3651,7 @@ class Client
}
/**
* Get the private property $debug
* Get the private property $debug.
*
* @return bool the current boolean value for $debug
*/
@@ -3577,7 +3661,7 @@ class Client
}
/**
* Get last raw results
* Get last raw results.
*
* @param boolean $return_json true returns the results in "pretty printed" JSON format,
* false returns PHP stdClass Object format (default)
@@ -3597,7 +3681,7 @@ class Client
}
/**
* Get the last error message
* Get the last error message.
*
* @return string the error message of the last method called in PHP stdClass Object format, an empty string when
* none available
@@ -3608,7 +3692,7 @@ class Client
}
/**
* Get Cookie from UniFi controller (singular and plural)
* Get Cookie from UniFi controller (singular and plural for backward compatibility).
*
* @note When the results from this method are stored in $_SESSION[$this->unificookie_name], the Class initially
* does not log in to the controller when a subsequent request is made using a new instance.
@@ -3630,28 +3714,28 @@ class Client
}
/**
* Get the version of the Class
* Get the Unix timestamp of the latest cookie creation.
*
* @return string semver compatible version of this class
* https://semver.org/
* @return int
*/
public function get_class_version(): string
public function get_cookies_created_at(): int
{
return self::CLASS_VERSION;
return $this->cookies_created_at;
}
/**
* Set value for the private property $cookies
* Set the value for the private property $cookies and update $cookies_created_at timestamp.
*
* @param string $cookies_value new value for $cookies
*/
public function set_cookies(string $cookies_value)
{
$this->cookies = $cookies_value;
$this->cookies = $cookies_value;
$this->cookies_created_at = time();
}
/**
* Get the current value of the private property $unificookie_name
* Get the current value of the private property $unificookie_name.
*
* @return string current value of $unificookie_name
*/
@@ -3661,7 +3745,7 @@ class Client
}
/**
* Get current request method
* Get current request method.
*
* @return string request type
*/
@@ -3671,7 +3755,7 @@ class Client
}
/**
* Set request method
* Set request method.
*
* @param string $curl_method a valid HTTP request method
* @return bool whether the request was successful or not
@@ -3688,7 +3772,7 @@ class Client
}
/**
* Get value for cURL option CURLOPT_SSL_VERIFYPEER
* Get value for cURL option CURLOPT_SSL_VERIFYPEER.
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
*
@@ -3700,7 +3784,7 @@ class Client
}
/**
* Set value for cURL option CURLOPT_SSL_VERIFYPEER
* Set value for cURL option CURLOPT_SSL_VERIFYPEER.
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
*
@@ -3715,7 +3799,7 @@ class Client
}
/**
* Get value for cURL option CURLOPT_SSL_VERIFYHOST
* Get value for cURL option CURLOPT_SSL_VERIFYHOST.
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
*
@@ -3727,7 +3811,7 @@ class Client
}
/**
* Set value for cURL option CURLOPT_SSL_VERIFYHOST
* Set value for cURL option CURLOPT_SSL_VERIFYHOST.
*
* https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
*
@@ -3746,7 +3830,7 @@ class Client
}
/**
* Is current controller UniFi OS-based
* Is the current controller UniFi OS-based?
*
* @return bool whether the current controller is UniFi OS-based or not
*/
@@ -3756,7 +3840,7 @@ class Client
}
/**
* Set value for private property $is_unifi_os
* Set value for private property $is_unifi_os.
*
* @param bool $is_unifi_os the new value
* @return bool whether the request was successful or not
@@ -3769,7 +3853,7 @@ class Client
}
/**
* Set value for the private property $connect_timeout
* Set value for the private property $connect_timeout.
*
* @param int $timeout new value for $connect_timeout in seconds
* @return bool whether the request was successful or not
@@ -3782,7 +3866,7 @@ class Client
}
/**
* Get the current value of the private property $connect_timeout
* Get the current value of the private property $connect_timeout.
*
* @return int current value of $connect_timeout
*/
@@ -3792,7 +3876,7 @@ class Client
}
/**
* Set value for the private property $request_timeout
* Set value for the private property $request_timeout.
*
* @param int $timeout new value for $request_timeout in seconds
* @return bool whether the request was successful or not
@@ -3805,7 +3889,7 @@ class Client
}
/**
* Get the current value of the private property $request_timeout
* Get the current value of the private property $request_timeout.
*
* @return int current value of $request_timeout
*/
@@ -3815,7 +3899,7 @@ class Client
}
/**
* Set value for the private property $curl_http_version
* Set value for the private property $curl_http_version.
*
* @note As of cURL version 7.62.0 the default value is CURL_HTTP_VERSION_2TLS which may cause issues,
* this method allows you to set the value to CURL_HTTP_VERSION_1_1 when needed.
@@ -3832,7 +3916,7 @@ class Client
}
/**
* Get current value of the private property $curl_http_version
* Get current value of the private property $curl_http_version.
*
* @return int the current value of $request_timeout, can be CURL_HTTP_VERSION_1_1 int(2) or
* CURL_HTTP_VERSION_2TLS int(4)
@@ -3848,9 +3932,7 @@ class Client
****************************************************************/
/**
* Fetch results
*
* Execute the cURL request and return results
* Fetch results; execute the cURL request and return results.
*
* @param string $path request path
* @param object|array|null $payload optional, PHP associative array or stdClass Object, payload to pass with the
@@ -3867,7 +3949,7 @@ class Client
bool $login_required = true
)
{
/** guard clause to check if logged in when needed */
/** Guard clause to check if logged in when needed. */
if ($login_required && !$this->is_logged_in) {
return false;
}
@@ -3890,7 +3972,7 @@ class Client
if ($response->meta->rc === 'error') {
/**
* an error occurred:
* An error occurred:
* set $this->set last_error_message if the returned error message is available
*/
if (isset($response->meta->msg)) {
@@ -3902,7 +3984,7 @@ class Client
}
}
/** to deal with a response coming from the new v2 API */
/** Deal with a response coming from the new v2 API. */
if (strpos($path, '/v2/api/') === 0) {
if (isset($response->errorCode)) {
if (isset($response->message)) {
@@ -3923,9 +4005,7 @@ class Client
}
/**
* Fetch results where output should be boolean (true/false)
*
* execute the cURL request and return a boolean value
* Fetch results where output should be boolean (true/false); execute the cURL request and return a boolean value.
*
* @param string $path request path
* @param object|array|null $payload optional, PHP associative array or stdClass Object, payload to pass with the
@@ -3939,7 +4019,7 @@ class Client
}
/**
* Capture the latest JSON error when $this->debug is true
* Capture the latest JSON error when $this->debug is true.
*
* @return bool true upon success, false upon failure
*/
@@ -3953,51 +4033,41 @@ class Client
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;
}
/** check whether we have PHP >= 7.0.0 */
/** Check whether we have PHP >= 7.0.0. */
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;
}
}
@@ -4011,7 +4081,7 @@ class Client
}
/**
* Validate the submitted base URL
* Validate the submitted base URL.
*
* @param string $baseurl the base URL to validate
* @return bool true if base URL is a valid URL, else returns false
@@ -4028,7 +4098,7 @@ class Client
}
/**
* Check the (short) site name
* Check the (short) site name.
*
* @param string $site the (short) site name to check
* @return bool true if (short) site name is valid, else returns false
@@ -4045,14 +4115,15 @@ class Client
}
/**
* Update the unificookie if sessions are enabled
* Update the unificookie if sessions are enabled.
*
* @return bool returns true when unificookie was updated, else returns false
*/
protected function update_unificookie(): bool
{
if (session_status() === PHP_SESSION_ACTIVE && isset($_SESSION[$this->unificookie_name]) && !empty($_SESSION[$this->unificookie_name])) {
$this->cookies = $_SESSION[$this->unificookie_name];
$this->cookies = $_SESSION[$this->unificookie_name];
$this->cookies_created_at = time();
/** if the cookie contains a JWT, this is a UniFi OS controller */
if (strpos($this->cookies, 'TOKEN') !== false) {
@@ -4066,7 +4137,7 @@ class Client
}
/**
* Add a cURL header containing the CSRF token from the TOKEN in our Cookie string
* Add a cURL header containing the CSRF token from the TOKEN in our Cookie string.
*
* @return void
*/
@@ -4097,7 +4168,7 @@ class Client
}
/**
* Callback function for cURL to extract and store cookies as needed
* Callback function for cURL to extract and store cookies as needed.
*
* @param object|resource $ch the cURL instance (type hinting is unavailable for cURL resources)
* @param string $header_line the response header line number
@@ -4112,18 +4183,18 @@ class Client
$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;
$this->cookies = $cookie_crumb;
$this->cookies_created_at = time();
$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;
$this->cookies = $cookie_crumb;
$this->cookies_created_at = time();
$this->is_logged_in = true;
$this->is_unifi_os = true;
break;
}
}
@@ -4134,7 +4205,7 @@ class Client
}
/**
* Execute the cURL request
* Execute the cURL request.
*
* @param string $path path for the request
* @param object|array|null $payload optional, payload to pass with the request
@@ -4159,7 +4230,7 @@ class Client
CURLOPT_URL => $url,
];
/** when a payload is passed */
/** When a payload is passed. */
$json_payload = '';
if (!empty($payload)) {
$json_payload = json_encode($payload, JSON_UNESCAPED_SLASHES);
@@ -4167,8 +4238,8 @@ class Client
/**
* should not use GET (the default request type) or DELETE when passing a payload,
* switch to POST instead
* Should not use GET (the default request type) or DELETE when passing a payload,
* switch to POST instead.
*/
if ($this->curl_method === 'GET' || $this->curl_method === 'DELETE') {
$this->curl_method = 'POST';
@@ -4198,19 +4269,19 @@ class Client
curl_setopt_array($ch, $curl_options);
/** execute the cURL request */
/** Execute the cURL request. */
$response = curl_exec($ch);
if (curl_errno($ch)) {
trigger_error('cURL error: ' . curl_error($ch));
}
/** get the HTTP response code */
/** Get the HTTP response code. */
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
/**
* an HTTP response code 401 (Unauthorized) indicates the Cookie/Token has expired in which case
* re-login is required
* An HTTP response code 401 (Unauthorized) indicates the Cookie/Token has expired, in which case
* re-login is required.
*/
if ($http_code === 401) {
if ($this->debug) {
@@ -4218,21 +4289,25 @@ class Client
}
if ($this->exec_retries === 0) {
/** explicitly clear the expired Cookie/Token, update other properties and log out before logging in again */
/**
* Explicitly clear the expired Cookie/Token, update other properties and log out before logging in
* again.
*/
if (isset($_SESSION[$this->unificookie_name])) {
$_SESSION[$this->unificookie_name] = '';
}
$this->is_logged_in = false;
$this->cookies = '';
$this->is_logged_in = false;
$this->cookies = '';
$this->cookies_created_at = 0;
$this->exec_retries++;
curl_close($ch);
/** then login again */
/** Login again. */
$this->login();
/** when re-login was successful, execute the same cURL request again */
/** When the re-login was successful, execute the same cURL request again. */
if ($this->is_logged_in) {
if ($this->debug) {
error_log(__FUNCTION__ . ': re-logged in, calling exec_curl again');
@@ -4269,14 +4344,14 @@ class Client
curl_close($ch);
/** set the method back to the default value, just in case */
/** Set the method back to the default value, just in case. */
$this->curl_method = self::DEFAULT_CURL_METHOD;
return $response;
}
/**
* Create and return a new cURL handle
* Create and return a new cURL handle.
*
* @return object|resource CurlHandle object with PHP 8.* and higher, or a resource for lower PHP versions
*/