Drupal 7.19 7.19
authorDavid Rothstein
Wed, 16 Jan 2013 21:45:48 +0000 (16:45 -0500)
committerDavid Rothstein
Wed, 16 Jan 2013 21:45:48 +0000 (16:45 -0500)
CHANGELOG.txt
includes/bootstrap.inc
misc/collapse.js
misc/drupal.js
misc/vertical-tabs.js
modules/book/book.pages.inc
modules/book/book.test
modules/image/image.module

index 7f4f0ff..08acf95 100644 (file)
@@ -1,3 +1,7 @@
+Drupal 7.19, 2013-01-16
+-----------------------
+- Fixed security issues (multiple vulnerabilities). See SA-CORE-2013-001.
+
 Drupal 7.18, 2012-12-19
 -----------------------
 - Fixed security issues (multiple vulnerabilities). See SA-CORE-2012-004.
index 1b48217..53f70e1 100644 (file)
@@ -8,7 +8,7 @@
 /**
  * The current system version.
  */
-define('VERSION', '7.18');
+define('VERSION', '7.19');
 
 /**
  * Core API compatibility.
index bd51ce5..512ff2f 100644 (file)
@@ -58,9 +58,9 @@ Drupal.behaviors.collapse = {
     $('fieldset.collapsible', context).once('collapse', function () {
       var $fieldset = $(this);
       // Expand fieldset if there are errors inside, or if it contains an
-      // element that is targeted by the URI fragment identifier. 
+      // element that is targeted by the URI fragment identifier.
       var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
-      if ($('.error' + anchor, $fieldset).length) {
+      if ($fieldset.find('.error' + anchor).length) {
         $fieldset.removeClass('collapsed');
       }
 
index 83b0884..643baa1 100644 (file)
@@ -7,6 +7,27 @@ jQuery.noConflict();
 (function ($) {
 
 /**
+ * Override jQuery.fn.init to guard against XSS attacks.
+ *
+ * See http://bugs.jquery.com/ticket/9521
+ */
+var jquery_init = $.fn.init;
+$.fn.init = function (selector, context, rootjQuery) {
+  // If the string contains a "#" before a "<", treat it as invalid HTML.
+  if (selector && typeof selector === 'string') {
+    var hash_position = selector.indexOf('#');
+    if (hash_position >= 0) {
+      var bracket_position = selector.indexOf('<');
+      if (bracket_position > hash_position) {
+        throw 'Syntax error, unrecognized expression: ' + selector;
+      }
+    }
+  }
+  return jquery_init.call(this, selector, context, rootjQuery);
+};
+$.fn.init.prototype = jquery_init.prototype;
+
+/**
  * Attach all registered behaviors to a page element.
  *
  * Behaviors are event-triggered actions that attach to page elements, enhancing
index 14d0660..ebfaa4f 100644 (file)
@@ -50,8 +50,8 @@ Drupal.behaviors.verticalTabs = {
       if (!tab_focus) {
         // If the current URL has a fragment and one of the tabs contains an
         // element that matches the URL fragment, activate that tab.
-        if (window.location.hash && $(window.location.hash, this).length) {
-          tab_focus = $(window.location.hash, this).closest('.vertical-tabs-pane');
+        if (window.location.hash && $(this).find(window.location.hash).length) {
+          tab_focus = $(this).find(window.location.hash).closest('.vertical-tabs-pane');
         }
         else {
           tab_focus = $('> .vertical-tabs-pane:first', this);
index 583eb7a..63a1d15 100644 (file)
@@ -38,6 +38,15 @@ function book_render() {
  *   format determined by the $type parameter.
  */
 function book_export($type, $nid) {
+  // Check that the node exists and that the current user has access to it.
+  $node = node_load($nid);
+  if (!$node) {
+    return MENU_NOT_FOUND;
+  }
+  if (!node_access('view', $node)) {
+    return MENU_ACCESS_DENIED;
+  }
+
   $type = drupal_strtolower($type);
 
   $export_function = 'book_export_' . $type;
index d1f5273..2708e36 100644 (file)
@@ -258,6 +258,13 @@ class BookTestCase extends DrupalWebTestCase {
     // Try getting the URL directly, and verify it fails.
     $this->drupalGet('book/export/html/' . $this->book->nid);
     $this->assertResponse('403', t('Anonymous user properly forbidden.'));
+
+    // Now grant anonymous users permission to view the printer-friendly
+    // version and verify that node access restrictions still prevent them from
+    // seeing it.
+    user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access printer-friendly version'));
+    $this->drupalGet('book/export/html/' . $this->book->nid);
+    $this->assertResponse('403', 'Anonymous user properly forbidden from seeing the printer-friendly version when denied by node access.');
   }
 
   /**
index ff50452..07f4892 100644 (file)
@@ -292,7 +292,8 @@ function image_file_download($uri) {
     if ($info = image_get_info($uri)) {
       // Check the permissions of the original to grant access to this image.
       $headers = module_invoke_all('file_download', $original_uri);
-      if (!in_array(-1, $headers)) {
+      // Confirm there's at least one module granting access and none denying access.
+      if (!empty($headers) && !in_array(-1, $headers)) {
         return array(
           // Send headers describing the image's size, and MIME-type...
           'Content-Type' => $info['mime_type'],