Редакция 68 | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 68 | Редакция 87 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | /**
|
2 | /**
|
3 | * File/Directory manipulation
|
3 | * File/Directory manipulation
|
4 | *
|
4 | *
|
5 | * PHP versions 4 and 5
|
5 | * PHP versions 4 and 5
|
6 | *
|
6 | *
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
8 | * that is available through the world-wide-web at the following URI:
|
8 | * that is available through the world-wide-web at the following URI:
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
10 | * the PHP License and are unable to obtain it through the web, please
|
10 | * the PHP License and are unable to obtain it through the web, please
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
12 | *
|
12 | *
|
13 | * @category pear
|
13 | * @category pear
|
14 | * @package System
|
14 | * @package System
|
15 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
15 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
16 | * @copyright 1997-2008 The PHP Group
|
16 | * @copyright 1997-2008 The PHP Group
|
17 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
17 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
18 | * @version CVS: $Id: System.php,v 1.62 2008/01/03 20:26:34 cellog Exp $
|
18 | * @version CVS: $Id: System.php,v 1.62 2008/01/03 20:26:34 cellog Exp $
|
19 | * @link http://pear.php.net/package/PEAR
|
19 | * @link http://pear.php.net/package/PEAR
|
20 | * @since File available since Release 0.1
|
20 | * @since File available since Release 0.1
|
21 | */
|
21 | */
|
22 | 22 | ||
23 | /**
|
23 | /**
|
24 | * base class
|
24 | * base class
|
25 | */
|
25 | */
|
26 | require_once 'PEAR.php'; |
26 | require_once 'PEAR.php'; |
27 | require_once 'Console/Getopt.php'; |
27 | require_once 'Console/Getopt.php'; |
28 | 28 | ||
29 | $GLOBALS['_System_temp_files'] = array(); |
29 | $GLOBALS['_System_temp_files'] = array(); |
30 | 30 | ||
31 | /**
|
31 | /**
|
32 | * System offers cross plattform compatible system functions
|
32 | * System offers cross plattform compatible system functions
|
33 | *
|
33 | *
|
34 | * Static functions for different operations. Should work under
|
34 | * Static functions for different operations. Should work under
|
35 | * Unix and Windows. The names and usage has been taken from its respectively
|
35 | * Unix and Windows. The names and usage has been taken from its respectively
|
36 | * GNU commands. The functions will return (bool) false on error and will
|
36 | * GNU commands. The functions will return (bool) false on error and will
|
37 | * trigger the error with the PHP trigger_error() function (you can silence
|
37 | * trigger the error with the PHP trigger_error() function (you can silence
|
38 | * the error by prefixing a '@' sign after the function call, but this
|
38 | * the error by prefixing a '@' sign after the function call, but this
|
39 | * is not recommended practice. Instead use an error handler with
|
39 | * is not recommended practice. Instead use an error handler with
|
40 | * {@link set_error_handler()}).
|
40 | * {@link set_error_handler()}).
|
41 | *
|
41 | *
|
42 | * Documentation on this class you can find in:
|
42 | * Documentation on this class you can find in:
|
43 | * http://pear.php.net/manual/
|
43 | * http://pear.php.net/manual/
|
44 | *
|
44 | *
|
45 | * Example usage:
|
45 | * Example usage:
|
46 | * if (!@System::rm('-r file1 dir1')) {
|
46 | * if (!@System::rm('-r file1 dir1')) {
|
47 | * print "could not delete file1 or dir1";
|
47 | * print "could not delete file1 or dir1";
|
48 | * }
|
48 | * }
|
49 | *
|
49 | *
|
50 | * In case you need to to pass file names with spaces,
|
50 | * In case you need to to pass file names with spaces,
|
51 | * pass the params as an array:
|
51 | * pass the params as an array:
|
52 | *
|
52 | *
|
53 | * System::rm(array('-r', $file1, $dir1));
|
53 | * System::rm(array('-r', $file1, $dir1));
|
54 | *
|
54 | *
|
55 | * @category pear
|
55 | * @category pear
|
56 | * @package System
|
56 | * @package System
|
57 | * @author Tomas V.V. Cox <cox@idecnet.com>
|
57 | * @author Tomas V.V. Cox <cox@idecnet.com>
|
58 | * @copyright 1997-2006 The PHP Group
|
58 | * @copyright 1997-2006 The PHP Group
|
59 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
59 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
60 | * @version Release: 1.7.2
|
60 | * @version Release: 1.7.2
|
61 | * @link http://pear.php.net/package/PEAR
|
61 | * @link http://pear.php.net/package/PEAR
|
62 | * @since Class available since Release 0.1
|
62 | * @since Class available since Release 0.1
|
63 | * @static
|
63 | * @static
|
64 | */
|
64 | */
|
65 | class System |
65 | class System |
66 | {
|
66 | {
|
67 | /**
|
67 | /**
|
68 | * returns the commandline arguments of a function
|
68 | * returns the commandline arguments of a function
|
69 | *
|
69 | *
|
70 | * @param string $argv the commandline
|
70 | * @param string $argv the commandline
|
71 | * @param string $short_options the allowed option short-tags
|
71 | * @param string $short_options the allowed option short-tags
|
72 | * @param string $long_options the allowed option long-tags
|
72 | * @param string $long_options the allowed option long-tags
|
73 | * @return array the given options and there values
|
73 | * @return array the given options and there values
|
74 | * @static
|
74 | * @static
|
75 | * @access private
|
75 | * @access private
|
76 | */
|
76 | */
|
77 | function _parseArgs($argv, $short_options, $long_options = null) |
77 | function _parseArgs($argv, $short_options, $long_options = null) |
78 | {
|
78 | {
|
79 | if (!is_array($argv) && $argv !== null) { |
79 | if (!is_array($argv) && $argv !== null) { |
80 | $argv = preg_split('/\s+/', $argv, -1, PREG_SPLIT_NO_EMPTY); |
80 | $argv = preg_split('/\s+/', $argv, -1, PREG_SPLIT_NO_EMPTY); |
81 | }
|
81 | }
|
82 | return Console_Getopt::getopt2($argv, $short_options); |
82 | return Console_Getopt::getopt2($argv, $short_options); |
83 | }
|
83 | }
|
84 | 84 | ||
85 | /**
|
85 | /**
|
86 | * Output errors with PHP trigger_error(). You can silence the errors
|
86 | * Output errors with PHP trigger_error(). You can silence the errors
|
87 | * with prefixing a "@" sign to the function call: @System::mkdir(..);
|
87 | * with prefixing a "@" sign to the function call: @System::mkdir(..);
|
88 | *
|
88 | *
|
89 | * @param mixed $error a PEAR error or a string with the error message
|
89 | * @param mixed $error a PEAR error or a string with the error message
|
90 | * @return bool false
|
90 | * @return bool false
|
91 | * @static
|
91 | * @static
|
92 | * @access private
|
92 | * @access private
|
93 | */
|
93 | */
|
94 | function raiseError($error) |
94 | function raiseError($error) |
95 | {
|
95 | {
|
96 | if (PEAR::isError($error)) { |
96 | if (PEAR::isError($error)) { |
97 | $error = $error->getMessage(); |
97 | $error = $error->getMessage(); |
98 | }
|
98 | }
|
99 | trigger_error($error, E_USER_WARNING); |
99 | trigger_error($error, E_USER_WARNING); |
100 | return false; |
100 | return false; |
101 | }
|
101 | }
|
102 | 102 | ||
103 | /**
|
103 | /**
|
104 | * Creates a nested array representing the structure of a directory
|
104 | * Creates a nested array representing the structure of a directory
|
105 | *
|
105 | *
|
106 | * System::_dirToStruct('dir1', 0) =>
|
106 | * System::_dirToStruct('dir1', 0) =>
|
107 | * Array
|
107 | * Array
|
108 | * (
|
108 | * (
|
109 | * [dirs] => Array
|
109 | * [dirs] => Array
|
110 | * (
|
110 | * (
|
111 | * [0] => dir1
|
111 | * [0] => dir1
|
112 | * )
|
112 | * )
|
113 | *
|
113 | *
|
114 | * [files] => Array
|
114 | * [files] => Array
|
115 | * (
|
115 | * (
|
116 | * [0] => dir1/file2
|
116 | * [0] => dir1/file2
|
117 | * [1] => dir1/file3
|
117 | * [1] => dir1/file3
|
118 | * )
|
118 | * )
|
119 | * )
|
119 | * )
|
120 | * @param string $sPath Name of the directory
|
120 | * @param string $sPath Name of the directory
|
121 | * @param integer $maxinst max. deep of the lookup
|
121 | * @param integer $maxinst max. deep of the lookup
|
122 | * @param integer $aktinst starting deep of the lookup
|
122 | * @param integer $aktinst starting deep of the lookup
|
123 | * @param bool $silent if true, do not emit errors.
|
123 | * @param bool $silent if true, do not emit errors.
|
124 | * @return array the structure of the dir
|
124 | * @return array the structure of the dir
|
125 | * @static
|
125 | * @static
|
126 | * @access private
|
126 | * @access private
|
127 | */
|
127 | */
|
128 | 128 | ||
129 | function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) |
129 | function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) |
130 | {
|
130 | {
|
131 | $struct = array('dirs' => array(), 'files' => array()); |
131 | $struct = array('dirs' => array(), 'files' => array()); |
132 | if (($dir = @opendir($sPath)) === false) { |
132 | if (($dir = @opendir($sPath)) === false) { |
133 | if (!$silent) { |
133 | if (!$silent) { |
134 | System::raiseError("Could not open dir $sPath"); |
134 | System::raiseError("Could not open dir $sPath"); |
135 | }
|
135 | }
|
136 | return $struct; // XXX could not open error |
136 | return $struct; // XXX could not open error |
137 | }
|
137 | }
|
138 | $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? |
138 | $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? |
139 | $list = array(); |
139 | $list = array(); |
140 | while (false !== ($file = readdir($dir))) { |
140 | while (false !== ($file = readdir($dir))) { |
141 | if ($file != '.' && $file != '..') { |
141 | if ($file != '.' && $file != '..') { |
142 | $list[] = $file; |
142 | $list[] = $file; |
143 | }
|
143 | }
|
144 | }
|
144 | }
|
145 | closedir($dir); |
145 | closedir($dir); |
146 | sort($list); |
146 | sort($list); |
147 | if ($aktinst < $maxinst || $maxinst == 0) { |
147 | if ($aktinst < $maxinst || $maxinst == 0) { |
148 | foreach ($list as $val) { |
148 | foreach ($list as $val) { |
149 | $path = $sPath . DIRECTORY_SEPARATOR . $val; |
149 | $path = $sPath . DIRECTORY_SEPARATOR . $val; |
150 | if (is_dir($path) && !is_link($path)) { |
150 | if (is_dir($path) && !is_link($path)) { |
151 | $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); |
151 | $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); |
152 | $struct = array_merge_recursive($tmp, $struct); |
152 | $struct = array_merge_recursive($tmp, $struct); |
153 | } else { |
153 | } else { |
154 | $struct['files'][] = $path; |
154 | $struct['files'][] = $path; |
155 | }
|
155 | }
|
156 | }
|
156 | }
|
157 | }
|
157 | }
|
158 | return $struct; |
158 | return $struct; |
159 | }
|
159 | }
|
160 | 160 | ||
161 | /**
|
161 | /**
|
162 | * Creates a nested array representing the structure of a directory and files
|
162 | * Creates a nested array representing the structure of a directory and files
|
163 | *
|
163 | *
|
164 | * @param array $files Array listing files and dirs
|
164 | * @param array $files Array listing files and dirs
|
165 | * @return array
|
165 | * @return array
|
166 | * @static
|
166 | * @static
|
167 | * @see System::_dirToStruct()
|
167 | * @see System::_dirToStruct()
|
168 | */
|
168 | */
|
169 | function _multipleToStruct($files) |
169 | function _multipleToStruct($files) |
170 | {
|
170 | {
|
171 | $struct = array('dirs' => array(), 'files' => array()); |
171 | $struct = array('dirs' => array(), 'files' => array()); |
172 | settype($files, 'array'); |
172 | settype($files, 'array'); |
173 | foreach ($files as $file) { |
173 | foreach ($files as $file) { |
174 | if (is_dir($file) && !is_link($file)) { |
174 | if (is_dir($file) && !is_link($file)) { |
175 | $tmp = System::_dirToStruct($file, 0); |
175 | $tmp = System::_dirToStruct($file, 0); |
176 | $struct = array_merge_recursive($tmp, $struct); |
176 | $struct = array_merge_recursive($tmp, $struct); |
177 | } else { |
177 | } else { |
178 | $struct['files'][] = $file; |
178 | $struct['files'][] = $file; |
179 | }
|
179 | }
|
180 | }
|
180 | }
|
181 | return $struct; |
181 | return $struct; |
182 | }
|
182 | }
|
183 | 183 | ||
184 | /**
|
184 | /**
|
185 | * The rm command for removing files.
|
185 | * The rm command for removing files.
|
186 | * Supports multiple files and dirs and also recursive deletes
|
186 | * Supports multiple files and dirs and also recursive deletes
|
187 | *
|
187 | *
|
188 | * @param string $args the arguments for rm
|
188 | * @param string $args the arguments for rm
|
189 | * @return mixed PEAR_Error or true for success
|
189 | * @return mixed PEAR_Error or true for success
|
190 | * @static
|
190 | * @static
|
191 | * @access public
|
191 | * @access public
|
192 | */
|
192 | */
|
193 | function rm($args) |
193 | function rm($args) |
194 | {
|
194 | {
|
195 | $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) |
195 | $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) |
196 | if (PEAR::isError($opts)) { |
196 | if (PEAR::isError($opts)) { |
197 | return System::raiseError($opts); |
197 | return System::raiseError($opts); |
198 | }
|
198 | }
|
199 | foreach ($opts[0] as $opt) { |
199 | foreach ($opts[0] as $opt) { |
200 | if ($opt[0] == 'r') { |
200 | if ($opt[0] == 'r') { |
201 | $do_recursive = true; |
201 | $do_recursive = true; |
202 | }
|
202 | }
|
203 | }
|
203 | }
|
204 | $ret = true; |
204 | $ret = true; |
205 | if (isset($do_recursive)) { |
205 | if (isset($do_recursive)) { |
206 | $struct = System::_multipleToStruct($opts[1]); |
206 | $struct = System::_multipleToStruct($opts[1]); |
207 | foreach ($struct['files'] as $file) { |
207 | foreach ($struct['files'] as $file) { |
208 | if (!@unlink($file)) { |
208 | if (!@unlink($file)) { |
209 | $ret = false; |
209 | $ret = false; |
210 | }
|
210 | }
|
211 | }
|
211 | }
|
212 | foreach ($struct['dirs'] as $dir) { |
212 | foreach ($struct['dirs'] as $dir) { |
213 | if (!@rmdir($dir)) { |
213 | if (!@rmdir($dir)) { |
214 | $ret = false; |
214 | $ret = false; |
215 | }
|
215 | }
|
216 | }
|
216 | }
|
217 | } else { |
217 | } else { |
218 | foreach ($opts[1] as $file) { |
218 | foreach ($opts[1] as $file) { |
219 | $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; |
219 | $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; |
220 | if (!@$delete($file)) { |
220 | if (!@$delete($file)) { |
221 | $ret = false; |
221 | $ret = false; |
222 | }
|
222 | }
|
223 | }
|
223 | }
|
224 | }
|
224 | }
|
225 | return $ret; |
225 | return $ret; |
226 | }
|
226 | }
|
227 | 227 | ||
228 | /**
|
228 | /**
|
229 | * Make directories.
|
229 | * Make directories.
|
230 | *
|
230 | *
|
231 | * The -p option will create parent directories
|
231 | * The -p option will create parent directories
|
232 | * @param string $args the name of the director(y|ies) to create
|
232 | * @param string $args the name of the director(y|ies) to create
|
233 | * @return bool True for success
|
233 | * @return bool True for success
|
234 | * @static
|
234 | * @static
|
235 | * @access public
|
235 | * @access public
|
236 | */
|
236 | */
|
237 | function mkDir($args) |
237 | function mkDir($args) |
238 | {
|
238 | {
|
239 | $opts = System::_parseArgs($args, 'pm:'); |
239 | $opts = System::_parseArgs($args, 'pm:'); |
240 | if (PEAR::isError($opts)) { |
240 | if (PEAR::isError($opts)) { |
241 | return System::raiseError($opts); |
241 | return System::raiseError($opts); |
242 | }
|
242 | }
|
243 | $mode = 0777; // default mode |
243 | $mode = 0777; // default mode |
244 | foreach ($opts[0] as $opt) { |
244 | foreach ($opts[0] as $opt) { |
245 | if ($opt[0] == 'p') { |
245 | if ($opt[0] == 'p') { |
246 | $create_parents = true; |
246 | $create_parents = true; |
247 | } elseif ($opt[0] == 'm') { |
247 | } elseif ($opt[0] == 'm') { |
248 | // if the mode is clearly an octal number (starts with 0)
|
248 | // if the mode is clearly an octal number (starts with 0)
|
249 | // convert it to decimal
|
249 | // convert it to decimal
|
250 | if (strlen($opt[1]) && $opt[1]{0} == '0') { |
250 | if (strlen($opt[1]) && $opt[1]{0} == '0') { |
251 | $opt[1] = octdec($opt[1]); |
251 | $opt[1] = octdec($opt[1]); |
252 | } else { |
252 | } else { |
253 | // convert to int
|
253 | // convert to int
|
254 | $opt[1] += 0; |
254 | $opt[1] += 0; |
255 | }
|
255 | }
|
256 | $mode = $opt[1]; |
256 | $mode = $opt[1]; |
257 | }
|
257 | }
|
258 | }
|
258 | }
|
259 | $ret = true; |
259 | $ret = true; |
260 | if (isset($create_parents)) { |
260 | if (isset($create_parents)) { |
261 | foreach ($opts[1] as $dir) { |
261 | foreach ($opts[1] as $dir) { |
262 | $dirstack = array(); |
262 | $dirstack = array(); |
263 | while ((!file_exists($dir) || !is_dir($dir)) && |
263 | while ((!file_exists($dir) || !is_dir($dir)) && |
264 | $dir != DIRECTORY_SEPARATOR) { |
264 | $dir != DIRECTORY_SEPARATOR) { |
265 | array_unshift($dirstack, $dir); |
265 | array_unshift($dirstack, $dir); |
266 | $dir = dirname($dir); |
266 | $dir = dirname($dir); |
267 | }
|
267 | }
|
268 | while ($newdir = array_shift($dirstack)) { |
268 | while ($newdir = array_shift($dirstack)) { |
269 | if (!is_writeable(dirname($newdir))) { |
269 | if (!is_writeable(dirname($newdir))) { |
270 | $ret = false; |
270 | $ret = false; |
271 | break; |
271 | break; |
272 | }
|
272 | }
|
273 | if (!mkdir($newdir, $mode)) { |
273 | if (!mkdir($newdir, $mode)) { |
274 | $ret = false; |
274 | $ret = false; |
275 | }
|
275 | }
|
276 | }
|
276 | }
|
277 | }
|
277 | }
|
278 | } else { |
278 | } else { |
279 | foreach($opts[1] as $dir) { |
279 | foreach($opts[1] as $dir) { |
280 | if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { |
280 | if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { |
281 | $ret = false; |
281 | $ret = false; |
282 | }
|
282 | }
|
283 | }
|
283 | }
|
284 | }
|
284 | }
|
285 | return $ret; |
285 | return $ret; |
286 | }
|
286 | }
|
287 | 287 | ||
288 | /**
|
288 | /**
|
289 | * Concatenate files
|
289 | * Concatenate files
|
290 | *
|
290 | *
|
291 | * Usage:
|
291 | * Usage:
|
292 | * 1) $var = System::cat('sample.txt test.txt');
|
292 | * 1) $var = System::cat('sample.txt test.txt');
|
293 | * 2) System::cat('sample.txt test.txt > final.txt');
|
293 | * 2) System::cat('sample.txt test.txt > final.txt');
|
294 | * 3) System::cat('sample.txt test.txt >> final.txt');
|
294 | * 3) System::cat('sample.txt test.txt >> final.txt');
|
295 | *
|
295 | *
|
296 | * Note: as the class use fopen, urls should work also (test that)
|
296 | * Note: as the class use fopen, urls should work also (test that)
|
297 | *
|
297 | *
|
298 | * @param string $args the arguments
|
298 | * @param string $args the arguments
|
299 | * @return boolean true on success
|
299 | * @return boolean true on success
|
300 | * @static
|
300 | * @static
|
301 | * @access public
|
301 | * @access public
|
302 | */
|
302 | */
|
303 | function &cat($args) |
303 | function &cat($args) |
304 | {
|
304 | {
|
305 | $ret = null; |
305 | $ret = null; |
306 | $files = array(); |
306 | $files = array(); |
307 | if (!is_array($args)) { |
307 | if (!is_array($args)) { |
308 | $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
308 | $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
309 | }
|
309 | }
|
310 | 310 | ||
311 | $count_args = count($args); |
311 | $count_args = count($args); |
312 | for ($i = 0; $i < $count_args; $i++) { |
312 | for ($i = 0; $i < $count_args; $i++) { |
313 | if ($args[$i] == '>') { |
313 | if ($args[$i] == '>') { |
314 | $mode = 'wb'; |
314 | $mode = 'wb'; |
315 | $outputfile = $args[$i+1]; |
315 | $outputfile = $args[$i+1]; |
316 | break; |
316 | break; |
317 | } elseif ($args[$i] == '>>') { |
317 | } elseif ($args[$i] == '>>') { |
318 | $mode = 'ab+'; |
318 | $mode = 'ab+'; |
319 | $outputfile = $args[$i+1]; |
319 | $outputfile = $args[$i+1]; |
320 | break; |
320 | break; |
321 | } else { |
321 | } else { |
322 | $files[] = $args[$i]; |
322 | $files[] = $args[$i]; |
323 | }
|
323 | }
|
324 | }
|
324 | }
|
325 | $outputfd = false; |
325 | $outputfd = false; |
326 | if (isset($mode)) { |
326 | if (isset($mode)) { |
327 | if (!$outputfd = fopen($outputfile, $mode)) { |
327 | if (!$outputfd = fopen($outputfile, $mode)) { |
328 | $err = System::raiseError("Could not open $outputfile"); |
328 | $err = System::raiseError("Could not open $outputfile"); |
329 | return $err; |
329 | return $err; |
330 | }
|
330 | }
|
331 | $ret = true; |
331 | $ret = true; |
332 | }
|
332 | }
|
333 | foreach ($files as $file) { |
333 | foreach ($files as $file) { |
334 | if (!$fd = fopen($file, 'r')) { |
334 | if (!$fd = fopen($file, 'r')) { |
335 | System::raiseError("Could not open $file"); |
335 | System::raiseError("Could not open $file"); |
336 | continue; |
336 | continue; |
337 | }
|
337 | }
|
338 | while ($cont = fread($fd, 2048)) { |
338 | while ($cont = fread($fd, 2048)) { |
339 | if (is_resource($outputfd)) { |
339 | if (is_resource($outputfd)) { |
340 | fwrite($outputfd, $cont); |
340 | fwrite($outputfd, $cont); |
341 | } else { |
341 | } else { |
342 | $ret .= $cont; |
342 | $ret .= $cont; |
343 | }
|
343 | }
|
344 | }
|
344 | }
|
345 | fclose($fd); |
345 | fclose($fd); |
346 | }
|
346 | }
|
347 | if (is_resource($outputfd)) { |
347 | if (is_resource($outputfd)) { |
348 | fclose($outputfd); |
348 | fclose($outputfd); |
349 | }
|
349 | }
|
350 | return $ret; |
350 | return $ret; |
351 | }
|
351 | }
|
352 | 352 | ||
353 | /**
|
353 | /**
|
354 | * Creates temporary files or directories. This function will remove
|
354 | * Creates temporary files or directories. This function will remove
|
355 | * the created files when the scripts finish its execution.
|
355 | * the created files when the scripts finish its execution.
|
356 | *
|
356 | *
|
357 | * Usage:
|
357 | * Usage:
|
358 | * 1) $tempfile = System::mktemp("prefix");
|
358 | * 1) $tempfile = System::mktemp("prefix");
|
359 | * 2) $tempdir = System::mktemp("-d prefix");
|
359 | * 2) $tempdir = System::mktemp("-d prefix");
|
360 | * 3) $tempfile = System::mktemp();
|
360 | * 3) $tempfile = System::mktemp();
|
361 | * 4) $tempfile = System::mktemp("-t /var/tmp prefix");
|
361 | * 4) $tempfile = System::mktemp("-t /var/tmp prefix");
|
362 | *
|
362 | *
|
363 | * prefix -> The string that will be prepended to the temp name
|
363 | * prefix -> The string that will be prepended to the temp name
|
364 | * (defaults to "tmp").
|
364 | * (defaults to "tmp").
|
365 | * -d -> A temporary dir will be created instead of a file.
|
365 | * -d -> A temporary dir will be created instead of a file.
|
366 | * -t -> The target dir where the temporary (file|dir) will be created. If
|
366 | * -t -> The target dir where the temporary (file|dir) will be created. If
|
367 | * this param is missing by default the env vars TMP on Windows or
|
367 | * this param is missing by default the env vars TMP on Windows or
|
368 | * TMPDIR in Unix will be used. If these vars are also missing
|
368 | * TMPDIR in Unix will be used. If these vars are also missing
|
369 | * c:\windows\temp or /tmp will be used.
|
369 | * c:\windows\temp or /tmp will be used.
|
370 | *
|
370 | *
|
371 | * @param string $args The arguments
|
371 | * @param string $args The arguments
|
372 | * @return mixed the full path of the created (file|dir) or false
|
372 | * @return mixed the full path of the created (file|dir) or false
|
373 | * @see System::tmpdir()
|
373 | * @see System::tmpdir()
|
374 | * @static
|
374 | * @static
|
375 | * @access public
|
375 | * @access public
|
376 | */
|
376 | */
|
377 | function mktemp($args = null) |
377 | function mktemp($args = null) |
378 | {
|
378 | {
|
379 | static $first_time = true; |
379 | static $first_time = true; |
380 | $opts = System::_parseArgs($args, 't:d'); |
380 | $opts = System::_parseArgs($args, 't:d'); |
381 | if (PEAR::isError($opts)) { |
381 | if (PEAR::isError($opts)) { |
382 | return System::raiseError($opts); |
382 | return System::raiseError($opts); |
383 | }
|
383 | }
|
384 | foreach ($opts[0] as $opt) { |
384 | foreach ($opts[0] as $opt) { |
385 | if ($opt[0] == 'd') { |
385 | if ($opt[0] == 'd') { |
386 | $tmp_is_dir = true; |
386 | $tmp_is_dir = true; |
387 | } elseif ($opt[0] == 't') { |
387 | } elseif ($opt[0] == 't') { |
388 | $tmpdir = $opt[1]; |
388 | $tmpdir = $opt[1]; |
389 | }
|
389 | }
|
390 | }
|
390 | }
|
391 | $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; |
391 | $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; |
392 | if (!isset($tmpdir)) { |
392 | if (!isset($tmpdir)) { |
393 | $tmpdir = System::tmpdir(); |
393 | $tmpdir = System::tmpdir(); |
394 | }
|
394 | }
|
395 | if (!System::mkDir(array('-p', $tmpdir))) { |
395 | if (!System::mkDir(array('-p', $tmpdir))) { |
396 | return false; |
396 | return false; |
397 | }
|
397 | }
|
398 | $tmp = tempnam($tmpdir, $prefix); |
398 | $tmp = tempnam($tmpdir, $prefix); |
399 | if (isset($tmp_is_dir)) { |
399 | if (isset($tmp_is_dir)) { |
400 | unlink($tmp); // be careful possible race condition here |
400 | unlink($tmp); // be careful possible race condition here |
401 | if (!mkdir($tmp, 0700)) { |
401 | if (!mkdir($tmp, 0700)) { |
402 | return System::raiseError("Unable to create temporary directory $tmpdir"); |
402 | return System::raiseError("Unable to create temporary directory $tmpdir"); |
403 | }
|
403 | }
|
404 | }
|
404 | }
|
405 | $GLOBALS['_System_temp_files'][] = $tmp; |
405 | $GLOBALS['_System_temp_files'][] = $tmp; |
406 | if ($first_time) { |
406 | if ($first_time) { |
407 | PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); |
407 | PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); |
408 | $first_time = false; |
408 | $first_time = false; |
409 | }
|
409 | }
|
410 | return $tmp; |
410 | return $tmp; |
411 | }
|
411 | }
|
412 | 412 | ||
413 | /**
|
413 | /**
|
414 | * Remove temporary files created my mkTemp. This function is executed
|
414 | * Remove temporary files created my mkTemp. This function is executed
|
415 | * at script shutdown time
|
415 | * at script shutdown time
|
416 | *
|
416 | *
|
417 | * @static
|
417 | * @static
|
418 | * @access private
|
418 | * @access private
|
419 | */
|
419 | */
|
420 | function _removeTmpFiles() |
420 | function _removeTmpFiles() |
421 | {
|
421 | {
|
422 | if (count($GLOBALS['_System_temp_files'])) { |
422 | if (count($GLOBALS['_System_temp_files'])) { |
423 | $delete = $GLOBALS['_System_temp_files']; |
423 | $delete = $GLOBALS['_System_temp_files']; |
424 | array_unshift($delete, '-r'); |
424 | array_unshift($delete, '-r'); |
425 | System::rm($delete); |
425 | System::rm($delete); |
426 | $GLOBALS['_System_temp_files'] = array(); |
426 | $GLOBALS['_System_temp_files'] = array(); |
427 | }
|
427 | }
|
428 | }
|
428 | }
|
429 | 429 | ||
430 | /**
|
430 | /**
|
431 | * Get the path of the temporal directory set in the system
|
431 | * Get the path of the temporal directory set in the system
|
432 | * by looking in its environments variables.
|
432 | * by looking in its environments variables.
|
433 | * Note: php.ini-recommended removes the "E" from the variables_order setting,
|
433 | * Note: php.ini-recommended removes the "E" from the variables_order setting,
|
434 | * making unavaible the $_ENV array, that s why we do tests with _ENV
|
434 | * making unavaible the $_ENV array, that s why we do tests with _ENV
|
435 | *
|
435 | *
|
436 | * @static
|
436 | * @static
|
437 | * @return string The temporary directory on the system
|
437 | * @return string The temporary directory on the system
|
438 | */
|
438 | */
|
439 | function tmpdir() |
439 | function tmpdir() |
440 | {
|
440 | {
|
441 | if (OS_WINDOWS) { |
441 | if (OS_WINDOWS) { |
442 | if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { |
442 | if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { |
443 | return $var; |
443 | return $var; |
444 | }
|
444 | }
|
445 | if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { |
445 | if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { |
446 | return $var; |
446 | return $var; |
447 | }
|
447 | }
|
448 | if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { |
448 | if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { |
449 | return $var; |
449 | return $var; |
450 | }
|
450 | }
|
451 | if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { |
451 | if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { |
452 | return $var; |
452 | return $var; |
453 | }
|
453 | }
|
454 | return getenv('SystemRoot') . '\temp'; |
454 | return getenv('SystemRoot') . '\temp'; |
455 | }
|
455 | }
|
456 | if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { |
456 | if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { |
457 | return $var; |
457 | return $var; |
458 | }
|
458 | }
|
459 | return realpath('/tmp'); |
459 | return realpath('/tmp'); |
460 | }
|
460 | }
|
461 | 461 | ||
462 | /**
|
462 | /**
|
463 | * The "which" command (show the full path of a command)
|
463 | * The "which" command (show the full path of a command)
|
464 | *
|
464 | *
|
465 | * @param string $program The command to search for
|
465 | * @param string $program The command to search for
|
466 | * @param mixed $fallback Value to return if $program is not found
|
466 | * @param mixed $fallback Value to return if $program is not found
|
467 | *
|
467 | *
|
468 | * @return mixed A string with the full path or false if not found
|
468 | * @return mixed A string with the full path or false if not found
|
469 | * @static
|
469 | * @static
|
470 | * @author Stig Bakken <ssb@php.net>
|
470 | * @author Stig Bakken <ssb@php.net>
|
471 | */
|
471 | */
|
472 | function which($program, $fallback = false) |
472 | function which($program, $fallback = false) |
473 | {
|
473 | {
|
474 | // enforce API
|
474 | // enforce API
|
475 | if (!is_string($program) || '' == $program) { |
475 | if (!is_string($program) || '' == $program) { |
476 | return $fallback; |
476 | return $fallback; |
477 | }
|
477 | }
|
478 | 478 | ||
479 | // full path given
|
479 | // full path given
|
480 | if (basename($program) != $program) { |
480 | if (basename($program) != $program) { |
481 | $path_elements[] = dirname($program); |
481 | $path_elements[] = dirname($program); |
482 | $program = basename($program); |
482 | $program = basename($program); |
483 | } else { |
483 | } else { |
484 | // Honor safe mode
|
484 | // Honor safe mode
|
485 | if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) { |
485 | if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) { |
486 | $path = getenv('PATH'); |
486 | $path = getenv('PATH'); |
487 | if (!$path) { |
487 | if (!$path) { |
488 | $path = getenv('Path'); // some OSes are just stupid enough to do this |
488 | $path = getenv('Path'); // some OSes are just stupid enough to do this |
489 | }
|
489 | }
|
490 | }
|
490 | }
|
491 | $path_elements = explode(PATH_SEPARATOR, $path); |
491 | $path_elements = explode(PATH_SEPARATOR, $path); |
492 | }
|
492 | }
|
493 | 493 | ||
494 | if (OS_WINDOWS) { |
494 | if (OS_WINDOWS) { |
495 | $exe_suffixes = getenv('PATHEXT') |
495 | $exe_suffixes = getenv('PATHEXT') |
496 | ? explode(PATH_SEPARATOR, getenv('PATHEXT')) |
496 | ? explode(PATH_SEPARATOR, getenv('PATHEXT')) |
497 | : array('.exe','.bat','.cmd','.com'); |
497 | : array('.exe','.bat','.cmd','.com'); |
498 | // allow passing a command.exe param
|
498 | // allow passing a command.exe param
|
499 | if (strpos($program, '.') !== false) { |
499 | if (strpos($program, '.') !== false) { |
500 | array_unshift($exe_suffixes, ''); |
500 | array_unshift($exe_suffixes, ''); |
501 | }
|
501 | }
|
502 | // is_executable() is not available on windows for PHP4
|
502 | // is_executable() is not available on windows for PHP4
|
503 | $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file'; |
503 | $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file'; |
504 | } else { |
504 | } else { |
505 | $exe_suffixes = array(''); |
505 | $exe_suffixes = array(''); |
506 | $pear_is_executable = 'is_executable'; |
506 | $pear_is_executable = 'is_executable'; |
507 | }
|
507 | }
|
508 | 508 | ||
509 | foreach ($exe_suffixes as $suff) { |
509 | foreach ($exe_suffixes as $suff) { |
510 | foreach ($path_elements as $dir) { |
510 | foreach ($path_elements as $dir) { |
511 | $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; |
511 | $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; |
512 | if (@$pear_is_executable($file)) { |
512 | if (@$pear_is_executable($file)) { |
513 | return $file; |
513 | return $file; |
514 | }
|
514 | }
|
515 | }
|
515 | }
|
516 | }
|
516 | }
|
517 | return $fallback; |
517 | return $fallback; |
518 | }
|
518 | }
|
519 | 519 | ||
520 | /**
|
520 | /**
|
521 | * The "find" command
|
521 | * The "find" command
|
522 | *
|
522 | *
|
523 | * Usage:
|
523 | * Usage:
|
524 | *
|
524 | *
|
525 | * System::find($dir);
|
525 | * System::find($dir);
|
526 | * System::find("$dir -type d");
|
526 | * System::find("$dir -type d");
|
527 | * System::find("$dir -type f");
|
527 | * System::find("$dir -type f");
|
528 | * System::find("$dir -name *.php");
|
528 | * System::find("$dir -name *.php");
|
529 | * System::find("$dir -name *.php -name *.htm*");
|
529 | * System::find("$dir -name *.php -name *.htm*");
|
530 | * System::find("$dir -maxdepth 1");
|
530 | * System::find("$dir -maxdepth 1");
|
531 | *
|
531 | *
|
532 | * Params implmented:
|
532 | * Params implmented:
|
533 | * $dir -> Start the search at this directory
|
533 | * $dir -> Start the search at this directory
|
534 | * -type d -> return only directories
|
534 | * -type d -> return only directories
|
535 | * -type f -> return only files
|
535 | * -type f -> return only files
|
536 | * -maxdepth <n> -> max depth of recursion
|
536 | * -maxdepth <n> -> max depth of recursion
|
537 | * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
|
537 | * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
|
538 | *
|
538 | *
|
539 | * @param mixed Either array or string with the command line
|
539 | * @param mixed Either array or string with the command line
|
540 | * @return array Array of found files
|
540 | * @return array Array of found files
|
541 | * @static
|
541 | * @static
|
542 | *
|
542 | *
|
543 | */
|
543 | */
|
544 | function find($args) |
544 | function find($args) |
545 | {
|
545 | {
|
546 | if (!is_array($args)) { |
546 | if (!is_array($args)) { |
547 | $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
547 | $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); |
548 | }
|
548 | }
|
549 | $dir = realpath(array_shift($args)); |
549 | $dir = realpath(array_shift($args)); |
550 | if (!$dir) { |
550 | if (!$dir) { |
551 | return array(); |
551 | return array(); |
552 | }
|
552 | }
|
553 | $patterns = array(); |
553 | $patterns = array(); |
554 | $depth = 0; |
554 | $depth = 0; |
555 | $do_files = $do_dirs = true; |
555 | $do_files = $do_dirs = true; |
556 | $args_count = count($args); |
556 | $args_count = count($args); |
557 | for ($i = 0; $i < $args_count; $i++) { |
557 | for ($i = 0; $i < $args_count; $i++) { |
558 | switch ($args[$i]) { |
558 | switch ($args[$i]) { |
559 | case '-type': |
559 | case '-type': |
560 | if (in_array($args[$i+1], array('d', 'f'))) { |
560 | if (in_array($args[$i+1], array('d', 'f'))) { |
561 | if ($args[$i+1] == 'd') { |
561 | if ($args[$i+1] == 'd') { |
562 | $do_files = false; |
562 | $do_files = false; |
563 | } else { |
563 | } else { |
564 | $do_dirs = false; |
564 | $do_dirs = false; |
565 | }
|
565 | }
|
566 | }
|
566 | }
|
567 | $i++; |
567 | $i++; |
568 | break; |
568 | break; |
569 | case '-name': |
569 | case '-name': |
570 | $name = preg_quote($args[$i+1], '#'); |
570 | $name = preg_quote($args[$i+1], '#'); |
571 | // our magic characters ? and * have just been escaped,
|
571 | // our magic characters ? and * have just been escaped,
|
572 | // so now we change the escaped versions to PCRE operators
|
572 | // so now we change the escaped versions to PCRE operators
|
573 | $name = strtr($name, array('\?' => '.', '\*' => '.*')); |
573 | $name = strtr($name, array('\?' => '.', '\*' => '.*')); |
574 | $patterns[] = '('.$name.')'; |
574 | $patterns[] = '('.$name.')'; |
575 | $i++; |
575 | $i++; |
576 | break; |
576 | break; |
577 | case '-maxdepth': |
577 | case '-maxdepth': |
578 | $depth = $args[$i+1]; |
578 | $depth = $args[$i+1]; |
579 | break; |
579 | break; |
580 | }
|
580 | }
|
581 | }
|
581 | }
|
582 | $path = System::_dirToStruct($dir, $depth, 0, true); |
582 | $path = System::_dirToStruct($dir, $depth, 0, true); |
583 | if ($do_files && $do_dirs) { |
583 | if ($do_files && $do_dirs) { |
584 | $files = array_merge($path['files'], $path['dirs']); |
584 | $files = array_merge($path['files'], $path['dirs']); |
585 | } elseif ($do_dirs) { |
585 | } elseif ($do_dirs) { |
586 | $files = $path['dirs']; |
586 | $files = $path['dirs']; |
587 | } else { |
587 | } else { |
588 | $files = $path['files']; |
588 | $files = $path['files']; |
589 | }
|
589 | }
|
590 | if (count($patterns)) { |
590 | if (count($patterns)) { |
591 | $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); |
591 | $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); |
592 | $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; |
592 | $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; |
593 | $ret = array(); |
593 | $ret = array(); |
594 | $files_count = count($files); |
594 | $files_count = count($files); |
595 | for ($i = 0; $i < $files_count; $i++) { |
595 | for ($i = 0; $i < $files_count; $i++) { |
596 | // only search in the part of the file below the current directory
|
596 | // only search in the part of the file below the current directory
|
597 | $filepart = basename($files[$i]); |
597 | $filepart = basename($files[$i]); |
598 | if (preg_match($pattern, $filepart)) { |
598 | if (preg_match($pattern, $filepart)) { |
599 | $ret[] = $files[$i]; |
599 | $ret[] = $files[$i]; |
600 | }
|
600 | }
|
601 | }
|
601 | }
|
602 | return $ret; |
602 | return $ret; |
603 | }
|
603 | }
|
604 | return $files; |
604 | return $files; |
605 | }
|
605 | }
|
606 | }
|
606 | }
|