PageRenderTime 15ms CodeModel.GetById 2ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 1ms

/wp-includes/load.php

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