Sin descripción

load.php 49KB

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