phpzip.inc.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. class PHPZip
  3. {
  4. function Zip($dir, $zipfilename)
  5. {
  6. if (@function_exists('gzcompress'))
  7. {
  8. $curdir = getcwd();
  9. if (is_array($dir))
  10. {
  11. $filelist = $dir;
  12. }
  13. else
  14. {
  15. $filelist = $this -> GetFileList($dir);
  16. }
  17. if ((!empty($dir))&&(!is_array($dir))&&(file_exists($dir))) chdir($dir);
  18. else chdir($curdir);
  19. if (count($filelist)>0)
  20. {
  21. foreach($filelist as $filename)
  22. {
  23. if (is_file($filename))
  24. {
  25. $fd = fopen ($filename, "r");
  26. $content = @fread ($fd, filesize ($filename));
  27. fclose ($fd);
  28. if (is_array($dir)) $filename = basename($filename);
  29. $this -> addFile($content, $filename);
  30. }
  31. }
  32. $out = $this -> file();
  33. chdir($curdir);
  34. $fp = fopen($zipfilename, "w");
  35. fwrite($fp, $out, strlen($out));
  36. fclose($fp);
  37. }
  38. return 1;
  39. }
  40. else return 0;
  41. }
  42. function GetFileList($dir)
  43. {
  44. if (file_exists($dir))
  45. {
  46. $args = func_get_args();
  47. $pref = $args[1];
  48. $dh = opendir($dir);
  49. while($files = readdir($dh))
  50. {
  51. if (($files!=".")&&($files!=".."))
  52. {
  53. if (is_dir($dir.$files))
  54. {
  55. $curdir = getcwd();
  56. chdir($dir.$files);
  57. $file = array_merge($file, $this -> GetFileList("", "$pref$files/"));
  58. chdir($curdir);
  59. }
  60. else $file[]=$pref.$files;
  61. }
  62. }
  63. closedir($dh);
  64. }
  65. return $file;
  66. }
  67. var $datasec = array();
  68. var $ctrl_dir = array();
  69. var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  70. var $old_offset = 0;
  71. /**
  72. * Converts an Unix timestamp to a four byte DOS date and time format (date
  73. * in high two bytes, time in low two bytes allowing magnitude comparison).
  74. *
  75. * @param integer the current Unix timestamp
  76. *
  77. * @return integer the current date in a four byte DOS format
  78. *
  79. * @access private
  80. */
  81. function unix2DosTime($unixtime = 0) {
  82. $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
  83. if ($timearray['year'] < 1980) {
  84. $timearray['year'] = 1980;
  85. $timearray['mon'] = 1;
  86. $timearray['mday'] = 1;
  87. $timearray['hours'] = 0;
  88. $timearray['minutes'] = 0;
  89. $timearray['seconds'] = 0;
  90. } // end if
  91. return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
  92. ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
  93. } // end of the 'unix2DosTime()' method
  94. /**
  95. * Adds "file" to archive
  96. *
  97. * @param string file contents
  98. * @param string name of the file in the archive (may contains the path)
  99. * @param integer the current timestamp
  100. *
  101. * @access public
  102. */
  103. function addFile($data, $name, $time = 0)
  104. {
  105. $name = str_replace('\\', '/', $name);
  106. $dtime = dechex($this->unix2DosTime($time));
  107. $hexdtime = '\x' . $dtime[6] . $dtime[7]
  108. . '\x' . $dtime[4] . $dtime[5]
  109. . '\x' . $dtime[2] . $dtime[3]
  110. . '\x' . $dtime[0] . $dtime[1];
  111. eval('$hexdtime = "' . $hexdtime . '";');
  112. $fr = "\x50\x4b\x03\x04";
  113. $fr .= "\x14\x00"; // ver needed to extract
  114. $fr .= "\x00\x00"; // gen purpose bit flag
  115. $fr .= "\x08\x00"; // compression method
  116. $fr .= $hexdtime; // last mod time and date
  117. // "local file header" segment
  118. $unc_len = strlen($data);
  119. $crc = crc32($data);
  120. $zdata = gzcompress($data);
  121. $c_len = strlen($zdata);
  122. $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
  123. $fr .= pack('V', $crc); // crc32
  124. $fr .= pack('V', $c_len); // compressed filesize
  125. $fr .= pack('V', $unc_len); // uncompressed filesize
  126. $fr .= pack('v', strlen($name)); // length of filename
  127. $fr .= pack('v', 0); // extra field length
  128. $fr .= $name;
  129. // "file data" segment
  130. $fr .= $zdata;
  131. // "data descriptor" segment (optional but necessary if archive is not
  132. // served as file)
  133. $fr .= pack('V', $crc); // crc32
  134. $fr .= pack('V', $c_len); // compressed filesize
  135. $fr .= pack('V', $unc_len); // uncompressed filesize
  136. // add this entry to array
  137. $this -> datasec[] = $fr;
  138. $new_offset = strlen(implode('', $this->datasec));
  139. // now add to central directory record
  140. $cdrec = "\x50\x4b\x01\x02";
  141. $cdrec .= "\x00\x00"; // version made by
  142. $cdrec .= "\x14\x00"; // version needed to extract
  143. $cdrec .= "\x00\x00"; // gen purpose bit flag
  144. $cdrec .= "\x08\x00"; // compression method
  145. $cdrec .= $hexdtime; // last mod time & date
  146. $cdrec .= pack('V', $crc); // crc32
  147. $cdrec .= pack('V', $c_len); // compressed filesize
  148. $cdrec .= pack('V', $unc_len); // uncompressed filesize
  149. $cdrec .= pack('v', strlen($name) ); // length of filename
  150. $cdrec .= pack('v', 0 ); // extra field length
  151. $cdrec .= pack('v', 0 ); // file comment length
  152. $cdrec .= pack('v', 0 ); // disk number start
  153. $cdrec .= pack('v', 0 ); // internal file attributes
  154. $cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set
  155. $cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
  156. $this -> old_offset = $new_offset;
  157. $cdrec .= $name;
  158. // optional extra field, file comment goes here
  159. // save to central directory
  160. $this -> ctrl_dir[] = $cdrec;
  161. } // end of the 'addFile()' method
  162. /**
  163. * Dumps out file
  164. *
  165. * @return string the zipped file
  166. *
  167. * @access public
  168. */
  169. function file()
  170. {
  171. $data = implode('', $this -> datasec);
  172. $ctrldir = implode('', $this -> ctrl_dir);
  173. return
  174. $data .
  175. $ctrldir .
  176. $this -> eof_ctrl_dir .
  177. pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
  178. pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
  179. pack('V', strlen($ctrldir)) . // size of central dir
  180. pack('V', strlen($data)) . // offset to start of central dir
  181. "\x00\x00"; // .zip file comment length
  182. } // end of the 'file()' method
  183. } // end of the 'PHPZip' class
  184. ?>