Fixed issue #15601: Change all core PHP files to UTF8 encoding
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_exec.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2002-2010 René Fritz (r.fritz@colorcube.de)
6 * All rights reserved
7 *
8 * This script is part of the Typo3 project. The Typo3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * t3lib_exec finds executables (programs) on Unix and Windows without knowing where they are
26 *
27 * $Id$
28 *
29 * @author René Fritz <r.fritz@colorcube.de>
30 */
31 /**
32 * [CLASS/FUNCTION INDEX of SCRIPT]
33 *
34 *
35 *
36 * 85: class t3lib_exec
37 * 95: function checkCommand($cmd, $handler='')
38 * 166: function getCommand($cmd, $handler='', $handlerOpt='')
39 * 199: function addPaths($paths)
40 * 211: function getPaths($addInvalid=false)
41 * 237: function _init()
42 * 259: function _initPaths($paths='')
43 * 312: function _getConfiguredApps()
44 * 339: function _getPaths()
45 * 400: function _fixPath($path)
46 *
47 * TOTAL FUNCTIONS: 9
48 * (This index is automatically created/updated by the extension "extdeveval")
49 *
50 */
51
52
53
54
55
56 /**
57 * returns exec command for a program
58 * or false
59 *
60 * This class is meant to be used without instance:
61 * $cmd = t3lib_exec::getCommand ('awstats','perl');
62 *
63 * The data of this class is cached.
64 * That means if a program is found once it don't have to be searched again.
65 *
66 * user functions:
67 *
68 * addPaths() could be used to extend the search paths
69 * getCommand() get a command string
70 * checkCommand() returns true if a command is available
71 *
72 * Search paths that are included:
73 * $TYPO3_CONF_VARS['GFX']['im_path_lzw'] or $TYPO3_CONF_VARS['GFX']['im_path']
74 * $TYPO3_CONF_VARS['SYS']['binPath']
75 * $GLOBALS['_SERVER']['PATH']
76 * '/usr/bin/,/usr/local/bin/' on Unix
77 *
78 * binaries can be preconfigured with
79 * $TYPO3_CONF_VARS['SYS']['binSetup']
80 *
81 * @author René Fritz <r.fritz@colorcube.de>
82 * @package TYPO3
83 * @subpackage t3lib
84 */
85 class t3lib_exec {
86
87 /** Tells if object is already initialized */
88 protected static $initialized = FALSE;
89
90 /**
91 * Contains application list. This is an array with the following structure:
92 * - app => file name to the application (like 'tar' or 'bzip2')
93 * - path => full path to the application without application name (like '/usr/bin/' for '/usr/bin/tar')
94 * - valid => true or false
95 * Array key is identical to 'app'.
96 *
97 * @var array
98 */
99 protected static $applications = array();
100
101 /**
102 * Paths where to search for applications
103 *
104 * @var array
105 */
106 protected static $paths = NULL;
107
108 /**
109 * Checks if a command is valid or not, updates global variables
110 *
111 * @param string the command that should be executed. eg: "convert"
112 * @param string executer for the command. eg: "perl"
113 * @return boolean false if cmd is not found, or -1 if the handler is not found
114 */
115 public static function checkCommand($cmd, $handler = '') {
116 if (!self::init()) {
117 return FALSE;
118 }
119
120 if ($handler && !self::checkCommand($handler)) {
121 return -1;
122 }
123 // Already checked and valid
124 if (self::$applications[$cmd]['valid']) {
125 return TRUE;
126 }
127 // Is set but was (above) not true
128 if (isset(self::$applications[$cmd]['valid'])) {
129 return FALSE;
130 }
131
132 foreach (self::$paths as $path => $validPath) {
133 // Ignore invalid (false) paths
134 if ($validPath) {
135 if (TYPO3_OS == 'WIN') {
136 // Windows OS
137 // TODO Why is_executable() is not called here?
138 if (@is_file($path . $cmd)) {
139 self::$applications[$cmd]['app'] = $cmd;
140 self::$applications[$cmd]['path'] = $path;
141 self::$applications[$cmd]['valid'] = TRUE;
142 return TRUE;
143 }
144 if (@is_file($path . $cmd . '.exe')) {
145 self::$applications[$cmd]['app'] = $cmd . '.exe';
146 self::$applications[$cmd]['path'] = $path;
147 self::$applications[$cmd]['valid'] = TRUE;
148 return TRUE;
149 }
150 } else {
151 // Unix-like OS
152 $filePath = realpath($path . $cmd);
153 if ($filePath && @is_executable($filePath)) {
154 self::$applications[$cmd]['app'] = $cmd;
155 self::$applications[$cmd]['path'] = $path;
156 self::$applications[$cmd]['valid'] = TRUE;
157 return TRUE;
158 }
159 }
160 }
161 }
162
163 // Try to get the executable with the command 'which'.
164 // It does the same like already done, but maybe on other paths
165 if (TYPO3_OS != 'WIN') {
166 $cmd = @exec('which ' . $cmd);
167 if (@is_executable($cmd)) {
168 self::$applications[$cmd]['app'] = $cmd;
169 self::$applications[$cmd]['path'] = dirname($cmd) . '/';
170 self::$applications[$cmd]['valid'] = TRUE;
171 return TRUE;
172 }
173 }
174
175 return FALSE;
176 }
177
178
179 /**
180 * Returns a command string for exec(), system()
181 *
182 * @param string the command that should be executed. eg: "convert"
183 * @param string handler (executor) for the command. eg: "perl"
184 * @param string options for the handler, like '-w' for "perl"
185 * @return mixed returns command string, or false if cmd is not found, or -1 if the handler is not found
186 */
187 public static function getCommand($cmd, $handler = '', $handlerOpt = '') {
188 if (!self::init()) {
189 return FALSE;
190 }
191
192 // handler
193 if ($handler) {
194 $handler = self::getCommand($handler);
195
196 if (!$handler) {
197 return -1;
198 }
199 $handler .= ' ' . $handlerOpt . ' ';
200 }
201
202 // command
203 if (!self::checkCommand($cmd)) {
204 return FALSE;
205 }
206 $cmd = self::$applications[$cmd]['path'] . self::$applications[$cmd]['app'] . ' ';
207
208 return trim($handler . $cmd);
209 }
210
211
212 /**
213 * Extend the preset paths. This way an extension can install an executable and provide the path to t3lib_exec.
214 *
215 * @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).
216 * @return void
217 */
218 public static function addPaths($paths) {
219 self::initPaths($paths);
220 }
221
222
223 /**
224 * Returns an array of search paths
225 *
226 * @param boolean If set the array contains invalid path too. Then the key is the path and the value is empty
227 * @return array Array of search paths (empty if exec is disabled)
228 */
229 public static function getPaths($addInvalid = FALSE) {
230 if (!self::init()) {
231 return array();
232 }
233
234 $paths = self::$paths;
235
236 if (!$addInvalid) {
237 foreach ($paths as $path => $validPath) {
238 if (!$validPath) {
239 unset($paths[$path]);
240 }
241 }
242 }
243 return $paths;
244 }
245
246
247 /**
248 * Initializes this class
249 *
250 * @return void
251 */
252 protected static function init() {
253 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['disable_exec_function']) {
254 return FALSE;
255 }
256 if (!self::$initialized) {
257 self::initPaths();
258 self::$applications = self::getConfiguredApps();
259 self::$initialized = TRUE;
260 }
261 return TRUE;
262 }
263
264
265 /**
266 * Initializes and extends the preset paths with own
267 *
268 * @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).
269 * @return void
270 */
271 protected static function initPaths($paths = '') {
272 $doCheck = FALSE;
273
274 // init global paths array if not already done
275 if (!is_array(self::$paths)) {
276 self::$paths = self::getPathsInternal();
277 $doCheck = TRUE;
278 }
279 // merge the submitted paths array to the global
280 if ($paths) {
281 $paths = t3lib_div::trimExplode(',', $paths, 1);
282 if (is_array($paths)) {
283 foreach ($paths as $path) {
284 // make absolute path of relative
285 if (!preg_match('#^/#', $path)) {
286 $path = PATH_site . $path;
287 }
288 if (!isset(self::$paths[$path])) {
289 if (@is_dir($path)) {
290 self::$paths[$path] = $path;
291 } else {
292 self::$paths[$path] = FALSE;
293 }
294 }
295 }
296 }
297 }
298 // check if new paths are invalid
299 if ($doCheck) {
300 foreach (self::$paths as $path => $valid) {
301 // ignore invalid (false) paths
302 if ($valid AND !@is_dir($path)) {
303 self::$paths[$path] = FALSE;
304 }
305 }
306 }
307 }
308
309
310 /**
311 * Processes and returns the paths from $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']
312 *
313 * @return array Array of commands and path
314 */
315 protected static function getConfiguredApps() {
316 $cmdArr = array();
317
318 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']) {
319 $pathSetup = preg_split('/[\n,]+/', $GLOBALS['TYPO3_CONF_VARS']['SYS']['binSetup']);
320 foreach ($pathSetup as $val) {
321 list($cmd, $cmdPath) = t3lib_div::trimExplode('=', $val, 1);
322 $cmdArr[$cmd]['app'] = basename($cmdPath);
323 $cmdArr[$cmd]['path'] = dirname($cmdPath) . '/';
324 $cmdArr[$cmd]['valid'] = TRUE;
325 }
326 }
327
328 return $cmdArr;
329 }
330
331
332 /**
333 * Sets the search paths from different sources, internal
334 *
335 * @return array Array of absolute paths (keys and values are equal)
336 */
337 protected static function getPathsInternal() {
338
339 $pathsArr = array();
340 $sysPathArr = array();
341
342 // image magick paths first
343 // im_path_lzw take precedence over im_path
344 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']))) {
345 $imPath = self::fixPath($imPath);
346 $pathsArr[$imPath] = $imPath;
347 }
348
349 // add configured paths
350 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['binPath']) {
351 $sysPath = t3lib_div::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['binPath'], 1);
352 foreach ($sysPath as $val) {
353 $val = self::fixPath($val);
354 $sysPathArr[$val] = $val;
355 }
356 }
357
358
359 // add path from environment
360 // TODO: how does this work for WIN
361 if ($GLOBALS['_SERVER']['PATH']) {
362 $sep = (TYPO3_OS == 'WIN' ? ';' : ':');
363 $envPath = t3lib_div::trimExplode($sep, $GLOBALS['_SERVER']['PATH'], 1);
364 foreach ($envPath as $val) {
365 $val = self::fixPath($val);
366 $sysPathArr[$val] = $val;
367 }
368 }
369
370 // Set common paths for Unix (only)
371 if (TYPO3_OS !== 'WIN') {
372 $sysPathArr = array_merge($sysPathArr, array(
373 '/usr/bin/' => '/usr/bin/',
374 '/usr/local/bin/' => '/usr/local/bin/',
375 ));
376 }
377
378 $pathsArr = array_merge($pathsArr, $sysPathArr);
379
380 return $pathsArr;
381 }
382
383
384 /**
385 * Set a path to the right format
386 *
387 * @param string Input path
388 * @return string Output path
389 */
390 protected static function fixPath($path) {
391 return str_replace('//', '/', $path . '/');
392 }
393 }
394
395 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php']) {
396 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php']);
397 }
398 ?>