PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/compressor.php

http://textmotion.googlecode.com/
PHP | 242 lines | 149 code | 46 blank | 47 comment | 34 complexity | be44f3f355cbafeeeca6d56ba61c57cd MD5 | raw file
Possible License(s): MIT, CC0-1.0
  1. <?php
  2. /**
  3. * Compression handler
  4. * ---
  5. * Written by Jose Carlos Nieto <xiam@menteslibres.org>
  6. * Copyright (c) 2007 Jose Carlos Nieto <xiam@menteslibres.org>
  7. *
  8. * Licensed under The MIT License
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @author Jose Carlos Nieto <xiam@menteslibres.org>
  12. * @copyright Copyright (c) 2007-2008, Jose Carlos Nieto <xiam@menteslibres.org>
  13. * @link http://opensource.astrata.com.mx Astrata Open Source Projects
  14. * @version $Revision: 1115 $
  15. * @modifiedby $LastChangedBy: xiam.core $
  16. * @lastmodified $Date: 2008-05-26 14:32:25 +1000 (Mon, 26 May 2008) $
  17. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  18. *
  19. */
  20. class compressor extends tm_object {
  21. public function untar($file, $dest, $overwrite = true) {
  22. $env =& $this->using('env');
  23. /*
  24. *********************************************************
  25. This code portion is based on:
  26. Simple Machines Forum
  27. *********************************************************
  28. URL: http://www.simplemachines.org
  29. License: GNU/GPL
  30. Copyright: (c) Lewis Media (http://www.lewismedia.com)
  31. Software Version: SMF 1.0.3
  32. **********************************************************
  33. */
  34. // fixing destination
  35. if (substr($dest, -1) != '/')
  36. $dest = $dest.'/';
  37. @mkdir($dest, 0777);
  38. // checking destination
  39. if (!is_writable($dest)) {
  40. $this->error('Could not untar, destination directory "'.$dest.'" is not writable.');
  41. }
  42. $fp = fopen($file, "r");
  43. $octdec = array('mode', 'uid', 'gid', 'size', 'mtime', 'checksum', 'type');
  44. $blocks = filesize($file)/512 - 1;
  45. $offset = 0;
  46. while ($offset < $blocks) {
  47. fseek($fp, $offset << 9);
  48. $header = fread($fp, 512);
  49. if (!($current = @unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100linkname/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155path", $header))) {
  50. return false;
  51. }
  52. foreach ($current as $name => $value) {
  53. $current[$name]= trim($current[$name]);
  54. if (in_array($name, $octdec)) {
  55. $current[$name] = octdec($current[$name]);
  56. }
  57. }
  58. $checksum = 256;
  59. for ($i = 0; $i < 148; $i++) {
  60. $checksum += ord($header{$i});
  61. }
  62. for ($i = 156; $i < 512; $i++) {
  63. $checksum += ord($header{$i});
  64. }
  65. if ($current["checksum"] != $checksum) {
  66. if ($current["filename"]) {
  67. $env->error('Checksum error');
  68. } else {
  69. // Finished!
  70. return true;
  71. }
  72. }
  73. // protecting from parent directory writing
  74. $current["filename"] = preg_replace("/(\.\.\/|\/\.\.)/", "", $current["filename"]);
  75. $output = $dest.$current["filename"];
  76. $offset++;
  77. switch ($current["type"]) {
  78. case 5:
  79. // directory
  80. mkdir($output, 0755);
  81. break;
  82. default:
  83. if (!file_exists($output) || $overwrite) {
  84. fseek($fp, $offset << 9);
  85. $fh = fopen($output, 'wb');
  86. if ($current["size"]) {
  87. fwrite($fh, fread($fp, $current["size"]));
  88. }
  89. fclose($fh);
  90. }
  91. break;
  92. }
  93. $offset += ceil($current["size"]/512);
  94. @chmod($output, $current["mode"]);
  95. }
  96. fclose($fp);
  97. return true;
  98. }
  99. function unpack($file, $dest) {
  100. extract(
  101. $this->using(
  102. 'archive',
  103. 'env'
  104. )
  105. );
  106. @mkdir($dest, 0777);
  107. // Directory fix
  108. if (substr($dest, -1) != "/")
  109. $dest .= '/';
  110. if (!is_writable($dest)) {
  111. $this->error('Could not uncompress, destination directory "'.$dest.'" is not writable.');
  112. }
  113. if (($fp = fopen($file, "r")) != false) {
  114. $header = fread($fp, 4);
  115. fclose($fp);
  116. // guessing file type
  117. switch ($header) {
  118. case "\x1f\x8b\x08\x00":
  119. // gzip
  120. $fopen = "gzopen";
  121. $feof = "gzeof";
  122. $fread = "gzread";
  123. $fclose = "gzclose";
  124. break;
  125. case "\x42\x5a\x68\x39":
  126. // bzip2
  127. $fopen = "bzopen";
  128. $feof = "feof";
  129. $fread = "bzread";
  130. $fclose = "bzclose";
  131. break;
  132. case "\x50\x4b\x03\x04":
  133. // zip
  134. $zh = zip_open($file);
  135. while ($zfp = zip_read($zh)) {
  136. if (zip_entry_open($zh, $zfp, "w")) {
  137. $zipname = trim(zip_entry_name($zfp));
  138. // preventing hacks
  139. if (!preg_match("/\.\./", $zipname)) {
  140. $path = "{$dest}{$zipname}";
  141. if (substr($zipname, -1) == '/') {
  142. mkdir($path, 0777);
  143. } else {
  144. $fh = fopen ($path, "w");
  145. fwrite($fh, zip_entry_read($zfp, zip_entry_filesize($zfp)));
  146. fclose($fh);
  147. zip_entry_close($zfp);
  148. }
  149. chmod ($path, 0775);
  150. }
  151. }
  152. }
  153. zip_close($zh);
  154. return true;
  155. break;
  156. default:
  157. if ($archive->extension($file) == "tar") {
  158. // let's suppose this is as a .tar archive
  159. $fopen = "fopen";
  160. $feof = "feof";
  161. $fread = "fread";
  162. $fclose = "fclose";
  163. } else {
  164. trigger_error("Unknown file type. You may specify .tar.gz, .tar.bz2, .zip or even .tar files only.", E_USER_ERROR);
  165. }
  166. break;
  167. }
  168. // temporary file name
  169. $temp = tempnam($dest, "tar");
  170. if (isset($fopen)) {
  171. // creating temporary file
  172. $tempf = fopen($temp, "w");
  173. // uncompressing
  174. $fi = $fopen($file, "r");
  175. while (!$feof($fi))
  176. fwrite($tempf, $fread($fi, 1024*1024));
  177. $fclose($fi);
  178. // closing temp file
  179. fclose($tempf);
  180. }
  181. $this->untar($temp, $dest);
  182. // removing temporary file
  183. unlink($temp);
  184. return true;
  185. } else {
  186. return false;
  187. }
  188. }
  189. static function run_test() {
  190. $c = new compressor();
  191. $c->unpack('/tmp/tm.tar.bz2', '/tmp/test_1');
  192. $c->unpack('/tmp/tm.tar.gz', '/tmp/test_2');
  193. }
  194. }
  195. // compressor::run_test();
  196. ?>