diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 89c74f8..3d93cbd 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -138,15 +138,19 @@ const DRUPAL_BOOTSTRAP_SESSION = 4; const DRUPAL_BOOTSTRAP_PAGE_HEADER = 5; /** - * Seventh bootstrap phase: load code for subsystems and modules; validate and - * fix input data. + * Seventh bootstrap phase: validate and fix input data. */ -const DRUPAL_BOOTSTRAP_CODE = 6; +const DRUPAL_BOOTSTRAP_INPUT = 6; + +/** + * Eighth bootstrap phase: load code for subsystems and modules. + */ +const DRUPAL_BOOTSTRAP_CODE = 7; /** * Final bootstrap phase: initialize language, path, theme, and modules. */ -const DRUPAL_BOOTSTRAP_FULL = 7; +const DRUPAL_BOOTSTRAP_FULL = 8; /** * Role ID for anonymous users; should match what's in the "role" table. @@ -2046,6 +2050,7 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) { DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_PAGE_HEADER, + DRUPAL_BOOTSTRAP_INPUT, DRUPAL_BOOTSTRAP_CODE, DRUPAL_BOOTSTRAP_FULL, ); @@ -2099,6 +2104,10 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) { _drupal_bootstrap_page_header(); break; + case DRUPAL_BOOTSTRAP_INPUT: + _drupal_bootstrap_input(); + break; + case DRUPAL_BOOTSTRAP_CODE: require_once DRUPAL_ROOT . '/core/includes/common.inc'; _drupal_bootstrap_code(); @@ -2332,6 +2341,18 @@ function _drupal_bootstrap_page_header() { } /** + * Checks and configures string handling, and fixes "magic quotes" errors. + */ +function _drupal_bootstrap_input() { + // Detect string handling method. + require_once DRUPAL_ROOT . '/core/includes/unicode.inc'; + unicode_check(); + + // Undo magic quotes. + fix_gpc_magic(); +} + +/** * Returns the current bootstrap phase for this Drupal process. * * The current phase is the one most recently completed by drupal_bootstrap(). @@ -3346,3 +3367,64 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) { // - The memory limit is greater than the memory required for the operation. return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) > parse_size($required))); } + +/** + * Strips slashes from a string or array of strings. + * + * Callback for array_walk() within fix_gpx_magic(). + * + * @param $item + * An individual string or array of strings from superglobals. + */ +function _fix_gpc_magic(&$item) { + if (is_array($item)) { + array_walk($item, '_fix_gpc_magic'); + } + else { + $item = stripslashes($item); + } +} + +/** + * Strips slashes from $_FILES items. + * + * Callback for array_walk() within fix_gpc_magic(). + * + * The tmp_name key is skipped keys since PHP generates single backslashes for + * file paths on Windows systems. + * + * @param $item + * An item from $_FILES. + * @param $key + * The key for the item within $_FILES. + * + * @see http://php.net/manual/features.file-upload.php#42280 + */ +function _fix_gpc_magic_files(&$item, $key) { + if ($key != 'tmp_name') { + if (is_array($item)) { + array_walk($item, '_fix_gpc_magic_files'); + } + else { + $item = stripslashes($item); + } + } +} + +/** + * Fixes double-escaping caused by "magic quotes" in some PHP installations. + * + * @see _fix_gpc_magic() + * @see _fix_gpc_magic_files() + */ +function fix_gpc_magic() { + static $fixed = FALSE; + if (!$fixed && ini_get('magic_quotes_gpc')) { + array_walk($_GET, '_fix_gpc_magic'); + array_walk($_POST, '_fix_gpc_magic'); + array_walk($_COOKIE, '_fix_gpc_magic'); + array_walk($_REQUEST, '_fix_gpc_magic'); + array_walk($_FILES, '_fix_gpc_magic_files'); + } + $fixed = TRUE; +} diff --git a/core/includes/common.inc b/core/includes/common.inc index 8437eff..6edf5fd 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1034,67 +1034,6 @@ function drupal_http_request($url, array $options = array()) { */ /** - * Strips slashes from a string or array of strings. - * - * Callback for array_walk() within fix_gpx_magic(). - * - * @param $item - * An individual string or array of strings from superglobals. - */ -function _fix_gpc_magic(&$item) { - if (is_array($item)) { - array_walk($item, '_fix_gpc_magic'); - } - else { - $item = stripslashes($item); - } -} - -/** - * Strips slashes from $_FILES items. - * - * Callback for array_walk() within fix_gpc_magic(). - * - * The tmp_name key is skipped keys since PHP generates single backslashes for - * file paths on Windows systems. - * - * @param $item - * An item from $_FILES. - * @param $key - * The key for the item within $_FILES. - * - * @see http://php.net/manual/features.file-upload.php#42280 - */ -function _fix_gpc_magic_files(&$item, $key) { - if ($key != 'tmp_name') { - if (is_array($item)) { - array_walk($item, '_fix_gpc_magic_files'); - } - else { - $item = stripslashes($item); - } - } -} - -/** - * Fixes double-escaping caused by "magic quotes" in some PHP installations. - * - * @see _fix_gpc_magic() - * @see _fix_gpc_magic_files() - */ -function fix_gpc_magic() { - static $fixed = FALSE; - if (!$fixed && ini_get('magic_quotes_gpc')) { - array_walk($_GET, '_fix_gpc_magic'); - array_walk($_POST, '_fix_gpc_magic'); - array_walk($_COOKIE, '_fix_gpc_magic'); - array_walk($_REQUEST, '_fix_gpc_magic'); - array_walk($_FILES, '_fix_gpc_magic_files'); - } - $fixed = TRUE; -} - -/** * @defgroup validation Input validation * @{ * Functions to validate user input. @@ -5166,20 +5105,16 @@ function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) { return (($skip_anonymous && $user->uid == 0) || ($token == drupal_get_token($value))); } +/** + * Loads code for subsystems and modules, and registers stream wrappers. + */ function _drupal_bootstrap_code() { - static $called = FALSE; - - if ($called) { - return; - } - $called = TRUE; require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'core/includes/path.inc'); require_once DRUPAL_ROOT . '/core/includes/theme.inc'; require_once DRUPAL_ROOT . '/core/includes/pager.inc'; require_once DRUPAL_ROOT . '/' . variable_get('menu_inc', 'core/includes/menu.inc'); require_once DRUPAL_ROOT . '/core/includes/tablesort.inc'; require_once DRUPAL_ROOT . '/core/includes/file.inc'; - require_once DRUPAL_ROOT . '/core/includes/unicode.inc'; require_once DRUPAL_ROOT . '/core/includes/image.inc'; require_once DRUPAL_ROOT . '/core/includes/form.inc'; require_once DRUPAL_ROOT . '/core/includes/mail.inc'; @@ -5189,19 +5124,16 @@ function _drupal_bootstrap_code() { require_once DRUPAL_ROOT . '/core/includes/errors.inc'; require_once DRUPAL_ROOT . '/core/includes/schema.inc'; - // Detect string handling method - unicode_check(); - // Undo magic quotes - fix_gpc_magic(); - // Load all enabled modules + // Load all enabled modules. module_load_all(); + // Make sure all stream wrappers are registered. file_get_stream_wrappers(); + // Now that stream wrappers are registered, log fatal errors from a simpletest + // child site to a test specific file directory. $test_info = &$GLOBALS['drupal_test_info']; if (!empty($test_info['in_child_site'])) { - // Running inside the simpletest child site, log fatal errors to test - // specific file directory. ini_set('log_errors', 1); ini_set('error_log', 'public://error.log'); } @@ -5211,6 +5143,9 @@ function _drupal_bootstrap_code() { * Temporary BC function for scripts not using DrupalKernel. * * DrupalKernel skips this and replicates it via event listeners. + * + * @see Drupal\Core\EventSubscriber\PathSubscriber; + * @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; */ function _drupal_bootstrap_full($skip = FALSE) { static $called = FALSE; diff --git a/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php index 9b346e0..093728e 100644 --- a/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php @@ -27,6 +27,13 @@ class LegacyRequestSubscriber implements EventSubscriberInterface { * The Event to process. */ public function onKernelRequestLegacy(GetResponseEvent $event) { + // Prior to invoking hook_init(), initialize the theme (potentially a custom + // one for this page), so that: + // - Modules with hook_init() implementations that call theme() or + // theme_get_registry() don't initialize the incorrect theme. + // - The theme can have hook_*_alter() implementations affect page building + // (e.g., hook_form_alter(), hook_node_view_alter(), hook_page_alter()), + // ahead of when rendering starts. menu_set_custom_theme(); drupal_theme_initialize(); module_invoke_all('init'); diff --git a/core/update.php b/core/update.php index ab050a8..6437d4a 100644 --- a/core/update.php +++ b/core/update.php @@ -439,9 +439,13 @@ if (is_null($op) && update_access_allowed()) { install_goto('core/update.php?op=info'); } -// Bootstrap, fix requirements, and set the maintenance theme. -drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); +// Ensure valid input, but allow update_fix_d8_requirements() to run before +// code that can break on a Drupal 7 database. +drupal_bootstrap(DRUPAL_BOOTSTRAP_INPUT); update_fix_d8_requirements(); + +// Now proceed with a full bootstrap. +drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); drupal_maintenance_theme(); // Turn error reporting back on. From now on, only fatal errors (which are diff --git a/index.php b/index.php index 244d4ae..d886deb 100644 --- a/index.php +++ b/index.php @@ -32,6 +32,11 @@ $request = Request::createFromGlobals(); // injection container at some point. request($request); +// Bootstrap all of Drupal's subsystems, but do not initialize anything that +// depends on the fully resolved Drupal path, because path resolution happens +// during the REQUEST event of the kernel. +// @see Drupal\Core\EventSubscriber\PathSubscriber; +// @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); $dispatcher = new EventDispatcher();