angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

compat.php (12087B)


      1 <?php
      2 /**
      3  * WordPress implementation for PHP functions either missing from older PHP versions or not included by default.
      4  *
      5  * @package PHP
      6  * @access private
      7  */
      8 
      9 // If gettext isn't available.
     10 if ( ! function_exists( '_' ) ) {
     11 	function _( $string ) {
     12 		return $string;
     13 	}
     14 }
     15 
     16 /**
     17  * Returns whether PCRE/u (PCRE_UTF8 modifier) is available for use.
     18  *
     19  * @ignore
     20  * @since 4.2.2
     21  * @access private
     22  *
     23  * @param bool $set - Used for testing only
     24  *             null   : default - get PCRE/u capability
     25  *             false  : Used for testing - return false for future calls to this function
     26  *             'reset': Used for testing - restore default behavior of this function
     27  */
     28 function _wp_can_use_pcre_u( $set = null ) {
     29 	static $utf8_pcre = 'reset';
     30 
     31 	if ( null !== $set ) {
     32 		$utf8_pcre = $set;
     33 	}
     34 
     35 	if ( 'reset' === $utf8_pcre ) {
     36 		// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- intentional error generated to detect PCRE/u support.
     37 		$utf8_pcre = @preg_match( '/^./u', 'a' );
     38 	}
     39 
     40 	return $utf8_pcre;
     41 }
     42 
     43 if ( ! function_exists( 'mb_substr' ) ) :
     44 	/**
     45 	 * Compat function to mimic mb_substr().
     46 	 *
     47 	 * @ignore
     48 	 * @since 3.2.0
     49 	 *
     50 	 * @see _mb_substr()
     51 	 *
     52 	 * @param string      $str      The string to extract the substring from.
     53 	 * @param int         $start    Position to being extraction from in `$str`.
     54 	 * @param int|null    $length   Optional. Maximum number of characters to extract from `$str`.
     55 	 *                              Default null.
     56 	 * @param string|null $encoding Optional. Character encoding to use. Default null.
     57 	 * @return string Extracted substring.
     58 	 */
     59 	function mb_substr( $str, $start, $length = null, $encoding = null ) {
     60 		return _mb_substr( $str, $start, $length, $encoding );
     61 	}
     62 endif;
     63 
     64 /**
     65  * Internal compat function to mimic mb_substr().
     66  *
     67  * Only understands UTF-8 and 8bit.  All other character sets will be treated as 8bit.
     68  * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
     69  * The behavior of this function for invalid inputs is undefined.
     70  *
     71  * @ignore
     72  * @since 3.2.0
     73  *
     74  * @param string      $str      The string to extract the substring from.
     75  * @param int         $start    Position to being extraction from in `$str`.
     76  * @param int|null    $length   Optional. Maximum number of characters to extract from `$str`.
     77  *                              Default null.
     78  * @param string|null $encoding Optional. Character encoding to use. Default null.
     79  * @return string Extracted substring.
     80  */
     81 function _mb_substr( $str, $start, $length = null, $encoding = null ) {
     82 	if ( null === $encoding ) {
     83 		$encoding = get_option( 'blog_charset' );
     84 	}
     85 
     86 	/*
     87 	 * The solution below works only for UTF-8, so in case of a different
     88 	 * charset just use built-in substr().
     89 	 */
     90 	if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ), true ) ) {
     91 		return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length );
     92 	}
     93 
     94 	if ( _wp_can_use_pcre_u() ) {
     95 		// Use the regex unicode support to separate the UTF-8 characters into an array.
     96 		preg_match_all( '/./us', $str, $match );
     97 		$chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length );
     98 		return implode( '', $chars );
     99 	}
    100 
    101 	$regex = '/(
    102 		[\x00-\x7F]                  # single-byte sequences   0xxxxxxx
    103 		| [\xC2-\xDF][\x80-\xBF]       # double-byte sequences   110xxxxx 10xxxxxx
    104 		| \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
    105 		| [\xE1-\xEC][\x80-\xBF]{2}
    106 		| \xED[\x80-\x9F][\x80-\xBF]
    107 		| [\xEE-\xEF][\x80-\xBF]{2}
    108 		| \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
    109 		| [\xF1-\xF3][\x80-\xBF]{3}
    110 		| \xF4[\x80-\x8F][\x80-\xBF]{2}
    111 	)/x';
    112 
    113 	// Start with 1 element instead of 0 since the first thing we do is pop.
    114 	$chars = array( '' );
    115 	do {
    116 		// We had some string left over from the last round, but we counted it in that last round.
    117 		array_pop( $chars );
    118 
    119 		/*
    120 		 * Split by UTF-8 character, limit to 1000 characters (last array element will contain
    121 		 * the rest of the string).
    122 		 */
    123 		$pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
    124 
    125 		$chars = array_merge( $chars, $pieces );
    126 
    127 		// If there's anything left over, repeat the loop.
    128 	} while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) );
    129 
    130 	return implode( '', array_slice( $chars, $start, $length ) );
    131 }
    132 
    133 if ( ! function_exists( 'mb_strlen' ) ) :
    134 	/**
    135 	 * Compat function to mimic mb_strlen().
    136 	 *
    137 	 * @ignore
    138 	 * @since 4.2.0
    139 	 *
    140 	 * @see _mb_strlen()
    141 	 *
    142 	 * @param string      $str      The string to retrieve the character length from.
    143 	 * @param string|null $encoding Optional. Character encoding to use. Default null.
    144 	 * @return int String length of `$str`.
    145 	 */
    146 	function mb_strlen( $str, $encoding = null ) {
    147 		return _mb_strlen( $str, $encoding );
    148 	}
    149 endif;
    150 
    151 /**
    152  * Internal compat function to mimic mb_strlen().
    153  *
    154  * Only understands UTF-8 and 8bit.  All other character sets will be treated as 8bit.
    155  * For $encoding === UTF-8, the `$str` input is expected to be a valid UTF-8 byte
    156  * sequence. The behavior of this function for invalid inputs is undefined.
    157  *
    158  * @ignore
    159  * @since 4.2.0
    160  *
    161  * @param string      $str      The string to retrieve the character length from.
    162  * @param string|null $encoding Optional. Character encoding to use. Default null.
    163  * @return int String length of `$str`.
    164  */
    165 function _mb_strlen( $str, $encoding = null ) {
    166 	if ( null === $encoding ) {
    167 		$encoding = get_option( 'blog_charset' );
    168 	}
    169 
    170 	/*
    171 	 * The solution below works only for UTF-8, so in case of a different charset
    172 	 * just use built-in strlen().
    173 	 */
    174 	if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ), true ) ) {
    175 		return strlen( $str );
    176 	}
    177 
    178 	if ( _wp_can_use_pcre_u() ) {
    179 		// Use the regex unicode support to separate the UTF-8 characters into an array.
    180 		preg_match_all( '/./us', $str, $match );
    181 		return count( $match[0] );
    182 	}
    183 
    184 	$regex = '/(?:
    185 		[\x00-\x7F]                  # single-byte sequences   0xxxxxxx
    186 		| [\xC2-\xDF][\x80-\xBF]       # double-byte sequences   110xxxxx 10xxxxxx
    187 		| \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
    188 		| [\xE1-\xEC][\x80-\xBF]{2}
    189 		| \xED[\x80-\x9F][\x80-\xBF]
    190 		| [\xEE-\xEF][\x80-\xBF]{2}
    191 		| \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
    192 		| [\xF1-\xF3][\x80-\xBF]{3}
    193 		| \xF4[\x80-\x8F][\x80-\xBF]{2}
    194 	)/x';
    195 
    196 	// Start at 1 instead of 0 since the first thing we do is decrement.
    197 	$count = 1;
    198 	do {
    199 		// We had some string left over from the last round, but we counted it in that last round.
    200 		$count--;
    201 
    202 		/*
    203 		 * Split by UTF-8 character, limit to 1000 characters (last array element will contain
    204 		 * the rest of the string).
    205 		 */
    206 		$pieces = preg_split( $regex, $str, 1000 );
    207 
    208 		// Increment.
    209 		$count += count( $pieces );
    210 
    211 		// If there's anything left over, repeat the loop.
    212 	} while ( $str = array_pop( $pieces ) );
    213 
    214 	// Fencepost: preg_split() always returns one extra item in the array.
    215 	return --$count;
    216 }
    217 
    218 if ( ! function_exists( 'hash_hmac' ) ) :
    219 	/**
    220 	 * Compat function to mimic hash_hmac().
    221 	 *
    222 	 * The Hash extension is bundled with PHP by default since PHP 5.1.2.
    223 	 * However, the extension may be explicitly disabled on select servers.
    224 	 * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no
    225 	 * longer be disabled.
    226 	 * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill
    227 	 * and the associated `_hash_hmac()` function can be safely removed.
    228 	 *
    229 	 * @ignore
    230 	 * @since 3.2.0
    231 	 *
    232 	 * @see _hash_hmac()
    233 	 *
    234 	 * @param string $algo       Hash algorithm. Accepts 'md5' or 'sha1'.
    235 	 * @param string $data       Data to be hashed.
    236 	 * @param string $key        Secret key to use for generating the hash.
    237 	 * @param bool   $raw_output Optional. Whether to output raw binary data (true),
    238 	 *                           or lowercase hexits (false). Default false.
    239 	 * @return string|false The hash in output determined by `$raw_output`. False if `$algo`
    240 	 *                      is unknown or invalid.
    241 	 */
    242 	function hash_hmac( $algo, $data, $key, $raw_output = false ) {
    243 		return _hash_hmac( $algo, $data, $key, $raw_output );
    244 	}
    245 endif;
    246 
    247 /**
    248  * Internal compat function to mimic hash_hmac().
    249  *
    250  * @ignore
    251  * @since 3.2.0
    252  *
    253  * @param string $algo       Hash algorithm. Accepts 'md5' or 'sha1'.
    254  * @param string $data       Data to be hashed.
    255  * @param string $key        Secret key to use for generating the hash.
    256  * @param bool   $raw_output Optional. Whether to output raw binary data (true),
    257  *                           or lowercase hexits (false). Default false.
    258  * @return string|false The hash in output determined by `$raw_output`. False if `$algo`
    259  *                      is unknown or invalid.
    260  */
    261 function _hash_hmac( $algo, $data, $key, $raw_output = false ) {
    262 	$packs = array(
    263 		'md5'  => 'H32',
    264 		'sha1' => 'H40',
    265 	);
    266 
    267 	if ( ! isset( $packs[ $algo ] ) ) {
    268 		return false;
    269 	}
    270 
    271 	$pack = $packs[ $algo ];
    272 
    273 	if ( strlen( $key ) > 64 ) {
    274 		$key = pack( $pack, $algo( $key ) );
    275 	}
    276 
    277 	$key = str_pad( $key, 64, chr( 0 ) );
    278 
    279 	$ipad = ( substr( $key, 0, 64 ) ^ str_repeat( chr( 0x36 ), 64 ) );
    280 	$opad = ( substr( $key, 0, 64 ) ^ str_repeat( chr( 0x5C ), 64 ) );
    281 
    282 	$hmac = $algo( $opad . pack( $pack, $algo( $ipad . $data ) ) );
    283 
    284 	if ( $raw_output ) {
    285 		return pack( $pack, $hmac );
    286 	}
    287 	return $hmac;
    288 }
    289 
    290 if ( ! function_exists( 'hash_equals' ) ) :
    291 	/**
    292 	 * Timing attack safe string comparison
    293 	 *
    294 	 * Compares two strings using the same time whether they're equal or not.
    295 	 *
    296 	 * Note: It can leak the length of a string when arguments of differing length are supplied.
    297 	 *
    298 	 * This function was added in PHP 5.6.
    299 	 * However, the Hash extension may be explicitly disabled on select servers.
    300 	 * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no
    301 	 * longer be disabled.
    302 	 * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill
    303 	 * can be safely removed.
    304 	 *
    305 	 * @since 3.9.2
    306 	 *
    307 	 * @param string $a Expected string.
    308 	 * @param string $b Actual, user supplied, string.
    309 	 * @return bool Whether strings are equal.
    310 	 */
    311 	function hash_equals( $a, $b ) {
    312 		$a_length = strlen( $a );
    313 		if ( strlen( $b ) !== $a_length ) {
    314 			return false;
    315 		}
    316 		$result = 0;
    317 
    318 		// Do not attempt to "optimize" this.
    319 		for ( $i = 0; $i < $a_length; $i++ ) {
    320 			$result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] );
    321 		}
    322 
    323 		return 0 === $result;
    324 	}
    325 endif;
    326 
    327 // random_int() was introduced in PHP 7.0.
    328 if ( ! function_exists( 'random_int' ) ) {
    329 	require ABSPATH . WPINC . '/random_compat/random.php';
    330 }
    331 // sodium_crypto_box() was introduced in PHP 7.2.
    332 if ( ! function_exists( 'sodium_crypto_box' ) ) {
    333 	require ABSPATH . WPINC . '/sodium_compat/autoload.php';
    334 }
    335 
    336 if ( ! function_exists( 'is_countable' ) ) {
    337 	/**
    338 	 * Polyfill for is_countable() function added in PHP 7.3.
    339 	 *
    340 	 * Verify that the content of a variable is an array or an object
    341 	 * implementing the Countable interface.
    342 	 *
    343 	 * @since 4.9.6
    344 	 *
    345 	 * @param mixed $var The value to check.
    346 	 * @return bool True if `$var` is countable, false otherwise.
    347 	 */
    348 	function is_countable( $var ) {
    349 		return ( is_array( $var )
    350 			|| $var instanceof Countable
    351 			|| $var instanceof SimpleXMLElement
    352 			|| $var instanceof ResourceBundle
    353 		);
    354 	}
    355 }
    356 
    357 if ( ! function_exists( 'is_iterable' ) ) {
    358 	/**
    359 	 * Polyfill for is_iterable() function added in PHP 7.1.
    360 	 *
    361 	 * Verify that the content of a variable is an array or an object
    362 	 * implementing the Traversable interface.
    363 	 *
    364 	 * @since 4.9.6
    365 	 *
    366 	 * @param mixed $var The value to check.
    367 	 * @return bool True if `$var` is iterable, false otherwise.
    368 	 */
    369 	function is_iterable( $var ) {
    370 		return ( is_array( $var ) || $var instanceof Traversable );
    371 	}
    372 }
    373 
    374 // IMAGETYPE_WEBP constant is only defined in PHP 7.1 or later.
    375 if ( ! defined( 'IMAGETYPE_WEBP' ) ) {
    376 	define( 'IMAGETYPE_WEBP', 18 );
    377 }
    378 
    379 // IMG_WEBP constant is only defined in PHP 7.0.10 or later.
    380 if ( ! defined( 'IMG_WEBP' ) ) {
    381 	define( 'IMG_WEBP', IMAGETYPE_WEBP ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.imagetype_webpFound
    382 }