TYPO3 API  SVNRelease
class.t3lib_exec.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 2002-2011 René Fritz (r.fritz@colorcube.de)
00006  *  All rights reserved
00007  *
00008  *  This script is part of the Typo3 project. The Typo3 project is
00009  *  free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  The GNU General Public License can be found at
00015  *  http://www.gnu.org/copyleft/gpl.html.
00016  *
00017  *  This script is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU General Public License for more details.
00021  *
00022  *  This copyright notice MUST APPEAR in all copies of the script!
00023  ***************************************************************/
00024 /**
00025  * t3lib_exec finds executables (programs) on Unix and Windows without knowing where they are
00026  *
00027  * $Id: class.t3lib_exec.php 10121 2011-01-18 20:15:30Z ohader $
00028  *
00029  * @author  René Fritz <r.fritz@colorcube.de>
00030  */
00031 /**
00032  * [CLASS/FUNCTION INDEX of SCRIPT]
00033  *
00034  *
00035  *
00036  *   85: class t3lib_exec
00037  *   95:     function checkCommand($cmd, $handler='')
00038  *  166:     function getCommand($cmd, $handler='', $handlerOpt='')
00039  *  199:     function addPaths($paths)
00040  *  211:     function getPaths($addInvalid=false)
00041  *  237:     function _init()
00042  *  259:     function _initPaths($paths='')
00043  *  312:     function _getConfiguredApps()
00044  *  339:     function _getPaths()
00045  *  400:     function _fixPath($path)
00046  *
00047  * TOTAL FUNCTIONS: 9
00048  * (This index is automatically created/updated by the extension "extdeveval")
00049  *
00050  */
00051 
00052 
00053 /**
00054  * returns exec command for a program
00055  * or false
00056  *
00057  * This class is meant to be used without instance:
00058  * $cmd = t3lib_exec::getCommand ('awstats','perl');
00059  *
00060  * The data of this class is cached.
00061  * That means if a program is found once it don't have to be searched again.
00062  *
00063  * user functions:
00064  *
00065  * addPaths() could be used to extend the search paths
00066  * getCommand() get a command string
00067  * checkCommand() returns true if a command is available
00068  *
00069  * Search paths that are included:
00070  * $TYPO3_CONF_VARS['GFX']['im_path_lzw'] or $TYPO3_CONF_VARS['GFX']['im_path']
00071  * $TYPO3_CONF_VARS['SYS']['binPath']
00072  * $GLOBALS['_SERVER']['PATH']
00073  * '/usr/bin/,/usr/local/bin/' on Unix
00074  *
00075  * binaries can be preconfigured with
00076  * $TYPO3_CONF_VARS['SYS']['binSetup']
00077  *
00078  * @author      René Fritz <r.fritz@colorcube.de>
00079  * @package     TYPO3
00080  * @subpackage  t3lib
00081  */
00082 class t3lib_exec {
00083 
00084     /** Tells if object is already initialized */
00085     protected static $initialized = FALSE;
00086 
00087     /**
00088      * Contains application list. This is an array with the following structure:
00089      * - app => file name to the application (like 'tar' or 'bzip2')
00090      * - path => full path to the application without application name (like '/usr/bin/' for '/usr/bin/tar')
00091      * - valid => true or false
00092      * Array key is identical to 'app'.
00093      *
00094      * @var array
00095      */
00096     protected static $applications = array();
00097 
00098     /**
00099      * Paths where to search for applications
00100      *
00101      * @var array
00102      */
00103     protected static $paths = NULL;
00104 
00105     /**
00106      * Checks if a command is valid or not, updates global variables
00107      *
00108      * @param   string      the command that should be executed. eg: "convert"
00109      * @param   string      executer for the command. eg: "perl"
00110      * @return  boolean     false if cmd is not found, or -1 if the handler is not found
00111      */
00112     public static function checkCommand($cmd, $handler = '') {
00113         if (!self::init()) {
00114             return FALSE;
00115         }
00116 
00117         if ($handler && !self::checkCommand($handler)) {
00118             return -1;
00119         }
00120             // Already checked and valid
00121         if (self::$applications[$cmd]['valid']) {
00122             return TRUE;
00123         }
00124             // Is set but was (above) not true
00125         if (isset(self::$applications[$cmd]['valid'])) {
00126             return FALSE;
00127         }
00128 
00129         foreach (self::$paths as $path => $validPath) {
00130                 // Ignore invalid (false) paths
00131             if ($validPath) {
00132                 if (TYPO3_OS == 'WIN') {
00133                         // Windows OS
00134                         // TODO Why is_executable() is not called here?
00135                     if (@is_file($path . $cmd)) {
00136                         self::$applications[$cmd]['app'] = $cmd;
00137                         self::$applications[$cmd]['path'] = $path;
00138                         self::$applications[$cmd]['valid'] = TRUE;
00139                         return TRUE;
00140                     }
00141                     if (@is_file($path . $cmd . '.exe')) {
00142                         self::$applications[$cmd]['app'] = $cmd . '.exe';
00143                         self::$applications[$cmd]['path'] = $path;
00144                         self::$applications[$cmd]['valid'] = TRUE;
00145                         return TRUE;
00146                     }
00147                 } else {
00148                         // Unix-like OS
00149                     $filePath = realpath($path . $cmd);
00150                     if ($filePath && @is_executable($filePath)) {
00151                         self::$applications[$cmd]['app'] = $cmd;
00152                         self::$applications[$cmd]['path'] = $path;
00153                         self::$applications[$cmd]['valid'] = TRUE;
00154                         return TRUE;
00155                     }
00156                 }
00157             }
00158         }
00159 
00160             // Try to get the executable with the command 'which'.
00161             // It does the same like already done, but maybe on other paths
00162         if (TYPO3_OS != 'WIN') {
00163             $cmd = @t3lib_utility_Command::exec('which ' . $cmd);
00164             if (@is_executable($cmd)) {
00165                 self::$applications[$cmd]['app'] = $cmd;
00166                 self::$applications[$cmd]['path'] = dirname($cmd) . '/';
00167                 self::$applications[$cmd]['valid'] = TRUE;
00168                 return TRUE;
00169             }
00170         }
00171 
00172         return FALSE;
00173     }
00174 
00175 
00176     /**
00177      * Returns a command string for exec(), system()
00178      *
00179      * @param   string      the command that should be executed. eg: "convert"
00180      * @param   string      handler (executor) for the command. eg: "perl"
00181      * @param   string      options for the handler, like '-w' for "perl"
00182      * @return  mixed       returns command string, or false if cmd is not found, or -1 if the handler is not found
00183      */
00184     public static function getCommand($cmd, $handler = '', $handlerOpt = '') {
00185         if (!self::init()) {
00186             return FALSE;
00187         }
00188 
00189             // handler
00190         if ($handler) {
00191             $handler = self::getCommand($handler);
00192 
00193             if (!$handler) {
00194                 return -1;
00195             }
00196             $handler .= ' ' . $handlerOpt . ' ';
00197         }
00198 
00199             // command
00200         if (!self::checkCommand($cmd)) {
00201             return FALSE;
00202         }
00203         $cmd = self::$applications[$cmd]['path'] . self::$applications[$cmd]['app'] . ' ';
00204 
00205         return trim($handler . $cmd);
00206     }
00207 
00208 
00209     /**
00210      * Extend the preset paths. This way an extension can install an executable and provide the path to t3lib_exec.
00211      *
00212      * @param   string      comma separated list of extra paths where a command should be searched. Relative paths (without leading "/") are prepend with site root path (PATH_site).
00213      * @return  void
00214      */
00215     public static function addPaths($paths) {
00216         self::initPaths($paths);
00217     }
00218 
00219 
00220     /**
00221      * Returns an array of search paths
00222      *
00223      * @param   boolean     If set the array contains invalid path too. Then the key is the path and the value is empty
00224      * @return  array       Array of search paths (empty if exec is disabled)
00225      */
00226     public static function getPaths($addInvalid = FALSE) {
00227         if (!self::init()) {
00228             return array();
00229         }
00230 
00231         $paths = self::$paths;
00232 
00233         if (!$addInvalid) {
00234             foreach ($paths as $path => $validPath) {
00235                 if (!$validPath) {
00236                     unset($paths[$path]);
00237                 }
00238             }
00239         }
00240         return $paths;
00241     }
00242 
00243 
00244     /**
00245      * Initializes this class
00246      *
00247      * @return  void
00248      */
00249     protected static function init() {
00250         if ($GLOBALS['TYPO3_CONF_VARS']['BE']['disable_exec_function']) {
00251             return FALSE;
00252         }
00253         if (!self::$initialized) {
00254             self::initPaths();
00255             self::$applications = self::getConfiguredApps();
00256             self::$initialized = TRUE;
00257         }
00258         return TRUE;
00259     }
00260 
00261 
00262     /**
00263      * Initializes and extends the preset paths with own
00264      *
00265      * @param   string      Comma seperated list of extra paths where a command should be searched. Relative paths (without leading "/") are prepend with site root path (PATH_site).
00266      * @return  void
00267      */
00268     protected static function initPaths($paths = '') {
00269         $doCheck = FALSE;
00270 
00271             // init global paths array if not already done
00272         if (!is_array(self::$paths)) {
00273             self::$paths = self::getPathsInternal();
00274             $doCheck = TRUE;
00275         }
00276             // merge the submitted paths array to the global
00277         if ($paths) {
00278             $paths = t3lib_div::trimExplode(',', $paths, 1);
00279             if (is_array($paths)) {
00280                 foreach ($paths as $path) {
00281                         // make absolute path of relative
00282                     if (!preg_match('#^/#', $path)) {
00283                         $path = PATH_site . $path;
00284                     }
00285                     if (!isset(self::$paths[$path])) {
00286                         if (@is_dir($path)) {
00287                             self::$paths[$path] = $path;
00288                         } else {
00289                             self::$paths[$path] = FALSE;
00290                         }
00291                     }
00292                 }
00293             }
00294         }
00295             // check if new paths are invalid
00296         if ($doCheck) {
00297             foreach (self::$paths as $path => $valid) {
00298                     // ignore invalid (false) paths
00299                 if ($valid AND !@is_dir($path)) {
00300                     self::$paths[$path] = FALSE;
00301                 }
00302             }
00303         }
00304     }
00305 
00306 
00307     /**
00308      * Processes and returns the paths from $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']
00309      *
00310      * @return  array   Array of commands and path
00311      */
00312     protected static function getConfiguredApps() {
00313         $cmdArr = array();
00314 
00315         if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']) {
00316             $pathSetup = preg_split('/[\n,]+/', $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']);
00317             foreach ($pathSetup as $val) {
00318                 list($cmd, $cmdPath) = t3lib_div::trimExplode('=', $val, 1);
00319                 $cmdArr[$cmd]['app'] = basename($cmdPath);
00320                 $cmdArr[$cmd]['path'] = dirname($cmdPath) . '/';
00321                 $cmdArr[$cmd]['valid'] = TRUE;
00322             }
00323         }
00324 
00325         return $cmdArr;
00326     }
00327 
00328 
00329     /**
00330      * Sets the search paths from different sources, internal
00331      *
00332      * @return  array       Array of absolute paths (keys and values are equal)
00333      */
00334     protected static function getPathsInternal() {
00335 
00336         $pathsArr = array();
00337         $sysPathArr = array();
00338 
00339             // image magick paths first
00340             // im_path_lzw take precedence over im_path
00341         if (($imPath = ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'] ? $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'] : $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']))) {
00342             $imPath = self::fixPath($imPath);
00343             $pathsArr[$imPath] = $imPath;
00344         }
00345 
00346             // add configured paths
00347         if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['binPath']) {
00348             $sysPath = t3lib_div::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['binPath'], 1);
00349             foreach ($sysPath as $val) {
00350                 $val = self::fixPath($val);
00351                 $sysPathArr[$val] = $val;
00352             }
00353         }
00354 
00355 
00356             // add path from environment
00357             // TODO: how does this work for WIN
00358         if ($GLOBALS['_SERVER']['PATH']) {
00359             $sep = (TYPO3_OS == 'WIN' ? ';' : ':');
00360             $envPath = t3lib_div::trimExplode($sep, $GLOBALS['_SERVER']['PATH'], 1);
00361             foreach ($envPath as $val) {
00362                 $val = self::fixPath($val);
00363                 $sysPathArr[$val] = $val;
00364             }
00365         }
00366 
00367             // Set common paths for Unix (only)
00368         if (TYPO3_OS !== 'WIN') {
00369             $sysPathArr = array_merge($sysPathArr, array(
00370                 '/usr/bin/' => '/usr/bin/',
00371                 '/usr/local/bin/' => '/usr/local/bin/',
00372             ));
00373         }
00374 
00375         $pathsArr = array_merge($pathsArr, $sysPathArr);
00376 
00377         return $pathsArr;
00378     }
00379 
00380 
00381     /**
00382      * Set a path to the right format
00383      *
00384      * @param   string      Input path
00385      * @return  string      Output path
00386      */
00387     protected static function fixPath($path) {
00388         return str_replace('//', '/', $path . '/');
00389     }
00390 }
00391 
00392 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php'])) {
00393     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php']);
00394 }
00395 ?>