From 552991869d10f93af99f0aa0959b58ff8fd48f00 Mon Sep 17 00:00:00 2001
From: Oliver Hader <oliver@typo3.org>
Date: Wed, 20 Jan 2016 19:18:24 +0100
Subject: [PATCH] [BUGFIX] Absolute URIs get prefixed with absRefPrefix in
 typolink

An absolute URI (e.g. "/folder/someFile.png") gets prefixed with
absRefPrefix (e.g. "/") which results in "//folder/someFile.png",
which is a schema-less URI notation and thus "folder" is
interpreted as hostname.

Resolves: #72846
Releases: master, 7.6
Change-Id: Ic49c0a24a17f754c6c89186e6041b9857eb967b1
Reviewed-on: https://review.typo3.org/46113
Reviewed-by: Jan Helke <typo3@helke.de>
Tested-by: Jan Helke <typo3@helke.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
---
 .../ContentObject/ContentObjectRenderer.php   |   3 +-
 .../ContentObjectRendererTest.php             | 149 ++++++++++++++++++
 2 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
index 6dd8af10b7f0..ea9be1157346 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
@@ -5905,7 +5905,8 @@ class ContentObjectRenderer
                 if (file_exists(rawurldecode($splitLinkParam[0])) || strpos($linkParameter, '/') !== false) {
                     // Setting title if blank value to link
                     $linkText = $this->parseFallbackLinkTextIfLinkTextIsEmpty($linkText, rawurldecode($linkParameter));
-                    $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_FILE, $GLOBALS['TSFE']->absRefPrefix . $linkParameter, $conf);
+                    $fileUri = (!StringUtility::beginsWith($linkParameter, '/') ? $GLOBALS['TSFE']->absRefPrefix : '') . $linkParameter;
+                    $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_FILE, $fileUri, $conf);
                     $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
                     if (empty($target)) {
                         $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $tsfe->fileTarget;
diff --git a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
index 0247404cddd7..ba46e80f888c 100755
--- a/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
+++ b/typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php
@@ -4572,6 +4572,155 @@ class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
     }
 
+    /**
+     * @return array
+     */
+    public function typolinkReturnsCorrectLinksForFilesWithAbsRefPrefixDataProvider()
+    {
+        return array(
+            'Link to file' => array(
+                'My file',
+                array(
+                    'parameter' => 'fileadmin/foo.bar',
+                ),
+                '/',
+                '<a href="/fileadmin/foo.bar">My file</a>',
+            ),
+            'Link to file with longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => 'fileadmin/foo.bar',
+                ),
+                '/sub/',
+                '<a href="/sub/fileadmin/foo.bar">My file</a>',
+            ),
+            'Link to absolute file' => array(
+                'My file',
+                array(
+                    'parameter' => '/images/foo.bar',
+                ),
+                '/',
+                '<a href="/images/foo.bar">My file</a>',
+            ),
+            'Link to absolute file with longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/images/foo.bar',
+                ),
+                '/sub/',
+                '<a href="/images/foo.bar">My file</a>',
+            ),
+            'Link to absolute file with identical longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/sub/fileadmin/foo.bar',
+                ),
+                '/sub/',
+                '<a href="/sub/fileadmin/foo.bar">My file</a>',
+            ),
+            'Link to file with empty absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => 'fileadmin/foo.bar',
+                ),
+                '',
+                '<a href="fileadmin/foo.bar">My file</a>',
+            ),
+            'Link to absolute file with empty absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/fileadmin/foo.bar',
+                ),
+                '',
+                '<a href="/fileadmin/foo.bar">My file</a>',
+            ),
+            'Link to file with attributes with absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => 'fileadmin/foo.bar',
+                    'ATagParams' => 'class="file-class"',
+                    'fileTarget' => '_blank',
+                    'title' => 'Title of the file',
+                ),
+                '/',
+                '<a href="/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
+            ),
+            'Link to file with attributes with longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => 'fileadmin/foo.bar',
+                    'ATagParams' => 'class="file-class"',
+                    'fileTarget' => '_blank',
+                    'title' => 'Title of the file',
+                ),
+                '/sub/',
+                '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
+            ),
+            'Link to absolute file with attributes with absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/images/foo.bar',
+                    'ATagParams' => 'class="file-class"',
+                    'fileTarget' => '_blank',
+                    'title' => 'Title of the file',
+                ),
+                '/',
+                '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
+            ),
+            'Link to absolute file with attributes with longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/images/foo.bar',
+                    'ATagParams' => 'class="file-class"',
+                    'fileTarget' => '_blank',
+                    'title' => 'Title of the file',
+                ),
+                '/sub/',
+                '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
+            ),
+            'Link to absolute file with attributes with identical longer absRefPrefix' => array(
+                'My file',
+                array(
+                    'parameter' => '/sub/fileadmin/foo.bar',
+                    'ATagParams' => 'class="file-class"',
+                    'fileTarget' => '_blank',
+                    'title' => 'Title of the file',
+                ),
+                '/sub/',
+                '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
+            ),
+        );
+    }
+
+    /**
+     * @test
+     * @param string $linkText
+     * @param array $configuration
+     * @param string $absRefPrefix
+     * @param string $expectedResult
+     * @dataProvider typolinkReturnsCorrectLinksForFilesWithAbsRefPrefixDataProvider
+     */
+    public function typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
+    {
+        $templateServiceObjectMock = $this->getMock(TemplateService::class, array('dummy'));
+        $templateServiceObjectMock->setup = array(
+            'lib.' => array(
+                'parseFunc.' => $this->getLibParseFunc(),
+            ),
+        );
+        $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, array(), array(), '', false);
+        $typoScriptFrontendControllerMockObject->config = array(
+            'config' => array(),
+            'mainScript' => 'index.php',
+        );
+        $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
+        $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
+        $GLOBALS['TSFE']->absRefPrefix = $absRefPrefix;
+        $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
+
+        $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
+    }
+
     /**
      * @test
      */
-- 
GitLab