);
if ($type == self::INPUT_REQUEST) {
$result = self::filterInputRequest($var_name, $filter, $options);
} else {
$result = filter_input($type, $var_name, $filter, $options);
}
if (is_null($result)) {
return $default;
}
return self::sanitizeNSCharsNewlineTrim($result);
}
/**
* All characters that are not explicitly accepted are removed.
* By default, only alphanumeric characters are accepted.
*
* @param mixed $input input value
* @param string $extraAcceptChars extra accepted chars
*
* @return string|string[]
*/
public static function sanitizeStrict($input, $extraAcceptChars = '')
{
$regex = '/[^a-zA-Z0-9' . preg_quote($extraAcceptChars, '/') . ' ]/m';
if (is_scalar($input) || is_null($input)) {
$input = (string) $input;
} elseif (is_array($input)) {
} elseif (is_object($input)) {
$input = (array) $input;
} else {
$input = '';
}
if (is_array($input)) {
foreach ($input as $key => $val) {
$input[$key] = self::sanitizeStrict($val, $extraAcceptChars);
}
return $input;
}
$result = preg_replace($regex, '', $input);
return (is_null($result) ? '' : $result);
}
/**
* Sanitize value to int
*
* @param mixed $input Input value
* @param int $default Default value if input isnt valid
*
* @return int
*/
public static function sanitizeInt($input, $default = 0)
{
if (!is_scalar($input)) {
return $default;
} elseif (is_bool($input)) {
return (int) $input;
} else {
return filter_var($input, FILTER_VALIDATE_INT, [ 'options' => [ 'default' => $default]]);
}
}
/**
* Sanitize value to bool
*
* @param mixed $input Input value
*
* @return bool
*/
public static function sanitizeBool($input)
{
if (!is_scalar($input)) {
return false;
} elseif (is_bool($input)) {
return $input;
} else {
return filter_var($input, FILTER_VALIDATE_BOOLEAN);
}
}
/**
* Sanitize value from input $_GET, $_POST, $_REQUEST ...
*
* @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or SnapUtil::INPUT_REQUEST
* @param string $varName Name of a variable to get.
* @param mixed $default default value if var $varName don't exists
* @param string $extraAcceptChars extra accepted chars
*
* @return string|string[]|mixed return default value if varName isn't defined
*/
public static function sanitizeStrictInput($type, $varName, $default = false, $extraAcceptChars = '')
{
if (($value = self::getValueByType($type, $varName)) === null) {
return $default;
}
return self::sanitizeStrict($value, $extraAcceptChars);
}
/**
* Sanitize value from input $_GET, $_POST, $_REQUEST ...
*
* @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or SnapUtil::INPUT_REQUEST
* @param string $varName Name of a variable to get.
* @param int $default default value if var $varName don't exists
*
* @return int return default value if varName isn't defined
*/
public static function sanitizeIntInput($type, $varName, $default = 0)
{
if (($value = self::getValueByType($type, $varName)) === null) {
return $default;
}
return self::sanitizeInt($value);
}
/**
* Sanitize value from input $_GET, $_POST, $_REQUEST ...
*
* @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or SnapUtil::INPUT_REQUEST
* @param string $varName Name of a variable to get.
* @param null|bool $default default value if var $varName don't exists
*
* @return bool return default value if varName isn't defined
*/
public static function sanitizeBoolInput($type, $varName, $default = false)
{
if (($value = self::getValueByType($type, $varName)) === null) {
return $default;
}
return self::sanitizeBool($value);
}
/**
* Sanitize value from input $_GET, $_POST, $_REQUEST ...
*
* @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or SnapUtil::INPUT_REQUEST
* @param string $varName Name of a variable to get.
* @param mixed $default default value if var $varName don't exists
*
* @return string|string[]|mixed return default value if varName isn't defined
*/
public static function sanitizeInput($type, $varName, $default = false)
{
if (($value = self::getValueByType($type, $varName)) === null) {
return $default;
}
return self::sanitize($value);
}
/**
* Return value input by type null if don't exists
*
* @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or SnapUtil::INPUT_REQUEST
* @param string $varName Name of a variable to get.
*
* @return string|string[]|null
*/
protected static function getValueByType($type, $varName)
{
$doNothingCallback = function ($v) {
return $v;
};
if ($type === self::INPUT_REQUEST) {
$type = ((isset($_GET[$varName]) && !isset($_POST[$varName])) ? INPUT_GET : INPUT_POST);
}
$value = filter_input($type, $varName, FILTER_CALLBACK, array('options' => $doNothingCallback));
/** @var string|string[]|null $value */
return $value;
}
/**
* Gets external variables and optionally filters them
* This function is useful for retrieving many values without repetitively calling filter_input()
.
*
* @param mixed[]|int $definition An array defining the arguments.
* A valid key is a string
containing a variable name and a valid value is either a filter type,
* or an array
optionally specifying the filter, flags and options.
* If the value is an array, valid keys are filter which specifies the filter type,
* flags which specifies any flags that apply to the filter, and options
* which specifies any options that apply to the filter. See the example below for a better understanding.
* This parameter can be also an integer holding a filter constant.
* Then all values in the input array are filtered by this filter.
* @param bool $add_empty Add missing keys as NULL
to the return value.
*
* @return mixed An array containing the values of the requested variables on success.
*
* @link http://php.net/manual/en/function.filter-input-array.php
* @see filter_input(), filter_var_array()
*/
public static function filterInputRequestArray($definition = FILTER_DEFAULT, $add_empty = true)
{
if (!is_array($definition) || count($definition) === 0) {
return array();
}
$getKeys = array_keys($_GET);
$postKeys = array_keys($_POST);
$keys = array_keys($definition);
if (count(array_intersect($keys, $getKeys)) && !count(array_intersect($keys, $postKeys))) {
$type = INPUT_GET;
} else {
$type = INPUT_POST;
}
$result = filter_input_array($type, $definition, $add_empty);
if (!is_array($result)) {
$result = array();
foreach ($keys as $key) {
$result[$key] = null;
}
}
return $result;
}
/**
* Close all buffers and return content
*
* @param bool $getContent If true it returns buffer content, otherwise it is discarded
*
* @return string
*/
public static function obCleanAll($getContent = true)
{
$result = '';
for ($i = 0; $i < ob_get_level(); $i++) {
if ($getContent) {
$result .= ob_get_contents();
}
ob_clean();
}
return $result;
}
/**
* Array map recursively
*
* @param callable $callback callback function
* @param mixed[] $array array input
*
* @return mixed[]
*/
public static function arrayMapRecursive($callback, $array)
{
if (!is_array($array)) {
throw new Exception('$array must be an array');
}
if (!is_callable($callback)) {
throw new Exception('$callback must be callable');
}
$func = function ($item) use (&$func, &$callback) {
return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item);
};
return array_map($func, $array);
}
/**
* Implemented array_key_first
*
* @link https://www.php.net/manual/en/function.array-key-first.php
*
* @param mixed[] $arr array input
*
* @return int|string|null
*/
public static function arrayKeyFirst($arr)
{
if (!function_exists('array_key_first')) {
foreach ($arr as $key => $unused) {
return $key;
}
return null;
} else {
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.array_key_firstFound
return array_key_first($arr);
}
}
/**
* Get number of bit supported by PHP
*
* @return string
*/
public static function getArchitectureString()
{
return (PHP_INT_SIZE * 8) . '-bit';
}
/**
* In array check by callback
*
* @param mixed[] $haystack array input
* @param callable $callback callback function
*
* @return null|bool
*/
public static function inArrayExtended($haystack, $callback)
{
if (!is_callable($callback)) {
return null;
}
foreach ($haystack as $value) {
if (call_user_func($callback, $value)) {
return true;
}
}
return false;
}
/**
* This is a binary recursion, so it only works on an ordered array of integers.
* (If it is not ordered, it does not work)
*
* The advantage of using this search instead of normal array search is that the complexity goes from O(n) to O(log n).
*
* @param int[] $array array values
* @param int $x element to search
*
* @return bool
*/
public static function binarySearch($array, $x)
{
if (count($array) === 0) {
return false;
}
$low = 0;
$high = count($array) - 1;
while ($low <= $high) {
$mid = floor(($low + $high) / 2);
if ($array[$mid] == $x) {
return true;
}
if ($x < $array[$mid]) {
$high = $mid - 1;
} else {
$low = $mid + 1;
}
}
return false;
}
/**
* Generates a random password drawn from the defined set of characters.
* Copy of the wp_generate_password() function from wp-includes/pluggable.php with minor tweaks
*
* @param int $length Optional. The length of password to generate. Default 12.
* @param bool $special_chars Optional. Whether to include standard special characters.
* Default true.
* @param bool $extra_special_chars Optional. Whether to include other special characters.
* Used when generating secret keys and salts. Default false.
*
* @return string The random password.
*/
public static function generatePassword($length = 12, $special_chars = true, $extra_special_chars = false)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
if ($special_chars) {
$chars .= '!@#$%^&*()';
}
if ($extra_special_chars) {
$chars .= '-_ []{}<>~`+=,.;:/?|';
}
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= substr($chars, self::rand(0, strlen($chars) - 1), 1);
}
return $password;
}
/**
* Generates a random number
* Copy of the wp_rand() function from wp-includes/pluggable.php with minor tweaks
*
* @param int $min Lower limit for the generated number
* @param int $max Upper limit for the generated number
*
* @return int A random number between min and max
*/
public static function rand($min = 0, $max = 0)
{
global $rnd_value;
// Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers
// larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats.
$max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // @phpstan-ignore-line
// 4294967295 = 0xffffffff
// We only handle Ints, floats are truncated to their integer value.
$min = (int) $min;
$max = (int) $max;
// Use PHP's CSPRNG, or a compatible method
static $use_random_int_functionality = null;
if (is_null($use_random_int_functionality)) {
$use_random_int_functionality = function_exists('random_int');
}
if ($use_random_int_functionality) {
try {
$_max = ( 0 != $max ) ? $max : $max_random_number;
// rand() can accept arguments in either order, PHP cannot.
$_max = max($min, $_max);
$_min = min($min, $_max);
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.random_intFound
$val = random_int($_min, $_max);
if (false !== $val) {
return abs(intval($val));
} else { // @phpstan-ignore-line
$use_random_int_functionality = false;
}
} catch (Error $e) {
$use_random_int_functionality = false;
} catch (Exception $e) {
$use_random_int_functionality = false;
}
}
// Reset $rnd_value after 14 uses
// 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
if (strlen($rnd_value) < 8) {
static $seed = '';
$rnd_value = md5(uniqid(microtime() . mt_rand(), true) . $seed);
$rnd_value .= sha1($rnd_value);
$rnd_value .= sha1($rnd_value . $seed);
$seed = md5($seed . $rnd_value);
}
// Take the first 8 digits for our value
$value = substr($rnd_value, 0, 8);
// Strip the first eight, leaving the remainder for the next call to rand().
$rnd_value = substr($rnd_value, 8);
$value = abs(hexdec($value));
// Reduce the value to be within the min - max range
if ($max != 0) {
$value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
}
return abs(intval($value));
}
/**
* Returns true if the class exists, false otherwise
*
* @param string $className Name of the class to check if it exists
* @param boolean $autoload Parameter that will be passed to class_exists as second
*
* @return boolean
*/
public static function classExists($className, $autoload = true)
{
if (!class_exists($className, $autoload)) {
return false;
}
if (function_exists("ini_get")) {
$disabled = explode(',', ini_get('disable_classes'));
return in_array($className, $disabled) ? false : true;
}
// We can only suppose that it exists, can't be 100% sure, but it's the best guess
return true;
}
/**
* Function phpinfo wrapper
*
* @see https://www.php.net/manual/en/function.phpinfo.php
*
* @param int $flags see phpinfo function flags
*
* @return bool Returns true on success or false on failure.
*/
public static function phpinfo($flags = INFO_ALL)
{
if (!function_exists('phpinfo')) {
return false;
}
return phpinfo($flags);
}
/**
* Checks if CURL is enabled
*
* @param bool $sslCheck Optional. Whether to check that the installed curl version supports SSL.
* @param bool $multiCheck Optional. Whether to check that the installed curl version supports multi.
*
* @return bool True if CURL is enabled, false otherwise
*/
public static function isCurlEnabled($sslCheck = true, $multiCheck = false)
{
if (!function_exists('curl_init') || !function_exists('curl_exec') || !function_exists('curl_getinfo')) {
return false;
}
// If needed, check that our installed curl version supports SSL
if ($sslCheck) {
if (($curl_version = curl_version()) === false) {
return false;
}
if (!(CURL_VERSION_SSL & $curl_version['features'])) {
return false;
}
}
if ($multiCheck) {
if (!function_exists('curl_multi_exec')) {
return false;
}
}
return true;
}
/**
* Check if URL fopen is enabled
*
* @return bool
*/
public static function isUrlFopenEnabled()
{
if (!function_exists('ini_get')) {
// is impossibile to know so is considered enabled
return true;
}
return filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN);
}
/**
* Set whether a client disconnect should abort script execution
*
* @param bool|null $enable true to enable, false to disable
*
* @return bool|int false if function can't be run, otherwise the value of the setting as integer before running this function
*/
public static function ignoreUserAbort($enable)
{
if (!function_exists('ignore_user_abort') || !is_callable('ignore_user_abort')) {
return false;
}
return ignore_user_abort($enable);
}
}