From d5cff00d1042c557e034ae9c80aac1b2f35076d9 Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Sun, 14 Nov 2021 00:58:36 +0900 Subject: [PATCH 1/6] Fix missing setlocale with php 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When php version = 8, basename('§') does not bug even if LC_ALL is non-UTF-8 locale. This cause OC_Util::isSetLocaleWorking() to skip setlocale("C.UTF-8"). Fix it by using escapeshellcmd instead of basename. Signed-off-by: Naoto Kobayashi --- lib/private/legacy/OC_Util.php | 4 ++-- tests/lib/UtilTest.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 87964f98374ac..9978815e486cd 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -1280,14 +1280,14 @@ public function isHtaccessWorking(\OCP\IConfig $config) { * @return bool */ public static function isSetLocaleWorking() { - if ('' === basename('§')) { + if ('' === escapeshellcmd('§')) { // Borrowed from \Patchwork\Utf8\Bootup::initLocale setlocale(LC_ALL, 'C.UTF-8', 'C'); setlocale(LC_CTYPE, 'en_US.UTF-8', 'fr_FR.UTF-8', 'es_ES.UTF-8', 'de_DE.UTF-8', 'ru_RU.UTF-8', 'pt_BR.UTF-8', 'it_IT.UTF-8', 'ja_JP.UTF-8', 'zh_CN.UTF-8', '0'); } // Check again - if ('' === basename('§')) { + if ('' === escapeshellcmd('§')) { return false; } return true; diff --git a/tests/lib/UtilTest.php b/tests/lib/UtilTest.php index e21a5323b1b5a..54630f6471cb6 100644 --- a/tests/lib/UtilTest.php +++ b/tests/lib/UtilTest.php @@ -75,6 +75,14 @@ public function testEncodePath() { $this->assertEquals("/%C2%A7%23%40test%25%26%5E%C3%A4/-child", $result); } + public function testIsSetLocaleWorking() { + // OC_Util::isSetLocaleWorking() assumes escapeshellcmd('§') returns '' with non-UTF-8 locale. + $locale = setlocale(LC_CTYPE, 0); + setlocale(LC_CTYPE, 'C'); + $this->assertEquals('', escapeshellcmd('§')); + setlocale(LC_CTYPE, $locale); + } + public function testFileInfoLoaded() { $expected = function_exists('finfo_open'); $this->assertEquals($expected, \OC_Util::fileInfoLoaded()); From 87a5620032ba7161223897b16fb9ca59188aa3c4 Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Sun, 14 Nov 2021 08:25:32 +0900 Subject: [PATCH 2/6] Check whether setlocale works only after setlocale Signed-off-by: Naoto Kobayashi --- lib/private/legacy/OC_Util.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 9978815e486cd..987765e23ee1b 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -1284,12 +1284,13 @@ public static function isSetLocaleWorking() { // Borrowed from \Patchwork\Utf8\Bootup::initLocale setlocale(LC_ALL, 'C.UTF-8', 'C'); setlocale(LC_CTYPE, 'en_US.UTF-8', 'fr_FR.UTF-8', 'es_ES.UTF-8', 'de_DE.UTF-8', 'ru_RU.UTF-8', 'pt_BR.UTF-8', 'it_IT.UTF-8', 'ja_JP.UTF-8', 'zh_CN.UTF-8', '0'); - } - // Check again - if ('' === escapeshellcmd('§')) { - return false; + // Check again + if ('' === escapeshellcmd('§')) { + return false; + } } + return true; } From 0c1f10880b0d9a1e85c2259336e2714713112924 Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Mon, 15 Nov 2021 18:33:50 +0900 Subject: [PATCH 3/6] Add check whether escapeshellcmd behaves the same as basename Signed-off-by: Naoto Kobayashi --- tests/lib/UtilTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/lib/UtilTest.php b/tests/lib/UtilTest.php index 54630f6471cb6..fd4cdadfb0b85 100644 --- a/tests/lib/UtilTest.php +++ b/tests/lib/UtilTest.php @@ -80,6 +80,8 @@ public function testIsSetLocaleWorking() { $locale = setlocale(LC_CTYPE, 0); setlocale(LC_CTYPE, 'C'); $this->assertEquals('', escapeshellcmd('§')); + setlocale(LC_CTYPE, 'C.UTF-8'); + $this->assertEquals('§', escapeshellcmd('§')); setlocale(LC_CTYPE, $locale); } From 0bb3232a33831a37914df3f319c162690d0b9188 Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Tue, 16 Nov 2021 00:40:52 +0900 Subject: [PATCH 4/6] OC_Util: Add fallbacks to check if current locale is UTF8 Using escapeshellcmd to get current locale causes error if the function is disabled. Add fallbacks to prevent the error. Signed-off-by: Naoto Kobayashi --- lib/private/legacy/OC_Util.php | 19 +++++++++++++++++-- tests/lib/UtilTest.php | 6 ++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 987765e23ee1b..887985aa4293e 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -1273,6 +1273,21 @@ public function isHtaccessWorking(\OCP\IConfig $config) { return $content !== $testContent && $fallbackContent !== $testContent; } + /** + * Check if current locale is non-UTF8 + * + * @return bool + */ + private static function isNonUTF8Locale() { + if (function_exists("escapeshellcmd")) { + return ('' === escapeshellcmd('§')); + } else if (function_exists("escapeshellarg")) { + return ('\'\'' === escapeshellarg('§')); + } else { + return (0 === preg_match('/utf-?8/i', setlocale(LC_CTYPE, 0))); + } + } + /** * Check if the setlocal call does not work. This can happen if the right * local packages are not available on the server. @@ -1280,13 +1295,13 @@ public function isHtaccessWorking(\OCP\IConfig $config) { * @return bool */ public static function isSetLocaleWorking() { - if ('' === escapeshellcmd('§')) { + if (self::isNonUTF8Locale()) { // Borrowed from \Patchwork\Utf8\Bootup::initLocale setlocale(LC_ALL, 'C.UTF-8', 'C'); setlocale(LC_CTYPE, 'en_US.UTF-8', 'fr_FR.UTF-8', 'es_ES.UTF-8', 'de_DE.UTF-8', 'ru_RU.UTF-8', 'pt_BR.UTF-8', 'it_IT.UTF-8', 'ja_JP.UTF-8', 'zh_CN.UTF-8', '0'); // Check again - if ('' === escapeshellcmd('§')) { + if (self::isNonUTF8Locale()) { return false; } } diff --git a/tests/lib/UtilTest.php b/tests/lib/UtilTest.php index fd4cdadfb0b85..af309f5cdcfeb 100644 --- a/tests/lib/UtilTest.php +++ b/tests/lib/UtilTest.php @@ -75,13 +75,15 @@ public function testEncodePath() { $this->assertEquals("/%C2%A7%23%40test%25%26%5E%C3%A4/-child", $result); } - public function testIsSetLocaleWorking() { - // OC_Util::isSetLocaleWorking() assumes escapeshellcmd('§') returns '' with non-UTF-8 locale. + public function testIsNonUTF8Locale() { + // OC_Util::isNonUTF8Locale() assumes escapeshellcmd('§') returns '' with non-UTF-8 locale. $locale = setlocale(LC_CTYPE, 0); setlocale(LC_CTYPE, 'C'); $this->assertEquals('', escapeshellcmd('§')); + $this->assertEquals('\'\'', escapeshellarg('§')); setlocale(LC_CTYPE, 'C.UTF-8'); $this->assertEquals('§', escapeshellcmd('§')); + $this->assertEquals('\'§\'', escapeshellarg('§')); setlocale(LC_CTYPE, $locale); } From a0cd7fc1763fbb5bf59e5e208ce9d5ebd9f9ffa6 Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Tue, 16 Nov 2021 00:46:21 +0900 Subject: [PATCH 5/6] OC_Util::isSetLocaleWorking: fix typo Signed-off-by: Naoto Kobayashi --- lib/private/legacy/OC_Util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 887985aa4293e..50ff1c682c8cb 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -1289,7 +1289,7 @@ private static function isNonUTF8Locale() { } /** - * Check if the setlocal call does not work. This can happen if the right + * Check if the setlocale call does not work. This can happen if the right * local packages are not available on the server. * * @return bool From 4d1daa55490c7db6de5a36281d5a73ec1673049a Mon Sep 17 00:00:00 2001 From: Naoto Kobayashi Date: Tue, 16 Nov 2021 21:05:43 +0900 Subject: [PATCH 6/6] OC_Util::isNonUTF8Locale: fix lint error Signed-off-by: Naoto Kobayashi --- lib/private/legacy/OC_Util.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 50ff1c682c8cb..49d24efdfb9b0 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -1279,12 +1279,12 @@ public function isHtaccessWorking(\OCP\IConfig $config) { * @return bool */ private static function isNonUTF8Locale() { - if (function_exists("escapeshellcmd")) { - return ('' === escapeshellcmd('§')); - } else if (function_exists("escapeshellarg")) { - return ('\'\'' === escapeshellarg('§')); + if (function_exists('escapeshellcmd')) { + return '' === escapeshellcmd('§'); + } elseif (function_exists('escapeshellarg')) { + return '\'\'' === escapeshellarg('§'); } else { - return (0 === preg_match('/utf-?8/i', setlocale(LC_CTYPE, 0))); + return 0 === preg_match('/utf-?8/i', setlocale(LC_CTYPE, 0)); } }