installConfig(['system']);
$manager = $this->container->get('plugin.manager.filter');
$bag = new FilterPluginCollection($manager, []);
$this->filters = $bag->getAll();
}
/**
* Tests the align filter.
*/
public function testAlignFilter() {
$filter = $this->filters['filter_align'];
$test = function($input) use ($filter) {
return $filter->process($input, 'und');
};
// No data-align attribute.
$input = '';
$expected = $input;
$this->assertIdentical($expected, $test($input)->getProcessedText());
// Data-align attribute: all 3 allowed values.
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
// Data-align attribute: a disallowed value.
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
// Empty data-align attribute.
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
// Ensure the filter also works with uncommon yet valid attribute quoting.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
// Security test: attempt to inject an additional class.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
// Security test: attempt an XSS.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
}
/**
* Tests the caption filter.
*/
public function testCaptionFilter() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$filter = $this->filters['filter_caption'];
$test = function($input) use ($filter, $renderer) {
return $renderer->executeInRenderContext(new RenderContext(), function () use ($input, $filter) {
return $filter->process($input, 'und');
});
};
$attached_library = [
'library' => [
'filter/caption',
],
];
// No data-caption attribute.
$input = '';
$expected = $input;
$this->assertIdentical($expected, $test($input)->getProcessedText());
// Data-caption attribute.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// Empty data-caption attribute.
$input = '';
$expected = '';
$this->assertIdentical($expected, $test($input)->getProcessedText());
// HTML entities in the caption.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// HTML encoded as HTML entities in data-caption attribute.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// HTML (not encoded as HTML entities) in data-caption attribute, which is
// not allowed by the HTML spec, but may happen when people manually write
// HTML, so we explicitly support it.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// Security test: attempt an XSS.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// Ensure the filter also works with uncommon yet valid attribute quoting.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
// Finally, ensure that this also works on any other tag.
$input = '';
$expected = '';
$output = $test($input);
$this->assertIdentical($expected, $output->getProcessedText());
$this->assertIdentical($attached_library, $output->getAttachments());
$input = '
tags, while paragraphs
// separated with double line breaks should be enclosed with
aaa
\nbbb
ccc
" => TRUE, ], // Skip contents of certain block tags entirely. "aaa\nbbb\n\nccc" => [ "" => TRUE, "" => TRUE, "
aaa\nbbb\n\nccc" => TRUE, "" => TRUE, "" => TRUE, ], // Skip comments entirely. "One. Two.\n\n" => [ '' => TRUE, "" => TRUE, ], // Resulting HTML should produce matching paragraph tags. '
\n
' => [ "aaa
" => TRUE, ], "aaa
aaa\nbbb\nccc\nddd\neee" => [ "
aaa\nbbb\nccc" => TRUE, "
ddd
\neee
aaa
\n\nbbb
\nccc
\nddd
" => TRUE, "\neee
\nfff
" => TRUE, ], // Check that a comment in a PRE will result that the text after // the comment, but still in PRE, is not transformed. "aaa\nbbb\n\nccc\nddd" => [ "
aaa\nbbb\n\nccc" => TRUE, ], // Bug 810824, paragraphs were appearing around iframe tags. "\n\n" => [ "" => FALSE, ], ]; $this->assertFilteredString($filter, $tests); // Very long string hitting PCRE limits. $limit = max(ini_get('pcre.backtrack_limit'), ini_get('pcre.recursion_limit')); $source = $this->randomMachineName($limit); $result = _filter_autop($source); $success = $this->assertEqual($result, '
' . $source . "
\n", 'Line break filter can process very long strings.'); if (!$success) { $this->verbose("\n" . $source . "\n Three.
',
'filter_html_help' => 1,
'filter_html_nofollow' => 0,
]
]);
// HTML filter is not able to secure some tags, these should never be
// allowed.
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove script tags.');
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove iframe tags.');
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove object tags.');
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove style tags.');
// Some tags make CSRF attacks easier, let the user take the risk herself.
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove img tags by default.');
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, '', 'HTML filter should remove input tags by default.');
// Filtering content of some attributes is infeasible, these shouldn't be
// allowed too.
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNoNormalized($f, 'style', 'HTML filter should remove style attributes.');
$this->assertIdentical($f, '');
$f = (string) $filter->process('', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNoNormalized($f, 'onerror', 'HTML filter should remove on* attributes.');
$this->assertIdentical($f, '');
$f = (string) $filter->process('
', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNoNormalized($f, 'onerror', 'HTML filter should remove empty on* attributes.');
// Note - this string has a decoded character.
$this->assertIdentical($f, '
');
$f = (string) $filter->process('
', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, '
', 'HTML filter should allow line breaks.');
$f = (string) $filter->process('
', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, '
', 'HTML filter should allow self-closing line breaks.');
// All attributes of whitelisted tags are stripped by default.
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'link', 'HTML filter should remove attributes that are not explicitly allowed.');
// Now whitelist the "llama" attribute on .
$filter->setConfiguration([
'settings' => [
'allowed_html' => '
',
'filter_html_help' => 1,
'filter_html_nofollow' => 0,
]
]);
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'link', 'HTML filter keeps explicitly allowed attributes, and removes attributes that are not explicitly allowed.');
// Restrict the whitelisted "llama" attribute on to only allow the value
// "majestical", or "epic".
$filter->setConfiguration([
'settings' => [
'allowed_html' => '
", Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent evasion -- some nulls.');
$f = (string) $filter->process('text', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNoNormalized($f, 'rel="follow"', 'Spam deterrent evasion -- with rel set - rel="follow" removed.');
$this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent evasion -- with rel set - rel="nofollow" added.');
}
/**
* Tests the HTML escaping filter.
*/
public function testHtmlEscapeFilter() {
// Get FilterHtmlEscape object.
$filter = $this->filters['filter_html_escape'];
$tests = [
" One. Two'.\n
',
'filter_html_help' => 1,
'filter_html_nofollow' => 0,
]
]);
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, 'link', 'HTML filter removes allowed attributes that do not have an explicitly allowed value.');
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, 'link', 'HTML filter keeps explicitly allowed attributes with an attribute value that is also explicitly allowed.');
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'link', 'HTML filter removes allowed attributes that have a not explicitly allowed value.');
$f = (string) $filter->process('link', Language::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($f, 'link', 'HTML filter keeps explicitly allowed attributes with an attribute value that is also explicitly allowed.');
}
/**
* Tests the spam deterrent.
*/
public function testNoFollowFilter() {
// Get FilterHtml object.
$filter = $this->filters['filter_html'];
$filter->setConfiguration([
'settings' => [
'allowed_html' => '',
'filter_html_help' => 1,
'filter_html_nofollow' => 1,
]
]);
// Test if the rel="nofollow" attribute is added, even if we try to prevent
// it.
$f = (string) $filter->process('text', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent -- no evasion.');
$f = (string) $filter->process('text', Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent evasion -- capital A.');
$f = (string) $filter->process("text", Language::LANGCODE_NOT_SPECIFIED);
$this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent evasion -- non whitespace character after tag name.');
$f = (string) $filter->process("<\0a\0 href=\"http://www.example.com/\">text
An anchor.
' => [ '' => TRUE, '' => TRUE,
'href="http://www.namespace.com"' => FALSE,
'href="http://namespace.com"' => FALSE,
'An anchor.' => TRUE,
],
'
Not www.relative.com or www.absolute.com
but http://www.strong.net or www.emphasis.info
' => [
'www.relative.com' => TRUE,
'href="http://www.relative.com"' => FALSE,
'www.absolute.com' => TRUE,
'http://www.strong.net' => TRUE,
'www.emphasis.info' => TRUE,
],
'
Test using www.example.com the code tag
.
' => [
'href' => FALSE,
'http' => FALSE,
],
'
Intro.
Quoted text linking to www.example.com, written by person@example.com, originating from http://origin.example.com. @see www.usage.example.com or www.example.info bla bla
.
Outro.
' => [
'href="http://www.example.com"' => TRUE,
'href="mailto:person@example.com"' => TRUE,
'href="http://origin.example.com"' => TRUE,
'http://www.usage.example.com' => FALSE,
'http://www.example.info' => FALSE,
'Intro.' => TRUE,
'Outro.' => TRUE,
],
'
Unknown tag Test <br/>: This is a www.example17.com example with various http://www.example18.com tags. *
It is important www.example19.com to *
test different URLs and http://www.example20.com in the same paragraph. *
HTML www.example21.com soup by person@example22.com can litererally http://www.example23.com contain *img* anything. Just a www.example24.com with http://www.example25.com thrown in. www.example26.com from person@example27.com with extra http://www.example28.com.
' => [
'href="http://www.example17.com"' => TRUE,
'href="http://www.example18.com"' => TRUE,
'href="http://www.example19.com"' => TRUE,
'href="http://www.example20.com"' => TRUE,
'href="http://www.example21.com"' => TRUE,
'href="mailto:person@example22.com"' => TRUE,
'href="http://www.example23.com"' => TRUE,
'href="http://www.example24.com"' => TRUE,
'href="http://www.example25.com"' => TRUE,
'href="http://www.example26.com"' => TRUE,
'href="mailto:person@example27.com"' => TRUE,
'href="http://www.example28.com"' => TRUE,
],
'
' => [
'href="http://www.example.com"' => FALSE,
'href="http://example.net"' => FALSE,
],
'
' => [
'href' => FALSE,
],
'
' => [
'href' => FALSE,
],
'
' => [
'href' => FALSE,
],
'
' => [
'href' => FALSE,
],
'
Input string
' => TRUE, * 'Input string' . Html::escape(var_export($source, TRUE)) . '' . '
' . Html::escape(var_export($result, TRUE)) . '' . '
' . Html::escape(var_export($value, TRUE)) . '' ); } } } } /** * Tests URL filter on longer content. * * Filters based on regular expressions should also be tested with a more * complex content than just isolated test lines. * The most common errors are: * - accidental '*' (greedy) match instead of '*?' (minimal) match. * - only matching first occurrence instead of all. * - newlines not matching '.*'. * * This test covers: * - Document with multiple newlines and paragraphs (two newlines). * - Mix of several HTML tags, invalid non-HTML tags, tags to ignore and HTML * comments. * - Empty HTML tags (BR, IMG). * - Mix of absolute and partial URLs, and email addresses in one content. */ public function testUrlFilterContent() { // Get FilterUrl object. $filter = $this->filters['filter_url']; $filter->setConfiguration([ 'settings' => [ 'filter_url_length' => 496, ] ]); $path = __DIR__ . '/../..'; $input = file_get_contents($path . '/filter.url-input.txt'); $expected = file_get_contents($path . '/filter.url-output.txt'); $result = _filter_url($input, $filter); $this->assertIdentical($result, $expected, 'Complex HTML document was correctly processed.'); } /** * Tests the HTML corrector filter. * * @todo This test could really use some validity checking function. */ public function testHtmlCorrectorFilter() { // Tag closing. $f = Html::normalize('
text'); $this->assertEqual($f, '
text
', 'HTML corrector -- tag closing at the end of input.'); $f = Html::normalize('text
text'); $this->assertEqual($f, '
text
text
', 'HTML corrector -- tag closing.'); $f = Html::normalize("test
'); $this->assertEqual($f, 'test
', 'HTML corrector -- Convert uppercased tags to proper lowercased ones.'); $f = Html::normalize('test
'); $this->assertEqual($f, 'test
', 'HTML corrector -- Convert uppercased tags to proper lowercased ones.'); $f = Html::normalize('testline1
line1
line1
line1
test
test
\n'); $this->assertEqual($f, 'test
test
\n', 'HTML corrector -- Auto-close improperly nested tags.'); $f = Html::normalize('Line1 Line1 test\n test\n دروبال');
$this->assertEqual($f, ' دروبال
bold stuff');
$this->assertEqual($f, '
bold stuff