diff --git a/composer.lock b/composer.lock index 3dfa8906c414ebdfc848a1985ce70891bd38d82e..84b33dbd027bbe62af59600038af37270b091722 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,6 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7d101b08e5ae002d827cd42ae9a4e344", "content-hash": "60f7057617c6d995bf9946d0b12f0b5d", "packages": [ { @@ -48,7 +47,7 @@ "cors", "stack" ], - "time": "2016-08-01 12:05:04" + "time": "2016-08-01T12:05:04+00:00" }, { "name": "composer/installers", @@ -143,7 +142,7 @@ "zend", "zikula" ], - "time": "2015-02-18 17:17:01" + "time": "2015-02-18T17:17:01+00:00" }, { "name": "composer/semver", @@ -204,7 +203,7 @@ "validation", "versioning" ], - "time": "2015-09-21 09:42:36" + "time": "2015-09-21T09:42:36+00:00" }, { "name": "doctrine/annotations", @@ -272,7 +271,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2015-08-31T12:32:49+00:00" }, { "name": "doctrine/cache", @@ -342,7 +341,7 @@ "cache", "caching" ], - "time": "2015-08-31 12:36:41" + "time": "2015-08-31T12:36:41+00:00" }, { "name": "doctrine/collections", @@ -408,7 +407,7 @@ "collections", "iterator" ], - "time": "2015-04-14 22:21:58" + "time": "2015-04-14T22:21:58+00:00" }, { "name": "doctrine/common", @@ -481,7 +480,7 @@ "persistence", "spl" ], - "time": "2015-08-31 13:00:22" + "time": "2015-08-31T13:00:22+00:00" }, { "name": "doctrine/inflector", @@ -548,7 +547,7 @@ "singularize", "string" ], - "time": "2014-12-20 21:24:13" + "time": "2014-12-20T21:24:13+00:00" }, { "name": "doctrine/lexer", @@ -602,7 +601,7 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "easyrdf/easyrdf", @@ -664,7 +663,7 @@ "rdfa", "sparql" ], - "time": "2015-02-27 09:45:49" + "time": "2015-02-27T09:45:49+00:00" }, { "name": "egulias/email-validator", @@ -717,7 +716,7 @@ "validation", "validator" ], - "time": "2015-06-22 21:07:51" + "time": "2015-06-22T21:07:51+00:00" }, { "name": "guzzlehttp/guzzle", @@ -779,7 +778,7 @@ "rest", "web service" ], - "time": "2016-07-15 17:22:37" + "time": "2016-07-15T17:22:37+00:00" }, { "name": "guzzlehttp/promises", @@ -830,7 +829,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-05-18T16:56:05+00:00" }, { "name": "guzzlehttp/psr7", @@ -888,7 +887,7 @@ "stream", "uri" ], - "time": "2016-06-24 23:00:38" + "time": "2016-06-24T23:00:38+00:00" }, { "name": "ircmaxell/password-compat", @@ -930,7 +929,7 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "masterminds/html5", @@ -995,7 +994,7 @@ "serializer", "xml" ], - "time": "2016-05-10 14:11:45" + "time": "2016-05-10T14:11:45+00:00" }, { "name": "paragonie/random_compat", @@ -1043,7 +1042,7 @@ "pseudorandom", "random" ], - "time": "2015-12-01 02:52:15" + "time": "2015-12-01T02:52:15+00:00" }, { "name": "psr/http-message", @@ -1092,7 +1091,7 @@ "request", "response" ], - "time": "2015-05-04 20:22:00" + "time": "2015-05-04T20:22:00+00:00" }, { "name": "psr/log", @@ -1130,7 +1129,7 @@ "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2012-12-21T11:40:51+00:00" }, { "name": "stack/builder", @@ -1179,7 +1178,7 @@ "keywords": [ "stack" ], - "time": "2016-06-02 06:58:42" + "time": "2016-06-02T06:58:42+00:00" }, { "name": "symfony-cmf/routing", @@ -1238,7 +1237,7 @@ "database", "routing" ], - "time": "2016-03-31 09:11:39" + "time": "2016-03-31T09:11:39+00:00" }, { "name": "symfony/class-loader", @@ -1291,7 +1290,7 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2017-01-10 14:03:07" + "time": "2017-01-10T14:03:07+00:00" }, { "name": "symfony/console", @@ -1352,7 +1351,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-01-08 20:43:03" + "time": "2017-01-08T20:43:03+00:00" }, { "name": "symfony/debug", @@ -1409,7 +1408,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/dependency-injection", @@ -1472,7 +1471,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-01-10 14:27:01" + "time": "2017-01-10T14:27:01+00:00" }, { "name": "symfony/event-dispatcher", @@ -1532,7 +1531,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/http-foundation", @@ -1587,7 +1586,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2017-01-08 20:43:03" + "time": "2017-01-08T20:43:03+00:00" }, { "name": "symfony/http-kernel", @@ -1669,7 +1668,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2017-01-12 20:27:24" + "time": "2017-01-12T20:27:24+00:00" }, { "name": "symfony/polyfill-apcu", @@ -1722,7 +1721,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-iconv", @@ -1781,7 +1780,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -1840,7 +1839,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php54", @@ -1898,7 +1897,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php55", @@ -1954,7 +1953,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/process", @@ -2003,7 +2002,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -2057,7 +2056,7 @@ "http-message", "psr-7" ], - "time": "2015-05-29 17:57:12" + "time": "2015-05-29T17:57:12+00:00" }, { "name": "symfony/routing", @@ -2132,7 +2131,7 @@ "uri", "url" ], - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/serializer", @@ -2196,7 +2195,7 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/translation", @@ -2260,7 +2259,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/validator", @@ -2333,7 +2332,7 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2017-01-12 19:24:25" + "time": "2017-01-12T19:24:25+00:00" }, { "name": "symfony/yaml", @@ -2382,7 +2381,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-03 13:49:52" + "time": "2017-01-03T13:49:52+00:00" }, { "name": "twig/twig", @@ -2443,7 +2442,7 @@ "keywords": [ "templating" ], - "time": "2016-01-25 21:22:18" + "time": "2016-01-25T21:22:18+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -2492,7 +2491,7 @@ } ], "description": "Composer plugin to merge multiple composer.json files", - "time": "2016-03-08 17:11:37" + "time": "2016-03-08T17:11:37+00:00" }, { "name": "zendframework/zend-diactoros", @@ -2542,7 +2541,7 @@ "psr", "psr-7" ], - "time": "2015-08-10 20:04:20" + "time": "2015-08-10T20:04:20+00:00" }, { "name": "zendframework/zend-escaper", @@ -2586,7 +2585,7 @@ "escaper", "zf2" ], - "time": "2015-06-03 14:05:37" + "time": "2015-06-03T14:05:37+00:00" }, { "name": "zendframework/zend-feed", @@ -2645,7 +2644,7 @@ "feed", "zf2" ], - "time": "2015-08-04 21:39:18" + "time": "2015-08-04T21:39:18+00:00" }, { "name": "zendframework/zend-hydrator", @@ -2701,7 +2700,7 @@ "hydrator", "zf2" ], - "time": "2015-09-17 14:06:43" + "time": "2015-09-17T14:06:43+00:00" }, { "name": "zendframework/zend-stdlib", @@ -2759,7 +2758,7 @@ "stdlib", "zf2" ], - "time": "2015-09-25 04:06:33" + "time": "2015-09-25T04:06:33+00:00" } ], "packages-dev": [ @@ -2819,7 +2818,7 @@ "testing", "web" ], - "time": "2016-03-05 08:26:18" + "time": "2016-03-05T08:26:18+00:00" }, { "name": "behat/mink-browserkit-driver", @@ -2875,7 +2874,7 @@ "browser", "testing" ], - "time": "2016-03-05 08:59:47" + "time": "2016-03-05T08:59:47+00:00" }, { "name": "behat/mink-goutte-driver", @@ -2930,7 +2929,7 @@ "headless", "testing" ], - "time": "2016-03-05 09:04:22" + "time": "2016-03-05T09:04:22+00:00" }, { "name": "doctrine/instantiator", @@ -2984,7 +2983,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "fabpot/goutte", @@ -3033,7 +3032,7 @@ "keywords": [ "scraper" ], - "time": "2015-11-05 12:58:44" + "time": "2015-11-05T12:58:44+00:00" }, { "name": "jcalderonzumba/gastonjs", @@ -3090,7 +3089,7 @@ "headless", "phantomjs" ], - "time": "2016-01-18 09:21:03" + "time": "2016-01-18T09:21:03+00:00" }, { "name": "jcalderonzumba/mink-phantomjs-driver", @@ -3151,7 +3150,7 @@ "phantomjs", "testing" ], - "time": "2015-12-04 13:55:02" + "time": "2015-12-04T13:55:02+00:00" }, { "name": "mikey179/vfsStream", @@ -3197,7 +3196,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2015-10-06 16:59:57" + "time": "2015-10-06T16:59:57+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -3246,7 +3245,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2015-02-03T12:10:50+00:00" }, { "name": "phpspec/prophecy", @@ -3306,7 +3305,7 @@ "spy", "stub" ], - "time": "2015-08-13 10:07:40" + "time": "2015-08-13T10:07:40+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3368,7 +3367,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3415,7 +3414,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2015-06-21T13:08:43+00:00" }, { "name": "phpunit/php-text-template", @@ -3456,7 +3455,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -3497,7 +3496,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2015-06-21T08:01:12+00:00" }, { "name": "phpunit/php-token-stream", @@ -3546,20 +3545,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2015-09-15T10:49:45+00:00" }, { "name": "phpunit/phpunit", - "version": "4.8.27", + "version": "4.8.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90" + "reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90", - "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/558a3a0d28b4cb7e4a593a4fbd2220e787076225", + "reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225", "shasum": "" }, "require": { @@ -3618,7 +3617,7 @@ "testing", "xunit" ], - "time": "2016-07-21 06:48:14" + "time": "2016-11-14T06:25:28+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -3674,7 +3673,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "sebastian/comparator", @@ -3738,7 +3737,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2015-07-26T15:48:44+00:00" }, { "name": "sebastian/diff", @@ -3790,7 +3789,7 @@ "keywords": [ "diff" ], - "time": "2015-02-22 15:13:53" + "time": "2015-02-22T15:13:53+00:00" }, { "name": "sebastian/environment", @@ -3840,7 +3839,7 @@ "environment", "hhvm" ], - "time": "2015-08-03 06:14:51" + "time": "2015-08-03T06:14:51+00:00" }, { "name": "sebastian/exporter", @@ -3906,7 +3905,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2015-06-21T07:55:53+00:00" }, { "name": "sebastian/global-state", @@ -3957,7 +3956,7 @@ "keywords": [ "global state" ], - "time": "2014-10-06 09:23:50" + "time": "2014-10-06T09:23:50+00:00" }, { "name": "sebastian/recursion-context", @@ -4010,7 +4009,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21 08:04:50" + "time": "2015-06-21T08:04:50+00:00" }, { "name": "sebastian/version", @@ -4045,7 +4044,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "symfony/browser-kit", @@ -4102,7 +4101,7 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/css-selector", @@ -4155,7 +4154,7 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" }, { "name": "symfony/dom-crawler", @@ -4211,7 +4210,7 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-01-02T20:30:24+00:00" } ], "aliases": [], diff --git a/core/CHANGELOG.txt b/core/CHANGELOG.txt index 2b424d27cceb444773b48f49206fddc5955ccddd..853260ae9f38863850ddbc29d8b0964f11aa2d9b 100644 --- a/core/CHANGELOG.txt +++ b/core/CHANGELOG.txt @@ -1,3 +1,7 @@ +Drupal 8.2.7, 2017-03-15 +------------------------ +- Fixed security issues. See SA-CORE-2017-001. + Drupal 8.2.3, 2016-11-16 ------------------------ - Fixed security issues. See SA-CORE-2016-005. diff --git a/core/composer.json b/core/composer.json index b9a3fad8b077311ff669efea1c5369eda3d2a214..6782469d6df37224bfb7bddd4bb5f6b993042e59 100644 --- a/core/composer.json +++ b/core/composer.json @@ -40,7 +40,7 @@ "jcalderonzumba/gastonjs": "~1.0.2", "jcalderonzumba/mink-phantomjs-driver": "~0.3.1", "mikey179/vfsStream": "~1.2", - "phpunit/phpunit": "~4.8", + "phpunit/phpunit": ">=4.8.28 <5", "symfony/css-selector": "~2.8" }, "replace": { diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index a363e253dad4863fa0e3cde0c0fbd3f0c5a6ff1c..5dec88bd1e06cf32d52cfdcdc16481906dac598f 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -81,7 +81,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '8.2.7-dev'; + const VERSION = '8.2.6'; /** * Core API compatibility. diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module index 010177974405a17f28308318969acce97c570b56..f48c51b80fd2c0b34d18b661ac99ff112c5b3d4a 100644 --- a/core/modules/editor/editor.module +++ b/core/modules/editor/editor.module @@ -519,8 +519,8 @@ function editor_file_download($uri) { if ($file->isPermanent()) { $referencing_entity_is_accessible = FALSE; $references = empty($usage_list['editor']) ? [] : $usage_list['editor']; - foreach ($references as $entity_type => $entity_ids) { - $referencing_entities = entity_load_multiple($entity_type, $entity_ids); + foreach ($references as $entity_type => $entity_ids_usage_count) { + $referencing_entities = entity_load_multiple($entity_type, array_keys($entity_ids_usage_count)); /** @var \Drupal\Core\Entity\EntityInterface $referencing_entity */ foreach ($referencing_entities as $referencing_entity) { if ($referencing_entity->access('view', NULL, TRUE)->isAllowed()) { diff --git a/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php b/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php index 5f689b3f0d1759d9023efebc76481adc3d0b908c..354ceede0b35a1b76b5ca736fe8fb3e448fb9617 100644 --- a/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php +++ b/core/modules/editor/src/Tests/EditorPrivateFileReferenceFilterTest.php @@ -68,9 +68,18 @@ function testEditorPrivateFileReferenceFilter() { $file->setPermanent(); $file->save(); + // Create some nodes to ensure file usage count does not match the ID's + // of the nodes we are going to check. + for ($i = 0; $i < 5; $i++) { + $this->drupalCreateNode([ + 'type' => 'page', + 'uid' => $author->id(), + ]); + } + // Create a node with its body field properly pointing to the just-created // file. - $node = $this->drupalCreateNode([ + $published_node = $this->drupalCreateNode([ 'type' => 'page', 'body' => [ 'value' => 'alt', @@ -79,19 +88,44 @@ function testEditorPrivateFileReferenceFilter() { 'uid' => $author->id(), ]); + // Create an unpublished node with its body field properly pointing to the + // just-created file. + $unpublished_node = $this->drupalCreateNode([ + 'type' => 'page', + 'status' => NODE_NOT_PUBLISHED, + 'body' => [ + 'value' => 'alt', + 'format' => 'private_images', + ], + 'uid' => $author->id(), + ]); + // Do the actual test. The image should be visible for anonymous users, - // because they can view the referencing entity. - $this->drupalGet($node->toUrl()); + // because they can view the published node. Even though they can't view + // the unpublished node. + $this->drupalGet($published_node->toUrl()); $this->assertSession()->statusCodeEquals(200); + $this->drupalGet($unpublished_node->toUrl()); + $this->assertSession()->statusCodeEquals(403); $this->drupalGet($src); $this->assertSession()->statusCodeEquals(200); + // When the published node is also unpublished, the image should also + // become inaccessible to anonymous users. + $published_node->setPublished(FALSE)->save(); + + $this->drupalGet($published_node->toUrl()); + $this->assertSession()->statusCodeEquals(403); + $this->drupalGet($src); + $this->assertSession()->statusCodeEquals(403); + // Disallow anonymous users to view the entity, which then should also // disallow them to view the image. + $published_node->setPublished(TRUE)->save(); Role::load(RoleInterface::ANONYMOUS_ID) ->revokePermission('access content') ->save(); - $this->drupalGet($node->toUrl()); + $this->drupalGet($published_node->toUrl()); $this->assertSession()->statusCodeEquals(403); $this->drupalGet($src); $this->assertSession()->statusCodeEquals(403); diff --git a/core/modules/search/search.routing.yml b/core/modules/search/search.routing.yml index ec273f166882e00e6f159d77c33482b74ecc4b5d..98969a6e21c7fa4bc0e71531560aceba79de3f7f 100644 --- a/core/modules/search/search.routing.yml +++ b/core/modules/search/search.routing.yml @@ -37,6 +37,7 @@ entity.search_page.enable: op: 'enable' requirements: _entity_access: 'search_page.update' + _csrf_token: 'TRUE' entity.search_page.disable: path: '/admin/config/search/pages/manage/{search_page}/disable' @@ -45,6 +46,7 @@ entity.search_page.disable: op: 'disable' requirements: _entity_access: 'search_page.disable' + _csrf_token: 'TRUE' entity.search_page.set_default: path: '/admin/config/search/pages/manage/{search_page}/set-default' @@ -52,6 +54,7 @@ entity.search_page.set_default: _controller: '\Drupal\search\Controller\SearchController::setAsDefault' requirements: _entity_access: 'search_page.update' + _csrf_token: 'TRUE' entity.search_page.delete_form: path: '/admin/config/search/pages/manage/{search_page}/delete' diff --git a/core/modules/search/src/Form/SearchBlockForm.php b/core/modules/search/src/Form/SearchBlockForm.php index cd198fd7944df4e5c2396695c620f1ca6b792030..0e623a8778757a779d81e44f24b2dc7b20857d78 100644 --- a/core/modules/search/src/Form/SearchBlockForm.php +++ b/core/modules/search/src/Form/SearchBlockForm.php @@ -75,6 +75,16 @@ public function getFormId() { public function buildForm(array $form, FormStateInterface $form_state) { // Set up the form to submit using GET to the correct search page. $entity_id = $this->searchPageRepository->getDefaultSearchPage(); + + $form = []; + + // SearchPageRepository::getDefaultSearchPage() depends on search.settings. + // The dependency needs to be added before the conditional return, otherwise + // the block would get cached without the necessary cacheablity metadata in + // case there is no default search page and would not be invalidated if that + // changes. + $this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings')); + if (!$entity_id) { $form['message'] = array( '#markup' => $this->t('Search is currently disabled'), @@ -103,9 +113,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#name' => '', ); - // SearchPageRepository::getDefaultSearchPage() depends on search.settings. - $this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings')); - return $form; } diff --git a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php index 9ca87d61987f40ef15fa4a9013c231bd6fe82083..fe93f90687c464c273a72659b40be53dc8a36909 100644 --- a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php +++ b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php @@ -154,8 +154,7 @@ function testSearchModuleDisabling() { // Test each plugin if it's enabled as the only search plugin. foreach ($entities as $entity_id => $entity) { - // Set this as default. - $this->drupalGet("admin/config/search/pages/manage/$entity_id/set-default"); + $this->setDefaultThroughUi($entity_id); // Run a search from the correct search URL. $info = $plugin_info[$entity_id]; @@ -187,13 +186,16 @@ function testSearchModuleDisabling() { $entity->disable()->save(); } + // Set the node search as default. + $this->setDefaultThroughUi('node_search'); + // Test with all search plugins enabled. When you go to the search // page or run search, all plugins should be shown. foreach ($entities as $entity) { $entity->enable()->save(); } - // Set the node search as default. - $this->drupalGet('admin/config/search/pages/manage/node_search/set-default'); + + \Drupal::service('router.builder')->rebuild(); $paths = array( array('path' => 'search/node', 'options' => array('query' => array('keys' => 'pizza'))), @@ -316,6 +318,19 @@ public function testMultipleSearchPages() { $this->verifySearchPageOperations($first_id, FALSE, FALSE, FALSE, FALSE); } + /** + * Tests that the enable/disable/default routes are protected from CSRF. + */ + public function testRouteProtection() { + // Ensure that the enable and disable routes are protected. + $this->drupalGet('admin/config/search/pages/manage/node_search/enable'); + $this->assertResponse(403); + $this->drupalGet('admin/config/search/pages/manage/node_search/disable'); + $this->assertResponse(403); + $this->drupalGet('admin/config/search/pages/manage/node_search/set-default'); + $this->assertResponse(403); + } + /** * Checks that the search page operations match expectations. * @@ -373,4 +388,17 @@ protected function assertDefaultSearch($expected, $message = '', $group = 'Other $this->assertIdentical($search_page_repository->getDefaultSearchPage(), $expected, $message, $group); } + /** + * Sets a search page as the default in the UI. + * + * @param string $entity_id + * The search page entity ID to enable. + */ + protected function setDefaultThroughUi($entity_id) { + $this->drupalGet('admin/config/search/pages'); + preg_match('|href="([^"]+' . $entity_id . '/set-default[^"]+)"|', $this->getRawContent(), $matches); + + $this->drupalGet($this->getAbsoluteUrl($matches[1])); + } + } diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index f54dcf79e71ff52321f69f13352e4ca639fa780e..547de13a417746b74d42c63349e981e6cb25f383 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -1301,7 +1301,7 @@ protected function drupalGet($path, array $options = array(), array $headers = a } if ($path instanceof Url) { - $path = $path->toString(); + $path = $path->setAbsolute()->toString(TRUE)->getGeneratedUrl(); } $verbose = 'GET request to: ' . $path . @@ -2588,7 +2588,7 @@ protected function buildUrl($path, array $options = array()) { $url_options = $path->getOptions(); $options = $url_options + $options; $path->setOptions($options); - return $path->setAbsolute()->toString(); + return $path->setAbsolute()->toString(TRUE)->getGeneratedUrl(); } // The URL generator service is not necessarily available yet; e.g., in // interactive installer tests.