diff options
Diffstat (limited to 'includes/common.inc')
-rw-r--r-- | includes/common.inc | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/includes/common.inc b/includes/common.inc index c6303efad..34fa9b962 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -688,13 +688,6 @@ function drupal_goto($path = '', array $options = array(), $http_response_code = $options['fragment'] = $destination['fragment']; } - // In some cases modules call drupal_goto(current_path()). We need to ensure - // that such a redirect is not to an external URL. - if ($path === current_path() && empty($options['external']) && url_is_external($path)) { - // Force url() to generate a non-external URL. - $options['external'] = FALSE; - } - drupal_alter('drupal_goto', $path, $options, $http_response_code); // The 'Location' HTTP header must be absolute. @@ -2227,8 +2220,20 @@ function url($path = NULL, array $options = array()) { 'prefix' => '' ); + // A duplicate of the code from url_is_external() to avoid needing another + // function call, since performance inside url() is critical. if (!isset($options['external'])) { - $options['external'] = url_is_external($path); + // Return an external link if $path contains an allowed absolute URL. Avoid + // calling drupal_strip_dangerous_protocols() if there is any slash (/), + // hash (#) or question_mark (?) before the colon (:) occurrence - if any - + // as this would clearly mean it is not a URL. If the path starts with 2 + // slashes then it is always considered an external URL without an explicit + // protocol part. + $colonpos = strpos($path, ':'); + $options['external'] = (strpos($path, '//') === 0) + || ($colonpos !== FALSE + && !preg_match('![/?#]!', substr($path, 0, $colonpos)) + && drupal_strip_dangerous_protocols($path) == $path); } // Preserve the original path before altering or aliasing. @@ -2348,18 +2353,12 @@ function url($path = NULL, array $options = array()) { */ function url_is_external($path) { $colonpos = strpos($path, ':'); - // Some browsers treat \ as / so normalize to forward slashes. - $path = str_replace('\\', '/', $path); - // If the path starts with 2 slashes then it is always considered an external - // URL without an explicit protocol part. + // Avoid calling drupal_strip_dangerous_protocols() if there is any slash (/), + // hash (#) or question_mark (?) before the colon (:) occurrence - if any - as + // this would clearly mean it is not a URL. If the path starts with 2 slashes + // then it is always considered an external URL without an explicit protocol + // part. return (strpos($path, '//') === 0) - // Leading control characters may be ignored or mishandled by browsers, so - // assume such a path may lead to an external location. The \p{C} character - // class matches all UTF-8 control, unassigned, and private characters. - || (preg_match('/^\p{C}/u', $path) !== 0) - // Avoid calling drupal_strip_dangerous_protocols() if there is any slash - // (/), hash (#) or question_mark (?) before the colon (:) occurrence - if - // any - as this would clearly mean it is not a URL. || ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path); |