From b71e34d890415ed06db6c059cacdda4d0f8ff617 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 4 Jun 2012 12:40:37 +0200 Subject: [PATCH] MDL-33353 make fix_utf8() to work better under some systems. This is a partial backport of MDL-32586 and MDL-33007 in order to get some systems handling utf-8 strings better: - debian/ubuntu. Avoid some glibc iconv() implementations to throw one PHP notice each time the //IGNORE option is used. - redhat. Avoid some implementations to return false each time the //IGNORE option is used. Note this does not include any backport of the admin notification not the configmin stuff. --- lib/moodlelib.php | 39 +++++++++++++++++++++++++++++++- lib/simpletest/testmoodlelib.php | 3 ++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 38bf0fec0ec..ae868b86afd 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -1127,7 +1127,44 @@ function fix_utf8($value) { // shortcut return $value; } - return iconv('UTF-8', 'UTF-8//IGNORE', $value); + + // Note: This is a partial backport of MDL-32586 and MDL-33007 to stable branches. + // Lower error reporting because glibc throws bogus notices. + $olderror = error_reporting(); + if ($olderror & E_NOTICE) { + error_reporting($olderror ^ E_NOTICE); + } + + // Detect buggy iconv implementations borking results. + static $buggyiconv = null; + if ($buggyiconv === null) { + $buggyiconv = (!function_exists('iconv') or iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€'); + } + + if ($buggyiconv) { + if (function_exists('mb_convert_encoding')) { + // Fallback to mbstring if available. + $subst = mb_substitute_character(); + mb_substitute_character(''); + $result = mb_convert_encoding($value, 'utf-8', 'utf-8'); + mb_substitute_character($subst); + + } else { + // Return unmodified text, mbstring not available. + $result = $value; + } + + } else { + // Working iconv, use it normally (with PHP notices disabled) + $result = iconv('UTF-8', 'UTF-8//IGNORE', $value); + } + + // Back to original reporting level + if ($olderror & E_NOTICE) { + error_reporting($olderror); + } + + return $result; } else if (is_array($value)) { foreach ($value as $k=>$v) { diff --git a/lib/simpletest/testmoodlelib.php b/lib/simpletest/testmoodlelib.php index 0fed885b0ff..a17fc1697a3 100644 --- a/lib/simpletest/testmoodlelib.php +++ b/lib/simpletest/testmoodlelib.php @@ -311,6 +311,7 @@ class moodlelib_test extends UnitTestCase { $this->assertidentical(1, fix_utf8(1)); $this->assertidentical(1.1, fix_utf8(1.1)); $this->assertidentical(true, fix_utf8(true)); + $this->assertidentical('abc', fix_utf8('abc')); $this->assertidentical('', fix_utf8('')); $array = array('do', 're', 'mi'); $this->assertidentical($array, fix_utf8($array)); @@ -323,7 +324,7 @@ class moodlelib_test extends UnitTestCase { $this->assertidentical("žlutý koníček přeskočil potůček \n\t\r\0", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0")); // invalid utf8 string - $this->assertidentical('aaabbb', fix_utf8('aaa'.chr(130).'bbb')); + $this->assertidentical('aš', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.'); } function test_optional_param() {