Initial revision
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_exec.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2002-2003 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 find executables (programs) on unix and windows without knowing where they are
26 *
27 * @author René Fritz <r.fritz@colorcube.de>
28 * @package TYPO3
29 * @subpackage t3lib
30 */
31
32 #require_once(t3lib_extMgm::extPath('cc_debug').'class.tx_ccdebug.php');
33
34 /**
35 * returns exec command for a program
36 * or false
37 *
38 * This class is meant to be used without instance:
39 * $cmd = t3lib_exec::getCommand ('awstats','perl');
40 *
41 * The data of this class is hold in a global variable. Doing it this way the setup is cached.
42 * That means if a program is found once it don't have to be searched again.
43 *
44 * user functions:
45 *
46 * addPaths() could be used to extend the search paths
47 * getCommand() get a command string
48 * checkCommand() returns true if a command is available
49 *
50 * Search paths that are included:
51 * $TYPO3_CONF_VARS['GFX']['im_path_lzw'] or $TYPO3_CONF_VARS['GFX']['im_path']
52 * $TYPO3_CONF_VARS['SYS']['binPath']
53 * $GLOBALS['_SERVER']['PATH']
54 * '/usr/bin/,/usr/local/bin/' on Unix
55 *
56 * @author René Fritz <r.fritz@colorcube.de>
57 */
58 class t3lib_exec {
59
60
61
62 /**
63 * checks if a command is valid or not
64 * updates global vars
65 *
66 * @param string the command that should be executed. eg: "convert"
67 * @param string executer for the command. eg: "perl"
68 * @return boolean -1 if cmd is not found, or -2 if the handler is not found
69 */
70 function checkCommand($cmd, $handler='') {
71
72 t3lib_exec::_init();
73 $osType = t3lib_exec::_getOS();
74
75
76 #debug($GLOBALS['t3lib_exec'], 't3lib_exec', __LINE__, __FILE__);
77
78 if ($handler && !t3lib_exec::checkCommand($handler)) {
79 return -2;
80 }
81 // already checked and valid
82 if ($GLOBALS['t3lib_exec']['apps'][$cmd]['valid']) {
83 return true;
84 }
85 // is set but was (above) not true
86 if (isset($GLOBALS['t3lib_exec']['apps'][$cmd]['valid'])) {
87 return false;
88 }
89
90 reset($GLOBALS['t3lib_exec']['paths']);
91 while(list($path,$validPath)=each($GLOBALS['t3lib_exec']['paths'])) {
92 // ignore invalid (false) paths
93 if ($validPath) {
94 if ($osType=='WIN') {
95 if (@is_file($path.$cmd)) {
96 $GLOBALS['t3lib_exec']['apps'][$cmd]['app'] = $cmd;
97 $GLOBALS['t3lib_exec']['apps'][$cmd]['path'] = $path;
98 $GLOBALS['t3lib_exec']['apps'][$cmd]['valid'] = true;
99 return true;
100 }
101 if (@is_file($path.$cmd.'.exe')) {
102 $GLOBALS['t3lib_exec']['apps'][$cmd]['app'] = $cmd.'.exe';
103 $GLOBALS['t3lib_exec']['apps'][$cmd]['path'] = $path;
104 $GLOBALS['t3lib_exec']['apps'][$cmd]['valid'] = true;
105 return true;
106 }
107 } else { // UNIX
108 if (@is_executable($path.$cmd)) {
109 $GLOBALS['t3lib_exec']['apps'][$cmd]['app'] = $cmd;
110 $GLOBALS['t3lib_exec']['apps'][$cmd]['path'] = $path;
111 $GLOBALS['t3lib_exec']['apps'][$cmd]['valid'] = true;
112 return true;
113 }
114 }
115 }
116 }
117
118 // try to get the executable with the command 'which'. It do the same like already done, but that on other paths??
119 if ($osType=='UNIX') {
120 $cmd = exec ('which '.$val['cmd']);
121
122 if (@is_executable($cmd)) {
123 $GLOBALS['t3lib_exec']['apps'][$cmd]['app'] = $cmd;
124 $GLOBALS['t3lib_exec']['apps'][$cmd]['path'] = dirname($cmd).'/';
125 $GLOBALS['t3lib_exec']['apps'][$cmd]['valid'] = true;
126 return true;
127 }
128 }
129
130 return -1;
131 }
132
133
134 /**
135 * returns a command string for exec(), system()
136 *
137 *
138 * @param string the command that should be executed. eg: "convert"
139 * @param string handler (executor) for the command. eg: "perl"
140 * @param string options for the handler, like '-w' for "perl"
141 * @return mixed returns command string, or -1 if cmd is not found, or -2 if the handler is not found
142 */
143 function getCommand($cmd, $handler='', $handlerOpt='') {
144
145 t3lib_exec::_init();
146
147 // handler
148 if ($handler) {
149 $handler = t3lib_exec::getCommand($handler);
150
151 if (!$handler) {
152 return -2;
153 }
154 $handler .= ' '.$handlerOpt.' ';
155 }
156
157 // command
158 if (!t3lib_exec::checkCommand($cmd)) {
159 return -1;
160 }
161 $cmd = $GLOBALS['t3lib_exec']['apps'][$cmd]['path'].$GLOBALS['t3lib_exec']['apps'][$cmd]['app'].' ';
162
163 return $handler.$cmd;
164 }
165
166
167
168
169 /**
170 * Extend the preset paths. This way an extension can install an axecutable and provide the path to t3lib_exec.
171 *
172 * @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).
173 */
174 function addPaths($paths) {
175 t3lib_exec::_initPaths($paths);
176 }
177
178
179
180
181
182
183
184 /**
185 * set the search paths from different sources
186 * @internal
187 */
188 function _getPaths() {
189 global $TYPO3_CONF_VARS;
190
191 $pathsArr = array();
192 $sysPathArr = array();
193 $osType = t3lib_exec::_getOS();
194
195 // image magick paths first
196 // im_path_lzw take precedence over im_path
197 if ($imPath = ($TYPO3_CONF_VARS['GFX']['im_path_lzw'] ? $TYPO3_CONF_VARS['GFX']['im_path_lzw'] : $TYPO3_CONF_VARS['GFX']['im_path'])) {
198 $imPath = t3lib_exec::_fixPath($imPath);
199 $pathsArr[$imPath] = $imPath;
200 }
201
202 // add configured paths
203 if ($TYPO3_CONF_VARS['SYS']['binPath']) {
204 $sysPath = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['SYS']['binPath'],1);
205 reset($sysPath);
206 while(list(,$val)=each($sysPath)) {
207 $val = t3lib_exec::_fixPath($val);
208 $sysPathArr[$val]=$val;
209 }
210 }
211
212
213
214
215 # ???? t3lib_div::getIndpEnv('REQUEST_URI');
216
217
218 // add path from environment
219 #TODO: how does this work for WIN
220 if ($GLOBALS['_SERVER']['PATH']) {
221 $sep = ($osType=='WIN') ? ';' : ':';
222 $envPath = t3lib_div::trimExplode($sep,$GLOBALS['_SERVER']['PATH'],1);
223 reset($envPath);
224 while(list(,$val)=each($envPath)) {
225 $val = t3lib_exec::_fixPath($val);
226 $sysPathArr[$val]=$val;
227 }
228 }
229
230 if ($osType=='WIN') {
231 #TODO: add the most common paths for WIN
232 $sysPathArr = array_merge($sysPathArr, array (
233 '/usr/bin/' => '/usr/bin/',
234 '/perl/bin/' => '/perl/bin/',
235 ));
236 } else { // UNIX
237 $sysPathArr = array_merge($sysPathArr, array (
238 '/usr/bin/' => '/usr/bin/',
239 '/usr/local/bin/' => '/usr/local/bin/',
240 ));
241 }
242
243 #debug($pathsArr, '$pathsArr', __LINE__, __FILE__);
244 #debug($GLOBALS['_SERVER']['PATH'], 'PATH', __LINE__, __FILE__);
245
246 $pathsArr = array_merge($pathsArr, $sysPathArr);
247 return $pathsArr;
248 }
249
250
251 /**
252 * init
253 * @internal
254 */
255 function _init() {
256 if (!$GLOBALS['t3lib_exec']['init']) {
257
258 t3lib_exec::_initPaths();
259 $GLOBALS['t3lib_exec']['apps'] = array();
260 $GLOBALS['t3lib_exec']['init'] = true;
261 }
262 }
263
264
265 /**
266 * init and extend the preset paths with own
267 *
268 * @internal
269 * @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).
270 */
271 function _initPaths($paths='') {
272 $doCeck=false;
273
274 // init global paths array if not already done
275 if (!is_array($GLOBALS['t3lib_exec']['paths'])) {
276 $GLOBALS['t3lib_exec']['paths'] = t3lib_exec::_getPaths();
277 $doCeck=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 reset($paths);
284 while(list(,$path)=each($paths)) {
285 // make absolute path of relative
286 if (!preg_match('#^/#',$path)) {
287 $path = PATH_site.$path;
288 }
289 if (!isset($GLOBALS['t3lib_exec']['paths'][$path])) {
290 if (@is_dir($path)) {
291 $GLOBALS['t3lib_exec']['paths'][$path] = $path;
292 $GLOBALS['t3lib_exec']['allPaths'].=','.$path;
293 // $doCeck=true; just done
294 } else {
295 $GLOBALS['t3lib_exec']['paths'][$path] = false;
296 }
297 }
298 }
299 }
300 }
301 // check if new paths are invalid
302 if ($doCeck) {
303 $GLOBALS['t3lib_exec']['allPaths']='';
304 reset($GLOBALS['t3lib_exec']['paths']);
305 while(list($path,$valid)=each($GLOBALS['t3lib_exec']['paths'])) {
306 // ignore invalid (false) paths
307 #TODO: what's the idea not to remove invalid paths?
308 if ($valid) {
309 if (!@is_dir($path)) {
310 $GLOBALS['t3lib_exec']['paths'][$path] = false;
311 }
312 }
313 if ($path = $GLOBALS['t3lib_exec']['paths'][$path]) {
314 $GLOBALS['t3lib_exec']['allPaths'].=','.$path;
315 }
316 }
317 }
318 }
319
320
321 /**
322 * returns on which OS we're runing
323 *
324 * @return string the OS type: "UNIX" or "WIN"
325 * @internal
326 */
327 function _getOS() {
328 return stristr(PHP_OS,'win')&&!stristr(PHP_OS,'darwin')?"WIN":"UNIX";
329 }
330
331 /**
332 * set a path to the right format
333 * @internal
334 * @param string path
335 * @return string path
336 */
337 function _fixPath($path) {
338 return str_replace ('//',"/",$path.'/');
339 }
340
341 }
342
343
344 // Include extension?
345 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php']) {
346 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_exec.php']);
347 }
348
349
350 ?>
351
352