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