From 4303e488b8f11cd52d9fbea4c8cc4d0a644a6ef7 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Sun, 14 Jan 2024 11:32:15 +0100 Subject: [PATCH] chg: [internal] PHP 7.4 is required, so we can remove hacks for older versions --- app/Lib/Tools/JsonTool.php | 29 +++++++++++++------------ app/Lib/Tools/ProcessTool.php | 15 +++++-------- app/Model/AccessLog.php | 34 +----------------------------- app/Test/JSONConverterToolTest.php | 8 ++----- 4 files changed, 24 insertions(+), 62 deletions(-) diff --git a/app/Lib/Tools/JsonTool.php b/app/Lib/Tools/JsonTool.php index 0760dcade..5958190c7 100644 --- a/app/Lib/Tools/JsonTool.php +++ b/app/Lib/Tools/JsonTool.php @@ -9,10 +9,7 @@ class JsonTool */ public static function encode($value, $prettyPrint = false) { - $flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; - if (defined('JSON_THROW_ON_ERROR')) { - $flags |= JSON_THROW_ON_ERROR; // Throw exception on error if supported - } + $flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR; if ($prettyPrint) { $flags |= JSON_PRETTY_PRINT; } @@ -34,16 +31,8 @@ class JsonTool } catch (SimdJsonException $e) { throw new JsonException($e->getMessage(), $e->getCode(), $e); } - } elseif (defined('JSON_THROW_ON_ERROR')) { - // JSON_THROW_ON_ERROR is supported since PHP 7.3 - return json_decode($value, true, 512, JSON_THROW_ON_ERROR); - } else { - $decoded = json_decode($value, true); - if ($decoded === null) { - throw new UnexpectedValueException('Could not parse JSON: ' . json_last_error_msg(), json_last_error()); - } - return $decoded; } + return json_decode($value, true, 512, JSON_THROW_ON_ERROR); } /** @@ -78,4 +67,18 @@ class JsonTool return false; } } + + /** + * JSON supports just unicode strings. This helper method converts non unicode chars to Unicode Replacement Character U+FFFD (UTF-8) + * @param string $string + * @return string + */ + public static function escapeNonUnicode($string) + { + if (json_encode($string, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS) !== false) { + return $string; // string is valid unicode + } + + return htmlspecialchars_decode(htmlspecialchars($string, ENT_SUBSTITUTE, 'UTF-8')); + } } diff --git a/app/Lib/Tools/ProcessTool.php b/app/Lib/Tools/ProcessTool.php index 26d48cc47..b0003938b 100644 --- a/app/Lib/Tools/ProcessTool.php +++ b/app/Lib/Tools/ProcessTool.php @@ -8,14 +8,14 @@ class ProcessException extends Exception private $stdout; /** - * @param string|array $command + * @param array $command * @param int $returnCode * @param string $stderr * @param string $stdout */ - public function __construct($command, $returnCode, $stderr, $stdout) + public function __construct(array $command, $returnCode, $stderr, $stdout) { - $commandForException = is_array($command) ? implode(' ', $command) : $command; + $commandForException = implode(' ', $command); $message = "Command '$commandForException' finished with error code $returnCode.\nSTDERR: '$stderr'\nSTDOUT: '$stdout'"; $this->stderr = $stderr; $this->stdout = $stdout; @@ -56,11 +56,6 @@ class ProcessTool self::logMessage('Running command ' . implode(' ', $command)); } - // PHP older than 7.4 do not support proc_open with array, so we need to convert values to string manually - if (PHP_VERSION_ID < 70400) { - $command = array_map('escapeshellarg', $command); - $command = implode(' ', $command); - } $process = proc_open($command, $descriptorSpec, $pipes, $cwd); if (!$process) { $commandForException = self::commandFormat($command); @@ -136,8 +131,8 @@ class ProcessTool * @param array|string $command * @return string */ - private static function commandFormat($command) + private static function commandFormat(array $command) { - return is_array($command) ? implode(' ', $command) : $command; + return implode(' ', $command); } } diff --git a/app/Model/AccessLog.php b/app/Model/AccessLog.php index f1f70b453..55a7ae2f9 100644 --- a/app/Model/AccessLog.php +++ b/app/Model/AccessLog.php @@ -202,7 +202,7 @@ class AccessLog extends AppModel if ($includeSqlQueries && !empty($sqlLog['log'])) { foreach ($sqlLog['log'] as &$log) { - $log['query'] = $this->escapeNonUnicode($log['query']); + $log['query'] = JsonTool::escapeNonUnicode($log['query']); unset($log['affected']); // affected is the same as numRows unset($log['params']); // no need to save for your use case } @@ -310,36 +310,4 @@ class AccessLog extends AppModel } return $data; } - - /** - * @param $string - * @return string - */ - private function escapeNonUnicode($string) - { - if (json_encode($string, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS) !== false) { - return $string; // string is valid unicode - } - - if (function_exists('mb_str_split')) { - $result = mb_str_split($string); - } else { - $result = []; - $length = mb_strlen($string); - for ($i = 0; $i < $length; $i++) { - $result[] = mb_substr($string, $i, 1); - } - } - - $string = ''; - foreach ($result as $char) { - if (strlen($char) === 1 && !preg_match('/[[:print:]]/', $char)) { - $string .= '\x' . bin2hex($char); - } else { - $string .= $char; - } - } - - return $string; - } } \ No newline at end of file diff --git a/app/Test/JSONConverterToolTest.php b/app/Test/JSONConverterToolTest.php index 5e7758148..adc47fb4a 100644 --- a/app/Test/JSONConverterToolTest.php +++ b/app/Test/JSONConverterToolTest.php @@ -1,4 +1,5 @@ assertEquals($jsonNormalWithoutSpaces, $jsonStreamWithoutSpaces); - if (defined('JSON_THROW_ON_ERROR')) { - json_decode($json, true, 512, JSON_THROW_ON_ERROR); - $this->assertTrue(true); - } else { - $this->assertNotNull(json_decode($json)); - } + $this->assertTrue(JsonTool::isValid($json)); } }