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