diff options
Diffstat (limited to 'includes/common.inc')
-rw-r--r-- | includes/common.inc | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/includes/common.inc b/includes/common.inc index 19798bae1c4..9a28c06cc09 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -142,6 +142,10 @@ function drupal_clear_path_cache() { * * Note: When sending a Content-Type header, always include a 'charset' type, * too. This is necessary to avoid security bugs (e.g. UTF-7 XSS). + * + * Note: No special sanitizing needs to be done to headers. However if a header + * value contains a line break a PHP warning will be thrown and the header + * will not be set. */ function drupal_set_header($header = NULL) { // We use an array to guarantee there are no leading or trailing delimiters. @@ -150,8 +154,15 @@ function drupal_set_header($header = NULL) { static $stored_headers = array(); if (strlen($header)) { - header($header); - $stored_headers[] = $header; + // Protect against header injection attacks if PHP is too old to do that. + if (version_compare(PHP_VERSION, '5.1.2', '<') && (strpos($header, "\n") !== FALSE || strpos($header, "\r") !== FALSE)) { + // Use the same warning message that newer versions of PHP use. + trigger_error('Header may not contain more than a single header, new line detected', E_USER_WARNING); + } + else { + header($header); + $stored_headers[] = $header; + } } return implode("\n", $stored_headers); } @@ -330,14 +341,20 @@ function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response if ($destination) { // Do not redirect to an absolute URL originating from user input. - $colonpos = strpos($destination, ':'); - $absolute = strpos($destination, '//') === 0 || ($colonpos !== FALSE && !preg_match('![/?#]!', substr($destination, 0, $colonpos))); - if (!$absolute) { - extract(parse_url(urldecode($destination))); + if (!menu_path_is_external($destination)) { + extract(parse_url($destination)); } } - $url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE)); + $options = array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE); + // In some cases modules call drupal_goto($_GET['q']). We need to ensure that + // such a redirect is not to an external URL. + if ($path === $_GET['q'] && menu_path_is_external($path)) { + // Force url() to generate a non-external URL. + $options['external'] = FALSE; + } + + $url = url($path, $options); // Remove newlines from the URL to avoid header injection attacks. $url = str_replace(array("\n", "\r"), '', $url); @@ -672,7 +689,7 @@ function drupal_error_handler($errno, $message, $filename, $line, $context) { return; } - if ($errno & (E_ALL ^ E_DEPRECATED)) { + if ($errno & (E_ALL ^ E_DEPRECATED ^ E_NOTICE)) { $types = array(1 => 'error', 2 => 'warning', 4 => 'parse error', 8 => 'notice', 16 => 'core error', 32 => 'core warning', 64 => 'compile error', 128 => 'compile warning', 256 => 'user error', 512 => 'user warning', 1024 => 'user notice', 2048 => 'strict warning', 4096 => 'recoverable fatal error'); // For database errors, we want the line number/file name of the place that @@ -1480,20 +1497,9 @@ function url($path = NULL, $options = array()) { 'alias' => FALSE, 'prefix' => '' ); - // A duplicate of the code from menu_path_is_external() to avoid needing - // another function call, since performance inside url() is critical. + if (!isset($options['external'])) { - // Return an external link if $path contains an allowed absolute URL. Avoid - // calling filter_xss_bad_protocol() 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)) - && filter_xss_bad_protocol($path, FALSE) == check_plain($path)); + $options['external'] = menu_path_is_external($path); } // May need language dependent rewriting if language.inc is present. |