&$value) { if (is_array($value) /* Recursive function call here. */) $value = c_ws_plugin__s2member_utils_arrays::remove_nulls ($value); else if (is_null /* Is it null? */ ($value)) unset($array[$key]); } return $array; } /** * Removes all 0-byte strings from an array *(or even a multi-dimensional array)*. * * @package s2Member\Utilities * @since 111216 * * @param array $array An input array. * @return array Returns the ``$array`` after having reduced its set of values. */ public static function remove_0b_strings ($array = FALSE) { $array = (array)$array; foreach ($array as $key => &$value) { if (is_array($value) /* Recursive function call here. */) $value = c_ws_plugin__s2member_utils_arrays::remove_0b_strings ($value); else if (is_string ($value) && !strlen ($value)) unset($array[$key]); } return $array; } /** * Sets specified array elements to an empty string when they are not set according to ``isset()`` (missing or NULL). * * @package s2Member\Utilities * @since 260814 * * @param array $array An input array. * @param array $keys Array keys whose unset elements should be set. * @return array Returns the ``$array`` after setting unset elements to empty strings. */ public static function set_unset_elements ($array = FALSE, $keys = FALSE) { $array = (array)$array; $keys = (array)$keys; //260814 isset() treats both missing keys and null values as unset; initialize either case to an empty string. foreach ($keys as $key) if (!isset($array[$key])) $array[$key] = ''; return $array; } /** * Forces string values on each array value *(also supports multi-dimensional arrays)*. * * @package s2Member\Utilities * @since 111101 * * @param array $array An input array. * @return array Returns the ``$array`` after having forced it to set of string values. */ public static function force_strings ($array = FALSE) { $array = (array)$array; foreach ($array as &$value) { if (is_array($value) /* Recursive function call here. */) $value = c_ws_plugin__s2member_utils_arrays::force_strings ($value); else if (!is_string ($value) /* String? */) $value = (string)$value; } return $array; } /** * Forces integer values on each array value *(also supports multi-dimensional arrays)*. * * @package s2Member\Utilities * @since 111101 * * @param array $array An input array. * @return array Returns the ``$array`` after having forced it to set of integer values. */ public static function force_integers ($array = array()) { $array = (array)$array; foreach ($array as &$value) { if (is_array($value) /* Recursive function call here. */) $value = c_ws_plugin__s2member_utils_arrays::force_integers ($value); else if (!is_integer ($value) /* Integer? */) $value = (int)$value; } return $array; } /** * Sorts arrays *(also supports multi-dimensional arrays)* by key, low to high. * * @package s2Member\Utilities * @since 111205 * * @param array $array An input array. * @param int $flags Optional. Can be used to modify the sorting behavior. * See: {@link http://www.php.net/manual/en/function.ksort.php} * @return Unlike PHP's ``ksort()``, this function returns the array, and does NOT work on a reference. */ public static function ksort_deep ($array = FALSE, $flags = SORT_REGULAR) { $array = (array)$array; ksort /* Sort by key. */ ($array, $flags); foreach ($array as &$value) if (is_array($value) /* Recursive function call here. */) $value = c_ws_plugin__s2member_utils_arrays::ksort_deep ($value, $flags); return /* Now return the array. */ $array; } /** * Safely unserializes a value when appropriate. * * @package s2Member\Utilities * @since 250801 * @since 260808 Added additional validation before unserializing. * * @param mixed $value The value to be unserialized. * @return mixed The unserialized value, or original if not serialized or blocked. */ public static function maybe_unserialize($value) { if (!is_string($value) || !is_serialized($value)) { return $value; } $value = trim($value); //260808 Reject disallowed serialization types without matching harmless text inside serialized strings. if (self::serialized_contains_disallowed_type($value)) { do_action('ws_plugin__s2member_security_object_detected', $value); return null; } if (version_compare(PHP_VERSION, '7.0.0', '>=')) { return @unserialize($value, ['allowed_classes' => false]); } return @unserialize($value); } /** * Checks serialized data for disallowed serialization types. * * Serialized string payloads are skipped so object-like text inside a * normal string does not produce a false positive. * * @package s2Member\Utilities * @since 260808 * * @param string $value Serialized value to inspect. * @return bool True if a disallowed serialization type is present. */ private static function serialized_contains_disallowed_type($value) { $length = strlen($value); for ($offset = 0; $offset < $length; ++$offset) { $token = $value[$offset]; //260808 Skip complete serialized strings so harmless text such as "PROMO:" is not mistaken for an object token. if ($token === 's' && isset($value[$offset + 1]) && $value[$offset + 1] === ':') { if (!preg_match('/\Gs:([0-9]+):"/', $value, $match, 0, $offset)) { continue; } $string_length = (int)$match[1]; $string_start = $offset + strlen($match[0]); $string_end = $string_start + $string_length; if ($string_end + 1 >= $length || substr($value, $string_end, 2) !== '";') { return true; } $offset = $string_end + 1; continue; } //260808 O=object, C=Serializable object, E=enum object, S=noncanonical string, R/r=references that can create cyclic structures. if (($token === 'O' || $token === 'C' || $token === 'E' || $token === 'S' || $token === 'R' || $token === 'r') && isset($value[$offset + 1]) && $value[$offset + 1] === ':') { return true; } } return false; } } }