diff --git a/core/includes/common.inc b/core/includes/common.inc index c465349..4ecbec2 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -20,7 +20,6 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Language\Language; use Drupal\Core\Site\Settings; -use Drupal\Core\Template\SafeMarkup; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Drupal\Core\PhpStorage\PhpStorageFactory; @@ -29,6 +28,7 @@ use Drupal\Core\EventSubscriber\HtmlViewSubscriber; use Drupal\Core\Routing\GeneratorNotInitializedException; use Drupal\Core\Template\Attribute; +use Drupal\Core\Template\SafeMarkup; use Drupal\Core\Render\Element; use Drupal\Core\Session\AnonymousUserSession; @@ -915,6 +915,7 @@ function l($text, $path, array $options = array()) { // Sanitize the link text if necessary. $text = $variables['options']['html'] ? $variables['text'] : String::checkPlain($variables['text']); + // $attributes and $url is known to be safe. $safe = $text instanceof SafeMarkup; $link = '' . $text . ''; @@ -1471,6 +1472,9 @@ function drupal_html_class($class) { // static instead of drupal_static(). static $classes = array(); + // @todo Needs safe makrup preservation or should be cast to string before + // arg is passed to this function? + $class = (string) $class; if (!isset($classes[$class])) { $classes[$class] = drupal_clean_css_identifier(drupal_strtolower($class)); } @@ -2873,7 +2877,8 @@ function drupal_pre_render_conditional_comments($elements) { function drupal_pre_render_html_tag($element) { $attributes = isset($element['#attributes']) ? new Attribute($element['#attributes']) : ''; if (!isset($element['#value'])) { - // Attributes is safe. + // Attributes are safe and we are assuming people don't use this function + // and second they don't pass unsafe variables to #tag. $markup = new SafeMarkup('<' . $element['#tag'] . $attributes . " />\n"); } else { @@ -2886,7 +2891,7 @@ function drupal_pre_render_html_tag($element) { $markup .= $element['#value_suffix']; } $markup .= '\n"; - // @TODO! + // @TODO Creating safe markup, avoid if possible! $markup = new SafeMarkup($markup); } if (!empty($element['#noscript'])) { @@ -3386,6 +3391,9 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { // is common for theme suggestions. $theme_is_implemented = ($elements['#children'] !== FALSE); } + + // Assume still safe unless the element or it's __toString return value aren't + // instances of Twig_Markup. $safe = TRUE; $get_string = function ($element) use (&$safe) { if (is_object($element) && method_exists($element, '__toString')) { @@ -3394,7 +3402,7 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { else { $markup = $element; } - $safe = $safe && (!$markup || $element instanceof SafeMarkup || $markup instanceof SafeMarkup); + $safe = $safe && (!$markup || $element instanceof \Twig_Markup || $markup instanceof \Twig_Markup); return $markup; }; diff --git a/core/includes/form.inc b/core/includes/form.inc index 3be1d3e..8bc313c 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1660,7 +1660,7 @@ function theme_tableselect($variables) { foreach ($element['#header'] as $fieldname => $title) { // A row cell can span over multiple headers, which means less row cells // than headers could be present. - if (isset($element['#options'][$key][$fieldname])) { + if (isset($element['#options'][$key][$fieldname]) && is_array($element['#options'][$key][$fieldname])) { // A header can span over multiple cells and in this case the cells // are passed in an array. The order of this array determines the // order in which they are added. diff --git a/core/includes/theme.inc b/core/includes/theme.inc index e5a917f..5c5ae2b 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2053,7 +2053,9 @@ function template_preprocess_html(&$variables) { // Wrap function calls in an object so they can be called when printed. $variables['head'] = new RenderWrapper(function() use ($page) { + // @todo Creates safe makrup, maybe should preserve? return new SafeMarkup(implode("\n", $page->getMetaElements()) . implode("\n", $page->getLinkElements())); + // return String::concat(String::implode("\n", $page->getMetaElements()), String::implode("\n", $page->getLinkElements())); }); $variables['styles'] = new RenderWrapper('drupal_get_css'); $variables['scripts'] = new RenderWrapper('drupal_get_js'); diff --git a/core/lib/Drupal/Component/Utility/String.php b/core/lib/Drupal/Component/Utility/String.php index a71dc1a..fed1c73 100644 --- a/core/lib/Drupal/Component/Utility/String.php +++ b/core/lib/Drupal/Component/Utility/String.php @@ -6,6 +6,7 @@ */ namespace Drupal\Component\Utility; + use Drupal\Core\Template\SafeMarkup; /** @@ -128,12 +129,18 @@ public static function placeholder($text) { return new SafeMarkup('' . static::checkPlain($text) . ''); } + /** + * @todo. + */ public static function concat($string1, $string2) { $string = $string1 . $string2; $safe = $string1 instanceof SafeMarkup && $string2 instanceof SafeMarkup; return $safe ? new SafeMarkup($string) : $string; } + /** + * @todo. + */ public static function implode($delimiter, array $array) { $real_delimiter = ''; $safe = TRUE; @@ -145,4 +152,5 @@ public static function implode($delimiter, array $array) { } return $safe ? new SafeMarkup($imploded) : $imploded; } + } diff --git a/core/lib/Drupal/Component/Utility/Xss.php b/core/lib/Drupal/Component/Utility/Xss.php index 8117ccf..dd0df76 100644 --- a/core/lib/Drupal/Component/Utility/Xss.php +++ b/core/lib/Drupal/Component/Utility/Xss.php @@ -6,6 +6,7 @@ */ namespace Drupal\Component\Utility; + use Drupal\Core\Template\SafeMarkup; /** diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index 791a927..8354bea 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -626,6 +626,7 @@ public function getName($theme) { if (!isset($themes[$theme])) { throw new \InvalidArgumentException(String::format('Requested the name of a non-existing theme @theme', array('@theme' => $theme))); } + // @todo For testing please remove before commit. return \Drupal::config('system.site')->get('name'); return String::checkPlain($themes[$theme]->info['name']); } diff --git a/core/lib/Drupal/Core/Form/OptGroup.php b/core/lib/Drupal/Core/Form/OptGroup.php index f94d62d..21e9855 100644 --- a/core/lib/Drupal/Core/Form/OptGroup.php +++ b/core/lib/Drupal/Core/Form/OptGroup.php @@ -43,7 +43,7 @@ public static function flattenOptions(array $array) { */ protected static function doFlattenOptions(array $array, array &$options) { foreach ($array as $key => $value) { - if (is_object($value)) { + if (is_object($value) && isset($value->option)) { static::doFlattenOptions($value->option, $options); } elseif (is_array($value)) { diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php index 18a7430..e80bf7c 100644 --- a/core/lib/Drupal/Core/Template/Attribute.php +++ b/core/lib/Drupal/Core/Template/Attribute.php @@ -31,7 +31,7 @@ * // Produces * @endcode */ -class Attribute extends SafeMarkup implements \ArrayAccess, \IteratorAggregate { +class Attribute extends \Twig_Markup implements \ArrayAccess, \IteratorAggregate { /** * Stores the attribute data. diff --git a/core/lib/Drupal/Core/Template/SafeMarkup.php b/core/lib/Drupal/Core/Template/SafeMarkup.php index a874c62..31cbf4e 100644 --- a/core/lib/Drupal/Core/Template/SafeMarkup.php +++ b/core/lib/Drupal/Core/Template/SafeMarkup.php @@ -12,11 +12,24 @@ */ class SafeMarkup extends \Twig_Markup { - function __construct($content) { + /** + * Constructs a SafeMarkup object. + * + * @param string $content + * The callback function name. + */ + public function __construct($content) { return parent::__construct($content, 'utf-8'); } + /** + * Renders the markup. + * + * @return string + * The results of the callback function. + */ public function render() { return $this->__toString(); } + } diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php index 88d5d60..c793786 100644 --- a/core/lib/Drupal/Core/Utility/LinkGenerator.php +++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php @@ -11,8 +11,8 @@ use Drupal\Component\Utility\String; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Path\AliasManagerInterface; -use Drupal\Core\Template\Attribute; use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Core\Template\Attribute; use Drupal\Core\Template\SafeMarkup; use Drupal\Core\Url; @@ -123,6 +123,7 @@ public function generateFromUrl($text, Url $url) { // Sanitize the link text if necessary. $text = $variables['options']['html'] ? $variables['text'] : String::checkPlain($variables['text']); + // $attributes and $url is known to be safe. $safe = $text instanceof SafeMarkup; $link = '' . $text . ''; diff --git a/core/modules/contextual/lib/Drupal/contextual/ContextualController.php b/core/modules/contextual/lib/Drupal/contextual/ContextualController.php index aeee4a6..fcc47de 100644 --- a/core/modules/contextual/lib/Drupal/contextual/ContextualController.php +++ b/core/modules/contextual/lib/Drupal/contextual/ContextualController.php @@ -44,7 +44,10 @@ public function render(Request $request) { '#type' => 'contextual_links', '#contextual_links' => _contextual_id_to_links($id), ); - $rendered[$id] = drupal_render($element); + // Cast any returned safe markup to string so that it is created + // as correct JSON. + // @todo Maybe check safeness and checkplain the results? + $rendered[$id] = (string) drupal_render($element); } return new JsonResponse($rendered); diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module index 3d13b7b..4ded696 100644 --- a/core/modules/datetime/datetime.module +++ b/core/modules/datetime/datetime.module @@ -8,6 +8,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Template\Attribute; +use Drupal\Core\Template\SafeMarkup; use Drupal\datetime\DateHelper; use Drupal\node\NodeInterface; diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php index e1d96c6..11ef3f4 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php @@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; +use Drupal\Core\Template\SafeMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -117,7 +118,8 @@ public function buildRow(EntityInterface $field) { $usage[] = $this->bundles[$field->entity_type][$bundle]['label']; } } - $row['data']['usage'] = implode(', ', $usage); + // @todo Needs to preserve safe markup. + $row['data']['usage'] = new SafeMarkup(implode(', ', $usage)); return $row; } diff --git a/core/modules/node/node.install b/core/modules/node/node.install index b075d93..7888e2b 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -7,6 +7,7 @@ use Drupal\Component\Uuid\Uuid; use Drupal\Core\Language\Language; +use Drupal\Core\Template\SafeMarkup; /** * Implements hook_requirements(). @@ -29,7 +30,9 @@ function node_requirements($phase) { $requirements['node_access'] = array( 'title' => t('Node Access Permissions'), 'value' => $value, - 'description' => $description . ' ' . l(t('Rebuild permissions'), 'admin/reports/status/rebuild'), + // The results of t() is safe and so is the results of l(). Preserving + // safe object. + 'description' => new SafeMarkup($description . ' ' . l(t('Rebuild permissions'), 'admin/reports/status/rebuild')), ); } return $requirements; diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php index 299f305..2786a3a 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Database\Connection; use Drupal\Core\Form\FormBase; +use Drupal\Core\Template\SafeMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -155,7 +156,8 @@ public function buildForm(array $form, array &$form_state, $test_id = NULL) { $rows = array(); foreach ($assertions as $assertion) { $row = array(); - $row[] = $assertion->message; + // @todo Need to preserve safe markup, not create it. + $row[] = new SafeMarkup($assertion->message); $row[] = $assertion->message_group; $row[] = drupal_basename($assertion->file); $row[] = $assertion->line; diff --git a/core/modules/system/system.install b/core/modules/system/system.install index a14cd7b..b8b4d6d 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -10,6 +10,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\PublicStream; +use Drupal\Core\Template\SafeMarkup; /** * Implements hook_requirements(). @@ -56,7 +57,8 @@ function system_requirements($phase) { if (function_exists('phpinfo')) { $requirements['php'] = array( 'title' => t('PHP'), - 'value' => ($phase == 'runtime') ? $phpversion .' ('. l(t('more information'), 'admin/reports/status/php') .')' : $phpversion, + // $phpversion is safe and output of l() is safe, so this value is safe. + 'value' => new SafeMarkup(($phase == 'runtime') ? $phpversion . ' (' . l(t('more information'), 'admin/reports/status/php') . ')' : $phpversion), ); } else { @@ -318,7 +320,8 @@ function system_requirements($phase) { 'title' => t('Cron maintenance tasks'), 'severity' => $severity, 'value' => $summary, - 'description' => $description + // @todo Needs to preserve safe markup. + 'description' => new SafeMarkup($description), ); } if ($phase != 'install') { diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php index 902b543..42b8d0b 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php @@ -1159,8 +1159,7 @@ protected function prepareFilterSelectOptions(&$options) { $this->prepareFilterSelectOptions($options[$value]); } // FAPI has some special value to allow hierarchy. - // @see _form_options_flatten - elseif (is_object($label)) { + elseif (is_object($label) && isset($options[$value]->option)) { $this->prepareFilterSelectOptions($options[$value]->option); } else { diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc index 430f14a..bb10ee1 100644 --- a/core/modules/views_ui/views_ui.theme.inc +++ b/core/modules/views_ui/views_ui.theme.inc @@ -7,6 +7,7 @@ use Drupal\Core\Render\Element; use Drupal\Core\Template\Attribute; +use Drupal\Core\Template\SafeMarkup; /** * Prepares variables for Views UI display tab setting templates. diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Core.php b/core/vendor/twig/twig/lib/Twig/Extension/Core.php index 968b292..cdb5874 100644 --- a/core/vendor/twig/twig/lib/Twig/Extension/Core.php +++ b/core/vendor/twig/twig/lib/Twig/Extension/Core.php @@ -922,6 +922,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', if (!is_string($string)) { if (is_object($string) && method_exists($string, '__toString')) { + // @todo Move to twig engine. $string = $string->__toString(); if ($autoescape && $string instanceof Twig_Markup) { return $string;