38 |
40 |
39 return $utf8_pcre; |
41 return $utf8_pcre; |
40 } |
42 } |
41 |
43 |
42 if ( ! function_exists( 'mb_substr' ) ) : |
44 if ( ! function_exists( 'mb_substr' ) ) : |
|
45 /** |
|
46 * Compat function to mimic mb_substr(). |
|
47 * |
|
48 * @ignore |
|
49 * @since 3.2.0 |
|
50 * |
|
51 * @see _mb_substr() |
|
52 * |
|
53 * @param string $str The string to extract the substring from. |
|
54 * @param int $start Position to being extraction from in `$str`. |
|
55 * @param int|null $length Optional. Maximum number of characters to extract from `$str`. |
|
56 * Default null. |
|
57 * @param string|null $encoding Optional. Character encoding to use. Default null. |
|
58 * @return string Extracted substring. |
|
59 */ |
43 function mb_substr( $str, $start, $length = null, $encoding = null ) { |
60 function mb_substr( $str, $start, $length = null, $encoding = null ) { |
44 return _mb_substr( $str, $start, $length, $encoding ); |
61 return _mb_substr( $str, $start, $length, $encoding ); |
45 } |
62 } |
46 endif; |
63 endif; |
47 |
64 |
48 /* |
65 /** |
|
66 * Internal compat function to mimic mb_substr(). |
|
67 * |
49 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
68 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
50 * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence. |
69 * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence. |
51 * The behavior of this function for invalid inputs is undefined. |
70 * The behavior of this function for invalid inputs is undefined. |
|
71 * |
|
72 * @ignore |
|
73 * @since 3.2.0 |
|
74 * |
|
75 * @param string $str The string to extract the substring from. |
|
76 * @param int $start Position to being extraction from in `$str`. |
|
77 * @param int|null $length Optional. Maximum number of characters to extract from `$str`. |
|
78 * Default null. |
|
79 * @param string|null $encoding Optional. Character encoding to use. Default null. |
|
80 * @return string Extracted substring. |
52 */ |
81 */ |
53 function _mb_substr( $str, $start, $length = null, $encoding = null ) { |
82 function _mb_substr( $str, $start, $length = null, $encoding = null ) { |
54 if ( null === $encoding ) { |
83 if ( null === $encoding ) { |
55 $encoding = get_option( 'blog_charset' ); |
84 $encoding = get_option( 'blog_charset' ); |
56 } |
85 } |
57 |
86 |
58 // The solution below works only for UTF-8, |
87 /* |
59 // so in case of a different charset just use built-in substr() |
88 * The solution below works only for UTF-8, so in case of a different |
|
89 * charset just use built-in substr(). |
|
90 */ |
60 if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
91 if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
61 return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length ); |
92 return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length ); |
62 } |
93 } |
63 |
94 |
64 if ( _wp_can_use_pcre_u() ) { |
95 if ( _wp_can_use_pcre_u() ) { |
65 // Use the regex unicode support to separate the UTF-8 characters into an array |
96 // Use the regex unicode support to separate the UTF-8 characters into an array. |
66 preg_match_all( '/./us', $str, $match ); |
97 preg_match_all( '/./us', $str, $match ); |
67 $chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length ); |
98 $chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length ); |
68 return implode( '', $chars ); |
99 return implode( '', $chars ); |
69 } |
100 } |
70 |
101 |
78 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
109 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
79 | [\xF1-\xF3][\x80-\xBF]{3} |
110 | [\xF1-\xF3][\x80-\xBF]{3} |
80 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
111 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
81 )/x'; |
112 )/x'; |
82 |
113 |
83 $chars = array( '' ); // Start with 1 element instead of 0 since the first thing we do is pop |
114 // Start with 1 element instead of 0 since the first thing we do is pop. |
|
115 $chars = array( '' ); |
84 do { |
116 do { |
85 // We had some string left over from the last round, but we counted it in that last round. |
117 // We had some string left over from the last round, but we counted it in that last round. |
86 array_pop( $chars ); |
118 array_pop( $chars ); |
87 |
119 |
88 // Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string) |
120 /* |
|
121 * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
|
122 * the rest of the string). |
|
123 */ |
89 $pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
124 $pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
90 |
125 |
91 $chars = array_merge( $chars, $pieces ); |
126 $chars = array_merge( $chars, $pieces ); |
92 } while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop. |
127 |
|
128 // If there's anything left over, repeat the loop. |
|
129 } while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) ); |
93 |
130 |
94 return join( '', array_slice( $chars, $start, $length ) ); |
131 return join( '', array_slice( $chars, $start, $length ) ); |
95 } |
132 } |
96 |
133 |
97 if ( ! function_exists( 'mb_strlen' ) ) : |
134 if ( ! function_exists( 'mb_strlen' ) ) : |
|
135 /** |
|
136 * Compat function to mimic mb_strlen(). |
|
137 * |
|
138 * @ignore |
|
139 * @since 4.2.0 |
|
140 * |
|
141 * @see _mb_strlen() |
|
142 * |
|
143 * @param string $str The string to retrieve the character length from. |
|
144 * @param string|null $encoding Optional. Character encoding to use. Default null. |
|
145 * @return int String length of `$str`. |
|
146 */ |
98 function mb_strlen( $str, $encoding = null ) { |
147 function mb_strlen( $str, $encoding = null ) { |
99 return _mb_strlen( $str, $encoding ); |
148 return _mb_strlen( $str, $encoding ); |
100 } |
149 } |
101 endif; |
150 endif; |
102 |
151 |
103 /* |
152 /** |
|
153 * Internal compat function to mimic mb_strlen(). |
|
154 * |
104 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
155 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
105 * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence. |
156 * For $encoding === UTF-8, the `$str` input is expected to be a valid UTF-8 byte |
106 * The behavior of this function for invalid inputs is undefined. |
157 * sequence. The behavior of this function for invalid inputs is undefined. |
|
158 * |
|
159 * @ignore |
|
160 * @since 4.2.0 |
|
161 * |
|
162 * @param string $str The string to retrieve the character length from. |
|
163 * @param string|null $encoding Optional. Character encoding to use. Default null. |
|
164 * @return int String length of `$str`. |
107 */ |
165 */ |
108 function _mb_strlen( $str, $encoding = null ) { |
166 function _mb_strlen( $str, $encoding = null ) { |
109 if ( null === $encoding ) { |
167 if ( null === $encoding ) { |
110 $encoding = get_option( 'blog_charset' ); |
168 $encoding = get_option( 'blog_charset' ); |
111 } |
169 } |
112 |
170 |
113 // The solution below works only for UTF-8, |
171 /* |
114 // so in case of a different charset just use built-in strlen() |
172 * The solution below works only for UTF-8, so in case of a different charset |
|
173 * just use built-in strlen(). |
|
174 */ |
115 if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
175 if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
116 return strlen( $str ); |
176 return strlen( $str ); |
117 } |
177 } |
118 |
178 |
119 if ( _wp_can_use_pcre_u() ) { |
179 if ( _wp_can_use_pcre_u() ) { |
120 // Use the regex unicode support to separate the UTF-8 characters into an array |
180 // Use the regex unicode support to separate the UTF-8 characters into an array. |
121 preg_match_all( '/./us', $str, $match ); |
181 preg_match_all( '/./us', $str, $match ); |
122 return count( $match[0] ); |
182 return count( $match[0] ); |
123 } |
183 } |
124 |
184 |
125 $regex = '/(?: |
185 $regex = '/(?: |
132 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
192 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
133 | [\xF1-\xF3][\x80-\xBF]{3} |
193 | [\xF1-\xF3][\x80-\xBF]{3} |
134 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
194 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
135 )/x'; |
195 )/x'; |
136 |
196 |
137 $count = 1; // Start at 1 instead of 0 since the first thing we do is decrement |
197 // Start at 1 instead of 0 since the first thing we do is decrement. |
|
198 $count = 1; |
138 do { |
199 do { |
139 // We had some string left over from the last round, but we counted it in that last round. |
200 // We had some string left over from the last round, but we counted it in that last round. |
140 $count--; |
201 $count--; |
141 |
202 |
142 // Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string) |
203 /* |
|
204 * Split by UTF-8 character, limit to 1000 characters (last array element will contain |
|
205 * the rest of the string). |
|
206 */ |
143 $pieces = preg_split( $regex, $str, 1000 ); |
207 $pieces = preg_split( $regex, $str, 1000 ); |
144 |
208 |
145 // Increment |
209 // Increment. |
146 $count += count( $pieces ); |
210 $count += count( $pieces ); |
147 } while ( $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop. |
211 |
148 |
212 // If there's anything left over, repeat the loop. |
149 // Fencepost: preg_split() always returns one extra item in the array |
213 } while ( $str = array_pop( $pieces ) ); |
|
214 |
|
215 // Fencepost: preg_split() always returns one extra item in the array. |
150 return --$count; |
216 return --$count; |
151 } |
217 } |
152 |
218 |
153 if ( !function_exists('hash_hmac') ): |
219 if ( !function_exists('hash_hmac') ): |
|
220 /** |
|
221 * Compat function to mimic hash_hmac(). |
|
222 * |
|
223 * @ignore |
|
224 * @since 3.2.0 |
|
225 * |
|
226 * @see _hash_hmac() |
|
227 * |
|
228 * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
|
229 * @param string $data Data to be hashed. |
|
230 * @param string $key Secret key to use for generating the hash. |
|
231 * @param bool $raw_output Optional. Whether to output raw binary data (true), |
|
232 * or lowercase hexits (false). Default false. |
|
233 * @return string|false The hash in output determined by `$raw_output`. False if `$algo` |
|
234 * is unknown or invalid. |
|
235 */ |
154 function hash_hmac($algo, $data, $key, $raw_output = false) { |
236 function hash_hmac($algo, $data, $key, $raw_output = false) { |
155 return _hash_hmac($algo, $data, $key, $raw_output); |
237 return _hash_hmac($algo, $data, $key, $raw_output); |
156 } |
238 } |
157 endif; |
239 endif; |
158 |
240 |
|
241 /** |
|
242 * Internal compat function to mimic hash_hmac(). |
|
243 * |
|
244 * @ignore |
|
245 * @since 3.2.0 |
|
246 * |
|
247 * @param string $algo Hash algorithm. Accepts 'md5' or 'sha1'. |
|
248 * @param string $data Data to be hashed. |
|
249 * @param string $key Secret key to use for generating the hash. |
|
250 * @param bool $raw_output Optional. Whether to output raw binary data (true), |
|
251 * or lowercase hexits (false). Default false. |
|
252 * @return string|false The hash in output determined by `$raw_output`. False if `$algo` |
|
253 * is unknown or invalid. |
|
254 */ |
159 function _hash_hmac($algo, $data, $key, $raw_output = false) { |
255 function _hash_hmac($algo, $data, $key, $raw_output = false) { |
160 $packs = array('md5' => 'H32', 'sha1' => 'H40'); |
256 $packs = array('md5' => 'H32', 'sha1' => 'H40'); |
161 |
257 |
162 if ( !isset($packs[$algo]) ) |
258 if ( !isset($packs[$algo]) ) |
163 return false; |
259 return false; |
204 $res = $wp_json->decode( $string ); |
306 $res = $wp_json->decode( $string ); |
205 if ( $assoc_array ) |
307 if ( $assoc_array ) |
206 $res = _json_decode_object_helper( $res ); |
308 $res = _json_decode_object_helper( $res ); |
207 return $res; |
309 return $res; |
208 } |
310 } |
|
311 |
|
312 /** |
|
313 * @param object $data |
|
314 * @return array |
|
315 */ |
209 function _json_decode_object_helper($data) { |
316 function _json_decode_object_helper($data) { |
210 if ( is_object($data) ) |
317 if ( is_object($data) ) |
211 $data = get_object_vars($data); |
318 $data = get_object_vars($data); |
212 return is_array($data) ? array_map(__FUNCTION__, $data) : $data; |
319 return is_array($data) ? array_map(__FUNCTION__, $data) : $data; |
213 } |
320 } |
214 } |
321 } |
215 |
322 |
216 if ( ! function_exists( 'hash_equals' ) ) : |
323 if ( ! function_exists( 'hash_equals' ) ) : |
217 /** |
324 /** |
218 * Compare two strings in constant time. |
325 * Timing attack safe string comparison |
|
326 * |
|
327 * Compares two strings using the same time whether they're equal or not. |
219 * |
328 * |
220 * This function was added in PHP 5.6. |
329 * This function was added in PHP 5.6. |
221 * It can leak the length of a string. |
330 * |
|
331 * Note: It can leak the length of a string when arguments of differing length are supplied. |
222 * |
332 * |
223 * @since 3.9.2 |
333 * @since 3.9.2 |
224 * |
334 * |
225 * @param string $a Expected string. |
335 * @param string $a Expected string. |
226 * @param string $b Actual string. |
336 * @param string $b Actual, user supplied, string. |
227 * @return bool Whether strings are equal. |
337 * @return bool Whether strings are equal. |
228 */ |
338 */ |
229 function hash_equals( $a, $b ) { |
339 function hash_equals( $a, $b ) { |
230 $a_length = strlen( $a ); |
340 $a_length = strlen( $a ); |
231 if ( $a_length !== strlen( $b ) ) { |
341 if ( $a_length !== strlen( $b ) ) { |
245 // JSON_PRETTY_PRINT was introduced in PHP 5.4 |
355 // JSON_PRETTY_PRINT was introduced in PHP 5.4 |
246 // Defined here to prevent a notice when using it with wp_json_encode() |
356 // Defined here to prevent a notice when using it with wp_json_encode() |
247 if ( ! defined( 'JSON_PRETTY_PRINT' ) ) { |
357 if ( ! defined( 'JSON_PRETTY_PRINT' ) ) { |
248 define( 'JSON_PRETTY_PRINT', 128 ); |
358 define( 'JSON_PRETTY_PRINT', 128 ); |
249 } |
359 } |
|
360 |
|
361 if ( ! function_exists( 'json_last_error_msg' ) ) : |
|
362 /** |
|
363 * Retrieves the error string of the last json_encode() or json_decode() call. |
|
364 * |
|
365 * @since 4.4.0 |
|
366 * |
|
367 * @internal This is a compatibility function for PHP <5.5 |
|
368 * |
|
369 * @return bool|string Returns the error message on success, "No Error" if no error has occurred, |
|
370 * or false on failure. |
|
371 */ |
|
372 function json_last_error_msg() { |
|
373 // See https://core.trac.wordpress.org/ticket/27799. |
|
374 if ( ! function_exists( 'json_last_error' ) ) { |
|
375 return false; |
|
376 } |
|
377 |
|
378 $last_error_code = json_last_error(); |
|
379 |
|
380 // Just in case JSON_ERROR_NONE is not defined. |
|
381 $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; |
|
382 |
|
383 switch ( true ) { |
|
384 case $last_error_code === $error_code_none: |
|
385 return 'No error'; |
|
386 |
|
387 case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code: |
|
388 return 'Maximum stack depth exceeded'; |
|
389 |
|
390 case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code: |
|
391 return 'State mismatch (invalid or malformed JSON)'; |
|
392 |
|
393 case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code: |
|
394 return 'Control character error, possibly incorrectly encoded'; |
|
395 |
|
396 case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code: |
|
397 return 'Syntax error'; |
|
398 |
|
399 case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code: |
|
400 return 'Malformed UTF-8 characters, possibly incorrectly encoded'; |
|
401 |
|
402 case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code: |
|
403 return 'Recursion detected'; |
|
404 |
|
405 case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code: |
|
406 return 'Inf and NaN cannot be JSON encoded'; |
|
407 |
|
408 case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code: |
|
409 return 'Type is not supported'; |
|
410 |
|
411 default: |
|
412 return 'An unknown error occurred'; |
|
413 } |
|
414 } |
|
415 endif; |
|
416 |
|
417 if ( ! interface_exists( 'JsonSerializable' ) ) { |
|
418 define( 'WP_JSON_SERIALIZE_COMPATIBLE', true ); |
|
419 /** |
|
420 * JsonSerializable interface. |
|
421 * |
|
422 * Compatibility shim for PHP <5.4 |
|
423 * |
|
424 * @link https://secure.php.net/jsonserializable |
|
425 * |
|
426 * @since 4.4.0 |
|
427 */ |
|
428 interface JsonSerializable { |
|
429 public function jsonSerialize(); |
|
430 } |
|
431 } |
|
432 |
|
433 // random_int was introduced in PHP 7.0 |
|
434 if ( ! function_exists( 'random_int' ) ) { |
|
435 require ABSPATH . WPINC . '/random_compat/random.php'; |
|
436 } |
|
437 |
|
438 if ( ! function_exists( 'array_replace_recursive' ) ) : |
|
439 /** |
|
440 * PHP-agnostic version of {@link array_replace_recursive()}. |
|
441 * |
|
442 * The array_replace_recursive() function is a PHP 5.3 function. WordPress |
|
443 * currently supports down to PHP 5.2, so this method is a workaround |
|
444 * for PHP 5.2. |
|
445 * |
|
446 * Note: array_replace_recursive() supports infinite arguments, but for our use- |
|
447 * case, we only need to support two arguments. |
|
448 * |
|
449 * Subject to removal once WordPress makes PHP 5.3.0 the minimum requirement. |
|
450 * |
|
451 * @since 4.5.3 |
|
452 * |
|
453 * @see https://secure.php.net/manual/en/function.array-replace-recursive.php#109390 |
|
454 * |
|
455 * @param array $base Array with keys needing to be replaced. |
|
456 * @param array $replacements Array with the replaced keys. |
|
457 * |
|
458 * @return array |
|
459 */ |
|
460 function array_replace_recursive( $base = array(), $replacements = array() ) { |
|
461 foreach ( array_slice( func_get_args(), 1 ) as $replacements ) { |
|
462 $bref_stack = array( &$base ); |
|
463 $head_stack = array( $replacements ); |
|
464 |
|
465 do { |
|
466 end( $bref_stack ); |
|
467 |
|
468 $bref = &$bref_stack[ key( $bref_stack ) ]; |
|
469 $head = array_pop( $head_stack ); |
|
470 |
|
471 unset( $bref_stack[ key( $bref_stack ) ] ); |
|
472 |
|
473 foreach ( array_keys( $head ) as $key ) { |
|
474 if ( isset( $key, $bref ) && |
|
475 isset( $bref[ $key ] ) && is_array( $bref[ $key ] ) && |
|
476 isset( $head[ $key ] ) && is_array( $head[ $key ] ) |
|
477 ) { |
|
478 $bref_stack[] = &$bref[ $key ]; |
|
479 $head_stack[] = $head[ $key ]; |
|
480 } else { |
|
481 $bref[ $key ] = $head[ $key ]; |
|
482 } |
|
483 } |
|
484 } while ( count( $head_stack ) ); |
|
485 } |
|
486 |
|
487 return $base; |
|
488 } |
|
489 endif; |
|
490 |
|
491 /** |
|
492 * Polyfill for the SPL autoloader. In PHP 5.2 (but not 5.3 and later), SPL can |
|
493 * be disabled, and PHP 7.2 raises notices if the compiler finds an __autoload() |
|
494 * function declaration. Function availability is checked here, and the |
|
495 * autoloader is included only if necessary. |
|
496 */ |
|
497 if ( ! function_exists( 'spl_autoload_register' ) ) { |
|
498 require_once ABSPATH . WPINC . '/spl-autoload-compat.php'; |
|
499 } |
|
500 |
|
501 if ( ! function_exists( 'is_countable' ) ) { |
|
502 /** |
|
503 * Polyfill for is_countable() function added in PHP 7.3. |
|
504 * |
|
505 * Verify that the content of a variable is an array or an object |
|
506 * implementing the Countable interface. |
|
507 * |
|
508 * @since 4.9.6 |
|
509 * |
|
510 * @param mixed $var The value to check. |
|
511 * |
|
512 * @return bool True if `$var` is countable, false otherwise. |
|
513 */ |
|
514 function is_countable( $var ) { |
|
515 return ( is_array( $var ) |
|
516 || $var instanceof Countable |
|
517 || $var instanceof SimpleXMLElement |
|
518 || $var instanceof ResourceBundle |
|
519 ); |
|
520 } |
|
521 } |
|
522 |
|
523 if ( ! function_exists( 'is_iterable' ) ) { |
|
524 /** |
|
525 * Polyfill for is_iterable() function added in PHP 7.1. |
|
526 * |
|
527 * Verify that the content of a variable is an array or an object |
|
528 * implementing the Traversable interface. |
|
529 * |
|
530 * @since 4.9.6 |
|
531 * |
|
532 * @param mixed $var The value to check. |
|
533 * |
|
534 * @return bool True if `$var` is iterable, false otherwise. |
|
535 */ |
|
536 function is_iterable( $var ) { |
|
537 return ( is_array( $var ) || $var instanceof Traversable ); |
|
538 } |
|
539 } |