PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/io/FileUtil.php

http://rhaco.googlecode.com/
PHP | 771 lines | 508 code | 14 blank | 249 comment | 136 complexity | fb6ec4a669700225f17e66f619580932 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. Rhaco::import("network.Url");
  3. Rhaco::import("lang.StringUtil");
  4. Rhaco::import("lang.Variable");
  5. Rhaco::import("lang.Env");
  6. Rhaco::import("lang.ArrayUtil");
  7. Rhaco::import("exception.ExceptionTrigger");
  8. Rhaco::import("exception.model.PermissionException");
  9. Rhaco::import("exception.model.NotFoundException");
  10. Rhaco::import("resources.Message");
  11. Rhaco::import("io.model.File");
  12. /**
  13. * ????????????
  14. *
  15. * @author Kazutaka Tokushima
  16. * @license New BSD License
  17. * @copyright Copyright 2005- rhaco project. All rights reserved.
  18. */
  19. class FileUtil{
  20. var $resource = array();
  21. var $source = array();
  22. var $regClose = true;
  23. var $transaction = false;
  24. function FileUtil($transaction=false){
  25. $this->transaction = $transaction;
  26. }
  27. /**
  28. * ???????????????
  29. * @param string $filename
  30. */
  31. function close($filename=""){
  32. /*** unit("io.FileUtilTest"); */
  33. $list = array();
  34. if(empty($filename)){
  35. $list = $this->resource;
  36. }else if(isset($this->resource[$filename])){
  37. $list[$filename] = $this->resource[$filename];
  38. }
  39. foreach($list as $name => $fp){
  40. if(is_resource($this->resource[$name]) && (Env::w() || flock($this->resource[$name],LOCK_UN))){
  41. $this->commit($name);
  42. fclose($this->resource[$name]);
  43. }
  44. unset($this->resource[$name]);
  45. unset($this->source[$name]);
  46. }
  47. }
  48. /**
  49. * ??????????
  50. * ??????????????????
  51. * @param string $filename
  52. * @param string $enc
  53. * @return string
  54. */
  55. function fgets($filename,$enc=""){
  56. /*** unit("io.FileUtilTest"); */
  57. if(FileUtil::isFile($filename) && $this->_open($filename) && $this->_seekhome($filename)){
  58. if($this->transaction){
  59. return StringUtil::encode($this->source[$filename],$enc);
  60. }else{
  61. $this->_seekhome($filename);
  62. $buffer = "";
  63. while(!feof($this->resource[$filename])){
  64. $buffer .= fgets($this->resource[$filename],4096);
  65. }
  66. }
  67. return empty($enc) ? $buffer : StringUtil::encode($buffer,$enc);
  68. }
  69. return ExceptionTrigger::raise(new NotFoundException($filename));
  70. }
  71. /**
  72. * ?????????
  73. * ??????????????????
  74. * @param string $filename
  75. * @param string $src
  76. * @param string $enc
  77. * @return boolean
  78. */
  79. function fputs($filename,$src,$enc=""){
  80. /*** unit("io.FileUtilTest"); */
  81. if($this->_open($filename) && $this->_seekend($filename)){
  82. if($this->transaction){
  83. $this->source[$filename] = $this->source[$filename].(empty($enc) ? $src : StringUtil::encode($src,$enc));
  84. return true;
  85. }else{
  86. if(false !== fwrite($this->resource[$filename],(empty($enc) ? $src : StringUtil::encode($src,$enc)))) return true;
  87. ExceptionTrigger::raise(new PermissionException($filename));
  88. }
  89. }
  90. return false;
  91. }
  92. /**
  93. * ??????????
  94. * ??????????????
  95. * @param string $filename
  96. * @param string $src
  97. * @param string $enc
  98. * @return boolean
  99. */
  100. function fwrite($filename,$src,$enc=""){
  101. /*** unit("io.FileUtilTest"); */
  102. if($this->_open($filename) && $this->_seekhome($filename)){
  103. if($this->transaction){
  104. $this->source[$filename] = (empty($enc) ? $src : StringUtil::encode($src,$enc));
  105. return true;
  106. }else{
  107. if(ftruncate($this->resource[$filename],0) && false !== fwrite($this->resource[$filename],(empty($enc) ? $src : StringUtil::encode($src,$enc)))) return true;
  108. ExceptionTrigger::raise(new PermissionException($filename));
  109. }
  110. }
  111. return false;
  112. }
  113. /**
  114. * ??????????????
  115. * @param boolean $bool
  116. */
  117. function setTransaction($bool){
  118. /*** unit("io.FileUtilTest"); */
  119. $this->transaction = Variable::bool($bool);
  120. }
  121. /**
  122. * ???????????????
  123. * @param string $filename
  124. * @return boolean
  125. */
  126. function commit($filename){
  127. /*** unit("io.FileUtilTest"); */
  128. if($this->transaction){
  129. if(isset($this->resource[$filename]) && is_resource($this->resource[$filename]) && $this->_seekhome($filename) && ftruncate($this->resource[$filename],0)){
  130. if(false === fwrite($this->resource[$filename],$this->source[$filename])) return false;
  131. }
  132. }
  133. return true;
  134. }
  135. /**
  136. * ?????????????????
  137. * @param string $filename
  138. * @return boolean
  139. */
  140. function rollback($filename){
  141. /*** unit("io.FileUtilTest"); */
  142. if($this->transaction) $this->_setSource($filename);
  143. }
  144. function _open($filename){
  145. if(!isset($this->resource[$filename])) $this->resource[$filename] = false;
  146. if(!is_resource($this->resource[$filename])){
  147. if($this->mkdir(dirname($filename))){
  148. $this->resource[$filename] = (!FileUtil::exist($filename) || is_writable($filename)) ? @fopen($filename,"ab+") : @fopen($filename,"r");
  149. if(!is_resource($this->resource[$filename])){
  150. unset($this->resource[$filename]);
  151. return ExceptionTrigger::raise(new PermissionException($filename));
  152. }
  153. if($this->transaction) $this->_setSource($filename);
  154. // Windows does not lock
  155. if(Env::w() || flock($this->resource[$filename],LOCK_SH)){
  156. if(!$this->regClose){
  157. Rhaco::register_shutdown(array($this,'close'));
  158. $this->regClose = true;
  159. }
  160. return true;
  161. }
  162. }
  163. return ExceptionTrigger::raise(new PermissionException($filename));
  164. }
  165. return true;
  166. }
  167. function _setSource($filename){
  168. if($this->_seekhome($filename)){
  169. $this->source[$filename] = "";
  170. while(!feof($this->resource[$filename])){
  171. $this->source[$filename] .= fgets($this->resource[$filename],4096);
  172. }
  173. }
  174. }
  175. function _seekend($filename){
  176. return (!preg_match("/\:\/\//",$filename) && isset($this->resource[$filename]) &&
  177. is_resource($this->resource[$filename]) && fseek($this->resource[$filename],0,SEEK_END) >= 0);
  178. }
  179. function _seekhome($filename){
  180. return (isset($this->resource[$filename]) && is_resource($this->resource[$filename]) &&
  181. !preg_match("/\:\/\//",$filename) && fseek($this->resource[$filename],0,SEEK_SET) >= 0);
  182. }
  183. function _isResource($filename){
  184. return (isset($this->resource[$filename]) && is_resource($this->resource[$filename]));
  185. }
  186. /**
  187. * ??????????
  188. * @static
  189. * @param string $filename
  190. * @param string $enc
  191. * @return string
  192. */
  193. function read($filename,$enc=""){
  194. /*** unit("io.FileUtilTest"); */
  195. $buffer = "";
  196. if(is_array($filename)){
  197. foreach($filename as $f){
  198. $buffer .= FileUtil::read($f,$enc);
  199. }
  200. return $buffer;
  201. }
  202. if(!is_readable($filename) || !is_file($filename)){
  203. ExceptionTrigger::raise(new PermissionException($filename));
  204. return null;
  205. }
  206. return (!empty($enc)) ? StringUtil::encode(file_get_contents($filename),$enc) : file_get_contents($filename);
  207. }
  208. /**
  209. * ?????????
  210. * @static
  211. * @param string $filename
  212. * @param string $src
  213. * @param string $enc
  214. * @return string
  215. */
  216. function write($filename,$src="",$enc=""){
  217. /*** unit("io.FileUtilTest"); */
  218. $io = new FileUtil();
  219. if($io->fwrite($filename,$src,$enc)){
  220. $io->close($filename);
  221. unset($io);
  222. return true;
  223. }
  224. unset($io);
  225. return ExceptionTrigger::raise(new PermissionException($filename));
  226. }
  227. /**
  228. * ?????????
  229. * @static
  230. * @param string $filename
  231. * @param string $src
  232. * @param string $enc
  233. * @return string
  234. */
  235. function append($filename,$src="",$enc=""){
  236. /*** unit("io.FileUtilTest"); */
  237. $io = new FileUtil();
  238. if($io->fputs($filename,$src,$enc)){
  239. $io->close($filename);
  240. unset($io);
  241. return true;
  242. }
  243. unset($io);
  244. return false;
  245. }
  246. /**
  247. * ???????????
  248. * @static
  249. * @param string $base
  250. * @param string $path
  251. * @return string
  252. */
  253. function path($base,$path=""){
  254. /***
  255. * eq("/abc/def/hig.php",FileUtil::path("/abc/def","hig.php"));
  256. * eq("/xyz/abc/hig.php",FileUtil::path("/xyz/","/abc/hig.php"));
  257. */
  258. if(!empty($path)){
  259. $path = FileUtil::parseFilename($path);
  260. if(preg_match("/^[\/]/",$path,$null)){
  261. $path = substr($path,1);
  262. }
  263. }
  264. return Url::parseAbsolute(FileUtil::parseFilename($base),FileUtil::parseFilename($path));
  265. }
  266. /**
  267. * ?????????????
  268. * @static
  269. * @param string $filename
  270. * @return string
  271. */
  272. function parseFilename($filename){
  273. /***
  274. * eq("/Users/kaz/Sites/rhacotest/test/io/FileUtilTest.php",FileUtil::parseFilename("/Users/kaz/Sites/rhacotest/test/io/FileUtilTest.php"));
  275. * eq("/Users/kaz/Sites/rhacotest/test/io",FileUtil::parseFilename("/Users/kaz/Sites/rhacotest/test/io"));
  276. * eq("/Users/kaz/Sites/rhacotest/test/io",FileUtil::parseFilename("/Users/kaz/Sites/rhacotest/test/io/"));
  277. * eq("/Users/kaz/Sites/rhacotest/test/io",FileUtil::parseFilename("\\Users\\kaz\\Sites\\rhacotest\\test\\io"));
  278. * eq("C:/Users/kaz/Sites/rhacotest/test/io",FileUtil::parseFilename("C:\\Users\\kaz\\Sites\\rhacotest\\test\\io"));
  279. */
  280. $filename = preg_replace("/[\/]+/","/",str_replace("\\","/",trim($filename)));
  281. return (substr($filename,-1) == "/") ? substr($filename,0,-1) : $filename;
  282. }
  283. /**
  284. * ????????????????????
  285. * @static
  286. * @param $filename
  287. * @return boolean
  288. */
  289. function exist($filename){
  290. /*** unit("io.FileUtilTest"); */
  291. return (is_readable($filename) && (is_file($filename) || is_dir($filename) || is_link($filename)));
  292. }
  293. /**
  294. * ????????????
  295. * @static
  296. * @param $filename
  297. * @return boolean
  298. */
  299. function isFile($filename){
  300. return (is_readable($filename) && is_file($filename));
  301. }
  302. /**
  303. * ????????????
  304. * @static
  305. * @param $filename
  306. * @return boolean
  307. */
  308. function isDir($filename){
  309. return (is_readable($filename) && is_dir($filename));
  310. }
  311. /**
  312. * ?????$directory?????????io.model.File????????
  313. * @static
  314. * @param string $directory
  315. * @param boolean $recursive ???????????
  316. * @return File[]
  317. */
  318. function ls($directory,$recursive=false){
  319. /*** unit("io.FileUtilTest"); */
  320. $dataFileList = array();
  321. $directory = FileUtil::parseFilename($directory);
  322. if(is_dir($directory)){
  323. if($handle = opendir($directory)){
  324. while($pointer = readdir($handle)){
  325. if($pointer != "." && $pointer != ".."){
  326. $source = sprintf("%s/%s",$directory,$pointer);
  327. if(is_file($source)){
  328. $dataFile = new File($source);
  329. $dataFileList[$dataFile->fullname] = $dataFile;
  330. }else{
  331. if($recursive) $dataFileList = array_merge($dataFileList,FileUtil::ls($source,$recursive));
  332. }
  333. }
  334. }
  335. closedir($handle);
  336. }
  337. }else{
  338. ExceptionTrigger::raise(new PermissionException($directory));
  339. }
  340. return $dataFileList;
  341. }
  342. /**
  343. * ???????????
  344. * @static
  345. * @param string $directory
  346. * @param boolean $recursive ???????????
  347. * @return string[]
  348. */
  349. function dirs($directory,$recursive=false,$fullpath=true){
  350. /*** unit("io.FileUtilTest"); */
  351. $list = array();
  352. $directory = FileUtil::parseFilename($directory);
  353. if(is_readable($directory) && is_dir($directory)){
  354. if($handle = opendir($directory)){
  355. while($pointer = readdir($handle)){
  356. if( $pointer != "." && $pointer != ".."){
  357. $source = sprintf("%s/%s",$directory,$pointer);
  358. if(is_dir($source)){
  359. $list[$source] = ($fullpath) ? $source : $pointer;
  360. if($recursive) $list = array_merge($list,FileUtil::dirs($source,$recursive));
  361. }
  362. }
  363. }
  364. closedir($handle) ;
  365. }
  366. }
  367. usort($list,create_function('$a,$b','
  368. $at = strtolower($a);
  369. $bt = strtolower($b);
  370. return ($at == $bt) ? 0 : (($at < $bt) ? -1 : 1);'));
  371. return $list;
  372. }
  373. /**
  374. * ?????????
  375. * @static
  376. * @param string $pattern ????????
  377. * @param string $directory
  378. * @param boolean $recursive ???????????
  379. * @return File[]
  380. */
  381. function find($pattern,$directory,$recursive=false){
  382. /*** unit("io.FileUtilTest"); */
  383. $match = array();
  384. $directory = trim($directory);
  385. $fileList = FileUtil::ls($directory,$recursive);
  386. if(!empty($fileList)){
  387. foreach($fileList as $dataFile){
  388. if(preg_match($pattern,$dataFile->getName())) $match[$dataFile->getFullname()] = $dataFile;
  389. }
  390. }
  391. return $match;
  392. }
  393. /**
  394. * ???
  395. * $source???????????????????
  396. * @static
  397. * @param string $source
  398. * @param string $dest
  399. * @param int $permission
  400. * @return boolean
  401. */
  402. function cp($source,$dest,$permission=755){
  403. /*** unit("io.FileUtilTest"); */
  404. $source = FileUtil::parseFilename($source);
  405. $dest = FileUtil::parseFilename($dest);
  406. $dir = (preg_match("/^(.+)\/[^\/]+$/",$dest,$tmp)) ? $tmp[1] : $dest;
  407. $bool = true;
  408. if(!FileUtil::exist($source)) return false;
  409. if(FileUtil::mkdir($dir)){
  410. if(is_dir($source)){
  411. if($handle = opendir($source)){
  412. while($pointer = readdir($handle)){
  413. if( $pointer != "." && $pointer != ".."){
  414. $srcname = sprintf("%s/%s",$source,$pointer);
  415. $destname = sprintf("%s/%s",$dest,$pointer);
  416. $bool = FileUtil::cp($srcname,$destname);
  417. if(!$bool) break;
  418. }
  419. }
  420. closedir($handle);
  421. }
  422. return $bool;
  423. }else{
  424. $filename = (preg_match("/^.+(\/[^\/]+)$/",$source,$tmp)) ? $tmp[1] : "";
  425. $dest = (is_dir($dest)) ? $dest.$filename : $dest;
  426. if(is_writable(dirname($dest))) copy($source,$dest);
  427. return FileUtil::exist($dest);
  428. }
  429. }
  430. return true;
  431. }
  432. /**
  433. * ??
  434. * $source???????????????????
  435. * @static
  436. * @param string $source
  437. * @return boolean
  438. */
  439. function rm($source){
  440. /*** unit("io.FileUtilTest"); */
  441. if(Variable::istype("File",$source)) $source = $source->getFullname();
  442. $source = FileUtil::parseFilename($source);
  443. if(!FileUtil::exist($source)) return true;
  444. if(is_writable($source)){
  445. if(is_dir($source)){
  446. if($handle = opendir($source)){
  447. $list = array();
  448. while($pointer = readdir($handle)){
  449. if($pointer != "." && $pointer != "..") $list[] = sprintf("%s/%s",$source,$pointer);
  450. }
  451. closedir($handle);
  452. foreach($list as $path){
  453. if(!FileUtil::rm($path)) return false;
  454. }
  455. }
  456. if(rmdir($source)){
  457. clearstatcache();
  458. return true;
  459. }
  460. }else if(is_file($source) && unlink($source)){
  461. clearstatcache();
  462. return true;
  463. }
  464. }
  465. ExceptionTrigger::raise(new PermissionException($source));
  466. return false;
  467. }
  468. /**
  469. * ???????????
  470. * @static
  471. * @param string $source
  472. * @param int $permission
  473. * @return boolean
  474. */
  475. function mkdir($source,$permission=null){
  476. /*** unit("io.FileUtilTest"); */
  477. $source = FileUtil::parseFilename($source);
  478. if(!FileUtil::isDir($source)){
  479. $path = $source;
  480. $dirstack = array();
  481. while(!is_dir($path) && $path != DIRECTORY_SEPARATOR){
  482. array_unshift($dirstack,$path);
  483. $path = dirname($path);
  484. }
  485. while($path = array_shift($dirstack)){
  486. $bool = (empty($permission)) ? @mkdir($path) : @mkdir($path,Rhaco::phpexe(sprintf("return %04d;",$permission)));
  487. if($bool === false) return ExceptionTrigger::raise(new PermissionException($path));
  488. }
  489. }
  490. if(!empty($permission)) FileUtil::chmod($source,$permission);
  491. return true;
  492. }
  493. /**
  494. * ??
  495. * @static
  496. * @param string $source
  497. * @param string $dest
  498. * @return boolean
  499. */
  500. function mv($source,$dest){
  501. /*** unit("io.FileUtilTest"); */
  502. $source = FileUtil::parseFilename($source);
  503. $dest = FileUtil::parseFilename($dest);
  504. return (FileUtil::exist($source) && FileUtil::mkdir(dirname($dest))) ? rename($source,$dest) : false;
  505. }
  506. /**
  507. * ???????
  508. * @static
  509. * @param string $source
  510. * @param int $permission
  511. * @return boolean
  512. */
  513. function chmod($source,$permission=755){
  514. if(FileUtil::exist($source) && Env::w()){
  515. return chmod($source,Rhaco::phpexe(sprintf("return %04d;",$permission)));
  516. }
  517. return true;
  518. }
  519. /**
  520. * ????????????
  521. * @static
  522. * @param string $filename
  523. * @param string $format
  524. * @return int
  525. */
  526. function size($filename,$format="kb"){
  527. if(is_readable($filename) && is_file($filename)){
  528. switch(strtolower($format)){
  529. case "b": return filesize($filename);
  530. case "mb": return ceil((filesize($filename) / 1024) / 1024);
  531. case "gb": return ceil(((filesize($filename) / 1024) / 1024) / 1024);
  532. case "tb": return ceil((((filesize($filename) / 1024) / 1024) / 1024) / 1024);
  533. case "kb":
  534. default: return $size = ceil(filesize($filename) / 1024);
  535. }
  536. }
  537. return 0;
  538. }
  539. /**
  540. * ????????????
  541. * @static
  542. * @param string $directory
  543. * @param string $format
  544. * @return int
  545. */
  546. function free($directory,$format="kb"){
  547. if(is_readable($directory) && is_dir($directory)){
  548. switch(strtolower($format)){
  549. case "b": return disk_free_space($directory);
  550. case "mb": return ceil((disk_free_space($directory) / 1024) / 1024);
  551. case "gb": return ceil(((disk_free_space($directory) / 1024) / 1024) / 1024);
  552. case "tb": return ceil((((disk_free_space($directory) / 1024) / 1024) / 1024) / 1024);
  553. case "kb":
  554. default: return ceil(disk_free_space($directory) / 1024);
  555. }
  556. }
  557. return 0;
  558. }
  559. /**
  560. * ???????
  561. * @static
  562. * @param $filename
  563. * @return int
  564. */
  565. function time($filename){
  566. return (is_readable($filename) && is_file($filename)) ? filemtime($filename) : -1;
  567. }
  568. /**
  569. * ????????????????????
  570. * @static
  571. * @param string/string[] $paths
  572. * @return string
  573. */
  574. function pack($paths,$replace=""){
  575. /***
  576. * $path = FileUtil::path(Rhaco::rhacopath(),"/io/FileUtil.php");
  577. * $paths = array("FileUtil.php"=>$path,"io/FileUtil.php"=>$path);
  578. * $src = FileUtil::pack($paths);
  579. * preg_match_all("/\[\[(.+)?\]\]/",$src,$match);
  580. * eq(2,sizeof($match[1]));
  581. */
  582. $io = new FileUtil();
  583. $result = "";
  584. $packs = array();
  585. foreach(ArrayUtil::arrays($paths) as $key => $value){
  586. if(preg_match("/^[\d]+$/",$key)){
  587. if(is_dir($value)){
  588. foreach(FileUtil::dirs($value,true) as $dir){
  589. $packs[substr($dir,strlen(empty($replace) ? $value : $replace))] = $dir;
  590. }
  591. foreach(FileUtil::ls($value,true) as $file){
  592. $packs[substr($file->fullname,strlen(empty($replace) ? $value : $replace))] = $file->fullname;
  593. }
  594. }else if(is_file($value)){
  595. $packs[substr($value,strlen($replace))] = $value;
  596. }
  597. }else{
  598. $packs[$key] = $value;
  599. }
  600. }
  601. foreach($packs as $name => $path){
  602. if(!FileUtil::exist($path)) Logger::error("pack fail [".$path."]");
  603. if(is_file($path)){
  604. $result .= "[[".$name."]]\n";
  605. $result .= chunk_split(base64_encode($io->read($path)),76,"\n");
  606. $result .= "\n\n";
  607. }else if(is_dir($path)){
  608. $result .= "[[[".$name."]]]\n";
  609. $result .= "\n\n";
  610. }
  611. }
  612. return $result;
  613. }
  614. /**
  615. * pack????????????
  616. * @static
  617. * @param string $src
  618. * @param string $outputdir
  619. * @return boolean
  620. */
  621. function unpack($src,$outputdir){
  622. $bool = true;
  623. $src = StringUtil::toULD($src);
  624. foreach(explode("\n\n\n",$src) as $value){
  625. list($conf,$body) = explode("\n",$value."\n",2);
  626. if(!empty($conf)){
  627. if(preg_match("/^\[\[\[([^\[\]]+?)\]\]\]/",$conf,$match)){
  628. if(!FileUtil::mkdir(FileUtil::path($outputdir,$match[1]))) $bool = false;
  629. }else if(preg_match("/\[\[([^\[\]]+?)\]\]/",$conf,$match)){
  630. if(!FileUtil::write(FileUtil::path($outputdir,$match[1]),(base64_decode($body)))) $bool = false;
  631. }
  632. }
  633. }
  634. return $bool;
  635. }
  636. /**
  637. * ???????????
  638. * @param string $path
  639. * @return boolean
  640. */
  641. function isPublic($path){
  642. return (strpos($path,"/.") === false && (basename($path) == "__init__.php" || strpos($path,"/_") === false));
  643. }
  644. /**
  645. * ????????????????tar???????????
  646. * @param string $base
  647. * @param string $path
  648. * @param string $ignore_pattern ??????
  649. * @return string
  650. */
  651. function tar($base,$path=null,$ignore_pattern=null){
  652. $result = null;
  653. $files = array();
  654. $base = FileUtil::parseFilename($base);
  655. $path = FileUtil::parseFilename($path);
  656. $ignore = (!empty($ignore_pattern));
  657. if(substr($base,0,-1) != "/") $base .= "/";
  658. $filepath = Url::parseAbsolute($base,$path);
  659. if(is_dir($filepath)){
  660. foreach(FileUtil::dirs($filepath,true) as $dir) $files[$dir] = FileUtil::_tarTypeDir();
  661. foreach(self::ls($filepath,true) as $file) $files[$file->getFullname()] = FileUtil::_tarTypeFile();
  662. }else{
  663. $files[$filepath] = FileUtil::_tarTypeFile();
  664. }
  665. foreach($files as $filename => $type){
  666. $target_filename = str_replace($base,"",$filename);
  667. if(!$ignore || !FileUtil::_isPattern($ignore_pattern,$target_filename)){
  668. switch($type){
  669. case FileUtil::_tarTypeFile():
  670. $info = stat($filename);
  671. $rp = fopen($filename,"rb");
  672. $result .= FileUtil::_tarHead($type,$target_filename,filesize($filename),fileperms($filename),$info[4],$info[5],filemtime($filename));
  673. while(!feof($rp)){
  674. $buf = fread($rp,512);
  675. if($buf !== "") $result .= pack("a512",$buf);
  676. }
  677. fclose($rp);
  678. break;
  679. case FileUtil::_tarTypeDir():
  680. $result .= FileUtil::_tarHead($type,$target_filename);
  681. break;
  682. }
  683. }
  684. }
  685. $result .= pack("a1024",null);
  686. return $result;
  687. }
  688. function _isPattern($pattern,$value){
  689. $pattern = (is_array($pattern)) ? $pattern : array($pattern);
  690. foreach($pattern as $p){
  691. if(preg_match("/".str_replace(array("\/","/","__SLASH__"),array("__SLASH__","\/","\/"),$p)."/",$value)) return true;
  692. }
  693. return false;
  694. }
  695. function _tarHead($type,$filename,$filesize=0,$fileperms=0744,$uid=0,$gid=0,$update_date=null){
  696. if($update_date === null) $update_date = time();
  697. $checksum = 256;
  698. $first = pack("a100a8a8a8a12A12",$filename,
  699. sprintf("%06s ",decoct($fileperms)),sprintf("%06s ",decoct($uid)),sprintf("%06s ",decoct($gid)),
  700. sprintf("%011s ",decoct(($type === 0) ? $filesize : 0)),sprintf("%11s",decoct($update_date)));
  701. $last = pack("a1a100a6a2a32a32a8a8a155a12",$type,null,null,null,null,null,null,null,null,null);
  702. for($i=0;$i<strlen($first);$i++) $checksum += ord($first[$i]);
  703. for($i=0;$i<strlen($last);$i++) $checksum += ord($last[$i]);
  704. return $first.pack("a8",sprintf("%6s ",decoct($checksum))).$last;
  705. }
  706. function _tarTypeDir(){
  707. return 5;
  708. }
  709. function _tarTypeFile(){
  710. return 0;
  711. }
  712. /**
  713. * tar??????$outpath????????
  714. * @param string $src
  715. * @param string $outpath
  716. * @return array
  717. */
  718. function untar($src,$outpath=null){
  719. $result = array();
  720. $out = null;
  721. for($pos=0,$vsize=0,$cur="";;){
  722. $buf = substr($src,$pos,512);
  723. if(strlen($buf) < 512) break;
  724. $data = unpack("a100name/a8mode/a8uid/a8gid/a12size/a12mtime/"
  725. ."a8chksum/"
  726. ."a1typeflg/a100linkname/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix",
  727. $buf);
  728. $pos += 512;
  729. if(!empty($data["name"])){
  730. $obj = new stdClass();
  731. $obj->type = (int)$data["typeflg"];
  732. $obj->path = $data["name"];
  733. $obj->update = base_convert($data["mtime"],8,10);
  734. if(!empty($outpath)) $out = Url::parseAbsolute($outpath,$obj->path);
  735. switch($obj->type){
  736. case FileUtil::_tarTypeFile():
  737. $obj->size = base_convert($data["size"],8,10);
  738. $obj->content = substr($src,$pos,$obj->size);
  739. $pos += (ceil($obj->size / 512) * 512);
  740. if(!empty($outpath)){
  741. FileUtil::write($out,$obj->content);
  742. touch($out,$obj->update);
  743. }
  744. break;
  745. case FileUtil::_tarTypeDir():
  746. if(!empty($outpath)){
  747. FileUtil::mkdir($out);
  748. }
  749. break;
  750. }
  751. $result[$obj->path] = $obj;
  752. }
  753. }
  754. return $result;
  755. }
  756. }
  757. ?>