summaryrefslogtreecommitdiff
path: root/includes/common.inc
diff options
context:
space:
mode:
Diffstat (limited to 'includes/common.inc')
-rw-r--r--includes/common.inc37
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);