Repository: slimphp/Slim (php)

Issue:
HTML Entity Encoding in PlainTextErrorRenderer
## Description
The `PlainTextErrorRenderer` in Slim Framework applies HTML entity encoding to exception messages via the `htmlentities` function. This behavior leads to the encoding of special characters in log messages and other plain text outputs, which might not be desired in all contexts.

## Slim Framework Version
4

## Steps to Reproduce
1. Use the `PlainTextErrorRenderer` to handle exceptions.
2. Trigger an exception with a message that includes characters that are typically encoded by `htmlentities` (like double quotes).
3. Observe the output (in logs, terminal, etc.) and notice that characters are HTML entity encoded (e.g., double quotes are converted to `&quot;`).

## Expected Behavior
In a plain text context, one would expect the error message to be rendered as-is, without HTML entity encoding. The use of `htmlentities` might be more appropriate for HTML-specific renderers.

## Actual Behavior
The error message is HTML entity encoded, leading to representations like `&quot;` in place of double quotes in plain text outputs.

## Possible Solution
Consider removing the `htmlentities` call from the `PlainTextErrorRenderer`, or provide an option to disable HTML entity encoding based on the context in which the renderer is used.

## Context
This encoding issue affects logging, CLI outputs, and other scenarios where HTML entity encoding is not desirable in error messages.


https://github.com/slimphp/Slim/blob/fdb6d614700a4e9390c3b08dde96e1f9147ec3fc/Slim/Error/Renderers/PlainTextErrorRenderer.php#L49

Pull request description:
Do not HTML entity encode in PlainTextErrorRenderer
The `PlainTextErrorRenderer` should not encode exception messages as that's not required for plain text in the same way that it is not required for the `JsonErrorRenderer`.

Closes #3298


Patch:
diff --git a/Slim/Error/Renderers/PlainTextErrorRenderer.php b/Slim/Error/Renderers/PlainTextErrorRenderer.php
index 3d80c74b..9788568d 100644
--- a/Slim/Error/Renderers/PlainTextErrorRenderer.php
+++ b/Slim/Error/Renderers/PlainTextErrorRenderer.php
@@ -46,7 +46,7 @@ class PlainTextErrorRenderer extends AbstractErrorRenderer
         /** @var int|string $code */
         $text .= sprintf("Code: %s\n", $code);
 
-        $text .= sprintf("Message: %s\n", htmlentities($exception->getMessage()));
+        $text .= sprintf("Message: %s\n", $exception->getMessage());
 
         $text .= sprintf("File: %s\n", $exception->getFile());
 


Test patch:
diff --git a/tests/Error/AbstractErrorRendererTest.php b/tests/Error/AbstractErrorRendererTest.php
index 13639dce..88cfa135 100644
--- a/tests/Error/AbstractErrorRendererTest.php
+++ b/tests/Error/AbstractErrorRendererTest.php
@@ -202,19 +202,24 @@ class AbstractErrorRendererTest extends TestCase
 
     public function testPlainTextErrorRendererFormatFragmentMethod()
     {
-        $exception = new Exception('Oops..', 500);
+        $message = 'Oops.. <br>';
+        $exception = new Exception($message, 500);
         $renderer = new PlainTextErrorRenderer();
         $reflectionRenderer = new ReflectionClass(PlainTextErrorRenderer::class);
 
         $method = $reflectionRenderer->getMethod('formatExceptionFragment');
         $method->setAccessible(true);
         $output = $method->invoke($renderer, $exception);
+        $this->assertIsString($output);
 
         $this->assertMatchesRegularExpression('/.*Type:*/', $output);
         $this->assertMatchesRegularExpression('/.*Code:*/', $output);
         $this->assertMatchesRegularExpression('/.*Message*/', $output);
         $this->assertMatchesRegularExpression('/.*File*/', $output);
         $this->assertMatchesRegularExpression('/.*Line*/', $output);
+
+        // ensure the renderer doesn't reformat the message
+        $this->assertMatchesRegularExpression("/.*$message/", $output);
     }
 
     public function testPlainTextErrorRendererDisplaysErrorDetails()