diff --git a/includes/authorize.inc b/includes/authorize.inc index 9cd4dd32f8e..772481b2dfe 100644 --- a/includes/authorize.inc +++ b/includes/authorize.inc @@ -10,10 +10,12 @@ * Build the form for choosing a FileTransfer type and supplying credentials. */ function authorize_filetransfer_form($form_state) { - global $base_url; + global $base_url, $is_https; $form = array(); - $form['#action'] = $base_url . '/authorize.php'; + // If possible, we want to post this form securely via https. + $form['#https'] = TRUE; + // CSS we depend on lives in modules/system/maintenance.css, which is loaded // via the default maintenance theme. $form['#attached']['js'][] = $base_url . '/misc/authorize.js'; @@ -26,6 +28,10 @@ function authorize_filetransfer_form($form_state) { $available_backends = $_SESSION['authorize_filetransfer_backends']; uasort($available_backends, 'drupal_sort_weight'); + if (!$is_https) { + drupal_set_message(t('WARNING: You are not using an encrypted connection, so your password will be sent in plain text. Learn more.', array('@https-link' => 'http://drupal.org/https-information')), 'error'); + } + // Decide on a default backend. if (isset($form_state['values']['connection_settings']['authorize_filetransfer_default'])) { $authorize_filetransfer_default = $form_state['values']['connection_settings']['authorize_filetransfer_default']; diff --git a/includes/common.inc b/includes/common.inc index adacdee5e1a..ce76725cf8e 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2375,10 +2375,10 @@ function format_username($account) { * - 'alias': Defaults to FALSE. Whether the given path is a URL alias * already. * - 'external': Whether the given path is an external URL. - * - 'language': An optional language object. Used to build the URL to link to - * and look up the proper alias for the link. + * - 'language': An optional language object. Used to build the URL to link + * to and look up the proper alias for the link. * - 'https': Whether this URL should point to a secure location. If not - * specified, the current scheme is used, so the user stays on http or https + * defined, the current scheme is used, so the user stays on http or https * respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can * only be enforced when the variable 'https' is set to TRUE. * - 'base_url': Only used internally, to modify the base URL when a language @@ -2401,14 +2401,15 @@ function url($path = NULL, array $options = array()) { 'query' => array(), 'absolute' => FALSE, 'alias' => FALSE, - 'https' => FALSE, 'prefix' => '' ); if (!isset($options['external'])) { // Return an external link if $path contains an allowed absolute URL. - // Only call the slow filter_xss_bad_protocol if $path contains a ':' before - // any / ? or #. + // Only call the slow filter_xss_bad_protocol if $path contains a ':' + // before any / ? or #. + // Note: we could use url_is_external($path) here, but that would + // requre another function call, and performance inside url() is critical. $colonpos = strpos($path, ':'); $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path)); } @@ -2443,6 +2444,14 @@ function url($path = NULL, array $options = array()) { if ($options['query']) { $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . drupal_http_build_query($options['query']); } + if (isset($options['https']) && variable_get('https', FALSE)) { + if ($options['https'] === TRUE) { + $path = str_replace('http://', 'https://', $path); + } + elseif ($options['https'] === FALSE) { + $path = str_replace('https://', 'http://', $path); + } + } // Reassemble. return $path . $options['fragment']; } @@ -2520,6 +2529,16 @@ function url($path = NULL, array $options = array()) { } } +/** + * Return TRUE if a path is external (e.g. http://example.com). + */ +function url_is_external($path) { + $colonpos = strpos($path, ':'); + // Only call the slow filter_xss_bad_protocol if $path contains a ':' + // before any / ? or #. + return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path); +} + /** * Format an attribute string to insert in a tag. * diff --git a/includes/form.inc b/includes/form.inc index 0de410ea596..062fc089e74 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -1017,7 +1017,7 @@ function form_builder($form_id, $element, &$form_state) { // Special handling if we're on the top level form element. if (isset($element['#type']) && $element['#type'] == 'form') { if (!empty($element['#https']) && variable_get('https', FALSE) && - !menu_path_is_external($element['#action'])) { + !url_is_external($element['#action'])) { global $base_root; // Not an external URL so ensure that it is secure. diff --git a/includes/menu.inc b/includes/menu.inc index 7a6787c5fb6..5582093556f 100644 --- a/includes/menu.inc +++ b/includes/menu.inc @@ -2517,7 +2517,7 @@ function menu_link_save(&$item) { // This is the easiest way to handle the unique internal path '', // since a path marked as external does not need to match a router path. - $item['external'] = (menu_path_is_external($item['link_path']) || $item['link_path'] == '') ? 1 : 0; + $item['external'] = (url_is_external($item['link_path']) || $item['link_path'] == '') ? 1 : 0; // Load defaults. $item += array( 'menu_name' => 'navigation', @@ -3186,14 +3186,6 @@ function _menu_router_save($menu, $masks) { return $menu; } -/** - * Returns TRUE if a path is external (e.g. http://example.com). - */ -function menu_path_is_external($path) { - $colonpos = strpos($path, ':'); - return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path); -} - /** * Checks whether the site is in maintenance mode. * @@ -3254,7 +3246,7 @@ function menu_valid_path($form_item) { $path = $form_item['link_path']; // We indicate that a menu administrator is running the menu access check. $menu_admin = TRUE; - if ($path == '' || menu_path_is_external($path)) { + if ($path == '' || url_is_external($path)) { $item = array('access' => TRUE); } elseif (preg_match('/\/\%/', $path)) { diff --git a/modules/menu/menu.admin.inc b/modules/menu/menu.admin.inc index 92f78a8181e..16fcadf7c06 100644 --- a/modules/menu/menu.admin.inc +++ b/modules/menu/menu.admin.inc @@ -355,7 +355,7 @@ function menu_edit_item_validate($form, &$form_state) { drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $item['link_path'], '%normal_path' => $normal_path))); $item['link_path'] = $normal_path; } - if (!menu_path_is_external($item['link_path'])) { + if (!url_is_external($item['link_path'])) { $parsed_link = parse_url($item['link_path']); if (isset($parsed_link['query'])) { $item['options']['query'] = $parsed_link['query']; diff --git a/modules/shortcut/shortcut.module b/modules/shortcut/shortcut.module index d3c9e2473d1..4607d488421 100644 --- a/modules/shortcut/shortcut.module +++ b/modules/shortcut/shortcut.module @@ -482,7 +482,7 @@ function shortcut_valid_link($path) { $path = $normal_path; } // Only accept links that correspond to valid paths on the site itself. - return !menu_path_is_external($path) && menu_get_item($path); + return !url_is_external($path) && menu_get_item($path); } /** diff --git a/modules/system/system.module b/modules/system/system.module index c7be27e9732..76ea922697a 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -1504,10 +1504,19 @@ function system_authorized_init($callback, $file, $arguments = array(), $page_ti /** * Return the URL for the authorize.php script. + * + * @param array $options + * Optional array of options to pass to url(). + * @return + * The full URL to authorize.php, using https if available. */ -function system_authorized_get_url() { +function system_authorized_get_url(array $options = array()) { global $base_url; - return $base_url . '/authorize.php'; + // 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. + return url($base_url . '/authorize.php', $options); } /** @@ -1520,6 +1529,17 @@ function system_authorized_run($callback, $file, $arguments = array(), $page_tit drupal_goto(system_authorized_get_url()); } +/** + * Use authorize.php to run batch_process(). + * + * @see batch_process() + */ +function system_authorized_batch_process() { + $finish_url = system_authorized_get_url(); + $process_url = system_authorized_get_url(array('query' => array('batch' => '1'))); + batch_process($finish_url, $process_url); +} + /** * @} End of "defgroup authorize". */ diff --git a/modules/update/update.authorize.inc b/modules/update/update.authorize.inc index 6b7c797a41d..0a5514d9d68 100644 --- a/modules/update/update.authorize.inc +++ b/modules/update/update.authorize.inc @@ -24,8 +24,6 @@ * - 'local_url': The locally installed location of new code to update with. */ function update_authorize_run_update($filetransfer, $projects) { - global $base_url; - $operations = array(); foreach ($projects as $project => $project_info) { $operations[] = array( @@ -49,7 +47,7 @@ function update_authorize_run_update($filetransfer, $projects) { batch_set($batch); // Invoke the batch via authorize.php. - batch_process($base_url . '/authorize.php', $base_url . '/authorize.php?batch=1'); + system_authorized_batch_process(); } /** @@ -67,8 +65,6 @@ function update_authorize_run_update($filetransfer, $projects) { * already been downloaded and extracted into. */ function update_authorize_run_install($filetransfer, $project, $updater_name, $local_url) { - global $base_url; - $operations[] = array( 'update_authorize_batch_copy_project', array( @@ -91,8 +87,7 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l batch_set($batch); // Invoke the batch via authorize.php. - batch_process($base_url . '/authorize.php', $base_url . '/authorize.php?batch=1'); - + system_authorized_batch_process(); } /**