Spaces:
Sleeping
Sleeping
| // | |
| // +----------------------------------------------------------------------+ | |
| // | PHP Version 5 | | |
| // +----------------------------------------------------------------------+ | |
| // | Copyright (c) 1997-2004 The PHP Group | | |
| // +----------------------------------------------------------------------+ | |
| // | This source file is subject to version 3.0 of the PHP license, | | |
| // | that is bundled with this package in the file LICENSE, and is | | |
| // | available through the world-wide-web at the following url: | | |
| // | http://www.php.net/license/3_0.txt. | | |
| // | If you did not receive a copy of the PHP license and are unable to | | |
| // | obtain it through the world-wide-web, please send a note to | | |
| // | license@php.net so we can mail you a copy immediately. | | |
| // +----------------------------------------------------------------------+ | |
| // | Authors: Tomas V.V.Cox <cox@idecnet.com> | | |
| // +----------------------------------------------------------------------+ | |
| // | |
| // $Id: System.php 6820 2007-06-20 13:35:30Z kevin_fourie $ | |
| // | |
| require_once 'PEAR.php'; | |
| require_once 'Console/Getopt.php'; | |
| $GLOBALS['_System_temp_files'] = array(); | |
| /** | |
| * System offers cross plattform compatible system functions | |
| * | |
| * Static functions for different operations. Should work under | |
| * Unix and Windows. The names and usage has been taken from its respectively | |
| * GNU commands. The functions will return (bool) false on error and will | |
| * trigger the error with the PHP trigger_error() function (you can silence | |
| * the error by prefixing a '@' sign after the function call). | |
| * | |
| * Documentation on this class you can find in: | |
| * http://pear.php.net/manual/ | |
| * | |
| * Example usage: | |
| * if (!@PearSystem::rm('-r file1 dir1')) { | |
| * print "could not delete file1 or dir1"; | |
| * } | |
| * | |
| * In case you need to to pass file names with spaces, | |
| * pass the params as an array: | |
| * | |
| * PearSystem::rm(array('-r', $file1, $dir1)); | |
| * | |
| * @package System | |
| * @author Tomas V.V.Cox <cox@idecnet.com> | |
| * @version $Revision: 6820 $ | |
| * @access public | |
| * @see http://pear.php.net/manual/ | |
| */ | |
| class PearSystem | |
| { | |
| /** | |
| * returns the commandline arguments of a function | |
| * | |
| * @param string $argv the commandline | |
| * @param string $short_options the allowed option short-tags | |
| * @param string $long_options the allowed option long-tags | |
| * @return array the given options and there values | |
| * @access private | |
| */ | |
| function _parseArgs($argv, $short_options, $long_options = null) | |
| { | |
| if (!is_array($argv) && $argv !== null) { | |
| $argv = preg_split('/\s+/', $argv); | |
| } | |
| return Console_Getopt::getopt2($argv, $short_options); | |
| } | |
| /** | |
| * Output errors with PHP trigger_error(). You can silence the errors | |
| * with prefixing a "@" sign to the function call: @PearSystem::mkdir(..); | |
| * | |
| * @param mixed $error a PEAR error or a string with the error message | |
| * @return bool false | |
| * @access private | |
| */ | |
| function raiseError($error) | |
| { | |
| if (PEAR::isError($error)) { | |
| $error = $error->getMessage(); | |
| } | |
| trigger_error($error, E_USER_WARNING); | |
| return false; | |
| } | |
| /** | |
| * Creates a nested array representing the structure of a directory | |
| * | |
| * PearSystem::_dirToStruct('dir1', 0) => | |
| * Array | |
| * ( | |
| * [dirs] => Array | |
| * ( | |
| * [0] => dir1 | |
| * ) | |
| * | |
| * [files] => Array | |
| * ( | |
| * [0] => dir1/file2 | |
| * [1] => dir1/file3 | |
| * ) | |
| * ) | |
| * @param string $sPath Name of the directory | |
| * @param integer $maxinst max. deep of the lookup | |
| * @param integer $aktinst starting deep of the lookup | |
| * @return array the structure of the dir | |
| * @access private | |
| */ | |
| function _dirToStruct($sPath, $maxinst, $aktinst = 0) | |
| { | |
| $struct = array('dirs' => array(), 'files' => array()); | |
| if (($dir = @opendir($sPath)) === false) { | |
| PearSystem::raiseError("Could not open dir $sPath"); | |
| return $struct; // XXX could not open error | |
| } | |
| $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ? | |
| $list = array(); | |
| while ($file = readdir($dir)) { | |
| if ($file != '.' && $file != '..') { | |
| $list[] = $file; | |
| } | |
| } | |
| closedir($dir); | |
| sort($list); | |
| if ($aktinst < $maxinst || $maxinst == 0) { | |
| foreach($list as $val) { | |
| $path = $sPath . DIRECTORY_SEPARATOR . $val; | |
| if (is_dir($path)) { | |
| $tmp = PearSystem::_dirToStruct($path, $maxinst, $aktinst+1); | |
| $struct = array_merge_recursive($tmp, $struct); | |
| } else { | |
| $struct['files'][] = $path; | |
| } | |
| } | |
| } | |
| return $struct; | |
| } | |
| /** | |
| * Creates a nested array representing the structure of a directory and files | |
| * | |
| * @param array $files Array listing files and dirs | |
| * @return array | |
| * @see PearSystem::_dirToStruct() | |
| */ | |
| function _multipleToStruct($files) | |
| { | |
| $struct = array('dirs' => array(), 'files' => array()); | |
| settype($files, 'array'); | |
| foreach ($files as $file) { | |
| if (is_dir($file)) { | |
| $tmp = PearSystem::_dirToStruct($file, 0); | |
| $struct = array_merge_recursive($tmp, $struct); | |
| } else { | |
| $struct['files'][] = $file; | |
| } | |
| } | |
| return $struct; | |
| } | |
| /** | |
| * The rm command for removing files. | |
| * Supports multiple files and dirs and also recursive deletes | |
| * | |
| * @param string $args the arguments for rm | |
| * @return mixed PEAR_Error or true for success | |
| * @access public | |
| */ | |
| function rm($args) | |
| { | |
| $opts = PearSystem::_parseArgs($args, 'rf'); // "f" do nothing but like it :-) | |
| if (PEAR::isError($opts)) { | |
| return PearSystem::raiseError($opts); | |
| } | |
| foreach($opts[0] as $opt) { | |
| if ($opt[0] == 'r') { | |
| $do_recursive = true; | |
| } | |
| } | |
| $ret = true; | |
| if (isset($do_recursive)) { | |
| $struct = PearSystem::_multipleToStruct($opts[1]); | |
| foreach($struct['files'] as $file) { | |
| if (!@unlink($file)) { | |
| $ret = false; | |
| } | |
| } | |
| foreach($struct['dirs'] as $dir) { | |
| if (!@rmdir($dir)) { | |
| $ret = false; | |
| } | |
| } | |
| } else { | |
| foreach ($opts[1] as $file) { | |
| $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; | |
| if (!@$delete($file)) { | |
| $ret = false; | |
| } | |
| } | |
| } | |
| return $ret; | |
| } | |
| /** | |
| * Make directories. Note that we use call_user_func('mkdir') to avoid | |
| * a problem with ZE2 calling PearSystem::mkDir instead of the native PHP func. | |
| * | |
| * @param string $args the name of the director(y|ies) to create | |
| * @return bool True for success | |
| * @access public | |
| */ | |
| function mkDir($args) | |
| { | |
| $opts = PearSystem::_parseArgs($args, 'pm:'); | |
| if (PEAR::isError($opts)) { | |
| return PearSystem::raiseError($opts); | |
| } | |
| $mode = 0777; // default mode | |
| foreach($opts[0] as $opt) { | |
| if ($opt[0] == 'p') { | |
| $create_parents = true; | |
| } elseif($opt[0] == 'm') { | |
| // if the mode is clearly an octal number (starts with 0) | |
| // convert it to decimal | |
| if (strlen($opt[1]) && $opt[1]{0} == '0') { | |
| $opt[1] = octdec($opt[1]); | |
| } else { | |
| // convert to int | |
| $opt[1] += 0; | |
| } | |
| $mode = $opt[1]; | |
| } | |
| } | |
| $ret = true; | |
| if (isset($create_parents)) { | |
| foreach($opts[1] as $dir) { | |
| $dirstack = array(); | |
| while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { | |
| array_unshift($dirstack, $dir); | |
| $dir = dirname($dir); | |
| } | |
| while ($newdir = array_shift($dirstack)) { | |
| if (!call_user_func('mkdir', $newdir, $mode)) { | |
| $ret = false; | |
| } | |
| } | |
| } | |
| } else { | |
| foreach($opts[1] as $dir) { | |
| if (!@is_dir($dir) && !call_user_func('mkdir', $dir, $mode)) { | |
| $ret = false; | |
| } | |
| } | |
| } | |
| return $ret; | |
| } | |
| /** | |
| * Concatenate files | |
| * | |
| * Usage: | |
| * 1) $var = PearSystem::cat('sample.txt test.txt'); | |
| * 2) PearSystem::cat('sample.txt test.txt > final.txt'); | |
| * 3) PearSystem::cat('sample.txt test.txt >> final.txt'); | |
| * | |
| * Note: as the class use fopen, urls should work also (test that) | |
| * | |
| * @param string $args the arguments | |
| * @return boolean true on success | |
| * @access public | |
| */ | |
| function &cat($args) | |
| { | |
| $ret = null; | |
| $files = array(); | |
| if (!is_array($args)) { | |
| $args = preg_split('/\s+/', $args); | |
| } | |
| for($i=0; $i < count($args); $i++) { | |
| if ($args[$i] == '>') { | |
| $mode = 'wb'; | |
| $outputfile = $args[$i+1]; | |
| break; | |
| } elseif ($args[$i] == '>>') { | |
| $mode = 'ab+'; | |
| $outputfile = $args[$i+1]; | |
| break; | |
| } else { | |
| $files[] = $args[$i]; | |
| } | |
| } | |
| if (isset($mode)) { | |
| if (!$outputfd = fopen($outputfile, $mode)) { | |
| $err = PearSystem::raiseError("Could not open $outputfile"); | |
| return $err; | |
| } | |
| $ret = true; | |
| } | |
| foreach ($files as $file) { | |
| if (!$fd = fopen($file, 'r')) { | |
| PearSystem::raiseError("Could not open $file"); | |
| continue; | |
| } | |
| while ($cont = fread($fd, 2048)) { | |
| if (isset($outputfd)) { | |
| fwrite($outputfd, $cont); | |
| } else { | |
| $ret .= $cont; | |
| } | |
| } | |
| fclose($fd); | |
| } | |
| if (@is_resource($outputfd)) { | |
| fclose($outputfd); | |
| } | |
| return $ret; | |
| } | |
| /** | |
| * Creates temporary files or directories. This function will remove | |
| * the created files when the scripts finish its execution. | |
| * | |
| * Usage: | |
| * 1) $tempfile = PearSystem::mktemp("prefix"); | |
| * 2) $tempdir = PearSystem::mktemp("-d prefix"); | |
| * 3) $tempfile = PearSystem::mktemp(); | |
| * 4) $tempfile = PearSystem::mktemp("-t /var/tmp prefix"); | |
| * | |
| * prefix -> The string that will be prepended to the temp name | |
| * (defaults to "tmp"). | |
| * -d -> A temporary dir will be created instead of a file. | |
| * -t -> The target dir where the temporary (file|dir) will be created. If | |
| * this param is missing by default the env vars TMP on Windows or | |
| * TMPDIR in Unix will be used. If these vars are also missing | |
| * c:\windows\temp or /tmp will be used. | |
| * | |
| * @param string $args The arguments | |
| * @return mixed the full path of the created (file|dir) or false | |
| * @see PearSystem::tmpdir() | |
| * @access public | |
| */ | |
| function mktemp($args = null) | |
| { | |
| static $first_time = true; | |
| $opts = PearSystem::_parseArgs($args, 't:d'); | |
| if (PEAR::isError($opts)) { | |
| return PearSystem::raiseError($opts); | |
| } | |
| foreach($opts[0] as $opt) { | |
| if($opt[0] == 'd') { | |
| $tmp_is_dir = true; | |
| } elseif($opt[0] == 't') { | |
| $tmpdir = $opt[1]; | |
| } | |
| } | |
| $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; | |
| if (!isset($tmpdir)) { | |
| $tmpdir = PearSystem::tmpdir(); | |
| } | |
| if (!PearSystem::mkDir("-p $tmpdir")) { | |
| return false; | |
| } | |
| $tmp = tempnam($tmpdir, $prefix); | |
| if (isset($tmp_is_dir)) { | |
| unlink($tmp); // be careful possible race condition here | |
| if (!call_user_func('mkdir', $tmp, 0700)) { | |
| return PearSystem::raiseError("Unable to create temporary directory $tmpdir"); | |
| } | |
| } | |
| $GLOBALS['_System_temp_files'][] = $tmp; | |
| if ($first_time) { | |
| PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); | |
| $first_time = false; | |
| } | |
| return $tmp; | |
| } | |
| /** | |
| * Remove temporary files created my mkTemp. This function is executed | |
| * at script shutdown time | |
| * | |
| * @access private | |
| */ | |
| function _removeTmpFiles() | |
| { | |
| if (count($GLOBALS['_System_temp_files'])) { | |
| $delete = $GLOBALS['_System_temp_files']; | |
| array_unshift($delete, '-r'); | |
| PearSystem::rm($delete); | |
| } | |
| } | |
| /** | |
| * Get the path of the temporal directory set in the system | |
| * by looking in its environments variables. | |
| * Note: php.ini-recommended removes the "E" from the variables_order setting, | |
| * making unavaible the $_ENV array, that s why we do tests with _ENV | |
| * | |
| * @return string The temporal directory on the system | |
| */ | |
| function tmpdir() | |
| { | |
| if (OS_WINDOWS) { | |
| if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { | |
| return $var; | |
| } | |
| if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { | |
| return $var; | |
| } | |
| if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { | |
| return $var; | |
| } | |
| return getenv('SystemRoot') . '\temp'; | |
| } | |
| if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { | |
| return $var; | |
| } | |
| return '/tmp'; | |
| } | |
| /** | |
| * The "which" command (show the full path of a command) | |
| * | |
| * @param string $program The command to search for | |
| * @return mixed A string with the full path or false if not found | |
| * @author Stig Bakken <ssb@php.net> | |
| */ | |
| function which($program, $fallback = false) | |
| { | |
| // is_executable() is not available on windows | |
| if (OS_WINDOWS) { | |
| $pear_is_executable = 'is_file'; | |
| } else { | |
| $pear_is_executable = 'is_executable'; | |
| } | |
| // full path given | |
| if (basename($program) != $program) { | |
| return (@$pear_is_executable($program)) ? $program : $fallback; | |
| } | |
| // XXX FIXME honor safe mode | |
| $path_delim = OS_WINDOWS ? ';' : ':'; | |
| $exe_suffixes = OS_WINDOWS ? array('.exe','.bat','.cmd','.com') : array(''); | |
| $path_elements = explode($path_delim, getenv('PATH')); | |
| foreach ($exe_suffixes as $suff) { | |
| foreach ($path_elements as $dir) { | |
| $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; | |
| if (@is_file($file) && @$pear_is_executable($file)) { | |
| return $file; | |
| } | |
| } | |
| } | |
| return $fallback; | |
| } | |
| /** | |
| * The "find" command | |
| * | |
| * Usage: | |
| * | |
| * PearSystem::find($dir); | |
| * PearSystem::find("$dir -type d"); | |
| * PearSystem::find("$dir -type f"); | |
| * PearSystem::find("$dir -name *.php"); | |
| * PearSystem::find("$dir -name *.php -name *.htm*"); | |
| * PearSystem::find("$dir -maxdepth 1"); | |
| * | |
| * Params implmented: | |
| * $dir -> Start the search at this directory | |
| * -type d -> return only directories | |
| * -type f -> return only files | |
| * -maxdepth <n> -> max depth of recursion | |
| * -name <pattern> -> search pattern (bash style). Multiple -name param allowed | |
| * | |
| * @param mixed Either array or string with the command line | |
| * @return array Array of found files | |
| * | |
| */ | |
| function find($args) | |
| { | |
| if (!is_array($args)) { | |
| $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); | |
| } | |
| $dir = array_shift($args); | |
| $patterns = array(); | |
| $depth = 0; | |
| $do_files = $do_dirs = true; | |
| for ($i = 0; $i < count($args); $i++) { | |
| switch ($args[$i]) { | |
| case '-type': | |
| if (in_array($args[$i+1], array('d', 'f'))) { | |
| if ($args[$i+1] == 'd') { | |
| $do_files = false; | |
| } else { | |
| $do_dirs = false; | |
| } | |
| } | |
| $i++; | |
| break; | |
| case '-name': | |
| $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), | |
| array('\.', '.*'), | |
| $args[$i+1]) | |
| . ")"; | |
| $i++; | |
| break; | |
| case '-maxdepth': | |
| $depth = $args[$i+1]; | |
| break; | |
| } | |
| } | |
| $path = PearSystem::_dirToStruct($dir, $depth); | |
| if ($do_files && $do_dirs) { | |
| $files = array_merge($path['files'], $path['dirs']); | |
| } elseif ($do_dirs) { | |
| $files = $path['dirs']; | |
| } else { | |
| $files = $path['files']; | |
| } | |
| if (count($patterns)) { | |
| $patterns = implode('|', $patterns); | |
| $ret = array(); | |
| for ($i = 0; $i < count($files); $i++) { | |
| if (preg_match("#^$patterns\$#", $files[$i])) { | |
| $ret[] = $files[$i]; | |
| } | |
| } | |
| return $ret; | |
| } | |
| return $files; | |
| } | |
| } | |