[BUGFIX] Decode tag attributes during HTML parsing 99/61799/9
authorHelmut Hummel <typo3@helhum.io>
Tue, 24 Sep 2019 14:09:43 +0000 (16:09 +0200)
committerBenni Mack <benni@typo3.org>
Sat, 9 Nov 2019 15:01:41 +0000 (16:01 +0100)
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: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/EmailViewHelperTest.php
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Classes/Typolink/ExternalUrlLinkBuilder.php
typo3/sysext/frontend/Tests/Functional/ContentObject/ContentObjectRendererTest.php
typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php

index 9894261..e45bd9f 100644 (file)
@@ -1226,7 +1226,7 @@ class GeneralUtility
             if ($val !== '=') {
                 if ($valuemode) {
                     if ($name) {
-                        $attributes[$name] = $val;
+                        $attributes[$name] = htmlspecialchars_decode($val);
                         $name = '';
                     }
                 } else {
index 00a9810..0fdb64e 100644 (file)
@@ -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>',
index 72fb858..98f4ae3 100644 (file)
@@ -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));
index efa4474..a20d11f 100644 (file)
@@ -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)
         ];
index 2f60684..3551cb9 100644 (file)
@@ -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']);
index c5ef2c0..e0178c7 100644 (file)
@@ -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' => [
                 [