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