From 02750689dd25677490f562b0a25e05875bc4c424 Mon Sep 17 00:00:00 2001 From: Dries <dries@buytaert.net> Date: Sun, 29 Apr 2012 11:16:27 -0400 Subject: [PATCH] - Patch #1183208 by effulgentsia, Niklas Fiekas, katbailey, no_commit_credit, catch: remove variable_get()('clean_url()') and switch to index.php/path pattern for dirty URL support. --- core/authorize.php | 11 - core/includes/bootstrap.inc | 115 ++++++---- core/includes/common.inc | 118 +++++------ core/includes/file.inc | 2 +- core/includes/form.inc | 4 +- core/includes/install.core.inc | 16 +- core/includes/install.inc | 3 +- core/includes/menu.inc | 35 ++-- core/includes/pager.inc | 4 +- core/includes/path.inc | 33 +-- core/includes/tablesort.inc | 4 +- core/includes/theme.inc | 2 +- core/misc/ajax.js | 12 +- core/misc/drupal.js | 7 + core/misc/timezone.js | 4 +- core/modules/block/block.module | 11 +- core/modules/comment/comment.module | 8 +- core/modules/contact/contact.module | 2 +- core/modules/image/image.module | 4 +- core/modules/image/image.test | 10 +- core/modules/language/language.admin.inc | 2 +- core/modules/language/language.module | 2 +- .../modules/language/language.negotiation.inc | 9 +- core/modules/locale/locale.module | 2 +- core/modules/locale/locale.test | 20 +- core/modules/menu/menu.admin.js | 3 +- core/modules/openid/tests/openid_test.module | 15 +- core/modules/overlay/overlay-parent.js | 30 +-- core/modules/overlay/overlay.module | 2 +- core/modules/path/path.admin.inc | 4 +- core/modules/search/search.module | 2 +- core/modules/shortcut/shortcut.admin.inc | 2 +- core/modules/shortcut/shortcut.module | 2 +- .../simpletest/drupal_web_test_case.php | 2 - core/modules/simpletest/simpletest.test | 2 - core/modules/statistics/statistics.module | 4 +- core/modules/statistics/statistics.test | 9 +- core/modules/system/system.admin.inc | 96 +-------- core/modules/system/system.api.php | 2 +- core/modules/system/system.cron.js | 2 +- core/modules/system/system.install | 7 + core/modules/system/system.js | 49 ----- core/modules/system/system.maintenance.css | 7 - core/modules/system/system.module | 22 +- core/modules/system/system.test | 5 +- core/modules/system/tests/ajax.test | 2 +- core/modules/system/tests/common.test | 198 ++++++------------ core/modules/system/tests/file.test | 21 +- core/modules/system/tests/menu.test | 4 +- .../tests/modules/menu_test/menu_test.module | 2 +- .../url_alter_test/url_alter_test.module | 4 +- core/modules/system/tests/path.test | 6 +- core/modules/system/tests/session.test | 4 +- core/modules/system/tests/tablesort.test | 7 +- core/modules/system/tests/theme.test | 14 +- .../modules/system/tests/upgrade/upgrade.test | 2 - core/modules/taxonomy/taxonomy.admin.inc | 4 +- core/modules/update/update.compare.inc | 3 +- core/modules/update/update.module | 2 +- core/modules/user/user.module | 4 +- core/scripts/drupal.sh | 7 +- core/scripts/run-tests.sh | 2 +- robots.txt | 18 +- web.config | 7 +- 64 files changed, 374 insertions(+), 644 deletions(-) diff --git a/core/authorize.php b/core/authorize.php index c6ba51dbf4da..d703b332c858 100644 --- a/core/authorize.php +++ b/core/authorize.php @@ -103,17 +103,6 @@ function authorize_access_allowed() { // Load the code that drives the authorize process. require_once DRUPAL_ROOT . '/core/includes/authorize.inc'; - // For the sake of Batch API and a few other low-level functions, we need to - // initialize the URL path into $_GET['q']. However, we do not want to raise - // our bootstrap level, nor do we want to call drupal_initialize_path(), - // since that is assuming that modules are loaded and invoking hooks. - // However, all we really care is if we're in the middle of a batch, in which - // case $_GET['q'] will already be set, we just initialize it to an empty - // string if it's not already defined. - if (!isset($_GET['q'])) { - $_GET['q'] = ''; - } - if (isset($_SESSION['authorize_operation']['page_title'])) { drupal_set_title($_SESSION['authorize_operation']['page_title']); } diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 6abe08a571b3..c3768825cd86 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -551,12 +551,8 @@ function drupal_environment_initialize() { $_SERVER['HTTP_HOST'] = ''; } - // When clean URLs are enabled, emulate ?q=foo/bar using REQUEST_URI. It is - // not possible to append the query string using mod_rewrite without the B - // flag (this was added in Apache 2.2.8), because mod_rewrite unescapes the - // path before passing it on to PHP. This is a problem when the path contains - // e.g. "&" or "%" that have special meanings in URLs and must be encoded. - $_GET['q'] = request_path(); + // @todo Refactor with the Symfony Request object. + _current_path(request_path()); // Enforce E_STRICT, but allow users to set levels not part of E_STRICT. error_reporting(E_STRICT | E_ALL | error_reporting()); @@ -597,7 +593,7 @@ function drupal_valid_http_host($host) { * Sets the base URL, cookie domain, and session name from configuration. */ function drupal_settings_initialize() { - global $base_url, $base_path, $base_root; + global $base_url, $base_path, $base_root, $script_path; // Export the following settings.php variables to the global namespace global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name, $config_signature_key; @@ -626,8 +622,8 @@ function drupal_settings_initialize() { $base_url = $base_root; - // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not - // be modified by a visitor. + // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is + // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'. if ($dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')) { // Remove "core" directory if present, allowing install.php, update.php, // cron.php and others to auto-detect a base path. @@ -648,6 +644,32 @@ function drupal_settings_initialize() { $base_secure_url = str_replace('http://', 'https://', $base_url); $base_insecure_url = str_replace('https://', 'http://', $base_url); + // Determine the path of the script relative to the base path, and add a + // trailing slash. This is needed for creating URLs to Drupal pages. + if (!isset($script_path)) { + $script_path = ''; + // We don't expect scripts outside of the base path, but sanity check + // anyway. + if (strpos($_SERVER['SCRIPT_NAME'], $base_path) === 0) { + $script_path = substr($_SERVER['SCRIPT_NAME'], strlen($base_path)) . '/'; + // If the request URI does not contain the script name, then clean URLs + // are in effect and the script path can be similarly dropped from URL + // generation. For servers that don't provide $_SERVER['REQUEST_URI'], we + // do not know the actual URI requested by the client, and request_uri() + // returns a URI with the script name, resulting in non-clean URLs unless + // there's other code that intervenes. + if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) { + $script_path = ''; + } + // @todo Temporary BC for install.php, update.php, and other scripts. + // - http://drupal.org/node/1547184 + // - http://drupal.org/node/1546082 + if ($script_path !== 'index.php/') { + $script_path = ''; + } + } + } + if ($cookie_domain) { // If the user specifies the cookie domain, also use it for session name. $session_name = $cookie_domain; @@ -1488,13 +1510,15 @@ function drupal_validate_utf8($text) { * * Because $_SERVER['REQUEST_URI'] is only available on Apache, we generate an * equivalent using other environment variables. + * + * @todo The above comment is incorrect: http://drupal.org/node/1547294. */ -function request_uri() { +function request_uri($omit_query_string = FALSE) { if (isset($_SERVER['REQUEST_URI'])) { $uri = $_SERVER['REQUEST_URI']; } else { - if (isset($_SERVER['argv'])) { + if (isset($_SERVER['argv'][0])) { $uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['argv'][0]; } elseif (isset($_SERVER['QUERY_STRING'])) { @@ -1507,7 +1531,7 @@ function request_uri() { // Prevent multiple slashes to avoid cross site requests via the Form API. $uri = '/' . ltrim($uri, '/'); - return $uri; + return $omit_query_string ? strtok($uri, '?') : $uri; } /** @@ -2181,7 +2205,7 @@ function _drupal_bootstrap_page_cache() { if (is_object($cache)) { header('X-Drupal-Cache: HIT'); // Restore the metadata cached with the page. - $_GET['q'] = $cache->data['path']; + _current_path($cache->data['path']); drupal_set_title($cache->data['title'], PASS_THROUGH); date_default_timezone_set(drupal_get_user_timezone()); // If the skipping of the bootstrap hooks is not enforced, call @@ -2418,9 +2442,9 @@ function drupal_maintenance_theme() { */ function drupal_fast_404() { $exclude_paths = variable_get('404_fast_paths_exclude', FALSE); - if ($exclude_paths && !preg_match($exclude_paths, $_GET['q'])) { + if ($exclude_paths && !preg_match($exclude_paths, request_path())) { $fast_paths = variable_get('404_fast_paths', FALSE); - if ($fast_paths && preg_match($fast_paths, $_GET['q'])) { + if ($fast_paths && preg_match($fast_paths, request_path())) { drupal_add_http_header('Status', '404 Not Found'); $fast_404_html = variable_get('404_fast_html', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>'); // Replace @path in the variable with the page path. @@ -2655,41 +2679,44 @@ function request_path() { return $path; } - if (isset($_GET['q'])) { - // This is a request with a ?q=foo/bar query string. $_GET['q'] is - // overwritten in drupal_path_initialize(), but request_path() is called - // very early in the bootstrap process, so the original value is saved in - // $path and returned in later calls. - $path = $_GET['q']; - } - elseif (isset($_SERVER['REQUEST_URI'])) { - // This request is either a clean URL, or 'index.php', or nonsense. - // Extract the path from REQUEST_URI. - $request_path = strtok($_SERVER['REQUEST_URI'], '?'); - $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')); - // Unescape and strip $base_path prefix, leaving q without a leading slash. - $path = substr(urldecode($request_path), $base_path_len + 1); - // If the path equals the script filename, either because 'index.php' was - // explicitly provided in the URL, or because the server added it to - // $_SERVER['REQUEST_URI'] even when it wasn't provided in the URL (some - // versions of Microsoft IIS do this), the front page should be served. - if ($path == basename($_SERVER['PHP_SELF'])) { - $path = ''; - } - } - else { - // This is the front page. + // Get the part of the URI between the base path of the Drupal installation + // and the query string, and unescape it. + $request_path = request_uri(TRUE); + $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')); + $path = substr(urldecode($request_path), $base_path_len + 1); + + // Depending on server configuration, the URI might or might not include the + // script name. For example, the front page might be accessed as + // http://example.com or as http://example.com/index.php, and the "user" + // page might be accessed as http://example.com/user or as + // http://example.com/index.php/user. Strip the script name from $path. + $script = basename($_SERVER['SCRIPT_NAME']); + if ($path == $script) { $path = ''; } + elseif (strpos($path, $script . '/') === 0) { + $path = substr($path, strlen($script) + 1); + } - // Under certain conditions Apache's RewriteRule directive prepends the value - // assigned to $_GET['q'] with a slash. Moreover we can always have a trailing - // slash in place, hence we need to normalize $_GET['q']. + // Extra slashes can appear in URLs or under some conditions, added by Apache, + // so normalize. $path = trim($path, '/'); return $path; } +/** + * @todo This is a temporary function pending refactoring Drupal to use + * Symfony's Request object exclusively. + */ +function _current_path($path = NULL) { + static $current_path = ''; + if (isset($path)) { + $current_path = $path; + } + return $current_path; +} + /** * Returns a component of the current Drupal path. * @@ -2726,7 +2753,9 @@ function arg($index = NULL, $path = NULL) { $arguments = &$drupal_static_fast['arguments']; if (!isset($path)) { - $path = $_GET['q']; + // @todo The public function current_path() is not available during early + // bootstrap. + $path = _current_path(); } if (!isset($arguments[$path])) { $arguments[$path] = explode('/', $path); diff --git a/core/includes/common.inc b/core/includes/common.inc index 353a9b51d8c9..17c626b2b6be 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -397,14 +397,14 @@ function drupal_get_feeds($delimiter = "\n") { * (optional) An array to be processed. Defaults to $_GET. * @param $exclude * (optional) A list of $query array keys to remove. Use "parent[child]" to - * exclude nested items. Defaults to array('q'). + * exclude nested items. * @param $parent * Internal use only. Used to build the $query array key for nested items. * * @return * An array containing query parameters, which can be used for url(). */ -function drupal_get_query_parameters(array $query = NULL, array $exclude = array('q'), $parent = '') { +function drupal_get_query_parameters(array $query = NULL, array $exclude = array(), $parent = '') { // Set defaults, if none given. if (!isset($query)) { $query = $_GET; @@ -517,7 +517,7 @@ function drupal_get_destination() { $destination = array('destination' => $_GET['destination']); } else { - $path = $_GET['q']; + $path = current_path(); $query = drupal_http_build_query(drupal_get_query_parameters()); if ($query != '') { $path .= '?' . $query; @@ -598,13 +598,6 @@ function drupal_parse_url($url) { $options['fragment'] = $parts['fragment']; } } - // The 'q' parameter contains the path of the current page if clean URLs are - // disabled. It overrides the 'path' of the URL when present, even if clean - // URLs are enabled, due to how Apache rewriting rules work. - if (isset($options['query']['q'])) { - $options['path'] = $options['query']['q']; - unset($options['query']['q']); - } return $options; } @@ -2138,14 +2131,9 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) { * dependent URL requires so. * - 'prefix': Only used internally, to modify the path when a language * dependent URL requires so. - * - 'script': The script filename in Drupal's root directory to use when - * clean URLs are disabled, such as 'index.php'. Defaults to an empty - * string, as most modern web servers automatically find 'index.php'. If - * clean URLs are disabled, the value of $path is appended as query - * parameter 'q' to $options['script'] in the returned URL. When deploying - * Drupal on a web server that cannot be configured to automatically find - * index.php, then hook_url_outbound_alter() can be implemented to force - * this value to 'index.php'. + * - 'script': Added to the URL between the base path and the path prefix. + * Defaults to empty string when clean URLs are in effect, and to + * 'index.php/' when they are not. * - 'entity_type': The entity type of the object that called url(). Only * set if url() is invoked by entity_uri(). * - 'entity': The entity object (such as a node) for which the URL is being @@ -2161,7 +2149,8 @@ function url($path = NULL, array $options = array()) { 'query' => array(), 'absolute' => FALSE, 'alias' => FALSE, - 'prefix' => '' + 'prefix' => '', + 'script' => $GLOBALS['script_path'], ); if (!isset($options['external'])) { @@ -2243,32 +2232,9 @@ function url($path = NULL, array $options = array()) { $base = $options['absolute'] ? $options['base_url'] . '/' : base_path(); $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; - // With Clean URLs. - if (!empty($GLOBALS['conf']['clean_url'])) { - $path = drupal_encode_path($prefix . $path); - if ($options['query']) { - return $base . $path . '?' . drupal_http_build_query($options['query']) . $options['fragment']; - } - else { - return $base . $path . $options['fragment']; - } - } - // Without Clean URLs. - else { - $path = $prefix . $path; - $query = array(); - if (!empty($path)) { - $query['q'] = $path; - } - if ($options['query']) { - // We do not use array_merge() here to prevent overriding $path via query - // parameters. - $query += $options['query']; - } - $query = $query ? ('?' . drupal_http_build_query($query)) : ''; - $script = isset($options['script']) ? $options['script'] : ''; - return $base . $script . $query . $options['fragment']; - } + $path = drupal_encode_path($prefix . $path); + $query = $options['query'] ? ('?' . drupal_http_build_query($options['query'])) : ''; + return $base . $options['script'] . $path . $query . $options['fragment']; } /** @@ -2404,7 +2370,7 @@ function l($text, $path, array $options = array()) { ); // Append active class. - if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) && + if (($path == current_path() || ($path == '<front>' && drupal_is_front_page())) && (empty($options['language']) || $options['language']->langcode == drupal_container()->get(LANGUAGE_TYPE_URL)->langcode)) { $options['attributes']['class'][] = 'active'; } @@ -2530,7 +2496,7 @@ function drupal_deliver_page($page_callback_result, $default_delivery_callback = // If a delivery callback is specified, but doesn't exist as a function, // something is wrong, but don't print anything, since it's not known // what format the response needs to be in. - watchdog('delivery callback not found', 'callback %callback not found: %q.', array('%callback' => $delivery_callback, '%q' => $_GET['q']), WATCHDOG_ERROR); + watchdog('delivery callback not found', 'callback %callback not found: %path.', array('%callback' => $delivery_callback, '%path' => current_path()), WATCHDOG_ERROR); } } @@ -2571,18 +2537,18 @@ function drupal_deliver_html_page($page_callback_result) { // Print a 404 page. drupal_add_http_header('Status', '404 Not Found'); - watchdog('page not found', check_plain($_GET['q']), NULL, WATCHDOG_WARNING); + watchdog('page not found', check_plain(current_path()), NULL, WATCHDOG_WARNING); // Check for and return a fast 404 page if configured. drupal_fast_404(); // Keep old path for reference, and to allow forms to redirect to it. if (!isset($_GET['destination'])) { - $_GET['destination'] = $_GET['q']; + $_GET['destination'] = current_path(); } $path = drupal_get_normal_path(variable_get('site_404', '')); - if ($path && $path != $_GET['q']) { + if ($path && $path != current_path()) { // Custom 404 handler. Set the active item in case there are tabs to // display, or other dependencies on the path. menu_set_active_item($path); @@ -2603,15 +2569,15 @@ function drupal_deliver_html_page($page_callback_result) { case MENU_ACCESS_DENIED: // Print a 403 page. drupal_add_http_header('Status', '403 Forbidden'); - watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING); + watchdog('access denied', check_plain(current_path()), NULL, WATCHDOG_WARNING); // Keep old path for reference, and to allow forms to redirect to it. if (!isset($_GET['destination'])) { - $_GET['destination'] = $_GET['q']; + $_GET['destination'] = current_path(); } $path = drupal_get_normal_path(variable_get('site_403', '')); - if ($path && $path != $_GET['q']) { + if ($path && $path != current_path()) { // Custom 403 handler. Set the active item in case there are tabs to // display or other dependencies on the path. menu_set_active_item($path); @@ -3570,11 +3536,15 @@ function drupal_build_css_cache($css) { if (!file_exists($uri) && !file_unmanaged_save_data($data, $uri, FILE_EXISTS_REPLACE)) { return FALSE; } - // If CSS gzip compression is enabled, clean URLs are enabled (which means - // that rewrite rules are working) and the zlib extension is available then - // create a gzipped version of this file. This file is served conditionally - // to browsers that accept gzip using .htaccess rules. - if (variable_get('css_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) { + // If CSS gzip compression is enabled and the zlib extension is available + // then create a gzipped version of this file. This file is served + // conditionally to browsers that accept gzip using .htaccess rules. + // It's possible that the rewrite rules in .htaccess aren't working on this + // server, but there's no harm (other than the time spent generating the + // file) in generating the file anyway. Sites on servers where rewrite rules + // aren't working can set css_gzip_compression to FALSE in order to skip + // generating a file that won't be used. + if (variable_get('css_gzip_compression', TRUE) && extension_loaded('zlib')) { if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) { return FALSE; } @@ -4105,15 +4075,19 @@ function drupal_add_js($data = NULL, $options = NULL) { // Add jquery.js and drupal.js, as well as the basePath setting, the // first time a JavaScript file is added. if (empty($javascript)) { - // url() generates the prefix using hook_url_outbound_alter(). Instead of - // running the hook_url_outbound_alter() again here, extract the prefix - // from url(). - url('', array('prefix' => &$prefix)); + // url() generates the script and prefix using hook_url_outbound_alter(). + // Instead of running the hook_url_outbound_alter() again here, extract + // them from url(). + // @todo Make this less hacky: http://drupal.org/node/1547376. + $scriptPath = $GLOBALS['script_path']; + $pathPrefix = ''; + url('', array('script' => &$scriptPath, 'prefix' => &$pathPrefix)); $javascript = array( 'settings' => array( 'data' => array( array('basePath' => base_path()), - array('pathPrefix' => empty($prefix) ? '' : $prefix), + array('scriptPath' => $scriptPath), + array('pathPrefix' => $pathPrefix), ), 'type' => 'setting', 'scope' => 'header', @@ -5056,11 +5030,15 @@ function drupal_build_js_cache($files) { if (!file_exists($uri) && !file_unmanaged_save_data($contents, $uri, FILE_EXISTS_REPLACE)) { return FALSE; } - // If JS gzip compression is enabled, clean URLs are enabled (which means - // that rewrite rules are working) and the zlib extension is available then - // create a gzipped version of this file. This file is served conditionally - // to browsers that accept gzip using .htaccess rules. - if (variable_get('js_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) { + // If JS gzip compression is enabled and the zlib extension is available + // then create a gzipped version of this file. This file is served + // conditionally to browsers that accept gzip using .htaccess rules. + // It's possible that the rewrite rules in .htaccess aren't working on this + // server, but there's no harm (other than the time spent generating the + // file) in generating the file anyway. Sites on servers where rewrite rules + // aren't working can set js_gzip_compression to FALSE in order to skip + // generating a file that won't be used. + if (variable_get('js_gzip_compression', TRUE) && extension_loaded('zlib')) { if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($contents, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) { return FALSE; } @@ -5217,7 +5195,7 @@ function _drupal_bootstrap_full() { ini_set('error_log', 'public://error.log'); } - // Initialize $_GET['q'] prior to invoking hook_init(). + // Initialize current_path() prior to invoking hook_init(). drupal_path_initialize(); // Let all modules take action before the menu system handles the request. @@ -5256,7 +5234,7 @@ function drupal_page_set_cache() { $cache = (object) array( 'cid' => $base_root . request_uri(), 'data' => array( - 'path' => $_GET['q'], + 'path' => current_path(), 'body' => ob_get_clean(), 'title' => drupal_get_title(), 'headers' => array(), diff --git a/core/includes/file.inc b/core/includes/file.inc index c4356a937a3a..b476bc78ddb5 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -2031,7 +2031,7 @@ function file_transfer($uri, $headers) { * @see system_menu() */ function file_download() { - // Merge remainder of arguments from GET['q'], into relative file path. + // Merge remaining path arguments into relative file path. $args = func_get_args(); $scheme = array_shift($args); $target = implode('/', $args); diff --git a/core/includes/form.inc b/core/includes/form.inc index 6d93420ceedf..bc71b9ef2d5f 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1248,7 +1248,7 @@ function drupal_redirect_form($form_state) { $function($form_state['redirect']); } } - drupal_goto($_GET['q']); + drupal_goto(current_path()); } } @@ -4682,7 +4682,7 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'd 'progressive' => TRUE, 'url' => $url, 'url_options' => array(), - 'source_url' => $_GET['q'], + 'source_url' => current_path(), 'redirect' => $redirect, 'theme' => $GLOBALS['theme_key'], 'redirect_callback' => $redirect_callback, diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 125852a9e567..5cb3399a094a 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1522,11 +1522,8 @@ function install_configure_form($form, &$form_state, &$install_state) { // We add these strings as settings because JavaScript translation does not // work on install time. drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail'))), 'setting'); - drupal_add_js('jQuery(function () { Drupal.cleanURLsInstallCheck(); });', 'inline'); // Add JS to show / hide the 'Email administrator about site updates' elements drupal_add_js('jQuery(function () { Drupal.hideEmailAdministratorCheckbox() });', 'inline'); - // Build menu to allow clean URL check. - menu_rebuild(); // Cache a fully-built schema. This is necessary for any invocation of // index.php because: (1) setting cache table entries requires schema @@ -1534,8 +1531,7 @@ function install_configure_form($form, &$form_state, &$install_state) { // loaded, so (3) if there is no cached schema, drupal_get_schema() will // try to generate one but with no loaded modules will return nothing. // - // This logically could be done during the 'install_finished' task, but the - // clean URL check requires it now. + // @todo Move this to the 'install_finished' task? drupal_get_schema(NULL, TRUE); // Return the form. @@ -1827,12 +1823,6 @@ function _install_configure_form($form, &$form_state, &$install_state) { '#attributes' => array('class' => array('timezone-detect')), ); - $form['server_settings']['clean_url'] = array( - '#type' => 'hidden', - '#default_value' => 0, - '#attributes' => array('id' => 'edit-clean-url', 'class' => array('install')), - ); - $form['update_notifications'] = array( '#type' => 'fieldset', '#title' => st('Update notifications'), @@ -1903,10 +1893,6 @@ function install_configure_form_submit($form, &$form_state) { $user = user_load(1); user_login_finalize(); - if (isset($form_state['values']['clean_url'])) { - variable_set('clean_url', $form_state['values']['clean_url']); - } - // Record when this install ran. variable_set('install_time', $_SERVER['REQUEST_TIME']); } diff --git a/core/includes/install.inc b/core/includes/install.inc index 72adf1ca16f0..283e31ca7b25 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -121,8 +121,7 @@ function drupal_detect_baseurl($file = 'core/install.php') { $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://'; $host = $_SERVER['SERVER_NAME']; $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']); - $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']); - $dir = str_replace("/$file", '', $uri); + $dir = str_replace("/$file", '', $_SERVER['SCRIPT_NAME']); return "$proto$host$port$dir"; } diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 96791e39ef78..2bfc39e6e89a 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -441,7 +441,7 @@ function menu_set_item($path, $router_item) { function menu_get_item($path = NULL, $router_item = NULL) { $router_items = &drupal_static(__FUNCTION__); if (!isset($path)) { - $path = $_GET['q']; + $path = current_path(); } if (isset($router_item)) { $router_items[$path] = $router_item; @@ -498,7 +498,7 @@ function menu_execute_active_handler($path = NULL, $deliver = TRUE) { // Allow other modules to change the site status but not the path because that // would not change the global variable. hook_url_inbound_alter() can be used // to change the path. Code later will not use the $read_only_path variable. - $read_only_path = !empty($path) ? $path : $_GET['q']; + $read_only_path = !empty($path) ? $path : current_path(); drupal_alter('menu_site_status', $page_callback_result, $read_only_path); // Only continue if the site status is not set. @@ -1043,11 +1043,11 @@ function menu_tree_output($tree) { $class[] = 'active-trail'; $data['link']['localized_options']['attributes']['class'][] = 'active-trail'; } - // Normally, l() compares the href of every link with $_GET['q'] and sets - // the active class accordingly. But local tasks do not appear in menu + // Normally, l() compares the href of every link with the current path and + // sets the active class accordingly. But local tasks do not appear in menu // trees, so if the current path is a local task, and this link is its // tab root, then we have to set the class manually. - if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) { + if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != current_path()) { $data['link']['localized_options']['attributes']['class'][] = 'active'; } @@ -1846,11 +1846,11 @@ function menu_navigation_links($menu_name, $level = 0) { $class = ' active-trail'; $l['attributes']['class'][] = 'active-trail'; } - // Normally, l() compares the href of every link with $_GET['q'] and sets - // the active class accordingly. But local tasks do not appear in menu - // trees, so if the current path is a local task, and this link is its - // tab root, then we have to set the class manually. - if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != $_GET['q']) { + // Normally, l() compares the href of every link with the current path and + // sets the active class accordingly. But local tasks do not appear in + // menu trees, so if the current path is a local task, and this link is + // its tab root, then we have to set the class manually. + if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != current_path()) { $l['attributes']['class'][] = 'active'; } // Keyed with the unique mlid to generate classes in theme_links(). @@ -1964,8 +1964,8 @@ function menu_local_tasks($level = 0) { // local tasks link to their parent, but the path of default local // tasks can still be accessed directly, in which case this link // would not be marked as active, since l() only compares the href - // with $_GET['q']. - if ($link['href'] != $_GET['q']) { + // with current_path(). + if ($link['href'] != current_path()) { $link['localized_options']['attributes']['class'][] = 'active'; } $tabs_current[] = array( @@ -2040,8 +2040,8 @@ function menu_local_tasks($level = 0) { // Mark the link as active, if the current path is a (second-level) // local task of a default local task. Since this default local task // links to its parent, l() will not mark it as active, as it only - // compares the link's href to $_GET['q']. - if ($link['href'] != $_GET['q']) { + // compares the link's href to current_path(). + if ($link['href'] != current_path()) { $link['localized_options']['attributes']['class'][] = 'active'; } $tabs_current[] = array( @@ -2304,10 +2304,11 @@ function menu_get_active_menu_names() { * A Drupal path - not a path alias. */ function menu_set_active_item($path) { - $_GET['q'] = $path; // Since the active item has changed, the active menu trail may also be out // of date. drupal_static_reset('menu_set_active_trail'); + // @todo Refactor to use the Symfony Request object. + _current_path($path); } /** @@ -2421,7 +2422,7 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) { $preferred_links = &drupal_static(__FUNCTION__); if (!isset($path)) { - $path = $_GET['q']; + $path = current_path(); } if (empty($selected_menu)) { @@ -3813,7 +3814,7 @@ function _menu_site_is_offline($check_only = FALSE) { // Ensure that the maintenance mode message is displayed only once // (allowing for page redirects) and specifically suppress its display on // the maintenance mode settings page. - if (!$check_only && $_GET['q'] != 'admin/config/development/maintenance') { + if (!$check_only && current_path() != 'admin/config/development/maintenance') { if (user_access('administer site configuration')) { drupal_set_message(t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => url('admin/config/development/maintenance'))), 'status', FALSE); } diff --git a/core/includes/pager.inc b/core/includes/pager.inc index c579e7e64809..201c5ad6f213 100644 --- a/core/includes/pager.inc +++ b/core/includes/pager.inc @@ -297,7 +297,7 @@ function pager_default_initialize($total, $limit, $element = 0) { function pager_get_query_parameters() { $query = &drupal_static(__FUNCTION__); if (!isset($query)) { - $query = drupal_get_query_parameters($_GET, array('q', 'page')); + $query = drupal_get_query_parameters($_GET, array('page')); } return $query; } @@ -638,7 +638,7 @@ function theme_pager_link($variables) { // none of the pager links is active at any time - but it should still be // possible to use l() here. // @see http://drupal.org/node/1410574 - $attributes['href'] = url($_GET['q'], array('query' => $query)); + $attributes['href'] = url(current_path(), array('query' => $query)); return '<a' . drupal_attributes($attributes) . '>' . check_plain($text) . '</a>'; } diff --git a/core/includes/path.inc b/core/includes/path.inc index d6a0201fbe8c..0c7e4d40ff0a 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -10,15 +10,24 @@ */ /** - * Initialize the $_GET['q'] variable to the proper normal path. + * Initializes the current path to the proper normal path. */ function drupal_path_initialize() { - // Ensure $_GET['q'] is set before calling drupal_normal_path(), to support - // path caching with hook_url_inbound_alter(). - if (empty($_GET['q'])) { - $_GET['q'] = variable_get('site_frontpage', 'user'); + // At this point, the current path is either the request path (due to + // drupal_environment_initialize()) or some modified version of it due to + // other bootstrap code (e.g., language negotiation), but it has not yet been + // normalized by drupal_get_normal_path(). + $path = _current_path(); + + // If on the front page, resolve to the front page path, including for calls + // to current_path() while drupal_get_normal_path() is in progress. + if (empty($path)) { + $path = variable_get('site_frontpage', 'user'); + _current_path($path); } - $_GET['q'] = drupal_get_normal_path($_GET['q']); + + // Normalize the path. + _current_path(drupal_get_normal_path($path)); } /** @@ -234,7 +243,7 @@ function drupal_cache_system_paths() { function drupal_get_path_alias($path = NULL, $langcode = NULL) { // If no path is specified, use the current page's path. if ($path == NULL) { - $path = $_GET['q']; + $path = current_path(); } $result = $path; if ($alias = drupal_lookup_path('alias', $path, $langcode)) { @@ -289,9 +298,7 @@ function drupal_is_front_page() { $is_front_page = &$drupal_static_fast['is_front_page']; if (!isset($is_front_page)) { - // As drupal_path_initialize updates $_GET['q'] with the 'site_frontpage' path, - // we can check it against the 'site_frontpage' variable. - $is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'user')); + $is_front_page = (current_path() == variable_get('site_frontpage', 'user')); } return $is_front_page; @@ -340,9 +347,9 @@ function drupal_match_path($path, $patterns) { * - http://example.com/path/alias (which is a path alias for node/306) returns * "node/306" as opposed to the path alias. * - * This function is not available in hook_boot() so use $_GET['q'] instead. + * This function is not available in hook_boot() so use request_path() instead. * However, be careful when doing that because in the case of Example #3 - * $_GET['q'] will contain "path/alias". If "node/306" is needed, calling + * request_path() will contain "path/alias". If "node/306" is needed, calling * drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) makes this function available. * * @return @@ -351,7 +358,7 @@ function drupal_match_path($path, $patterns) { * @see request_path() */ function current_path() { - return $_GET['q']; + return _current_path(); } /** diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc index 3c70b965c30a..a900a612fe73 100644 --- a/core/includes/tablesort.inc +++ b/core/includes/tablesort.inc @@ -150,7 +150,7 @@ function tablesort_header($cell, $header, $ts) { $ts['sort'] = 'asc'; $image = ''; } - $cell['data'] = l($cell['data'] . $image, $_GET['q'], array('attributes' => array('title' => $title), 'query' => array_merge($ts['query'], array('sort' => $ts['sort'], 'order' => $cell['data'])), 'html' => TRUE)); + $cell['data'] = l($cell['data'] . $image, current_path(), array('attributes' => array('title' => $title), 'query' => array_merge($ts['query'], array('sort' => $ts['sort'], 'order' => $cell['data'])), 'html' => TRUE)); unset($cell['field'], $cell['sort']); } @@ -193,7 +193,7 @@ function tablesort_cell($cell, $header, $ts, $i) { * page request except for those pertaining to table sorting. */ function tablesort_get_query_parameters() { - return drupal_get_query_parameters($_GET, array('q', 'sort', 'order')); + return drupal_get_query_parameters($_GET, array('sort', 'order')); } /** diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 99e872ed8544..aadafd8c08e9 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1743,7 +1743,7 @@ function theme_links($variables) { // Handle links. if (isset($link['href'])) { - $is_current_path = ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page())); + $is_current_path = ($link['href'] == current_path() || ($link['href'] == '<front>' && drupal_is_front_page())); $is_current_language = (empty($link['language']) || $link['language']->langcode == $language_url->langcode); if ($is_current_path && $is_current_language) { $class[] = 'active'; diff --git a/core/misc/ajax.js b/core/misc/ajax.js index c35241c94d82..072cd2bf6603 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -115,16 +115,12 @@ Drupal.ajax = function (base, element, element_settings) { // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let // the server detect when it needs to degrade gracefully. - // There are five scenarios to check for: + // There are four scenarios to check for: // 1. /nojs/ // 2. /nojs$ - The end of a URL string. - // 3. /nojs? - Followed by a query (with clean URLs enabled). - // E.g.: path/nojs?destination=foobar - // 4. /nojs& - Followed by a query (without clean URLs enabled). - // E.g.: ?q=path/nojs&destination=foobar - // 5. /nojs# - Followed by a fragment. - // E.g.: path/nojs#myfragment - this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1'); + // 3. /nojs? - Followed by a query (e.g. path/nojs?destination=foobar). + // 4. /nojs# - Followed by a fragment (e.g.: path/nojs#myfragment). + this.url = element_settings.url.replace(/\/nojs(\/|$|\?|#)/g, '/ajax$1'); this.wrapper = '#' + element_settings.wrapper; // If there isn't a form, jQuery.ajax() will be used instead, allowing us to diff --git a/core/misc/drupal.js b/core/misc/drupal.js index c7917b07e54b..5bbbf511023e 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -201,6 +201,13 @@ Drupal.t = function (str, args, options) { return str; }; +/** + * Returns the URL to a Drupal page. + */ +Drupal.url = function (path) { + return Drupal.settings.basePath + Drupal.settings.scriptPath + path; +} + /** * Format a string containing a count of items. * diff --git a/core/misc/timezone.js b/core/misc/timezone.js index 62b7d4b0219a..6f82bc1d3eae 100644 --- a/core/misc/timezone.js +++ b/core/misc/timezone.js @@ -50,8 +50,8 @@ Drupal.behaviors.setTimezone = { var element = this; $.ajax({ async: false, - url: settings.basePath, - data: { q: path, date: dateString }, + url: Drupal.url(path), + data: { date: dateString }, dataType: 'json', success: function (data) { if (data) { diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 488904ca182f..2bfd7653b9c1 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -836,13 +836,10 @@ function block_block_list_alter(&$blocks) { // with different case. Ex: /Page, /page, /PAGE. $pages = drupal_strtolower($block->pages); if ($block->visibility < BLOCK_VISIBILITY_PHP) { - // Convert the Drupal path to lowercase - $path = drupal_strtolower(drupal_get_path_alias($_GET['q'])); - // Compare the lowercase internal and lowercase path alias (if any). - $page_match = drupal_match_path($path, $pages); - if ($path != $_GET['q']) { - $page_match = $page_match || drupal_match_path($_GET['q'], $pages); - } + // Compare the lowercase path alias (if any) and internal path. + $path = current_path(); + $path_alias = drupal_strtolower(drupal_get_path_alias($path)); + $page_match = drupal_match_path($path_alias, $pages) || (($path != $path_alias) && drupal_match_path($path, $pages)); // When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED), // the block is displayed on all pages except those listed in $block->pages. // When set to 1 (BLOCK_VISIBILITY_LISTED), it is displayed only on those diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 03029131b1e2..c43e72540f2b 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -500,12 +500,10 @@ function comment_permalink($cid) { // Find the current display page for this comment. $page = comment_get_display_page($comment->cid, $node->type); - // Set $_GET['q'] and $_GET['page'] ourselves so that the node callback - // behaves as it would when visiting the page directly. - $_GET['q'] = 'node/' . $node->nid; - $_GET['page'] = $page; - // Return the node view, this will show the correct comment in context. + // @todo Refactor to use Symfony's Request object. + _current_path('node/' . $node->nid); + $_GET['page'] = $page; return menu_execute_active_handler('node/' . $node->nid, FALSE); } drupal_not_found(); diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index c695c7e2eaf3..48c12d90f615 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -173,7 +173,7 @@ function contact_mail($key, &$message, $params) { '!site-name' => variable_get('site_name', 'Drupal'), '!subject' => $params['subject'], '!category' => isset($params['category']['category']) ? $params['category']['category'] : '', - '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), + '!form-url' => url(current_path(), array('absolute' => TRUE, 'language' => $language)), '!sender-name' => user_format_name($params['sender']), '!sender-url' => $params['sender']->uid ? url('user/' . $params['sender']->uid, array('absolute' => TRUE, 'language' => $language)) : $params['sender']->mail, ); diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 9e13c85735c9..8fd8ceeb6991 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -869,10 +869,10 @@ function image_style_url($style_name, $path) { $uri = image_style_path($style_name, $path); // If not using clean URLs, the image derivative callback is only available - // with the query string. If the file does not exist, use url() to ensure + // with the script path. If the file does not exist, use url() to ensure // that it is included. Once the file exists it's fine to fall back to the // actual file path, this avoids bootstrapping PHP once the files are built. - if (!variable_get('clean_url') && file_uri_scheme($uri) == 'public' && !file_exists($uri)) { + if ($GLOBALS['script_path'] && file_uri_scheme($uri) == 'public' && !file_exists($uri)) { $directory_path = file_stream_wrapper_get_instance_by_uri($uri)->getDirectoryPath(); return url($directory_path . '/' . file_uri_target($uri), array('absolute' => TRUE)); } diff --git a/core/modules/image/image.test b/core/modules/image/image.test index d3b3374d1a9a..ff783be31188 100644 --- a/core/modules/image/image.test +++ b/core/modules/image/image.test @@ -184,10 +184,12 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase { * Test image_style_url(). */ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE) { + $script_path_original = $GLOBALS['script_path']; + $GLOBALS['script_path'] = $clean_url ? '' : 'index.php/'; + // Make the default scheme neither "public" nor "private" to verify the // functions work for other than the default scheme. variable_set('file_default_scheme', 'temporary'); - variable_set('clean_url', $clean_url); // Create the directories for the styles. $directory = $scheme . '://styles/' . $this->style_name; @@ -209,8 +211,8 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase { $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.')); $generate_url = image_style_url($this->style_name, $original_uri); - if (!$clean_url) { - $this->assertTrue(strpos($generate_url, '?q=') !== FALSE, 'When using non-clean URLS, the system path contains the query string.'); + if ($GLOBALS['script_path']) { + $this->assertTrue(strpos($generate_url, $GLOBALS['script_path']) !== FALSE, 'When using non-clean URLS, the system path contains the script name.'); } // Fetch the URL that generates the file. @@ -224,6 +226,8 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase { if ($scheme == 'private') { $this->assertEqual($this->drupalGetHeader('X-Image-Owned-By'), 'image_module_test', t('Expected custom header has been added.')); } + + $GLOBALS['script_path'] = $script_path_original; } } diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index b05a1306e967..c124b9e32b52 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -679,7 +679,7 @@ function language_negotiation_configure_url_form($form, &$form_state) { '#title' => t('%language (%langcode) path prefix', array('%language' => $language->name, '%langcode' => $language->langcode)), '#maxlength' => 64, '#default_value' => isset($prefixes[$langcode]) ? $prefixes[$langcode] : '', - '#field_prefix' => $base_url . '/' . (variable_get('clean_url', 0) ? '' : '?q='), + '#field_prefix' => $base_url . '/', ); $form['domain'][$langcode] = array( '#type' => 'textfield', diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 63b3743e9638..c7d6f1822d21 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -463,7 +463,7 @@ function language_block_info() { */ function language_block_view($type) { if (language_multilingual()) { - $path = drupal_is_front_page() ? '<front>' : $_GET['q']; + $path = drupal_is_front_page() ? '<front>' : current_path(); $links = language_negotiation_get_switch_links($type, $path); if (isset($links->links)) { diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index 6269e8b203e6..4d560e7d361d 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -209,9 +209,11 @@ function language_from_url($languages) { switch (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX)) { case LANGUAGE_NEGOTIATION_URL_PREFIX: - // $_GET['q'] might not be available at this time, because path - // initialization runs after the language bootstrap phase. - list($language, $_GET['q']) = language_url_split_prefix(isset($_GET['q']) ? $_GET['q'] : NULL, $languages); + // Language negotiation happens before the public function current_path() + // is available. + // @todo Refactor with Symfony's Request object. + list($language, $path) = language_url_split_prefix(_current_path(), $languages); + _current_path($path); if ($language !== FALSE) { $language_url = $language->langcode; } @@ -319,7 +321,6 @@ function language_switcher_session($type, $path) { $links = array(); $query = $_GET; - unset($query['q']); foreach ($languages as $language) { $langcode = $language->langcode; diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 4351342604e6..357166035b8c 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -197,7 +197,7 @@ function locale_init() { // in $conf. This should happen on all pages except the date and time formats // settings page, where we want to display the site default and not the // localized version. - if (strpos($_GET['q'], 'admin/config/regional/date-time/formats') !== 0) { + if (strpos(current_path(), 'admin/config/regional/date-time/formats') !== 0) { $languages = array($language_interface->langcode); // Setup appropriate date formats for this locale. diff --git a/core/modules/locale/locale.test b/core/modules/locale/locale.test index fa78e146860d..ded11ef68be2 100644 --- a/core/modules/locale/locale.test +++ b/core/modules/locale/locale.test @@ -2181,7 +2181,7 @@ class LocalePathFunctionalTest extends DrupalWebTestCase { // Test that both node titles link to our path alias. $this->drupalGet('<front>'); - $custom_path_url = base_path() . (variable_get('clean_url', 0) ? $custom_path : '?q=' . $custom_path); + $custom_path_url = base_path() . $GLOBALS['script_path'] . $custom_path; $elements = $this->xpath('//a[@href=:href and .=:title]', array(':href' => $custom_path_url, ':title' => $first_node->title)); $this->assertTrue(!empty($elements), t('First node links to the path alias.')); $elements = $this->xpath('//a[@href=:href and .=:title]', array(':href' => $custom_path_url, ':title' => $second_node->title)); @@ -2651,7 +2651,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { // Check that the language switcher active link matches the given browser // language. - $args = array(':url' => base_path() . (!empty($GLOBALS['conf']['clean_url']) ? $langcode_browser_fallback : "?q=$langcode_browser_fallback")); + $args = array(':url' => base_path() . $GLOBALS['script_path'] . $langcode_browser_fallback); $fields = $this->xpath('//div[@id="block-language-language-interface"]//a[@class="language-link active" and starts-with(@href, :url)]', $args); $this->assertTrue($fields[0] == $languages[$langcode_browser_fallback]->name, t('The browser language is the URL active language')); @@ -2686,21 +2686,21 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { ); $this->drupalPost('admin/config/regional/language/detection/url', $edit, t('Save configuration')); - // Build the link we're going to test based on the clean url setting. - $link = (!empty($GLOBALS['conf']['clean_url'])) ? 'it.example.com/admin' : 'it.example.com/?q=admin'; + // Build the link we're going to test. + $link = 'it.example.com/admin'; global $is_https; - // Test URL in another language: http://it.example.com/?q=admin. + // Test URL in another language: http://it.example.com/admin. // Base path gives problems on the testbot, so $correct_link is hard-coded. // @see UrlAlterFunctionalTest::assertUrlOutboundAlter (path.test). - $italian_url = url('admin', array('language' => $languages['it'])); + $italian_url = url('admin', array('language' => $languages['it'], 'script' => '')); $url_scheme = ($is_https) ? 'https://' : 'http://'; $correct_link = $url_scheme . $link; $this->assertTrue($italian_url == $correct_link, t('The url() function returns the right url (@url) in accordance with the chosen language', array('@url' => $italian_url))); // Test https via options. variable_set('https', TRUE); - $italian_url = url('admin', array('https' => TRUE, 'language' => $languages['it'])); + $italian_url = url('admin', array('https' => TRUE, 'language' => $languages['it'], 'script' => '')); $correct_link = 'https://' . $link; $this->assertTrue($italian_url == $correct_link, t('The url() function returns the right https url (via options) (@url) in accordance with the chosen language', array('@url' => $italian_url))); variable_set('https', FALSE); @@ -2708,7 +2708,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { // Test https via current url scheme. $temp_https = $is_https; $is_https = TRUE; - $italian_url = url('admin', array('language' => $languages['it'])); + $italian_url = url('admin', array('language' => $languages['it'], 'script' => '')); $correct_link = 'https://' . $link; $this->assertTrue($italian_url == $correct_link, t('The url() function returns the right url (via current url scheme) (@url) in accordance with the chosen language', array('@url' => $italian_url))); $is_https = $temp_https; @@ -2767,9 +2767,9 @@ class LocaleUrlRewritingTest extends DrupalWebTestCase { * is actually not working. */ private function checkUrl($language, $message1, $message2) { - $options = array('language' => $language); + $options = array('language' => $language, 'script' => ''); $base_path = trim(base_path(), '/'); - $rewritten_path = trim(str_replace(array('?q=', $base_path), '', url('node', $options)), '/'); + $rewritten_path = trim(str_replace($base_path, '', url('node', $options)), '/'); $segments = explode('/', $rewritten_path, 2); $prefix = $segments[0]; $path = isset($segments[1]) ? $segments[1] : $prefix; diff --git a/core/modules/menu/menu.admin.js b/core/modules/menu/menu.admin.js index 4e5bf0776380..42d69d533e12 100644 --- a/core/modules/menu/menu.admin.js +++ b/core/modules/menu/menu.admin.js @@ -22,9 +22,8 @@ Drupal.menu_update_parent_list = function () { values.push(Drupal.checkPlain($.trim($(this).val()))); }); - var url = Drupal.settings.basePath + 'admin/structure/menu/parents'; $.ajax({ - url: location.protocol + '//' + location.host + url, + url: location.protocol + '//' + location.host + Drupal.url('admin/structure/menu/parents'), type: 'POST', data: {'menus[]' : values}, dataType: 'json', diff --git a/core/modules/openid/tests/openid_test.module b/core/modules/openid/tests/openid_test.module index 5bd2f4ddf5bc..ac49dbd3d32a 100644 --- a/core/modules/openid/tests/openid_test.module +++ b/core/modules/openid/tests/openid_test.module @@ -94,19 +94,8 @@ function openid_test_yadis_xrds() { // Only respond to XRI requests for one specific XRI. The is used to verify // that the XRI has been properly encoded. The "+" sign in the _xrd_r query // parameter is decoded to a space by PHP. - if (arg(3) == 'xri') { - if (variable_get('clean_url', 0)) { - if (arg(4) != '@example*résumé;%25' || $_GET['_xrd_r'] != 'application/xrds xml') { - drupal_not_found(); - } - } - else { - // Drupal cannot properly emulate an XRI proxy resolver using unclean - // URLs, so the arguments gets messed up. - if (arg(4) . '/' . arg(5) != '@example*résumé;%25?_xrd_r=application/xrds xml') { - drupal_not_found(); - } - } + if (arg(3) == 'xri' && (arg(4) != '@example*résumé;%25' || $_GET['_xrd_r'] != 'application/xrds xml')) { + drupal_not_found(); } drupal_add_http_header('Content-Type', 'application/xrds+xml'); print '<?xml version="1.0" encoding="UTF-8"?> diff --git a/core/modules/overlay/overlay-parent.js b/core/modules/overlay/overlay-parent.js index 19d2d649a71a..aa90d9bb5069 100644 --- a/core/modules/overlay/overlay-parent.js +++ b/core/modules/overlay/overlay-parent.js @@ -569,7 +569,7 @@ Drupal.overlay.eventhandlerOverrideLink = function (event) { // If the link contains the overlay-restore class and the overlay-context // state is set, also update the parent window's location. var parentLocation = ($target.hasClass('overlay-restore') && typeof $.bbq.getState('overlay-context') == 'string') - ? Drupal.settings.basePath + $.bbq.getState('overlay-context') + ? Drupal.url($.bbq.getState('overlay-context')) : null; href = this.fragmentizeLink($target.get(0), parentLocation); // Only override default behavior when left-clicking and user is not @@ -653,10 +653,10 @@ Drupal.overlay.eventhandlerOperateByURLFragment = function (event) { if (state) { // Append render variable, so the server side can choose the right // rendering and add child frame code to the page if needed. - var url = $.param.querystring(Drupal.settings.basePath + state, { render: 'overlay' }); + var url = $.param.querystring(Drupal.url(state), { render: 'overlay' }); this.open(url); - this.resetActiveClass(this.getPath(Drupal.settings.basePath + state)); + this.resetActiveClass(this.getPath(url)); } // If there is no overlay URL in the fragment and the overlay is (still) // open, close the overlay. @@ -688,7 +688,7 @@ Drupal.overlay.eventhandlerSyncURLFragment = function (event) { if (this.isOpen) { var expected = $.bbq.getState('overlay'); // This is just a sanity check, so we're comparing paths, not query strings. - if (this.getPath(Drupal.settings.basePath + expected) != this.getPath(this.iframeWindow.document.location)) { + if (this.getPath(Drupal.url(expected)) != this.getPath(this.iframeWindow.document.location)) { // There may have been a redirect inside the child overlay window that the // parent wasn't aware of. Update the parent URL fragment appropriately. var newLocation = Drupal.overlay.fragmentizeLink(this.iframeWindow.document.location); @@ -752,10 +752,8 @@ Drupal.overlay.fragmentizeLink = function (link, parentLocation) { return link.href; } - // Determine the link's original destination. Set ignorePathFromQueryString to - // true to prevent transforming this link into a clean URL while clean URLs - // may be disabled. - var path = this.getPath(link, true); + // Determine the link's original destination. + var path = this.getPath(link); // Preserve existing query and fragment parameters in the URL, except for // "render=overlay" which is re-added in Drupal.overlay.eventhandlerOperateByURLFragment. var destination = path + link.search.replace(/&?render=overlay/, '').replace(/\?$/, '') + link.hash; @@ -783,7 +781,7 @@ Drupal.overlay.refreshRegions = function (data) { (function (regionName, regionSelector) { var $region = $(regionSelector); Drupal.detachBehaviors($region); - $.get(Drupal.settings.basePath + Drupal.settings.overlay.ajaxCallback + '/' + regionName, function (newElement) { + $.get(Drupal.url(Drupal.settings.overlay.ajaxCallback + '/' + regionName), function (newElement) { $region.replaceWith($(newElement)); Drupal.attachBehaviors($region, Drupal.settings); }); @@ -827,13 +825,11 @@ Drupal.overlay.resetActiveClass = function(activePath) { * * @param link * Link object or string to get the Drupal path from. - * @param ignorePathFromQueryString - * Boolean whether to ignore path from query string if path appears empty. * * @return * The Drupal path. */ -Drupal.overlay.getPath = function (link, ignorePathFromQueryString) { +Drupal.overlay.getPath = function (link) { if (typeof link == 'string') { // Create a native Link object, so we can use its object methods. link = $(link.link(link)).get(0); @@ -844,15 +840,7 @@ Drupal.overlay.getPath = function (link, ignorePathFromQueryString) { if (path.charAt(0) != '/') { path = '/' + path; } - path = path.replace(new RegExp(Drupal.settings.basePath + '(?:index.php)?'), ''); - if (path == '' && !ignorePathFromQueryString) { - // If the path appears empty, it might mean the path is represented in the - // query string (clean URLs are not used). - var match = new RegExp('([?&])q=(.+)([&#]|$)').exec(link.search); - if (match && match.length == 4) { - path = match[2]; - } - } + path = path.replace(new RegExp(Drupal.settings.basePath + Drupal.settings.scriptPath), ''); return path; }; diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index e2ecd19144a8..271f15dd5a97 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -143,7 +143,7 @@ function overlay_init() { // If this page shouldn't be rendered inside the overlay, redirect to the // parent. elseif (!path_is_admin($current_path)) { - overlay_close_dialog($current_path, array('query' => drupal_get_query_parameters(NULL, array('q', 'render')))); + overlay_close_dialog($current_path, array('query' => drupal_get_query_parameters(NULL, array('render')))); } // Indicate that we are viewing an overlay child page. diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc index 9e22cffd3187..d45ba59a4fc5 100644 --- a/core/modules/path/path.admin.inc +++ b/core/modules/path/path.admin.inc @@ -129,7 +129,7 @@ function path_admin_form($form, &$form_state, $path = array('source' => '', 'ali '#maxlength' => 255, '#size' => 45, '#description' => t('Specify the existing path you wish to alias. For example: node/28, forum/1, taxonomy/term/1.'), - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), + '#field_prefix' => url(NULL, array('absolute' => TRUE)), '#required' => TRUE, ); $form['alias'] = array( @@ -139,7 +139,7 @@ function path_admin_form($form, &$form_state, $path = array('source' => '', 'ali '#maxlength' => 255, '#size' => 45, '#description' => t('Specify an alternative path by which this data can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'), - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), + '#field_prefix' => url(NULL, array('absolute' => TRUE)), '#required' => TRUE, ); diff --git a/core/modules/search/search.module b/core/modules/search/search.module index 9a6a11adac0f..4e761505557f 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -239,7 +239,7 @@ function search_menu() { } /** - * Determines access for the ?q=search path. + * Determines access for the 'search' path. */ function search_is_active() { // This path cannot be accessed if there are no active modules. diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc index 75c12b404d69..9010f9063229 100644 --- a/core/modules/shortcut/shortcut.admin.inc +++ b/core/modules/shortcut/shortcut.admin.inc @@ -489,7 +489,7 @@ function _shortcut_link_form_elements($shortcut_link = NULL) { '#title' => t('Path'), '#size' => 40, '#maxlength' => 255, - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), + '#field_prefix' => url(NULL, array('absolute' => TRUE)), '#default_value' => $shortcut_link['link_path'], ); diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index aa43503da346..73b63850eaee 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -657,7 +657,7 @@ function shortcut_preprocess_page(&$variables) { // we do not want to display it on "access denied" or "page not found" // pages). if (shortcut_set_edit_access() && ($item = menu_get_item()) && $item['access']) { - $link = $_GET['q']; + $link = current_path(); $query_parameters = drupal_get_query_parameters(); if (!empty($query_parameters)) { $link .= '?' . drupal_http_build_query($query_parameters); diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php index 540dc0e9385a..4a01cdef9942 100644 --- a/core/modules/simpletest/drupal_web_test_case.php +++ b/core/modules/simpletest/drupal_web_test_case.php @@ -1318,7 +1318,6 @@ protected function setUp() { $this->originalConfigSignatureKey = $GLOBALS['config_signature_key']; $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); $this->originalProfile = drupal_get_profile(); - $clean_url_original = variable_get('clean_url', 0); // Set to English to prevent exceptions from utf8_truncate() from t() // during install if the current language is not 'en'. @@ -1435,7 +1434,6 @@ protected function setUp() { // Restore necessary variables. variable_set('install_task', 'done'); - variable_set('clean_url', $clean_url_original); variable_set('site_mail', 'simpletest@example.com'); variable_set('date_default_timezone', date_default_timezone_get()); // Set up English language. diff --git a/core/modules/simpletest/simpletest.test b/core/modules/simpletest/simpletest.test index 4cecbe6b8afd..185a71ab55cf 100644 --- a/core/modules/simpletest/simpletest.test +++ b/core/modules/simpletest/simpletest.test @@ -341,8 +341,6 @@ class SimpleTestBrowserTestCase extends DrupalWebTestCase { * Test DrupalWebTestCase::getAbsoluteUrl(). */ function testGetAbsoluteUrl() { - // Testbed runs with Clean URLs disabled, so disable it here. - variable_set('clean_url', 0); $url = 'user/login'; $this->drupalGet($url); diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index 69d5f5be38fc..654621dbc453 100644 --- a/core/modules/statistics/statistics.module +++ b/core/modules/statistics/statistics.module @@ -67,7 +67,9 @@ function statistics_exit() { db_insert('accesslog') ->fields(array( 'title' => truncate_utf8(strip_tags(drupal_get_title()), 255), - 'path' => truncate_utf8($_GET['q'], 255), + // @todo The public function current_path() is not available on a cache + // hit. + 'path' => truncate_utf8(_current_path(), 255), 'url' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', 'hostname' => ip_address(), 'uid' => $user->uid, diff --git a/core/modules/statistics/statistics.test b/core/modules/statistics/statistics.test index 6f19e37f8bfe..331476174b1d 100644 --- a/core/modules/statistics/statistics.test +++ b/core/modules/statistics/statistics.test @@ -152,8 +152,13 @@ class StatisticsLoggingTestCase extends DrupalWebTestCase { $this->assertTrue(is_array($log) && count($log) == 7, t('Page request was logged.')); $this->assertEqual(array_intersect_key($log[6], $expected), $expected); - // Create a path longer than 255 characters. - $long_path = $this->randomName(256); + // Create a path longer than 255 characters. Drupal's .htaccess file + // instructs Apache to test paths against the file system before routing to + // index.php. Many file systems restrict file names to 255 characters + // (http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits), and + // Apache returns a 403 when testing longer file names, but the total path + // length is not restricted. + $long_path = $this->randomName(127) . '/' . $this->randomName(128); // Test that the long path is properly truncated when logged. $this->drupalGet($long_path); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index aac0c3dded21..9619461d3033 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -1494,7 +1494,7 @@ function system_site_information_settings() { '#default_value' => (variable_get('site_frontpage') != 'user' ? drupal_get_path_alias(variable_get('site_frontpage', 'user')) : ''), '#size' => 40, '#description' => t('Optionally, specify a relative URL to display as the front page. Leave blank to display the default content feed.'), - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), + '#field_prefix' => url(NULL, array('absolute' => TRUE)), ); $form['front_page']['default_nodes_main'] = array( '#type' => 'select', '#title' => t('Number of posts on front page'), @@ -1513,7 +1513,7 @@ function system_site_information_settings() { '#default_value' => variable_get('site_403', ''), '#size' => 40, '#description' => t('This page is displayed when the requested document is denied to the current user. Leave blank to display a generic "access denied" page.'), - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=') + '#field_prefix' => url(NULL, array('absolute' => TRUE)), ); $form['error_page']['site_404'] = array( '#type' => 'textfield', @@ -1521,7 +1521,7 @@ function system_site_information_settings() { '#default_value' => variable_get('site_404', ''), '#size' => 40, '#description' => t('This page is displayed when no other content matches the requested document. Leave blank to display a generic "page not found" page.'), - '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=') + '#field_prefix' => url(NULL, array('absolute' => TRUE)), ); $form['#validate'][] = 'system_site_information_settings_validate'; @@ -2205,96 +2205,6 @@ function system_site_maintenance_mode() { return system_settings_form($form); } -/** - * Form builder; Configure clean URL settings. - * - * @ingroup forms - * @see system_settings_form() - */ -function system_clean_url_settings($form, &$form_state) { - $available = FALSE; - $conflict = FALSE; - - // If the request URI is a clean URL, clean URLs must be available. - // Otherwise, run a test. - if (strpos(request_uri(), '?q=') === FALSE && strpos(request_uri(), '&q=') === FALSE) { - $available = TRUE; - } - else { - $request = drupal_http_request($GLOBALS['base_url'] . '/admin/config/search/clean-urls/check'); - // If the request returns HTTP 200, clean URLs are available. - if (isset($request->code) && $request->code == 200) { - $available = TRUE; - // If the user started the clean URL test, provide explicit feedback. - if (isset($form_state['input']['clean_url_test_execute'])) { - drupal_set_message(t('The clean URL test passed.')); - } - } - else { - // If the test failed while clean URLs are enabled, make sure clean URLs - // can be disabled. - if (variable_get('clean_url', 0)) { - $conflict = TRUE; - // Warn the user of a conflicting situation, unless after processing - // a submitted form. - if (!isset($form_state['input']['op'])) { - drupal_set_message(t('Clean URLs are enabled, but the clean URL test failed. Uncheck the box below to disable clean URLs.'), 'warning'); - } - } - // If the user started the clean URL test, provide explicit feedback. - elseif (isset($form_state['input']['clean_url_test_execute'])) { - drupal_set_message(t('The clean URL test failed.'), 'warning'); - } - } - } - - // Show the enable/disable form if clean URLs are available or if the user - // must be able to resolve a conflicting setting. - if ($available || $conflict) { - $form['clean_url'] = array( - '#type' => 'checkbox', - '#title' => t('Enable clean URLs'), - '#default_value' => variable_get('clean_url', 0), - '#description' => t('Use URLs like <code>example.com/user</code> instead of <code>example.com/?q=user</code>.'), - ); - $form = system_settings_form($form); - if ($conflict) { - // $form_state['redirect'] needs to be set to the non-clean URL, - // otherwise the setting is not saved. - $form_state['redirect'] = url('', array('query' => array('q' => '/admin/config/search/clean-urls'))); - } - } - // Show the clean URLs test form. - else { - drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); - - $form_state['redirect'] = url('admin/config/search/clean-urls'); - $form['clean_url_description'] = array( - '#type' => 'markup', - '#markup' => '<p>' . t('Use URLs like <code>example.com/user</code> instead of <code>example.com/?q=user</code>.'), - ); - // Explain why the user is seeing this page and what to expect after - // clicking the 'Run the clean URL test' button. - $form['clean_url_test_result'] = array( - '#type' => 'markup', - '#markup' => '<p>' . t('Clean URLs cannot be enabled. If you are directed to this page or to a <em>Page not found (404)</em> error after testing for clean URLs, see the <a href="@handbook">online handbook</a>.', array('@handbook' => 'http://drupal.org/node/15365')) . '</p>', - ); - $form['actions'] = array( - '#type' => 'actions', - 'clean_url_test' => array( - '#type' => 'submit', - '#value' => t('Run the clean URL test'), - ), - ); - $form['clean_url_test_execute'] = array( - '#type' => 'hidden', - '#value' => 1, - ); - } - - return $form; -} - /** * Menu callback: displays the site status report. Can also be used as a pure check. * diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index c6e1288b9be4..15ffa2175695 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -497,7 +497,7 @@ function hook_page_build(&$page) { */ function hook_menu_get_item_alter(&$router_item, $path, $original_map) { // When retrieving the router item for the current path... - if ($path == $_GET['q']) { + if ($path == current_path()) { // ...call a function that prepares something for this request. mymodule_prepare_something(); } diff --git a/core/modules/system/system.cron.js b/core/modules/system/system.cron.js index af17dab52739..aa5b35113860 100644 --- a/core/modules/system/system.cron.js +++ b/core/modules/system/system.cron.js @@ -9,7 +9,7 @@ Drupal.behaviors.cronCheck = { $('body').once('cron-check', function() { // Only execute the cron check if its the right time. if (Math.round(new Date().getTime() / 1000.0) > settings.cronCheck) { - $.get(settings.basePath + 'system/run-cron-check'); + $.get(Drupal.url('system/run-cron-check')); } }); } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 51603ffe3c8d..f0e36cc3ceff 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -1848,6 +1848,13 @@ function system_update_8007() { } } +/** + * Remove the 'clean_url' configuration variable. + */ +function system_update_8008() { + variable_del('clean_url'); +} + /** * @} End of "defgroup updates-7.x-to-8.x" * The next series of updates should start at 9000. diff --git a/core/modules/system/system.js b/core/modules/system/system.js index 98da1a660767..ab00426b2024 100644 --- a/core/modules/system/system.js +++ b/core/modules/system/system.js @@ -19,55 +19,6 @@ Drupal.hideEmailAdministratorCheckbox = function () { }); }; -/** - * Internal function to check using Ajax if clean URLs can be enabled on the - * settings page. - * - * This function is not used to verify whether or not clean URLs - * are currently enabled. - */ -Drupal.behaviors.cleanURLsSettingsCheck = { - attach: function (context, settings) { - // This behavior attaches by ID, so is only valid once on a page. - // Also skip if we are on an install page, as Drupal.cleanURLsInstallCheck will handle - // the processing. - if (!($('#edit-clean-url').length) || $('#edit-clean-url.install').once('clean-url').length) { - return; - } - var url = settings.basePath + 'admin/config/search/clean-urls/check'; - $.ajax({ - url: location.protocol + '//' + location.host + url, - dataType: 'json', - success: function () { - // Check was successful. Redirect using a "clean URL". This will force the form that allows enabling clean URLs. - location = settings.basePath +"admin/config/search/clean-urls"; - } - }); - } -}; - -/** - * Internal function to check using Ajax if clean URLs can be enabled on the - * install page. - * - * This function is not used to verify whether or not clean URLs - * are currently enabled. - */ -Drupal.cleanURLsInstallCheck = function () { - var url = location.protocol + '//' + location.host + Drupal.settings.basePath + 'admin/config/search/clean-urls/check'; - // Submit a synchronous request to avoid database errors associated with - // concurrent requests during install. - $.ajax({ - async: false, - url: url, - dataType: 'json', - success: function () { - // Check was successful. - $('#edit-clean-url').attr('value', 1); - } - }); -}; - /** * When a field is filled out, apply its value to other fields that will likely * use the same value. In the installer this is used to populate the diff --git a/core/modules/system/system.maintenance.css b/core/modules/system/system.maintenance.css index 5543c2db816e..c6a5a4991510 100644 --- a/core/modules/system/system.maintenance.css +++ b/core/modules/system/system.maintenance.css @@ -46,10 +46,3 @@ ol.task-list li.active { font-weight: bold; } - -/** - * Installation clean URLs - */ -#clean-url.install { - display: none; -} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index dfb8936cd479..20afc296d6b4 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -88,7 +88,7 @@ function system_help($path, $arg) { $output .= '<dt>' . t('Performing system maintenance') . '</dt>'; $output .= '<dd>' . t('In order for the site and its modules to continue to operate well, a set of routine administrative operations must run on a regular basis. The System module manages this task by making use of a system cron job. You can verify the status of cron tasks by visiting the <a href="@status">Status report page</a>. For more information, see the online handbook entry for <a href="@handbook">configuring cron jobs</a>. You can set up cron job by visiting <a href="@cron">Cron configuration</a> page', array('@status' => url('admin/reports/status'), '@handbook' => 'http://drupal.org/cron', '@cron' => url('admin/config/system/cron'))) . '</dd>'; $output .= '<dt>' . t('Configuring basic site settings') . '</dt>'; - $output .= '<dd>' . t('The System module also handles basic configuration options for your site, including <a href="@date-time-settings">Date and time settings</a>, <a href="@file-system">File system settings</a>, <a href="@clean-url">Clean URL support</a>, <a href="@site-info">Site name and other information</a>, and a <a href="@maintenance-mode">Maintenance mode</a> for taking your site temporarily offline.', array('@date-time-settings' => url('admin/config/regional/date-time'), '@file-system' => url('admin/config/media/file-system'), '@clean-url' => url('admin/config/search/clean-urls'), '@site-info' => url('admin/config/system/site-information'), '@maintenance-mode' => url('admin/config/development/maintenance'))) . '</dd>'; + $output .= '<dd>' . t('The System module also handles basic configuration options for your site, including <a href="@date-time-settings">Date and time settings</a>, <a href="@file-system">File system settings</a>, <a href="@site-info">Site name and other information</a>, and a <a href="@maintenance-mode">Maintenance mode</a> for taking your site temporarily offline.', array('@date-time-settings' => url('admin/config/regional/date-time'), '@file-system' => url('admin/config/media/file-system'), '@site-info' => url('admin/config/system/site-information'), '@maintenance-mode' => url('admin/config/development/maintenance'))) . '</dd>'; $output .= '<dt>' . t('Configuring actions') . '</dt>'; $output .= '<dd>' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Other modules can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions. Visit the <a href="@actions">Actions page</a> to configure actions.', array('@actions' => url('admin/config/system/actions'))) . '</dd>'; $output .= '</dl>'; @@ -971,23 +971,6 @@ function system_menu() { 'access arguments' => array('access administration pages'), 'file' => 'system.admin.inc', ); - $items['admin/config/search/clean-urls'] = array( - 'title' => 'Clean URLs', - 'description' => 'Enable or disable clean URLs for your site.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_clean_url_settings'), - 'access arguments' => array('administer site configuration'), - 'file' => 'system.admin.inc', - 'weight' => 5, - ); - $items['admin/config/search/clean-urls/check'] = array( - 'title' => 'Clean URL check', - 'page callback' => 'drupal_json_output', - 'page arguments' => array(array('status' => TRUE)), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - 'file' => 'system.admin.inc', - ); // System settings. $items['admin/config/system'] = array( @@ -1850,8 +1833,7 @@ function system_authorized_get_url(array $options = array()) { global $base_url; // Force https if available, regardless of what the caller specifies. $options['https'] = TRUE; - // We prefix with $base_url so we get a full path even if clean URLs are - // disabled. + // Prefix with $base_url so url() treats it as an external link. return url($base_url . '/core/authorize.php', $options); } diff --git a/core/modules/system/system.test b/core/modules/system/system.test index 16348cc8203c..4fdad7172e1d 100644 --- a/core/modules/system/system.test +++ b/core/modules/system/system.test @@ -2896,10 +2896,7 @@ class SystemIndexPhpTest extends DrupalWebTestCase { $this->drupalGet($index_php, array('external' => TRUE)); $this->assertResponse(200, t('Make sure index.php returns a valid page.')); - $this->drupalGet($index_php, array('external' => TRUE, 'query' => array('q' => 'user'))); - $this->assertResponse(200, t('Make sure index.php?q=user returns a valid page.')); - $this->drupalGet($index_php .'/user', array('external' => TRUE)); - $this->assertResponse(404, t("Make sure index.php/user returns a 'page not found'.")); + $this->assertResponse(200, t("Make sure index.php/user returns a valid page.")); } } diff --git a/core/modules/system/tests/ajax.test b/core/modules/system/tests/ajax.test index 4f254f81f382..49f1632981bf 100644 --- a/core/modules/system/tests/ajax.test +++ b/core/modules/system/tests/ajax.test @@ -80,7 +80,7 @@ class AJAXFrameworkTestCase extends AJAXTestCase { // drupal_add_js(). $expected = array( 'command' => 'settings', - 'settings' => array('basePath' => base_path(), 'ajax' => 'test'), + 'settings' => array('ajax' => 'test'), ); $this->assertCommand($commands, $expected, t('ajax_render() loads settings added with drupal_add_js().')); diff --git a/core/modules/system/tests/common.test b/core/modules/system/tests/common.test index f0ac957ef22b..46b379ee799a 100644 --- a/core/modules/system/tests/common.test +++ b/core/modules/system/tests/common.test @@ -97,7 +97,7 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { * Tests for active class in l() function. */ function testLActiveClass() { - $link = l($this->randomName(), $_GET['q']); + $link = l($this->randomName(), current_path()); $this->assertTrue($this->hasClass($link, 'active'), t('Class @class is present on link to the current page', array('@class' => 'active'))); } @@ -106,7 +106,7 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { */ function testLCustomClass() { $class = $this->randomName(); - $link = l($this->randomName(), $_GET['q'], array('attributes' => array('class' => array($class)))); + $link = l($this->randomName(), current_path(), array('attributes' => array('class' => array($class)))); $this->assertTrue($this->hasClass($link, $class), t('Custom class @class is present on link when requested', array('@class' => $class))); $this->assertTrue($this->hasClass($link, 'active'), t('Class @class is present on link to the current page', array('@class' => 'active'))); } @@ -128,19 +128,8 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { ), ), 'c' => 3, - 'q' => 'foo/bar', ); - // Default arguments. - $result = $_GET; - unset($result['q']); - $this->assertEqual(drupal_get_query_parameters(), $result, t("\$_GET['q'] was removed.")); - - // Default exclusion. - $result = $original; - unset($result['q']); - $this->assertEqual(drupal_get_query_parameters($original), $result, t("'q' was removed.")); - // First-level exclusion. $result = $original; unset($result['b']); @@ -176,14 +165,21 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { * Test drupal_parse_url(). */ function testDrupalParseUrl() { - // Relative URL. - $url = 'foo/bar?foo=bar&bar=baz&baz#foo'; - $result = array( - 'path' => 'foo/bar', - 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''), - 'fragment' => 'foo', - ); - $this->assertEqual(drupal_parse_url($url), $result, t('Relative URL parsed correctly.')); + // Relative, absolute, and external URLs, without/with explicit script path, + // without/with Drupal path. + foreach (array('', '/', 'http://drupal.org/') as $absolute) { + foreach (array('', 'index.php/') as $script) { + foreach (array('', 'foo/bar') as $path) { + $url = $absolute . $script . $path . '?foo=bar&bar=baz&baz#foo'; + $expected = array( + 'path' => $absolute . $script . $path, + 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''), + 'fragment' => 'foo', + ); + $this->assertEqual(drupal_parse_url($url), $expected, t('URL parsed correctly.')); + } + } + } // Relative URL that is known to confuse parse_url(). $url = 'foo/bar:1'; @@ -194,47 +190,10 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { ); $this->assertEqual(drupal_parse_url($url), $result, t('Relative URL parsed correctly.')); - // Absolute URL. - $url = '/foo/bar?foo=bar&bar=baz&baz#foo'; - $result = array( - 'path' => '/foo/bar', - 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''), - 'fragment' => 'foo', - ); - $this->assertEqual(drupal_parse_url($url), $result, t('Absolute URL parsed correctly.')); - - // External URL testing. - $url = 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo'; - // Test that drupal can recognize an absolute URL. Used to prevent attack vectors. + $url = 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo'; $this->assertTrue(url_is_external($url), t('Correctly identified an external URL.')); - // Test the parsing of absolute URLs. - $result = array( - 'path' => 'http://drupal.org/foo/bar', - 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''), - 'fragment' => 'foo', - ); - $this->assertEqual(drupal_parse_url($url), $result, t('External URL parsed correctly.')); - - // Verify proper parsing of URLs when clean URLs are disabled. - $result = array( - 'path' => 'foo/bar', - 'query' => array('bar' => 'baz'), - 'fragment' => 'foo', - ); - // Non-clean URLs #1: Absolute URL generated by url(). - $url = $GLOBALS['base_url'] . '/?q=foo/bar&bar=baz#foo'; - $this->assertEqual(drupal_parse_url($url), $result, t('Absolute URL with clean URLs disabled parsed correctly.')); - - // Non-clean URLs #2: Relative URL generated by url(). - $url = '?q=foo/bar&bar=baz#foo'; - $this->assertEqual(drupal_parse_url($url), $result, t('Relative URL with clean URLs disabled parsed correctly.')); - - // Non-clean URLs #3: URL generated by url() on non-Apache webserver. - $url = 'index.php?q=foo/bar&bar=baz#foo'; - $this->assertEqual(drupal_parse_url($url), $result, t('Relative URL on non-Apache webserver with clean URLs disabled parsed correctly.')); - // Test that drupal_parse_url() does not allow spoofing a URL to force a malicious redirect. $parts = drupal_parse_url('forged:http://cwe.mitre.org/data/definitions/601.html'); $this->assertFalse(valid_url($parts['path'], TRUE), t('drupal_parse_url() correctly parsed a forged URL.')); @@ -245,75 +204,41 @@ class CommonURLUnitTestCase extends DrupalWebTestCase { * assert all that works when clean URLs are on and off. */ function testUrl() { - global $base_url; - - foreach (array(FALSE, TRUE) as $absolute) { - // Get the expected start of the path string. - $base = $absolute ? $base_url . '/' : base_path(); - $absolute_string = $absolute ? 'absolute' : NULL; - - // Disable Clean URLs. - $GLOBALS['conf']['clean_url'] = 0; - - $url = $base . '?q=node/123'; - $result = url('node/123', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123#foo'; - $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123&foo'; - $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123&foo=bar&bar=baz'; - $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123&foo#bar'; - $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123&foo#0'; - $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => '0', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . '?q=node/123&foo'; - $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => '', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base; - $result = url('<front>', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - // Enable Clean URLs. - $GLOBALS['conf']['clean_url'] = 1; - - $url = $base . 'node/123'; - $result = url('node/123', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123#foo'; - $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo'; - $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo=bar&bar=baz'; - $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo#bar'; - $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base; - $result = url('<front>', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); + global $base_url, $script_path; + + $script_path_original = $script_path; + foreach (array('', 'index.php/') as $script_path) { + foreach (array(FALSE, TRUE) as $absolute) { + // Get the expected start of the path string. + $base = ($absolute ? $base_url . '/' : base_path()) . $script_path; + $absolute_string = $absolute ? 'absolute' : NULL; + + $url = $base . 'node/123'; + $result = url('node/123', array('absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123#foo'; + $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo'; + $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo=bar&bar=baz'; + $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo#bar'; + $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base; + $result = url('<front>', array('absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + } } + $script_path = $script_path_original; } /** @@ -1230,8 +1155,8 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase { $this->assertTrue(array_key_exists('core/misc/html5.js', $javascript), t('html5.js is added when file is added.')); $this->assertTrue(array_key_exists('core/misc/collapse.js', $javascript), t('JavaScript files are correctly added.')); $this->assertEqual(base_path(), $javascript['settings']['data'][0]['basePath'], t('Base path JavaScript setting is correctly set.')); - url('', array('prefix' => &$prefix)); - $this->assertEqual(empty($prefix) ? '' : $prefix, $javascript['settings']['data'][1]['pathPrefix'], t('Path prefix JavaScript setting is correctly set.')); + $this->assertIdentical($GLOBALS['script_path'], $javascript['settings']['data'][1]['scriptPath'], t('Script path JavaScript setting is correctly set.')); + $this->assertIdentical('', $javascript['settings']['data'][2]['pathPrefix'], t('Path prefix JavaScript setting is correctly set.')); } /** @@ -1239,8 +1164,8 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase { */ function testAddSetting() { $javascript = drupal_add_js(array('drupal' => 'rocks', 'dries' => 280342800), 'setting'); - $this->assertEqual(280342800, $javascript['settings']['data'][2]['dries'], t('JavaScript setting is set correctly.')); - $this->assertEqual('rocks', $javascript['settings']['data'][2]['drupal'], t('The other JavaScript setting is set correctly.')); + $this->assertEqual(280342800, $javascript['settings']['data'][3]['dries'], t('JavaScript setting is set correctly.')); + $this->assertEqual('rocks', $javascript['settings']['data'][3]['drupal'], t('The other JavaScript setting is set correctly.')); } /** @@ -1269,8 +1194,9 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase { $javascript = drupal_get_js('header'); $this->assertTrue(strpos($javascript, 'basePath') > 0, t('Rendered JavaScript header returns basePath setting.')); - $this->assertTrue(strpos($javascript, 'core/misc/jquery.js') > 0, t('Rendered JavaScript header includes jQuery.')); + $this->assertTrue(strpos($javascript, 'scriptPath') > 0, t('Rendered JavaScript header returns scriptPath setting.')); $this->assertTrue(strpos($javascript, 'pathPrefix') > 0, t('Rendered JavaScript header returns pathPrefix setting.')); + $this->assertTrue(strpos($javascript, 'core/misc/jquery.js') > 0, t('Rendered JavaScript header includes jQuery.')); // Test whether drupal_add_js can be used to override a previous setting. $this->assertTrue(strpos($javascript, 'commonTestShouldAppear') > 0, t('Rendered JavaScript header returns custom setting.')); @@ -1974,8 +1900,8 @@ class CommonValidUrlUnitTestCase extends DrupalUnitTestCase { 'example.com/index.html#pagetop', 'example.com:8080', 'subdomain.example.com', - 'example.com/index.php?q=node', - 'example.com/index.php?q=node¶m=false', + 'example.com/index.php/node', + 'example.com/index.php/node?param=false', 'user@www.example.com', 'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop', '127.0.0.1', @@ -2022,8 +1948,8 @@ class CommonValidUrlUnitTestCase extends DrupalUnitTestCase { $valid_relative_urls = array( 'paren(the)sis', 'index.html#pagetop', - 'index.php?q=node', - 'index.php?q=node¶m=false', + 'index.php/node', + 'index.php/node?param=false', 'login.php?do=login&style=%23#pagetop', ); diff --git a/core/modules/system/tests/file.test b/core/modules/system/tests/file.test index 173d05abb743..ab930090fee2 100644 --- a/core/modules/system/tests/file.test +++ b/core/modules/system/tests/file.test @@ -2422,7 +2422,7 @@ class FileDownloadTest extends FileTestCase { * Test file_create_url(). */ function testFileCreateUrl() { - global $base_url; + global $base_url, $script_path; // Tilde (~) is excluded from this test because it is encoded by // rawurlencode() in PHP 5.2 but not in PHP 5.3, as per RFC 3986. @@ -2434,9 +2434,16 @@ class FileDownloadTest extends FileTestCase { '%2523%2525%2526%252B%252F%253F' . '%C3%A9%C3%B8%C3%AF%D0%B2%CE%B2%E4%B8%AD%E5%9C%8B%E6%9B%B8%DB%9E'; - $this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); - $this->checkUrl('private', '', $basename, $base_url . '/system/files/' . $basename_encoded); - $this->checkUrl('private', '', $basename, $base_url . '/?q=system/files/' . $basename_encoded, '0'); + // Public files should not be served by Drupal, so their URLs should not be + // generated by url(), whereas private files should be served by Drupal, so + // their URLs should be generated by url(). The difference is most apparent + // when $script_path is not empty (i.e., when not using clean URLs). + $script_path_original = $script_path; + foreach (array('', 'index.php/') as $script_path) { + $this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); + $this->checkUrl('private', '', $basename, $base_url . '/' . $script_path . 'system/files/' . $basename_encoded); + } + $script_path = $script_path_original; } /** @@ -2454,12 +2461,8 @@ class FileDownloadTest extends FileTestCase { * A filename * @param $expected_url * The expected URL - * @param $clean_url - * The value of the clean_url setting */ - private function checkUrl($scheme, $directory, $filename, $expected_url, $clean_url = '1') { - variable_set('clean_url', $clean_url); - + private function checkUrl($scheme, $directory, $filename, $expected_url) { // Convert $filename to a valid filename, i.e. strip characters not // supported by the filesystem, and create the file in the specified // directory. diff --git a/core/modules/system/tests/menu.test b/core/modules/system/tests/menu.test index 0a10ec8c4fd8..c17adb57620c 100644 --- a/core/modules/system/tests/menu.test +++ b/core/modules/system/tests/menu.test @@ -262,11 +262,11 @@ class MenuRouterTestCase extends DrupalWebTestCase { $this->drupalGet('user/login'); // Check that we got to 'user'. - $this->assertTrue($this->url == url('user', array('absolute' => TRUE)), t("Logged-in user redirected to q=user on accessing q=user/login")); + $this->assertTrue($this->url == url('user', array('absolute' => TRUE)), t("Logged-in user redirected to user on accessing user/login")); // user/register should redirect to user/UID/edit. $this->drupalGet('user/register'); - $this->assertTrue($this->url == url('user/' . $this->loggedInUser->uid . '/edit', array('absolute' => TRUE)), t("Logged-in user redirected to q=user/UID/edit on accessing q=user/register")); + $this->assertTrue($this->url == url('user/' . $this->loggedInUser->uid . '/edit', array('absolute' => TRUE)), t("Logged-in user redirected to user/UID/edit on accessing user/register")); } /** diff --git a/core/modules/system/tests/modules/menu_test/menu_test.module b/core/modules/system/tests/modules/menu_test/menu_test.module index 0b954ae1cbad..6e6bb4d8278b 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.module +++ b/core/modules/system/tests/modules/menu_test/menu_test.module @@ -537,7 +537,7 @@ function menu_test_static_variable($value = NULL) { * Implements hook_menu_site_status_alter(). */ function menu_test_menu_site_status_alter(&$menu_site_status, $path) { - // Allow access to ?q=menu_login_callback even if in maintenance mode. + // Allow access to menu_login_callback even if in maintenance mode. if ($menu_site_status == MENU_SITE_OFFLINE && $path == 'menu_login_callback') { $menu_site_status = MENU_SITE_ONLINE; } diff --git a/core/modules/system/tests/modules/url_alter_test/url_alter_test.module b/core/modules/system/tests/modules/url_alter_test/url_alter_test.module index 9287ff52307a..a5ca13deb4c6 100644 --- a/core/modules/system/tests/modules/url_alter_test/url_alter_test.module +++ b/core/modules/system/tests/modules/url_alter_test/url_alter_test.module @@ -30,8 +30,8 @@ function url_alter_test_foo() { * Implements hook_url_inbound_alter(). */ function url_alter_test_url_inbound_alter(&$path, $original_path, $path_language) { - if (!request_path() && !empty($_GET['q'])) { - drupal_set_message("\$_GET['q'] is non-empty with an empty request path."); + if (!request_path() && current_path()) { + drupal_set_message("current_path() is non-empty with an empty request path."); } // Rewrite user/username to user/uid. diff --git a/core/modules/system/tests/path.test b/core/modules/system/tests/path.test index fe6f73459fd0..f02a9b4b91a5 100644 --- a/core/modules/system/tests/path.test +++ b/core/modules/system/tests/path.test @@ -201,11 +201,11 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase { } /** - * Tests that $_GET['q'] is initialized when the request path is empty. + * Tests that current_path() is initialized when the request path is empty. */ function testGetQInitialized() { $this->drupalGet(''); - $this->assertText("\$_GET['q'] is non-empty with an empty request path.", "\$_GET['q'] is initialized with an empty request path."); + $this->assertText("current_path() is non-empty with an empty request path.", "current_path() is initialized with an empty request path."); } /** @@ -221,7 +221,7 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase { protected function assertUrlOutboundAlter($original, $final) { // Test outbound altering. $result = url($original); - $base_path = base_path() . (variable_get('clean_url', '0') ? '' : '?q='); + $base_path = base_path() . $GLOBALS['script_path']; $result = substr($result, strlen($base_path)); $this->assertIdentical($result, $final, t('Altered outbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result))); } diff --git a/core/modules/system/tests/session.test b/core/modules/system/tests/session.test index 5cc8fe9476ea..ff0afb85fdaf 100644 --- a/core/modules/system/tests/session.test +++ b/core/modules/system/tests/session.test @@ -513,7 +513,7 @@ class SessionHttpsTestCase extends DrupalWebTestCase { */ protected function httpsUrl($url) { global $base_url; - return $base_url . '/core/modules/system/tests/https.php?q=' . $url; + return $base_url . '/core/modules/system/tests/https.php/' . $url; } /** @@ -527,7 +527,7 @@ class SessionHttpsTestCase extends DrupalWebTestCase { */ protected function httpUrl($url) { global $base_url; - return $base_url . '/core/modules/system/tests/http.php?q=' . $url; + return $base_url . '/core/modules/system/tests/http.php/' . $url; } } diff --git a/core/modules/system/tests/tablesort.test b/core/modules/system/tests/tablesort.test index 9c068f861459..aaea5058b7af 100644 --- a/core/modules/system/tests/tablesort.test +++ b/core/modules/system/tests/tablesort.test @@ -49,7 +49,7 @@ class TableSortTest extends DrupalUnitTestCase { $headers = array('foo', 'bar', 'baz'); // Reset $_GET to prevent parameters from Simpletest and Batch API ending // up in $ts['query']. - $_GET = array('q' => 'jahwohl'); + $_GET = array(); $expected_ts = array( 'name' => 'foo', 'sql' => '', @@ -64,7 +64,6 @@ class TableSortTest extends DrupalUnitTestCase { // override the default. $_GET = array( - 'q' => 'jahwohl', // This should not override the table order because only complex // headers are overridable. 'order' => 'bar', @@ -77,7 +76,6 @@ class TableSortTest extends DrupalUnitTestCase { // override the default. $_GET = array( - 'q' => 'jahwohl', 'sort' => 'DESC', // Add an unrelated parameter to ensure that tablesort will include // it in the links that it creates. @@ -107,7 +105,6 @@ class TableSortTest extends DrupalUnitTestCase { ); // Reset $_GET from previous assertion. $_GET = array( - 'q' => 'jahwohl', 'order' => '2', ); $ts = tablesort_init($headers); @@ -124,7 +121,6 @@ class TableSortTest extends DrupalUnitTestCase { // override the default. $_GET = array( - 'q' => 'jahwohl', // This should not override the table order because this header does not // exist. 'order' => 'bar', @@ -144,7 +140,6 @@ class TableSortTest extends DrupalUnitTestCase { // override the default. $_GET = array( - 'q' => 'jahwohl', 'order' => '1', 'sort' => 'ASC', // Add an unrelated parameter to ensure that tablesort will include diff --git a/core/modules/system/tests/theme.test b/core/modules/system/tests/theme.test index c1ba08f809fb..2a1959c77890 100644 --- a/core/modules/system/tests/theme.test +++ b/core/modules/system/tests/theme.test @@ -69,14 +69,14 @@ class ThemeUnitTest extends DrupalWebTestCase { * Ensure page-front template suggestion is added when on front page. */ function testFrontPageThemeSuggestion() { - $q = $_GET['q']; - // Set $_GET['q'] to node because theme_get_suggestions() will query it to - // see if we are on the front page. + $original_path = _current_path(); + // Set the current path to node because theme_get_suggestions() will query + // it to see if we are on the front page. variable_set('site_frontpage', 'node'); - $_GET['q'] = 'node'; - $suggestions = theme_get_suggestions(explode('/', $_GET['q']), 'page'); + _current_path('node'); + $suggestions = theme_get_suggestions(array('node'), 'page'); // Set it back to not annoy the batch runner. - $_GET['q'] = $q; + _current_path($original_path); $this->assertTrue(in_array('page__front', $suggestions), t('Front page template was suggested.')); } @@ -317,7 +317,7 @@ class ThemeFunctionsTestCase extends DrupalWebTestCase { // Required to verify the "active" class in expected links below, and // because the current path is different when running tests manually via // simpletest.module ('batch') and via the testing framework (''). - $_GET['q'] = variable_get('site_frontpage', 'user'); + _current_path(variable_get('site_frontpage', 'user')); // Verify that a list of links is properly rendered. $variables = array(); diff --git a/core/modules/system/tests/upgrade/upgrade.test b/core/modules/system/tests/upgrade/upgrade.test index e4045beb789b..52d78006bee8 100644 --- a/core/modules/system/tests/upgrade/upgrade.test +++ b/core/modules/system/tests/upgrade/upgrade.test @@ -78,7 +78,6 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase { $this->originalLanguageDefault = variable_get('language_default'); $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); $this->originalProfile = drupal_get_profile(); - $clean_url_original = variable_get('clean_url', 0); // Unregister the registry. // This is required to make sure that the database layer works properly. @@ -138,7 +137,6 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase { drupal_save_session(FALSE); // Restore necessary variables. - $this->variable_set('clean_url', $clean_url_original); $this->variable_set('site_mail', 'simpletest@example.com'); drupal_set_time_limit($this->timeLimit); diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc index a95b856416d2..9b230055526a 100644 --- a/core/modules/taxonomy/taxonomy.admin.inc +++ b/core/modules/taxonomy/taxonomy.admin.inc @@ -422,7 +422,7 @@ function taxonomy_overview_terms($form, &$form_state, TaxonomyVocabulary $vocabu '#type' => 'submit', '#value' => t('Reset to alphabetical') ); - $form_state['redirect'] = array($_GET['q'], (isset($_GET['page']) ? array('query' => array('page' => $_GET['page'])) : array())); + $form_state['redirect'] = array(current_path(), (isset($_GET['page']) ? array('query' => array('page' => $_GET['page'])) : array())); } return $form; @@ -784,7 +784,7 @@ function taxonomy_form_term($form, &$form_state, TaxonomyTerm $term = NULL, Taxo ); } else { - $form_state['redirect'] = $_GET['q']; + $form_state['redirect'] = current_path(); } return $form; diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc index 3b1de4852822..46e98d422651 100644 --- a/core/modules/update/update.compare.inc +++ b/core/modules/update/update.compare.inc @@ -741,7 +741,6 @@ function update_project_cache($cid) { // On certain paths, we should clear the cache and recompute the projects for // update status of the site to avoid presenting stale information. - $q = $_GET['q']; $paths = array( 'admin/modules', 'admin/modules/update', @@ -753,7 +752,7 @@ function update_project_cache($cid) { 'admin/reports/status', 'admin/reports/updates/check', ); - if (in_array($q, $paths)) { + if (in_array(current_path(), $paths)) { _update_cache_clear($cid); } else { diff --git a/core/modules/update/update.module b/core/modules/update/update.module index 6142a209a2c0..44d86d6af619 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -107,7 +107,7 @@ function update_help($path, $arg) { */ function update_init() { if (arg(0) == 'admin' && user_access('administer site configuration')) { - switch ($_GET['q']) { + switch (current_path()) { // These pages don't need additional nagging. case 'admin/appearance/update': case 'admin/appearance/install': diff --git a/core/modules/user/user.module b/core/modules/user/user.module index e6fa2dd1325a..4219728ab8b7 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1025,7 +1025,7 @@ function user_account_form_validate($form, &$form_state) { } function user_login_block($form) { - $form['#action'] = url($_GET['q'], array('query' => drupal_get_destination())); + $form['#action'] = url(current_path(), array('query' => drupal_get_destination())); $form['#id'] = 'user-login-form'; $form['#validate'] = user_login_default_validators(); $form['#submit'][] = 'user_login_submit'; @@ -3557,7 +3557,7 @@ function user_register_form($form, &$form_state) { if ($admin) { // Redirect back to page which initiated the create request; // usually admin/people/create. - $form_state['redirect'] = $_GET['q']; + $form_state['redirect'] = current_path(); } $form['actions'] = array('#type' => 'actions'); diff --git a/core/scripts/drupal.sh b/core/scripts/drupal.sh index cf17e68bf03a..fb5e82c1061e 100755 --- a/core/scripts/drupal.sh +++ b/core/scripts/drupal.sh @@ -119,16 +119,15 @@ $cmd = substr($path['path'], 1); } elseif (isset($path['path'])) { - if (!isset($_GET['q'])) { - $_REQUEST['q'] = $_GET['q'] = $path['path']; - } + $_SERVER['SCRIPT_NAME'] = '/' . $cmd; + $_SERVER['REQUEST_URI'] = $path['path']; } // display setup in verbose mode if ($_verbose_mode) { echo "Hostname set to: {$_SERVER['HTTP_HOST']}\n"; echo "Script name set to: {$cmd}\n"; - echo "Path set to: {$_GET['q']}\n"; + echo "Path set to: {$path['path']}\n"; } } break; diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 47bfd4893f87..644ff47fcf2e 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -155,7 +155,7 @@ function simpletest_script_help() { One or more tests to be run. By default, these are interpreted as the names of test groups as shown at - ?q=admin/config/development/testing. + admin/config/development/testing. These group names typically correspond to module names like "User" or "Profile" or "System", but there is also a group "XML-RPC". If --class is specified then these are interpreted as the names of diff --git a/robots.txt b/robots.txt index 90bec1e52b51..d590fbfa7c55 100644 --- a/robots.txt +++ b/robots.txt @@ -35,12 +35,12 @@ Disallow: /user/password/ Disallow: /user/login/ Disallow: /user/logout/ # Paths (no clean URLs) -Disallow: /?q=admin/ -Disallow: /?q=comment/reply/ -Disallow: /?q=filter/tips/ -Disallow: /?q=node/add/ -Disallow: /?q=search/ -Disallow: /?q=user/password/ -Disallow: /?q=user/register/ -Disallow: /?q=user/login/ -Disallow: /?q=user/logout/ +Disallow: /index.php/admin/ +Disallow: /index.php/comment/reply/ +Disallow: /index.php/filter/tips/ +Disallow: /index.php/node/add/ +Disallow: /index.php/search/ +Disallow: /index.php/user/password/ +Disallow: /index.php/user/register/ +Disallow: /index.php/user/login/ +Disallow: /index.php/user/logout/ diff --git a/web.config b/web.config index e990e035f5f1..06e4cbe6eb87 100644 --- a/web.config +++ b/web.config @@ -57,7 +57,9 @@ </rule> --> - <!-- Rewrite URLs of the form 'x' to the form 'index.php?q=x'. --> + <!-- Pass all requests not referring directly to files in the filesystem + to index.php. Clean URLs are handled in + drupal_environment_initialize(). --> <rule name="Short URLS" stopProcessing="true"> <match url="^(.*)$" ignoreCase="false" /> <conditions> @@ -65,9 +67,6 @@ <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" /> <add input="{URL}" pattern="^/favicon.ico$" ignoreCase="false" negate="true" /> </conditions> - <!-- Pass all requests not referring directly to files in the - filesystem to index.php. Clean URLs are handled in - drupal_environment_initialize(). --> <action type="Rewrite" url="index.php" /> </rule> </rules> -- GitLab