diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 6f05be09ada3c0f1a66445313fc87317c4925968..329ff58c626d5fbe663e419131064941de1135ce 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -20,7 +20,6 @@ use Drupal\Core\Theme\ThemeSettings; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Render\Element; -use Drupal\Core\Render\SafeString; /** * @defgroup content_flags Content markers @@ -1242,8 +1241,7 @@ function template_preprocess_html(&$variables) { } if (!empty($variables['page']['#title'])) { $head_title = array( - // Marking the title as safe since it has had the tags stripped. - 'title' => SafeString::create(trim(strip_tags($variables['page']['#title']))), + 'title' => trim(strip_tags($variables['page']['#title'])), 'name' => $site_config->get('name'), ); } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php index 9d2b7306fc3e83d012cf3db4b8406c437e5274cf..c03b96d2018253711c8460594a9fceb73c706506 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter; -use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\FieldItemListInterface; @@ -37,7 +37,7 @@ public function viewElements(FieldItemListInterface $items) { foreach ($items as $delta => $item) { // The text value has no text format assigned to it, so the user input // should equal the output, including newlines. - $elements[$delta] = array('#markup' => nl2br(Html::escape($item->value))); + $elements[$delta] = array('#markup' => nl2br(SafeMarkup::checkPlain($item->value))); } return $elements; diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php index e4b41b82b8866a31c05cc608f84fe45797041cb1..dea2989ad8b5c3641a200fc2fe13f294b7ee3690 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemInterface; @@ -122,9 +123,7 @@ protected function viewValue(FieldItemInterface $item) { // storage by LanguageManager::getLanguages()) or in its native language // name. That only depends on formatter settings and no language condition. $languages = $this->getSetting('native_language') ? $this->languageManager->getNativeLanguages(LanguageInterface::STATE_ALL) : $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); - return [ - '#plain_text' => $item->language && isset($languages[$item->language->getId()]) ? $languages[$item->language->getId()]->getName() : '' - ]; + return $item->language && isset($languages[$item->language->getId()]) ? SafeMarkup::checkPlain($languages[$item->language->getId()]->getName()) : ''; } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php index fd5c3bbb5027cc8f9aabc075a101b7bff31aeec2..6276f9538c3ebadf19a67ebb579c2929c949f5c7 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter; -use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\RevisionableInterface; use Drupal\Core\Field\FieldDefinitionInterface; @@ -128,16 +128,16 @@ public function viewElements(FieldItemListInterface $items) { } foreach ($items as $delta => $item) { - $view_value = $this->viewValue($item); + $string = $this->viewValue($item); if ($url) { $elements[$delta] = [ '#type' => 'link', - '#title' => $view_value, + '#title' => $string, '#url' => $url, ]; } else { - $elements[$delta] = is_array($view_value) ? $view_value : ['#markup' => $view_value]; + $elements[$delta] = ['#markup' => $string]; } } return $elements; @@ -149,15 +149,13 @@ public function viewElements(FieldItemListInterface $items) { * @param \Drupal\Core\Field\FieldItemInterface $item * One field item. * - * @return array - * The textual output generated as a render array. + * @return string + * The textual output generated. */ protected function viewValue(FieldItemInterface $item) { // The text value has no text format assigned to it, so the user input // should equal the output, including newlines. - return [ - '#markup' => nl2br(Html::escape($item->value)) - ]; + return nl2br(SafeMarkup::checkPlain($item->value)); } } diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index 575daf925308cb72d29a26cd2b0d92bcacada3e1..0103071cd3113ae4ca648add6ec56b0b1e33a357 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\SortArray; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; use Symfony\Component\Validator\ConstraintViolationInterface; @@ -84,7 +85,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter if ($this->handlesMultipleValues() || isset($get_delta)) { $delta = isset($get_delta) ? $get_delta : 0; $element = array( - '#title' => $this->fieldDefinition->getLabel(), + '#title' => SafeMarkup::checkPlain($this->fieldDefinition->getLabel()), '#description' => FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription())), ); $element = $this->formSingleElement($items, $delta, $element, $form, $form_state); @@ -163,7 +164,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f break; } - $title = $this->fieldDefinition->getLabel(); + $title = SafeMarkup::checkPlain($this->fieldDefinition->getLabel()); $description = FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription())); $elements = array(); @@ -178,7 +179,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f // table. if ($is_multiple) { $element = [ - '#title' => $this->t('@title (value @number)', ['@title' => $title, '@number' => $delta + 1]), + '#title' => $title . ' ' . $this->t('(value @number)', ['@number' => $delta + 1]), '#title_display' => 'invisible', '#description' => '', ]; diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php index 9a582352343ef6f179adc3229fcd3d395b2e2857..6e99faae00de324a85670de6065220cd6c56a0ea 100644 --- a/core/modules/block/src/BlockViewBuilder.php +++ b/core/modules/block/src/BlockViewBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\block; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Block\MainContentBlockPluginInterface; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableMetadata; @@ -163,6 +164,8 @@ protected static function buildPreRenderableBlock($entity, ModuleHandlerInterfac '#block' => $entity, ]; + $build['#configuration']['label'] = SafeMarkup::checkPlain($configuration['label']); + // If an alter hook wants to modify the block contents, it can append // another #pre_render hook. $module_handler->alter(['block_view', "block_view_$base_id"], $build, $plugin); diff --git a/core/modules/block/src/Controller/BlockLibraryController.php b/core/modules/block/src/Controller/BlockLibraryController.php index 972dd73155d7f07edde83592116ca811605d64ef..2a0148fda0f10a47473369a8de9df17c822faae2 100644 --- a/core/modules/block/src/Controller/BlockLibraryController.php +++ b/core/modules/block/src/Controller/BlockLibraryController.php @@ -8,6 +8,7 @@ namespace Drupal\block\Controller; use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Block\BlockManagerInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; @@ -108,7 +109,7 @@ public function listBlocks(Request $request, $theme) { '#prefix' => '<div class="block-filter-text-source">', '#suffix' => '</div>', ]; - $row['category']['data'] = $plugin_definition['category']; + $row['category']['data'] = SafeMarkup::checkPlain($plugin_definition['category']); $links['add'] = [ 'title' => $this->t('Place block'), 'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]), diff --git a/core/modules/color/color.module b/core/modules/color/color.module index 46ddce5f18edd31d9db0b4ee254536f5852c8e9c..fa9499b1011202d84a4d1eaf1bbde10f903e63b1 100644 --- a/core/modules/color/color.module +++ b/core/modules/color/color.module @@ -8,6 +8,7 @@ use Drupal\Core\Asset\CssOptimizer; use Drupal\Component\Utility\Bytes; use Drupal\Component\Utility\Environment; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Cache\Cache; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; @@ -250,7 +251,7 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them if (isset($names[$name])) { $form['palette'][$name] = array( '#type' => 'textfield', - '#title' => $names[$name], + '#title' => SafeMarkup::checkPlain($names[$name]), '#value_callback' => 'color_palette_color_value', '#default_value' => $value, '#size' => 8, diff --git a/core/modules/comment/src/CommentTypeListBuilder.php b/core/modules/comment/src/CommentTypeListBuilder.php index f8a34510266d74da01c54b61924c63371a691376..4f998718e9d580e9cda95a9205366ebfa85bc3a9 100644 --- a/core/modules/comment/src/CommentTypeListBuilder.php +++ b/core/modules/comment/src/CommentTypeListBuilder.php @@ -7,6 +7,8 @@ namespace Drupal\comment; +use Drupal\Component\Utility\SafeMarkup; +use Drupal\Component\Utility\Xss; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; @@ -43,7 +45,7 @@ public function buildHeader() { * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { - $row['type'] = $entity->label(); + $row['type'] = SafeMarkup::checkPlain($entity->label()); $row['description']['data'] = ['#markup' => $entity->getDescription()]; return $row + parent::buildRow($entity); } diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php index c6e8a491639f3f3578468acd31b787abeb9c357b..74e276a9d591e823eb5d4878c50312412c43dfb9 100644 --- a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php +++ b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\config_translation\Controller; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -69,12 +70,12 @@ public function buildRow(EntityInterface $entity) { ); $row['theme'] = array( - 'data' => $this->themes[$theme]->info['name'], + 'data' => SafeMarkup::checkPlain($this->themes[$theme]->info['name']), 'class' => 'table-filter-text-source', ); $row['category'] = array( - 'data' => $plugin_definition['category'], + 'data' => SafeMarkup::checkPlain($plugin_definition['category']), 'class' => 'table-filter-text-source', ); diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php index 282d3eb4915d1061edb75007932248e69b6a7a53..1b2a08b6b036c3c3d9c25c77ee21a301cc7bde42 100644 --- a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php +++ b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\config_translation\Controller; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; @@ -122,7 +123,7 @@ public function buildRow(EntityInterface $entity) { if ($this->displayBundle()) { $bundle = $entity->get('bundle'); $row['bundle'] = array( - 'data' => $this->baseEntityBundles[$bundle]['label'], + 'data' => SafeMarkup::checkPlain($this->baseEntityBundles[$bundle]['label']), 'class' => 'table-filter-text-source', ); } diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php b/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php index 5c954526323d8713926d4562469b67abc5217b6e..e32714b975cd0a697ef66a05519d2337d96e079a 100644 --- a/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php +++ b/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php @@ -7,6 +7,7 @@ namespace Drupal\config_translation\Controller; +use Drupal\Component\Utility\SafeMarkup; use Drupal\config_translation\ConfigMapperInterface; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -93,7 +94,7 @@ public function render() { * A render array structure of fields for this mapper. */ public function buildRow(ConfigMapperInterface $mapper) { - $row['label'] = $mapper->getTypeLabel(); + $row['label'] = SafeMarkup::checkPlain($mapper->getTypeLabel()); $row['operations']['data'] = $this->buildOperations($mapper); return $row; } diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php index eb5cf75c5aaa7f2c333c13a5da77bf7c538fa51e..221b7d6680ea910a6106c7eed67a3a7c6dd1084e 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php @@ -7,6 +7,7 @@ namespace Drupal\config_translation\Tests; +use Drupal\Component\Utility\SafeMarkup; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\simpletest\WebTestBase; @@ -102,7 +103,7 @@ public function testMapperListPage() { $base_url = 'admin/structure/config_test/manage/' . $test_entity->id(); $this->drupalGet('admin/config/regional/config-translation/config_test'); $this->assertLinkByHref($base_url . '/translate'); - $this->assertEscaped($test_entity->label()); + $this->assertText(SafeMarkup::checkPlain($test_entity->label())); // Make sure there is only a single 'Translate' operation for each // dropbutton. diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php index e4a4e3fde2f944215d03cf9d9b3a37d34604ce4d..41840ad96b9669e1e816a570e7dbbb5b7216f630 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php @@ -753,9 +753,9 @@ public function testFieldConfigTranslation() { $this->clickLink('Add'); $this->assertText('Translatable field setting'); - $this->assertEscaped($translatable_field_setting); + $this->assertRaw(SafeMarkup::checkPlain($translatable_field_setting)); $this->assertText('Translatable storage setting'); - $this->assertEscaped($translatable_storage_setting); + $this->assertRaw(SafeMarkup::checkPlain($translatable_storage_setting)); } /** diff --git a/core/modules/contact/src/Controller/ContactController.php b/core/modules/contact/src/Controller/ContactController.php index 1abd33c58f362bfd7dd9b0c23b3ccccb1fdc6406..7233bb8747931871085369398defc763b79f8e4b 100644 --- a/core/modules/contact/src/Controller/ContactController.php +++ b/core/modules/contact/src/Controller/ContactController.php @@ -11,6 +11,7 @@ use Drupal\contact\ContactFormInterface; use Drupal\Core\Render\RendererInterface; use Drupal\user\UserInterface; +use Drupal\Component\Utility\SafeMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -86,7 +87,7 @@ public function contactSitePage(ContactFormInterface $contact_form = NULL) { )); $form = $this->entityFormBuilder()->getForm($message); - $form['#title'] = $contact_form->label(); + $form['#title'] = SafeMarkup::checkPlain($contact_form->label()); $form['#cache']['contexts'][] = 'user.permissions'; $this->renderer->addCacheableDependency($form, $config); return $form; diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php index eff66268aebc8b73bb083d7963aa20222fbcffb4..08d826bc0eab1c9d99d4490bc03d18a51954997b 100644 --- a/core/modules/dblog/src/Controller/DbLogController.php +++ b/core/modules/dblog/src/Controller/DbLogController.php @@ -8,7 +8,9 @@ namespace Drupal\dblog\Controller; use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; +use Drupal\Component\Utility\Xss; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Database\Connection; use Drupal\Core\Datetime\DateFormatter; @@ -281,7 +283,7 @@ public function eventDetails($event_id) { ), array( array('data' => $this->t('Hostname'), 'header' => TRUE), - $dblog->hostname, + SafeMarkup::checkPlain($dblog->hostname), ), array( array('data' => $this->t('Operations'), 'header' => TRUE), diff --git a/core/modules/field/src/Tests/String/UuidFormatterTest.php b/core/modules/field/src/Tests/String/UuidFormatterTest.php index 4d849cda8d168e9993dc39bd1bbad8ced22fc08e..2eaf7e9424664bf026092a32a7ddd1a0aaca7087 100644 --- a/core/modules/field/src/Tests/String/UuidFormatterTest.php +++ b/core/modules/field/src/Tests/String/UuidFormatterTest.php @@ -51,7 +51,7 @@ public function testUuidStringFormatter() { $render_array = $uuid_field->view(['settings' => ['link_to_entity' => TRUE]]); $this->assertIdentical($render_array[0]['#type'], 'link'); - $this->assertIdentical($render_array[0]['#title']['#markup'], $entity->uuid()); + $this->assertIdentical($render_array[0]['#title'], $entity->uuid()); $this->assertIdentical($render_array[0]['#url']->toString(), $entity->url()); } diff --git a/core/modules/field_ui/src/FieldConfigListBuilder.php b/core/modules/field_ui/src/FieldConfigListBuilder.php index 1dd2c7cc86c5ee46a0de1ce5d4adf11375ee5a26..d3feac1257f0ab5881c52e123b1433ab46a58073 100644 --- a/core/modules/field_ui/src/FieldConfigListBuilder.php +++ b/core/modules/field_ui/src/FieldConfigListBuilder.php @@ -8,6 +8,7 @@ namespace Drupal\field_ui; use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; @@ -130,7 +131,7 @@ public function buildRow(EntityInterface $field_config) { $row = array( 'id' => Html::getClass($field_config->getName()), 'data' => array( - 'label' => $field_config->getLabel(), + 'label' => SafeMarkup::checkPlain($field_config->getLabel()), 'field_name' => $field_config->getName(), 'field_type' => array( 'data' => array( diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php index 31d5e0571f4a4180b5b84144c4fbcb7078c13959..865471200a9ee64d8390e87d17ed931af51de015 100644 --- a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php @@ -56,17 +56,17 @@ public function viewElements(FieldItemListInterface $items) { } foreach ($items as $delta => $item) { - $view_value = $this->viewValue($item); + $string = $this->viewValue($item); if ($url) { $elements[$delta] = [ '#type' => 'link', - '#title' => $view_value, + '#title' => $string, '#url' => Url::fromUri($url), ]; } else { - $elements[$delta] = is_array($view_value) ? $view_value : ['#markup' => $view_value]; + $elements[$delta] = is_array($string) ? $string : ['#markup' => $string]; } } diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php index acba472018a67cc5b60dc496d90230c2f62cba48..fb69d9cd9240eadb66b9be5900a79ba5cc429704 100644 --- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php +++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php @@ -7,6 +7,7 @@ namespace Drupal\file\Plugin\Field\FieldWidget; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldFilteredString; @@ -118,7 +119,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f break; } - $title = $this->fieldDefinition->getLabel(); + $title = SafeMarkup::checkPlain($this->fieldDefinition->getLabel()); $description = FieldFilteredString::create($this->fieldDefinition->getDescription()); $elements = array(); diff --git a/core/modules/filter/src/FilterFormatListBuilder.php b/core/modules/filter/src/FilterFormatListBuilder.php index 685112a761974c2f7766960f287c167deb283bd8..5ae317e4f0fca958d070277b2e48712bdeaeba9c 100644 --- a/core/modules/filter/src/FilterFormatListBuilder.php +++ b/core/modules/filter/src/FilterFormatListBuilder.php @@ -98,10 +98,10 @@ public function buildRow(EntityInterface $entity) { if ($entity->isFallbackFormat()) { $fallback_choice = $this->configFactory->get('filter.settings')->get('always_show_fallback_choice'); if ($fallback_choice) { - $row['roles']['#markup'] = $this->t('All roles may use this format'); + $roles_markup = $this->t('All roles may use this format'); } else { - $row['roles']['#markup'] = $this->t('This format is shown when no other formats are available'); + $roles_markup = $this->t('This format is shown when no other formats are available'); } // Emphasize the fallback role text since it is important to understand // how it works which configuring filter formats. Additionally, it is not @@ -110,14 +110,12 @@ public function buildRow(EntityInterface $entity) { $row['roles']['#suffix'] = '</em>'; } else { - $row['roles'] = [ - '#theme' => 'item_list', - '#items' => filter_get_roles_by_format($entity), - '#empty' => $this->t('No roles may use this format'), - '#context' => ['list_style' => 'comma-list'], - ]; + $roles = array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', filter_get_roles_by_format($entity)); + $roles_markup = $roles ? implode(', ', $roles) : $this->t('No roles may use this format'); } + $row['roles']['#markup'] = $roles_markup; + return $row + parent::buildRow($entity); } diff --git a/core/modules/filter/src/Plugin/Filter/FilterHtml.php b/core/modules/filter/src/Plugin/Filter/FilterHtml.php index 4708cc6f1c386d7986161a3745959e6fdf37c384..63e3f5706ae516a1c2c0ca46871c2971b81512d7 100644 --- a/core/modules/filter/src/Plugin/Filter/FilterHtml.php +++ b/core/modules/filter/src/Plugin/Filter/FilterHtml.php @@ -149,7 +149,7 @@ public function tips($long = FALSE) { array('data' => array( '#prefix' => '<code>', - '#plain_text' => $tips[$tag][1], + '#markup' => Html::escape($tips[$tag][1]), '#suffix' => '</code>' ), 'class' => array('type')), @@ -193,7 +193,7 @@ public function tips($long = FALSE) { array( 'data' => array( '#prefix' => '<code>', - '#plain_text' => $entity[1], + '#markup' => Html::escape($entity[1]), '#suffix' => '</code>', ), 'class' => array('type'), diff --git a/core/modules/help/src/Controller/HelpController.php b/core/modules/help/src/Controller/HelpController.php index 4ebd4c8ef3b857018d4611468af3c003b690a168..802f9d9c1a52108692eea42375772e5e3515fa84 100644 --- a/core/modules/help/src/Controller/HelpController.php +++ b/core/modules/help/src/Controller/HelpController.php @@ -12,6 +12,7 @@ use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Drupal\Component\Utility\SafeMarkup; /** * Controller routines for help routes. @@ -114,7 +115,7 @@ public function helpPage($name) { $build = array(); if ($this->moduleHandler()->implementsHook($name, 'help')) { $module_name = $this->moduleHandler()->getName($name); - $build['#title'] = $module_name; + $build['#title'] = SafeMarkup::checkPlain($module_name); $temp = $this->moduleHandler()->invoke($name, 'help', array("help.page.$name", $this->routeMatch)); if (empty($temp)) { diff --git a/core/modules/language/src/Form/NegotiationConfigureForm.php b/core/modules/language/src/Form/NegotiationConfigureForm.php index 7f230451577ad7863053f592d3625fec721aa549..938564e11a885166e02c484a676672fbcd14cf5f 100644 --- a/core/modules/language/src/Form/NegotiationConfigureForm.php +++ b/core/modules/language/src/Form/NegotiationConfigureForm.php @@ -8,6 +8,7 @@ namespace Drupal\language\Form; use Drupal\Core\Block\BlockManagerInterface; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\Xss; use Drupal\Core\Config\ConfigFactoryInterface; @@ -276,22 +277,22 @@ protected function configureFormTable(array &$form, $type) { if (isset($types[$type])) { $table_form['#language_negotiation_info'][$method_id] = $method; - $method_name = $method['name']; + $method_name = SafeMarkup::checkPlain($method['name']); $table_form['weight'][$method_id] = array( '#type' => 'weight', - '#title' => $this->t('Weight for @title language detection method', array('@title' => Unicode::strtolower($method_name))), + '#title' => $this->t('Weight for !title language detection method', array('!title' => Unicode::strtolower($method_name))), '#title_display' => 'invisible', '#default_value' => $weight, '#attributes' => array('class' => array("language-method-weight-$type")), '#delta' => 20, ); - $table_form['title'][$method_id] = array('#plain_text' => $method_name); + $table_form['title'][$method_id] = array('#markup' => $method_name); $table_form['enabled'][$method_id] = array( '#type' => 'checkbox', - '#title' => $this->t('Enable @title language detection method', array('@title' => Unicode::strtolower($method_name))), + '#title' => $this->t('Enable !title language detection method', array('!title' => Unicode::strtolower($method_name))), '#title_display' => 'invisible', '#default_value' => $enabled, ); diff --git a/core/modules/locale/src/Form/TranslateEditForm.php b/core/modules/locale/src/Form/TranslateEditForm.php index dbd450a12e9a4421b5e95e92eb172ecec55e4822..e9c5359d61d1ccec6035ffd758946d8bd4d79fff 100644 --- a/core/modules/locale/src/Form/TranslateEditForm.php +++ b/core/modules/locale/src/Form/TranslateEditForm.php @@ -7,6 +7,7 @@ namespace Drupal\locale\Form; +use Drupal\Component\Utility\Html; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; use Drupal\locale\SourceString; @@ -72,9 +73,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'item', '#title' => $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))), '#title_display' => 'invisible', - '#plain_text' => $source_array[0], - '#preffix' => '<span lang="en">', - '#suffix' => '</span>', + '#markup' => '<span lang="en">' . Html::escape($source_array[0]) . '</span>', ); } else { @@ -83,16 +82,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { $original_singular = [ '#type' => 'item', '#title' => $this->t('Singular form'), - '#plain_text' => $source_array[0], - '#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span><span lang="en">', - '#suffix' => '</span>', + '#markup' => '<span lang="en">' . Html::escape($source_array[0]) . '</span>', + '#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span>', ]; $original_plural = [ '#type' => 'item', '#title' => $this->t('Plural form'), - '#plain_text' => $source_array[1], - '#preffix' => '<span lang="en">', - '#suffix' => '</span>', + '#markup' => '<span lang="en">' . Html::escape($source_array[1]) . '</span>', ]; $form['strings'][$string->lid]['original'] = [ $original_singular, diff --git a/core/modules/locale/src/Form/TranslationStatusForm.php b/core/modules/locale/src/Form/TranslationStatusForm.php index f71ec525f33c780a8d2dc314a9d0573c17ab8325..d2571399a74009715b78b5d4c9465374ec2f0d8b 100644 --- a/core/modules/locale/src/Form/TranslationStatusForm.php +++ b/core/modules/locale/src/Form/TranslationStatusForm.php @@ -7,6 +7,7 @@ namespace Drupal\locale\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; @@ -81,7 +82,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Build data options for the select table. foreach ($updates as $langcode => $update) { - $title = $languages[$langcode]->getName(); + $title = SafeMarkup::checkPlain($languages[$langcode]->getName()); $locale_translation_update_info = array('#theme' => 'locale_translation_update_info'); foreach (array('updates', 'not_found') as $update_status) { if (isset($update[$update_status])) { @@ -93,7 +94,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { 'class' => array('label'), 'data' => array( '#title' => $title, - '#plain_text' => $title, + '#markup' => $title, ), ), 'status' => array( diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index 26f28763aebab56dc87ae1545217a09e5eb01ab1..7acbfc9296f6b7a82726ef0d8d7b86449f78369e 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\node; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Datetime\DateFormatter; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityListBuilder; @@ -118,7 +119,7 @@ public function buildRow(EntityInterface $entity) { '#suffix' => ' ' . drupal_render($mark), '#url' => $uri, ); - $row['type'] = node_get_type_label($entity); + $row['type'] = SafeMarkup::checkPlain(node_get_type_label($entity)); $row['author']['data'] = array( '#theme' => 'username', '#account' => $entity->getOwner(), diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php index 24b47b3545e1d4a8c98a546aa0a02135e8dbe237..ff757f98b37921cb54fd5a1fce081a4349dd2040 100644 --- a/core/modules/node/src/NodeTypeForm.php +++ b/core/modules/node/src/NodeTypeForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; @@ -54,7 +55,7 @@ public function form(array $form, FormStateInterface $form_state) { $type = $this->entity; if ($this->operation == 'add') { - $form['#title'] = $this->t('Add content type'); + $form['#title'] = SafeMarkup::checkPlain($this->t('Add content type')); $fields = $this->entityManager->getBaseFieldDefinitions('node'); // Create a node with a fake bundle using the type's UUID so that we can // get the default values for workflow settings. diff --git a/core/modules/node/src/Plugin/Search/NodeSearch.php b/core/modules/node/src/Plugin/Search/NodeSearch.php index ce5ddb66aefc3d996f5b35d8bb2632db768d7a2a..bab5cc953ec4d39f6fad8f4df14dc5fe9d73f9d7 100644 --- a/core/modules/node/src/Plugin/Search/NodeSearch.php +++ b/core/modules/node/src/Plugin/Search/NodeSearch.php @@ -7,6 +7,7 @@ namespace Drupal\node\Plugin\Search; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Access\AccessResult; use Drupal\Core\Config\Config; use Drupal\Core\Database\Connection; @@ -345,7 +346,7 @@ protected function prepareResults(StatementInterface $found) { $result = array( 'link' => $node->url('canonical', array('absolute' => TRUE, 'language' => $language)), - 'type' => $type->label(), + 'type' => SafeMarkup::checkPlain($type->label()), 'title' => $node->label(), 'node' => $node, 'extra' => $extra, @@ -445,15 +446,9 @@ protected function indexNode(NodeInterface $node) { $build = $node_render->view($node, 'search_index', $language->getId()); unset($build['#theme']); + $rendered = $this->renderer->renderPlain($build); - // Add the title to text so it is searchable. - $build['search_title'] = [ - '#prefix' => '<h1>', - '#plain_text' => $node->label($language->getId()), - '#suffix' => '</h1>', - '#weight' => -1000 - ]; - $text = $this->renderer->renderPlain($build); + $text = '<h1>' . SafeMarkup::checkPlain($node->label($language->getId())) . '</h1>' . $rendered; // Fetch extra data normally not visible. $extra = $this->moduleHandler->invokeAll('node_update_index', array($node, $language->getId())); diff --git a/core/modules/node/src/Tests/NodeTitleTest.php b/core/modules/node/src/Tests/NodeTitleTest.php index 40460a6a58a1ecadc68c67d83c88cae254626256..ddf1fc62021c188510124266839c7438badefea4 100644 --- a/core/modules/node/src/Tests/NodeTitleTest.php +++ b/core/modules/node/src/Tests/NodeTitleTest.php @@ -8,7 +8,6 @@ namespace Drupal\node\Tests; use Drupal\comment\Tests\CommentTestTrait; -use Drupal\Component\Utility\Html; /** * Tests node title. @@ -86,22 +85,5 @@ function testNodeTitle() { // Test that 0 appears in the template <h1>. $xpath = '//h1'; $this->assertEqual(current($this->xpath($xpath)), 0, 'Node title is displayed as 0.', 'Node'); - - // Test edge case where node title contains special characters. - $edge_case_title = 'article\'s "title".'; - $settings = array( - 'title' => $edge_case_title, - ); - $node = $this->drupalCreateNode($settings); - // Test that the title appears as <title>. The title will be escaped on the - // the page. - $edge_case_title_escaped = Html::escape($edge_case_title); - $this->drupalGet('node/' . $node->id()); - $this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node'); - - // Test that the title appears as <title> when reloading the node page. - $this->drupalGet('node/' . $node->id()); - $this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node'); - } } diff --git a/core/modules/node/src/Tests/NodeTitleXSSTest.php b/core/modules/node/src/Tests/NodeTitleXSSTest.php index 70e4498e2f027577d7431c856a6ced45bdaf22ad..f0e80eaf4f175282f3b056d7a4a55e67b9e273e5 100644 --- a/core/modules/node/src/Tests/NodeTitleXSSTest.php +++ b/core/modules/node/src/Tests/NodeTitleXSSTest.php @@ -7,8 +7,6 @@ namespace Drupal\node\Tests; -use Drupal\Component\Utility\Html; - /** * Create a node with dangerous tags in its title and test that they are * escaped. @@ -36,8 +34,8 @@ function testNodeTitleXSS() { $node = $this->drupalCreateNode($settings); $this->drupalGet('node/' . $node->id()); - // Titles should be escaped. - $this->assertTitle(Html::escape($title) . ' | Drupal', 'Title is displayed when viewing a node.'); + // assertTitle() decodes HTML-entities inside the <title> element. + $this->assertTitle($title . ' | Drupal', 'Title is displayed when viewing a node.'); $this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.'); $this->drupalGet('node/' . $node->id() . '/edit'); diff --git a/core/modules/path/src/Form/EditForm.php b/core/modules/path/src/Form/EditForm.php index a1f4a771186791e8d37a479c0a8d4fdb223ed8fb..fc85a42e095a099536915de7e3b8a017432cc14f 100644 --- a/core/modules/path/src/Form/EditForm.php +++ b/core/modules/path/src/Form/EditForm.php @@ -7,6 +7,7 @@ namespace Drupal\path\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; @@ -35,7 +36,7 @@ protected function buildPath($pid) { public function buildForm(array $form, FormStateInterface $form_state, $pid = NULL) { $form = parent::buildForm($form, $form_state, $pid); - $form['#title'] = $this->path['alias']; + $form['#title'] = SafeMarkup::checkPlain($this->path['alias']); $form['pid'] = array( '#type' => 'hidden', '#value' => $this->path['pid'], diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php index eaf4b4195d100fbb819a5f31ba263f20c73d00f6..c6019434fdb5445e7d45832eed296e07ddaa8103 100644 --- a/core/modules/simpletest/src/AssertContentTrait.php +++ b/core/modules/simpletest/src/AssertContentTrait.php @@ -775,19 +775,14 @@ protected function assertTextPattern($pattern, $message = NULL, $group = 'Other' * TRUE on pass, FALSE on fail. */ protected function assertTitle($title, $message = '', $group = 'Other') { - // Don't use xpath as it messes with HTML escaping. - preg_match('@<title>(.*)</title>@', $this->getRawContent(), $matches); - if (isset($matches[1])) { - $actual = $matches[1]; - if (!$message) { - $message = SafeMarkup::format('Page title @actual is equal to @expected.', array( - '@actual' => var_export($actual, TRUE), - '@expected' => var_export($title, TRUE), - )); - } - return $this->assertEqual($actual, $title, $message, $group); + $actual = (string) current($this->xpath('//title')); + if (!$message) { + $message = SafeMarkup::format('Page title @actual is equal to @expected.', array( + '@actual' => var_export($actual, TRUE), + '@expected' => var_export($title, TRUE), + )); } - return $this->fail('No title element found on the page.'); + return $this->assertEqual($actual, $title, $message, $group); } /** diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php index 0a52d2f8c2a0993598e18b63bfdea2d9bc6747a4..289928f4d0fcfe15acf9cf1a7cfd37de58d1fb89 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Form/ModulesListForm.php @@ -7,6 +7,7 @@ namespace Drupal\system\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; use Drupal\Core\Config\PreExistingConfigException; use Drupal\Core\Config\UnmetDependenciesException; @@ -168,7 +169,7 @@ public function getFormId() { */ public function buildForm(array $form, FormStateInterface $form_state) { require_once DRUPAL_ROOT . '/core/includes/install.inc'; - $distribution = drupal_install_profile_distribution_name(); + $distribution = SafeMarkup::checkPlain(drupal_install_profile_distribution_name()); // Include system.admin.inc so we can use the sort callbacks. $this->moduleHandler->loadInclude('system', 'inc', 'system.admin'); diff --git a/core/modules/system/src/Tests/System/PageTitleTest.php b/core/modules/system/src/Tests/System/PageTitleTest.php index 56fa556b4876965661207302cc208fdf15224964..369b55439f85645b1780416455810843ac50a5b3 100644 --- a/core/modules/system/src/Tests/System/PageTitleTest.php +++ b/core/modules/system/src/Tests/System/PageTitleTest.php @@ -147,6 +147,15 @@ public function testRoutingTitle() { $this->drupalGet('test-page-cached-controller'); $this->assertTitle('Cached title | Drupal'); $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>'); + + // Ensure that titles are cacheable and are escaped normally if the + // controller escapes them use Html::escape(). + $this->drupalGet('test-page-cached-controller-safe'); + $this->assertTitle('<span>Cached title</span> | Drupal'); + $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>'); + $this->drupalGet('test-page-cached-controller-safe'); + $this->assertTitle('<span>Cached title</span> | Drupal'); + $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>'); } } diff --git a/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php b/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php index 73f39b1fa5d64aa631f86bb63db5569800339d1f..342151e2295301c9eb93f68cd5f403adffb94bf6 100644 --- a/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php +++ b/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php @@ -7,6 +7,7 @@ namespace Drupal\database_test\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\user\Entity\User; @@ -55,8 +56,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { foreach (User::loadMultiple($uids) as $account) { $options[$account->id()] = array( - 'title' => array('data' => array('#title' => $account->getUsername())), - 'username' => $account->getUsername(), + 'title' => array('data' => array('#title' => SafeMarkup::checkPlain($account->getUsername()))), + 'username' => SafeMarkup::checkPlain($account->getUsername()), 'status' => $account->isActive() ? t('active') : t('blocked'), ); } diff --git a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php index 9c347be09e45f44009cedef1c60b95e980951607..a7fa82ce2a016207dde7feec9811f4a004380358 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php @@ -7,6 +7,7 @@ namespace Drupal\form_test; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; @@ -37,7 +38,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $arg = NU $form['bananas'] = array( '#type' => 'textfield', - '#default_value' => $arg, + '#default_value' => SafeMarkup::checkPlain($arg), '#title' => $this->t('Bananas'), ); diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php index 934e6a2be00b8166e499298d9a0126099ff659b8..b0d4136b3d228c2c62a25b83e3422a7dc03ebe52 100644 --- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php +++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php @@ -7,7 +7,7 @@ namespace Drupal\test_page_test\Controller; -use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; /** * Defines a test controller for page titles. @@ -54,13 +54,19 @@ public function dynamicTitle() { /** * Defines a controller with a cached render array. * + * @param bool $mark_safe + * Whether or not to mark the title as safe use SafeMarkup::checkPlain. + * * @return array * A render array */ - public function controllerWithCache() { + public function controllerWithCache($mark_safe = FALSE) { $build = []; $build['#title'] = '<span>Cached title</span>'; - $build['#cache']['keys'] = ['test_controller', 'with_title']; + if ($mark_safe) { + $build['#title'] = SafeMarkup::checkPlain($build['#title']); + } + $build['#cache']['keys'] = ['test_controller', 'with_title', $mark_safe]; return $build; } diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml index 240842349af3f3c7673f83892af455e0c2b17fbd..5330be824b36512670eb615f8c4f0411c3399661 100644 --- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml +++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml @@ -28,6 +28,14 @@ test_page_test.cached_controller: requirements: _access: 'TRUE' +test_page_test.cached_controller.safe: + path: '/test-page-cached-controller-safe' + defaults: + _controller: '\Drupal\test_page_test\Controller\Test::controllerWithCache' + mark_safe: true + requirements: + _access: 'TRUE' + test_page_test.dynamic_title: path: '/test-page-dynamic-title' defaults: diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc index 47bd3efedb3abe6d97b60ba21bbbde21d14ad495..ffbf316fe9dcc1011092c63efb7a7a9a1285f1d5 100644 --- a/core/modules/tracker/tracker.pages.inc +++ b/core/modules/tracker/tracker.pages.inc @@ -5,6 +5,7 @@ * User page callbacks for tracker.module. */ +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Cache\Cache; use Drupal\node\Entity\Node; @@ -84,7 +85,7 @@ function tracker_page($account = NULL) { } $row = array( - 'type' => node_get_type_label($node), + 'type' => SafeMarkup::checkPlain(node_get_type_label($node)), 'title' => array( 'data' => array( '#type' => 'link', diff --git a/core/modules/update/src/Form/UpdateManagerUpdate.php b/core/modules/update/src/Form/UpdateManagerUpdate.php index cafa4d13f95d4914eeb33f4e6a5483b732eed152..f0f64ea32d557eb0c81d5f017bb93221e5542350 100644 --- a/core/modules/update/src/Form/UpdateManagerUpdate.php +++ b/core/modules/update/src/Form/UpdateManagerUpdate.php @@ -7,6 +7,7 @@ namespace Drupal\update\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; @@ -114,14 +115,14 @@ public function buildForm(array $form, FormStateInterface $form_state) { $project_name = $this->l($project['title'], Url::fromUri($project['link'])); } else { - $project_name = $project['title']; + $project_name = SafeMarkup::checkPlain($project['title']); } } elseif (!empty($project['info']['name'])) { - $project_name = $project['info']['name']; + $project_name = SafeMarkup::checkPlain($project['info']['name']); } else { - $project_name = $name; + $project_name = SafeMarkup::checkPlain($name); } if ($project['project_type'] == 'theme' || $project['project_type'] == 'theme-disabled') { $project_name .= ' ' . $this->t('(Theme)'); diff --git a/core/modules/user/src/Form/UserPermissionsForm.php b/core/modules/user/src/Form/UserPermissionsForm.php index e96efda0c3254ba55c882e2adbb9c97c13c267bb..0e0a01a5e0af4e1e78e5c4fc23446818026da1ee 100644 --- a/core/modules/user/src/Form/UserPermissionsForm.php +++ b/core/modules/user/src/Form/UserPermissionsForm.php @@ -7,6 +7,7 @@ namespace Drupal\user\Form; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; @@ -93,7 +94,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { $admin_roles = array(); foreach ($this->getRoles() as $role_name => $role) { // Retrieve role names for columns. - $role_names[$role_name] = $role->label(); + $role_names[$role_name] = SafeMarkup::checkPlain($role->label()); // Fetch permissions for the roles. $role_permissions[$role_name] = $role->getPermissions(); $admin_roles[$role_name] = $role->isAdmin(); diff --git a/core/modules/user/src/Plugin/views/access/Permission.php b/core/modules/user/src/Plugin/views/access/Permission.php index fab8f882b020422587c5ef7ad844cb295bf1c59d..0dc5165db57b963c92faf64e2d903c6f6645d1c0 100644 --- a/core/modules/user/src/Plugin/views/access/Permission.php +++ b/core/modules/user/src/Plugin/views/access/Permission.php @@ -7,6 +7,7 @@ namespace Drupal\user\Plugin\views\access; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; @@ -120,7 +121,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { foreach ($permissions as $perm => $perm_item) { $provider = $perm_item['provider']; $display_name = $this->moduleHandler->getName($provider); - $perms[$display_name][$perm] = strip_tags($perm_item['title']); + $perms[$display_name][$perm] = SafeMarkup::checkPlain(strip_tags($perm_item['title'])); } $form['perm'] = array( diff --git a/core/modules/user/src/UserListBuilder.php b/core/modules/user/src/UserListBuilder.php index 85b52f2e24aab533528076e7149d4a3f3cb11cb1..7575b867270d6caf0f5665925fa1ab647c281d59 100644 --- a/core/modules/user/src/UserListBuilder.php +++ b/core/modules/user/src/UserListBuilder.php @@ -138,7 +138,7 @@ public function buildRow(EntityInterface $entity) { ); $row['status'] = $entity->isActive() ? $this->t('active') : $this->t('blocked'); - $roles = user_role_names(TRUE); + $roles = array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', user_role_names(TRUE)); unset($roles[RoleInterface::AUTHENTICATED_ID]); $users_roles = array(); foreach ($entity->getRoles() as $role) { diff --git a/core/modules/views/src/Plugin/views/display/Block.php b/core/modules/views/src/Plugin/views/display/Block.php index 08e44675244b7d41b87276dc79946ce04a4f174b..411c50ee24187f6af541be55c11f3dca5c1d3c63 100644 --- a/core/modules/views/src/Plugin/views/display/Block.php +++ b/core/modules/views/src/Plugin/views/display/Block.php @@ -7,6 +7,7 @@ namespace Drupal\views\Plugin\views\display; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\Block\ViewsBlock; @@ -148,7 +149,7 @@ public function optionsSummary(&$categories, &$options) { if (empty($block_description)) { $block_description = $this->t('None'); } - $block_category = $this->getOption('block_category'); + $block_category = SafeMarkup::checkPlain($this->getOption('block_category')); $options['block_description'] = array( 'category' => 'block', diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 534925c91324ad80f2d296821ad9059543b3b56e..f9ae57a0584a6119d4655c0a3a160c6c1fc28b50 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -1062,7 +1062,7 @@ public function getArgumentsTokens() { } // Use strip tags as there should never be HTML in the path. // However, we need to preserve special characters like " that - // were encoded by \Drupal\Component\Utility\Html::escape(). + // were removed by SafeMarkup::checkPlain(). $tokens["!$count"] = isset($this->view->args[$count - 1]) ? strip_tags(Html::decodeEntities($this->view->args[$count - 1])) : ''; } @@ -1394,7 +1394,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { if ($this->defaultableSections($section)) { views_ui_standard_display_dropdown($form, $form_state, $section); } - $form['#title'] = $this->display['display_title'] . ': '; + $form['#title'] = SafeMarkup::checkPlain($this->display['display_title']) . ': '; // Set the 'section' to highlight on the form. // If it's the item we're looking at is pulling from the default display, diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php index 8c716f19a8742dbabe71609be3515a25d70e2f58..d2e9fe895b28aba0ee892b58db74a539943b44c1 100644 --- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php +++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php @@ -766,7 +766,7 @@ public function groupForm(&$form, FormStateInterface $form_state) { $value = $this->options['group_info']['identifier']; $form[$value] = array( - '#title' => $this->options['group_info']['label'], + '#title' => SafeMarkup::checkPlain($this->options['group_info']['label']), '#type' => $this->options['group_info']['widget'], '#default_value' => $this->group_info, '#options' => $groups, diff --git a/core/modules/views/src/Tests/SearchIntegrationTest.php b/core/modules/views/src/Tests/SearchIntegrationTest.php index 78c43ac359df9a9892cc733b74d0fddd85375e46..2edd22da7ea12f55b5c7992f89e9891691d3b2e7 100644 --- a/core/modules/views/src/Tests/SearchIntegrationTest.php +++ b/core/modules/views/src/Tests/SearchIntegrationTest.php @@ -108,16 +108,15 @@ public function testSearchIntegration() { 'type' => $type->id(), ]; $this->drupalCreateNode($node); - $node['title'] = "Drupal's search rocks <em>really</em> rocks!"; + $node['title'] = "Drupal's search rocks really rocks!"; $this->drupalCreateNode($node); $this->cronRun(); $this->drupalGet('test-arg/rocks'); $xpath = '//div[@class="views-row"]//a'; /** @var \SimpleXMLElement[] $results */ $results = $this->xpath($xpath); - $this->assertEqual((string) $results[0], "Drupal's search rocks <em>really</em> rocks!"); + $this->assertEqual((string) $results[0], "Drupal's search rocks really rocks!"); $this->assertEqual((string) $results[1], "Drupal's search rocks."); - $this->assertEscaped("Drupal's search rocks <em>really</em> rocks!"); // Test sorting with another set of titles. $node = [ diff --git a/core/modules/views_ui/src/Tests/XssTest.php b/core/modules/views_ui/src/Tests/XssTest.php index a8474347cd44b0549590502282dcbc26becf58b0..21080cbfcd3699cc51d82b38ba42fe70f03c4274 100644 --- a/core/modules/views_ui/src/Tests/XssTest.php +++ b/core/modules/views_ui/src/Tests/XssTest.php @@ -23,10 +23,10 @@ class XssTest extends UITestBase { public function testViewsUi() { $this->drupalGet('admin/structure/views'); - $this->assertEscaped('<script>alert("foo");</script>, <marquee>test</marquee>', 'The view tag is properly escaped.'); + $this->assertRaw('<script>alert("foo");</script>, <marquee>test</marquee>', 'The view tag is properly escaped.'); $this->drupalGet('admin/structure/views/view/sa_contrib_2013_035'); - $this->assertEscaped('<marquee>test</marquee>', 'Field admin label is properly escaped.'); + $this->assertRaw('&lt;marquee&gt;test&lt;/marquee&gt;', 'Field admin label is properly escaped.'); $this->drupalGet('admin/structure/views/nojs/handler/sa_contrib_2013_035/page_1/header/area'); $this->assertRaw('[title] == &lt;marquee&gt;test&lt;/marquee&gt;', 'Token label is properly escaped.'); diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php index e13ae62f03de137eaba22052bfa4c55b71bd25b4..05bc5fd7241d2cc88c79be9608e798315c592200 100644 --- a/core/modules/views_ui/src/ViewEditForm.php +++ b/core/modules/views_ui/src/ViewEditForm.php @@ -494,7 +494,7 @@ public function getDisplayDetails($view, $display) { $build['top']['display_title'] = array( '#theme' => 'views_ui_display_tab_setting', '#description' => $this->t('Display name'), - '#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink($display_title, 'display_title'), + '#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink(SafeMarkup::checkPlain($display_title), 'display_title'), ); } @@ -1060,7 +1060,7 @@ public function getFormBucket(ViewUI $view, $type, $display) { continue; } - $field_name = $handler->adminLabel(TRUE); + $field_name = SafeMarkup::checkPlain($handler->adminLabel(TRUE)); if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { $field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name; } diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php index 0d8125b81c99686232b7b86fe0c76ffd139be8b1..ece0acfdd3acb0ed701f7a80c9ad46619dd22df7 100644 --- a/core/modules/views_ui/src/ViewListBuilder.php +++ b/core/modules/views_ui/src/ViewListBuilder.php @@ -7,6 +7,7 @@ namespace Drupal\views_ui; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; @@ -277,7 +278,7 @@ protected function getDisplayPaths(EntityInterface $view) { $all_paths[] = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path)); } else { - $all_paths[] = '/' . $path; + $all_paths[] = SafeMarkup::checkPlain('/' . $path); } } } diff --git a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php index 4089d3a2e89d8486a5bb94fd346abfb62263f85a..d4bc2b6bd1e78e6c5902437fcb6ce85bfd2409e5 100644 --- a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php +++ b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php @@ -7,7 +7,6 @@ namespace Drupal\Tests\views_ui\Unit; -use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\EntityInterface; use Drupal\Tests\UnitTestCase; @@ -166,10 +165,7 @@ public function testBuildRowEntityList() { $this->assertEquals($expected_displays, $row['data']['view_name']['data']['#displays']); $display_paths = $row['data']['path']['data']['#items']; - // These values will be escaped by Twig when rendered. - $this->assertEquals('/test_page, /<object>malformed_path</object>, /<script>alert("placeholder_page/%")</script>', implode(', ', $display_paths)); - $this->assertFalse(SafeMarkup::isSafe('/<object>malformed_path</object>'), '/<script>alert("/<object>malformed_path</object> is not marked safe.'); - $this->assertFalse(SafeMarkup::isSafe('/<script>alert("placeholder_page/%")'), '/<script>alert("/<script>alert("placeholder_page/%") is not marked safe.'); + $this->assertEquals('/test_page, /<object>malformed_path</object>, /<script>alert("placeholder_page/%")</script>', implode(', ', $display_paths)); } }