diff --git a/resources/functions.php b/resources/functions.php
index b65a8ffe28..1cd1270b65 100644
--- a/resources/functions.php
+++ b/resources/functions.php
@@ -69,26 +69,31 @@ if (!function_exists('str_ends_with')) {
}
}
-if (!function_exists('mb_strtoupper')) {
- function mb_strtoupper($string) {
- return strtoupper($string);
- }
-}
-
if (!function_exists('check_float')) {
- function check_float($string) {
+ /**
+ * Converts a given string to float format and trims whitespace.
+ *
+ * @param string $string The input string to convert. If not provided, an empty string is used.
+ *
+ * @return string The converted float string with whitespace trimmed.
+ */
+ function check_float($string): string {
$string = str_replace(",", ".", $string ?? '');
return trim($string);
}
}
if (!function_exists('check_str')) {
+
/**
- * check_str function
- * @param mixed $string
- * @param boolean $trim
- * @return void
+ * Escapes and trims a given string based on the database type.
+ *
+ * @param string $string The input string to process.
+ * @param bool $trim Whether to trim the string. Defaults to true.
+ *
+ * @return string The processed string.
* @deprecated 5.0
+ * @internal Use parameterized queries
*/
function check_str($string, $trim = true) {
global $db_type, $db;
@@ -123,7 +128,17 @@ if (!function_exists('check_str')) {
}
if (!function_exists('check_sql')) {
+ /**
+ * Alias of trim
+ *
+ * @param string $string
+ *
+ * @return void
+ * @see trim()
+ * @deprecated 5.0
+ */
function check_sql($string) {
+ trigger_error('check_sql should not be used. Use parameterized queries instead.', E_USER_WARNING);
return trim($string); //remove white space
}
}
@@ -133,9 +148,10 @@ if (!function_exists('check_cidr')) {
* Checks if the $ip_address is within the range of the given $cidr
* @param string|array $cidr
* @param string $ip_address
+ *
* @return bool return true if the IP address is in CIDR or if it is empty
*/
- function check_cidr($cidr, $ip_address) {
+ function check_cidr($cidr, string $ip_address): bool {
//no cidr restriction
if (empty($cidr)) {
@@ -152,7 +168,7 @@ if (!function_exists('check_cidr')) {
}
} else {
//cidr is a string
- list ($subnet, $mask) = explode('/', $cidr);
+ [$subnet, $mask] = explode('/', $cidr);
return (ip2long($ip_address) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet);
}
@@ -162,10 +178,17 @@ if (!function_exists('check_cidr')) {
}
if (!function_exists('fix_postback')) {
- function fix_postback($post_array) {
+ /**
+ * Processes an array to replace certain characters in its values to prevent issues during postback.
+ *
+ * @param array $post_array The input array to be processed. It may contain nested arrays or string values.
+ *
+ * @return array The processed array with specific characters replaced in all string values.
+ */
+ function fix_postback(array $post_array): array {
foreach ($post_array as $index => $value) {
if (is_array($value)) {
- fix_postback($value);
+ $post_array[$index] = fix_postback($value);
} else {
$value = str_replace('"', """, $value);
$value = str_replace("'", "'", $value);
@@ -177,7 +200,19 @@ if (!function_exists('fix_postback')) {
}
if (!function_exists('uuid')) {
- function uuid() {
+ /**
+ * Generates a unique identifier (UUID) based on the operating system.
+ *
+ * This function tries to generate a UUID using platform-specific methods:
+ * - On FreeBSD, it uses `uuidgen`.
+ * - On Linux, it first attempts to read from `/proc/sys/kernel/random/uuid`, then falls back to `uuidgen`.
+ * - On Windows, it uses the `com_create_guid()` function.
+ *
+ * If none of these methods succeed, an error message is displayed, and the script exits.
+ *
+ * @return string The generated UUID as a string.
+ */
+ function uuid(): string {
$uuid = null;
if (PHP_OS === 'FreeBSD') {
$uuid = trim(shell_exec("uuidgen"));
@@ -212,10 +247,18 @@ if (!function_exists('uuid')) {
}
}
}
+
}
if (!function_exists('is_uuid')) {
- function is_uuid($str) {
+ /**
+ * Checks if a given string is a valid UUID (Universally Unique Identifier).
+ *
+ * @param mixed $str The input string to be checked.
+ *
+ * @return bool True if the input string is a valid UUID, false otherwise.
+ */
+ function is_uuid($str): bool {
$is_uuid = false;
if (gettype($str) == 'string') {
if (substr_count($str, '-') != 0 && strlen($str) == 36) {
@@ -231,7 +274,14 @@ if (!function_exists('is_uuid')) {
}
if (!function_exists('is_xml')) {
- function is_xml($string) {
+ /**
+ * Checks if the given string is a well-formed XML.
+ *
+ * @param string $string The input string to check.
+ *
+ * @return bool True if the string is a well-formed XML, false otherwise.
+ */
+ function is_xml($string): bool {
$pattern = '/^<\?xml(?:\s+[^>]+\s*)?\?>\s*<(\w+)>.*<\/\1>\s*$/s';
return preg_match($pattern, $string) === 1;
}
@@ -240,6 +290,15 @@ if (!function_exists('is_xml')) {
if (!function_exists('recursive_copy')) {
if (file_exists('/bin/cp')) {
+ /**
+ * Recursively copies the source directory or file to the destination location.
+ *
+ * @param string $source The path of the source directory or file to copy.
+ * @param string $destination The path where the source will be copied.
+ * @param string $options Optional command-line options for the 'cp' command. Defaults to an empty string.
+ *
+ * @return void
+ */
function recursive_copy($source, $destination, $options = '') {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'SUN') {
//copy -R recursive, preserve attributes for SUN
@@ -253,6 +312,17 @@ if (!function_exists('recursive_copy')) {
} elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ /**
+ * Recursively copies a source directory to a destination directory.
+ *
+ * @param string $source The path of the source directory to copy.
+ * @param string $destination The path of the destination directory where the source will be copied.
+ * @param array $options An associative array of options:
+ * - overwrite (bool) Whether to overwrite existing files. Default is false.
+ * - preserve_permissions (bool) Whether to preserve file permissions. Default is true.
+ *
+ * @return bool True if the copy was successful, false otherwise.
+ */
function recursive_copy($source, $destination, $options = '') {
$source = normalize_path_to_os($source);
$destination = normalize_path_to_os($destination);
@@ -261,6 +331,16 @@ if (!function_exists('recursive_copy')) {
} else {
+ /**
+ * Recursively copies a source directory to a destination directory.
+ *
+ * @param string $source The path of the source directory.
+ * @param string $destination The path where the copy will be created.
+ * @param array $options An associative array of options. Currently not used.
+ *
+ * @return void
+ * @throws Exception If the source directory does not exist or if it fails to create the destination directory.
+ */
function recursive_copy($source, $destination, $options = '') {
$dir = opendir($source);
if (!$dir) {
@@ -288,6 +368,13 @@ if (!function_exists('recursive_copy')) {
if (!function_exists('recursive_delete')) {
if (file_exists('/usr/bin/find')) {
+ /**
+ * Recursively deletes all files and directories within the given directory.
+ *
+ * @param string $directory The directory path to delete files from.
+ *
+ * @return void This function does not return a value.
+ */
function recursive_delete($directory) {
if (isset($directory) && strlen($directory) > 8) {
exec('/usr/bin/find ' . $directory . '/* -name "*" -delete');
@@ -296,6 +383,13 @@ if (!function_exists('recursive_delete')) {
}
}
} elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ /**
+ * Recursively deletes the given directory and all its contents.
+ *
+ * @param string $directory The directory to delete. If the path is not normalized, it will be converted using normalize_path_to_os().
+ *
+ * @return bool True if the deletion was successful, false otherwise.
+ */
function recursive_delete($directory) {
$directory = normalize_path_to_os($directory);
//$this->write_debug("del /S /F /Q \"$dir\"");
@@ -303,6 +397,13 @@ if (!function_exists('recursive_delete')) {
clearstatcache();
}
} else {
+ /**
+ * Recursively deletes files and directories in the given directory.
+ *
+ * @param string $directory The path to the directory containing files/directories to delete.
+ *
+ * @return bool True if all files/directories were successfully deleted, false otherwise.
+ */
function recursive_delete($directory) {
foreach (glob($directory) as $file) {
if (is_dir($file)) {
@@ -320,7 +421,14 @@ if (!function_exists('recursive_delete')) {
}
if (!function_exists('if_group')) {
- function if_group($group) {
+ /**
+ * Checks if the user belongs to the specified group.
+ *
+ * @param string $group The name of the group to check for.
+ *
+ * @return bool True if the user is in the specified group, false otherwise.
+ */
+ function if_group($group): bool {
//set default false
$result = false;
@@ -341,7 +449,14 @@ if (!function_exists('if_group')) {
//check if the permission exists
if (!function_exists('permission_exists')) {
- function permission_exists($permission_name) {
+ /**
+ * Checks if a permission with the given name exists.
+ *
+ * @param string $permission_name The name of the permission to check for existence.
+ *
+ * @return bool True if the permission exists, false otherwise.
+ */
+ function permission_exists($permission_name): bool {
//define the global variables
global $database, $domain_uuid, $user_uuid;
@@ -351,6 +466,14 @@ if (!function_exists('permission_exists')) {
}
if (!function_exists('if_group_member')) {
+ /**
+ * Checks if a given group exists in the list of group members.
+ *
+ * @param string $group_members A double pipe-separated string of group members, formatted as "||group1||group2||group3||".
+ * @param string $group The name of the group to search for.
+ *
+ * @return bool True if the group is found in the group members list, false otherwise.
+ */
function if_group_member($group_members, $group) {
if (stripos($group_members, "||" . $group . "||") === false) {
return false; //group does not exist
@@ -361,28 +484,40 @@ if (!function_exists('if_group_member')) {
}
if (!function_exists('superadmin_list')) {
- function superadmin_list() {
+ /**
+ * Retrieves a double pipe-separated list of UUIDs for users in the 'superadmin' group.
+ *
+ * @return string The list of superadmins as a double pipe-separated string of UUIDs, prefixed and suffixed with "||".
+ */
+ function superadmin_list(): string {
//define the global variables
global $database, $domain_uuid;
-
- //get the liset of users in the superadmin group
+ $superadmin_list = '';
+ //get the list of users in the superadmin group
$sql = "select * from v_user_groups ";
$sql .= "where group_name = 'superadmin' ";
$result = $database->select($sql, null, 'all');
- $superadmin_list = "||";
if (is_array($result) && @sizeof($result) != 0) {
+ $superadmin_list .= "||";
foreach ($result as $field) {
//get the list of superadmins
$superadmin_list .= $field['user_uuid'] . "||";
}
}
- unset($sql, $result, $field);
return $superadmin_list;
}
}
if (!function_exists('if_superadmin')) {
- function if_superadmin($superadmin_list, $user_uuid) {
+ /**
+ * Checks if the given user UUID exists in the superadmin list.
+ *
+ * @param string $superadmin_list The comma-separated list of superadmin UUIDs.
+ * @param string $user_uuid The user UUID to search for in the list.
+ *
+ * @return bool True if the user UUID is found in the superadmin list, false otherwise.
+ */
+ function if_superadmin($superadmin_list, $user_uuid): bool {
if (stripos($superadmin_list, "||" . $user_uuid . "||") === false) {
return false;
} else {
@@ -392,7 +527,19 @@ if (!function_exists('if_superadmin')) {
}
if (!function_exists('html_select_other')) {
- function html_select_other($table_name, $field_name, $sql_where_optional, $field_current_value, $sql_order_by = null, $label_other = 'Other...') {
+ /**
+ * Generates an HTML select box with distinct items from a database table and an 'Other' option.
+ *
+ * @param string $table_name The name of the database table to retrieve distinct values from.
+ * @param string $field_name The name of the field in the table to retrieve distinct values from.
+ * @param string|null $sql_where_optional An optional SQL WHERE clause to filter records.
+ * @param string $field_current_value The current value of the select box.
+ * @param string|null $sql_order_by An optional SQL ORDER BY clause to sort retrieved values. Defaults to ordering by the field name in ascending order if not provided.
+ * @param string $label_other The label for the 'Other' option. Defaults to 'Other...'.
+ *
+ * @return string The generated HTML select box as a string.
+ */
+ function html_select_other($table_name, $field_name, $sql_where_optional, $field_current_value, $sql_order_by = null, $label_other = 'Other...'): string {
//define the global variables
global $database, $domain_uuid;
@@ -435,7 +582,20 @@ if (!function_exists('html_select_other')) {
}
if (!function_exists('html_select')) {
- function html_select($table_name, $field_name, $sql_where_optional, $field_current_value, $field_value = '', $style = '', $on_change = '') {
+ /**
+ * Generates an HTML select element based on distinct values from a database field.
+ *
+ * @param string $table_name The name of the table in the database.
+ * @param string $field_name The name of the field to retrieve distinct values from.
+ * @param string $sql_where_optional An optional SQL WHERE clause to filter results.
+ * @param mixed $field_current_value The current value to be selected by default. If not provided, no 'selected' attribute will be added.
+ * @param string $field_value Optional. The name of the field whose values should be used as the option's value. Defaults to $field_name.
+ * @param string $style Optional. The inline style for the select element.
+ * @param string $on_change Optional. JavaScript code to execute when the selected option changes.
+ *
+ * @return string The generated HTML select element as a string.
+ */
+ function html_select($table_name, $field_name, $sql_where_optional, $field_current_value, $field_value = '', $style = '', $on_change = ''): string {
//define the global variables
global $database, $domain_uuid;
@@ -478,18 +638,32 @@ if (!function_exists('html_select')) {
}
if (!function_exists('th_order_by')) {
- //html table header order by
- function th_order_by($field_name, $column_title, $order_by, $order, $app_uuid = '', $css = '', $http_get_params = '', $description = '') {
+ //HTML table header order by
+ /**
+ * Generates the HTML for a table header cell with ordering functionality.
+ *
+ * @param string $field_name The name of the field used for ordering.
+ * @param string $column_title The title to display in the column header.
+ * @param string $order_by The current order by field.
+ * @param string $order The current sorting direction ('asc' or 'desc'). Default is 'asc'.
+ * @param string $app_uuid Optional application UUID parameter. Default is an empty string.
+ * @param string $css Optional CSS classes for the table header cell. Default is an empty string.
+ * @param string $http_get_params Optional additional HTTP GET parameters to include in the ordering URL. Default is an empty string.
+ * @param string $description Optional description text to be included in the title attribute of the column header link. Default is an empty string.
+ *
+ * @return string The generated HTML for the table header cell with ordering functionality.
+ */
+ function th_order_by(string $field_name, string $column_title, string $order_by, string $order, string $app_uuid = '', string $css = '', string $http_get_params = '', string $description = ''): string {
global $text;
if (is_uuid($app_uuid) > 0) {
$app_uuid = "&app_uuid=" . urlencode($app_uuid);
- } // accomodate need to pass app_uuid where necessary (inbound/outbound routes lists)
+ } // accommodate the need to pass app_uuid where necessary (inbound/outbound routes lists)
$field_name = preg_replace("#[^a-zA-Z0-9_]#", "", $field_name);
$field_value = preg_replace("#[^a-zA-Z0-9_]#", "", $field_value ?? '');
$sanitized_parameters = '';
- if (isset($http_get_params) && !empty($http_get_params)) {
+ if (!empty($http_get_params)) {
$parameters = explode('&', $http_get_params);
if (is_array($parameters)) {
foreach ($parameters as $parameter) {
@@ -543,29 +717,42 @@ if (!function_exists('th_order_by')) {
}
if (!function_exists('get_ext')) {
- function get_ext($filename) {
+
+ /**
+ * Retrieves the file extension from the given filename.
+ *
+ * @param string $filename The input filename to extract the extension from.
+ *
+ * @return string The extracted file extension or an empty string if no extension is found.
+ */
+ function get_ext(string $filename): string {
preg_match('/[^?]*/', $filename, $matches);
$string = $matches[0];
$pattern = preg_split('/\./', $string, -1, PREG_SPLIT_OFFSET_CAPTURE);
- // check if there is any extension
- if (count($pattern) == 1) {
- //echo 'No File Extension Present';
- return '';
- }
-
if (count($pattern) > 1) {
$filenamepart = $pattern[count($pattern) - 1][0];
preg_match('/[^?]*/', $filenamepart, $matches);
return $matches[0];
}
+ return '';
}
//echo "ext: ".get_ext('test.txt');
}
if (!function_exists('file_upload')) {
- function file_upload($field = '', $file_type = '', $dest_dir = '') {
+ /**
+ * Uploads a file to the specified destination directory.
+ *
+ * @param string $field The name of the input field where the file was uploaded. Default is an empty string.
+ * @param string $file_type The type of files allowed for upload ('img' or 'file'). Default is an empty string.
+ * @param string $dest_dir The destination directory to save the uploaded file. Default is an empty string.
+ *
+ * @return string|bool The original name of the uploaded file if successful, false otherwise. If the file already exists in
+ * the destination directory, it will be renamed with an incremented number until a unique filename is found.
+ */
+ function file_upload(string $field = '', string $file_type = '', string $dest_dir = '') {
$uploadtempdir = $_ENV["TEMP"] . "\\";
ini_set('upload_tmp_dir', $uploadtempdir);
@@ -644,7 +831,15 @@ if (!function_exists('file_upload')) {
}
if (!function_exists('sys_get_temp_dir')) {
- function sys_get_temp_dir() {
+ /**
+ * Retrieves the system's temporary directory.
+ *
+ * Attempts to retrieve the temporary directory from environment variables ('TMP', 'TEMP', or 'TMPDIR').
+ * If not found in environment variables, creates a temporary file and uses its directory as fallback.
+ *
+ * @return string|null The temporary directory path on success, null if unable to determine the temp dir.
+ */
+ function sys_get_temp_dir(): ?string {
if ($temp = getenv('TMP')) {
return $temp;
}
@@ -666,24 +861,45 @@ if (!function_exists('sys_get_temp_dir')) {
if (!function_exists('normalize_path')) {
//don't use DIRECTORY_SEPARATOR as it will change on a per platform basis and we need consistency
- function normalize_path($path) {
+ /**
+ * Normalizes the given file path by replacing all occurrences of backslashes with forward slashes.
+ *
+ * @param string $path The input file path to normalize.
+ *
+ * @return string The normalized file path with uniform directory separators ('/').
+ */
+ function normalize_path(string $path): string {
return str_replace(array('/', '\\'), '/', $path);
}
}
if (!function_exists('normalize_path_to_os')) {
- function normalize_path_to_os($path) {
+ /**
+ * Normalizes the given path to the operating system's directory separator.
+ *
+ * @param string $path The input path to normalize.
+ *
+ * @return string The normalized path with appropriate directory separator for the OS.
+ */
+ function normalize_path_to_os(string $path): string {
return str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
}
}
if (!function_exists('username_exists')) {
- function username_exists($username) {
+ /**
+ * Checks if a username already exists in the system.
+ *
+ * @param string $username The username to search for.
+ *
+ * @return bool True if the username exists, false otherwise.
+ */
+ function username_exists(string $username): bool {
//define the global variables
global $database, $domain_uuid;
//get the number of rows for the user exists
- $sql = "select count(*) from v_users ";
+ $sql = "select count(user_uuid) from v_users ";
$sql .= "where domain_uuid = :domain_uuid ";
$sql .= "and username = :username ";
$parameters['domain_uuid'] = $domain_uuid;
@@ -691,12 +907,20 @@ if (!function_exists('username_exists')) {
$num_rows = $database->select($sql, $parameters, 'column');
//return whether the user exists
- return $num_rows > 0 ? true : false;
+ return $num_rows > 0;
}
}
if (!function_exists('add_extension_user')) {
- function add_extension_user($extension_uuid, $username) {
+ /**
+ * Adds an extension user association based on the provided extension UUID and username.
+ *
+ * @param string $extension_uuid The UUID of the extension to be associated with the user.
+ * @param string $username The username of the user to associate with the extension.
+ *
+ * @return void This method does not return a value.
+ */
+ function add_extension_user(string $extension_uuid, string $username) {
//define the global variables
global $database, $domain_uuid;
@@ -711,7 +935,7 @@ if (!function_exists('add_extension_user')) {
if (is_uuid($user_uuid)) {
//check if the user_uuid exists in v_extension_users
- $sql = "select count(*) from v_extension_users ";
+ $sql = "select count(extension_user_uuid) from v_extension_users ";
$sql .= "where domain_uuid = :domain_uuid ";
$sql .= "and user_uuid = :user_uuid ";
$parameters['domain_uuid'] = $domain_uuid;
@@ -741,7 +965,16 @@ if (!function_exists('add_extension_user')) {
}
if (!function_exists('user_add')) {
- function user_add($username, $password, $user_email = '') {
+ /**
+ * Adds a new user with the provided username and password.
+ *
+ * @param string $username The username for the new user.
+ * @param string $password The password for the new user.
+ * @param string $user_email Optional email address for the new user (default is empty).
+ *
+ * @return bool True if the user was added successfully, false otherwise. If the username or password are not provided, false will be returned immediately.
+ */
+ function user_add(string $username, string $password, string $user_email = ''): bool {
//define the global variables
global $database, $domain_uuid;
@@ -788,11 +1021,21 @@ if (!function_exists('user_add')) {
//revoke temporary permissions
$p->delete('user_add', 'temp');
$p->delete('user_group_add', 'temp');
+ return true;
}
+ return false;
}
}
-function switch_module_is_running($mod, event_socket $esl = null) {
+/**
+ * Checks if a given FreeSwitch module is running.
+ *
+ * @param string $mod The name of the module to check.
+ * @param event_socket|null $esl An optional event_socket object. If not provided, a new one will be created.
+ *
+ * @return bool True if the module is running, false otherwise or if not connected to FreeSwitch.
+ */
+function switch_module_is_running($mod, event_socket $esl = null): bool {
//if the object does not exist create it
if ($esl === null) {
$esl = event_socket::create();
@@ -808,7 +1051,20 @@ function switch_module_is_running($mod, event_socket $esl = null) {
//print (switch_module_is_running('mod_spidermonkey') ? "true" : "false");
//format a number (n) replace with a number (r) remove the number
-function format_string($format, $data) {
+/**
+ * Formats a given string based on a provided format string.
+ *
+ * The format string can contain the following characters:
+ * - 'x': includes the next character from the data string.
+ * - 'R' or 'r': skips the next character from the data string.
+ * - Any other character: inserts the character into the formatted string as-is.
+ *
+ * @param string $format The format string to use for formatting. Empty strings will return the input data unchanged.
+ * @param string $data The input string to format.
+ *
+ * @return string The formatted string, or the original input if the format string does not match the input length or is empty.
+ */
+function format_string(string $format, string $data): string {
//nothing to do so return
if (empty($format)) {
return $data;
@@ -845,7 +1101,14 @@ function format_string($format, $data) {
}
//get the format and use it to format the phone number
-function format_phone($phone_number) {
+/**
+ * Formats a given phone number based on user-defined formats stored in session.
+ *
+ * @param string $phone_number The phone number to format.
+ *
+ * @return string The formatted phone number if the input matches any defined format, otherwise the original input.
+ */
+function format_phone(string $phone_number): string {
if (is_numeric(trim($phone_number ?? '', ' +'))) {
if (isset($_SESSION["format"]["phone"])) {
$phone_number = trim($phone_number, ' +');
@@ -864,7 +1127,14 @@ function format_phone($phone_number) {
}
//format seconds into hh:mm:ss
-function format_hours($seconds) {
+/**
+ * Formats the given number of seconds into hours, minutes, and seconds with leading zeros.
+ *
+ * @param int|string $seconds The number of seconds to format.
+ *
+ * @return string The formatted time in HH:MM:SS format.
+ */
+function format_hours($seconds): string {
$seconds = (int) $seconds; //convert seconds to an integer
$hours = floor($seconds / 3600);
$minutes = floor(floor($seconds / 60) % 60);
@@ -873,12 +1143,28 @@ function format_hours($seconds) {
}
//format seconds
-function format_seconds($seconds) {
+/**
+ * Formats given seconds into a GM date string (HH:MM:SS).
+ *
+ * @param int|null $seconds The number of seconds to format.
+ *
+ * @return string The formatted time as HH:MM:SS, or "00:00:00" if $seconds is negative or zero.
+ */
+function format_seconds(?int $seconds): string {
return gmdate("H:i:s", $seconds);
}
-//browser detection without browscap.ini dependency
-function http_user_agent($info = '') {
+/**
+ * Retrieves and analyzes the user agent string from $_SERVER['HTTP_USER_AGENT'] without browscap.ini dependency.
+ *
+ * @param string $info The specific information to retrieve. Can be one of 'agent', 'name', 'name_short',
+ * 'version', 'platform', 'mobile', or 'pattern'. Defaults to returning an associative array
+ * containing all the analyzed data if no parameter is provided.
+ *
+ * @return mixed The requested user agent information based on the $info parameter. If no parameter is provided,
+ * returns an associative array containing all the analyzed data.
+ */
+function http_user_agent(string $info = '') {
//set default values
$user_agent = $_SERVER['HTTP_USER_AGENT'];
@@ -984,8 +1270,15 @@ function http_user_agent($info = '') {
}
}
-//tail php function for non posix systems
-function tail($file, $num_to_get = 10) {
+/**
+ * tail php function for non posix systems
+ *
+ * @param string $file The path to the file.
+ * @param int $num_to_get Number of lines to retrieve (default is 10).
+ *
+ * @return string The retrieved lines concatenated with newline characters.
+ */
+function tail(string $file, int $num_to_get = 10): string {
$esl = fopen($file, 'r');
$position = filesize($file);
$chunklen = 4096;
@@ -1022,7 +1315,21 @@ function tail($file, $num_to_get = 10) {
}
//generate a random password with upper, lowercase and symbols
-function generate_password($length = 0, $strength = 0) {
+/**
+ * Generates a random password of specified length and strength.
+ *
+ * @param int $length The desired length of the password. Defaults to default settings if not provided or zero.
+ * @param int $strength The desired strength level of the password. Defaults to default settings if not provided or
+ * zero.
+ * - Level 1: Numeric
+ * - Level 2: Lowercase letters
+ * - Level 3: Uppercase letters
+ * - Level 4: Special characters (!^$%*?.)
+ *
+ * @return string The generated password.
+ * @throws \Random\RandomException
+ */
+function generate_password(int $length = 0, int $strength = 0): string {
//define the global variables
global $settings;
@@ -1051,12 +1358,21 @@ function generate_password($length = 0, $strength = 0) {
}
//check password strength against requirements (if any)
-function check_password_strength($password, $text, $type = 'default') {
+/**
+ * Checks the strength of the given password based on configured requirements.
+ *
+ * @param string $password The input password to check.
+ * @param array $text Language text object containing message labels.
+ * @param string $type The type of password requirements ('default' or 'user'). Default is 'default'.
+ *
+ * @return bool True if the password meets the strength requirements, false otherwise. If the password is empty, it will return true without checking.
+ */
+function check_password_strength(string $password, array $text, string $type = 'default'): bool {
//define the global variables
global $database, $settings;
- //initialize the settigns object
+ //initialize the settings object
$settings = new settings(['database' => $database, 'domain_uuid' => $_SESSION['domain_uuid']]);
if (!empty($password)) {
@@ -1100,7 +1416,18 @@ function check_password_strength($password, $text, $type = 'default') {
//based on Wez Furlong do_post_request
if (!function_exists('send_http_request')) {
- function send_http_request($url, $data, $method = "POST", $optional_headers = null) {
+ /**
+ * Sends an HTTP request to the specified URL with optional data and method.
+ *
+ * @param string $url The URL to send the request to.
+ * @param mixed $data The data to send with the request. This can be a string or an array, depending on the content type.
+ * @param string $method The HTTP method to use for the request. Defaults to "POST".
+ * @param string|array|null $optional_headers Optional headers to include in the request. Defaults to null.
+ *
+ * @return string The response from the server as a string.
+ * @throws Exception If there is a problem with the request or reading the response.
+ */
+ function send_http_request($url, $data, string $method = "POST", $optional_headers = null): string {
$params = array('http' => array(
'method' => $method,
'content' => $data
@@ -1123,7 +1450,15 @@ if (!function_exists('send_http_request')) {
//convert the string to a named array
if (!function_exists('csv_to_named_array')) {
- function csv_to_named_array($tmp_str, $tmp_delimiter) {
+ /**
+ * Converts a CSV string into an associative array with named keys.
+ *
+ * @param string $tmp_str The input CSV string.
+ * @param string $tmp_delimiter The delimiter used in the CSV string. Defaults to ",".
+ *
+ * @return array An associative array where keys are the first row of the CSV as column headers and values are arrays representing each row.
+ */
+ function csv_to_named_array(string $tmp_str, string $tmp_delimiter): array {
$tmp_array = explode("\n", $tmp_str);
$result = array();
if (trim(strtoupper($tmp_array[0])) !== "+OK") {
@@ -1149,7 +1484,16 @@ if (!function_exists('csv_to_named_array')) {
}
}
-function get_time_zone_offset($remote_tz, $origin_tz = 'UTC') {
+/**
+ * Calculates the time zone offset between a remote time zone and an origin time zone.
+ *
+ * @param string $remote_tz The ID of the remote time zone.
+ * @param string $origin_tz The ID of the origin time zone. Defaults to 'UTC'.
+ *
+ * @return int The difference in seconds between the remote time zone and the origin time zone.
+ * @throws \DateInvalidTimeZoneException
+ */
+function get_time_zone_offset(string $remote_tz, string $origin_tz = 'UTC'): int {
$origin_dtz = new DateTimeZone($origin_tz);
$remote_dtz = new DateTimeZone($remote_tz);
$origin_dt = new DateTime("now", $origin_dtz);
@@ -1158,20 +1502,45 @@ function get_time_zone_offset($remote_tz, $origin_tz = 'UTC') {
return $offset;
}
-function number_pad($number, $n) {
+/**
+ * Pads a number with leading zeros to reach a specified length.
+ *
+ * @param int $number The number to pad.
+ * @param int $n The desired total length of the padded number.
+ *
+ * @return string The padded number as a string.
+ */
+function number_pad($number, $n): string {
return str_pad((int) $number, $n, "0", STR_PAD_LEFT);
}
// validate email address syntax
if (!function_exists('valid_email')) {
- function valid_email($email) {
+ /**
+ * Validates an email address using PHP's built-in filter_var function.
+ *
+ * @param string $email The email address to validate.
+ *
+ * @return bool True if the email is valid, false otherwise.
+ */
+ function valid_email(string $email): bool {
return (filter_var($email, FILTER_VALIDATE_EMAIL)) ? true : false;
}
}
//function to convert hexidecimal color value to rgb string/array value
if (!function_exists('hex_to_rgb')) {
- function hex_to_rgb($hex, $delim = null, $include_alpha = false, $alpha = 1) {
+ /**
+ * Converts a hexadecimal color code to an RGB representation.
+ *
+ * @param string $hex The hexadecimal color code. If it's a 3-digit hex, each digit will be doubled.
+ * @param string|null $delim Optional delimiter for the RGB values if returned as a string. Default is null (return array).
+ * @param bool $include_alpha Whether to include an alpha channel in the output. Default is false.
+ * @param float $alpha The value of the alpha channel if included. Default is 1 (opaque).
+ *
+ * @return array|string RGB values as an array or a delimited string depending on $delim parameter.
+ */
+ function hex_to_rgb(string $hex, ?string $delim = null, bool $include_alpha = false, $alpha = 1) {
$hex = str_replace("#", "", $hex);
if (strlen($hex) == 3) {
@@ -1198,7 +1567,16 @@ if (!function_exists('hex_to_rgb')) {
//function to convert a hex or rgb/a color to an rgba array
if (!function_exists('color_to_rgba_array')) {
- function color_to_rgba_array($string, $alpha = null) {
+ /**
+ * Converts a color string to an RGB(A) array.
+ *
+ * @param string $string The input color string (hex or rgb/a).
+ * @param float|null $alpha The desired alpha value. If null, it will be omitted from the output array.
+ *
+ * @return array|bool An associative array containing 'r', 'g', 'b', and optionally 'a' keys with their respective color values,
+ * or false if the input string is invalid.
+ */
+ function color_to_rgba_array(string $string, ?float $alpha = null) {
if (!empty($string)) {
if (strpos($string, '#') === 0) { //is hex
return hex_to_rgb($string, null, true, $alpha);
@@ -1223,6 +1601,13 @@ if (!function_exists('color_to_rgba_array')) {
//function to get a color's luminence level -- dependencies: rgb_to_hsl()
if (!function_exists('get_color_luminence')) {
+ /**
+ * Retrieves the luminosity of a given color.
+ *
+ * @param string|array $color The input color as either a hexadecimal string or RGB array. If an array, it must contain 3 elements: red, green, blue.
+ *
+ * @return float|null The luminosity value if the input is valid, otherwise null.
+ */
function get_color_luminence($color) {
//convert hex to rgb
if (substr_count($color, ',') == 0) {
@@ -1257,6 +1642,22 @@ if (!function_exists('get_color_luminence')) {
//function to lighten or darken a hexidecimal, rgb, or rgba color value by a percentage -- dependencies: rgb_to_hsl(), hsl_to_rgb()
if (!function_exists('color_adjust')) {
+ /**
+ * Adjusts the brightness of a given color by a specified percentage.
+ *
+ * @param string|array $color The input color in hexadecimal (#RRGGBB) or RGB(a)(r, g, b, a)
+ * format. If array is provided, it should contain three elements:
+ * red, green, blue values.
+ * @param float $percent The percentage by which to adjust the brightness of the color. A positive
+ * value lightens the color, while a negative value darkens it.
+ *
+ * @return string|array The adjusted color in the same format as the input color.
+ *
+ * Example usage:
+ * - To lighten a color by 20%: `color_adjust('#3f4265', 0.2)`
+ * - To darken a color by 20%: `color_adjust('#3f4265', -0.2)`
+ * - To adjust RGB(a) colors: `color_adjust('rgb(234,120,6)', 0.2)`, `color_adjust('rgba(234,120,6,0.3)', -0.2)`
+ */
function color_adjust($color, $percent) {
/*
USAGE
@@ -1340,6 +1741,15 @@ if (!function_exists('color_adjust')) {
//function to convert an rgb color array to an hsl color array
if (!function_exists('rgb_to_hsl')) {
+ /**
+ * Converts RGB color to HSL.
+ *
+ * @param int $r The red component (0-255).
+ * @param int $g The green component (0-255).
+ * @param int $b The blue component (0-255).
+ *
+ * @return array An array containing the HSL components: [hue, saturation, lightness].
+ */
function rgb_to_hsl($r, $g, $b) {
$r /= 255;
$g /= 255;
@@ -1379,6 +1789,15 @@ if (!function_exists('rgb_to_hsl')) {
//function to convert an hsl color array to an rgb color array
if (!function_exists('hsl_to_rgb')) {
+ /**
+ * Converts HSL color to RGB.
+ *
+ * @param float $h Hue component in degrees (0-360).
+ * @param float $s Saturation component (0-1).
+ * @param float $l Lightness component (0-1).
+ *
+ * @return array An array representing the RGB color values ([red, green, blue]), each value ranging from 0 to 255.
+ */
function hsl_to_rgb($h, $s, $l) {
$r = 0;
$g = 0;
@@ -1506,7 +1925,23 @@ if (!function_exists('send_email')) {
Error messages are stored in the variable passed into $email_error BY REFERENCE
*/
- function send_email($email_recipients, $email_subject, $email_body, &$email_error = '', $email_from_address = '', $email_from_name = '', $email_priority = 3, $email_debug_level = 0, $email_attachments = '', $email_read_confirmation = false) {
+ /**
+ * Sends an email with the given recipients, subject, body, and optional parameters.
+ *
+ * @param array|string $email_recipients An array of recipient emails or a single/delimited string of email addresses.
+ * @param string $email_subject The subject of the email.
+ * @param string $email_body The body content of the email.
+ * @param string & $email_error (optional) A reference variable to store any error messages that occur during sending. Default is an empty string.
+ * @param string $email_from_address (optional) The email address of the sender. Defaults to the SMTP from address in settings if not provided.
+ * @param string $email_from_name (optional) The name of the sender. Defaults to the SMTP from name in settings if not provided.
+ * @param int $email_priority (optional) The priority of the email (1: Low, 3: Normal, 5: High). Default is 3.
+ * @param int $email_debug_level (optional) The debug level for sending emails. Default is 0.
+ * @param string|array $email_attachments (optional) A string path to an attachment file or an array of attachments. Default is no attachments.
+ * @param bool $email_read_confirmation (optional) Whether to enable read receipts. Default is false.
+ *
+ * @return bool True if the email was sent successfully, false otherwise. If any errors occur, they will be stored in the provided `$email_error` variable.
+ */
+ function send_email($email_recipients, $email_subject, $email_body, &$email_error = '', $email_from_address = '', $email_from_name = '', $email_priority = 3, $email_debug_level = 0, $email_attachments = '', bool $email_read_confirmation = false): bool {
//define the global variables
global $database, $settings;
@@ -1552,14 +1987,23 @@ if (!function_exists('send_email')) {
$email->attachments = $email_attachments;
$email->debug_level = 3;
$sent = $email->send();
- //$email_error = $email->email_error;
-
+ $email_error = $email->email_error;
+ return true;
}
+ return false;
}
//encrypt a string
if (!function_exists('encrypt')) {
- function encrypt($key, $data) {
+ /**
+ * Encrypts the given data using AES-256-CBC with the provided key.
+ *
+ * @param string $key The encryption key. Should be a base64 encoded string.
+ * @param string $data The data to encrypt.
+ *
+ * @return string The encrypted data along with initialization vector (IV). Result is a base64 encoded string formatted as 'encrypted_data::iv'.
+ */
+ function encrypt($key, $data): string {
$encryption_key = base64_decode($key);
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
@@ -1569,23 +2013,46 @@ if (!function_exists('encrypt')) {
//decrypt a string
if (!function_exists('decrypt')) {
+ /**
+ * Decrypts the given encrypted data using the provided encryption key.
+ *
+ * @param string $key The base64 encoded encryption key.
+ * @param string $data The base64 encoded encrypted data with IV (separated by '::').
+ *
+ * @return string The decrypted data.
+ * @throws Exception If openssl_decrypt fails or if $data does not contain both encrypted_data and iv separated by '::'.
+ */
function decrypt($key, $data) {
$encryption_key = base64_decode($key);
- list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
+ [$encrypted_data, $iv] = explode('::', base64_decode($data), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}
}
//json detection
if (!function_exists('is_json')) {
- function is_json($str) {
- return is_string($str) && is_array(json_decode($str, true)) ? true : false;
+ /**
+ * Checks if the given string is a valid JSON.
+ *
+ * @param string $str The input string to check.
+ *
+ * @return bool True if the string is valid JSON, false otherwise.
+ */
+ function is_json($str): bool {
+ return is_string($str) && is_array(json_decode($str, true));
}
}
// PHP versions lower than 8.3 need the json_validate function
if (!function_exists('json_validate')) {
- function json_validate($json) {
+ /**
+ * Validates if the given string is a valid JSON.
+ *
+ * @param string $json The input JSON string to validate.
+ *
+ * @return bool True if the string is a valid JSON, false otherwise.
+ */
+ function json_validate($json): bool {
// decode the JSON data
$data = json_decode($json);
@@ -1600,14 +2067,26 @@ if (!function_exists('json_validate')) {
//mac detection
if (!function_exists('is_mac')) {
- function is_mac($str) {
- return preg_match('/([a-fA-F0-9]{2}[:|\-]?){6}/', $str) == 1 && strlen(preg_replace("#[^a-fA-F0-9]#", '', $str)) == 12 ? true : false;
+ /**
+ * Checks if the given string is a MAC address.
+ *
+ * @param string $str The input string to check.
+ *
+ * @return bool True if the string is a valid MAC address, false otherwise.
+ */
+ function is_mac($str): bool {
+ return preg_match('/([a-fA-F0-9]{2}[:|\-]?){6}/', $str) == 1 && strlen(preg_replace("#[^a-fA-F0-9]#", '', $str)) === 12;
}
}
//detect if php is running as command line interface
if (!function_exists('is_cli')) {
- function is_cli() {
+ /**
+ * Checks if the current script is running from the command line interface.
+ *
+ * @return bool True if running from CLI, false otherwise.
+ */
+ function is_cli(): bool {
if (defined('STDIN')) {
return true;
}
@@ -1620,6 +2099,15 @@ if (!function_exists('is_cli')) {
//format device address
if (!function_exists('format_device_address')) {
+ /**
+ * Formats a device address string.
+ *
+ * @param string $str The input device address string.
+ * @param string $delim The delimiter to use for MAC addresses (default is '-').
+ * @param string $case The case to convert the formatted string to ('lower' or 'upper', default is 'lower').
+ *
+ * @return string|false The formatted device address string, or false if the input string is empty.
+ */
function format_device_address($str, $delim = '-', $case = 'lower') {
if (empty($str)) {
return false;
@@ -1638,6 +2126,15 @@ if (!function_exists('format_device_address')) {
//transparent gif
if (!function_exists('img_spacer')) {
+ /**
+ * Creates an invisible spacer image with specified dimensions.
+ *
+ * @param string $width The desired width of the image. Default is '1px'.
+ * @param string $height The desired height of the image. Default is '1px'.
+ * @param string|null $custom Additional custom styles to apply to the image. Optional.
+ *
+ * @return string The HTML for the spacer image.
+ */
function img_spacer($width = '1px', $height = '1px', $custom = null) {
return "
";
}
@@ -1645,26 +2142,53 @@ if (!function_exists('img_spacer')) {
}
//lower case
-function lower_case($string) {
+/**
+ * Converts a given string to lowercase giving preference to using multibyte UTF-8 encoding.
+ *
+ * @param string $string The input string to convert.
+ *
+ * @return string The converted string in lowercase.
+ */
+function lower_case($string): string {
if (function_exists('mb_strtolower')) {
- return mb_strtolower($string, 'UTF-8');
+ return mb_strtolower($string ?? '', 'UTF-8');
} else {
- return strtolower($string);
+ return strtolower($string ?? '');
}
}
//upper case
-function upper_case($string) {
+/**
+ * Converts a given string to uppercase giving preference to using multibyte UTF-8 encoding.
+ *
+ * @param string $string The input string to convert.
+ *
+ * @return string The converted string in uppercase.
+ */
+function upper_case($string): string {
if (function_exists('mb_strtoupper')) {
- return mb_strtoupper($string, 'UTF-8');
+ return mb_strtoupper($string ?? '', 'UTF-8');
} else {
- return strtoupper($string);
+ return strtoupper($string ?? '');
}
}
//write javascript function that detects select key combinations to perform designated actions
if (!function_exists('key_press')) {
- function key_press($key, $direction = 'up', $subject = 'document', $exceptions = array(), $prompt = null, $action = null, $script_wrapper = true) {
+ /**
+ * Handles key press events based on the given parameters.
+ *
+ * @param string $key The key to listen for. Can be a single character or a special key like 'escape', 'delete', etc.
+ * @param string $direction The direction of the event, either 'up' (keyup), 'down' (keydown), 'press' (keypress). Defaults to 'up'.
+ * @param string $subject The element to attach the event listener to. Can be an ID, class, or one of the special keywords 'window' or 'document'. Defaults to 'document'.
+ * @param array $exceptions An optional array of selectors for elements that should not trigger the event.
+ * @param null|string $prompt An optional prompt message to display before executing the action. If provided, a confirm dialog will be displayed.
+ * @param null|string $action The action to execute when the key is pressed and there are no exceptions. Defaults to displaying an alert with the key name if no other action is specified.
+ * @param bool $script_wrapper Whether to wrap the output script in `