From 8e78f279fa91e525ec98e983b6aca951f9cc5a16 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Tue, 7 Nov 2023 13:09:49 +0000 Subject: [PATCH] [1.x] Fixes message and options html output not escaped (#16) * Fixes message and options html output not escaped * Fixes style --- src/Printers/CliPrinter.php | 5 ++- tests/Unit/CliPrinterTest.php | 77 ++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/Printers/CliPrinter.php b/src/Printers/CliPrinter.php index e3efed9..b89a9f6 100644 --- a/src/Printers/CliPrinter.php +++ b/src/Printers/CliPrinter.php @@ -133,6 +133,8 @@ protected function messageHtml(string $message): string return 'No message.'; } + $message = htmlspecialchars($message); + return "$message"; } @@ -204,7 +206,8 @@ public function optionsHtml(MessageLogged $messageLogged): string return collect($options)->merge( $messageLogged->context() // @phpstan-ignore-line )->reject(fn (mixed $value, string|int $key) => is_int($key) && is_null($value)) - ->map(fn (mixed $value) => is_string($value) ? e($value) : var_export($value, true)) + ->map(fn (mixed $value) => is_string($value) ? $value : var_export($value, true)) + ->map(fn (string $value) => htmlspecialchars($value)) ->map(fn (string $value, string|int $key) => is_string($key) ? "$key: $value" : $value) ->map(fn (string $value) => "$value") ->implode(' • '); diff --git a/tests/Unit/CliPrinterTest.php b/tests/Unit/CliPrinterTest.php index b7add12..2b81568 100644 --- a/tests/Unit/CliPrinterTest.php +++ b/tests/Unit/CliPrinterTest.php @@ -114,13 +114,42 @@ ); }); +test('escaping message', function () { + $output = output([ + 'message' => '
escaping message
', + 'level_name' => 'info', + 'datetime' => '2021-01-01 00:00:00', + 'context' => [ + '__pail' => [ + 'origin' => [ + 'type' => 'http', + 'method' => 'GET', + 'path' => '/logs', + 'auth_id' => null, + 'auth_email' => null, + ], + ], + ], + ], true); + + expect($output)->toBe(<<<'EOF' + ┌ 2024-01-01 03:04:05 INFO ─────────────────────── + │
escaping message
+ │ 1. app/MyClass.php:12 + │ 2. app/MyClass.php:34 + └──────────────────── GET: /logs • Auth ID: guest + + EOF + ); +}); + test('escaping html options', function () { $output = output([ 'message' => 'Context that contains html', 'level_name' => 'info', 'datetime' => '2021-01-01 00:00:00', 'context' => [ - 'html' => '
', + 'html' => '
escaping html options
', '__pail' => [ 'origin' => [ 'type' => 'http', @@ -131,12 +160,50 @@ ], ], ], - ]); + ], true); + + expect($output)->toBe(<<<'EOF' + ┌ 2024-01-01 03:04:05 INFO ─────────────────────── + │ Context that contains html + │ 1. app/MyClass.php:12 + │ 2. app/MyClass.php:34 + └ GET: /logs • Auth ID: guest • html:
escaping html options
+ + EOF + ); +}); + +test('escaping html arrayable options', function () { + $output = output([ + 'message' => 'Context that contains html', + 'level_name' => 'info', + 'datetime' => '2021-01-01 00:00:00', + 'context' => [ + 'html' => [ + 'first' => 'first', + 'second' => [ + 'a' => 'a', + 'b' => 'b', + ], + ], + '__pail' => [ + 'origin' => [ + 'type' => 'http', + 'method' => 'GET', + 'path' => '/logs', + 'auth_id' => null, + 'auth_email' => null, + ], + ], + ], + ], true); expect($output)->toBe(<<<'EOF' - ┌ 03:04:05 INFO ─────────────────────────────────┐ - │ Context that contains html │ - └ GET: /logs • Auth ID: guest • html:
┘ + ┌ 2024-01-01 03:04:05 INFO ─────────────────────── + │ Context that contains html + │ 1. app/MyClass.php:12 + │ 2. app/MyClass.php:34 + └ GET: /logs • Auth ID: guest • html: array ( 'first' => 'first', 'second' => array ( 'a' => 'a', 'b' => 'b', ), ) EOF );