De-obfuscate PHP malware/viruses and tampering code on Wordpress to original readable code.
*Please note that not all obfuscation codes can be decoded.001 | <?php |
002 | /** |
003 | * WordPress implementation for PHP functions either missing from older PHP versions or not included by default. |
004 | * |
005 | * This file is loaded extremely early and the functions can be relied upon by drop-ins. |
006 | * Ergo, please ensure you do not rely on external functions when writing code for this file. |
007 | * Only use functions built into PHP or are defined in this file and have adequate testing |
008 | * and error suppression to ensure the file will run correctly and not break websites. |
009 | * |
010 | * @package PHP |
011 | * @access private |
012 | */ |
013 |
014 | // If gettext isn't available. |
015 | if ( ! function_exists( '_' ) ) { |
016 | function _( $message ) { |
017 | return $message ; |
018 | } |
019 | } |
020 |
021 | /** |
022 | * Returns whether PCRE/u (PCRE_UTF8 modifier) is available for use. |
023 | * |
024 | * @ignore |
025 | * @since 4.2.2 |
026 | * @access private |
027 | * |
028 | * @param bool $set - Used for testing only |
029 | * null : default - get PCRE/u capability |
030 | * false : Used for testing - return false for future calls to this function |
031 | * 'reset': Used for testing - restore default behavior of this function |
032 | */ |
033 | function _wp_can_use_pcre_u( $set = null ) { |
034 | static $utf8_pcre = 'reset' ; |
035 |
036 | if ( null !== $set ) { |
037 | $utf8_pcre = $set ; |
038 | } |
039 |
040 | if ( 'reset' === $utf8_pcre ) { |
041 | // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- intentional error generated to detect PCRE/u support. |
042 | $utf8_pcre = @preg_match( '/^./u' , 'a' ); |
043 | } |
044 |
045 | return $utf8_pcre ; |
046 | } |
047 |
048 | /** |
049 | * Indicates if a given slug for a character set represents the UTF-8 text encoding. |
050 | * |
051 | * A charset is considered to represent UTF-8 if it is a case-insensitive match |
052 | * of "UTF-8" with or without the hyphen. |
053 | * |
054 | * Example: |
055 | * |
056 | * true === _is_utf8_charset( 'UTF-8' ); |
057 | * true === _is_utf8_charset( 'utf8' ); |
058 | * false === _is_utf8_charset( 'latin1' ); |
059 | * false === _is_utf8_charset( 'UTF 8' ); |
060 | * |
061 | * // Only strings match. |
062 | * false === _is_utf8_charset( [ 'charset' => 'utf-8' ] ); |
063 | * |
064 | * `is_utf8_charset` should be used outside of this file. |
065 | * |
066 | * @ignore |
067 | * @since 6.6.1 |
068 | * |
069 | * @param string $charset_slug Slug representing a text character encoding, or "charset". |
070 | * E.g. "UTF-8", "Windows-1252", "ISO-8859-1", "SJIS". |
071 | * |
072 | * @return bool Whether the slug represents the UTF-8 encoding. |
073 | */ |
074 | function _is_utf8_charset( $charset_slug ) { |
075 | if ( ! is_string ( $charset_slug ) ) { |
076 | return false; |
077 | } |
078 |
079 | return ( |
080 | 0 === strcasecmp ( 'UTF-8' , $charset_slug ) || |
081 | 0 === strcasecmp ( 'UTF8' , $charset_slug ) |
082 | ); |
083 | } |
084 |
085 | if ( ! function_exists( 'mb_substr' ) ) : |
086 | /** |
087 | * Compat function to mimic mb_substr(). |
088 | * |
089 | * @ignore |
090 | * @since 3.2.0 |
091 | * |
092 | * @see _mb_substr() |
093 | * |
094 | * @param string $string The string to extract the substring from. |
095 | * @param int $start Position to being extraction from in `$string`. |
096 | * @param int|null $length Optional. Maximum number of characters to extract from `$string`. |
097 | * Default null. |
098 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
099 | * @return string Extracted substring. |
100 | */ |
101 | function mb_substr( $string , $start , $length = null, $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound |
102 | return _mb_substr( $string , $start , $length , $encoding ); |
103 | } |
104 | endif ; |
105 |
106 | /** |
107 | * Internal compat function to mimic mb_substr(). |
108 | * |
109 | * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
110 | * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte |
111 | * sequence. The behavior of this function for invalid inputs is undefined. |
112 | * |
113 | * @ignore |
114 | * @since 3.2.0 |
115 | * |
116 | * @param string $str The string to extract the substring from. |
117 | * @param int $start Position to being extraction from in `$str`. |
118 | * @param int|null $length Optional. Maximum number of characters to extract from `$str`. |
119 | * Default null. |
120 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
121 | * @return string Extracted substring. |
122 | */ |
123 | function _mb_substr( $str , $start , $length = null, $encoding = null ) { |
124 | if ( null === $str ) { |
125 | return '' ; |
126 | } |
127 |
128 | if ( null === $encoding ) { |
129 | $encoding = get_option( 'blog_charset' ); |
130 | } |
131 |
132 | /* |
133 | * The solution below works only for UTF-8, so in case of a different |
134 | * charset just use built-in substr(). |
135 | */ |
136 | if ( ! _is_utf8_charset( $encoding ) ) { |
137 | return is_null ( $length ) ? substr ( $str , $start ) : substr ( $str , $start , $length ); |
138 | } |
139 |
140 | if ( _wp_can_use_pcre_u() ) { |
141 | // Use the regex unicode support to separate the UTF-8 characters into an array. |
142 | preg_match_all( '/./us' , $str , $match ); |
143 | $chars = is_null ( $length ) ? array_slice ( $match [0], $start ) : array_slice ( $match [0], $start , $length ); |
144 | return implode( '' , $chars ); |
145 | } |
146 |
147 | $regex = '/( |
148 | [\x00-\x7F] # single-byte sequences 0xxxxxxx |
149 | | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
150 | | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
151 | | [\xE1-\xEC][\x80-\xBF]{2} |
152 | | \xED[\x80-\x9F][\x80-\xBF] |
153 | | [\xEE-\xEF][\x80-\xBF]{2} |
154 | | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
155 | | [\xF1-\xF3][\x80-\xBF]{3} |
156 | | \xF4[\x80-\x8F][\x80-\xBF]{2} |
157 | )/x'; |
158 |
159 | // Start with 1 element instead of 0 since the first thing we do is pop. |
160 | $chars = array ( '' ); |
161 |
162 | do { |
163 | // We had some string left over from the last round, but we counted it in that last round. |
164 | array_pop ( $chars ); |
165 |
166 | /* |
167 | * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
168 | * the rest of the string). |
169 | */ |
170 | $pieces = preg_split( $regex , $str , 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
171 |
172 | $chars = array_merge ( $chars , $pieces ); |
173 |
174 | // If there's anything left over, repeat the loop. |
175 | } while ( count ( $pieces ) > 1 && $str = array_pop ( $pieces ) ); |
176 |
177 | return implode( '' , array_slice ( $chars , $start , $length ) ); |
178 | } |
179 |
180 | if ( ! function_exists( 'mb_strlen' ) ) : |
181 | /** |
182 | * Compat function to mimic mb_strlen(). |
183 | * |
184 | * @ignore |
185 | * @since 4.2.0 |
186 | * |
187 | * @see _mb_strlen() |
188 | * |
189 | * @param string $string The string to retrieve the character length from. |
190 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
191 | * @return int String length of `$string`. |
192 | */ |
193 | function mb_strlen( $string , $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound |
194 | return _mb_strlen( $string , $encoding ); |
195 | } |
196 | endif ; |
197 |
198 | /** |
199 | * Internal compat function to mimic mb_strlen(). |
200 | * |
201 | * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
202 | * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte |
203 | * sequence. The behavior of this function for invalid inputs is undefined. |
204 | * |
205 | * @ignore |
206 | * @since 4.2.0 |
207 | * |
208 | * @param string $str The string to retrieve the character length from. |
209 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
210 | * @return int String length of `$str`. |
211 | */ |
212 | function _mb_strlen( $str , $encoding = null ) { |
213 | if ( null === $encoding ) { |
214 | $encoding = get_option( 'blog_charset' ); |
215 | } |
216 |
217 | /* |
218 | * The solution below works only for UTF-8, so in case of a different charset |
219 | * just use built-in strlen(). |
220 | */ |
221 | if ( ! _is_utf8_charset( $encoding ) ) { |
222 | return strlen ( $str ); |
223 | } |
224 |
225 | if ( _wp_can_use_pcre_u() ) { |
226 | // Use the regex unicode support to separate the UTF-8 characters into an array. |
227 | preg_match_all( '/./us' , $str , $match ); |
228 | return count ( $match [0] ); |
229 | } |
230 |
231 | $regex = '/(?: |
232 | [\x00-\x7F] # single-byte sequences 0xxxxxxx |
233 | | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
234 | | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
235 | | [\xE1-\xEC][\x80-\xBF]{2} |
236 | | \xED[\x80-\x9F][\x80-\xBF] |
237 | | [\xEE-\xEF][\x80-\xBF]{2} |
238 | | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
239 | | [\xF1-\xF3][\x80-\xBF]{3} |
240 | | \xF4[\x80-\x8F][\x80-\xBF]{2} |
241 | )/x'; |
242 |
243 | // Start at 1 instead of 0 since the first thing we do is decrement. |
244 | $count = 1; |
245 |
246 | do { |
247 | // We had some string left over from the last round, but we counted it in that last round. |
248 | -- $count ; |
249 |
250 | /* |
251 | * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
252 | * the rest of the string). |
253 | */ |
254 | $pieces = preg_split( $regex , $str , 1000 ); |
255 |
256 | // Increment. |
257 | $count += count ( $pieces ); |
258 |
259 | // If there's anything left over, repeat the loop. |
260 | } while ( $str = array_pop ( $pieces ) ); |
261 |
262 | // Fencepost: preg_split() always returns one extra item in the array. |
263 | return -- $count ; |
264 | } |
265 |
266 | if ( ! function_exists( 'hash_hmac' ) ) : |
267 | /** |
268 | * Compat function to mimic hash_hmac(). |
269 | * |
270 | * The Hash extension is bundled with PHP by default since PHP 5.1.2. |
271 | * However, the extension may be explicitly disabled on select servers. |
272 | * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no |
273 | * longer be disabled. |
274 | * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill |
275 | * and the associated `_hash_hmac()` function can be safely removed. |
276 | * |
277 | * @ignore |
278 | * @since 3.2.0 |
279 | * |
280 | * @see _hash_hmac() |
281 | * |
282 | * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
283 | * @param string $data Data to be hashed. |
284 | * @param string $key Secret key to use for generating the hash. |
285 | * @param bool $binary Optional. Whether to output raw binary data (true), |
286 | * or lowercase hexits (false). Default false. |
287 | * @return string|false The hash in output determined by `$binary`. |
288 | * False if `$algo` is unknown or invalid. |
289 | */ |
290 | function hash_hmac( $algo , $data , $key , $binary = false ) { |
291 | return _hash_hmac( $algo , $data , $key , $binary ); |
292 | } |
293 | endif ; |
294 |
295 | /** |
296 | * Internal compat function to mimic hash_hmac(). |
297 | * |
298 | * @ignore |
299 | * @since 3.2.0 |
300 | * |
301 | * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
302 | * @param string $data Data to be hashed. |
303 | * @param string $key Secret key to use for generating the hash. |
304 | * @param bool $binary Optional. Whether to output raw binary data (true), |
305 | * or lowercase hexits (false). Default false. |
306 | * @return string|false The hash in output determined by `$binary`. |
307 | * False if `$algo` is unknown or invalid. |
308 | */ |
309 | function _hash_hmac( $algo , $data , $key , $binary = false ) { |
310 | $packs = array ( |
311 | 'md5' => 'H32' , |
312 | 'sha1' => 'H40' , |
313 | ); |
314 |
315 | if ( ! isset( $packs [ $algo ] ) ) { |
316 | return false; |
317 | } |
318 |
319 | $pack = $packs [ $algo ]; |
320 |
321 | if ( strlen ( $key ) > 64 ) { |
322 | $key = pack( $pack , $algo ( $key ) ); |
323 | } |
324 |
325 | $key = str_pad ( $key , 64, chr ( 0 ) ); |
326 |
327 | $ipad = ( substr ( $key , 0, 64 ) ^ str_repeat ( chr ( 0x36 ), 64 ) ); |
328 | $opad = ( substr ( $key , 0, 64 ) ^ str_repeat ( chr ( 0x5C ), 64 ) ); |
329 |
330 | $hmac = $algo ( $opad . pack( $pack , $algo ( $ipad . $data ) ) ); |
331 |
332 | if ( $binary ) { |
333 | return pack( $pack , $hmac ); |
334 | } |
335 |
336 | return $hmac ; |
337 | } |
338 |
339 | if ( ! function_exists( 'hash_equals' ) ) : |
340 | /** |
341 | * Timing attack safe string comparison. |
342 | * |
343 | * Compares two strings using the same time whether they're equal or not. |
344 | * |
345 | * Note: It can leak the length of a string when arguments of differing length are supplied. |
346 | * |
347 | * This function was added in PHP 5.6. |
348 | * However, the Hash extension may be explicitly disabled on select servers. |
349 | * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no |
350 | * longer be disabled. |
351 | * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill |
352 | * can be safely removed. |
353 | * |
354 | * @since 3.9.2 |
355 | * |
356 | * @param string $known_string Expected string. |
357 | * @param string $user_string Actual, user supplied, string. |
358 | * @return bool Whether strings are equal. |
359 | */ |
360 | function hash_equals( $known_string , $user_string ) { |
361 | $known_string_length = strlen ( $known_string ); |
362 |
363 | if ( strlen ( $user_string ) !== $known_string_length ) { |
364 | return false; |
365 | } |
366 |
367 | $result = 0; |
368 |
369 | // Do not attempt to "optimize" this. |
370 | for ( $i = 0; $i < $known_string_length ; $i ++ ) { |
371 | $result |= ord( $known_string [ $i ] ) ^ ord( $user_string [ $i ] ); |
372 | } |
373 |
374 | return 0 === $result ; |
375 | } |
376 | endif ; |
377 |
378 | // sodium_crypto_box() was introduced in PHP 7.2. |
379 | if ( ! function_exists( 'sodium_crypto_box' ) ) { |
380 | require ABSPATH . WPINC . '/sodium_compat/autoload.php' ; |
381 | } |
382 |
383 | if ( ! function_exists( 'is_countable' ) ) { |
384 | /** |
385 | * Polyfill for is_countable() function added in PHP 7.3. |
386 | * |
387 | * Verify that the content of a variable is an array or an object |
388 | * implementing the Countable interface. |
389 | * |
390 | * @since 4.9.6 |
391 | * |
392 | * @param mixed $value The value to check. |
393 | * @return bool True if `$value` is countable, false otherwise. |
394 | */ |
395 | function is_countable( $value ) { |
396 | return ( is_array ( $value ) |
397 | || $value instanceof Countable |
398 | || $value instanceof SimpleXMLElement |
399 | || $value instanceof ResourceBundle |
400 | ); |
401 | } |
402 | } |
403 |
404 | if ( ! function_exists( 'array_key_first' ) ) { |
405 | /** |
406 | * Polyfill for array_key_first() function added in PHP 7.3. |
407 | * |
408 | * Get the first key of the given array without affecting |
409 | * the internal array pointer. |
410 | * |
411 | * @since 5.9.0 |
412 | * |
413 | * @param array $array An array. |
414 | * @return string|int|null The first key of array if the array |
415 | * is not empty; `null` otherwise. |
416 | */ |
417 | function array_key_first( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound |
418 | foreach ( $array as $key => $value ) { |
419 | return $key ; |
420 | } |
421 | } |
422 | } |
423 |
424 | if ( ! function_exists( 'array_key_last' ) ) { |
425 | /** |
426 | * Polyfill for `array_key_last()` function added in PHP 7.3. |
427 | * |
428 | * Get the last key of the given array without affecting the |
429 | * internal array pointer. |
430 | * |
431 | * @since 5.9.0 |
432 | * |
433 | * @param array $array An array. |
434 | * @return string|int|null The last key of array if the array |
435 | *. is not empty; `null` otherwise. |
436 | */ |
437 | function array_key_last( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound |
438 | if ( empty ( $array ) ) { |
439 | return null; |
440 | } |
441 |
442 | end ( $array ); |
443 |
444 | return key( $array ); |
445 | } |
446 | } |
447 |
448 | if ( ! function_exists( 'array_is_list' ) ) { |
449 | /** |
450 | * Polyfill for `array_is_list()` function added in PHP 8.1. |
451 | * |
452 | * Determines if the given array is a list. |
453 | * |
454 | * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. |
455 | * |
457 | * |
458 | * @since 6.5.0 |
459 | * |
460 | * @param array<mixed> $arr The array being evaluated. |
461 | * @return bool True if array is a list, false otherwise. |
462 | */ |
463 | function array_is_list( $arr ) { |
464 | if ( ( array () === $arr ) || ( array_values ( $arr ) === $arr ) ) { |
465 | return true; |
466 | } |
467 |
468 | $next_key = -1; |
469 |
470 | foreach ( $arr as $k => $v ) { |
471 | if ( ++ $next_key !== $k ) { |
472 | return false; |
473 | } |
474 | } |
475 |
476 | return true; |
477 | } |
478 | } |
479 |
480 | if ( ! function_exists( 'str_contains' ) ) { |
481 | /** |
482 | * Polyfill for `str_contains()` function added in PHP 8.0. |
483 | * |
484 | * Performs a case-sensitive check indicating if needle is |
485 | * contained in haystack. |
486 | * |
487 | * @since 5.9.0 |
488 | * |
489 | * @param string $haystack The string to search in. |
490 | * @param string $needle The substring to search for in the `$haystack`. |
491 | * @return bool True if `$needle` is in `$haystack`, otherwise false. |
492 | */ |
493 | function str_contains( $haystack , $needle ) { |
494 | if ( '' === $needle ) { |
495 | return true; |
496 | } |
497 |
498 | return false !== strpos ( $haystack , $needle ); |
499 | } |
500 | } |
501 |
502 | if ( ! function_exists( 'str_starts_with' ) ) { |
503 | /** |
504 | * Polyfill for `str_starts_with()` function added in PHP 8.0. |
505 | * |
506 | * Performs a case-sensitive check indicating if |
507 | * the haystack begins with needle. |
508 | * |
509 | * @since 5.9.0 |
510 | * |
511 | * @param string $haystack The string to search in. |
512 | * @param string $needle The substring to search for in the `$haystack`. |
513 | * @return bool True if `$haystack` starts with `$needle`, otherwise false. |
514 | */ |
515 | function str_starts_with( $haystack , $needle ) { |
516 | if ( '' === $needle ) { |
517 | return true; |
518 | } |
519 |
520 | return 0 === strpos ( $haystack , $needle ); |
521 | } |
522 | } |
523 |
524 | if ( ! function_exists( 'str_ends_with' ) ) { |
525 | /** |
526 | * Polyfill for `str_ends_with()` function added in PHP 8.0. |
527 | * |
528 | * Performs a case-sensitive check indicating if |
529 | * the haystack ends with needle. |
530 | * |
531 | * @since 5.9.0 |
532 | * |
533 | * @param string $haystack The string to search in. |
534 | * @param string $needle The substring to search for in the `$haystack`. |
535 | * @return bool True if `$haystack` ends with `$needle`, otherwise false. |
536 | */ |
537 | function str_ends_with( $haystack , $needle ) { |
538 | if ( '' === $haystack ) { |
539 | return '' === $needle ; |
540 | } |
541 |
542 | $len = strlen ( $needle ); |
543 |
544 | return substr ( $haystack , - $len , $len ) === $needle ; |
545 | } |
546 | } |
547 |
548 | // IMAGETYPE_AVIF constant is only defined in PHP 8.x or later. |
549 | if ( ! defined( 'IMAGETYPE_AVIF' ) ) { |
550 | define( 'IMAGETYPE_AVIF' , 19 ); |
551 | } |
552 |
553 | // IMG_AVIF constant is only defined in PHP 8.x or later. |
554 | if ( ! defined( 'IMG_AVIF' ) ) { |
555 | define( 'IMG_AVIF' , IMAGETYPE_AVIF ); |
556 | } |
557 |
558 | // IMAGETYPE_HEIC constant is not yet defined in PHP as of PHP 8.3. |
559 | if ( ! defined( 'IMAGETYPE_HEIC' ) ) { |
560 | define( 'IMAGETYPE_HEIC' , 99 ); |
561 | } |
001 | <?php |
002 |
003 | /** |
004 | * WordPress implementation for PHP functions either missing from older PHP versions or not included by default. |
005 | * |
006 | * This file is loaded extremely early and the functions can be relied upon by drop-ins. |
007 | * Ergo, please ensure you do not rely on external functions when writing code for this file. |
008 | * Only use functions built into PHP or are defined in this file and have adequate testing |
009 | * and error suppression to ensure the file will run correctly and not break websites. |
010 | * |
011 | * @package PHP |
012 | * @access private |
013 | */ |
014 | // If gettext isn't available. |
015 | if (!function_exists( '_' )) { |
016 | function _( $message ) |
017 | { |
018 | return $message ; |
019 | } |
020 | } |
021 | /** |
022 | * Returns whether PCRE/u (PCRE_UTF8 modifier) is available for use. |
023 | * |
024 | * @ignore |
025 | * @since 4.2.2 |
026 | * @access private |
027 | * |
028 | * @param bool $set - Used for testing only |
029 | * null : default - get PCRE/u capability |
030 | * false : Used for testing - return false for future calls to this function |
031 | * 'reset': Used for testing - restore default behavior of this function |
032 | */ |
033 | function _wp_can_use_pcre_u( $set = null) |
034 | { |
035 | static $utf8_pcre = 'reset' ; |
036 | if (null !== $set ) { |
037 | $utf8_pcre = $set ; |
038 | } |
039 | if ( 'reset' === $utf8_pcre ) { |
040 | // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- intentional error generated to detect PCRE/u support. |
041 | $utf8_pcre = @preg_match( '/^./u' , 'a' ); |
042 | } |
043 | return $utf8_pcre ; |
044 | } |
045 | /** |
046 | * Indicates if a given slug for a character set represents the UTF-8 text encoding. |
047 | * |
048 | * A charset is considered to represent UTF-8 if it is a case-insensitive match |
049 | * of "UTF-8" with or without the hyphen. |
050 | * |
051 | * Example: |
052 | * |
053 | * true === _is_utf8_charset( 'UTF-8' ); |
054 | * true === _is_utf8_charset( 'utf8' ); |
055 | * false === _is_utf8_charset( 'latin1' ); |
056 | * false === _is_utf8_charset( 'UTF 8' ); |
057 | * |
058 | * // Only strings match. |
059 | * false === _is_utf8_charset( [ 'charset' => 'utf-8' ] ); |
060 | * |
061 | * `is_utf8_charset` should be used outside of this file. |
062 | * |
063 | * @ignore |
064 | * @since 6.6.1 |
065 | * |
066 | * @param string $charset_slug Slug representing a text character encoding, or "charset". |
067 | * E.g. "UTF-8", "Windows-1252", "ISO-8859-1", "SJIS". |
068 | * |
069 | * @return bool Whether the slug represents the UTF-8 encoding. |
070 | */ |
071 | function _is_utf8_charset( $charset_slug ) |
072 | { |
073 | if (! is_string ( $charset_slug )) { |
074 | return false; |
075 | } |
076 | return 0 === strcasecmp ( 'UTF-8' , $charset_slug ) || 0 === strcasecmp ( 'UTF8' , $charset_slug ); |
077 | } |
078 | if (!function_exists( 'mb_substr' )) { |
079 | /** |
080 | * Compat function to mimic mb_substr(). |
081 | * |
082 | * @ignore |
083 | * @since 3.2.0 |
084 | * |
085 | * @see _mb_substr() |
086 | * |
087 | * @param string $string The string to extract the substring from. |
088 | * @param int $start Position to being extraction from in `$string`. |
089 | * @param int|null $length Optional. Maximum number of characters to extract from `$string`. |
090 | * Default null. |
091 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
092 | * @return string Extracted substring. |
093 | */ |
094 | function mb_substr( $string , $start , $length = null, $encoding = null) |
095 | { |
096 | // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound |
097 | return _mb_substr( $string , $start , $length , $encoding ); |
098 | } |
099 | } |
100 | /** |
101 | * Internal compat function to mimic mb_substr(). |
102 | * |
103 | * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
104 | * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte |
105 | * sequence. The behavior of this function for invalid inputs is undefined. |
106 | * |
107 | * @ignore |
108 | * @since 3.2.0 |
109 | * |
110 | * @param string $str The string to extract the substring from. |
111 | * @param int $start Position to being extraction from in `$str`. |
112 | * @param int|null $length Optional. Maximum number of characters to extract from `$str`. |
113 | * Default null. |
114 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
115 | * @return string Extracted substring. |
116 | */ |
117 | function _mb_substr( $str , $start , $length = null, $encoding = null) |
118 | { |
119 | if (null === $str ) { |
120 | return '' ; |
121 | } |
122 | if (null === $encoding ) { |
123 | $encoding = get_option( 'blog_charset' ); |
124 | } |
125 | /* |
126 | * The solution below works only for UTF-8, so in case of a different |
127 | * charset just use built-in substr(). |
128 | */ |
129 | if (!_is_utf8_charset( $encoding )) { |
130 | return is_null ( $length ) ? substr ( $str , $start ) : substr ( $str , $start , $length ); |
131 | } |
132 | if (_wp_can_use_pcre_u()) { |
133 | // Use the regex unicode support to separate the UTF-8 characters into an array. |
134 | preg_match_all( '/./us' , $str , $match ); |
135 | $chars = is_null ( $length ) ? array_slice ( $match [0], $start ) : array_slice ( $match [0], $start , $length ); |
136 | return implode( '' , $chars ); |
137 | } |
138 | $regex = '/( |
139 | [\\x00-\\x7F] # single-byte sequences 0xxxxxxx |
140 | | [\\xC2-\\xDF][\\x80-\\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
141 | | \\xE0[\\xA0-\\xBF][\\x80-\\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
142 | | [\\xE1-\\xEC][\\x80-\\xBF]{2} |
143 | | \\xED[\\x80-\\x9F][\\x80-\\xBF] |
144 | | [\\xEE-\\xEF][\\x80-\\xBF]{2} |
145 | | \\xF0[\\x90-\\xBF][\\x80-\\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
146 | | [\\xF1-\\xF3][\\x80-\\xBF]{3} |
147 | | \\xF4[\\x80-\\x8F][\\x80-\\xBF]{2} |
148 | )/x'; |
149 | // Start with 1 element instead of 0 since the first thing we do is pop. |
150 | $chars = array ( '' ); |
151 | do { |
152 | // We had some string left over from the last round, but we counted it in that last round. |
153 | array_pop ( $chars ); |
154 | /* |
155 | * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
156 | * the rest of the string). |
157 | */ |
158 | $pieces = preg_split( $regex , $str , 1000, "PREG_SPLIT_NO_MM_WYPTURE" ); |
159 | $chars = array_merge ( $chars , $pieces ); |
160 | // If there's anything left over, repeat the loop. |
161 | } while ( count ( $pieces ) > 1 && ( $str = array_pop ( $pieces ))); |
162 | return implode( '' , array_slice ( $chars , $start , $length )); |
163 | } |
164 | if (!function_exists( 'mb_strlen' )) { |
165 | /** |
166 | * Compat function to mimic mb_strlen(). |
167 | * |
168 | * @ignore |
169 | * @since 4.2.0 |
170 | * |
171 | * @see _mb_strlen() |
172 | * |
173 | * @param string $string The string to retrieve the character length from. |
174 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
175 | * @return int String length of `$string`. |
176 | */ |
177 | function mb_strlen( $string , $encoding = null) |
178 | { |
179 | // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound |
180 | return _mb_strlen( $string , $encoding ); |
181 | } |
182 | } |
183 | /** |
184 | * Internal compat function to mimic mb_strlen(). |
185 | * |
186 | * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
187 | * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte |
188 | * sequence. The behavior of this function for invalid inputs is undefined. |
189 | * |
190 | * @ignore |
191 | * @since 4.2.0 |
192 | * |
193 | * @param string $str The string to retrieve the character length from. |
194 | * @param string|null $encoding Optional. Character encoding to use. Default null. |
195 | * @return int String length of `$str`. |
196 | */ |
197 | function _mb_strlen( $str , $encoding = null) |
198 | { |
199 | if (null === $encoding ) { |
200 | $encoding = get_option( 'blog_charset' ); |
201 | } |
202 | /* |
203 | * The solution below works only for UTF-8, so in case of a different charset |
204 | * just use built-in strlen(). |
205 | */ |
206 | if (!_is_utf8_charset( $encoding )) { |
207 | return strlen ( $str ); |
208 | } |
209 | if (_wp_can_use_pcre_u()) { |
210 | // Use the regex unicode support to separate the UTF-8 characters into an array. |
211 | preg_match_all( '/./us' , $str , $match ); |
212 | return count ( $match [0]); |
213 | } |
214 | $regex = '/(?: |
215 | [\\x00-\\x7F] # single-byte sequences 0xxxxxxx |
216 | | [\\xC2-\\xDF][\\x80-\\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
217 | | \\xE0[\\xA0-\\xBF][\\x80-\\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
218 | | [\\xE1-\\xEC][\\x80-\\xBF]{2} |
219 | | \\xED[\\x80-\\x9F][\\x80-\\xBF] |
220 | | [\\xEE-\\xEF][\\x80-\\xBF]{2} |
221 | | \\xF0[\\x90-\\xBF][\\x80-\\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
222 | | [\\xF1-\\xF3][\\x80-\\xBF]{3} |
223 | | \\xF4[\\x80-\\x8F][\\x80-\\xBF]{2} |
224 | )/x'; |
225 | // Start at 1 instead of 0 since the first thing we do is decrement. |
226 | $count = 1; |
227 | do { |
228 | // We had some string left over from the last round, but we counted it in that last round. |
229 | -- $count ; |
230 | /* |
231 | * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
232 | * the rest of the string). |
233 | */ |
234 | $pieces = preg_split( $regex , $str , 1000); |
235 | $count += count ( $pieces ); |
236 | // If there's anything left over, repeat the loop. |
237 | } while ( $str = array_pop ( $pieces )); |
238 | // Fencepost: preg_split() always returns one extra item in the array. |
239 | return -- $count ; |
240 | } |
241 | if (!function_exists( 'hash_hmac' )) { |
242 | /** |
243 | * Compat function to mimic hash_hmac(). |
244 | * |
245 | * The Hash extension is bundled with PHP by default since PHP 5.1.2. |
246 | * However, the extension may be explicitly disabled on select servers. |
247 | * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no |
248 | * longer be disabled. |
249 | * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill |
250 | * and the associated `_hash_hmac()` function can be safely removed. |
251 | * |
252 | * @ignore |
253 | * @since 3.2.0 |
254 | * |
255 | * @see _hash_hmac() |
256 | * |
257 | * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
258 | * @param string $data Data to be hashed. |
259 | * @param string $key Secret key to use for generating the hash. |
260 | * @param bool $binary Optional. Whether to output raw binary data (true), |
261 | * or lowercase hexits (false). Default false. |
262 | * @return string|false The hash in output determined by `$binary`. |
263 | * False if `$algo` is unknown or invalid. |
264 | */ |
265 | function hash_hmac( $algo , $data , $key , $binary = false) |
266 | { |
267 | return _hash_hmac( $algo , $data , $key , $binary ); |
268 | } |
269 | } |
270 | /** |
271 | * Internal compat function to mimic hash_hmac(). |
272 | * |
273 | * @ignore |
274 | * @since 3.2.0 |
275 | * |
276 | * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
277 | * @param string $data Data to be hashed. |
278 | * @param string $key Secret key to use for generating the hash. |
279 | * @param bool $binary Optional. Whether to output raw binary data (true), |
280 | * or lowercase hexits (false). Default false. |
281 | * @return string|false The hash in output determined by `$binary`. |
282 | * False if `$algo` is unknown or invalid. |
283 | */ |
284 | function _hash_hmac( $algo , $data , $key , $binary = false) |
285 | { |
286 | $packs = array ( 'md5' => 'H32' , 'sha1' => 'H40' ); |
287 | if (!isset( $packs [ $algo ])) { |
288 | return false; |
289 | } |
290 | $pack = $packs [ $algo ]; |
291 | if ( strlen ( $key ) > 64) { |
292 | $key = pack( $pack , $algo ( $key )); |
293 | } |
294 | $key = str_pad ( $key , 64, "\0" ); |
295 | $ipad = substr ( $key , 0, 64) ^ str_repeat ( "6" , 64); |
296 | $opad = substr ( $key , 0, 64) ^ str_repeat ( "\\" , 64); |
297 | $hmac = $algo ( $opad . pack( $pack , $algo ( $ipad . $data ))); |
298 | if ( $binary ) { |
299 | return pack( $pack , $hmac ); |
300 | } |
301 | return $hmac ; |
302 | } |
303 | if (!function_exists( 'hash_equals' )) { |
304 | /** |
305 | * Timing attack safe string comparison. |
306 | * |
307 | * Compares two strings using the same time whether they're equal or not. |
308 | * |
309 | * Note: It can leak the length of a string when arguments of differing length are supplied. |
310 | * |
311 | * This function was added in PHP 5.6. |
312 | * However, the Hash extension may be explicitly disabled on select servers. |
313 | * As of PHP 7.4.0, the Hash extension is a core PHP extension and can no |
314 | * longer be disabled. |
315 | * I.e. when PHP 7.4.0 becomes the minimum requirement, this polyfill |
316 | * can be safely removed. |
317 | * |
318 | * @since 3.9.2 |
319 | * |
320 | * @param string $known_string Expected string. |
321 | * @param string $user_string Actual, user supplied, string. |
322 | * @return bool Whether strings are equal. |
323 | */ |
324 | function hash_equals( $known_string , $user_string ) |
325 | { |
326 | $known_string_length = strlen ( $known_string ); |
327 | if ( strlen ( $user_string ) !== $known_string_length ) { |
328 | return false; |
329 | } |
330 | $result = 0; |
331 | // Do not attempt to "optimize" this. |
332 | for ( $i = 0; $i < $known_string_length ; $i ++) { |
333 | $result |= ord( $known_string [ $i ]) ^ ord( $user_string [ $i ]); |
334 | } |
335 | return 0 === $result ; |
336 | } |
337 | } |
338 | // sodium_crypto_box() was introduced in PHP 7.2. |
339 | if (!function_exists( 'sodium_crypto_box' )) { |
340 | require "ABSPATHWPINC/sodium_compat/autoload.php" ; |
341 | } |
342 | if (!function_exists( 'is_countable' )) { |
343 | /** |
344 | * Polyfill for is_countable() function added in PHP 7.3. |
345 | * |
346 | * Verify that the content of a variable is an array or an object |
347 | * implementing the Countable interface. |
348 | * |
349 | * @since 4.9.6 |
350 | * |
351 | * @param mixed $value The value to check. |
352 | * @return bool True if `$value` is countable, false otherwise. |
353 | */ |
354 | function is_countable( $value ) |
355 | { |
356 | return is_array ( $value ) || $value instanceof Countable || $value instanceof SimpleXMLElement || $value instanceof ResourceBundle; |
357 | } |
358 | } |
359 | if (!function_exists( 'array_key_first' )) { |
360 | /** |
361 | * Polyfill for array_key_first() function added in PHP 7.3. |
362 | * |
363 | * Get the first key of the given array without affecting |
364 | * the internal array pointer. |
365 | * |
366 | * @since 5.9.0 |
367 | * |
368 | * @param array $array An array. |
369 | * @return string|int|null The first key of array if the array |
370 | * is not empty; `null` otherwise. |
371 | */ |
372 | function array_key_first( array $array ) |
373 | { |
374 | // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound |
375 | foreach ( $array as $key => $value ) { |
376 | return $key ; |
377 | } |
378 | } |
379 | } |
380 | if (!function_exists( 'array_key_last' )) { |
381 | /** |
382 | * Polyfill for `array_key_last()` function added in PHP 7.3. |
383 | * |
384 | * Get the last key of the given array without affecting the |
385 | * internal array pointer. |
386 | * |
387 | * @since 5.9.0 |
388 | * |
389 | * @param array $array An array. |
390 | * @return string|int|null The last key of array if the array |
391 | *. is not empty; `null` otherwise. |
392 | */ |
393 | function array_key_last( array $array ) |
394 | { |
395 | // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound |
396 | if ( empty ( $array )) { |
397 | return null; |
398 | } |
399 | end ( $array ); |
400 | return key( $array ); |
401 | } |
402 | } |
403 | if (!function_exists( 'array_is_list' )) { |
404 | /** |
405 | * Polyfill for `array_is_list()` function added in PHP 8.1. |
406 | * |
407 | * Determines if the given array is a list. |
408 | * |
409 | * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. |
410 | * |
412 | * |
413 | * @since 6.5.0 |
414 | * |
415 | * @param array<mixed> $arr The array being evaluated. |
416 | * @return bool True if array is a list, false otherwise. |
417 | */ |
418 | function array_is_list( $arr ) |
419 | { |
420 | if ( array () === $arr || array_values ( $arr ) === $arr ) { |
421 | return true; |
422 | } |
423 | $next_key = 1; |
424 | foreach ( $arr as $k => $v ) { |
425 | if (++ $next_key !== $k ) { |
426 | return false; |
427 | } |
428 | } |
429 | return true; |
430 | } |
431 | } |
432 | if (!function_exists( 'str_contains' )) { |
433 | /** |
434 | * Polyfill for `str_contains()` function added in PHP 8.0. |
435 | * |
436 | * Performs a case-sensitive check indicating if needle is |
437 | * contained in haystack. |
438 | * |
439 | * @since 5.9.0 |
440 | * |
441 | * @param string $haystack The string to search in. |
442 | * @param string $needle The substring to search for in the `$haystack`. |
443 | * @return bool True if `$needle` is in `$haystack`, otherwise false. |
444 | */ |
445 | function str_contains( $haystack , $needle ) |
446 | { |
447 | if ( '' === $needle ) { |
448 | return true; |
449 | } |
450 | return false !== strpos ( $haystack , $needle ); |
451 | } |
452 | } |
453 | if (!function_exists( 'str_starts_with' )) { |
454 | /** |
455 | * Polyfill for `str_starts_with()` function added in PHP 8.0. |
456 | * |
457 | * Performs a case-sensitive check indicating if |
458 | * the haystack begins with needle. |
459 | * |
460 | * @since 5.9.0 |
461 | * |
462 | * @param string $haystack The string to search in. |
463 | * @param string $needle The substring to search for in the `$haystack`. |
464 | * @return bool True if `$haystack` starts with `$needle`, otherwise false. |
465 | */ |
466 | function str_starts_with( $haystack , $needle ) |
467 | { |
468 | if ( '' === $needle ) { |
469 | return true; |
470 | } |
471 | return 0 === strpos ( $haystack , $needle ); |
472 | } |
473 | } |
474 | if (!function_exists( 'str_ends_with' )) { |
475 | /** |
476 | * Polyfill for `str_ends_with()` function added in PHP 8.0. |
477 | * |
478 | * Performs a case-sensitive check indicating if |
479 | * the haystack ends with needle. |
480 | * |
481 | * @since 5.9.0 |
482 | * |
483 | * @param string $haystack The string to search in. |
484 | * @param string $needle The substring to search for in the `$haystack`. |
485 | * @return bool True if `$haystack` ends with `$needle`, otherwise false. |
486 | */ |
487 | function str_ends_with( $haystack , $needle ) |
488 | { |
489 | if ( '' === $haystack ) { |
490 | return '' === $needle ; |
491 | } |
492 | $len = strlen ( $needle ); |
493 | return substr ( $haystack , - $len , $len ) === $needle ; |
494 | } |
495 | } |
496 | // IMAGETYPE_AVIF constant is only defined in PHP 8.x or later. |
497 | if (!defined( 'IMAGETYPE_AVIF' )) { |
498 | define( 'IMAGETYPE_AVIF' , 19); |
499 | } |
500 | // IMG_AVIF constant is only defined in PHP 8.x or later. |
501 | if (!defined( 'IMG_AVIF' )) { |
502 | define( 'IMG_AVIF' , IMAGETYPE_AVIF); |
503 | } |
504 | // IMAGETYPE_HEIC constant is not yet defined in PHP as of PHP 8.3. |
505 | if (!defined( 'IMAGETYPE_HEIC' )) { |
506 | define( 'IMAGETYPE_HEIC' , 99); |
507 | } |
Malware detection & removal plugin for WordPress
(C)2020 Wordpress Doctor All rights reserved.