Merge branch 'MDL-84907-401' of https://github.com/HuongNV13/moodle into MOODLE_401_STABLE

This commit is contained in:
Jun Pataleta 2025-04-04 11:31:11 +08:00
commit aaf985001e
No known key found for this signature in database
GPG Key ID: F83510526D99E2C7
6 changed files with 23 additions and 12 deletions

View File

@ -168,8 +168,7 @@ abstract class restore_qtype_plugin extends restore_plugin {
$this->questionanswercacheid = $newquestionid;
// Cache all cleaned answers for a simple text match.
foreach ($answers as $answer) {
// MDL-30018: Clean in the same way as {@link xml_writer::xml_safe_utf8()}.
$clean = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is','', $answer->answer); // Clean CTRL chars.
$clean = core_text::trim_ctrl_chars($answer->answer); // Clean CTRL chars.
$clean = preg_replace("/\r\n|\r/", "\n", $clean); // Normalize line ending.
$this->questionanswercache[$clean] = $answer->id;
}

View File

@ -5154,8 +5154,7 @@ class restore_create_categories_and_questions extends restore_structure_step {
$potentialhints = $DB->get_records('question_hints',
array('questionid' => $newquestionid), '', 'id, hint');
foreach ($potentialhints as $potentialhint) {
// Clean in the same way than {@link xml_writer::xml_safe_utf8()}.
$cleanhint = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is','', $potentialhint->hint); // Clean CTRL chars.
$cleanhint = core_text::trim_ctrl_chars($potentialhint->hint); // Clean CTRL chars.
$cleanhint = preg_replace("/\r\n|\r/", "\n", $cleanhint); // Normalize line ending.
if ($cleanhint === $data->hint) {
$newitemid = $data->id;

View File

@ -253,14 +253,14 @@ class xml_writer {
}
/**
* Perform some UTF-8 cleaning, stripping the control chars (\x0-\x1f)
* but tabs (\x9), newlines (\xa) and returns (\xd). The delete control
* Perform some UTF-8 cleaning, stripping the control chars (\x00-\x1f)
* but tabs (\x09), newlines (\xa) and returns (\xd). The delete control
* char (\x7f) is also included. All them are forbiden in XML 1.0 specs.
* The expression below seems to be UTF-8 safe too because it simply
* ignores the rest of characters. Also normalize linefeeds and return chars.
*/
protected function xml_safe_utf8($content) {
$content = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is', '', $content ?? ''); // clean CTRL chars.
$content = core_text::trim_ctrl_chars($content ?? '');
$content = preg_replace("/\r\n|\r/", "\n", $content); // Normalize line&return=>line
return fix_utf8($content);
}

View File

@ -676,4 +676,16 @@ class core_text {
return mb_convert_case($text, MB_CASE_TITLE, 'UTF-8');
}
/**
* Trims control characters out of a string.
* Example: (\x00-\x1f) and (\x7f)
*
* @param string $text Input string
* @return string Cleaned string value
*/
public static function trim_ctrl_chars(string $text): string {
// Remove control characters text.
return preg_replace('/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/i', '', $text);
}
}

View File

@ -1,6 +1,10 @@
This files describes API changes in core libraries and APIs,
information provided here is intended especially for developers.
=== 4.1.18 ===
* A new method, `core_text::trim_ctrl_chars()`, has been introduced to clean control characters from text.
This ensures cleaner input handling and prevents issues caused by invisible or non-printable characters
=== 4.1.12 ===
* Added the ability for unit tests to autoload classes in the `\[component]\tests\` namespace from the `[path/to/component]/tests/classes` directory.

View File

@ -157,13 +157,10 @@ class restore_qtype_match_plugin extends restore_qtype_plugin {
$this->questionsubcacheid = $newquestionid;
// Cache all cleaned answers and questiontext.
foreach ($potentialsubs as $potentialsub) {
// Clean in the same way than {@link xml_writer::xml_safe_utf8()}.
$cleanquestion = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is',
'', $potentialsub->questiontext); // Clean CTRL chars.
$cleanquestion = core_text::trim_ctrl_chars($potentialsub->questiontext); // Clean CTRL chars.
$cleanquestion = preg_replace("/\r\n|\r/", "\n", $cleanquestion); // Normalize line ending.
$cleananswer = preg_replace('/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is',
'', $potentialsub->answertext); // Clean CTRL chars.
$cleananswer = core_text::trim_ctrl_chars($potentialsub->answertext); // Clean CTRL chars.
$cleananswer = preg_replace("/\r\n|\r/", "\n", $cleananswer); // Normalize line ending.
$this->questionsubcache[$cleanquestion][$cleananswer] = $potentialsub->id;