Commit c6f589f3 authored by Helmut Hummel's avatar Helmut Hummel Committed by Benni Mack
Browse files

[BUGFIX] Decode tag attributes during HTML parsing

When parsing HTML in parsefunc, we need to make sure
that the attributes that are extracted for further processing
are properly HTML decoded, as per definition they are encoded in
the HTML being parsed.

At the same time we revert a decode that was applied in ExternalUrlLinkBuilder,
as this is the wrong place to handle HTML decoding, as the link builder
is as well called with data from other contexts (TypoScript, data from link fields)
that must not have the URL HTML encoded.

This fix is required to allow email links to add subject and body arguments like:
test@foo.test?subject=foo%20bar&body=baz

and not have the ampersand in the url double encoded when generating links
from RTE content.

Additionally we need to properly encode the masked value for the JavaScript
URI, to prevent browsers from url decoding wrong values.

Releases: master, 9.5
Resolves: #89264
Related: #81625
Related: #80985
Change-Id: I3be2478df83cffc0dfe6af918eb224b4ee480b10
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61799

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 2485bdf5
......@@ -1226,7 +1226,7 @@ class GeneralUtility
if ($val !== '=') {
if ($valuemode) {
if ($name) {
$attributes[$name] = $val;
$attributes[$name] = htmlspecialchars_decode($val);
$name = '';
}
} else {
......
......@@ -102,7 +102,7 @@ class EmailViewHelperTest extends ViewHelperBaseTestcase
'Plain email with spam protection' => [
'some@email.tld',
1,
'<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnfAfnbjm\/ume\');">some(at)email.tld</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2BtpnfAfnbjm%5C%2Fume%27);">some(at)email.tld</a>',
],
'Plain email with ascii spam protection' => [
'some@email.tld',
......@@ -117,7 +117,7 @@ class EmailViewHelperTest extends ViewHelperBaseTestcase
'Susceptible email with spam protection' => [
'"><script>alert(\'email\')</script>',
1,
'<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+\u0022\u003E\u003Ctdsjqu\u003Ebmfsu(\u0027fnbjm\u0027)\u003C0tdsjqu\u003E\');">&quot;&gt;&lt;script&gt;alert(\'email\')&lt;/script&gt;</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2B%5Cu0022%5Cu003E%5Cu003Ctdsjqu%5Cu003Ebmfsu%28%5Cu0027fnbjm%5Cu0027%29%5Cu003C0tdsjqu%5Cu003E%27);">&quot;&gt;&lt;script&gt;alert(\'email\')&lt;/script&gt;</a>',
],
'Susceptible email with ascii spam protection' => [
'"><script>alert(\'email\')</script>',
......
......@@ -5397,7 +5397,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
if ($tsfe->spamProtectEmailAddresses) {
$mailToUrl = $this->encryptEmail($mailToUrl, $tsfe->spamProtectEmailAddresses);
if ($tsfe->spamProtectEmailAddresses !== 'ascii') {
$mailToUrl = 'javascript:linkTo_UnCryptMailto(' . GeneralUtility::quoteJSvalue($mailToUrl) . ');';
$encodedForJsAndHref = rawurlencode(GeneralUtility::quoteJSvalue($mailToUrl));
$mailToUrl = 'javascript:linkTo_UnCryptMailto(' . $encodedForJsAndHref . ');';
}
$atLabel = trim($tsfe->config['config']['spamProtectEmailAddresses_atSubst']) ?: '(at)';
$spamProtectedMailAddress = str_replace('@', $atLabel, htmlspecialchars($mailAddress));
......
......@@ -27,7 +27,7 @@ class ExternalUrlLinkBuilder extends AbstractTypolinkBuilder
public function build(array &$linkDetails, string $linkText, string $target, array $conf): array
{
return [
$this->processUrl(UrlProcessorInterface::CONTEXT_EXTERNAL, htmlspecialchars_decode($linkDetails['url']), $conf),
$this->processUrl(UrlProcessorInterface::CONTEXT_EXTERNAL, $linkDetails['url'], $conf),
$this->parseFallbackLinkTextIfLinkTextIsEmpty($linkText, $linkDetails['url']),
$target ?: $this->resolveTargetAttribute($conf, 'extTarget', true, $this->getTypoScriptFrontendController()->extTarget)
];
......
......@@ -494,7 +494,7 @@ class ContentObjectRendererTest extends FunctionalTestCase
$tsfe->spamProtectEmailAddresses = 1;
$result = $subject->typoLink('Send me an email', ['parameter' => 'mailto:test@example.com']);
self::assertEquals('<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+uftuAfybnqmf\/dpn\');">Send me an email</a>', $result);
self::assertEquals('<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2BuftuAfybnqmf%5C%2Fdpn%27);">Send me an email</a>', $result);
$tsfe->spamProtectEmailAddresses = 'ascii';
$result = $subject->typoLink('Send me an email', ['parameter' => 'mailto:test@example.com']);
......
......@@ -2909,7 +2909,7 @@ class ContentObjectRendererTest extends UnitTestCase
],
'some.body@test.typo3.org',
'mailto:some.body@test.typo3.org',
'<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3.org</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2Btpnf%5C%2FcpezAuftu%5C%2Fuzqp4%5C%2Fpsh%27);">some.body(at)test.typo3.org</a>',
],
'mono-alphabetic substitution offset +1 with at substitution' => [
[
......@@ -2919,7 +2919,7 @@ class ContentObjectRendererTest extends UnitTestCase
],
'some.body@test.typo3.org',
'mailto:some.body@test.typo3.org',
'<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body@test.typo3.org</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2Btpnf%5C%2FcpezAuftu%5C%2Fuzqp4%5C%2Fpsh%27);">some.body@test.typo3.org</a>',
],
'mono-alphabetic substitution offset +1 with at and dot substitution' => [
[
......@@ -2929,7 +2929,7 @@ class ContentObjectRendererTest extends UnitTestCase
],
'some.body@test.typo3.org',
'mailto:some.body@test.typo3.org',
'<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3(dot)org</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27nbjmup%2Btpnf%5C%2FcpezAuftu%5C%2Fuzqp4%5C%2Fpsh%27);">some.body(at)test.typo3(dot)org</a>',
],
'mono-alphabetic substitution offset -1 with at and dot substitution' => [
[
......@@ -2939,7 +2939,17 @@ class ContentObjectRendererTest extends UnitTestCase
],
'some.body@test.typo3.org',
'mailto:some.body@test.typo3.org',
'<a href="javascript:linkTo_UnCryptMailto(\'lzhksn9rnld-ancxZsdrs-sxon2-nqf\');">some.body(at)test.typo3(dot)org</a>',
'<a href="javascript:linkTo_UnCryptMailto(%27lzhksn9rnld-ancxZsdrs-sxon2-nqf%27);">some.body(at)test.typo3(dot)org</a>',
],
'mono-alphabetic substitution offset 2 with at and dot substitution and encoded subject' => [
[
'spamProtectEmailAddresses' => '2',
'spamProtectEmailAddresses_atSubst' => '(at)',
'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
],
'some.body@test.typo3.org',
'mailto:some.body@test.typo3.org?subject=foo%20bar',
'<a href="javascript:linkTo_UnCryptMailto(%27ocknvq%2Cuqog0dqfaBvguv0varq50qti%3Fuwdlgev%3Dhqq%2542dct%27);">some.body@test.typo3.org</a>',
],
'entity substitution with at and dot substitution' => [
[
......
Supports Markdown
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