Skip to content

Commit

Permalink
[TASK] Add iframe example scenario
Browse files Browse the repository at this point in the history
Related: TYPO3#70
  • Loading branch information
ohader committed Oct 6, 2022
1 parent 46a9b03 commit 00dfa6f
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/Behavior/MultiTokenAttrValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 project.
*
* It is free software; you can redistribute it and/or modify it under the terms
* of the MIT License (MIT). For the full copyright and license information,
* please read the LICENSE file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\HtmlSanitizer\Behavior;

use LogicException;

class MultiTokenAttrValue implements AttrValueInterface
{
/**
* @var string
*/
protected $delimiter;

/**
* @var list<string>
*/
protected $tokens;

public function __construct(string $delimiter, string ...$tokens)
{
if ($delimiter === '') {
throw new LogicException('Delimiter cannot be empty', 1642111976);
}
$tokens = array_filter($tokens, [$this, 'keepNonEmpty']);
if ($tokens === []) {
throw new LogicException('Tokens cannot be empty or only empty strings', 1642111637);
}
$this->delimiter = $delimiter;
$this->tokens = $tokens;
}

public function matches(string $value): bool
{
$tokens = explode($this->delimiter, $value);
$tokens = array_filter($tokens, [$this, 'keepNonEmpty']);
// in case there is no token, the result implicit is `true`
// @todo has to be changed, in case mandatory tokes would be implemented
if (empty($tokens)) {
return true;
}
return array_diff($tokens, $this->tokens) === [];
}

protected function keepNonEmpty(string $item): bool
{
return $item !== '';
}
}
56 changes: 56 additions & 0 deletions tests/ScenarioTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use PHPUnit\Framework\TestCase;
use TYPO3\HtmlSanitizer\Behavior;
use TYPO3\HtmlSanitizer\Behavior\Attr\UriAttrValueBuilder;
use TYPO3\HtmlSanitizer\Sanitizer;
use TYPO3\HtmlSanitizer\Visitor\CommonVisitor;

Expand Down Expand Up @@ -154,4 +155,59 @@ public function isJsonLdScriptAllowed(): void
);
self::assertSame($expectation, $sanitizer->sanitize($payload));
}

/**
* @test
*/
public function iframeSandboxIsAllowed(): void
{
$payload = implode("\n" , [
'1:<iframe src="https://example.org/"></iframe>',
'2:<iframe src="https://example.org/" sandbox></iframe>',
// `sandbox` will be removed, since token is not valid
'3:<iframe src="https://example.org/" sandbox="allow-non-existing-property"></iframe>',
'4:<iframe src="https://example.org/" allow="fullscreen" sandbox="allow-downloads allow-modals"></iframe>',
'5:<iframe src="https://example.org/" sandbox="allow-downloads allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-scripts"></iframe>',
]);
$expectation = implode("\n" , [
'1:&lt;iframe src="https://example.org/"&gt;&lt;/iframe&gt;',
'2:<iframe src="https://example.org/" sandbox></iframe>',
'3:&lt;iframe src="https://example.org/"&gt;&lt;/iframe&gt;',
'4:<iframe src="https://example.org/" allow="fullscreen" sandbox="allow-downloads allow-modals"></iframe>',
'5:<iframe src="https://example.org/" sandbox="allow-downloads allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-scripts"></iframe>',
]);

$behavior = (new Behavior())
->withFlags(Behavior::ENCODE_INVALID_TAG + Behavior::REMOVE_UNEXPECTED_CHILDREN)
->withName('scenario-test')
->withTags(
(new Behavior\Tag('iframe'))->addAttrs(
(new Behavior\Attr('id')),
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allow
(new Behavior\Attr('allow'))->withValues(
new Behavior\MultiTokenAttrValue(' ', 'fullscreen')
),
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox
(new Behavior\Attr('sandbox', Behavior\Attr::MANDATORY))->withValues(
new Behavior\MultiTokenAttrValue(
' ',
'allow-downloads',
'allow-modals',
'allow-orientation-lock',
'allow-pointer-lock',
'allow-popups',
'allow-scripts'
)
),
(new Behavior\Attr('src'))->withValues(
...(new UriAttrValueBuilder())->allowSchemes('http', 'https')->getValues()
)
)
);

$sanitizer = new Sanitizer(
new CommonVisitor($behavior)
);
self::assertSame($expectation, $sanitizer->sanitize($payload));
}
}

0 comments on commit 00dfa6f

Please sign in to comment.