From c7ca868da63a6dad34545f00fe7ade18b899e716 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Fri, 21 Aug 2015 09:23:22 +0100 Subject: [PATCH] Issue #2505931 by stefan.r, akalata, cilefen, pwolanin, joelpittet, YesCT, alexpott, davidhernandez, larowlan, colbol, xjm, Wim Leers, dawehner, Cottser, catch: Remove SafeMarkup::set in ViewListBuilder --- .../system/css/components/item-list.theme.css | 20 +++++++++++++ .../system/templates/item-list.html.twig | 5 ++++ .../views_ui/src/Tests/DisplayPathTest.php | 23 +++++++++++++++ core/modules/views_ui/src/ViewListBuilder.php | 14 ++++----- .../tests/src/Unit/ViewListBuilderTest.php | 29 +++++++++++++++++-- .../bartik/css/components/item-list.css | 7 +++++ .../templates/dataset/item-list.html.twig | 5 ++++ .../seven/css/components/menus-and-lists.css | 3 ++ 8 files changed, 96 insertions(+), 10 deletions(-) diff --git a/core/modules/system/css/components/item-list.theme.css b/core/modules/system/css/components/item-list.theme.css index 49f81725dc09..9a1088e062d5 100644 --- a/core/modules/system/css/components/item-list.theme.css +++ b/core/modules/system/css/components/item-list.theme.css @@ -17,3 +17,23 @@ [dir="rtl"] .item-list ul li { margin: 0 1.5em 0.25em 0; } +ul.item-list__comma-list { + display: inline; +} +ul.item-list__comma-list li { + display: inline; + list-style-type: none; +} +ul.item-list__comma-list, +ul.item-list__comma-list li, +[dir="rtl"] ul.item-list__comma-list, +[dir="rtl"] ul.item-list__comma-list li { + margin: 0; + padding: 0; +} +ul.item-list__comma-list li:after { + content: ", "; +} +ul.item-list__comma-list li:last-child:after { + content: ""; +} diff --git a/core/modules/system/templates/item-list.html.twig b/core/modules/system/templates/item-list.html.twig index 2cef1d022f5d..172799d8f1d8 100644 --- a/core/modules/system/templates/item-list.html.twig +++ b/core/modules/system/templates/item-list.html.twig @@ -12,12 +12,17 @@ * - attributes: HTML attributes to be applied to the list. * - empty: A message to display when there are no items. Allowed value is a * string or render array. + * - context: A list of contextual data associated with the list. May contain: + * - list_style: The custom list style. * * @see template_preprocess_item_list() * * @ingroup themeable */ #} +{% if context.list_style %} + {% set attributes = attributes.addClass('item-list__' ~ context.list_style) %} +{% endif %} {%- if items or empty -%} {%- if title is not empty -%} <h3>{{ title }}</h3> diff --git a/core/modules/views_ui/src/Tests/DisplayPathTest.php b/core/modules/views_ui/src/Tests/DisplayPathTest.php index 004b9f045162..1515b2f8aa45 100644 --- a/core/modules/views_ui/src/Tests/DisplayPathTest.php +++ b/core/modules/views_ui/src/Tests/DisplayPathTest.php @@ -35,6 +35,7 @@ class DisplayPathTest extends UITestBase { public function testPathUI() { $this->doBasicPathUITest(); $this->doAdvancedPathsValidationTest(); + $this->doPathXssFilterTest(); } /** @@ -59,6 +60,28 @@ protected function doBasicPathUITest() { $this->assertLink(t('View @display', array('@display' => 'Page')), 0, 'view page link found on the page.'); } + /** + * Tests that View paths are properly filtered for XSS. + */ + public function doPathXssFilterTest() { + $this->drupalGet('admin/structure/views/view/test_view'); + $this->drupalPostForm(NULL, array(), 'Add Page'); + $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_2/path', array('path' => '<object>malformed_path</object>'), t('Apply')); + $this->drupalPostForm(NULL, array(), 'Add Page'); + $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_3/path', array('path' => '<script>alert("hello");</script>'), t('Apply')); + $this->drupalPostForm(NULL, array(), 'Add Page'); + $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_4/path', array('path' => '<script>alert("hello I have placeholders %");</script>'), t('Apply')); + $this->drupalPostForm('admin/structure/views/view/test_view', array(), t('Save')); + $this->drupalGet('admin/structure/views'); + // The anchor text should be escaped. + $this->assertEscaped('/<object>malformed_path</object>'); + $this->assertEscaped('/<script>alert("hello");</script>'); + $this->assertEscaped('/<script>alert("hello I have placeholders %");</script>'); + // Links should be url-encoded. + $this->assertRaw('/%3Cobject%3Emalformed_path%3C/object%3E'); + $this->assertRaw('/%3Cscript%3Ealert%28%22hello%22%29%3B%3C/script%3E'); + } + /** * Tests a couple of invalid path patterns. */ diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php index 00be178a092f..16abf608b276 100644 --- a/core/modules/views_ui/src/ViewListBuilder.php +++ b/core/modules/views_ui/src/ViewListBuilder.php @@ -91,12 +91,6 @@ public function load() { */ public function buildRow(EntityInterface $view) { $row = parent::buildRow($view); - $display_paths = ''; - $separator = ''; - foreach ($this->getDisplayPaths($view) as $display_path) { - $display_paths .= $separator . SafeMarkup::escape($display_path); - $separator = ', '; - } return array( 'data' => array( 'view_name' => array( @@ -113,7 +107,13 @@ public function buildRow(EntityInterface $view) { 'class' => array('views-table-filter-text-source'), ), 'tag' => $view->get('tag'), - 'path' => SafeMarkup::set($display_paths), + 'path' => array( + 'data' => array( + '#theme' => 'item_list', + '#items' => $this->getDisplayPaths($view), + '#context' => ['list_style' => 'comma-list'], + ), + ), 'operations' => $row['operations'], ), 'title' => $this->t('Machine name: @name', array('@name' => $view->id())), diff --git a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php index a42a879e22ce..d4bc2b6bd1e7 100644 --- a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php +++ b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php @@ -89,7 +89,10 @@ public function testBuildRowEntityList() { ); $page_display->expects($this->any()) ->method('getPath') - ->will($this->returnValue('test_page')); + ->will($this->onConsecutiveCalls( + $this->returnValue('test_page'), + $this->returnValue('<object>malformed_path</object>'), + $this->returnValue('<script>alert("placeholder_page/%")</script>'))); $embed_display = $this->getMock('Drupal\views\Plugin\views\display\Embed', array('initDisplay'), array(array(), 'default', $display_manager->getDefinition('embed')) @@ -106,6 +109,16 @@ public function testBuildRowEntityList() { $values['display']['page_1']['display_plugin'] = 'page'; $values['display']['page_1']['display_options']['path'] = 'test_page'; + $values['display']['page_2']['id'] = 'page_2'; + $values['display']['page_2']['display_title'] = 'Page 2'; + $values['display']['page_2']['display_plugin'] = 'page'; + $values['display']['page_2']['display_options']['path'] = '<object>malformed_path</object>'; + + $values['display']['page_3']['id'] = 'page_3'; + $values['display']['page_3']['display_title'] = 'Page 3'; + $values['display']['page_3']['display_plugin'] = 'page'; + $values['display']['page_3']['display_options']['path'] = '<script>alert("placeholder_page/%")</script>'; + $values['display']['embed']['id'] = 'embed'; $values['display']['embed']['display_title'] = 'Embedded'; $values['display']['embed']['display_plugin'] = 'embed'; @@ -115,6 +128,8 @@ public function testBuildRowEntityList() { ->will($this->returnValueMap(array( array('default', $values['display']['default'], $default_display), array('page', $values['display']['page_1'], $page_display), + array('page', $values['display']['page_2'], $page_display), + array('page', $values['display']['page_3'], $page_display), array('embed', $values['display']['embed'], $embed_display), ))); @@ -141,8 +156,16 @@ public function testBuildRowEntityList() { $row = $view_list_builder->buildRow($view); - $this->assertEquals(array('Embed admin label', 'Page admin label'), $row['data']['view_name']['data']['#displays'], 'Wrong displays got added to view list'); - $this->assertEquals($row['data']['path'], '/test_page', 'The path of the page display is not added.'); + $expected_displays = array( + 'Embed admin label', + 'Page admin label', + 'Page admin label', + 'Page admin label', + ); + $this->assertEquals($expected_displays, $row['data']['view_name']['data']['#displays']); + + $display_paths = $row['data']['path']['data']['#items']; + $this->assertEquals('/test_page, /<object>malformed_path</object>, /<script>alert("placeholder_page/%")</script>', implode(', ', $display_paths)); } } diff --git a/core/themes/bartik/css/components/item-list.css b/core/themes/bartik/css/components/item-list.css index eeb4e77b8174..698bd56c81ca 100644 --- a/core/themes/bartik/css/components/item-list.css +++ b/core/themes/bartik/css/components/item-list.css @@ -10,3 +10,10 @@ [dir="rtl"] .item-list ul li { padding: 0.2em 0 0 0.5em; } +.item-list .item-list__comma-list, +.item-list .item-list__comma-list li, +[dir="rtl"] .item-list .item-list__comma-list, +[dir="rtl"] .item-list .item-list__comma-list li { + margin: 0; + padding: 0; +} diff --git a/core/themes/classy/templates/dataset/item-list.html.twig b/core/themes/classy/templates/dataset/item-list.html.twig index 0f17cdfc3fe8..7ba8be4910de 100644 --- a/core/themes/classy/templates/dataset/item-list.html.twig +++ b/core/themes/classy/templates/dataset/item-list.html.twig @@ -12,10 +12,15 @@ * - attributes: HTML attributes to be applied to the list. * - empty: A message to display when there are no items. Allowed value is a * string or render array. + * - context: A list of contextual data associated with the list. May contain: + * - list_style: The custom list style. * * @see template_preprocess_item_list() */ #} +{% if context.list_style %} + {% set attributes = attributes.addClass('item-list__' ~ context.list_style) %} +{% endif %} {%- if items or empty -%} <div class="item-list"> {%- if title is not empty -%} diff --git a/core/themes/seven/css/components/menus-and-lists.css b/core/themes/seven/css/components/menus-and-lists.css index d96fe5516b82..6f87c4c52c6b 100644 --- a/core/themes/seven/css/components/menus-and-lists.css +++ b/core/themes/seven/css/components/menus-and-lists.css @@ -38,3 +38,6 @@ ul.inline li { ul.inline li { display: inline; } +[dir="rtl"] ul.item-list__comma-list { + margin: 0; +} -- GitLab