File Editor
Directories:
.. (Back)
parser
storage
Files:
api.php
config.php
http.php
i18n.php
json.php
request.php
rules.php
shutdown.php
storage.php
utils.php
view.php
waf.php
xmlrpc.php
Create New File
Create
Edit File: utils.php
<?php if (defined('WFWAF_VERSION') && !defined('WFWAF_RUN_COMPLETE')) { class wfWAFUtils { /** * Return dot or colon notation of IPv4 or IPv6 address. * * @param string $ip * @return string|bool */ public static function inet_ntop($ip) { // trim this to the IPv4 equiv if it's in the mapped range if (wfWAFUtils::strlen($ip) == 16 && wfWAFUtils::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") { $ip = wfWAFUtils::substr($ip, 12, 4); } return self::hasIPv6Support() ? @inet_ntop($ip) : self::_inet_ntop($ip); } /** * Return the packed binary string of an IPv4 or IPv6 address. * * @param string $ip * @return string */ public static function inet_pton($ip) { // convert the 4 char IPv4 to IPv6 mapped version. $pton = str_pad(self::hasIPv6Support() ? @inet_pton($ip) : self::_inet_pton($ip), 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00", STR_PAD_LEFT); return $pton; } /** * Added compatibility for hosts that do not have inet_pton. * * @param $ip * @return bool|string */ public static function _inet_pton($ip) { // IPv4 if (preg_match('/^(?:\d{1,3}(?:\.|$)){4}/', $ip)) { $octets = explode('.', $ip); $bin = chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]); return $bin; } // IPv6 if (preg_match('/^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i', $ip)) { if ($ip === '::') { return "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; } $colon_count = wfWAFUtils::substr_count($ip, ':'); $dbl_colon_pos = wfWAFUtils::strpos($ip, '::'); if ($dbl_colon_pos !== false) { $ip = str_replace('::', str_repeat(':0000', (($dbl_colon_pos === 0 || $dbl_colon_pos === wfWAFUtils::strlen($ip) - 2) ? 9 : 8) - $colon_count) . ':', $ip); $ip = trim($ip, ':'); } $ip_groups = explode(':', $ip); $ipv6_bin = ''; foreach ($ip_groups as $ip_group) { $ipv6_bin .= pack('H*', str_pad($ip_group, 4, '0', STR_PAD_LEFT)); } return wfWAFUtils::strlen($ipv6_bin) === 16 ? $ipv6_bin : false; } // IPv4 mapped IPv6 if (preg_match('/^((?:0{1,4}(?::|)){0,5})(::)?ffff:((?:\d{1,3}(?:\.|$)){4})$/i', $ip, $matches)) { $octets = explode('.', $matches[3]); return "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]); } return false; } /** * Added compatibility for hosts that do not have inet_ntop. * * @param $ip * @return bool|string */ public static function _inet_ntop($ip) { // IPv4 if (wfWAFUtils::strlen($ip) === 4) { return ord($ip[0]) . '.' . ord($ip[1]) . '.' . ord($ip[2]) . '.' . ord($ip[3]); } // IPv6 if (wfWAFUtils::strlen($ip) === 16) { // IPv4 mapped IPv6 if (wfWAFUtils::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") { return "::ffff:" . ord($ip[12]) . '.' . ord($ip[13]) . '.' . ord($ip[14]) . '.' . ord($ip[15]); } $hex = bin2hex($ip); $groups = str_split($hex, 4); $collapse = false; $done_collapse = false; foreach ($groups as $index => $group) { if ($group == '0000' && !$done_collapse) { if (!$collapse) { $groups[$index] = ':'; } else { $groups[$index] = ''; } $collapse = true; } else if ($collapse) { $done_collapse = true; $collapse = false; } $groups[$index] = ltrim($groups[$index], '0'); } $ip = join(':', array_filter($groups)); $ip = str_replace(':::', '::', $ip); return $ip == ':' ? '::' : $ip; } return false; } /** * Verify PHP was compiled with IPv6 support. * * Some hosts appear to not have inet_ntop, and others appear to have inet_ntop but are unable to process IPv6 addresses. * * @return bool */ public static function hasIPv6Support() { return defined('AF_INET6'); } /** * Expand a compressed printable representation of an IPv6 address. * * @param string $ip * @return string */ public static function expandIPv6Address($ip) { $hex = bin2hex(self::inet_pton($ip)); $ip = wfWAFUtils::substr(preg_replace("/([a-f0-9]{4})/i", "$1:", $hex), 0, -1); return $ip; } protected static $servicesJSON; public static function json_encode($string) { if (function_exists('json_encode')) { return json_encode($string); } else { if (!self::$servicesJSON) { require_once WFWAF_LIB_PATH . 'json.php'; self::$servicesJSON = new wfServices_JSON(); } return self::$servicesJSON->encodeUnsafe($string); } } public static function json_decode($string, $assoc_array = false) { if (function_exists('json_decode')) { return json_decode($string, $assoc_array); } else { if (!self::$servicesJSON) { require_once WFWAF_LIB_PATH . 'json.php'; self::$servicesJSON = new wfServices_JSON(); } $res = self::$servicesJSON->decode($string); if ($assoc_array) $res = self::_json_decode_object_helper($res); return $res; } } /** * @param object $data * @return array */ protected static function _json_decode_object_helper($data) { if (is_object($data)) $data = get_object_vars($data); return is_array($data) ? array_map('wfWAFUtils::_json_decode_object_helper', $data) : $data; } public static function json_encode_limited($data, $limit, $truncatable) { $json = self::json_encode($data); $size = strlen($json); if ($size > $limit) { $json = null; $minimalData = $data; foreach ($minimalData as $key => &$value) { if (in_array($key, $truncatable)) { $value = ''; } } $minimumSize = strlen(self::json_encode($minimalData)); if ($minimumSize <= $limit) { $excess = $size - $limit; foreach ($truncatable as $field) { if (!array_key_exists($field, $data)) continue; $value = $data[$field]; if (is_string($value)) { $originalLength = strlen($value); $truncatedLength = max(0, $originalLength - $excess); $excess -= ($originalLength - $truncatedLength); $data[$field] = substr($value, 0, $truncatedLength); } if ($excess === 0) { $json = self::json_encode($data); break; } } } } return $json; } /** * Compare two strings in constant time. It can leak the length of a string. * * @param string $a Expected string. * @param string $b Actual string. * @return bool Whether strings are equal. */ public static function hash_equals($a, $b) { $a_length = wfWAFUtils::strlen($a); if ($a_length !== wfWAFUtils::strlen($b)) { return false; } $result = 0; // Do not attempt to "optimize" this. for ($i = 0; $i < $a_length; $i++) { $result |= ord($a[$i]) ^ ord($b[$i]); } return $result === 0; } /** * @param $algo * @param $data * @param $key * @param bool|false $raw_output * @return bool|string */ public static function hash_hmac($algo, $data, $key, $raw_output = false) { if (function_exists('hash_hmac')) { return hash_hmac($algo, $data, $key, $raw_output); } return self::_hash_hmac($algo, $data, $key, $raw_output); } /** * @param $algo * @param $data * @param $key * @param bool|false $raw_output * @return bool|string */ private static function _hash_hmac($algo, $data, $key, $raw_output = false) { $packs = array('md5' => 'H32', 'sha1' => 'H40'); if (!isset($packs[$algo])) return false; $pack = $packs[$algo]; if (wfWAFUtils::strlen($key) > 64) $key = pack($pack, $algo($key)); $key = str_pad($key, 64, chr(0)); $ipad = (wfWAFUtils::substr($key, 0, 64) ^ str_repeat(chr(0x36), 64)); $opad = (wfWAFUtils::substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64)); $hmac = $algo($opad . pack($pack, $algo($ipad . $data))); if ($raw_output) return pack($pack, $hmac); return $hmac; } /** * @param int $length * @param string $chars * @return string */ public static function getRandomString($length = 16, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|') { // This is faster than calling self::random_int for $length $bytes = self::random_bytes($length); $return = ''; $maxIndex = wfWAFUtils::strlen($chars) - 1; for ($i = 0; $i < $length; $i++) { $fp = (float) ord($bytes[$i]) / 255.0; // convert to [0,1] $index = (int) (round($fp * $maxIndex)); $return .= $chars[$index]; } return $return; } /** * Polyfill for random_bytes. * * @param int $bytes * @return string */ public static function random_bytes($bytes) { $bytes = (int) $bytes; if (function_exists('random_bytes')) { try { $rand = random_bytes($bytes); if (is_string($rand) && wfWAFUtils::strlen($rand) === $bytes) { return $rand; } } catch (Exception $e) { // Fall through } catch (TypeError $e) { // Fall through } catch (Error $e) { // Fall through } } if (function_exists('mcrypt_create_iv')) { // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.mcrypt_create_ivDeprecatedRemoved,PHPCompatibility.Extensions.RemovedExtensions.mcryptDeprecatedRemoved,PHPCompatibility.Constants.RemovedConstants.mcrypt_dev_urandomDeprecatedRemoved $rand = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); if (is_string($rand) && wfWAFUtils::strlen($rand) === $bytes) { return $rand; } } if (function_exists('openssl_random_pseudo_bytes')) { $rand = @openssl_random_pseudo_bytes($bytes, $strong); if (is_string($rand) && wfWAFUtils::strlen($rand) === $bytes) { return $rand; } } // Last resort is insecure $return = ''; for ($i = 0; $i < $bytes; $i++) { $return .= chr(mt_rand(0, 255)); } return $return; } /** * Polyfill for random_int. * * @param int $min * @param int $max * @return int */ public static function random_int($min = 0, $max = 0x7FFFFFFF) { if (function_exists('random_int')) { try { return random_int($min, $max); } catch (Exception $e) { // Fall through } catch (TypeError $e) { // Fall through } catch (Error $e) { // Fall through } } $diff = $max - $min; $bytes = self::random_bytes(4); if ($bytes === false || wfWAFUtils::strlen($bytes) != 4) { throw new RuntimeException("Unable to get 4 bytes"); } $val = @unpack("Nint", $bytes); $val = $val['int'] & 0x7FFFFFFF; $fp = (float) $val / 2147483647.0; // convert to [0,1] return (int) (round($fp * $diff) + $min); } /** * @param mixed $subject * @return array|string */ public static function stripMagicQuotes($subject) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.magic_quotes_sybaseDeprecatedRemoved $sybase = ini_get('magic_quotes_sybase'); $sybaseEnabled = ((is_numeric($sybase) && $sybase) || (is_string($sybase) && $sybase && !in_array(wfWAFUtils::strtolower($sybase), array( 'off', 'false' )))); if (defined('PHP_VERSION_ID') && PHP_VERSION_ID >= 70400) { //Avoid get_magic_quotes_gpc on PHP >= 7.4.0 return $subject; } // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated if ((function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) || $sybaseEnabled) { return self::stripslashes_deep($subject); } return $subject; } /** * @param mixed $subject * @return array|string */ public static function stripslashes_deep($subject) { if (is_array($subject)) { return array_map(array( 'self', 'stripslashes_deep', ), $subject); } else if (is_string($subject)) { return stripslashes($subject); } return $subject; } /** * Set the mbstring internal encoding to a binary safe encoding when func_overload * is enabled. * * When mbstring.func_overload is in use for multi-byte encodings, the results from * strlen() and similar functions respect the utf8 characters, causing binary data * to return incorrect lengths. * * This function overrides the mbstring encoding to a binary-safe encoding, and * resets it to the users expected encoding afterwards through the * `reset_mbstring_encoding` function. * * It is safe to recursively call this function, however each * `mbstring_binary_safe_encoding()` call must be followed up with an equal number * of `reset_mbstring_encoding()` calls. * * @see wfWAFUtils::reset_mbstring_encoding * * @staticvar array $encodings * @staticvar bool $overloaded * * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding. * Default false. */ public static function mbstring_binary_safe_encoding($reset = false) { static $encodings = array(); static $overloaded = null; if (is_null($overloaded)) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated $overloaded = function_exists('mb_internal_encoding') && (ini_get('mbstring.func_overload') & 2); } if (false === $overloaded) { return; } if (!$reset) { $encoding = mb_internal_encoding(); array_push($encodings, $encoding); mb_internal_encoding('ISO-8859-1'); } if ($reset && $encodings) { $encoding = array_pop($encodings); mb_internal_encoding($encoding); } } /** * Reset the mbstring internal encoding to a users previously set encoding. * * @see wfWAFUtils::mbstring_binary_safe_encoding */ public static function reset_mbstring_encoding() { self::mbstring_binary_safe_encoding(true); } /** * @param callable $function * @param array $args * @return mixed */ protected static function callMBSafeStrFunction($function, $args) { self::mbstring_binary_safe_encoding(); $return = call_user_func_array($function, $args); self::reset_mbstring_encoding(); return $return; } /** * Multibyte safe strlen. * * @param $binary * @return int */ public static function strlen($binary) { $args = func_get_args(); return self::callMBSafeStrFunction('strlen', $args); } /** * @param $haystack * @param $needle * @param int $offset * @return int */ public static function stripos($haystack, $needle, $offset = 0) { $args = func_get_args(); return self::callMBSafeStrFunction('stripos', $args); } /** * @param $string * @return mixed */ public static function strtolower($string) { $args = func_get_args(); return self::callMBSafeStrFunction('strtolower', $args); } /** * @param $string * @param $start * @param $length * @return mixed */ public static function substr($string, $start, $length = null) { if ($length === null) { $length = self::strlen($string); } return self::callMBSafeStrFunction('substr', array( $string, $start, $length )); } /** * @param $haystack * @param $needle * @param int $offset * @return mixed */ public static function strpos($haystack, $needle, $offset = 0) { $args = func_get_args(); return self::callMBSafeStrFunction('strpos', $args); } /** * @param string $haystack * @param string $needle * @param int $offset * @param int $length * @return mixed */ public static function substr_count($haystack, $needle, $offset = 0, $length = null) { if ($length === null) { $length = self::strlen($haystack); } return self::callMBSafeStrFunction('substr_count', array( $haystack, $needle, $offset, $length )); } /** * @param $string * @return mixed */ public static function strtoupper($string) { $args = func_get_args(); return self::callMBSafeStrFunction('strtoupper', $args); } /** * @param string $haystack * @param string $needle * @param int $offset * @return mixed */ public static function strrpos($haystack, $needle, $offset = 0) { $args = func_get_args(); return self::callMBSafeStrFunction('strrpos', $args); } /** * @param string $val An ini byte size value (e.g., 20M) * @return int */ public static function iniSizeToBytes($val) { $val = trim($val); if (preg_match('/^\d+$/', $val)) { return (int) $val; } $last = strtolower(substr($val, -1)); $val = (int) substr($val, 0, -1); switch ($last) { case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; } public static function reverseLookup($IP) { $IPn = self::inet_pton($IP); // This function works for IPv4 or IPv6 if (function_exists('gethostbyaddr')) { $host = @gethostbyaddr($IP); } if (!$host) { $ptr = false; if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) { $ptr = implode(".", array_reverse(explode(".", $IP))) . ".in-addr.arpa"; } else if (filter_var($IP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) { $ptr = implode(".", array_reverse(str_split(bin2hex($IPn)))) . ".ip6.arpa"; } if ($ptr && function_exists('dns_get_record')) { $host = @dns_get_record($ptr, DNS_PTR); if ($host) { $host = $host[0]['target']; } } } if (!$host) { return ''; } return $host; } public static function patternToRegex($pattern, $mod = 'i', $sep = '/') { $pattern = preg_quote(trim($pattern), $sep); $pattern = str_replace(' ', '\s', $pattern); return $sep . '^' . str_replace('\*', '.*', $pattern) . '$' . $sep . $mod; } public static function isUABlocked($uaPattern, $ua) { // takes a pattern using asterisks as wildcards, turns it into regex and checks it against the visitor UA returning true if blocked return fnmatch($uaPattern, $ua, FNM_CASEFOLD); } public static function isRefererBlocked($refPattern, $referer) { return fnmatch($refPattern, $referer, FNM_CASEFOLD); } public static function extractBareURI($URL) { $URL = preg_replace('/^https?:\/\/[^\/]+/i', '', $URL); //strip of method and host $URL = preg_replace('/\#.*$/', '', $URL); //strip off fragment $URL = preg_replace('/\?.*$/', '', $URL); //strip off query string return $URL; } public static function extractHostname($str) { if (preg_match('/https?:\/\/([a-zA-Z0-9\.\-]+)(?:\/|$)/i', $str, $matches)) { return strtolower($matches[1]); } else { return false; } } public static function redirect($location, $status = 302) { $is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false); $is_IIS = !$is_apache && (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false); self::doNotCache(); if (!$is_IIS && PHP_SAPI != 'cgi-fcgi') { self::statusHeader($status); // This causes problems on IIS and some FastCGI setups } header("Location: {$location}", true, $status); exit; } public static function statusHeader($code) { $code = abs(intval($code)); $statusCodes = array( 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 510 => 'Not Extended', 511 => 'Network Authentication Required', ); $description = (isset($statusCodes[$code]) ? $statusCodes[$code] : ''); $protocol = $_SERVER['SERVER_PROTOCOL']; if (!in_array($protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0'))) { $protocol = 'HTTP/1.0'; } $header = "{$protocol} {$code} {$description}"; @header($header, true, $code); } public static function doNotCache() { header("Pragma: no-cache"); header("Cache-Control: no-cache, must-revalidate, private, max-age=0"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //In the past if (!defined('DONOTCACHEPAGE')) { define('DONOTCACHEPAGE', true); } if (!defined('DONOTCACHEDB')) { define('DONOTCACHEDB', true); } if (!defined('DONOTCDN')) { define('DONOTCDN', true); } if (!defined('DONOTCACHEOBJECT')) { define('DONOTCACHEOBJECT', true); } } /** * Check if an IP address is in a network block * * @param string $subnet Single IP or subnet in CIDR notation (e.g. '192.168.100.0' or '192.168.100.0/22') * @param string $ip IPv4 or IPv6 address in dot or colon notation * @return boolean */ public static function subnetContainsIP($subnet, $ip) { static $_network_cache = array(); static $_ip_cache = array(); static $_masks = array( 0 => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 1 => "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 2 => "\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 3 => "\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 4 => "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 5 => "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 6 => "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 7 => "\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 8 => "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 9 => "\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10 => "\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 11 => "\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12 => "\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 13 => "\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14 => "\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 15 => "\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16 => "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 17 => "\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 18 => "\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 19 => "\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 20 => "\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 21 => "\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 22 => "\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 23 => "\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24 => "\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 25 => "\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 26 => "\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 27 => "\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 28 => "\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 29 => "\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 30 => "\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 31 => "\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32 => "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 33 => "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 34 => "\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 35 => "\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 36 => "\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 37 => "\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 38 => "\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 39 => "\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 40 => "\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 41 => "\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 42 => "\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 43 => "\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 44 => "\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 45 => "\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 46 => "\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 47 => "\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 48 => "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 49 => "\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00", 50 => "\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00", 51 => "\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00", 52 => "\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00", 53 => "\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00", 54 => "\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00", 55 => "\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00", 56 => "\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00", 57 => "\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00", 58 => "\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00", 59 => "\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00", 60 => "\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00", 61 => "\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00", 62 => "\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00", 63 => "\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00", 64 => "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00", 65 => "\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", 66 => "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00", 67 => "\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00", 68 => "\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00", 69 => "\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00", 70 => "\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00", 71 => "\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00", 72 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00", 73 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00", 74 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00", 75 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00", 76 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00", 77 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00", 78 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00", 79 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00", 80 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00", 81 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00", 82 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00", 83 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00", 84 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00", 85 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00", 86 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00", 87 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00", 88 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00", 89 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00", 90 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00", 91 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00", 92 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00", 93 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00", 94 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00", 95 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00", 96 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00", 97 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00", 98 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00", 99 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00", 100 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00", 101 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00", 102 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00", 103 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00", 104 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00", 105 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00", 106 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00", 107 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00", 108 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00", 109 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00", 110 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00", 111 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00", 112 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00", 113 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00", 114 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00", 115 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00", 116 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00", 117 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00", 118 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00", 119 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00", 120 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00", 121 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80", 122 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0", 123 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0", 124 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0", 125 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8", 126 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc", 127 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe", 128 => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); /* * The above is generated by: * function gen_mask($prefix, $size = 128) { //Workaround to avoid overflow, split into four pieces $mask_1 = (pow(2, $size / 4) - 1) ^ (pow(2, min($size / 4, max(0, 1 * $size / 4 - $prefix))) - 1); $mask_2 = (pow(2, $size / 4) - 1) ^ (pow(2, min($size / 4, max(0, 2 * $size / 4 - $prefix))) - 1); $mask_3 = (pow(2, $size / 4) - 1) ^ (pow(2, min($size / 4, max(0, 3 * $size / 4 - $prefix))) - 1); $mask_4 = (pow(2, $size / 4) - 1) ^ (pow(2, min($size / 4, max(0, 4 * $size / 4 - $prefix))) - 1); return ($mask_1 ? pack('N', $mask_1) : "\0\0\0\0") . ($mask_2 ? pack('N', $mask_2) : "\0\0\0\0") . ($mask_3 ? pack('N', $mask_3) : "\0\0\0\0") . ($mask_4 ? pack('N', $mask_4) : "\0\0\0\0"); } $masks = array(); for ($i = 0; $i <= 128; $i++) { $mask = gen_mask($i); $chars = str_split($mask); $masks[] = implode('', array_map(function($c) { return '\\x' . bin2hex($c); }, $chars)); } echo 'array(' . "\n"; foreach ($masks as $index => $m) { echo "\t{$index} => \"{$m}\",\n"; } echo ')'; * */ if (isset($_network_cache[$subnet])) { list($bin_network, $prefix, $masked_network) = $_network_cache[$subnet]; $mask = $_masks[$prefix]; } else { list($network, $prefix) = array_pad(explode('/', $subnet, 2), 2, null); if (filter_var($network, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { // If no prefix was supplied, 32 is implied for IPv4 if ($prefix === null) { $prefix = 32; } // Validate the IPv4 network prefix if ($prefix < 0 || $prefix > 32) { return false; } // Increase the IPv4 network prefix to work in the IPv6 address space $prefix += 96; } else { // If no prefix was supplied, 128 is implied for IPv6 if ($prefix === null) { $prefix = 128; } // Validate the IPv6 network prefix if ($prefix < 1 || $prefix > 128) { return false; } } $mask = $_masks[$prefix]; $bin_network = self::inet_pton($network); $masked_network = $bin_network & $mask; $_network_cache[$subnet] = array($bin_network, $prefix, $masked_network); } if (isset($_ip_cache[$ip]) && isset($_ip_cache[$ip][$prefix])) { list($bin_ip, $masked_ip) = $_ip_cache[$ip][$prefix]; } else { $bin_ip = self::inet_pton($ip); $masked_ip = $bin_ip & $mask; if (!isset($_ip_cache[$ip])) { $_ip_cache[$ip] = array(); } $_ip_cache[$ip][$prefix] = array($bin_ip, $masked_ip); } return ($masked_ip === $masked_network); } /** * Behaves exactly like PHP's parse_url but uses WP's compatibility fixes for early PHP 5 versions. * * @param string $url * @param int $component * @return mixed */ public static function parse_url($url, $component = -1) { $to_unset = array(); $url = strval($url); if (substr($url, 0, 2) === '//') { $to_unset[] = 'scheme'; $url = 'placeholder:' . $url; } elseif (substr($url, 0, 1) === '/') { $to_unset[] = 'scheme'; $to_unset[] = 'host'; $url = 'placeholder://placeholder' . $url; } $parts = @parse_url($url); if ($parts === false) { // Parsing failure return $parts; } // Remove the placeholder values foreach ($to_unset as $key) { unset($parts[$key]); } if ($component === -1) { return $parts; } $translation = array( PHP_URL_SCHEME => 'scheme', PHP_URL_HOST => 'host', PHP_URL_PORT => 'port', PHP_URL_USER => 'user', PHP_URL_PASS => 'pass', PHP_URL_PATH => 'path', PHP_URL_QUERY => 'query', PHP_URL_FRAGMENT => 'fragment', ); $key = false; if (isset($translation[$component])) { $key = $translation[$component]; } if ($key !== false && is_array($parts) && isset($parts[$key])) { return $parts[$key]; } return null; } /** * Validates the URL, supporting both scheme-relative and path-relative formats. * * @param $url * @return mixed */ public static function validate_url($url) { $url = strval($url); if (substr($url, 0, 2) === '//') { $url = 'placeholder:' . $url; } elseif (substr($url, 0, 1) === '/') { $url = 'placeholder://placeholder' . $url; } return filter_var($url, FILTER_VALIDATE_URL); } public static function rawPOSTBody() { // phpcs:ignore PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved global $HTTP_RAW_POST_DATA; // phpcs:ignore PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved if (empty($HTTP_RAW_POST_DATA)) { //Defined if always_populate_raw_post_data is on, PHP < 7, and the encoding type is not multipart/form-data $avoidPHPInput = false; try { $avoidPHPInput = wfWAF::getSharedStorageEngine() && wfWAF::getSharedStorageEngine()->getConfig('avoid_php_input', false); } catch (Exception $e) { //Ignore } if ($avoidPHPInput) { //Some custom PHP builds break reading from php://input //Reconstruct the best possible approximation of it from $_POST if populated -- won't help JSON or other raw payloads $data = http_build_query($_POST, '', '&'); } else { $data = file_get_contents('php://input'); //Available if the encoding type is not multipart/form-data; it can only be read once prior to PHP 5.6 so we save it in $HTTP_RAW_POST_DATA for WP Core and others //For our purposes, we don't currently need the raw POST body if it's multipart/form-data since the data will be in $_POST/$_FILES. If we did, we could reconstruct the body here. // phpcs:ignore PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved $HTTP_RAW_POST_DATA = $data; } } else { // phpcs:ignore PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved $data =& $HTTP_RAW_POST_DATA; } return $data; } /** * Returns the current timestamp, adjusted as needed to get close to what we consider a true timestamp. We use this * because a significant number of servers are using a drastically incorrect time. * * @return int */ public static function normalizedTime() { $offset = 0; try { $offset = wfWAF::getInstance()->getStorageEngine()->getConfig('timeoffset_ntp', false, 'synced'); if ($offset === false) { $offset = wfWAF::getInstance()->getStorageEngine()->getConfig('timeoffset_wf', false, 'synced'); if ($offset === false) { $offset = 0; } } } catch (Exception $e) { //Ignore } return time() + $offset; } /** * @param $file * @return array|bool */ public static function extractCredentialsWPConfig($file, &$return = array()) { $configContents = file_get_contents($file); $tokens = token_get_all($configContents); $tokens = array_values(array_filter($tokens, 'wfWAFUtils::_removeUnneededTokens')); $parsedConstants = array(); $parsedVariables = array(); for ($i = 0; $i < count($tokens); $i++) { $token = $tokens[$i]; if (is_array($token)) { if (token_name($token[0]) === 'T_STRING' && strtolower($token[1]) === 'define') { $startParenToken = $tokens[$i + 1]; $constantNameToken = $tokens[$i + 2]; $commaToken = $tokens[$i + 3]; $constantValueToken = $tokens[$i + 4]; $endParenToken = $tokens[$i + 5]; if ( !is_array($startParenToken) && $startParenToken === '(' && is_array($constantNameToken) && token_name($constantNameToken[0]) === 'T_CONSTANT_ENCAPSED_STRING' && !is_array($commaToken) && $commaToken === ',' && is_array($constantValueToken) && in_array(token_name($constantValueToken[0]), array('T_CONSTANT_ENCAPSED_STRING', 'T_STRING')) && !is_array($endParenToken) && $endParenToken === ')' ) { if (token_name($constantValueToken[0]) === 'T_STRING') { $value = defined($constantValueToken[1]) ? constant($constantValueToken[1]) : null; } else { $value = self::substr($constantValueToken[1], 1, -1); } $parsedConstants[self::substr($constantNameToken[1], 1, -1)] = $value; } } if (token_name($token[0]) === 'T_VARIABLE') { $assignmentToken = $tokens[$i + 1]; $variableValueToken = $tokens[$i + 2]; if ( !is_array($assignmentToken) && $assignmentToken === '=' && is_array($variableValueToken) && token_name($variableValueToken[0]) === 'T_CONSTANT_ENCAPSED_STRING' ) { $parsedVariables[$token[1]] = self::substr($variableValueToken[1], 1, -1); } } } } $optionalConstants = array( 'flags' => 'MYSQL_CLIENT_FLAGS' ); $constants = array( 'user' => 'DB_USER', 'pass' => 'DB_PASSWORD', 'database' => 'DB_NAME', 'host' => 'DB_HOST', 'charset' => 'DB_CHARSET', 'collation' => 'DB_COLLATE' ); $constants += $optionalConstants; foreach ($constants as $key => $constant) { if (array_key_exists($key, $return)) { continue; } else if (array_key_exists($constant, $parsedConstants)) { $return[$key] = $parsedConstants[$constant]; } else if (!array_key_exists($key, $optionalConstants)){ return ($return = false); } } /** * @see \wpdb::parse_db_host */ $socketPos = self::strpos($return['host'], ':/'); if ($socketPos !== false) { $return['socket'] = self::substr($return['host'], $socketPos + 1); $return['host'] = self::substr($return['host'], 0, $socketPos); } if ( self::substr_count( $return['host'], ':' ) > 1 ) { $pattern = '#^(?:\[)?(?P<host>[0-9a-fA-F:]+)(?:\]:(?P<port>[\d]+))?#'; $return['ipv6'] = true; } else { $pattern = '#^(?P<host>[^:/]*)(?::(?P<port>[\d]+))?#'; } $matches = array(); $result = preg_match($pattern, $return['host'], $matches); if (1 !== $result) { return ($return = false); } foreach (array('host', 'port') as $component) { if (!empty($matches[$component])) { $return[$component] = $matches[$component]; } } if (!array_key_exists('tablePrefix', $return)) { if (array_key_exists('$table_prefix', $parsedVariables)) { $return['tablePrefix'] = $parsedVariables['$table_prefix']; } else { return ($return = false); } } return $return; } protected static function _removeUnneededTokens($token) { if (is_array($token)) { return !in_array(token_name($token[0]), array( 'T_DOC_COMMENT', 'T_WHITESPACE' )); } return true; } public static function isVersionBelow($target, $compared) { return $compared === null || version_compare($compared, $target, '<'); } } }
Save Changes
Rename File
Rename