Chris@0: assertNormalized($value, $expected, $message);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Data provider for testFilterXssNormalized().
Chris@0: *
Chris@0: * @see testFilterXssNormalized()
Chris@0: *
Chris@0: * @return array
Chris@0: * An array of arrays containing strings:
Chris@0: * - The value to filter.
Chris@0: * - The value to expect after filtering.
Chris@0: * - The assertion message.
Chris@0: * - (optional) The allowed HTML HTML tags array that should be passed to
Chris@0: * \Drupal\Component\Utility\Xss::filter().
Chris@0: */
Chris@0: public function providerTestFilterXssNormalized() {
Chris@0: return [
Chris@0: [
Chris@0: "Who's Online",
Chris@0: "who's online",
Chris@0: 'HTML filter -- html entity number',
Chris@0: ],
Chris@0: [
Chris@0: "Who's Online",
Chris@0: "who's online",
Chris@0: 'HTML filter -- encoded html entity number',
Chris@0: ],
Chris@0: [
Chris@0: "Who' Online",
Chris@0: "who' online",
Chris@0: 'HTML filter -- double encoded html entity number',
Chris@0: ],
Chris@0: // Custom elements with dashes in the tag name.
Chris@0: [
Chris@0: "",
Chris@0: "",
Chris@0: 'Custom element with dashes in tag name.',
Chris@0: ['test-element'],
Chris@0: ],
Chris@0: ];
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Tests limiting to allowed tags and XSS prevention.
Chris@0: *
Chris@0: * XSS tests assume that script is disallowed by default and src is allowed
Chris@0: * by default, but on* and style attributes are disallowed.
Chris@0: *
Chris@0: * @param string $value
Chris@0: * The value to filter.
Chris@0: * @param string $expected
Chris@0: * The string that is expected to be missing.
Chris@0: * @param string $message
Chris@0: * The assertion message to display upon failure.
Chris@0: * @param array $allowed_tags
Chris@0: * (optional) The allowed HTML tags to be passed to \Drupal\Component\Utility\Xss::filter().
Chris@0: *
Chris@0: * @dataProvider providerTestFilterXssNotNormalized
Chris@0: */
Chris@0: public function testFilterXssNotNormalized($value, $expected, $message, array $allowed_tags = NULL) {
Chris@0: if ($allowed_tags === NULL) {
Chris@0: $value = Xss::filter($value);
Chris@0: }
Chris@0: else {
Chris@0: $value = Xss::filter($value, $allowed_tags);
Chris@0: }
Chris@0: $this->assertNotNormalized($value, $expected, $message);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Data provider for testFilterXssNotNormalized().
Chris@0: *
Chris@0: * @see testFilterXssNotNormalized()
Chris@0: *
Chris@0: * @return array
Chris@0: * An array of arrays containing the following elements:
Chris@0: * - The value to filter.
Chris@0: * - The value to expect that's missing after filtering.
Chris@0: * - The assertion message.
Chris@0: * - (optional) The allowed HTML HTML tags array that should be passed to
Chris@0: * \Drupal\Component\Utility\Xss::filter().
Chris@0: */
Chris@0: public function providerTestFilterXssNotNormalized() {
Chris@0: $cases = [
Chris@0: // Tag stripping, different ways to work around removal of HTML tags.
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping -- simple script without special characters.',
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping -- empty script with source.',
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- non whitespace character after tag name.',
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- no space between tag and attribute.',
Chris@0: ],
Chris@0: // Null between < and tag name works at least with IE6.
Chris@0: [
Chris@0: "<\0scr\0ipt>alert(0)",
Chris@0: 'ipt',
Chris@0: 'HTML tag stripping evasion -- breaking HTML with nulls.',
Chris@0: ],
Chris@0: [
Chris@0: "",
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- filter just removing "script".',
Chris@0: ],
Chris@0: [
Chris@0: '<',
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- double opening brackets.',
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- a malformed image tag.',
Chris@0: ['img'],
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- script in a blockqoute.',
Chris@0: ['blockquote'],
Chris@0: ],
Chris@0: [
Chris@0: "",
Chris@0: 'script',
Chris@0: 'HTML tag stripping evasion -- script within a comment.',
Chris@0: ],
Chris@0: // Dangerous attributes removal.
Chris@0: [
Chris@0: '
",
Chris@0: 'style',
Chris@0: 'HTML filter -- invalid UTF-8.',
Chris@0: ['p'],
Chris@0: ],
Chris@0: ];
Chris@0: // @fixme This dataset currently fails under 5.4 because of
Chris@0: // https://www.drupal.org/node/1210798. Restore after its fixed.
Chris@0: if (version_compare(PHP_VERSION, '5.4.0', '<')) {
Chris@0: $cases[] = [
Chris@0: '',
Chris@0: 'javascript',
Chris@0: 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.',
Chris@0: ['img'],
Chris@0: ];
Chris@0: }
Chris@0: return $cases;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Checks that invalid multi-byte sequences are rejected.
Chris@0: *
Chris@0: * @param string $value
Chris@0: * The value to filter.
Chris@0: * @param string $expected
Chris@0: * The expected result.
Chris@0: * @param string $message
Chris@0: * The assertion message to display upon failure.
Chris@0: *
Chris@0: * @dataProvider providerTestInvalidMultiByte
Chris@0: */
Chris@0: public function testInvalidMultiByte($value, $expected, $message) {
Chris@0: $this->assertEquals(Xss::filter($value), $expected, $message);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Data provider for testInvalidMultiByte().
Chris@0: *
Chris@0: * @see testInvalidMultiByte()
Chris@0: *
Chris@0: * @return array
Chris@0: * An array of arrays containing strings:
Chris@0: * - The value to filter.
Chris@0: * - The value to expect after filtering.
Chris@0: * - The assertion message.
Chris@0: */
Chris@0: public function providerTestInvalidMultiByte() {
Chris@0: return [
Chris@0: ["Foo\xC0barbaz", '', 'Xss::filter() accepted invalid sequence "Foo\xC0barbaz"'],
Chris@0: ["Fooÿñ", "Fooÿñ", 'Xss::filter() rejects valid sequence Fooÿñ"'],
Chris@0: ["\xc0aaa", '', 'HTML filter -- overlong UTF-8 sequences.'],
Chris@0: ];
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Checks that strings starting with a question sign are correctly processed.
Chris@0: */
Chris@0: public function testQuestionSign() {
Chris@0: $value = Xss::filter('');
Chris@0: $this->assertTrue(stripos($value, 'assertEquals($expected, $value, $message);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Data provider for testFilterXssAdminNotNormalized().
Chris@0: */
Chris@0: public function providerTestAttributes() {
Chris@0: return [
Chris@0: [
Chris@0: '',
Chris@0: '',
Chris@0: 'Image tag with alt and title attribute',
Chris@17: ['img'],
Chris@0: ],
Chris@0: [
Chris@0: 'Drupal',
Chris@0: 'Drupal',
Chris@0: 'Link tag with rel attribute',
Chris@17: ['a'],
Chris@0: ],
Chris@0: [
Chris@0: 'Drupal 8: The best release ever.',
Chris@0: 'Drupal 8: The best release ever.',
Chris@0: 'Span tag with property attribute',
Chris@17: ['span'],
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: '',
Chris@0: 'Image tag with data attribute',
Chris@17: ['img'],
Chris@0: ],
Chris@0: [
Chris@0: '',
Chris@0: '',
Chris@0: 'Link tag with numeric data attribute',
Chris@17: ['a'],
Chris@0: ],
Chris@0: ];
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Checks that \Drupal\Component\Utility\Xss::filterAdmin() correctly strips unallowed tags.
Chris@0: */
Chris@0: public function testFilterXSSAdmin() {
Chris@0: $value = Xss::filterAdmin('
');
Chris@0: $this->assertEquals($value, '', 'Admin HTML filter -- should never allow some tags.');
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Tests the loose, admin HTML filter.
Chris@0: *
Chris@0: * @param string $value
Chris@0: * The value to filter.
Chris@0: * @param string $expected
Chris@0: * The expected result.
Chris@0: * @param string $message
Chris@0: * The assertion message to display upon failure.
Chris@0: *
Chris@0: * @dataProvider providerTestFilterXssAdminNotNormalized
Chris@0: */
Chris@0: public function testFilterXssAdminNotNormalized($value, $expected, $message) {
Chris@0: $this->assertNotNormalized(Xss::filterAdmin($value), $expected, $message);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Data provider for testFilterXssAdminNotNormalized().
Chris@0: *
Chris@0: * @see testFilterXssAdminNotNormalized()
Chris@0: *
Chris@0: * @return array
Chris@0: * An array of arrays containing strings:
Chris@0: * - The value to filter.
Chris@0: * - The value to expect after filtering.
Chris@0: * - The assertion message.
Chris@0: */
Chris@0: public function providerTestFilterXssAdminNotNormalized() {
Chris@0: return [
Chris@0: // DRUPAL-SA-2008-044
Chris@0: ['', 'object', 'Admin HTML filter -- should not allow object tag.'],
Chris@0: ['', 'script', 'Admin HTML filter -- should not allow script tag.'],
Chris@0: ];
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Asserts that a text transformed to lowercase with HTML entities decoded does contain a given string.
Chris@0: *
Chris@0: * Otherwise fails the test with a given message, similar to all the
Chris@0: * SimpleTest assert* functions.
Chris@0: *
Chris@0: * Note that this does not remove nulls, new lines and other characters that
Chris@0: * could be used to obscure a tag or an attribute name.
Chris@0: *
Chris@0: * @param string $haystack
Chris@0: * Text to look in.
Chris@0: * @param string $needle
Chris@0: * Lowercase, plain text to look for.
Chris@0: * @param string $message
Chris@0: * (optional) Message to display if failed. Defaults to an empty string.
Chris@0: * @param string $group
Chris@0: * (optional) The group this message belongs to. Defaults to 'Other'.
Chris@0: */
Chris@0: protected function assertNormalized($haystack, $needle, $message = '', $group = 'Other') {
Chris@0: $this->assertTrue(strpos(strtolower(Html::decodeEntities($haystack)), $needle) !== FALSE, $message, $group);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Asserts that text transformed to lowercase with HTML entities decoded does not contain a given string.
Chris@0: *
Chris@0: * Otherwise fails the test with a given message, similar to all the
Chris@0: * SimpleTest assert* functions.
Chris@0: *
Chris@0: * Note that this does not remove nulls, new lines, and other character that
Chris@0: * could be used to obscure a tag or an attribute name.
Chris@0: *
Chris@0: * @param string $haystack
Chris@0: * Text to look in.
Chris@0: * @param string $needle
Chris@0: * Lowercase, plain text to look for.
Chris@0: * @param string $message
Chris@0: * (optional) Message to display if failed. Defaults to an empty string.
Chris@0: * @param string $group
Chris@0: * (optional) The group this message belongs to. Defaults to 'Other'.
Chris@0: */
Chris@0: protected function assertNotNormalized($haystack, $needle, $message = '', $group = 'Other') {
Chris@0: $this->assertTrue(strpos(strtolower(Html::decodeEntities($haystack)), $needle) === FALSE, $message, $group);
Chris@0: }
Chris@0:
Chris@0: }