Provide a proper implementation for passing environment variables to wfShellExec()
authorPlatonides <platonides@users.mediawiki.org>
Tue, 26 Oct 2010 22:17:42 +0000 (22:17 +0000)
committerPlatonides <platonides@users.mediawiki.org>
Tue, 26 Oct 2010 22:17:42 +0000 (22:17 +0000)
The quick fix of r74821 is no longer needed.

includes/GlobalFunctions.php
includes/media/Bitmap.php

index 12464e6..778cadd 100644 (file)
@@ -2457,9 +2457,11 @@ function wfDl( $extension ) {
  * @param $cmd Command line, properly escaped for shell.
  * @param &$retval optional, will receive the program's exit code.
  *                 (non-zero is usually failure)
+ * @param $environ Array optional environment variables which should be 
+ *                 added to the executed command environment.
  * @return collected stdout as a string (trailing newlines stripped)
  */
-function wfShellExec( $cmd, &$retval = null ) {
+function wfShellExec( $cmd, &$retval = null, $environ = array() ) {
        global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime;
 
        static $disabled;
@@ -2487,6 +2489,25 @@ function wfShellExec( $cmd, &$retval = null ) {
 
        wfInitShellLocale();
 
+       $envcmd = '';
+       foreach( $environ as $k => $v ) {
+               if ( wfIsWindows() ) {
+                       /* Surrounding a set in quotes (method used by wfEscapeShellArg) makes the quotes themselves 
+                        * appear in the environment variable, so we must use carat escaping as documented in 
+                        * http://technet.microsoft.com/en-us/library/cc723564.aspx 
+                        * Note however that the quote isn't listed there, but is needed, and the parentheses 
+                        * are listed there but doesn't appear to need it.
+                        */
+                       $envcmd .= "set $k=" . preg_replace( '/([&|()<>^"])/', '^\\1', $v ) . ' && ';
+               } else {
+                       /* Assume this is a POSIX shell, thus required to accept variable assignments before the command 
+                        * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_09_01
+                        */
+                       $envcmd .= "$k=" . escapeshellarg( $v ) . ' ';
+               }
+       }
+       $cmd = $envcmd . $cmd;
+       
        if ( wfIsWindows() ) {
                if ( version_compare( PHP_VERSION, '5.3.0', '<' ) && /* Fixed in 5.3.0 :) */
                        ( version_compare( PHP_VERSION, '5.2.1', '>=' ) || php_uname( 's' ) == 'Windows NT' ) )
index 7e9edb7..c83f430 100644 (file)
@@ -148,9 +148,9 @@ class BitmapHandler extends ImageHandler {
                        }
 
                        // Use one thread only, to avoid deadlock bugs on OOM
-                       $tempEnv = 'OMP_NUM_THREADS=1 ';
+                       $env = array( 'OMP_NUM_THREADS' => 1 );
                        if ( strval( $wgImageMagickTempDir ) !== '' ) {
-                               $tempEnv .= 'MAGICK_TMPDIR=' . wfEscapeShellArg( $wgImageMagickTempDir ) . ' ';
+                               $env['MAGICK_TMPDIR'] = $wgImageMagickTempDir;
                        }
 
                        $cmd  = 
@@ -171,14 +171,9 @@ class BitmapHandler extends ImageHandler {
                                " {$animation_post} " .
                                wfEscapeShellArg( $this->escapeMagickOutput( $dstPath ) ) . " 2>&1";
 
-                       if ( !wfIsWindows() ) {
-                               // Assume we have a POSIX compliant shell which accepts variable assignments preceding the command
-                               $cmd = $tempEnv . $cmd;
-                       }
-
                        wfDebug( __METHOD__.": running ImageMagick: $cmd\n" );
                        wfProfileIn( 'convert' );
-                       $err = wfShellExec( $cmd, $retval );
+                       $err = wfShellExec( $cmd, $retval, $env );
                        wfProfileOut( 'convert' );
                } elseif( $scaler == 'custom' ) {
                        # Use a custom convert command