diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php
index d6a59ad..f306ad3 100644
--- a/core/modules/dblog/src/Tests/DbLogTest.php
+++ b/core/modules/dblog/src/Tests/DbLogTest.php
@@ -7,9 +7,11 @@
namespace Drupal\dblog\Tests;
+use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Logger\RfcLogLevel;
+use Drupal\Core\Url;
use Drupal\dblog\Controller\DbLogController;
use Drupal\simpletest\WebTestBase;
@@ -50,7 +52,12 @@ protected function setUp() {
$this->drupalPlaceBlock('system_breadcrumb_block');
// Create users with specific permissions.
- $this->adminUser = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports', 'administer users'));
+ $this->adminUser = $this->drupalCreateUser(array(
+ 'administer site configuration',
+ 'access administration pages',
+ 'access site reports',
+ 'administer users',
+ ));
$this->webUser = $this->drupalCreateUser(array());
}
@@ -61,7 +68,7 @@ protected function setUp() {
* Database Logging module functionality through both the admin and user
* interfaces.
*/
- function testDbLog() {
+ public function testDbLog() {
// Login the admin user.
$this->drupalLogin($this->adminUser);
@@ -71,6 +78,8 @@ function testDbLog() {
$this->verifyEvents();
$this->verifyReports();
$this->verifyBreadcrumbs();
+ $this->verifyLinkEscaping();
+ $this->verifyMessageEscaping();
// Verify the overview table sorting.
$orders = array('Date', 'Type', 'User');
$sorts = array('asc', 'desc');
@@ -129,21 +138,18 @@ private function verifyCron($row_limit) {
*
* @param int $count
* Number of watchdog entries to generate.
- * @param string $type
- * (optional) The type of watchdog entry. Defaults to 'custom'.
- * @param int $severity
- * (optional) The severity of the watchdog entry. Defaults to
- * \Drupal\Core\Logger\RfcLogLevel::NOTICE.
+ * @param array $options
+ * (optional) An array of options that override the default values.
*/
- private function generateLogEntries($count, $type = 'custom', $severity = RfcLogLevel::NOTICE) {
+ private function generateLogEntries($count, $options = array()) {
global $base_root;
- // Prepare the fields to be logged
- $log = array(
- 'channel' => $type,
- 'message' => 'Log entry added to test the dblog row limit.',
+ // Prepare the fields to be logged.
+ $log = $options + array(
+ 'channel' => 'system',
+ 'message' => 'Dblog test log message',
'variables' => array(),
- 'severity' => $severity,
+ 'severity' => RfcLogLevel::NOTICE,
'link' => NULL,
'user' => $this->adminUser,
'uid' => $this->adminUser->id(),
@@ -151,11 +157,18 @@ private function generateLogEntries($count, $type = 'custom', $severity = RfcLog
'referer' => \Drupal::request()->server->get('HTTP_REFERER'),
'ip' => '127.0.0.1',
'timestamp' => REQUEST_TIME,
- );
- $message = 'Log entry added to test the dblog row limit. Entry #';
- for ($i = 0; $i < $count; $i++) {
- $log['message'] = $message . $i;
- $this->container->get('logger.dblog')->log($severity, $log['message'], $log);
+ );
+
+ $logger = $this->container->get('logger.dblog');
+ if ($count > 1) {
+ $row_message = $log['message'] . ' Entry #';
+ for ($i = 0; $i < $count; $i++) {
+ $log['message'] = $row_message . $i;
+ $logger->log($log['severity'], $log['message'], $log);
+ }
+ }
+ else {
+ $logger->log($log['severity'], $log['message'], $log);
}
}
@@ -240,13 +253,89 @@ private function verifyEvents() {
* @param string $order
* The order by which the table should be sorted.
*/
- public function verifySort($sort = 'asc', $order = 'Date') {
+ protected function verifySort($sort = 'asc', $order = 'Date') {
$this->drupalGet('admin/reports/dblog', array('query' => array('sort' => $sort, 'order' => $order)));
$this->assertResponse(200);
$this->assertText(t('Recent log messages'), 'DBLog report was displayed correctly and sorting went fine.');
}
/**
+ * Tests the escaping of links in the operation row of a database log detail
+ * page.
+ */
+ private function verifyLinkEscaping() {
+ $link = \Drupal::l('View', Url::fromRoute('entity.node.canonical', array('node' => 1)));
+ $message = 'Log entry added to do the verifyLinkEscaping test.';
+ $this->generateLogEntries(1, array(
+ 'message' => $message,
+ 'link' => $link,
+ ));
+
+ $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1);
+ $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField());
+
+ // Check if the link exists (unescaped).
+ $this->assertRaw($link);
+
+ // Check for XSS filtering.
+ $js_txt = 'This should not pop up!';
+ $js = '';
+ $this->generateLogEntries(1, array(
+ 'message' => $message,
+ 'link' => $link . $js,
+ ));
+
+ $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1);
+ $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField());
+
+ // Check if the link exists (unescaped).
+ $this->assertRaw($link);
+
+ // Check if javascript was escaped.
+ $this->assertNoRaw($js, 'Detail view: javascript in link is blocked');
+ $this->assertRaw($js_txt, 'Detail view: javascript text exists');
+ }
+
+ /**
+ * Test the escaping of message in the operation row of a database log detail
+ * page.
+ */
+ private function verifyMessageEscaping() {
+ $link = \Drupal::l('View', Url::fromRoute('entity.node.canonical', array('node' => 1)));
+ $message = String::format('%message', array(
+ '%message' => 'Log entry added to do the verifyMessageEscaping test.',
+ ));
+ $this->generateLogEntries(1, array(
+ 'message' => $message,
+ 'link' => $link,
+ ));
+
+ $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1);
+ $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField());
+
+ // Check if the link exists (unescaped).
+ $this->assertRaw($message);
+
+ // Check for XSS filtering.
+ $js_txt = 'This should not pop up!';
+ $js = '';
+ $this->generateLogEntries(1, array(
+ 'message' => $message . $js,
+ 'link' => $link,
+ ));
+
+ $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1);
+ $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField());
+
+ // Check if the link exists (unescaped).
+ $this->assertRaw($message);
+
+ // Check if javascript was escaped.
+ $this->assertNoRaw($js, 'Detail view: javascript in message is blocked');
+ $this->assertRaw($js_txt, 'Detail view: javascript text exists ');
+ }
+
+ /**
* Generates and then verifies some user events.
*/
private function doUser() {
@@ -338,7 +427,11 @@ private function doUser() {
*/
private function doNode($type) {
// Create user.
- $perm = array('create ' . $type . ' content', 'edit own ' . $type . ' content', 'delete own ' . $type . ' content');
+ $perm = array(
+ 'create ' . $type . ' content',
+ 'edit own ' . $type . ' content',
+ 'delete own ' . $type . ' content',
+ );
$user = $this->drupalCreateUser($perm);
// Login user.
$this->drupalLogin($user);
@@ -497,7 +590,10 @@ protected function testFilter() {
'type' => $type_name,
'severity' => $severity++,
);
- $this->generateLogEntries($type['count'], $type['type'], $type['severity']);
+ $this->generateLogEntries($type['count'], array(
+ 'channel' => $type['type'],
+ 'severity' => $type['severity'],
+ ));
}
}