[TASK] Central function for escaping of shell-args 59/35959/6
authorStefan Neufeind <typo3.neufeind@speedpartner.de>
Sun, 11 Jan 2015 22:43:14 +0000 (23:43 +0100)
committerMarkus Klein <klein.t3@reelworx.at>
Mon, 19 Jan 2015 22:34:54 +0000 (23:34 +0100)
Instead of doing a (locale-aware) escaping in various
places use a central utility-function.

Change-Id: If0486b340543c33fc0794d754af81a4a666988c3
Resolves: #39928
Releases: master
Reviewed-on: http://review.typo3.org/35959
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/backend/Classes/View/ThumbnailView.php
typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php
typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php
typo3/sysext/core/Classes/Resource/Processing/LocalPreviewHelper.php
typo3/sysext/core/Classes/Utility/CommandUtility.php
typo3/sysext/scheduler/Classes/Scheduler.php

index a3419a2..972f0d8 100644 (file)
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Backend\View;
 
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Utility\CommandUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
@@ -209,7 +210,7 @@ class ThumbnailView {
                        if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
                                // If thumbnail does not exist, we generate it
                                if (!file_exists($this->output)) {
-                                       $parameters = '-sample ' . $this->size . ' ' . $this->wrapFileName($this->image->getForLocalProcessing(FALSE)) . '[0] ' . $this->wrapFileName($this->output);
+                                       $parameters = '-sample ' . $this->size . ' ' . CommandUtility::escapeShellArgument($this->image->getForLocalProcessing(FALSE)) . '[0] ' . CommandUtility::escapeShellArgument($this->output);
                                        $cmd = GeneralUtility::imageMagickCommand('convert', $parameters);
                                        \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd);
                                        if (!file_exists($this->output)) {
@@ -338,22 +339,4 @@ class ThumbnailView {
                die;
        }
 
-       /**
-        * Escapes a file name so it can safely be used on the command line.
-        *
-        * @param string $inputName Filename to safeguard, must not be empty
-        * @return string $inputName escaped as needed
-        */
-       protected function wrapFileName($inputName) {
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                       $currentLocale = setlocale(LC_CTYPE, 0);
-                       setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
-               }
-               $escapedInputName = escapeshellarg($inputName);
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                       setlocale(LC_CTYPE, $currentLocale);
-               }
-               return $escapedInputName;
-       }
-
 }
index fd41d0f..d2f21a7 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Imaging;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\CommandUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
@@ -2532,7 +2533,7 @@ class GraphicalFunctions {
        public function imageMagickIdentify($imagefile) {
                if (!$this->NO_IMAGE_MAGICK) {
                        $frame = $this->noFramePrepended ? '' : '[0]';
-                       $cmd = GeneralUtility::imageMagickCommand('identify', $this->wrapFileName($imagefile) . $frame);
+                       $cmd = GeneralUtility::imageMagickCommand('identify', CommandUtility::escapeShellArgument($imagefile) . $frame);
                        $returnVal = array();
                        \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd, $returnVal);
                        $splitstring = array_pop($returnVal);
@@ -2576,7 +2577,7 @@ class GraphicalFunctions {
                        } else {
                                $frame = '';
                        }
-                       $cmd = GeneralUtility::imageMagickCommand('convert', $params . ' ' . $this->wrapFileName($input . $frame) . ' ' . $this->wrapFileName($output));
+                       $cmd = GeneralUtility::imageMagickCommand('convert', $params . ' ' . CommandUtility::escapeShellArgument($input . $frame) . ' ' . CommandUtility::escapeShellArgument($output));
                        $this->IM_commands[] = array($output, $cmd);
                        $ret = \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd);
                        // Change the permissions of the file
@@ -2601,7 +2602,7 @@ class GraphicalFunctions {
                        $params = '-colorspace GRAY +matte';
                        $theMask = $this->randomName() . '.' . $this->gifExtension;
                        $this->imageMagickExec($mask, $theMask, $params);
-                       $cmd = GeneralUtility::imageMagickCommand('combine', '-compose over +matte ' . $this->wrapFileName($input) . ' ' . $this->wrapFileName($overlay) . ' ' . $this->wrapFileName($theMask) . ' ' . $this->wrapFileName($output));
+                       $cmd = GeneralUtility::imageMagickCommand('combine', '-compose over +matte ' . CommandUtility::escapeShellArgument($input) . ' ' . CommandUtility::escapeShellArgument($overlay) . ' ' . CommandUtility::escapeShellArgument($theMask) . ' ' . CommandUtility::escapeShellArgument($output));
                        // +matte = no alpha layer in output
                        $this->IM_commands[] = array($output, $cmd);
                        $ret = \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd);
@@ -2614,24 +2615,6 @@ class GraphicalFunctions {
                }
        }
 
-       /**
-        * Escapes a file name so it can safely be used on the command line.
-        *
-        * @param string $inputName filename to safeguard, must not be empty
-        * @return string $inputName escaped as needed
-        */
-       protected function wrapFileName($inputName) {
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                       $currentLocale = setlocale(LC_CTYPE, 0);
-                       setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
-               }
-               $escapedInputName = escapeshellarg($inputName);
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                       setlocale(LC_CTYPE, $currentLocale);
-               }
-               return $escapedInputName;
-       }
-
        /***********************************
         *
         * Various IO functions
index 733b47c..ecb273f 100644 (file)
@@ -14,7 +14,8 @@ namespace TYPO3\CMS\Core\Resource\Processing;
  * The TYPO3 project - inspiring people to share!
  */
 
-use \TYPO3\CMS\Core\Resource, \TYPO3\CMS\Core\Utility;
+use TYPO3\CMS\Core\Utility\CommandUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Processes Local Images files
@@ -31,7 +32,7 @@ class LocalImageProcessor implements ProcessorInterface {
         */
        public function __construct() {
                /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
-               $logManager = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class);
+               $logManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class);
                $this->logger = $logManager->getLogger(__CLASS__);
        }
 
@@ -88,10 +89,10 @@ class LocalImageProcessor implements ProcessorInterface {
        protected function getHelperByTaskName($taskName) {
                switch ($taskName) {
                        case 'Preview':
-                               $helper = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper::class, $this);
+                               $helper = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Processing\LocalPreviewHelper::class, $this);
                        break;
                        case 'CropScaleMask':
-                               $helper = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper::class, $this);
+                               $helper = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper::class, $this);
                        break;
                        default:
                                throw new \InvalidArgumentException('Cannot find helper for task name: "' . $taskName . '"', 1353401352);
@@ -101,26 +102,6 @@ class LocalImageProcessor implements ProcessorInterface {
        }
 
        /**
-        * Escapes a file name so it can safely be used on the command line.
-        *
-        * @param string $inputName filename to safeguard, must not be empty
-        * @return string $inputName escaped as needed
-        *
-        * @internal Don't use this method from outside the LocalImageProcessor!
-        */
-       public function wrapFileName($inputName) {
-               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                       $currentLocale = setlocale(LC_CTYPE, 0);
-                       setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
-                       $escapedInputName = escapeshellarg($inputName);
-                       setlocale(LC_CTYPE, $currentLocale);
-               } else {
-                       $escapedInputName = escapeshellarg($inputName);
-               }
-               return $escapedInputName;
-       }
-
-       /**
         * Creates error image based on gfx/notfound_thumb.png
         * Requires GD lib enabled, otherwise it will exit with the three
         * textstrings outputted as text. Outputs the image stream to browser and exits!
@@ -177,7 +158,7 @@ class LocalImageProcessor implements ProcessorInterface {
                static $graphicalFunctionsObject = NULL;
 
                if ($graphicalFunctionsObject === NULL) {
-                       $graphicalFunctionsObject = Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\GraphicalFunctions::class);
+                       $graphicalFunctionsObject = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\GraphicalFunctions::class);
                }
 
                return $graphicalFunctionsObject;
index d040ce1..e81d3a3 100644 (file)
@@ -14,7 +14,10 @@ namespace TYPO3\CMS\Core\Resource\Processing;
  * The TYPO3 project - inspiring people to share!
  */
 
-use \TYPO3\CMS\Core\Resource, \TYPO3\CMS\Core\Utility;
+use TYPO3\CMS\Core\Resource\File;
+use TYPO3\CMS\Core\Utility\CommandUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
  * Helper for creating local image previews using TYPO3s image processing classes.
@@ -49,26 +52,26 @@ class LocalPreviewHelper {
 
                        // Merge custom configuration with default configuration
                $configuration = array_merge(array('width' => 64, 'height' => 64), $task->getConfiguration());
-               $configuration['width'] = Utility\MathUtility::forceIntegerInRange($configuration['width'], 1);
-               $configuration['height'] = Utility\MathUtility::forceIntegerInRange($configuration['height'], 1);
+               $configuration['width'] = MathUtility::forceIntegerInRange($configuration['width'], 1);
+               $configuration['height'] = MathUtility::forceIntegerInRange($configuration['height'], 1);
 
                $originalFileName = $sourceFile->getForLocalProcessing(FALSE);
 
                        // Create a temporaryFile
-               $temporaryFileName = Utility\GeneralUtility::tempnam('preview_', '.' . $task->getTargetFileExtension());
+               $temporaryFileName = GeneralUtility::tempnam('preview_', '.' . $task->getTargetFileExtension());
                        // Check file extension
-               if ($sourceFile->getType() != Resource\File::FILETYPE_IMAGE &&
-                       !Utility\GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $sourceFile->getExtension())) {
+               if ($sourceFile->getType() != File::FILETYPE_IMAGE &&
+                       !GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $sourceFile->getExtension())) {
                                // Create a default image
                        $this->processor->getTemporaryImageWithText($temporaryFileName, 'Not imagefile!', 'No ext!', $sourceFile->getName());
                } else {
                                // Create the temporary file
                        if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
                                $parameters = '-sample ' . $configuration['width'] . 'x' . $configuration['height'] . ' '
-                                       . $this->processor->wrapFileName($originalFileName) . '[0] ' . $this->processor->wrapFileName($temporaryFileName);
+                                       . CommandUtility::escapeShellArgument($originalFileName) . '[0] ' . CommandUtility::escapeShellArgument($temporaryFileName);
 
-                               $cmd = Utility\GeneralUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
-                               Utility\CommandUtility::exec($cmd);
+                               $cmd = GeneralUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
+                               CommandUtility::exec($cmd);
 
                                if (!file_exists($temporaryFileName)) {
                                                // Create a error gif
index e4166b3..ccdcea1 100644 (file)
@@ -111,12 +111,12 @@ class CommandUtility {
                // Compile the path & command
                if ($im_version === 'gm') {
                        $switchCompositeParameters = TRUE;
-                       $path = escapeshellarg(($path . 'gm' . $isExt)) . ' ' . $command;
+                       $path = self::escapeShellArgument($path . 'gm' . $isExt) . ' ' . self::escapeShellArgument($command);
                } else {
                        if ($im_version === 'im6') {
                                $switchCompositeParameters = TRUE;
                        }
-                       $path = escapeshellarg($path . ($command == 'composite' ? 'composite' : $command) . $isExt);
+                       $path = self::escapeShellArgument($path . ($command == 'composite' ? 'composite' : $command) . $isExt);
                }
                // strip profile information for thumbnails and reduce their size
                if ($parameters && $command != 'identify' && $gfxConf['im_useStripProfileByDefault'] && $gfxConf['im_stripProfileCommand'] != '') {
@@ -412,7 +412,6 @@ class CommandUtility {
                return $pathsArr;
        }
 
-
        /**
         * Set a path to the right format
         *
@@ -423,4 +422,39 @@ class CommandUtility {
                return str_replace('//', '/', $path . '/');
        }
 
+       /**
+        * Escape shell arguments (for example filenames) to be used on the local system.
+        *
+        * The setting UTF8filesystem will be taken into account.
+        *
+        * @param string[] $input Input arguments to be escaped
+        * @return string[] Escaped shell arguments
+        */
+       public static function escapeShellArguments(array $input) {
+               $isUTF8Filesystem = !empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']);
+               if ($isUTF8Filesystem) {
+                       $currentLocale = setlocale(LC_CTYPE, 0);
+                       setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
+               }
+
+               $output = array_map('escapeshellarg', $input);
+
+               if ($isUTF8Filesystem) {
+                       setlocale(LC_CTYPE, $currentLocale);
+               }
+
+               return $output;
+       }
+
+       /**
+        * Escape a shell argument (for example a filename) to be used on the local system.
+        *
+        * The setting UTF8filesystem will be taken into account.
+        *
+        * @param string $input Input-argument to be escaped
+        * @return string Escaped shell argument
+        */
+       public static function escapeShellArgument($input) {
+               return self::escapeShellArguments(array($input))[0];
+       }
 }
index 7f95be2..abf3984 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Scheduler;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\CommandUtility;
+
 /**
  * TYPO3 Scheduler. This class handles scheduling and execution of tasks.
  * Formerly known as "Gabriel TYPO3 arch angel"
@@ -420,14 +422,9 @@ class Scheduler implements \TYPO3\CMS\Core\SingletonInterface {
                                $startTime = 'now+1minute';
                        }
                        $cliDispatchPath = PATH_site . 'typo3/cli_dispatch.phpsh';
-                       $currentLocale = setlocale(LC_CTYPE, 0);
-                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                               setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
-                       }
-                       $cmd = 'echo ' . escapeshellarg($cliDispatchPath) . ' scheduler | at ' . escapeshellarg($startTime) . ' 2>&1';
-                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
-                               setlocale(LC_CTYPE, $currentLocale);
-                       }
+                       list($cliDispatchPathEscaped, $startTimeEscaped) =
+                               CommandUtility::escapeShellArguments(array($cliDispatchPath, $startTime));
+                       $cmd = 'echo ' . $cliDispatchPathEscaped . ' scheduler | at ' . $startTimeEscaped . ' 2>&1';
                        $output = shell_exec($cmd);
                        $outputParts = '';
                        foreach (explode(LF, $output) as $outputLine) {