Commit 3a0b0178 authored by effulgentsia's avatar effulgentsia

Issue #2568613 by alexpott, lauriii, pwolanin: Remove HTML support from date...

Issue #2568613 by alexpott, lauriii, pwolanin: Remove HTML support from date formats and replace remaining !placeholder where format_date() and 'date.formatter' => format() are used
parent a537a309
......@@ -278,7 +278,7 @@ public function __construct($time = 'now', $timezone = NULL, $settings = array()
*
* @return string
*/
protected function render() {
public function render() {
return $this->format(static::FORMAT) . ' ' . $this->getTimeZone()->getName();
}
......
......@@ -7,7 +7,6 @@
namespace Drupal\Core\Datetime;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityManagerInterface;
......@@ -131,7 +130,8 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana
* the user interface language for the page.
*
* @return string
* A translated date string in the requested format.
* A translated date string in the requested format. Since the format may
* contain user input, this value should be escaped when output.
*/
public function format($timestamp, $type = 'medium', $format = '', $timezone = NULL, $langcode = NULL) {
if (!isset($timezone)) {
......@@ -168,7 +168,7 @@ public function format($timestamp, $type = 'medium', $format = '', $timezone = N
$settings = array(
'langcode' => $langcode,
);
return Xss::filter($date->format($format, $settings));
return $date->format($format, $settings);
}
/**
......
......@@ -90,7 +90,8 @@ protected function prepareTimezone($timezone) {
* the result of the format() method. Defaults to NULL.
*
* @return string
* The formatted value of the date.
* The formatted value of the date. Since the format may contain user input,
* this value should be escaped when output.
*/
public function format($format, $settings = array()) {
$langcode = !empty($settings['langcode']) ? $settings['langcode'] : $this->langcode;
......
......@@ -241,7 +241,7 @@ public static function processDatetime(&$element, FormStateInterface $form_state
// placeholders are invalid for HTML5 date and datetime, so an example
// format is appended to the title to appear in tooltips.
$extra_attributes = array(
'title' => t('Date (e.g. !format)', array('!format' => static::formatExample($date_format))),
'title' => t('Date (e.g. @format)', array('@format' => static::formatExample($date_format))),
'type' => $element['#date_date_element'],
);
......@@ -288,7 +288,7 @@ public static function processDatetime(&$element, FormStateInterface $form_state
// Adds the HTML5 attributes.
$extra_attributes = array(
'title' => t('Time (e.g. !format)', array('!format' => static::formatExample($time_format))),
'title' => t('Time (e.g. @format)', array('@format' => static::formatExample($time_format))),
'type' => $element['#date_time_element'],
'step' => $element['#date_increment'],
);
......
......@@ -946,7 +946,7 @@ function hook_requirements($phase) {
$cron_last = \Drupal::state()->get('system.cron_last');
if (is_numeric($cron_last)) {
$requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
$requirements['cron']['value'] = t('Last run @time ago', array('@time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
}
else {
$requirements['cron'] = array(
......
......@@ -117,5 +117,10 @@ function testFormatDate() {
$this->assertIdentical(format_date($timestamp, 'html_week'), '2007-W12', 'Test html_week date format.');
$this->assertIdentical(format_date($timestamp, 'html_month'), '2007-03', 'Test html_month date format.');
$this->assertIdentical(format_date($timestamp, 'html_year'), '2007', 'Test html_year date format.');
// HTML is not escaped by the date formatter, it must be escaped later.
$formatter = \Drupal::service('date.formatter');
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'Y\'\)\;\<\/\s\c\r\i\p\t\>'), "<script>alert('2007');</script>", 'Script tags not removed from dates.');
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\e\m\>Y\<\/\e\m\>'), '<em>2007</em>', 'Em tags are not removed from dates.');
}
}
......@@ -7,6 +7,7 @@
namespace Drupal\system\Tests\System;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
......@@ -133,20 +134,31 @@ function testDateFormatConfiguration() {
$this->assertText(t('Custom date format added.'), 'Date format added confirmation message appears.');
$this->assertText($name, 'Custom date format appears in the date format list.');
$this->assertText(t('Delete'), 'Delete link for custom date format appears.');
}
/**
* Test that date formats are sanitized.
*/
function testDateFormatXSS() {
$date_format = entity_create('date_format', array(
'id' => 'xss_short',
'label' => 'XSS format',
'pattern' => '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'\X\S\S\'\)\;\<\/\s\c\r\i\p\t\>',
));
));
$date_format->save();
$this->drupalGet('admin/config/regional/date-time');
$this->assertNoRaw("<script>alert('XSS');</script>", 'The date format was properly sanitized');
$this->drupalGet(Url::fromRoute('entity.date_format.collection'));
$this->assertEscaped("<script>alert('XSS');</script>", 'The date format was properly escaped');
// Add a new date format with HTML in it.
$date_format_id = strtolower($this->randomMachineName(8));
$name = ucwords($date_format_id);
$date_format = '& \<\e\m\>Y\<\/\e\m\>';
$edit = array(
'id' => $date_format_id,
'label' => $name,
'date_format_pattern' => $date_format,
);
$this->drupalPostForm('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
$this->assertUrl(\Drupal::url('entity.date_format.collection', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
$this->assertText(t('Custom date format added.'), 'Date format added confirmation message appears.');
$this->assertText($name, 'Custom date format appears in the date format list.');
$this->assertEscaped('<em>' . date("Y") . '</em>');
}
}
......@@ -464,7 +464,7 @@ function system_requirements($phase) {
}
// Set summary and description based on values determined above.
$summary = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
$summary = t('Last run @time ago', array('@time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
$requirements['cron'] = array(
'title' => t('Cron maintenance tasks'),
......
......@@ -106,8 +106,8 @@ function tracker_page($account = NULL) {
'data-history-node-last-comment-timestamp' => $node->last_comment_timestamp,
),
'last updated' => array(
'data' => t('!time ago', array(
'!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($node->last_activity),
'data' => t('@time ago', array(
'@time' => \Drupal::service('date.formatter')->formatTimeDiffSince($node->last_activity),
)),
),
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment