From a2f22e98e070d84211ebb55a306ef185c104c248 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 15:46:09 -0400 Subject: [PATCH 01/21] throw JSON errors, decode files, handle bad data in errorLog --- resources/lib/UnityHTTPD.php | 30 +++++++++++++++++++++++++----- resources/lib/UnityLDAP.php | 2 +- resources/lib/UnityWebhook.php | 2 +- resources/lib/utils.php | 8 +++++++- webroot/api/notices/index.php | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index 42e826e5..e34dfd39 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -58,9 +58,14 @@ public static function errorLog( $output["trace"] = explode("\n", (new \Exception())->getTraceAsString()); } if (!is_null($data)) { - $output["data"] = $data; + try { + \jsonEncode($data); + $output["data"] = $data; + } catch (\JsonException) { + $output["data"] = "data could not be JSON encoded"; + } } - error_log("$title: " . json_encode($output, JSON_UNESCAPED_SLASHES)); + error_log("$title: " . \jsonEncode($output)); } // recursive on $t->getPrevious() @@ -147,8 +152,11 @@ public static function getPostData(...$keys) } } - public static function getUploadedFileContents($filename, $do_delete_tmpfile_after_read = true) - { + public static function getUploadedFileContents( + $filename, + $do_delete_tmpfile_after_read = true, + $encoding = "UTF-8", + ) { try { $tmpfile_path = \arrayGet($_FILES, $filename, "tmp_name"); } catch (ArrayKeyException $e) { @@ -161,7 +169,19 @@ public static function getUploadedFileContents($filename, $do_delete_tmpfile_aft if ($do_delete_tmpfile_after_read) { unlink($tmpfile_path); } - return $contents; + $old_encoding = mb_detect_encoding($contents); + if ($old_encoding !== $encoding) { + $converted = mb_convert_encoding($contents, $encoding, $old_encoding); + if ($converted === false) { + self::badRequest( + "failed to convert file '$filename' from '$old_encoding' to '$encoding'" + ); + } else { + return $converted; + } + } else { + return $contents; + } } // in firefox, the user can disable alert/confirm/prompt after the 2nd or 3rd popup diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php index 7d1ae60d..74e30c08 100644 --- a/resources/lib/UnityLDAP.php +++ b/resources/lib/UnityLDAP.php @@ -332,7 +332,7 @@ public function getAllPIGroupOwnerAttributes($attributes) if (count($owners_not_found) > 0) { UnityHTTPD::errorLog( "warning", - "PI group owners not found: " . json_encode($owners_not_found) . "\n" + "PI group owners not found: " . \jsonEncode($owners_not_found) . "\n" ); } return $owner_attributes; diff --git a/resources/lib/UnityWebhook.php b/resources/lib/UnityWebhook.php index 3f479eb2..61c9dd1d 100644 --- a/resources/lib/UnityWebhook.php +++ b/resources/lib/UnityWebhook.php @@ -54,7 +54,7 @@ public function sendWebhook($template = null, $data = null) curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array('text' => $message))); + curl_setopt($ch, CURLOPT_POSTFIELDS, \jsonEncode(array('text' => $message))); $result = curl_exec($ch); curl_close($ch); return $result; diff --git a/resources/lib/utils.php b/resources/lib/utils.php index b5f5411a..14bd8f61 100644 --- a/resources/lib/utils.php +++ b/resources/lib/utils.php @@ -14,7 +14,7 @@ function arrayGet($array, ...$keys) throw new ArrayKeyException( "key not found: \$array" . // [1, 2, "foo"] => [1][2]["foo"] - implode("", array_map(fn($x) => json_encode([$x]), $keysTraversed)) + implode("", array_map(fn($x) => jsonEncode([$x]), $keysTraversed)) ); } $cursor = $cursor[$key]; @@ -53,3 +53,9 @@ function testValidSSHKey($key_str) return false; } } + +function jsonEncode($value, $flags = 0, $depth = 512) +{ + $flags |= JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES; + return json_encode($value, $flags, $depth); +} diff --git a/webroot/api/notices/index.php b/webroot/api/notices/index.php index 9c4eaca9..94076c8f 100644 --- a/webroot/api/notices/index.php +++ b/webroot/api/notices/index.php @@ -15,5 +15,5 @@ $jsonArray[] = $formattedNotice; } -$jsonOutput = json_encode($jsonArray, JSON_PRETTY_PRINT); +$jsonOutput = jsonEncode($jsonArray, JSON_PRETTY_PRINT); echo $jsonOutput; From 522bee786f7819c2bec6c0cbb15f81a9fd3d565b Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 15:52:21 -0400 Subject: [PATCH 02/21] document new convention, enforce conventions --- .pre-commit-config.yaml | 20 ++++++++++++++++++++ CONTRIBUTING.md | 3 ++- test/assert-no-assert.bash | 12 ++++++++++++ test/assert-no-json_encode.bash | 12 ++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/assert-no-assert.bash create mode 100644 test/assert-no-json_encode.bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index afb722f3..c5c9b013 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -70,3 +70,23 @@ repos: resources/lib/UnityHTTPD\.php$| workers/.*| )$ + - id: assert-no-assert + name: Assert no assert() + entry: ./test/assert-no-assert.bash + language: system + files: \.php$ + exclude: | + (?x)^( + resources/lib/utils\.php$| + workers/.*| + )$ + - id: assert-no-json_encode + name: Assert no json_encode() + entry: ./test/assert-no-json_encode.bash + language: system + files: \.php$ + exclude: | + (?x)^( + resources/lib/utils\.php$| + workers/.*| + )$ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea7c19ec..b27449f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,8 @@ * Comments should be used sparingly. * Empty lines should be used sparingly. * No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`. This will avoid the premature death of our automated testing processes. -* Instead of `assert`, use `\ensure`. This will enforce conditions even in production. +* No code should call `assert()`, instead `\ensure()`. This will enforce conditions even in production. +* No code should call `json_encode()`, instead `\jsonEncode()`. This will throw errors and escape slashes by default. This repository will automatically check PRs for linting compliance. diff --git a/test/assert-no-assert.bash b/test/assert-no-assert.bash new file mode 100644 index 00000000..35323a82 --- /dev/null +++ b/test/assert-no-assert.bash @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +# --color=never because magit git output log doesn't support it +if grep -H --color=never --line-number -P -P '\bassert\s*[\(;]' "$@"; then + echo "assert() is not allowed! use \ensure() instead." + exit 1 +fi diff --git a/test/assert-no-json_encode.bash b/test/assert-no-json_encode.bash new file mode 100644 index 00000000..841b1183 --- /dev/null +++ b/test/assert-no-json_encode.bash @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +# --color=never because magit git output log doesn't support it +if grep -H --color=never --line-number -P '\bjson_encode\b' "$@"; then + echo "json_encode() is not allowed! use \jsonEncode() instead." + exit 1 +fi From cee390c9ccacbead04f648f66b1829c5872a2bf2 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 15:55:37 -0400 Subject: [PATCH 03/21] update submodule --- resources/lib/phpopenldaper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/phpopenldaper b/resources/lib/phpopenldaper index eed8c05d..6eaf386b 160000 --- a/resources/lib/phpopenldaper +++ b/resources/lib/phpopenldaper @@ -1 +1 @@ -Subproject commit eed8c05d71b711d83f2ee3b5567c570a37212ed9 +Subproject commit 6eaf386b214506dd18f9ad6510579c3ba6d3c1a2 From bfd71239c2e28baec52be994040bcb129f34223b Mon Sep 17 00:00:00 2001 From: simonLeary42 <71396965+simonLeary42@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:57:00 -0400 Subject: [PATCH 04/21] Update test/assert-no-assert.bash Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/assert-no-assert.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/assert-no-assert.bash b/test/assert-no-assert.bash index 35323a82..71878ceb 100644 --- a/test/assert-no-assert.bash +++ b/test/assert-no-assert.bash @@ -6,7 +6,7 @@ if [[ $# -lt 1 ]]; then fi # --color=never because magit git output log doesn't support it -if grep -H --color=never --line-number -P -P '\bassert\s*[\(;]' "$@"; then +if grep -H --color=never --line-number -P '\bassert\s*[\(;]' "$@"; then echo "assert() is not allowed! use \ensure() instead." exit 1 fi From 09e57a181477ae36a1f6d42de509389df9de9b1f Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 15:58:33 -0400 Subject: [PATCH 05/21] fix permissions --- test/assert-no-assert.bash | 0 test/assert-no-json_encode.bash | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/assert-no-assert.bash mode change 100644 => 100755 test/assert-no-json_encode.bash diff --git a/test/assert-no-assert.bash b/test/assert-no-assert.bash old mode 100644 new mode 100755 diff --git a/test/assert-no-json_encode.bash b/test/assert-no-json_encode.bash old mode 100644 new mode 100755 From 7f5238780419f307512091484dfbec4196984aea Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 15:59:56 -0400 Subject: [PATCH 06/21] deindent --- resources/lib/UnityHTTPD.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index e34dfd39..346d5b00 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -170,18 +170,14 @@ public static function getUploadedFileContents( unlink($tmpfile_path); } $old_encoding = mb_detect_encoding($contents); - if ($old_encoding !== $encoding) { - $converted = mb_convert_encoding($contents, $encoding, $old_encoding); - if ($converted === false) { - self::badRequest( - "failed to convert file '$filename' from '$old_encoding' to '$encoding'" - ); - } else { - return $converted; - } - } else { + if ($old_encoding === $encoding) { return $contents; } + $converted = mb_convert_encoding($contents, $encoding, $old_encoding); + if ($converted !== false) { + return $converted; + } + self::badRequest("failed to convert file '$filename' from '$old_encoding' to '$encoding'"); } // in firefox, the user can disable alert/confirm/prompt after the 2nd or 3rd popup From 81e58b40864554452410a1694ee94c1522b736c4 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 16:00:28 -0400 Subject: [PATCH 07/21] exclude tests from assert convention --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c5c9b013..4578ff34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -79,6 +79,7 @@ repos: (?x)^( resources/lib/utils\.php$| workers/.*| + test/.*| )$ - id: assert-no-json_encode name: Assert no json_encode() From e7291495f12788f7f1a6af916ff81d989ee92c13 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 16:02:23 -0400 Subject: [PATCH 08/21] replace another json_encode --- resources/lib/UnityHTTPD.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index 346d5b00..63b26839 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -184,7 +184,7 @@ public static function getUploadedFileContents( // after I disable alerts, if I quit and reopen my browser, the alerts come back public static function alert(string $message) { - // json_encode escapes quotes - echo ""; + // jsonEncode escapes quotes + echo ""; } } From 3ee90630a60266ce00eceff81a9600dfe69f8b99 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 16:13:21 -0400 Subject: [PATCH 09/21] include JsonException message in error log --- resources/lib/UnityHTTPD.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index 63b26839..d2736644 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -61,8 +61,8 @@ public static function errorLog( try { \jsonEncode($data); $output["data"] = $data; - } catch (\JsonException) { - $output["data"] = "data could not be JSON encoded"; + } catch (\JsonException $e) { + $output["data"] = "data could not be JSON encoded: " . $e->getMessage(); } } error_log("$title: " . \jsonEncode($output)); From 866fa5da7e23c86a384c35cc765e89c2317f8e5c Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 17:56:21 -0400 Subject: [PATCH 10/21] enable strict mode --- resources/lib/UnityHTTPD.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index d2736644..c37f6f2d 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -169,7 +169,10 @@ public static function getUploadedFileContents( if ($do_delete_tmpfile_after_read) { unlink($tmpfile_path); } - $old_encoding = mb_detect_encoding($contents); + $old_encoding = mb_detect_encoding($contents, strict: true); + if ($old_encoding === false) { + self::badRequest("file '$filename' has invalid encoding"); + } if ($old_encoding === $encoding) { return $contents; } From 48382dc683ba3c0d2624ba1cfda97b11c9973bb8 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 17:57:52 -0400 Subject: [PATCH 11/21] flip conditional --- resources/lib/UnityHTTPD.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index c37f6f2d..d39e65cc 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -177,10 +177,12 @@ public static function getUploadedFileContents( return $contents; } $converted = mb_convert_encoding($contents, $encoding, $old_encoding); - if ($converted !== false) { - return $converted; + if ($converted === false) { + self::badRequest( + "failed to convert file '$filename' from '$old_encoding' to '$encoding'" + ); } - self::badRequest("failed to convert file '$filename' from '$old_encoding' to '$encoding'"); + return $converted; } // in firefox, the user can disable alert/confirm/prompt after the 2nd or 3rd popup From 9d2844b01b94555e8c97bce1aaec140f68586081 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 18:53:06 -0400 Subject: [PATCH 12/21] create strict versions of mb_check_encoding, mb_convert_encoding --- .pre-commit-config.yaml | 20 +++++++++++++++++ CONTRIBUTING.md | 2 ++ resources/autoload.php | 2 ++ resources/lib/UnityHTTPD.php | 16 ++------------ .../EncodingConversionException.php | 7 ++++++ .../exceptions/EncodingUnknownException.php | 7 ++++++ resources/lib/utils.php | 22 +++++++++++++++++++ test/assert-no-mb_convert_encoding.bash | 12 ++++++++++ test/assert-no-mb_detect_encoding.bash | 12 ++++++++++ test/phpunit-bootstrap.php | 2 ++ 10 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 resources/lib/exceptions/EncodingConversionException.php create mode 100644 resources/lib/exceptions/EncodingUnknownException.php create mode 100755 test/assert-no-mb_convert_encoding.bash create mode 100755 test/assert-no-mb_detect_encoding.bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4578ff34..dd3f3d2a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -91,3 +91,23 @@ repos: resources/lib/utils\.php$| workers/.*| )$ + - id: assert-no-mb_convert_encoding + name: Assert no mb_convert_encoding() + entry: ./test/assert-no-mb_convert_encoding.bash + language: system + files: \.php$ + exclude: | + (?x)^( + resources/lib/utils\.php$| + workers/.*| + )$ + - id: assert-no-mb_detect_encoding + name: Assert no mb_detect_encoding() + entry: ./test/assert-no-mb_detect_encoding.bash + language: system + files: \.php$ + exclude: | + (?x)^( + resources/lib/utils\.php$| + workers/.*| + )$ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b27449f7..fd8efc64 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,8 @@ * No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`. This will avoid the premature death of our automated testing processes. * No code should call `assert()`, instead `\ensure()`. This will enforce conditions even in production. * No code should call `json_encode()`, instead `\jsonEncode()`. This will throw errors and escape slashes by default. +* No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`. This will throw an exception rather than returning `false`. +* No code should call `mb_detect_encoding()`, instead `\mbConvertEncoding()`. This will enable strict mode and throw an exception rather than returning `false`. This repository will automatically check PRs for linting compliance. diff --git a/resources/autoload.php b/resources/autoload.php index a4326b05..6ec01691 100644 --- a/resources/autoload.php +++ b/resources/autoload.php @@ -29,6 +29,8 @@ require_once __DIR__ . "/lib/exceptions/SSOException.php"; require_once __DIR__ . "/lib/exceptions/ArrayKeyException.php"; require_once __DIR__ . "/lib/exceptions/EnsureException.php"; +require_once __DIR__ . "/lib/exceptions/EncodingUnknownException.php"; +require_once __DIR__ . "/lib/exceptions/EncodingConversionException.php"; require_once __DIR__ . "/config.php"; require __DIR__ . "/init.php"; diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php index d39e65cc..542ce41d 100644 --- a/resources/lib/UnityHTTPD.php +++ b/resources/lib/UnityHTTPD.php @@ -169,20 +169,8 @@ public static function getUploadedFileContents( if ($do_delete_tmpfile_after_read) { unlink($tmpfile_path); } - $old_encoding = mb_detect_encoding($contents, strict: true); - if ($old_encoding === false) { - self::badRequest("file '$filename' has invalid encoding"); - } - if ($old_encoding === $encoding) { - return $contents; - } - $converted = mb_convert_encoding($contents, $encoding, $old_encoding); - if ($converted === false) { - self::badRequest( - "failed to convert file '$filename' from '$old_encoding' to '$encoding'" - ); - } - return $converted; + $old_encoding = mbDetectEncoding($contents); + return mbConvertEncoding($contents, $encoding, $old_encoding); } // in firefox, the user can disable alert/confirm/prompt after the 2nd or 3rd popup diff --git a/resources/lib/exceptions/EncodingConversionException.php b/resources/lib/exceptions/EncodingConversionException.php new file mode 100644 index 00000000..ac316d89 --- /dev/null +++ b/resources/lib/exceptions/EncodingConversionException.php @@ -0,0 +1,7 @@ + $to_encoding, "from" => $from_encoding, "base64" => base64_encode($string)] + ) + ); + } + return $output; +} + +function mbDetectEncoding($string, $encodings = null, $_ = null) +{ + $output = mb_detect_encoding($string, $encodings, strict: true); + if ($output === false) { + throw new EncodingUnknownException(base64_encode($string)); + } + return $output; +} diff --git a/test/assert-no-mb_convert_encoding.bash b/test/assert-no-mb_convert_encoding.bash new file mode 100755 index 00000000..c7c8c6bb --- /dev/null +++ b/test/assert-no-mb_convert_encoding.bash @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +# --color=never because magit git output log doesn't support it +if grep -H --color=never --line-number -P '\bmb_convert_encoding\b' "$@"; then + echo "mb_convert_encoding() is not allowed! use \mbConvertEncoding() instead." + exit 1 +fi diff --git a/test/assert-no-mb_detect_encoding.bash b/test/assert-no-mb_detect_encoding.bash new file mode 100755 index 00000000..092b71a0 --- /dev/null +++ b/test/assert-no-mb_detect_encoding.bash @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +# --color=never because magit git output log doesn't support it +if grep -H --color=never --line-number -P '\bmb_detect_encoding\b' "$@"; then + echo "mb_detect_encoding() is not allowed! use \mbDetectEncoding() instead." + exit 1 +fi diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 1bd49bc3..1fed78e1 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -20,6 +20,8 @@ require_once __DIR__ . "/../resources/lib/exceptions/SSOException.php"; require_once __DIR__ . "/../resources/lib/exceptions/ArrayKeyException.php"; require_once __DIR__ . "/../resources/lib/exceptions/EnsureException.php"; +require_once __DIR__ . "/../resources/lib/exceptions/EncodingUnknownException.php"; +require_once __DIR__ . "/../resources/lib/exceptions/EncodingConversionException.php"; $_SERVER["HTTP_HOST"] = "phpunit"; // used for config override require_once __DIR__ . "/../resources/config.php"; From 5d59b55d255d660e29a32e1366bc1c6458794831 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 18:58:07 -0400 Subject: [PATCH 13/21] combine scripts --- .pre-commit-config.yaml | 49 +++---------------- ...-exit.bash => assert-UnityHTTPD-used.bash} | 0 test/assert-no-assert.bash | 12 ----- test/assert-no-json_encode.bash | 12 ----- test/assert-no-mb_convert_encoding.bash | 12 ----- test/assert-no-mb_detect_encoding.bash | 12 ----- test/assert-utils-used.bash | 24 +++++++++ 7 files changed, 31 insertions(+), 90 deletions(-) rename test/{assert-no-die-exit.bash => assert-UnityHTTPD-used.bash} (100%) delete mode 100755 test/assert-no-assert.bash delete mode 100755 test/assert-no-json_encode.bash delete mode 100755 test/assert-no-mb_convert_encoding.bash delete mode 100755 test/assert-no-mb_detect_encoding.bash create mode 100755 test/assert-utils-used.bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd3f3d2a..42770814 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -60,9 +60,9 @@ repos: language: system files: \.php$ args: [-l] - - id: assert-no-die-exit - name: Assert no die()/exit() - entry: ./test/assert-no-die-exit.bash + - id: assert-UnityHTTPD-used + name: Assert UnityHTTPD functions are used + entry: ./test/assert-UnityHTTPD-used.bash language: system files: \.php$ exclude: | @@ -70,44 +70,9 @@ repos: resources/lib/UnityHTTPD\.php$| workers/.*| )$ - - id: assert-no-assert - name: Assert no assert() - entry: ./test/assert-no-assert.bash + - id: assert-utils-used + name: Assert utils are used + entry: ./test/assert-utils-used.bash language: system files: \.php$ - exclude: | - (?x)^( - resources/lib/utils\.php$| - workers/.*| - test/.*| - )$ - - id: assert-no-json_encode - name: Assert no json_encode() - entry: ./test/assert-no-json_encode.bash - language: system - files: \.php$ - exclude: | - (?x)^( - resources/lib/utils\.php$| - workers/.*| - )$ - - id: assert-no-mb_convert_encoding - name: Assert no mb_convert_encoding() - entry: ./test/assert-no-mb_convert_encoding.bash - language: system - files: \.php$ - exclude: | - (?x)^( - resources/lib/utils\.php$| - workers/.*| - )$ - - id: assert-no-mb_detect_encoding - name: Assert no mb_detect_encoding() - entry: ./test/assert-no-mb_detect_encoding.bash - language: system - files: \.php$ - exclude: | - (?x)^( - resources/lib/utils\.php$| - workers/.*| - )$ + exclude: resources/lib/utils.php diff --git a/test/assert-no-die-exit.bash b/test/assert-UnityHTTPD-used.bash similarity index 100% rename from test/assert-no-die-exit.bash rename to test/assert-UnityHTTPD-used.bash diff --git a/test/assert-no-assert.bash b/test/assert-no-assert.bash deleted file mode 100755 index 71878ceb..00000000 --- a/test/assert-no-assert.bash +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -euo pipefail -if [[ $# -lt 1 ]]; then - echo "at least one argument required" - exit 1 -fi - -# --color=never because magit git output log doesn't support it -if grep -H --color=never --line-number -P '\bassert\s*[\(;]' "$@"; then - echo "assert() is not allowed! use \ensure() instead." - exit 1 -fi diff --git a/test/assert-no-json_encode.bash b/test/assert-no-json_encode.bash deleted file mode 100755 index 841b1183..00000000 --- a/test/assert-no-json_encode.bash +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -euo pipefail -if [[ $# -lt 1 ]]; then - echo "at least one argument required" - exit 1 -fi - -# --color=never because magit git output log doesn't support it -if grep -H --color=never --line-number -P '\bjson_encode\b' "$@"; then - echo "json_encode() is not allowed! use \jsonEncode() instead." - exit 1 -fi diff --git a/test/assert-no-mb_convert_encoding.bash b/test/assert-no-mb_convert_encoding.bash deleted file mode 100755 index c7c8c6bb..00000000 --- a/test/assert-no-mb_convert_encoding.bash +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -euo pipefail -if [[ $# -lt 1 ]]; then - echo "at least one argument required" - exit 1 -fi - -# --color=never because magit git output log doesn't support it -if grep -H --color=never --line-number -P '\bmb_convert_encoding\b' "$@"; then - echo "mb_convert_encoding() is not allowed! use \mbConvertEncoding() instead." - exit 1 -fi diff --git a/test/assert-no-mb_detect_encoding.bash b/test/assert-no-mb_detect_encoding.bash deleted file mode 100755 index 092b71a0..00000000 --- a/test/assert-no-mb_detect_encoding.bash +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -euo pipefail -if [[ $# -lt 1 ]]; then - echo "at least one argument required" - exit 1 -fi - -# --color=never because magit git output log doesn't support it -if grep -H --color=never --line-number -P '\bmb_detect_encoding\b' "$@"; then - echo "mb_detect_encoding() is not allowed! use \mbDetectEncoding() instead." - exit 1 -fi diff --git a/test/assert-utils-used.bash b/test/assert-utils-used.bash new file mode 100755 index 00000000..3cec42a1 --- /dev/null +++ b/test/assert-utils-used.bash @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +declare -A utils=( + ["assert"]="ensure" + ["json_encode"]="jsonEncode" + ["mb_detect_encoding"]="mbDetectEncoding" + ["mb_convert_encoding"]="mbConvertEncoding" +) + +rc=0 +for replaced in "${!utils[@]}"; do + replacement="${utils[$replaced]}" + # --color=never because magit git output log doesn't support it + if grep -H --color=never --line-number -P '\b'"$replaced"'\s*[\(;]' "$@"; then + echo "$replaced() is not allowed! use $replacement() instead." + rc=1 + fi +done +exit "$rc" From ec355eab84516576707fdbaec14197cce2131362 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 19:16:14 -0400 Subject: [PATCH 14/21] catch new encoding exceptions --- webroot/panel/account.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/webroot/panel/account.php b/webroot/panel/account.php index f97a84b6..fa2c5d6f 100644 --- a/webroot/panel/account.php +++ b/webroot/panel/account.php @@ -3,6 +3,8 @@ require_once __DIR__ . "/../../resources/autoload.php"; use UnityWebPortal\lib\UnityHTTPD; +use UnityWebPortal\lib\exceptions\EncodingUnknownException; +use UnityWebPortal\lib\exceptions\EncodingConversionException; $hasGroups = count($USER->getPIGroupGIDs()) > 0; @@ -15,7 +17,11 @@ array_push($keys, UnityHTTPD::getPostData("key")); break; case "import": - $key = UnityHTTPD::getUploadedFileContents("keyfile"); + try { + $key = UnityHTTPD::getUploadedFileContents("keyfile"); + } catch (EncodingUnknownException | EncodingConversionException $e) { + UnityHTTPD::badRequest("uploaded key has bad encoding", error: $e); + } array_push($keys, $key); break; case "generate": From ab9ea5498164b9a29ad209ecd2a8f98ba6d0c232 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 19:18:29 -0400 Subject: [PATCH 15/21] import --- resources/lib/utils.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/lib/utils.php b/resources/lib/utils.php index 56bcb0aa..1c9a8d53 100644 --- a/resources/lib/utils.php +++ b/resources/lib/utils.php @@ -2,6 +2,8 @@ use UnityWebPortal\lib\exceptions\ArrayKeyException; use UnityWebPortal\lib\exceptions\EnsureException; +use UnityWebPortal\lib\exceptions\EncodingUnknownException; +use UnityWebPortal\lib\exceptions\EncodingConversionException; use phpseclib3\Crypt\PublicKeyLoader; function arrayGet($array, ...$keys) From 3d1c334043501f759e3400ab4f38739d63750870 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 19:20:18 -0400 Subject: [PATCH 16/21] tests conform to standards --- test/functional/NewUserTest.php | 14 +++++++------- test/phpunit-bootstrap.php | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/functional/NewUserTest.php b/test/functional/NewUserTest.php index 268d5190..e9254ec1 100644 --- a/test/functional/NewUserTest.php +++ b/test/functional/NewUserTest.php @@ -108,14 +108,14 @@ private function ensureUserDoesNotExist() $org = $USER->getOrgGroup(); if ($org->exists() and $org->inOrg($USER)) { $org->removeUser($USER); - assert(!$org->inOrg($USER)); + ensure(!$org->inOrg($USER)); } $LDAP->getUserEntry($USER->uid)->delete(); - assert(!$USER->exists()); + ensure(!$USER->exists()); } if ($USER->getGroupEntry()->exists()) { $USER->getGroupEntry()->delete(); - assert(!$USER->getGroupEntry()->exists()); + ensure(!$USER->getGroupEntry()->exists()); } $all_users_group = $LDAP->getUserGroup(); $all_member_uids = $all_users_group->getAttribute("memberuid"); @@ -127,7 +127,7 @@ private function ensureUserDoesNotExist() array_values(array_diff($all_member_uids, [$USER->uid])) ); $all_users_group->write(); - assert(!in_array($USER->uid, $all_users_group->getAttribute("memberuid"))); + ensure(!in_array($USER->uid, $all_users_group->getAttribute("memberuid"))); } $REDIS->removeCacheArray("sorted_users", "", $USER->uid); } @@ -138,7 +138,7 @@ private function ensureOrgGroupDoesNotExist() $org_group = $LDAP->getOrgGroupEntry($SSO["org"]); if ($org_group->exists()) { $org_group->delete(); - assert(!$org_group->exists()); + ensure(!$org_group->exists()); } $REDIS->removeCacheArray("sorted_orgs", "", $SSO["org"]); } @@ -148,7 +148,7 @@ private function ensureUserNotInPIGroup(UnityGroup $pi_group) global $USER, $REDIS; if ($pi_group->memberExists($USER)) { $pi_group->removeUser($USER); - assert(!$pi_group->memberExists($USER)); + ensure(!$pi_group->memberExists($USER)); } $REDIS->removeCacheArray($pi_group->gid, "members", $USER->uid); } @@ -159,7 +159,7 @@ private function ensurePIGroupDoesNotExist() $gid = $USER->getPIGroup()->gid; if ($USER->getPIGroup()->exists()) { $LDAP->getPIGroupEntry($gid)->delete(); - assert(!$USER->getPIGroup()->exists()); + ensure(!$USER->getPIGroup()->exists()); } $REDIS->removeCacheArray("sorted_groups", "", $gid); } diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 1fed78e1..fe80589c 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -50,7 +50,7 @@ '{"key": "value"}', 'SGVsbG8sIFdvcmxkIQ==', "Hello\x00World", - mb_convert_encoding("Hello, World!", "UTF-16") + mbConvertEncoding("Hello, World!", "UTF-16", "UTF-8") ]; function arraysAreEqualUnOrdered(array $a, array $b): bool @@ -81,7 +81,7 @@ function switchUser( $_SERVER["givenName"] = $given_name; $_SERVER["sn"] = $sn; include __DIR__ . "/../resources/autoload.php"; - assert(!is_null($USER)); + ensure(!is_null($USER)); } function http_post(string $phpfile, array $post_data): void @@ -104,7 +104,7 @@ function http_post(string $phpfile, array $post_data): void $_SERVER = $_PREVIOUS_SERVER; } // https://en.wikipedia.org/wiki/Post/Redirect/Get - assert($post_did_redirect_or_die, "post did not redirect or die!"); + ensure($post_did_redirect_or_die, "post did not redirect or die!"); } function http_get(string $phpfile, array $get_data = array()): void From 868940ec9fb5dea3d8fd75fd987f975cdd0f787e Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 29 Sep 2025 19:24:54 -0400 Subject: [PATCH 17/21] compatibility --- resources/lib/utils.php | 2 +- test/phpunit-bootstrap.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/utils.php b/resources/lib/utils.php index 1c9a8d53..c0ae48ab 100644 --- a/resources/lib/utils.php +++ b/resources/lib/utils.php @@ -62,7 +62,7 @@ function jsonEncode($value, $flags = 0, $depth = 512) return json_encode($value, $flags, $depth); } -function mbConvertEncoding($string, $to_encoding, $from_encoding) +function mbConvertEncoding($string, $to_encoding, $from_encoding = null) { $output = mb_convert_encoding($string, $to_encoding, $from_encoding); if ($output === false) { diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index fe80589c..34b370d9 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -50,7 +50,7 @@ '{"key": "value"}', 'SGVsbG8sIFdvcmxkIQ==', "Hello\x00World", - mbConvertEncoding("Hello, World!", "UTF-16", "UTF-8") + mbConvertEncoding("Hello, World!", "UTF-16") ]; function arraysAreEqualUnOrdered(array $a, array $b): bool From 0f6e1f27f28f82c8425211d9e0776958115a9fbe Mon Sep 17 00:00:00 2001 From: simonLeary42 <71396965+simonLeary42@users.noreply.github.com> Date: Tue, 30 Sep 2025 09:01:14 -0400 Subject: [PATCH 18/21] Update CONTRIBUTING.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd8efc64..9ab70844 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ * No code should call `assert()`, instead `\ensure()`. This will enforce conditions even in production. * No code should call `json_encode()`, instead `\jsonEncode()`. This will throw errors and escape slashes by default. * No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`. This will throw an exception rather than returning `false`. -* No code should call `mb_detect_encoding()`, instead `\mbConvertEncoding()`. This will enable strict mode and throw an exception rather than returning `false`. +* No code should call `mb_detect_encoding()`, instead `\mbDetectEncoding()`. This will enable strict mode and throw an exception rather than returning `false`. This repository will automatically check PRs for linting compliance. From b4e8e9036fdb3d3ef885bc03d738d1965f6dbfe0 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Tue, 30 Sep 2025 09:19:44 -0400 Subject: [PATCH 19/21] add new convention documentation --- .pre-commit-config.yaml | 8 +++++++- CONTRIBUTING.md | 19 ++++++++++++++----- test/assert-exceptions-used.bash | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100755 test/assert-exceptions-used.bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42770814..abc365e7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -75,4 +75,10 @@ repos: entry: ./test/assert-utils-used.bash language: system files: \.php$ - exclude: resources/lib/utils.php + exclude: ^resources/lib/utils\.php$ + - id: assert-exceptions-used + name: Assert exceptions are used + entry: ./test/assert-exceptions-used.bash + language: system + files: ^resources/.*\.php$ + exclude: ^resources/lib/UnityHTTPD\.php$ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9ab70844..6f437e3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,11 +7,20 @@ * The maximum line length for any PHP file is 100 characters, instead of PSR-12's 120 characters. * Comments should be used sparingly. * Empty lines should be used sparingly. -* No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`. This will avoid the premature death of our automated testing processes. -* No code should call `assert()`, instead `\ensure()`. This will enforce conditions even in production. -* No code should call `json_encode()`, instead `\jsonEncode()`. This will throw errors and escape slashes by default. -* No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`. This will throw an exception rather than returning `false`. -* No code should call `mb_detect_encoding()`, instead `\mbDetectEncoding()`. This will enable strict mode and throw an exception rather than returning `false`. +* No code should fail quietly, instead exceptions should be thrown. + PHP builtin functions that fail quietly (ex: `json_encode`) should be replaced with a wrapper in `resources/utils.php`. +* No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`. + This will avoid the premature death of our automated testing processes. +* No code should call `assert()`, instead `\ensure()`. + This will enforce conditions even in production. +* No code should call `json_encode()`, instead `\jsonEncode()`. + This will throw errors and escape slashes by default. +* No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`. + This will throw an exception rather than returning `false`. +* No code should call `mb_detect_encoding()`, instead `\mbDetectEncoding()`. + This will enable strict mode and throw an exception rather than returning `false`. +* `UnityHTTPD`'s user-facing error functionality (ex: `badRequest`) should only be called from `webroot/**/*.php`. + `resources/**/*.php` should throw exceptions instead. This repository will automatically check PRs for linting compliance. diff --git a/test/assert-exceptions-used.bash b/test/assert-exceptions-used.bash new file mode 100755 index 00000000..bc911c37 --- /dev/null +++ b/test/assert-exceptions-used.bash @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail +if [[ $# -lt 1 ]]; then + echo "at least one argument required" + exit 1 +fi + +err_funcs=(badRequest forbidden internalServerError) + +rc=0 +for err_func in "${err_funcs[@]}"; do + # --color=never because magit git output log doesn't support it + if grep -H --color=never --line-number -P '\b'"$err_func"'\s*[\(;]' "$@"; then + echo "$err_func() is not allowed! use an exceptioninstead." + rc=1 + fi +done +exit "$rc" From 7699c791c0ed285091dfc1eacc20d1fd17ac3105 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Tue, 30 Sep 2025 10:09:51 -0400 Subject: [PATCH 20/21] improve convention scripts --- .pre-commit-config.yaml | 6 +++--- test/assert-UnityHTTPD-used.bash | 34 +++++++++++++------------------- test/assert-exceptions-used.bash | 20 +++++++++++-------- test/assert-utils-used.bash | 15 +++++++++----- 4 files changed, 39 insertions(+), 36 deletions(-) mode change 100755 => 100644 test/assert-UnityHTTPD-used.bash mode change 100755 => 100644 test/assert-exceptions-used.bash mode change 100755 => 100644 test/assert-utils-used.bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index abc365e7..15783fec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: args: [-l] - id: assert-UnityHTTPD-used name: Assert UnityHTTPD functions are used - entry: ./test/assert-UnityHTTPD-used.bash + entry: bash ./test/assert-UnityHTTPD-used.bash language: system files: \.php$ exclude: | @@ -72,13 +72,13 @@ repos: )$ - id: assert-utils-used name: Assert utils are used - entry: ./test/assert-utils-used.bash + entry: bash ./test/assert-utils-used.bash language: system files: \.php$ exclude: ^resources/lib/utils\.php$ - id: assert-exceptions-used name: Assert exceptions are used - entry: ./test/assert-exceptions-used.bash + entry: bash ./test/assert-exceptions-used.bash language: system files: ^resources/.*\.php$ exclude: ^resources/lib/UnityHTTPD\.php$ diff --git a/test/assert-UnityHTTPD-used.bash b/test/assert-UnityHTTPD-used.bash old mode 100755 new mode 100644 index 638c2e6b..a5b92dee --- a/test/assert-UnityHTTPD-used.bash +++ b/test/assert-UnityHTTPD-used.bash @@ -1,28 +1,22 @@ -#!/bin/bash set -euo pipefail +trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR if [[ $# -lt 1 ]]; then echo "at least one argument required" exit 1 fi +funcs=(die exit) rc=0 - -# --color=never because magit git output log doesn't support it -die_occurrences="$( - grep -H --color=never --line-number -P '\bdie\s*[\(;]' "$@" | grep -v -P 'UnityHTTPD::die' -)" || true -if [ -n "$die_occurrences" ]; then - echo "die is not allowed! use UnityHTTPD::die() instead." - echo "$die_occurrences" - rc=1 -fi - -# --color=never because magit git output log doesn't support it -exit_occurrences="$(grep -H --color=never --line-number -P '\bexit\s*[\(;]' "$@")" || true -if [ -n "$exit_occurrences" ]; then - echo "exit is not allowed! use UnityHTTPD::die() instead." - echo "$exit_occurrences" - rc=1 -fi - +for func in "${funcs[@]}"; do + # --color=never because magit git output log doesn't support it + grep_rc=0; grep -H --color=never --line-number -P '\b'"$func"'\s*[\(;]' "$@" | grep -v -E 'UnityHTTPD::'"$func" || grep_rc=$? + case "$grep_rc" in + 0) + echo "$func() are not allowed! use UnityHTTPD::die() instead."; rc=1 ;; + 1) + : ;; # code is good, do nothing + *) + echo "grep failed!"; rc=1 ;; + esac +done exit "$rc" diff --git a/test/assert-exceptions-used.bash b/test/assert-exceptions-used.bash old mode 100755 new mode 100644 index bc911c37..90177c74 --- a/test/assert-exceptions-used.bash +++ b/test/assert-exceptions-used.bash @@ -1,18 +1,22 @@ -#!/usr/bin/env bash set -euo pipefail +trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR if [[ $# -lt 1 ]]; then echo "at least one argument required" exit 1 fi -err_funcs=(badRequest forbidden internalServerError) - +funcs=(badRequest forbidden internalServerError) rc=0 -for err_func in "${err_funcs[@]}"; do +for func in "${funcs[@]}"; do # --color=never because magit git output log doesn't support it - if grep -H --color=never --line-number -P '\b'"$err_func"'\s*[\(;]' "$@"; then - echo "$err_func() is not allowed! use an exceptioninstead." - rc=1 - fi + grep_rc=0; grep -H --color=never --line-number -P '\b'"$func"'\s*[\(;]' "$@" || grep_rc=$? + case "$grep_rc" in + 0) + echo "$func() is not allowed! use an exception instead."; rc=1 ;; + 1) + : ;; # code is good, do nothing + *) + echo "grep failed!"; rc=1 ;; + esac done exit "$rc" diff --git a/test/assert-utils-used.bash b/test/assert-utils-used.bash old mode 100755 new mode 100644 index 3cec42a1..51e95e31 --- a/test/assert-utils-used.bash +++ b/test/assert-utils-used.bash @@ -1,5 +1,5 @@ -#!/usr/bin/env bash set -euo pipefail +trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR if [[ $# -lt 1 ]]; then echo "at least one argument required" exit 1 @@ -16,9 +16,14 @@ rc=0 for replaced in "${!utils[@]}"; do replacement="${utils[$replaced]}" # --color=never because magit git output log doesn't support it - if grep -H --color=never --line-number -P '\b'"$replaced"'\s*[\(;]' "$@"; then - echo "$replaced() is not allowed! use $replacement() instead." - rc=1 - fi + grep_rc=0; grep -H --color=never --line-number -P '\b'"$replaced"'\s*[\(;]' "$@" || grep_rc=$? + case "$grep_rc" in + 0) + echo "$replaced() are not allowed! use $replacement() instead."; rc=1 ;; + 1) + : ;; # code is good, do nothing + *) + echo "grep failed!"; rc=1 ;; + esac done exit "$rc" From c86bc6978f8919b4bf9a6fb05842059a52ac121c Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Tue, 30 Sep 2025 10:19:27 -0400 Subject: [PATCH 21/21] regex --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 15783fec..97d65767 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -67,7 +67,7 @@ repos: files: \.php$ exclude: | (?x)^( - resources/lib/UnityHTTPD\.php$| + resources/lib/UnityHTTPD\.php| workers/.*| )$ - id: assert-utils-used