279 return pack( $pack, $hmac ); |
285 return pack( $pack, $hmac ); |
280 } |
286 } |
281 return $hmac; |
287 return $hmac; |
282 } |
288 } |
283 |
289 |
284 if ( ! function_exists( 'json_encode' ) ) { |
|
285 function json_encode( $string ) { |
|
286 global $wp_json; |
|
287 |
|
288 if ( ! ( $wp_json instanceof Services_JSON ) ) { |
|
289 require_once( ABSPATH . WPINC . '/class-json.php' ); |
|
290 $wp_json = new Services_JSON(); |
|
291 } |
|
292 |
|
293 return $wp_json->encodeUnsafe( $string ); |
|
294 } |
|
295 } |
|
296 |
|
297 if ( ! function_exists( 'json_decode' ) ) { |
|
298 /** |
|
299 * @global Services_JSON $wp_json |
|
300 * @param string $string |
|
301 * @param bool $assoc_array |
|
302 * @return object|array |
|
303 */ |
|
304 function json_decode( $string, $assoc_array = false ) { |
|
305 global $wp_json; |
|
306 |
|
307 if ( ! ( $wp_json instanceof Services_JSON ) ) { |
|
308 require_once( ABSPATH . WPINC . '/class-json.php' ); |
|
309 $wp_json = new Services_JSON(); |
|
310 } |
|
311 |
|
312 $res = $wp_json->decode( $string ); |
|
313 if ( $assoc_array ) { |
|
314 $res = _json_decode_object_helper( $res ); |
|
315 } |
|
316 return $res; |
|
317 } |
|
318 |
|
319 /** |
|
320 * @param object $data |
|
321 * @return array |
|
322 */ |
|
323 function _json_decode_object_helper( $data ) { |
|
324 if ( is_object( $data ) ) { |
|
325 $data = get_object_vars( $data ); |
|
326 } |
|
327 return is_array( $data ) ? array_map( __FUNCTION__, $data ) : $data; |
|
328 } |
|
329 } |
|
330 |
|
331 if ( ! function_exists( 'hash_equals' ) ) : |
290 if ( ! function_exists( 'hash_equals' ) ) : |
332 /** |
291 /** |
333 * Timing attack safe string comparison |
292 * Timing attack safe string comparison |
334 * |
293 * |
335 * Compares two strings using the same time whether they're equal or not. |
294 * Compares two strings using the same time whether they're equal or not. |
336 * |
295 * |
|
296 * Note: It can leak the length of a string when arguments of differing length are supplied. |
|
297 * |
337 * This function was added in PHP 5.6. |
298 * This function was added in PHP 5.6. |
338 * |
299 * However, the Hash extension may be explicitly disabled on select servers. |
339 * Note: It can leak the length of a string when arguments of differing length are supplied. |
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. |
340 * |
304 * |
341 * @since 3.9.2 |
305 * @since 3.9.2 |
342 * |
306 * |
343 * @param string $a Expected string. |
307 * @param string $a Expected string. |
344 * @param string $b Actual, user supplied, string. |
308 * @param string $b Actual, user supplied, string. |
345 * @return bool Whether strings are equal. |
309 * @return bool Whether strings are equal. |
346 */ |
310 */ |
347 function hash_equals( $a, $b ) { |
311 function hash_equals( $a, $b ) { |
348 $a_length = strlen( $a ); |
312 $a_length = strlen( $a ); |
349 if ( $a_length !== strlen( $b ) ) { |
313 if ( strlen( $b ) !== $a_length ) { |
350 return false; |
314 return false; |
351 } |
315 } |
352 $result = 0; |
316 $result = 0; |
353 |
317 |
354 // Do not attempt to "optimize" this. |
318 // Do not attempt to "optimize" this. |
355 for ( $i = 0; $i < $a_length; $i++ ) { |
319 for ( $i = 0; $i < $a_length; $i++ ) { |
356 $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] ); |
320 $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] ); |
357 } |
321 } |
358 |
322 |
359 return $result === 0; |
323 return 0 === $result; |
360 } |
324 } |
361 endif; |
325 endif; |
362 |
326 |
363 // JSON_PRETTY_PRINT was introduced in PHP 5.4 |
327 // random_int() was introduced in PHP 7.0. |
364 // Defined here to prevent a notice when using it with wp_json_encode() |
|
365 if ( ! defined( 'JSON_PRETTY_PRINT' ) ) { |
|
366 define( 'JSON_PRETTY_PRINT', 128 ); |
|
367 } |
|
368 |
|
369 if ( ! function_exists( 'json_last_error_msg' ) ) : |
|
370 /** |
|
371 * Retrieves the error string of the last json_encode() or json_decode() call. |
|
372 * |
|
373 * @since 4.4.0 |
|
374 * |
|
375 * @internal This is a compatibility function for PHP <5.5 |
|
376 * |
|
377 * @return bool|string Returns the error message on success, "No Error" if no error has occurred, |
|
378 * or false on failure. |
|
379 */ |
|
380 function json_last_error_msg() { |
|
381 // See https://core.trac.wordpress.org/ticket/27799. |
|
382 if ( ! function_exists( 'json_last_error' ) ) { |
|
383 return false; |
|
384 } |
|
385 |
|
386 $last_error_code = json_last_error(); |
|
387 |
|
388 // Just in case JSON_ERROR_NONE is not defined. |
|
389 $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; |
|
390 |
|
391 switch ( true ) { |
|
392 case $last_error_code === $error_code_none: |
|
393 return 'No error'; |
|
394 |
|
395 case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code: |
|
396 return 'Maximum stack depth exceeded'; |
|
397 |
|
398 case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code: |
|
399 return 'State mismatch (invalid or malformed JSON)'; |
|
400 |
|
401 case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code: |
|
402 return 'Control character error, possibly incorrectly encoded'; |
|
403 |
|
404 case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code: |
|
405 return 'Syntax error'; |
|
406 |
|
407 case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code: |
|
408 return 'Malformed UTF-8 characters, possibly incorrectly encoded'; |
|
409 |
|
410 case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code: |
|
411 return 'Recursion detected'; |
|
412 |
|
413 case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code: |
|
414 return 'Inf and NaN cannot be JSON encoded'; |
|
415 |
|
416 case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code: |
|
417 return 'Type is not supported'; |
|
418 |
|
419 default: |
|
420 return 'An unknown error occurred'; |
|
421 } |
|
422 } |
|
423 endif; |
|
424 |
|
425 if ( ! interface_exists( 'JsonSerializable' ) ) { |
|
426 define( 'WP_JSON_SERIALIZE_COMPATIBLE', true ); |
|
427 /** |
|
428 * JsonSerializable interface. |
|
429 * |
|
430 * Compatibility shim for PHP <5.4 |
|
431 * |
|
432 * @link https://secure.php.net/jsonserializable |
|
433 * |
|
434 * @since 4.4.0 |
|
435 */ |
|
436 interface JsonSerializable { |
|
437 public function jsonSerialize(); |
|
438 } |
|
439 } |
|
440 |
|
441 // random_int was introduced in PHP 7.0 |
|
442 if ( ! function_exists( 'random_int' ) ) { |
328 if ( ! function_exists( 'random_int' ) ) { |
443 require ABSPATH . WPINC . '/random_compat/random.php'; |
329 require ABSPATH . WPINC . '/random_compat/random.php'; |
444 } |
330 } |
445 // sodium_crypto_box was introduced in PHP 7.2 |
331 // sodium_crypto_box() was introduced in PHP 7.2. |
446 if ( ! function_exists( 'sodium_crypto_box' ) ) { |
332 if ( ! function_exists( 'sodium_crypto_box' ) ) { |
447 require ABSPATH . WPINC . '/sodium_compat/autoload.php'; |
333 require ABSPATH . WPINC . '/sodium_compat/autoload.php'; |
448 } |
334 } |
449 |
335 |
450 if ( ! function_exists( 'array_replace_recursive' ) ) : |
|
451 /** |
|
452 * PHP-agnostic version of {@link array_replace_recursive()}. |
|
453 * |
|
454 * The array_replace_recursive() function is a PHP 5.3 function. WordPress |
|
455 * currently supports down to PHP 5.2, so this method is a workaround |
|
456 * for PHP 5.2. |
|
457 * |
|
458 * Note: array_replace_recursive() supports infinite arguments, but for our use- |
|
459 * case, we only need to support two arguments. |
|
460 * |
|
461 * Subject to removal once WordPress makes PHP 5.3.0 the minimum requirement. |
|
462 * |
|
463 * @since 4.5.3 |
|
464 * |
|
465 * @see https://secure.php.net/manual/en/function.array-replace-recursive.php#109390 |
|
466 * |
|
467 * @param array $base Array with keys needing to be replaced. |
|
468 * @param array $replacements Array with the replaced keys. |
|
469 * |
|
470 * @return array |
|
471 */ |
|
472 function array_replace_recursive( $base = array(), $replacements = array() ) { |
|
473 foreach ( array_slice( func_get_args(), 1 ) as $replacements ) { |
|
474 $bref_stack = array( &$base ); |
|
475 $head_stack = array( $replacements ); |
|
476 |
|
477 do { |
|
478 end( $bref_stack ); |
|
479 |
|
480 $bref = &$bref_stack[ key( $bref_stack ) ]; |
|
481 $head = array_pop( $head_stack ); |
|
482 |
|
483 unset( $bref_stack[ key( $bref_stack ) ] ); |
|
484 |
|
485 foreach ( array_keys( $head ) as $key ) { |
|
486 if ( isset( $key, $bref ) && |
|
487 isset( $bref[ $key ] ) && is_array( $bref[ $key ] ) && |
|
488 isset( $head[ $key ] ) && is_array( $head[ $key ] ) ) { |
|
489 |
|
490 $bref_stack[] = &$bref[ $key ]; |
|
491 $head_stack[] = $head[ $key ]; |
|
492 } else { |
|
493 $bref[ $key ] = $head[ $key ]; |
|
494 } |
|
495 } |
|
496 } while ( count( $head_stack ) ); |
|
497 } |
|
498 |
|
499 return $base; |
|
500 } |
|
501 endif; |
|
502 |
|
503 /** |
|
504 * Polyfill for the SPL autoloader. In PHP 5.2 (but not 5.3 and later), SPL can |
|
505 * be disabled, and PHP 7.2 raises notices if the compiler finds an __autoload() |
|
506 * function declaration. Function availability is checked here, and the |
|
507 * autoloader is included only if necessary. |
|
508 */ |
|
509 if ( ! function_exists( 'spl_autoload_register' ) ) { |
|
510 require_once ABSPATH . WPINC . '/spl-autoload-compat.php'; |
|
511 } |
|
512 |
|
513 if ( ! function_exists( 'is_countable' ) ) { |
336 if ( ! function_exists( 'is_countable' ) ) { |
514 /** |
337 /** |
515 * Polyfill for is_countable() function added in PHP 7.3. |
338 * Polyfill for is_countable() function added in PHP 7.3. |
516 * |
339 * |
517 * Verify that the content of a variable is an array or an object |
340 * Verify that the content of a variable is an array or an object |
518 * implementing the Countable interface. |
341 * implementing the Countable interface. |
519 * |
342 * |
520 * @since 4.9.6 |
343 * @since 4.9.6 |
521 * |
344 * |
522 * @param mixed $var The value to check. |
345 * @param mixed $var The value to check. |
523 * |
|
524 * @return bool True if `$var` is countable, false otherwise. |
346 * @return bool True if `$var` is countable, false otherwise. |
525 */ |
347 */ |
526 function is_countable( $var ) { |
348 function is_countable( $var ) { |
527 return ( is_array( $var ) |
349 return ( is_array( $var ) |
528 || $var instanceof Countable |
350 || $var instanceof Countable |