From c69d5d46e82030139af4d2785c1cfcb6041a0d3e Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Mon, 29 Sep 2008 10:19:11 +0000 Subject: [PATCH] Proposed fix for bug 14944, specifically the reports that some servers do not have en_US.UTF-8. Make the locale configurable via $wgShellLocale. Detect available locales and set $wgShellLocale to an appropriate value on install. Also fixes safe_mode putenv() warnings. RELEASE-NOTES entry will go to 1.13. --- config/index.php | 78 +++++++++++++++++++++++++++++++++++- includes/DefaultSettings.php | 7 ++++ includes/GlobalFunctions.php | 22 +++++++++- includes/Setup.php | 8 ---- 4 files changed, 105 insertions(+), 10 deletions(-) diff --git a/config/index.php b/config/index.php index 09c195614a..c5a7dea21c 100644 --- a/config/index.php +++ b/config/index.php @@ -598,7 +598,6 @@ print "
  • Environment check $conf->RootPW = importPost( "RootPW", "" ); $useRoot = importCheck( 'useroot', false ); $conf->LanguageCode = importPost( "LanguageCode", "en" ); - ## MySQL specific: $conf->DBprefix = importPost( "DBprefix" ); $conf->setSchema( @@ -617,6 +616,7 @@ print "
  • Environment check // We need a second field so it doesn't overwrite the MySQL one $conf->DBprefix2 = importPost( "DBprefix2" ); + $conf->ShellLocale = getShellLocale( $conf->LanguageCode ); /* Check for validity */ $errs = array(); @@ -1521,6 +1521,13 @@ function writeLocalSettings( $conf ) { $rights = ($conf->RightsUrl) ? "" : "# "; $hashedUploads = $conf->safeMode ? '' : '# '; + if ( $conf->ShellLocale ) { + $locale = ''; + } else { + $locale = '# '; + $conf->ShellLocale = 'en_US.UTF-8'; + } + switch ( $conf->Shm ) { case 'memcached': $cacheType = 'CACHE_MEMCACHED'; @@ -1692,6 +1699,11 @@ if ( \$wgCommandLineMode ) { {$magic}\$wgUseImageMagick = true; {$magic}\$wgImageMagickConvertCommand = \"{$convert}\"; +## If you use ImageMagick (or any other shell command) on a +## Linux server, this will need to be set to the name of an +## available UTF-8 locale +{$locale}\$wgShellLocale = \"{$slconf['ShellLocale']}\"; + ## If you want to use image uploads under safe mode, ## create the directories images/archive, images/thumb and ## images/temp, and make them all writable. Then uncomment @@ -1934,6 +1946,70 @@ function printListItem( $item ) { print "
  • $item
  • "; } +# Determine a suitable value for $wgShellLocale +function getShellLocale( $wikiLanguage ) { + # Give up now if we're in safe mode or open_basedir + # It's theoretically possible but tricky to work with + if ( wfIniGetBool( "safe_mode" ) || ini_get( 'open_basedir' ) ) { + return false; + } + + if ( php_uname( 's' ) != 'Linux' ) { + # TODO: need testing for other POSIX platforms + return false; + } + + # Get a list of available locales + $lines = $ret = false; + exec( '/usr/bin/locale -a', $lines, $ret ); + if ( $ret ) { + return false; + } + + $lines = array_map( 'trim', $lines ); + $candidatesByLocale = array(); + $candidatesByLang = array(); + foreach ( $lines as $line ) { + if ( $line === '' ) { + continue; + } + if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) { + continue; + } + list( $all, $lang, $territory, $charset, $modifier ) = $m; + $candidatesByLocale["$lang$territory.UTF-8$modifier"] = $m; + $candidatesByLang[$lang][] = $m; + } + + # Try the current value of LANG + if ( isset( $candidatesByLocale[ getenv( 'LANG' ) ] ) ) { + return getenv( 'LANG' ); + } + + # Try the most common ones + $commonLocales = array( 'en_US.UTF-8', 'de_DE.UTF-8' ); + foreach ( $commonLocales as $commonLocale ) { + if ( isset( $candidatesByLocale[$commonLocale] ) ) { + return $commonLocale; + } + } + + # Is there an available locale in the Wiki's language? + if ( isset( $candidatesByLang[$wikiLang] ) ) { + $m = reset( $candidatesByLang[$wikiLang] ); + return $m[0]; + } + + # Are there any at all? + if ( count( $candidatesByLocale ) ) { + $m = reset( $candidatesByLocale ); + return $m[0]; + } + + # Give up + return false; +} + ?>
    diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 62559d4283..85602dd796 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -769,6 +769,13 @@ $wgInputEncoding = 'UTF-8'; $wgOutputEncoding = 'UTF-8'; $wgEditEncoding = ''; +/** + * Locale for LC_CTYPE, to work around http://bugs.php.net/bug.php?id=45132 + * For Unix-like operating systems, set this to to a locale that has a UTF-8 + * character set. Only the character set is relevant. + */ +$wgShellLocale = 'en_US.utf8'; + /** * Set this to eg 'ISO-8859-1' to perform character set * conversion when loading old revisions not marked with diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index e241bcaf71..24b581562a 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1217,9 +1217,14 @@ function wfPurgeSquidServers ($urlArr) { /** * Windows-compatible version of escapeshellarg() * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() - * function puts single quotes in regardless of OS + * function puts single quotes in regardless of OS. + * + * Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to + * earlier distro releases of PHP) */ function wfEscapeShellArg( ) { + wfInitShellLocale(); + $args = func_get_args(); $first = true; $retVal = ''; @@ -2146,6 +2151,7 @@ function wfShellExec( $cmd, &$retval=null ) { $retval = 1; return "Unable to run external programs in safe mode."; } + wfInitShellLocale(); if ( php_uname( 's' ) == 'Linux' ) { $time = intval( ini_get( 'max_execution_time' ) ); @@ -2175,7 +2181,21 @@ function wfShellExec( $cmd, &$retval=null ) { wfDebugLog( 'exec', "Possibly missing executable file: $cmd\n" ); } return $output; +} +/** + * Workaround for http://bugs.php.net/bug.php?id=45132 + * escapeshellarg() destroys non-ASCII characters if LANG is not a UTF-8 locale + */ +function wfInitShellLocale() { + static $done = false; + if ( $done ) return; + $done = true; + global $wgShellLocale; + if ( !wfIniGetBool( 'safe_mode' ) ) { + putenv( "LC_CTYPE=$wgShellLocale" ); + setlocale( LC_CTYPE, $wgShellLocale ); + } } /** diff --git a/includes/Setup.php b/includes/Setup.php index b03e1884c2..8878d5df50 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -122,14 +122,6 @@ if ( $wgUseSharedUploads ) { ); } } - -/** - * Workaround for http://bugs.php.net/bug.php?id=45132 - * escapeshellarg() destroys non-ASCII characters if LANG is not a UTF-8 locale - */ -putenv( 'LC_CTYPE=en_US.UTF-8' ); -setlocale( LC_CTYPE, 'en_US.UTF-8' ); - if ( !class_exists( 'AutoLoader' ) ) { require_once( "$IP/includes/AutoLoader.php" ); } -- 2.20.1