From 2def80568b61b794ee65ade8a866eca7b6ff7e5f Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sun, 6 Mar 2022 16:30:20 +0100 Subject: [PATCH] MDL-74097 core_text: Ensure that transliteration always happens Before the patch, transliteration was only happening when the encoding of the string was utf-8. For other encodings only a simpler conversion (iconv) to ascii was done. For some reason iconv() own transliteration abilities are not consistent between systems (depends of libraries installed, locales and other bits). So now we always convert the string to utf-8, in order to transliterate it. And finally, also perform an iconv to cover some characters that transliterate doesn't handle ok. Also, remove a block of code that does nothing (previously it was executing some code, but now it just sets and restores the error level for nothing). --- lib/classes/text.php | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/classes/text.php b/lib/classes/text.php index f95d2b55c51..9402863a7d5 100644 --- a/lib/classes/text.php +++ b/lib/classes/text.php @@ -158,21 +158,13 @@ class core_text { } if ($toCS === 'ascii') { - // Try to normalize the conversion a bit. - $text = self::specialtoascii($text, $fromCS); + // Try to normalize the conversion a bit if the target is ascii. + return self::specialtoascii($text, $fromCS); } // Prevent any error notices, do not use //IGNORE so that we get // consistent result if iconv fails. - $result = @iconv($fromCS, $toCS.'//TRANSLIT', $text); - - if ($result === false or $result === '') { - // Note: iconv is prone to return empty string when invalid char encountered, or false if encoding unsupported. - $oldlevel = error_reporting(E_PARSE); - error_reporting($oldlevel); - } - - return $result; + return @iconv($fromCS, $toCS.'//TRANSLIT', $text); } /** @@ -341,10 +333,14 @@ class core_text { $charset = self::parse_charset($charset); $oldlevel = error_reporting(E_PARSE); - if ($charset == 'utf-8') { - $text = transliterator_transliterate('Any-Latin; Latin-ASCII', (string) $text); + // Always convert to utf-8, so transliteration can do its work always. + if ($charset !== 'utf-8') { + $text = iconv($charset, 'utf-8'.'//TRANSLIT', $text); } - $result = iconv($charset, 'ASCII//TRANSLIT//IGNORE', (string) $text); + $text = transliterator_transliterate('Any-Latin; Latin-ASCII', (string) $text); + + // Still, apply iconv because some chars are not handled by transliterate. + $result = iconv('utf-8', 'ASCII//TRANSLIT//IGNORE', (string) $text); error_reporting($oldlevel); return $result;