load.php (50040B)
1 <?php 2 /** 3 * These functions are needed to load WordPress. 4 * 5 * @package WordPress 6 */ 7 8 /** 9 * Return the HTTP protocol sent by the server. 10 * 11 * @since 4.4.0 12 * 13 * @return string The HTTP protocol. Default: HTTP/1.0. 14 */ 15 function wp_get_server_protocol() { 16 $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : ''; 17 if ( ! in_array( $protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0' ), true ) ) { 18 $protocol = 'HTTP/1.0'; 19 } 20 return $protocol; 21 } 22 23 /** 24 * Fix `$_SERVER` variables for various setups. 25 * 26 * @since 3.0.0 27 * @access private 28 * 29 * @global string $PHP_SELF The filename of the currently executing script, 30 * relative to the document root. 31 */ 32 function wp_fix_server_vars() { 33 global $PHP_SELF; 34 35 $default_server_values = array( 36 'SERVER_SOFTWARE' => '', 37 'REQUEST_URI' => '', 38 ); 39 40 $_SERVER = array_merge( $default_server_values, $_SERVER ); 41 42 // Fix for IIS when running with PHP ISAPI. 43 if ( empty( $_SERVER['REQUEST_URI'] ) || ( 'cgi-fcgi' !== PHP_SAPI && preg_match( '/^Microsoft-IIS\//', $_SERVER['SERVER_SOFTWARE'] ) ) ) { 44 45 if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) { 46 // IIS Mod-Rewrite. 47 $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL']; 48 } elseif ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) { 49 // IIS Isapi_Rewrite. 50 $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL']; 51 } else { 52 // Use ORIG_PATH_INFO if there is no PATH_INFO. 53 if ( ! isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) ) { 54 $_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO']; 55 } 56 57 // Some IIS + PHP configurations put the script-name in the path-info (no need to append it twice). 58 if ( isset( $_SERVER['PATH_INFO'] ) ) { 59 if ( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] ) { 60 $_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO']; 61 } else { 62 $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO']; 63 } 64 } 65 66 // Append the query string if it exists and isn't null. 67 if ( ! empty( $_SERVER['QUERY_STRING'] ) ) { 68 $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING']; 69 } 70 } 71 } 72 73 // Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests. 74 if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && ( strpos( $_SERVER['SCRIPT_FILENAME'], 'php.cgi' ) == strlen( $_SERVER['SCRIPT_FILENAME'] ) - 7 ) ) { 75 $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED']; 76 } 77 78 // Fix for Dreamhost and other PHP as CGI hosts. 79 if ( strpos( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) !== false ) { 80 unset( $_SERVER['PATH_INFO'] ); 81 } 82 83 // Fix empty PHP_SELF. 84 $PHP_SELF = $_SERVER['PHP_SELF']; 85 if ( empty( $PHP_SELF ) ) { 86 $_SERVER['PHP_SELF'] = preg_replace( '/(\?.*)?$/', '', $_SERVER['REQUEST_URI'] ); 87 $PHP_SELF = $_SERVER['PHP_SELF']; 88 } 89 90 wp_populate_basic_auth_from_authorization_header(); 91 } 92 93 /** 94 * Populates the Basic Auth server details from the Authorization header. 95 * 96 * Some servers running in CGI or FastCGI mode don't pass the Authorization 97 * header on to WordPress. If it's been rewritten to the `HTTP_AUTHORIZATION` header, 98 * fill in the proper $_SERVER variables instead. 99 * 100 * @since 5.6.0 101 */ 102 function wp_populate_basic_auth_from_authorization_header() { 103 // If we don't have anything to pull from, return early. 104 if ( ! isset( $_SERVER['HTTP_AUTHORIZATION'] ) && ! isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) { 105 return; 106 } 107 108 // If either PHP_AUTH key is already set, do nothing. 109 if ( isset( $_SERVER['PHP_AUTH_USER'] ) || isset( $_SERVER['PHP_AUTH_PW'] ) ) { 110 return; 111 } 112 113 // From our prior conditional, one of these must be set. 114 $header = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; 115 116 // Test to make sure the pattern matches expected. 117 if ( ! preg_match( '%^Basic [a-z\d/+]*={0,2}$%i', $header ) ) { 118 return; 119 } 120 121 // Removing `Basic ` the token would start six characters in. 122 $token = substr( $header, 6 ); 123 $userpass = base64_decode( $token ); 124 125 list( $user, $pass ) = explode( ':', $userpass ); 126 127 // Now shove them in the proper keys where we're expecting later on. 128 $_SERVER['PHP_AUTH_USER'] = $user; 129 $_SERVER['PHP_AUTH_PW'] = $pass; 130 } 131 132 /** 133 * Check for the required PHP version, and the MySQL extension or 134 * a database drop-in. 135 * 136 * Dies if requirements are not met. 137 * 138 * @since 3.0.0 139 * @access private 140 * 141 * @global string $required_php_version The required PHP version string. 142 * @global string $wp_version The WordPress version string. 143 */ 144 function wp_check_php_mysql_versions() { 145 global $required_php_version, $wp_version; 146 $php_version = phpversion(); 147 148 if ( version_compare( $required_php_version, $php_version, '>' ) ) { 149 $protocol = wp_get_server_protocol(); 150 header( sprintf( '%s 500 Internal Server Error', $protocol ), true, 500 ); 151 header( 'Content-Type: text/html; charset=utf-8' ); 152 printf( 'Your server is running PHP version %1$s but WordPress %2$s requires at least %3$s.', $php_version, $wp_version, $required_php_version ); 153 exit( 1 ); 154 } 155 156 if ( ! extension_loaded( 'mysql' ) && ! extension_loaded( 'mysqli' ) && ! extension_loaded( 'mysqlnd' ) 157 // This runs before default constants are defined, so we can't assume WP_CONTENT_DIR is set yet. 158 && ( defined( 'WP_CONTENT_DIR' ) && ! file_exists( WP_CONTENT_DIR . '/db.php' ) 159 || ! file_exists( ABSPATH . 'wp-content/db.php' ) ) 160 ) { 161 require_once ABSPATH . WPINC . '/functions.php'; 162 wp_load_translations_early(); 163 $args = array( 164 'exit' => false, 165 'code' => 'mysql_not_found', 166 ); 167 wp_die( 168 __( 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' ), 169 __( 'Requirements Not Met' ), 170 $args 171 ); 172 exit( 1 ); 173 } 174 } 175 176 /** 177 * Retrieves the current environment type. 178 * 179 * The type can be set via the `WP_ENVIRONMENT_TYPE` global system variable, 180 * or a constant of the same name. 181 * 182 * Possible values are 'local', 'development', 'staging', and 'production'. 183 * If not set, the type defaults to 'production'. 184 * 185 * @since 5.5.0 186 * @since 5.5.1 Added the 'local' type. 187 * @since 5.5.1 Removed the ability to alter the list of types. 188 * 189 * @return string The current environment type. 190 */ 191 function wp_get_environment_type() { 192 static $current_env = ''; 193 194 if ( $current_env ) { 195 return $current_env; 196 } 197 198 $wp_environments = array( 199 'local', 200 'development', 201 'staging', 202 'production', 203 ); 204 205 // Add a note about the deprecated WP_ENVIRONMENT_TYPES constant. 206 if ( defined( 'WP_ENVIRONMENT_TYPES' ) && function_exists( '_deprecated_argument' ) ) { 207 if ( function_exists( '__' ) ) { 208 /* translators: %s: WP_ENVIRONMENT_TYPES */ 209 $message = sprintf( __( 'The %s constant is no longer supported.' ), 'WP_ENVIRONMENT_TYPES' ); 210 } else { 211 $message = sprintf( 'The %s constant is no longer supported.', 'WP_ENVIRONMENT_TYPES' ); 212 } 213 214 _deprecated_argument( 215 'define()', 216 '5.5.1', 217 $message 218 ); 219 } 220 221 // Check if the environment variable has been set, if `getenv` is available on the system. 222 if ( function_exists( 'getenv' ) ) { 223 $has_env = getenv( 'WP_ENVIRONMENT_TYPE' ); 224 if ( false !== $has_env ) { 225 $current_env = $has_env; 226 } 227 } 228 229 // Fetch the environment from a constant, this overrides the global system variable. 230 if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) { 231 $current_env = WP_ENVIRONMENT_TYPE; 232 } 233 234 // Make sure the environment is an allowed one, and not accidentally set to an invalid value. 235 if ( ! in_array( $current_env, $wp_environments, true ) ) { 236 $current_env = 'production'; 237 } 238 239 return $current_env; 240 } 241 242 /** 243 * Don't load all of WordPress when handling a favicon.ico request. 244 * 245 * Instead, send the headers for a zero-length favicon and bail. 246 * 247 * @since 3.0.0 248 * @deprecated 5.4.0 Deprecated in favor of do_favicon(). 249 */ 250 function wp_favicon_request() { 251 if ( '/favicon.ico' === $_SERVER['REQUEST_URI'] ) { 252 header( 'Content-Type: image/vnd.microsoft.icon' ); 253 exit; 254 } 255 } 256 257 /** 258 * Die with a maintenance message when conditions are met. 259 * 260 * The default message can be replaced by using a drop-in (maintenance.php in 261 * the wp-content directory). 262 * 263 * @since 3.0.0 264 * @access private 265 */ 266 function wp_maintenance() { 267 // Return if maintenance mode is disabled. 268 if ( ! wp_is_maintenance_mode() ) { 269 return; 270 } 271 272 if ( file_exists( WP_CONTENT_DIR . '/maintenance.php' ) ) { 273 require_once WP_CONTENT_DIR . '/maintenance.php'; 274 die(); 275 } 276 277 require_once ABSPATH . WPINC . '/functions.php'; 278 wp_load_translations_early(); 279 280 header( 'Retry-After: 600' ); 281 282 wp_die( 283 __( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ), 284 __( 'Maintenance' ), 285 503 286 ); 287 } 288 289 /** 290 * Check if maintenance mode is enabled. 291 * 292 * Checks for a file in the WordPress root directory named ".maintenance". 293 * This file will contain the variable $upgrading, set to the time the file 294 * was created. If the file was created less than 10 minutes ago, WordPress 295 * is in maintenance mode. 296 * 297 * @since 5.5.0 298 * 299 * @global int $upgrading The Unix timestamp marking when upgrading WordPress began. 300 * 301 * @return bool True if maintenance mode is enabled, false otherwise. 302 */ 303 function wp_is_maintenance_mode() { 304 global $upgrading; 305 306 if ( ! file_exists( ABSPATH . '.maintenance' ) || wp_installing() ) { 307 return false; 308 } 309 310 require ABSPATH . '.maintenance'; 311 // If the $upgrading timestamp is older than 10 minutes, consider maintenance over. 312 if ( ( time() - $upgrading ) >= 10 * MINUTE_IN_SECONDS ) { 313 return false; 314 } 315 316 /** 317 * Filters whether to enable maintenance mode. 318 * 319 * This filter runs before it can be used by plugins. It is designed for 320 * non-web runtimes. If this filter returns true, maintenance mode will be 321 * active and the request will end. If false, the request will be allowed to 322 * continue processing even if maintenance mode should be active. 323 * 324 * @since 4.6.0 325 * 326 * @param bool $enable_checks Whether to enable maintenance mode. Default true. 327 * @param int $upgrading The timestamp set in the .maintenance file. 328 */ 329 if ( ! apply_filters( 'enable_maintenance_mode', true, $upgrading ) ) { 330 return false; 331 } 332 333 return true; 334 } 335 336 /** 337 * Get the time elapsed so far during this PHP script. 338 * 339 * Uses REQUEST_TIME_FLOAT that appeared in PHP 5.4.0. 340 * 341 * @since 5.8.0 342 * 343 * @return float Seconds since the PHP script started. 344 */ 345 function timer_float() { 346 return microtime( true ) - $_SERVER['REQUEST_TIME_FLOAT']; 347 } 348 349 /** 350 * Start the WordPress micro-timer. 351 * 352 * @since 0.71 353 * @access private 354 * 355 * @global float $timestart Unix timestamp set at the beginning of the page load. 356 * @see timer_stop() 357 * 358 * @return bool Always returns true. 359 */ 360 function timer_start() { 361 global $timestart; 362 $timestart = microtime( true ); 363 return true; 364 } 365 366 /** 367 * Retrieve or display the time from the page start to when function is called. 368 * 369 * @since 0.71 370 * 371 * @global float $timestart Seconds from when timer_start() is called. 372 * @global float $timeend Seconds from when function is called. 373 * 374 * @param int|bool $display Whether to echo or return the results. Accepts 0|false for return, 375 * 1|true for echo. Default 0|false. 376 * @param int $precision The number of digits from the right of the decimal to display. 377 * Default 3. 378 * @return string The "second.microsecond" finished time calculation. The number is formatted 379 * for human consumption, both localized and rounded. 380 */ 381 function timer_stop( $display = 0, $precision = 3 ) { 382 global $timestart, $timeend; 383 $timeend = microtime( true ); 384 $timetotal = $timeend - $timestart; 385 $r = ( function_exists( 'number_format_i18n' ) ) ? number_format_i18n( $timetotal, $precision ) : number_format( $timetotal, $precision ); 386 if ( $display ) { 387 echo $r; 388 } 389 return $r; 390 } 391 392 /** 393 * Set PHP error reporting based on WordPress debug settings. 394 * 395 * Uses three constants: `WP_DEBUG`, `WP_DEBUG_DISPLAY`, and `WP_DEBUG_LOG`. 396 * All three can be defined in wp-config.php. By default, `WP_DEBUG` and 397 * `WP_DEBUG_LOG` are set to false, and `WP_DEBUG_DISPLAY` is set to true. 398 * 399 * When `WP_DEBUG` is true, all PHP notices are reported. WordPress will also 400 * display internal notices: when a deprecated WordPress function, function 401 * argument, or file is used. Deprecated code may be removed from a later 402 * version. 403 * 404 * It is strongly recommended that plugin and theme developers use `WP_DEBUG` 405 * in their development environments. 406 * 407 * `WP_DEBUG_DISPLAY` and `WP_DEBUG_LOG` perform no function unless `WP_DEBUG` 408 * is true. 409 * 410 * When `WP_DEBUG_DISPLAY` is true, WordPress will force errors to be displayed. 411 * `WP_DEBUG_DISPLAY` defaults to true. Defining it as null prevents WordPress 412 * from changing the global configuration setting. Defining `WP_DEBUG_DISPLAY` 413 * as false will force errors to be hidden. 414 * 415 * When `WP_DEBUG_LOG` is true, errors will be logged to `wp-content/debug.log`. 416 * When `WP_DEBUG_LOG` is a valid path, errors will be logged to the specified file. 417 * 418 * Errors are never displayed for XML-RPC, REST, and Ajax requests. 419 * 420 * @since 3.0.0 421 * @since 5.1.0 `WP_DEBUG_LOG` can be a file path. 422 * @access private 423 */ 424 function wp_debug_mode() { 425 /** 426 * Filters whether to allow the debug mode check to occur. 427 * 428 * This filter runs before it can be used by plugins. It is designed for 429 * non-web run-times. Returning false causes the `WP_DEBUG` and related 430 * constants to not be checked and the default PHP values for errors 431 * will be used unless you take care to update them yourself. 432 * 433 * To use this filter you must define a `$wp_filter` global before 434 * WordPress loads, usually in `wp-config.php`. 435 * 436 * Example: 437 * 438 * $GLOBALS['wp_filter'] = array( 439 * 'enable_wp_debug_mode_checks' => array( 440 * 10 => array( 441 * array( 442 * 'accepted_args' => 0, 443 * 'function' => function() { 444 * return false; 445 * }, 446 * ), 447 * ), 448 * ), 449 * ); 450 * 451 * @since 4.6.0 452 * 453 * @param bool $enable_debug_mode Whether to enable debug mode checks to occur. Default true. 454 */ 455 if ( ! apply_filters( 'enable_wp_debug_mode_checks', true ) ) { 456 return; 457 } 458 459 if ( WP_DEBUG ) { 460 error_reporting( E_ALL ); 461 462 if ( WP_DEBUG_DISPLAY ) { 463 ini_set( 'display_errors', 1 ); 464 } elseif ( null !== WP_DEBUG_DISPLAY ) { 465 ini_set( 'display_errors', 0 ); 466 } 467 468 if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) { 469 $log_path = WP_CONTENT_DIR . '/debug.log'; 470 } elseif ( is_string( WP_DEBUG_LOG ) ) { 471 $log_path = WP_DEBUG_LOG; 472 } else { 473 $log_path = false; 474 } 475 476 if ( $log_path ) { 477 ini_set( 'log_errors', 1 ); 478 ini_set( 'error_log', $log_path ); 479 } 480 } else { 481 error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR ); 482 } 483 484 if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) || wp_doing_ajax() || wp_is_json_request() ) { 485 ini_set( 'display_errors', 0 ); 486 } 487 } 488 489 /** 490 * Set the location of the language directory. 491 * 492 * To set directory manually, define the `WP_LANG_DIR` constant 493 * in wp-config.php. 494 * 495 * If the language directory exists within `WP_CONTENT_DIR`, it 496 * is used. Otherwise the language directory is assumed to live 497 * in `WPINC`. 498 * 499 * @since 3.0.0 500 * @access private 501 */ 502 function wp_set_lang_dir() { 503 if ( ! defined( 'WP_LANG_DIR' ) ) { 504 if ( file_exists( WP_CONTENT_DIR . '/languages' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) || ! @is_dir( ABSPATH . WPINC . '/languages' ) ) { 505 /** 506 * Server path of the language directory. 507 * 508 * No leading slash, no trailing slash, full path, not relative to ABSPATH 509 * 510 * @since 2.1.0 511 */ 512 define( 'WP_LANG_DIR', WP_CONTENT_DIR . '/languages' ); 513 if ( ! defined( 'LANGDIR' ) ) { 514 // Old static relative path maintained for limited backward compatibility - won't work in some cases. 515 define( 'LANGDIR', 'wp-content/languages' ); 516 } 517 } else { 518 /** 519 * Server path of the language directory. 520 * 521 * No leading slash, no trailing slash, full path, not relative to `ABSPATH`. 522 * 523 * @since 2.1.0 524 */ 525 define( 'WP_LANG_DIR', ABSPATH . WPINC . '/languages' ); 526 if ( ! defined( 'LANGDIR' ) ) { 527 // Old relative path maintained for backward compatibility. 528 define( 'LANGDIR', WPINC . '/languages' ); 529 } 530 } 531 } 532 } 533 534 /** 535 * Load the database class file and instantiate the `$wpdb` global. 536 * 537 * @since 2.5.0 538 * 539 * @global wpdb $wpdb WordPress database abstraction object. 540 */ 541 function require_wp_db() { 542 global $wpdb; 543 544 require_once ABSPATH . WPINC . '/wp-db.php'; 545 if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) { 546 require_once WP_CONTENT_DIR . '/db.php'; 547 } 548 549 if ( isset( $wpdb ) ) { 550 return; 551 } 552 553 $dbuser = defined( 'DB_USER' ) ? DB_USER : ''; 554 $dbpassword = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : ''; 555 $dbname = defined( 'DB_NAME' ) ? DB_NAME : ''; 556 $dbhost = defined( 'DB_HOST' ) ? DB_HOST : ''; 557 558 $wpdb = new wpdb( $dbuser, $dbpassword, $dbname, $dbhost ); 559 } 560 561 /** 562 * Set the database table prefix and the format specifiers for database 563 * table columns. 564 * 565 * Columns not listed here default to `%s`. 566 * 567 * @since 3.0.0 568 * @access private 569 * 570 * @global wpdb $wpdb WordPress database abstraction object. 571 * @global string $table_prefix The database table prefix. 572 */ 573 function wp_set_wpdb_vars() { 574 global $wpdb, $table_prefix; 575 if ( ! empty( $wpdb->error ) ) { 576 dead_db(); 577 } 578 579 $wpdb->field_types = array( 580 'post_author' => '%d', 581 'post_parent' => '%d', 582 'menu_order' => '%d', 583 'term_id' => '%d', 584 'term_group' => '%d', 585 'term_taxonomy_id' => '%d', 586 'parent' => '%d', 587 'count' => '%d', 588 'object_id' => '%d', 589 'term_order' => '%d', 590 'ID' => '%d', 591 'comment_ID' => '%d', 592 'comment_post_ID' => '%d', 593 'comment_parent' => '%d', 594 'user_id' => '%d', 595 'link_id' => '%d', 596 'link_owner' => '%d', 597 'link_rating' => '%d', 598 'option_id' => '%d', 599 'blog_id' => '%d', 600 'meta_id' => '%d', 601 'post_id' => '%d', 602 'user_status' => '%d', 603 'umeta_id' => '%d', 604 'comment_karma' => '%d', 605 'comment_count' => '%d', 606 // Multisite: 607 'active' => '%d', 608 'cat_id' => '%d', 609 'deleted' => '%d', 610 'lang_id' => '%d', 611 'mature' => '%d', 612 'public' => '%d', 613 'site_id' => '%d', 614 'spam' => '%d', 615 ); 616 617 $prefix = $wpdb->set_prefix( $table_prefix ); 618 619 if ( is_wp_error( $prefix ) ) { 620 wp_load_translations_early(); 621 wp_die( 622 sprintf( 623 /* translators: 1: $table_prefix, 2: wp-config.php */ 624 __( '<strong>Error</strong>: %1$s in %2$s can only contain numbers, letters, and underscores.' ), 625 '<code>$table_prefix</code>', 626 '<code>wp-config.php</code>' 627 ) 628 ); 629 } 630 } 631 632 /** 633 * Toggle `$_wp_using_ext_object_cache` on and off without directly 634 * touching global. 635 * 636 * @since 3.7.0 637 * 638 * @global bool $_wp_using_ext_object_cache 639 * 640 * @param bool $using Whether external object cache is being used. 641 * @return bool The current 'using' setting. 642 */ 643 function wp_using_ext_object_cache( $using = null ) { 644 global $_wp_using_ext_object_cache; 645 $current_using = $_wp_using_ext_object_cache; 646 if ( null !== $using ) { 647 $_wp_using_ext_object_cache = $using; 648 } 649 return $current_using; 650 } 651 652 /** 653 * Start the WordPress object cache. 654 * 655 * If an object-cache.php file exists in the wp-content directory, 656 * it uses that drop-in as an external object cache. 657 * 658 * @since 3.0.0 659 * @access private 660 * 661 * @global array $wp_filter Stores all of the filters. 662 */ 663 function wp_start_object_cache() { 664 global $wp_filter; 665 static $first_init = true; 666 667 // Only perform the following checks once. 668 669 /** 670 * Filters whether to enable loading of the object-cache.php drop-in. 671 * 672 * This filter runs before it can be used by plugins. It is designed for non-web 673 * run-times. If false is returned, object-cache.php will never be loaded. 674 * 675 * @since 5.8.0 676 * 677 * @param bool $enable_object_cache Whether to enable loading object-cache.php (if present). 678 * Default true. 679 */ 680 if ( $first_init && apply_filters( 'enable_loading_object_cache_dropin', true ) ) { 681 if ( ! function_exists( 'wp_cache_init' ) ) { 682 /* 683 * This is the normal situation. First-run of this function. No 684 * caching backend has been loaded. 685 * 686 * We try to load a custom caching backend, and then, if it 687 * results in a wp_cache_init() function existing, we note 688 * that an external object cache is being used. 689 */ 690 if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { 691 require_once WP_CONTENT_DIR . '/object-cache.php'; 692 if ( function_exists( 'wp_cache_init' ) ) { 693 wp_using_ext_object_cache( true ); 694 } 695 696 // Re-initialize any hooks added manually by object-cache.php. 697 if ( $wp_filter ) { 698 $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter ); 699 } 700 } 701 } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { 702 /* 703 * Sometimes advanced-cache.php can load object-cache.php before 704 * this function is run. This breaks the function_exists() check 705 * above and can result in wp_using_ext_object_cache() returning 706 * false when actually an external cache is in use. 707 */ 708 wp_using_ext_object_cache( true ); 709 } 710 } 711 712 if ( ! wp_using_ext_object_cache() ) { 713 require_once ABSPATH . WPINC . '/cache.php'; 714 } 715 716 require_once ABSPATH . WPINC . '/cache-compat.php'; 717 718 /* 719 * If cache supports reset, reset instead of init if already 720 * initialized. Reset signals to the cache that global IDs 721 * have changed and it may need to update keys and cleanup caches. 722 */ 723 if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) ) { 724 wp_cache_switch_to_blog( get_current_blog_id() ); 725 } elseif ( function_exists( 'wp_cache_init' ) ) { 726 wp_cache_init(); 727 } 728 729 if ( function_exists( 'wp_cache_add_global_groups' ) ) { 730 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'site-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'blog_meta' ) ); 731 wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) ); 732 } 733 734 $first_init = false; 735 } 736 737 /** 738 * Redirect to the installer if WordPress is not installed. 739 * 740 * Dies with an error message when Multisite is enabled. 741 * 742 * @since 3.0.0 743 * @access private 744 */ 745 function wp_not_installed() { 746 if ( is_multisite() ) { 747 if ( ! is_blog_installed() && ! wp_installing() ) { 748 nocache_headers(); 749 750 wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) ); 751 } 752 } elseif ( ! is_blog_installed() && ! wp_installing() ) { 753 nocache_headers(); 754 755 require ABSPATH . WPINC . '/kses.php'; 756 require ABSPATH . WPINC . '/pluggable.php'; 757 758 $link = wp_guess_url() . '/wp-admin/install.php'; 759 760 wp_redirect( $link ); 761 die(); 762 } 763 } 764 765 /** 766 * Retrieve an array of must-use plugin files. 767 * 768 * The default directory is wp-content/mu-plugins. To change the default 769 * directory manually, define `WPMU_PLUGIN_DIR` and `WPMU_PLUGIN_URL` 770 * in wp-config.php. 771 * 772 * @since 3.0.0 773 * @access private 774 * 775 * @return string[] Array of absolute paths of files to include. 776 */ 777 function wp_get_mu_plugins() { 778 $mu_plugins = array(); 779 if ( ! is_dir( WPMU_PLUGIN_DIR ) ) { 780 return $mu_plugins; 781 } 782 $dh = opendir( WPMU_PLUGIN_DIR ); 783 if ( ! $dh ) { 784 return $mu_plugins; 785 } 786 while ( ( $plugin = readdir( $dh ) ) !== false ) { 787 if ( '.php' === substr( $plugin, -4 ) ) { 788 $mu_plugins[] = WPMU_PLUGIN_DIR . '/' . $plugin; 789 } 790 } 791 closedir( $dh ); 792 sort( $mu_plugins ); 793 794 return $mu_plugins; 795 } 796 797 /** 798 * Retrieve an array of active and valid plugin files. 799 * 800 * While upgrading or installing WordPress, no plugins are returned. 801 * 802 * The default directory is `wp-content/plugins`. To change the default 803 * directory manually, define `WP_PLUGIN_DIR` and `WP_PLUGIN_URL` 804 * in `wp-config.php`. 805 * 806 * @since 3.0.0 807 * @access private 808 * 809 * @return string[] Array of paths to plugin files relative to the plugins directory. 810 */ 811 function wp_get_active_and_valid_plugins() { 812 $plugins = array(); 813 $active_plugins = (array) get_option( 'active_plugins', array() ); 814 815 // Check for hacks file if the option is enabled. 816 if ( get_option( 'hack_file' ) && file_exists( ABSPATH . 'my-hacks.php' ) ) { 817 _deprecated_file( 'my-hacks.php', '1.5.0' ); 818 array_unshift( $plugins, ABSPATH . 'my-hacks.php' ); 819 } 820 821 if ( empty( $active_plugins ) || wp_installing() ) { 822 return $plugins; 823 } 824 825 $network_plugins = is_multisite() ? wp_get_active_network_plugins() : false; 826 827 foreach ( $active_plugins as $plugin ) { 828 if ( ! validate_file( $plugin ) // $plugin must validate as file. 829 && '.php' === substr( $plugin, -4 ) // $plugin must end with '.php'. 830 && file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist. 831 // Not already included as a network plugin. 832 && ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins, true ) ) 833 ) { 834 $plugins[] = WP_PLUGIN_DIR . '/' . $plugin; 835 } 836 } 837 838 /* 839 * Remove plugins from the list of active plugins when we're on an endpoint 840 * that should be protected against WSODs and the plugin is paused. 841 */ 842 if ( wp_is_recovery_mode() ) { 843 $plugins = wp_skip_paused_plugins( $plugins ); 844 } 845 846 return $plugins; 847 } 848 849 /** 850 * Filters a given list of plugins, removing any paused plugins from it. 851 * 852 * @since 5.2.0 853 * 854 * @param string[] $plugins Array of absolute plugin main file paths. 855 * @return string[] Filtered array of plugins, without any paused plugins. 856 */ 857 function wp_skip_paused_plugins( array $plugins ) { 858 $paused_plugins = wp_paused_plugins()->get_all(); 859 860 if ( empty( $paused_plugins ) ) { 861 return $plugins; 862 } 863 864 foreach ( $plugins as $index => $plugin ) { 865 list( $plugin ) = explode( '/', plugin_basename( $plugin ) ); 866 867 if ( array_key_exists( $plugin, $paused_plugins ) ) { 868 unset( $plugins[ $index ] ); 869 870 // Store list of paused plugins for displaying an admin notice. 871 $GLOBALS['_paused_plugins'][ $plugin ] = $paused_plugins[ $plugin ]; 872 } 873 } 874 875 return $plugins; 876 } 877 878 /** 879 * Retrieves an array of active and valid themes. 880 * 881 * While upgrading or installing WordPress, no themes are returned. 882 * 883 * @since 5.1.0 884 * @access private 885 * 886 * @return string[] Array of absolute paths to theme directories. 887 */ 888 function wp_get_active_and_valid_themes() { 889 global $pagenow; 890 891 $themes = array(); 892 893 if ( wp_installing() && 'wp-activate.php' !== $pagenow ) { 894 return $themes; 895 } 896 897 if ( TEMPLATEPATH !== STYLESHEETPATH ) { 898 $themes[] = STYLESHEETPATH; 899 } 900 901 $themes[] = TEMPLATEPATH; 902 903 /* 904 * Remove themes from the list of active themes when we're on an endpoint 905 * that should be protected against WSODs and the theme is paused. 906 */ 907 if ( wp_is_recovery_mode() ) { 908 $themes = wp_skip_paused_themes( $themes ); 909 910 // If no active and valid themes exist, skip loading themes. 911 if ( empty( $themes ) ) { 912 add_filter( 'wp_using_themes', '__return_false' ); 913 } 914 } 915 916 return $themes; 917 } 918 919 /** 920 * Filters a given list of themes, removing any paused themes from it. 921 * 922 * @since 5.2.0 923 * 924 * @param string[] $themes Array of absolute theme directory paths. 925 * @return string[] Filtered array of absolute paths to themes, without any paused themes. 926 */ 927 function wp_skip_paused_themes( array $themes ) { 928 $paused_themes = wp_paused_themes()->get_all(); 929 930 if ( empty( $paused_themes ) ) { 931 return $themes; 932 } 933 934 foreach ( $themes as $index => $theme ) { 935 $theme = basename( $theme ); 936 937 if ( array_key_exists( $theme, $paused_themes ) ) { 938 unset( $themes[ $index ] ); 939 940 // Store list of paused themes for displaying an admin notice. 941 $GLOBALS['_paused_themes'][ $theme ] = $paused_themes[ $theme ]; 942 } 943 } 944 945 return $themes; 946 } 947 948 /** 949 * Is WordPress in Recovery Mode. 950 * 951 * In this mode, plugins or themes that cause WSODs will be paused. 952 * 953 * @since 5.2.0 954 * 955 * @return bool 956 */ 957 function wp_is_recovery_mode() { 958 return wp_recovery_mode()->is_active(); 959 } 960 961 /** 962 * Determines whether we are currently on an endpoint that should be protected against WSODs. 963 * 964 * @since 5.2.0 965 * 966 * @global string $pagenow 967 * 968 * @return bool True if the current endpoint should be protected. 969 */ 970 function is_protected_endpoint() { 971 // Protect login pages. 972 if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) { 973 return true; 974 } 975 976 // Protect the admin backend. 977 if ( is_admin() && ! wp_doing_ajax() ) { 978 return true; 979 } 980 981 // Protect Ajax actions that could help resolve a fatal error should be available. 982 if ( is_protected_ajax_action() ) { 983 return true; 984 } 985 986 /** 987 * Filters whether the current request is against a protected endpoint. 988 * 989 * This filter is only fired when an endpoint is requested which is not already protected by 990 * WordPress core. As such, it exclusively allows providing further protected endpoints in 991 * addition to the admin backend, login pages and protected Ajax actions. 992 * 993 * @since 5.2.0 994 * 995 * @param bool $is_protected_endpoint Whether the currently requested endpoint is protected. 996 * Default false. 997 */ 998 return (bool) apply_filters( 'is_protected_endpoint', false ); 999 } 1000 1001 /** 1002 * Determines whether we are currently handling an Ajax action that should be protected against WSODs. 1003 * 1004 * @since 5.2.0 1005 * 1006 * @return bool True if the current Ajax action should be protected. 1007 */ 1008 function is_protected_ajax_action() { 1009 if ( ! wp_doing_ajax() ) { 1010 return false; 1011 } 1012 1013 if ( ! isset( $_REQUEST['action'] ) ) { 1014 return false; 1015 } 1016 1017 $actions_to_protect = array( 1018 'edit-theme-plugin-file', // Saving changes in the core code editor. 1019 'heartbeat', // Keep the heart beating. 1020 'install-plugin', // Installing a new plugin. 1021 'install-theme', // Installing a new theme. 1022 'search-plugins', // Searching in the list of plugins. 1023 'search-install-plugins', // Searching for a plugin in the plugin install screen. 1024 'update-plugin', // Update an existing plugin. 1025 'update-theme', // Update an existing theme. 1026 ); 1027 1028 /** 1029 * Filters the array of protected Ajax actions. 1030 * 1031 * This filter is only fired when doing Ajax and the Ajax request has an 'action' property. 1032 * 1033 * @since 5.2.0 1034 * 1035 * @param string[] $actions_to_protect Array of strings with Ajax actions to protect. 1036 */ 1037 $actions_to_protect = (array) apply_filters( 'wp_protected_ajax_actions', $actions_to_protect ); 1038 1039 if ( ! in_array( $_REQUEST['action'], $actions_to_protect, true ) ) { 1040 return false; 1041 } 1042 1043 return true; 1044 } 1045 1046 /** 1047 * Set internal encoding. 1048 * 1049 * In most cases the default internal encoding is latin1, which is 1050 * of no use, since we want to use the `mb_` functions for `utf-8` strings. 1051 * 1052 * @since 3.0.0 1053 * @access private 1054 */ 1055 function wp_set_internal_encoding() { 1056 if ( function_exists( 'mb_internal_encoding' ) ) { 1057 $charset = get_option( 'blog_charset' ); 1058 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged 1059 if ( ! $charset || ! @mb_internal_encoding( $charset ) ) { 1060 mb_internal_encoding( 'UTF-8' ); 1061 } 1062 } 1063 } 1064 1065 /** 1066 * Add magic quotes to `$_GET`, `$_POST`, `$_COOKIE`, and `$_SERVER`. 1067 * 1068 * Also forces `$_REQUEST` to be `$_GET + $_POST`. If `$_SERVER`, 1069 * `$_COOKIE`, or `$_ENV` are needed, use those superglobals directly. 1070 * 1071 * @since 3.0.0 1072 * @access private 1073 */ 1074 function wp_magic_quotes() { 1075 // Escape with wpdb. 1076 $_GET = add_magic_quotes( $_GET ); 1077 $_POST = add_magic_quotes( $_POST ); 1078 $_COOKIE = add_magic_quotes( $_COOKIE ); 1079 $_SERVER = add_magic_quotes( $_SERVER ); 1080 1081 // Force REQUEST to be GET + POST. 1082 $_REQUEST = array_merge( $_GET, $_POST ); 1083 } 1084 1085 /** 1086 * Runs just before PHP shuts down execution. 1087 * 1088 * @since 1.2.0 1089 * @access private 1090 */ 1091 function shutdown_action_hook() { 1092 /** 1093 * Fires just before PHP shuts down execution. 1094 * 1095 * @since 1.2.0 1096 */ 1097 do_action( 'shutdown' ); 1098 1099 wp_cache_close(); 1100 } 1101 1102 /** 1103 * Copy an object. 1104 * 1105 * @since 2.7.0 1106 * @deprecated 3.2.0 1107 * 1108 * @param object $object The object to clone. 1109 * @return object The cloned object. 1110 */ 1111 function wp_clone( $object ) { 1112 // Use parens for clone to accommodate PHP 4. See #17880. 1113 return clone( $object ); 1114 } 1115 1116 /** 1117 * Determines whether the current request is for an administrative interface page. 1118 * 1119 * Does not check if the user is an administrator; use current_user_can() 1120 * for checking roles and capabilities. 1121 * 1122 * For more information on this and similar theme functions, check out 1123 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1124 * Conditional Tags} article in the Theme Developer Handbook. 1125 * 1126 * @since 1.5.1 1127 * 1128 * @global WP_Screen $current_screen WordPress current screen object. 1129 * 1130 * @return bool True if inside WordPress administration interface, false otherwise. 1131 */ 1132 function is_admin() { 1133 if ( isset( $GLOBALS['current_screen'] ) ) { 1134 return $GLOBALS['current_screen']->in_admin(); 1135 } elseif ( defined( 'WP_ADMIN' ) ) { 1136 return WP_ADMIN; 1137 } 1138 1139 return false; 1140 } 1141 1142 /** 1143 * Whether the current request is for a site's administrative interface. 1144 * 1145 * e.g. `/wp-admin/` 1146 * 1147 * Does not check if the user is an administrator; use current_user_can() 1148 * for checking roles and capabilities. 1149 * 1150 * @since 3.1.0 1151 * 1152 * @global WP_Screen $current_screen WordPress current screen object. 1153 * 1154 * @return bool True if inside WordPress blog administration pages. 1155 */ 1156 function is_blog_admin() { 1157 if ( isset( $GLOBALS['current_screen'] ) ) { 1158 return $GLOBALS['current_screen']->in_admin( 'site' ); 1159 } elseif ( defined( 'WP_BLOG_ADMIN' ) ) { 1160 return WP_BLOG_ADMIN; 1161 } 1162 1163 return false; 1164 } 1165 1166 /** 1167 * Whether the current request is for the network administrative interface. 1168 * 1169 * e.g. `/wp-admin/network/` 1170 * 1171 * Does not check if the user is an administrator; use current_user_can() 1172 * for checking roles and capabilities. 1173 * 1174 * Does not check if the site is a Multisite network; use is_multisite() 1175 * for checking if Multisite is enabled. 1176 * 1177 * @since 3.1.0 1178 * 1179 * @global WP_Screen $current_screen WordPress current screen object. 1180 * 1181 * @return bool True if inside WordPress network administration pages. 1182 */ 1183 function is_network_admin() { 1184 if ( isset( $GLOBALS['current_screen'] ) ) { 1185 return $GLOBALS['current_screen']->in_admin( 'network' ); 1186 } elseif ( defined( 'WP_NETWORK_ADMIN' ) ) { 1187 return WP_NETWORK_ADMIN; 1188 } 1189 1190 return false; 1191 } 1192 1193 /** 1194 * Whether the current request is for a user admin screen. 1195 * 1196 * e.g. `/wp-admin/user/` 1197 * 1198 * Does not check if the user is an administrator; use current_user_can() 1199 * for checking roles and capabilities. 1200 * 1201 * @since 3.1.0 1202 * 1203 * @global WP_Screen $current_screen WordPress current screen object. 1204 * 1205 * @return bool True if inside WordPress user administration pages. 1206 */ 1207 function is_user_admin() { 1208 if ( isset( $GLOBALS['current_screen'] ) ) { 1209 return $GLOBALS['current_screen']->in_admin( 'user' ); 1210 } elseif ( defined( 'WP_USER_ADMIN' ) ) { 1211 return WP_USER_ADMIN; 1212 } 1213 1214 return false; 1215 } 1216 1217 /** 1218 * If Multisite is enabled. 1219 * 1220 * @since 3.0.0 1221 * 1222 * @return bool True if Multisite is enabled, false otherwise. 1223 */ 1224 function is_multisite() { 1225 if ( defined( 'MULTISITE' ) ) { 1226 return MULTISITE; 1227 } 1228 1229 if ( defined( 'SUBDOMAIN_INSTALL' ) || defined( 'VHOST' ) || defined( 'SUNRISE' ) ) { 1230 return true; 1231 } 1232 1233 return false; 1234 } 1235 1236 /** 1237 * Retrieve the current site ID. 1238 * 1239 * @since 3.1.0 1240 * 1241 * @global int $blog_id 1242 * 1243 * @return int Site ID. 1244 */ 1245 function get_current_blog_id() { 1246 global $blog_id; 1247 return absint( $blog_id ); 1248 } 1249 1250 /** 1251 * Retrieves the current network ID. 1252 * 1253 * @since 4.6.0 1254 * 1255 * @return int The ID of the current network. 1256 */ 1257 function get_current_network_id() { 1258 if ( ! is_multisite() ) { 1259 return 1; 1260 } 1261 1262 $current_network = get_network(); 1263 1264 if ( ! isset( $current_network->id ) ) { 1265 return get_main_network_id(); 1266 } 1267 1268 return absint( $current_network->id ); 1269 } 1270 1271 /** 1272 * Attempt an early load of translations. 1273 * 1274 * Used for errors encountered during the initial loading process, before 1275 * the locale has been properly detected and loaded. 1276 * 1277 * Designed for unusual load sequences (like setup-config.php) or for when 1278 * the script will then terminate with an error, otherwise there is a risk 1279 * that a file can be double-included. 1280 * 1281 * @since 3.4.0 1282 * @access private 1283 * 1284 * @global WP_Locale $wp_locale WordPress date and time locale object. 1285 */ 1286 function wp_load_translations_early() { 1287 global $wp_locale; 1288 1289 static $loaded = false; 1290 if ( $loaded ) { 1291 return; 1292 } 1293 $loaded = true; 1294 1295 if ( function_exists( 'did_action' ) && did_action( 'init' ) ) { 1296 return; 1297 } 1298 1299 // We need $wp_local_package. 1300 require ABSPATH . WPINC . '/version.php'; 1301 1302 // Translation and localization. 1303 require_once ABSPATH . WPINC . '/pomo/mo.php'; 1304 require_once ABSPATH . WPINC . '/l10n.php'; 1305 require_once ABSPATH . WPINC . '/class-wp-locale.php'; 1306 require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php'; 1307 1308 // General libraries. 1309 require_once ABSPATH . WPINC . '/plugin.php'; 1310 1311 $locales = array(); 1312 $locations = array(); 1313 1314 while ( true ) { 1315 if ( defined( 'WPLANG' ) ) { 1316 if ( '' === WPLANG ) { 1317 break; 1318 } 1319 $locales[] = WPLANG; 1320 } 1321 1322 if ( isset( $wp_local_package ) ) { 1323 $locales[] = $wp_local_package; 1324 } 1325 1326 if ( ! $locales ) { 1327 break; 1328 } 1329 1330 if ( defined( 'WP_LANG_DIR' ) && @is_dir( WP_LANG_DIR ) ) { 1331 $locations[] = WP_LANG_DIR; 1332 } 1333 1334 if ( defined( 'WP_CONTENT_DIR' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) ) { 1335 $locations[] = WP_CONTENT_DIR . '/languages'; 1336 } 1337 1338 if ( @is_dir( ABSPATH . 'wp-content/languages' ) ) { 1339 $locations[] = ABSPATH . 'wp-content/languages'; 1340 } 1341 1342 if ( @is_dir( ABSPATH . WPINC . '/languages' ) ) { 1343 $locations[] = ABSPATH . WPINC . '/languages'; 1344 } 1345 1346 if ( ! $locations ) { 1347 break; 1348 } 1349 1350 $locations = array_unique( $locations ); 1351 1352 foreach ( $locales as $locale ) { 1353 foreach ( $locations as $location ) { 1354 if ( file_exists( $location . '/' . $locale . '.mo' ) ) { 1355 load_textdomain( 'default', $location . '/' . $locale . '.mo' ); 1356 if ( defined( 'WP_SETUP_CONFIG' ) && file_exists( $location . '/admin-' . $locale . '.mo' ) ) { 1357 load_textdomain( 'default', $location . '/admin-' . $locale . '.mo' ); 1358 } 1359 break 2; 1360 } 1361 } 1362 } 1363 1364 break; 1365 } 1366 1367 $wp_locale = new WP_Locale(); 1368 } 1369 1370 /** 1371 * Check or set whether WordPress is in "installation" mode. 1372 * 1373 * If the `WP_INSTALLING` constant is defined during the bootstrap, `wp_installing()` will default to `true`. 1374 * 1375 * @since 4.4.0 1376 * 1377 * @param bool $is_installing Optional. True to set WP into Installing mode, false to turn Installing mode off. 1378 * Omit this parameter if you only want to fetch the current status. 1379 * @return bool True if WP is installing, otherwise false. When a `$is_installing` is passed, the function will 1380 * report whether WP was in installing mode prior to the change to `$is_installing`. 1381 */ 1382 function wp_installing( $is_installing = null ) { 1383 static $installing = null; 1384 1385 // Support for the `WP_INSTALLING` constant, defined before WP is loaded. 1386 if ( is_null( $installing ) ) { 1387 $installing = defined( 'WP_INSTALLING' ) && WP_INSTALLING; 1388 } 1389 1390 if ( ! is_null( $is_installing ) ) { 1391 $old_installing = $installing; 1392 $installing = $is_installing; 1393 return (bool) $old_installing; 1394 } 1395 1396 return (bool) $installing; 1397 } 1398 1399 /** 1400 * Determines if SSL is used. 1401 * 1402 * @since 2.6.0 1403 * @since 4.6.0 Moved from functions.php to load.php. 1404 * 1405 * @return bool True if SSL, otherwise false. 1406 */ 1407 function is_ssl() { 1408 if ( isset( $_SERVER['HTTPS'] ) ) { 1409 if ( 'on' === strtolower( $_SERVER['HTTPS'] ) ) { 1410 return true; 1411 } 1412 1413 if ( '1' == $_SERVER['HTTPS'] ) { 1414 return true; 1415 } 1416 } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { 1417 return true; 1418 } 1419 return false; 1420 } 1421 1422 /** 1423 * Converts a shorthand byte value to an integer byte value. 1424 * 1425 * @since 2.3.0 1426 * @since 4.6.0 Moved from media.php to load.php. 1427 * 1428 * @link https://www.php.net/manual/en/function.ini-get.php 1429 * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes 1430 * 1431 * @param string $value A (PHP ini) byte value, either shorthand or ordinary. 1432 * @return int An integer byte value. 1433 */ 1434 function wp_convert_hr_to_bytes( $value ) { 1435 $value = strtolower( trim( $value ) ); 1436 $bytes = (int) $value; 1437 1438 if ( false !== strpos( $value, 'g' ) ) { 1439 $bytes *= GB_IN_BYTES; 1440 } elseif ( false !== strpos( $value, 'm' ) ) { 1441 $bytes *= MB_IN_BYTES; 1442 } elseif ( false !== strpos( $value, 'k' ) ) { 1443 $bytes *= KB_IN_BYTES; 1444 } 1445 1446 // Deal with large (float) values which run into the maximum integer size. 1447 return min( $bytes, PHP_INT_MAX ); 1448 } 1449 1450 /** 1451 * Determines whether a PHP ini value is changeable at runtime. 1452 * 1453 * @since 4.6.0 1454 * 1455 * @link https://www.php.net/manual/en/function.ini-get-all.php 1456 * 1457 * @param string $setting The name of the ini setting to check. 1458 * @return bool True if the value is changeable at runtime. False otherwise. 1459 */ 1460 function wp_is_ini_value_changeable( $setting ) { 1461 static $ini_all; 1462 1463 if ( ! isset( $ini_all ) ) { 1464 $ini_all = false; 1465 // Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes". 1466 if ( function_exists( 'ini_get_all' ) ) { 1467 $ini_all = ini_get_all(); 1468 } 1469 } 1470 1471 // Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17. 1472 if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === ( $ini_all[ $setting ]['access'] & 7 ) || INI_USER === ( $ini_all[ $setting ]['access'] & 7 ) ) ) { 1473 return true; 1474 } 1475 1476 // If we were unable to retrieve the details, fail gracefully to assume it's changeable. 1477 if ( ! is_array( $ini_all ) ) { 1478 return true; 1479 } 1480 1481 return false; 1482 } 1483 1484 /** 1485 * Determines whether the current request is a WordPress Ajax request. 1486 * 1487 * @since 4.7.0 1488 * 1489 * @return bool True if it's a WordPress Ajax request, false otherwise. 1490 */ 1491 function wp_doing_ajax() { 1492 /** 1493 * Filters whether the current request is a WordPress Ajax request. 1494 * 1495 * @since 4.7.0 1496 * 1497 * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request. 1498 */ 1499 return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX ); 1500 } 1501 1502 /** 1503 * Determines whether the current request should use themes. 1504 * 1505 * @since 5.1.0 1506 * 1507 * @return bool True if themes should be used, false otherwise. 1508 */ 1509 function wp_using_themes() { 1510 /** 1511 * Filters whether the current request should use themes. 1512 * 1513 * @since 5.1.0 1514 * 1515 * @param bool $wp_using_themes Whether the current request should use themes. 1516 */ 1517 return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES ); 1518 } 1519 1520 /** 1521 * Determines whether the current request is a WordPress cron request. 1522 * 1523 * @since 4.8.0 1524 * 1525 * @return bool True if it's a WordPress cron request, false otherwise. 1526 */ 1527 function wp_doing_cron() { 1528 /** 1529 * Filters whether the current request is a WordPress cron request. 1530 * 1531 * @since 4.8.0 1532 * 1533 * @param bool $wp_doing_cron Whether the current request is a WordPress cron request. 1534 */ 1535 return apply_filters( 'wp_doing_cron', defined( 'DOING_CRON' ) && DOING_CRON ); 1536 } 1537 1538 /** 1539 * Checks whether the given variable is a WordPress Error. 1540 * 1541 * Returns whether `$thing` is an instance of the `WP_Error` class. 1542 * 1543 * @since 2.1.0 1544 * 1545 * @param mixed $thing The variable to check. 1546 * @return bool Whether the variable is an instance of WP_Error. 1547 */ 1548 function is_wp_error( $thing ) { 1549 $is_wp_error = ( $thing instanceof WP_Error ); 1550 1551 if ( $is_wp_error ) { 1552 /** 1553 * Fires when `is_wp_error()` is called and its parameter is an instance of `WP_Error`. 1554 * 1555 * @since 5.6.0 1556 * 1557 * @param WP_Error $thing The error object passed to `is_wp_error()`. 1558 */ 1559 do_action( 'is_wp_error_instance', $thing ); 1560 } 1561 1562 return $is_wp_error; 1563 } 1564 1565 /** 1566 * Determines whether file modifications are allowed. 1567 * 1568 * @since 4.8.0 1569 * 1570 * @param string $context The usage context. 1571 * @return bool True if file modification is allowed, false otherwise. 1572 */ 1573 function wp_is_file_mod_allowed( $context ) { 1574 /** 1575 * Filters whether file modifications are allowed. 1576 * 1577 * @since 4.8.0 1578 * 1579 * @param bool $file_mod_allowed Whether file modifications are allowed. 1580 * @param string $context The usage context. 1581 */ 1582 return apply_filters( 'file_mod_allowed', ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS, $context ); 1583 } 1584 1585 /** 1586 * Start scraping edited file errors. 1587 * 1588 * @since 4.9.0 1589 */ 1590 function wp_start_scraping_edited_file_errors() { 1591 if ( ! isset( $_REQUEST['wp_scrape_key'] ) || ! isset( $_REQUEST['wp_scrape_nonce'] ) ) { 1592 return; 1593 } 1594 $key = substr( sanitize_key( wp_unslash( $_REQUEST['wp_scrape_key'] ) ), 0, 32 ); 1595 $nonce = wp_unslash( $_REQUEST['wp_scrape_nonce'] ); 1596 1597 if ( get_transient( 'scrape_key_' . $key ) !== $nonce ) { 1598 echo "###### wp_scraping_result_start:$key ######"; 1599 echo wp_json_encode( 1600 array( 1601 'code' => 'scrape_nonce_failure', 1602 'message' => __( 'Scrape key check failed. Please try again.' ), 1603 ) 1604 ); 1605 echo "###### wp_scraping_result_end:$key ######"; 1606 die(); 1607 } 1608 if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) { 1609 define( 'WP_SANDBOX_SCRAPING', true ); 1610 } 1611 register_shutdown_function( 'wp_finalize_scraping_edited_file_errors', $key ); 1612 } 1613 1614 /** 1615 * Finalize scraping for edited file errors. 1616 * 1617 * @since 4.9.0 1618 * 1619 * @param string $scrape_key Scrape key. 1620 */ 1621 function wp_finalize_scraping_edited_file_errors( $scrape_key ) { 1622 $error = error_get_last(); 1623 echo "\n###### wp_scraping_result_start:$scrape_key ######\n"; 1624 if ( ! empty( $error ) && in_array( $error['type'], array( E_CORE_ERROR, E_COMPILE_ERROR, E_ERROR, E_PARSE, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) { 1625 $error = str_replace( ABSPATH, '', $error ); 1626 echo wp_json_encode( $error ); 1627 } else { 1628 echo wp_json_encode( true ); 1629 } 1630 echo "\n###### wp_scraping_result_end:$scrape_key ######\n"; 1631 } 1632 1633 /** 1634 * Checks whether current request is a JSON request, or is expecting a JSON response. 1635 * 1636 * @since 5.0.0 1637 * 1638 * @return bool True if `Accepts` or `Content-Type` headers contain `application/json`. 1639 * False otherwise. 1640 */ 1641 function wp_is_json_request() { 1642 1643 if ( isset( $_SERVER['HTTP_ACCEPT'] ) && wp_is_json_media_type( $_SERVER['HTTP_ACCEPT'] ) ) { 1644 return true; 1645 } 1646 1647 if ( isset( $_SERVER['CONTENT_TYPE'] ) && wp_is_json_media_type( $_SERVER['CONTENT_TYPE'] ) ) { 1648 return true; 1649 } 1650 1651 return false; 1652 1653 } 1654 1655 /** 1656 * Checks whether current request is a JSONP request, or is expecting a JSONP response. 1657 * 1658 * @since 5.2.0 1659 * 1660 * @return bool True if JSONP request, false otherwise. 1661 */ 1662 function wp_is_jsonp_request() { 1663 if ( ! isset( $_GET['_jsonp'] ) ) { 1664 return false; 1665 } 1666 1667 if ( ! function_exists( 'wp_check_jsonp_callback' ) ) { 1668 require_once ABSPATH . WPINC . '/functions.php'; 1669 } 1670 1671 $jsonp_callback = $_GET['_jsonp']; 1672 if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) { 1673 return false; 1674 } 1675 1676 /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ 1677 $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true ); 1678 1679 return $jsonp_enabled; 1680 1681 } 1682 1683 /** 1684 * Checks whether a string is a valid JSON Media Type. 1685 * 1686 * @since 5.6.0 1687 * 1688 * @param string $media_type A Media Type string to check. 1689 * @return bool True if string is a valid JSON Media Type. 1690 */ 1691 function wp_is_json_media_type( $media_type ) { 1692 static $cache = array(); 1693 1694 if ( ! isset( $cache[ $media_type ] ) ) { 1695 $cache[ $media_type ] = (bool) preg_match( '/(^|\s|,)application\/([\w!#\$&-\^\.\+]+\+)?json(\+oembed)?($|\s|;|,)/i', $media_type ); 1696 } 1697 1698 return $cache[ $media_type ]; 1699 } 1700 1701 /** 1702 * Checks whether current request is an XML request, or is expecting an XML response. 1703 * 1704 * @since 5.2.0 1705 * 1706 * @return bool True if `Accepts` or `Content-Type` headers contain `text/xml` 1707 * or one of the related MIME types. False otherwise. 1708 */ 1709 function wp_is_xml_request() { 1710 $accepted = array( 1711 'text/xml', 1712 'application/rss+xml', 1713 'application/atom+xml', 1714 'application/rdf+xml', 1715 'text/xml+oembed', 1716 'application/xml+oembed', 1717 ); 1718 1719 if ( isset( $_SERVER['HTTP_ACCEPT'] ) ) { 1720 foreach ( $accepted as $type ) { 1721 if ( false !== strpos( $_SERVER['HTTP_ACCEPT'], $type ) ) { 1722 return true; 1723 } 1724 } 1725 } 1726 1727 if ( isset( $_SERVER['CONTENT_TYPE'] ) && in_array( $_SERVER['CONTENT_TYPE'], $accepted, true ) ) { 1728 return true; 1729 } 1730 1731 return false; 1732 } 1733 1734 /** 1735 * Checks if this site is protected by HTTP Basic Auth. 1736 * 1737 * At the moment, this merely checks for the present of Basic Auth credentials. Therefore, calling 1738 * this function with a context different from the current context may give inaccurate results. 1739 * In a future release, this evaluation may be made more robust. 1740 * 1741 * Currently, this is only used by Application Passwords to prevent a conflict since it also utilizes 1742 * Basic Auth. 1743 * 1744 * @since 5.6.1 1745 * 1746 * @global string $pagenow The current page. 1747 * 1748 * @param string $context The context to check for protection. Accepts 'login', 'admin', and 'front'. 1749 * Defaults to the current context. 1750 * @return bool Whether the site is protected by Basic Auth. 1751 */ 1752 function wp_is_site_protected_by_basic_auth( $context = '' ) { 1753 global $pagenow; 1754 1755 if ( ! $context ) { 1756 if ( 'wp-login.php' === $pagenow ) { 1757 $context = 'login'; 1758 } elseif ( is_admin() ) { 1759 $context = 'admin'; 1760 } else { 1761 $context = 'front'; 1762 } 1763 } 1764 1765 $is_protected = ! empty( $_SERVER['PHP_AUTH_USER'] ) || ! empty( $_SERVER['PHP_AUTH_PW'] ); 1766 1767 /** 1768 * Filters whether a site is protected by HTTP Basic Auth. 1769 * 1770 * @since 5.6.1 1771 * 1772 * @param bool $is_protected Whether the site is protected by Basic Auth. 1773 * @param string $context The context to check for protection. One of 'login', 'admin', or 'front'. 1774 */ 1775 return apply_filters( 'wp_is_site_protected_by_basic_auth', $is_protected, $context ); 1776 }