From db96ba007b9bcc8de361d3a33bd993ceaea398a8 Mon Sep 17 00:00:00 2001
From: Oliver Bartsch <bo@cedev.de>
Date: Thu, 26 Aug 2021 17:54:27 +0200
Subject: [PATCH] [BUGFIX] Correctly replace error code placeholder

Fixes a regression, introduced in #94315 and
restores legacy placeholder in cases it is used
in custom error messages, set via TypoScript.

Resolves: #95008
Related: #94315
Releases: master
Change-Id: I59b95d9d311be81faa73ae14d48f97584882f5fd
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70771
Tested-by: Jochen <rothjochen@gmail.com>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Jochen <rothjochen@gmail.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../Exception/ProductionExceptionHandler.php  |  3 +-
 .../ProductionExceptionHandlerTest.php        | 72 +++++++++++++++++++
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/typo3/sysext/frontend/Classes/ContentObject/Exception/ProductionExceptionHandler.php b/typo3/sysext/frontend/Classes/ContentObject/Exception/ProductionExceptionHandler.php
index 7a7790300422..1460ff00fa1a 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/Exception/ProductionExceptionHandler.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/Exception/ProductionExceptionHandler.php
@@ -69,7 +69,8 @@ class ProductionExceptionHandler implements ExceptionHandlerInterface, LoggerAwa
 
         $this->logException($exception, $errorMessage, $code);
 
-        return sprintf($errorMessage, $code);
+        // "%s" is for b/w compatibility
+        return str_replace(['%s', '{code}'], $code, $errorMessage);
     }
 
     /**
diff --git a/typo3/sysext/frontend/Tests/Unit/ContentObject/Exception/ProductionExceptionHandlerTest.php b/typo3/sysext/frontend/Tests/Unit/ContentObject/Exception/ProductionExceptionHandlerTest.php
index 9689790ae3b5..e53eb04fab3c 100644
--- a/typo3/sysext/frontend/Tests/Unit/ContentObject/Exception/ProductionExceptionHandlerTest.php
+++ b/typo3/sysext/frontend/Tests/Unit/ContentObject/Exception/ProductionExceptionHandlerTest.php
@@ -17,10 +17,13 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Exception;
 
+use Prophecy\PhpUnit\ProphecyTrait;
 use Psr\Log\NullLogger;
+use TYPO3\CMS\Core\Crypto\Random;
 use TYPO3\CMS\Core\Http\HtmlResponse;
 use TYPO3\CMS\Core\Http\ImmediateResponseException;
 use TYPO3\CMS\Core\Http\PropagateResponseException;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\ContentObject\Exception\ProductionExceptionHandler;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
@@ -29,6 +32,8 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
  */
 class ProductionExceptionHandlerTest extends UnitTestCase
 {
+    use ProphecyTrait;
+
     /**
      * @var ProductionExceptionHandler
      */
@@ -70,4 +75,71 @@ class ProductionExceptionHandlerTest extends UnitTestCase
         $this->expectException(ImmediateResponseException::class);
         $this->subject->handle($exception);
     }
+
+    /**
+     * @test
+     */
+    public function handleReturnsMessageWithResolvedErrorCode(): void
+    {
+        $currentTimestamp = 1629993829;
+        $random = '029cca07';
+
+        $_SERVER['REQUEST_TIME'] = $currentTimestamp;
+        $randomProphecy = $this->prophesize(Random::class);
+        $randomProphecy->generateRandomHexString(8)->willReturn($random);
+        GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
+
+        self::assertEquals(
+            'Oops, an error occurred! Code: ' . date('YmdHis', $currentTimestamp) . $random,
+            $this->subject->handle(new \Exception('Some exception', 1629996089))
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function handleReturnsCustomErrorMessageWithResolvedErrorCode(): void
+    {
+        $currentTimestamp = 1629993829;
+        $random = '029cca07';
+
+        $_SERVER['REQUEST_TIME'] = $currentTimestamp;
+        $randomProphecy = $this->prophesize(Random::class);
+        $randomProphecy->generateRandomHexString(8)->willReturn($random);
+        GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
+
+        $exceptionHandler = new ProductionExceptionHandler([
+           'errorMessage' => 'Custom error message: {code}'
+       ]);
+        $exceptionHandler->setLogger(new NullLogger());
+
+        self::assertEquals(
+            'Custom error message: ' . date('YmdHis', $currentTimestamp) . $random,
+            $exceptionHandler->handle(new \Exception('Some exception', 1629996090))
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function handleReturnsCustomErrorMessageWithResolvedErrorCodeForLegacyPlaceholder(): void
+    {
+        $currentTimestamp = 1629993829;
+        $random = '029cca07';
+
+        $_SERVER['REQUEST_TIME'] = $currentTimestamp;
+        $randomProphecy = $this->prophesize(Random::class);
+        $randomProphecy->generateRandomHexString(8)->willReturn($random);
+        GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
+
+        $exceptionHandler = new ProductionExceptionHandler([
+            'errorMessage' => 'Custom error message: %s'
+        ]);
+        $exceptionHandler->setLogger(new NullLogger());
+
+        self::assertEquals(
+            'Custom error message: ' . date('YmdHis', $currentTimestamp) . $random,
+            $exceptionHandler->handle(new \Exception('Some exception', 1629996091))
+        );
+    }
 }
-- 
GitLab