Skip to content

Commit

Permalink
MDL-33007 add workaround for broken iconv //IGNORE
Browse files Browse the repository at this point in the history
This patch adds mbstring utf-8 cleanup fallback and admin warning if no utf-8 cleanup possible in user submitted data.
  • Loading branch information
skodak committed Jun 1, 2012
1 parent 3681e78 commit 0aff15c
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 15 deletions.
9 changes: 3 additions & 6 deletions admin/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@
echo 'Moodle requires the iconv PHP extension. Please install or enable the iconv extension.';
die();
}
if (iconv('UTF-8', 'UTF-8//IGNORE', 'abc') !== 'abc') {
// known to be broken in mid-2011 MAMP installations
echo 'Broken iconv PHP extension detected, installation/upgrade can not continue.';
die();
}

define('NO_OUTPUT_BUFFERING', true);

Expand Down Expand Up @@ -434,6 +429,8 @@
array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
$availableupdatesfetch = $updateschecker->get_last_timefetched();

$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'') !== '100€');

admin_externalpage_setup('adminnotifications');

if ($fetchupdates) {
Expand All @@ -444,4 +441,4 @@

$output = $PAGE->get_renderer('core', 'admin');
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch);
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb);
17 changes: 16 additions & 1 deletion admin/renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,14 @@ public function upgrade_plugin_check_page(plugin_manager $pluginman, available_u
* @param bool $cronoverdue warn cron not running
* @param bool $dbproblems warn db has problems
* @param bool $maintenancemode warn in maintenance mode
* @param bool $buggyiconvnomb warn iconv problems
* @param array|null $availableupdates array of available_update_info objects or null
* @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
*
* @return string HTML to output.
*/
public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch) {
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb) {
global $CFG;
$output = '';

Expand All @@ -257,6 +258,7 @@ public function admin_notifications_page($maturity, $insecuredataroot, $errorsdi
$output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : '';
$output .= $this->insecure_dataroot_warning($insecuredataroot);
$output .= $this->display_errors_warning($errorsdisplayed);
$output .= $this->buggy_iconv_warning($buggyiconvnomb);
$output .= $this->cron_overdue_warning($cronoverdue);
$output .= $this->db_problems($dbproblems);
$output .= $this->maintenance_mode_warning($maintenancemode);
Expand Down Expand Up @@ -381,6 +383,19 @@ protected function display_errors_warning($errorsdisplayed) {
return $this->warning(get_string('displayerrorswarning', 'admin'));
}

/**
* Render an appropriate message if iconv is buggy and mbstring missing.
* @param bool $buggyiconvnomb
* @return string HTML to output.
*/
protected function buggy_iconv_warning($buggyiconvnomb) {
if (!$buggyiconvnomb) {
return '';
}

return $this->warning(get_string('warningiconvbuggy', 'admin'));
}

/**
* Render an appropriate message if cron has not been run recently.
* @param bool $cronoverdue
Expand Down
5 changes: 0 additions & 5 deletions install.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@
echo 'Moodle requires the iconv PHP extension. Please install or enable the iconv extension.';
die();
}
if (iconv('UTF-8', 'UTF-8//IGNORE', 'abc') !== 'abc') {
// known to be broken in mid-2011 MAMP installations
echo 'Broken iconv PHP extension detected, installation can not continue.';
die;
}

if (PHP_INT_SIZE > 4) {
// most probably 64bit PHP - we need a lot more memory
Expand Down
1 change: 1 addition & 0 deletions lang/en/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,7 @@
$string['validateerror'] = 'This value was not valid:';
$string['verifychangedemail'] = 'Restrict domains when changing email';
$string['warningcurrentsetting'] = 'Invalid current value: {$a}';
$string['warningiconvbuggy'] = 'Your version of the iconv library does not support the //IGNORE modifier. You should install the mbstring extension which can be used instead for cleaning strings containing invalid UTF-8 characters.';
$string['webproxy'] = 'Web proxy';
$string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.<br /><em>PHP cURL extension is highly recommended.</em>';
$string['xmlrpcrecommended'] = 'The xmlrpc extension is needed for hub communication, and useful for web services and Moodle networking';
Expand Down
28 changes: 26 additions & 2 deletions lib/moodlelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1127,15 +1127,39 @@ function fix_utf8($value) {
// shortcut
return $value;
}
// lower error reporting because glibc throws bogus notices

// Lower error reporting because glibc throws bogus notices.
$olderror = error_reporting();
if ($olderror & E_NOTICE) {
error_reporting($olderror ^ E_NOTICE);
}
$result = iconv('UTF-8', 'UTF-8//IGNORE', $value);

// Note: this duplicates min_fix_utf8() intentionally.
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')) {
$subst = mb_substitute_character();
mb_substitute_character('');
$result = mb_convert_encoding($value, 'utf-8', 'utf-8');
mb_substitute_character($subst);

} else {
// Warn admins on admin/index.php page.
$result = $value;
}

} else {
$result = iconv('UTF-8', 'UTF-8//IGNORE', $value);
}

if ($olderror & E_NOTICE) {
error_reporting($olderror);
}

return $result;

} else if (is_array($value)) {
Expand Down
3 changes: 2 additions & 1 deletion lib/tests/moodlelib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ function test_fix_utf8() {
$this->assertSame(1.1, fix_utf8(1.1));
$this->assertSame(true, fix_utf8(true));
$this->assertSame('', fix_utf8(''));
$this->assertSame('abc', fix_utf8('abc'));
$array = array('do', 're', 'mi');
$this->assertSame($array, fix_utf8($array));
$object = new stdClass();
Expand All @@ -312,7 +313,7 @@ function test_fix_utf8() {
$this->assertSame("ž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->assertSame('aaabbb', fix_utf8('aaa'.chr(130).'bbb'));
$this->assertSame('', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.');
}

function test_optional_param() {
Expand Down

0 comments on commit 0aff15c

Please sign in to comment.