Proposed fix for bug 14944, specifically the reports that some servers do not have...
authorTim Starling <tstarling@users.mediawiki.org>
Mon, 29 Sep 2008 10:19:11 +0000 (10:19 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Mon, 29 Sep 2008 10:19:11 +0000 (10:19 +0000)
config/index.php
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/Setup.php

index 09c1956..c5a7dea 100644 (file)
@@ -598,7 +598,6 @@ print "<li style='font-weight:bold;color:green;font-size:110%'>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 "<li style='font-weight:bold;color:green;font-size:110%'>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 "<li>$item</li>";
 }
 
+# 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;
+}
+
 ?>
 
        <div class="license">
index 62559d4..85602dd 100644 (file)
@@ -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
index e241bca..24b5815 100644 (file)
@@ -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 );
+       }
 }
 
 /**
index b03e188..8878d5d 100644 (file)
@@ -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" );
 }