From 9dc72be2d4470c0ef488bd1688e30194b760373c Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 24 May 2023 22:48:12 +0800 Subject: [PATCH 1/2] MDL-78346 tool_langimport: Prevent uninstallation of invalid targets --- admin/tool/langimport/classes/controller.php | 12 ++++ admin/tool/langimport/index.php | 7 +++ .../tool/langimport/tests/controller_test.php | 59 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 admin/tool/langimport/tests/controller_test.php diff --git a/admin/tool/langimport/classes/controller.php b/admin/tool/langimport/classes/controller.php index cb38792bd9d..0c827b4c2f3 100644 --- a/admin/tool/langimport/classes/controller.php +++ b/admin/tool/langimport/classes/controller.php @@ -112,6 +112,18 @@ class controller { public function uninstall_language($lang) { global $CFG; + $lang = clean_param($lang, PARAM_LANG); + if ($lang === '') { + // Do not allow uninstallation of invalid languages. + // Note: PARAM_LANG returns an empty string for invalid validation. + return false; + } + + if ($lang === 'en') { + // Never allow removal of the default langauge. + return false; + } + $dest1 = $CFG->dataroot.'/lang/'.$lang; $dest2 = $CFG->dirroot.'/lang/'.$lang; $rm1 = false; diff --git a/admin/tool/langimport/index.php b/admin/tool/langimport/index.php index 407e5882ff6..7894153d428 100644 --- a/admin/tool/langimport/index.php +++ b/admin/tool/langimport/index.php @@ -43,6 +43,13 @@ $uninstalllang = optional_param_array('uninstalllang', array(), PARAM_LANG) $confirmtounistall = optional_param('confirmtouninstall', '', PARAM_SAFEPATH); // uninstallation confirmation $purgecaches = optional_param('purgecaches', false, PARAM_BOOL); // explicit caches reset +// Filter the uninstall language list. +// If the list contains a language which is not installed, it is replaced with an empty string. +// When we try to uninstall an empty string, we uninstall every language. +$uninstalllang = array_filter($uninstalllang, function($lang) { + return !empty($lang); +}); + if ($purgecaches) { require_sesskey(); get_string_manager()->reset_caches(); diff --git a/admin/tool/langimport/tests/controller_test.php b/admin/tool/langimport/tests/controller_test.php new file mode 100644 index 00000000000..03b0ebb4700 --- /dev/null +++ b/admin/tool/langimport/tests/controller_test.php @@ -0,0 +1,59 @@ +. + +namespace tool_langimport; + +/** + * Tests for \tool_langimport\locale class. + * + * @package tool_langimport + * @category test + * @coversDefaultClass \tool_langimport\controller + * @copyright 2023 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class controller_test extends \advanced_testcase { + + /** + * Test uninstall of language with invalid values. + * + * @covers ::uninstall_lang + * @dataProvider uninstall_lang_invalid_provider + * @params string $lang + */ + public function test_uninstall_lang_invalid(string $lang): void { + global $CFG; + + $controller = new controller(); + $this->assertFalse($controller->uninstall_language($lang)); + $this->assertFileExists("{$CFG->dataroot}/lang"); + $this->assertFileExists("{$CFG->dirroot}/lang/en"); + } + + /** + * Data provider for uninstall_lang tests with invalid values. + * + * @return array + */ + public function uninstall_lang_invalid_provider(): array { + return [ + 'Empty string' => [''], + 'Meaningless empty string' => [' '], + 'Default language' => ['en'], + 'Invalid language string' => ['swedish'], + ]; + } +} From 4ddbcf2aec4f6fbd57b40775f7725e665cedaa84 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 24 May 2023 22:48:28 +0800 Subject: [PATCH 2/2] MDL-78346 tool_langimport: Redirect after action to prevent resubmission --- admin/tool/langimport/index.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/admin/tool/langimport/index.php b/admin/tool/langimport/index.php index 7894153d428..b4bd4a47171 100644 --- a/admin/tool/langimport/index.php +++ b/admin/tool/langimport/index.php @@ -76,11 +76,12 @@ if (($mode == INSTALLATION_OF_SELECTED_LANG) and confirm_sesskey() and !empty($p if (is_array($pack) && count($pack) > 1) { // Installing multiple languages can take a while - perform it asynchronously in the background. $controller->schedule_languagepacks_installation($pack); - + redirect($PAGE->url); } else { // Single language pack to be installed synchronously. It should be reasonably quick and can be used for debugging, too. core_php_time_limit::raise(); $controller->install_languagepacks($pack); + redirect($PAGE->url); } } @@ -109,7 +110,7 @@ if ($mode == DELETION_OF_SELECTED_LANG and (!empty($uninstalllang) or !empty($co foreach ($uninstalllang as $ulang) { $controller->uninstall_language($ulang); } - + redirect($PAGE->url); } }