You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

411 lines
13 KiB

24 years ago
24 years ago
24 years ago
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Tomas V.V.Cox <cox@idecnet.com> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id$
  20. //
  21. require_once 'PEAR.php';
  22. require_once 'Console/Getopt.php';
  23. /**
  24. * System offers cross plattform compatible system functions
  25. *
  26. * Static functions for different operations. Should work under
  27. * Unix and Windows. The names and usage has been taken from its respectively
  28. * GNU commands. The functions will return (bool) false on error and will
  29. * trigger the error with the PHP trigger_error() function (you can silence
  30. * the error by prefixing a '@' sign after the function call).
  31. *
  32. * Documentation on this class you can find in:
  33. * http://pear.php.net/manual/
  34. *
  35. * Example usage:
  36. * if (!@System::rm('-r file1 dir1')) {
  37. * print "could not delete file1 or dir1";
  38. * }
  39. *
  40. * @package System
  41. * @author Tomas V.V.Cox <cox@idecnet.com>
  42. * @version $Revision$
  43. * @access public
  44. * @see http://pear.php.net/manual/
  45. */
  46. class System extends PEAR
  47. {
  48. /**
  49. * returns the commandline arguments of a function
  50. *
  51. * @param string $argv the commandline
  52. * @param string $short_options the allowed option short-tags
  53. * @param string $long_options the allowed option long-tags
  54. * @return array the given options and there values
  55. * @access private
  56. */
  57. function _parseArgs($argv, $short_options, $long_options = null)
  58. {
  59. if (!is_array($argv) && $argv !== null) {
  60. $argv = preg_split('/\s+/', $argv);
  61. }
  62. return Console_Getopt::getopt($argv, $short_options);
  63. }
  64. /**
  65. * Output errors with PHP trigger_error(). You can silence the errors
  66. * with prefixing a "@" sign to the function call: @System::mkdir(..);
  67. *
  68. * @param mixed $error a PEAR error or a string with the error message
  69. * @return bool false
  70. * @access private
  71. */
  72. function raiseError($error)
  73. {
  74. if (PEAR::isError($error)) {
  75. $error = $error->getMessage();
  76. }
  77. trigger_error($error, E_USER_WARNING);
  78. return false;
  79. }
  80. /**
  81. * Creates a nested array representing the structure of a directory
  82. *
  83. * System::_dirToStruct('dir1', 0) =>
  84. * Array
  85. * (
  86. * [dirs] => Array
  87. * (
  88. * [0] => dir1
  89. * )
  90. *
  91. * [files] => Array
  92. * (
  93. * [0] => dir1/file2
  94. * [1] => dir1/file3
  95. * )
  96. * )
  97. * @param string $sPath Name of the directory
  98. * @param integer $maxinst max. deep of the lookup
  99. * @param integer $aktinst starting deep of the lookup
  100. * @return array the structure of the dir
  101. * @access private
  102. */
  103. function _dirToStruct($sPath, $maxinst, $aktinst = 0)
  104. {
  105. $struct = array('dirs' => array(), 'files' => array());
  106. if (($dir = @opendir($sPath)) === false) {
  107. System::raiseError("Could not open dir $sPath");
  108. return $struct; // XXX could not open error
  109. }
  110. $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ?
  111. $list = array();
  112. while ($file = readdir($dir)) {
  113. if ($file != '.' && $file != '..') {
  114. $list[] = $file;
  115. }
  116. }
  117. closedir($dir);
  118. sort($list);
  119. foreach($list as $val) {
  120. $path = $sPath . DIRECTORY_SEPARATOR . $val;
  121. if (is_dir($path)) {
  122. if ($aktinst < $maxinst || $maxinst == 0) {
  123. $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);
  124. $struct = array_merge_recursive($tmp, $struct);
  125. }
  126. } else {
  127. $struct['files'][] = $path;
  128. }
  129. }
  130. return $struct;
  131. }
  132. /**
  133. * Creates a nested array representing the structure of a directory and files
  134. *
  135. * @param array $files Array listing files and dirs
  136. * @return array
  137. * @see System::_dirToStruct()
  138. */
  139. function _multipleToStruct($files)
  140. {
  141. $struct = array('dirs' => array(), 'files' => array());
  142. foreach($files as $file) {
  143. if (is_dir($file)) {
  144. $tmp = System::_dirToStruct($file, 0);
  145. $struct = array_merge_recursive($tmp, $struct);
  146. } else {
  147. $struct['files'][] = $file;
  148. }
  149. }
  150. return $struct;
  151. }
  152. /**
  153. * The rm command for removing files.
  154. * Supports multiple files and dirs and also recursive deletes
  155. *
  156. * @param string $args the arguments for rm
  157. * @return mixed PEAR_Error or true for success
  158. * @access public
  159. */
  160. function rm($args)
  161. {
  162. $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-)
  163. if (PEAR::isError($opts)) {
  164. return System::raiseError($opts);
  165. }
  166. foreach($opts[0] as $opt) {
  167. if ($opt[0] == 'r') {
  168. $do_recursive = true;
  169. }
  170. }
  171. $ret = true;
  172. if (isset($do_recursive)) {
  173. $struct = System::_multipleToStruct($opts[1]);
  174. foreach($struct['files'] as $file) {
  175. if (!unlink($file)) {
  176. $ret = false;
  177. }
  178. }
  179. foreach($struct['dirs'] as $dir) {
  180. if (!rmdir($dir)) {
  181. $ret = false;
  182. }
  183. }
  184. } else {
  185. foreach ($opts[1] as $file) {
  186. $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
  187. if (!$delete($file)) {
  188. $ret = false;
  189. }
  190. }
  191. }
  192. return $ret;
  193. }
  194. /**
  195. * Make directories
  196. *
  197. * @param string $args the name of the director(y|ies) to create
  198. * @return bool True for success
  199. * @access public
  200. */
  201. function mkDir($args)
  202. {
  203. $opts = System::_parseArgs($args, 'pm:');
  204. if (PEAR::isError($opts)) {
  205. return System::raiseError($opts);
  206. }
  207. $mode = 0777; // default mode
  208. foreach($opts[0] as $opt) {
  209. if ($opt[0] == 'p') {
  210. $create_parents = true;
  211. } elseif($opt[0] == 'm') {
  212. $mode = $opt[1];
  213. }
  214. }
  215. $ret = true;
  216. if (isset($create_parents)) {
  217. foreach($opts[1] as $dir) {
  218. $dirstack = array();
  219. while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) {
  220. array_unshift($dirstack, $dir);
  221. $dir = dirname($dir);
  222. }
  223. while ($newdir = array_shift($dirstack)) {
  224. if (!mkdir($newdir, $mode)) {
  225. $ret = false;
  226. }
  227. }
  228. }
  229. } else {
  230. foreach($opts[1] as $dir) {
  231. if (!@is_dir($dir) && !mkdir($dir, $mode)) {
  232. $ret = false;
  233. }
  234. }
  235. }
  236. return $ret;
  237. }
  238. /**
  239. * Concatenate files
  240. *
  241. * Usage:
  242. * 1) $var = System::cat('sample.txt test.txt');
  243. * 2) System::cat('sample.txt test.txt > final.txt');
  244. * 3) System::cat('sample.txt test.txt >> final.txt');
  245. *
  246. * Note: as the class use fopen, urls should work also (test that)
  247. *
  248. * @param string $args the arguments
  249. * @return boolean true on success
  250. * @access public
  251. */
  252. function &cat($args)
  253. {
  254. $ret = null;
  255. $files = array();
  256. if (!is_array($args)) {
  257. $args = preg_split('/\s+/', $args);
  258. }
  259. for($i=0; $i < count($args); $i++) {
  260. if ($args[$i] == '>') {
  261. $mode = 'wb';
  262. $outputfile = $args[$i+1];
  263. break;
  264. } elseif ($args[$i] == '>>') {
  265. $mode = 'ab+';
  266. $outputfile = $args[$i+1];
  267. break;
  268. } else {
  269. $files[] = $args[$i];
  270. }
  271. }
  272. if (isset($mode)) {
  273. if (!$outputfd = fopen($outputfile, $mode)) {
  274. return System::raiseError("Could not open $outputfile");
  275. }
  276. $ret = true;
  277. }
  278. foreach ($files as $file) {
  279. if (!$fd = fopen($file, 'r')) {
  280. System::raiseError("Could not open $file");
  281. continue;
  282. }
  283. while(!feof($fd)) {
  284. $cont = fread($fd, 2048);
  285. if (isset($outputfd)) {
  286. fwrite($outputfd, $cont);
  287. } else {
  288. $ret .= $cont;
  289. }
  290. }
  291. fclose($fd);
  292. }
  293. if (@is_resource($outputfd)) {
  294. fclose($outputfd);
  295. }
  296. return $ret;
  297. }
  298. /**
  299. * Creates temporal files or directories
  300. *
  301. * Usage:
  302. * 1) $tempfile = System::mktemp("prefix");
  303. * 2) $tempdir = System::mktemp("-d prefix");
  304. * 3) $tempfile = System::mktemp();
  305. * 4) $tempfile = System::mktemp("-t /var/tmp prefix");
  306. *
  307. * prefix -> The string that will be prepended to the temp name
  308. * (defaults to "tmp").
  309. * -d -> A temporal dir will be created instead of a file.
  310. * -t -> The target dir where the temporal (file|dir) will be created. If
  311. * this param is missing by default the env vars TMP on Windows or
  312. * TMPDIR in Unix will be used. If these vars are also missing
  313. * c:\windows\temp or /tmp will be used.
  314. *
  315. * @param string $args The arguments
  316. * @return mixed the full path of the created (file|dir) or false
  317. * @see System::tmpdir()
  318. * @access public
  319. */
  320. function mktemp($args = null)
  321. {
  322. $opts = System::_parseArgs($args, 't:d');
  323. if (PEAR::isError($opts)) {
  324. return System::raiseError($opts);
  325. }
  326. foreach($opts[0] as $opt) {
  327. if($opt[0] == 'd') {
  328. $tmp_is_dir = true;
  329. } elseif($opt[0] == 't') {
  330. $tmpdir = $opt[1];
  331. }
  332. }
  333. $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
  334. if (!isset($tmpdir)) {
  335. $tmpdir = System::tmpdir();
  336. }
  337. if (!System::mkDir("-p $tmpdir")) {
  338. return false;
  339. }
  340. $tmp = tempnam($tmpdir, $prefix);
  341. if (isset($tmp_is_dir)) {
  342. unlink($tmp); // be careful possible race condition here
  343. if (!mkdir($tmp, 0700)) {
  344. return System::raiseError("Unable to create temporary directory $tmpdir");
  345. }
  346. }
  347. return $tmp;
  348. }
  349. /**
  350. * Get the path of the temporal directory set in the system
  351. * by looking in its environments variables.
  352. *
  353. * @return string The temporal directory on the system
  354. */
  355. function tmpdir()
  356. {
  357. if (OS_WINDOWS){
  358. if (isset($_ENV['TEMP'])) {
  359. return $_ENV['TEMP'];
  360. }
  361. if (isset($_ENV['TMP'])) {
  362. return $_ENV['TMP'];
  363. }
  364. if (isset($_ENV['windir'])) {
  365. return $_ENV['windir'] . '\temp';
  366. }
  367. return $_ENV['SystemRoot'] . '\temp';
  368. }
  369. if (isset($_ENV['TMPDIR'])) {
  370. return $_ENV['TMPDIR'];
  371. }
  372. return '/tmp';
  373. }
  374. /**
  375. * The "type" command (show the full path of a command)
  376. *
  377. * @param string $program The command to search for
  378. * @return mixed A string with the full path or false if not found
  379. * @author Stig Bakken <ssb@fast.no>
  380. */
  381. function type($program)
  382. {
  383. // full path given
  384. if (basename($program) != $program) {
  385. return (@is_executable($program)) ? $program : false;
  386. }
  387. // XXX FIXME honor safe mode
  388. $path_delim = OS_WINDOWS ? ';' : ':';
  389. $exe_suffix = OS_WINDOWS ? '.exe' : '';
  390. $path_elements = explode($path_delim, getenv('PATH'));
  391. foreach ($path_elements as $dir) {
  392. $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix;
  393. if (@is_file($file) && @is_executable($file)) {
  394. return $file;
  395. }
  396. }
  397. return false;
  398. }
  399. }
  400. ?>