From a0291f5cff8c91000f5b34f69b5ec2c9acbd1031 Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Mon, 3 Feb 2020 16:01:29 +0100
Subject: [PATCH] [BUGFIX] Make overlaid mountpoint pages avoid redirects

If a MountPoint page was overlaid with the Mounted page,
a redirect was triggered. This happened because the slugs
were not identical, so the Mounted Page was not in the
list of the slug candidates.

The behaviour is now resolved, as the Mounted Page is
now added to the candidates and its slug is replaced
by the original slug of the MountPoint page.

Resolves: #90307
Releases: master, 9.5
Change-Id: I0a5bcc320b92e8a2e99ace49f2f84d56cd0b620b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63162
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Sattler <sattler@b13.de>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Daniel Sattler <sattler@b13.de>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
---
 .../Routing/PageSlugCandidateProvider.php     | 22 +++++++++----
 .../SiteHandling/MountPointTest.php           | 33 +++----------------
 2 files changed, 20 insertions(+), 35 deletions(-)

diff --git a/typo3/sysext/core/Classes/Routing/PageSlugCandidateProvider.php b/typo3/sysext/core/Classes/Routing/PageSlugCandidateProvider.php
index dd81d11b06ca..219e00fb5c74 100644
--- a/typo3/sysext/core/Classes/Routing/PageSlugCandidateProvider.php
+++ b/typo3/sysext/core/Classes/Routing/PageSlugCandidateProvider.php
@@ -247,18 +247,26 @@ class PageSlugCandidateProvider
 
             try {
                 $isOnSameSite = $siteFinder->getSiteByPageId($pageIdInDefaultLanguage)->getRootPageId() === $this->site->getRootPageId();
-                if ($isOnSameSite) {
-                    $pages[] = $row;
-                    $excludeUids[] = (int)$row['uid'];
-                } elseif ($mountedPage && $row['mount_pid_ol']) {
+                // If the page is a mountpoint which should be overlaid with the contents of the mounted page,
+                // it must never be accessible directly, but only in the mountpoint context. Therefore we change
+                // the current ID and slug.
+                if ($mountedPage && PageRepository::DOKTYPE_MOUNTPOINT === (int)$row['doktype'] && $row['mount_pid_ol']) {
                     // If the mounted page was already added from above, this should not be added again (to include
                     // the mount point parameter).
                     if (in_array((int)$mountedPage['uid'], $excludeUids, true)) {
                         continue;
                     }
-                    $mountedPage['MPvar'] = $mountPageInformation['MPvar'];
-                    $pages[] = $mountedPage;
-                    $excludeUids[] = (int)$mountedPage['uid'];
+                    $pageToAdd = $mountedPage;
+                    // Make sure target page "/about-us" is replaced by "/global-site/about-us" so router works
+                    $pageToAdd['MPvar'] = $mountPageInformation['MPvar'];
+                    $pageToAdd['slug'] = $row['slug'];
+                    $pages[] = $pageToAdd;
+                    $excludeUids[] = (int)$pageToAdd['uid'];
+                    $excludeUids[] = $pageIdInDefaultLanguage;
+                }
+                if ($isOnSameSite && !in_array($pageIdInDefaultLanguage, $excludeUids, true)) {
+                    $pages[] = $row;
+                    $excludeUids[] = $pageIdInDefaultLanguage;
                 }
             } catch (SiteNotFoundException $e) {
                 // Page is not in a site, so it's not considered
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/MountPointTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/MountPointTest.php
index 9894a4f52980..15a8e8dc392c 100644
--- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/MountPointTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/MountPointTest.php
@@ -492,43 +492,20 @@ class MountPointTest extends AbstractTestCase
         self::assertSame($expectedMountPointParameter, $responseData['dynamicArguments']['MP'] ?? null);
     }
 
-    /**
-     * @test
-     * @group not-postgres
-     * Does not work on postres currenly due to setUpFrontendRootPage which does not work with the database snapshotting
-     */
-    public function accessingAMountPointDirectlyThatShouldNotBeAvailableTriggersARedirect()
-    {
-        $uri = 'https://acme.ca/all-news/canada';
-        $targetUrl = 'https://acme.ca/all-news/canada/all-news/canada/';
-        $this->setUpFrontendRootPage(
-            2000,
-            [
-                'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkRequest.typoscript',
-            ],
-            [
-                'title' => 'ACME Root',
-                'sitetitle' => $this->siteTitle,
-            ]
-        );
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest($uri)),
-            $this->internalRequestContext
-        );
-        self::assertSame(307, $response->getStatusCode());
-        self::assertSame($targetUrl, $response->getHeaderLine('Location'));
-    }
-
     /**
      * @return array
      */
     public function mountPointPagesShowContentAsConfiguredDataProvider()
     {
         return [
-            'Show content of MountPoint page' => [
+            'Show content of MountPoint Page' => [
                 'https://acme.ca/all-news/archive',
                 'Content of MountPoint Page'
             ],
+            'Show content of Mounted Page' => [
+                'https://acme.ca/all-news/canada',
+                'See a list of all games distributed in canada'
+            ],
         ];
     }
 
-- 
GitLab