Ticket #538: 538-jZipCreator.diff
| File 538-jZipCreator.diff, 14.4 kB (added by Julien, 4 months ago) |
|---|
-
build/manifests/jelix-lib.mn
old new 703 703 ! WSDLException.class.php 704 704 ! WSDLStruct.class.php 705 705 ! WSException.class.php 706 707 cd lib/zip 708 zip.lib.php -
lib/zip/zip.lib.php
old new 1 <?php 2 /** 3 * Zip file creation class. 4 * Makes zip files. 5 * 6 * Based on : 7 * 8 * http://www.zend.com/codex.php?id=535&single=1 9 * By Eric Mueller <eric@themepark.com> 10 * 11 * http://www.zend.com/codex.php?id=470&single=1 12 * by Denis125 <webmaster@atlant.ru> 13 * 14 * a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified 15 * date and time of the compressed file 16 * 17 * Official ZIP file format: http://www.pkware.com/appnote.txt 18 * 19 * @access public 20 */ 21 class zipfile 22 { 23 /** 24 * Array to store compressed data 25 * 26 * @var array $datasec 27 */ 28 var $datasec = array(); 29 30 /** 31 * Central directory 32 * 33 * @var array $ctrl_dir 34 */ 35 var $ctrl_dir = array(); 36 37 /** 38 * End of central directory record 39 * 40 * @var string $eof_ctrl_dir 41 */ 42 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; 43 44 /** 45 * Last offset position 46 * 47 * @var integer $old_offset 48 */ 49 var $old_offset = 0; 50 51 52 /** 53 * Converts an Unix timestamp to a four byte DOS date and time format (date 54 * in high two bytes, time in low two bytes allowing magnitude comparison). 55 * 56 * @param integer the current Unix timestamp 57 * 58 * @return integer the current date in a four byte DOS format 59 * 60 * @access private 61 */ 62 function unix2DosTime($unixtime = 0) { 63 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); 64 65 if ($timearray['year'] < 1980) { 66 $timearray['year'] = 1980; 67 $timearray['mon'] = 1; 68 $timearray['mday'] = 1; 69 $timearray['hours'] = 0; 70 $timearray['minutes'] = 0; 71 $timearray['seconds'] = 0; 72 } // end if 73 74 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | 75 ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); 76 } // end of the 'unix2DosTime()' method 77 78 79 /** 80 * Adds "file" to archive 81 * 82 * @param string file contents 83 * @param string name of the file in the archive (may contains the path) 84 * @param integer the current timestamp 85 * 86 * @access public 87 */ 88 function addFile($data, $name, $time = 0) 89 { 90 $name = str_replace('\\', '/', $name); 91 92 $dtime = dechex($this->unix2DosTime($time)); 93 $hexdtime = '\x' . $dtime[6] . $dtime[7] 94 . '\x' . $dtime[4] . $dtime[5] 95 . '\x' . $dtime[2] . $dtime[3] 96 . '\x' . $dtime[0] . $dtime[1]; 97 eval('$hexdtime = "' . $hexdtime . '";'); 98 99 $fr = "\x50\x4b\x03\x04"; 100 $fr .= "\x14\x00"; // ver needed to extract 101 $fr .= "\x00\x00"; // gen purpose bit flag 102 $fr .= "\x08\x00"; // compression method 103 $fr .= $hexdtime; // last mod time and date 104 105 // "local file header" segment 106 $unc_len = strlen($data); 107 $crc = crc32($data); 108 $zdata = gzcompress($data); 109 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug 110 $c_len = strlen($zdata); 111 $fr .= pack('V', $crc); // crc32 112 $fr .= pack('V', $c_len); // compressed filesize 113 $fr .= pack('V', $unc_len); // uncompressed filesize 114 $fr .= pack('v', strlen($name)); // length of filename 115 $fr .= pack('v', 0); // extra field length 116 $fr .= $name; 117 118 // "file data" segment 119 $fr .= $zdata; 120 121 // "data descriptor" segment (optional but necessary if archive is not 122 // served as file) 123 // nijel(2004-10-19): this seems not to be needed at all and causes 124 // problems in some cases (bug #1037737) 125 //$fr .= pack('V', $crc); // crc32 126 //$fr .= pack('V', $c_len); // compressed filesize 127 //$fr .= pack('V', $unc_len); // uncompressed filesize 128 129 // add this entry to array 130 $this -> datasec[] = $fr; 131 132 // now add to central directory record 133 $cdrec = "\x50\x4b\x01\x02"; 134 $cdrec .= "\x00\x00"; // version made by 135 $cdrec .= "\x14\x00"; // version needed to extract 136 $cdrec .= "\x00\x00"; // gen purpose bit flag 137 $cdrec .= "\x08\x00"; // compression method 138 $cdrec .= $hexdtime; // last mod time & date 139 $cdrec .= pack('V', $crc); // crc32 140 $cdrec .= pack('V', $c_len); // compressed filesize 141 $cdrec .= pack('V', $unc_len); // uncompressed filesize 142 $cdrec .= pack('v', strlen($name)); // length of filename 143 $cdrec .= pack('v', 0); // extra field length 144 $cdrec .= pack('v', 0); // file comment length 145 $cdrec .= pack('v', 0); // disk number start 146 $cdrec .= pack('v', 0); // internal file attributes 147 $cdrec .= pack('V', 32); // external file attributes - 'archive' bit set 148 149 $cdrec .= pack('V', $this -> old_offset); // relative offset of local header 150 $this -> old_offset += strlen($fr); 151 152 $cdrec .= $name; 153 154 // optional extra field, file comment goes here 155 // save to central directory 156 $this -> ctrl_dir[] = $cdrec; 157 } // end of the 'addFile()' method 158 159 160 /** 161 * Dumps out file 162 * 163 * @return string the zipped file 164 * 165 * @access public 166 */ 167 function file() 168 { 169 $data = implode('', $this -> datasec); 170 $ctrldir = implode('', $this -> ctrl_dir); 171 172 return 173 $data . 174 $ctrldir . 175 $this -> eof_ctrl_dir . 176 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk" 177 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall 178 pack('V', strlen($ctrldir)) . // size of central dir 179 pack('V', strlen($data)) . // offset to start of central dir 180 "\x00\x00"; // .zip file comment length 181 } // end of the 'file()' method 182 183 } // end of the 'zipfile' class 184 185 ?> -
lib/jelix/utils/jZipCreator.class.php
old new 3 3 * @package jelix 4 4 * @subpackage utils 5 5 * @author Laurent Jouanneau 6 * @contributor Julien Issler 6 7 * @copyright 2006 Laurent Jouanneau 8 * @copyright 2008 Julien Issler 7 9 * @link http://www.jelix.org 8 10 * @licence GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html 9 11 */ 10 12 13 // need zipfile class from phpMyAdmin 14 require_once(LIB_PATH.'zip/zip.lib.php'); 15 11 16 /** 12 17 * Class to create a zip file. 13 18 * @package jelix 14 19 * @subpackage utils 15 20 * @link http://www.pkware.com/business_and_developers/developer/appnote/ Official ZIP file format 16 21 */ 17 class jZipCreator {22 class jZipCreator{ 18 23 19 /** 20 * contains all file records 21 * @var array $fileRecords 22 */ 23 protected $fileRecords = array(); 24 protected $_zipfile; 24 25 25 /** 26 * Contains the central directory 27 * @var array $centralDirectory 28 */ 29 protected $centralDirectory = array(); 26 public function __construct(){ 27 $this->_zipfile = new zipfile(); 28 } 30 29 31 30 /** 32 * Offset of the central directory33 * @var integer $centralDirOffset34 */35 protected $centralDirOffset = 0;36 37 /**38 31 * adds a physical file to the zip archive 39 32 * 40 33 * @param string $filename the path of the physical file you want to add 41 34 * @param string $zipPath the path of the file inside the zip archive 42 35 */ 43 public function addFile($filename, $zipFileName=''){36 public function addFile($filename,$zipFileName=''){ 44 37 if($zipFileName == '') $zipFileName = $filename; 45 38 if(file_exists($filename)){ 46 $this-> addContentFile($zipFileName, file_get_contents($filename),filemtime($filename));39 $this->_zipfile->addFile(file_get_contents($filename),$zipFileName,filemtime($filename)); 47 40 }else{ 48 41 throw new jException('jelix~errors.file.notexists', $filename); 49 42 } … … 84 77 * @param string $content the content of the file 85 78 * @param integer $filetime the time modification of the file 86 79 */ 87 public function addContentFile($zipFileName, $content, $filetime = 0){ 88 89 // converts unix timestamp to dos binary format 90 if($filetime == 0) 91 $filetime = mktime(); 92 elseif($filetime < 315529200) // 01/01/1980 93 $filetime = 315529200; 94 95 $dt = getdate($filetime); 96 97 $filetime = pack('V',($dt['seconds'] >> 1) | ($dt['minutes'] << 5) | ($dt['hours'] << 11) | 98 ($dt['mday'] << 16) | ($dt['mon'] << 21) | (($dt['year'] - 1980) << 25)); 99 100 /* 101 generation of the file record 102 103 file record: 104 - local file header signature 4 bytes (0x04034b50) 105 - version needed to extract 2 bytes 14 106 - general purpose bit flag 2 bytes 0 107 - compression method 2 bytes 0x8 108 - last mod file time 2 bytes (fileinfo) 109 - last mod file date 2 bytes (fileinfo) 110 - crc-32 4 bytes (fileinfo) 111 - compressed size 4 bytes (fileinfo) 112 - uncompressed size 4 bytes (fileinfo) 113 - file name length 2 bytes (fileinfo) 114 - extra field length 2 bytes (here 0) (fileinfo) 115 - file name (variable size) 116 - extra field (variable size) (here nothing) 117 - compressed content 118 */ 119 $zipFileName = str_replace('\\', '/', $zipFileName); 120 121 $zippedcontent = substr(gzcompress($content), 2, -4); // compress and fix crc bug 122 123 $fileinfo = $filetime.pack('V', crc32($content)); 124 $fileinfo .= pack('V', strlen($zippedcontent)). pack('V', strlen($content)); 125 $fileinfo .= pack('v', strlen($zipFileName))."\x00\x00"; 126 127 $filerecord = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00"; 128 $filerecord .= $fileinfo.$zipFileName.$zippedcontent; 129 130 $this->fileRecords[] = $filerecord; 131 132 133 /* 134 register the file into the central directory record 135 it contains an header for each file 136 - central file header signature 4 bytes (0x02014b50) 137 - version made by 2 bytes 0=DOS 138 - version needed to extract 2 bytes 0x14 139 - general purpose bit flag 2 bytes 0 140 - compression method 2 bytes 0x8 141 - last mod file time 2 bytes (fileinfo) 142 - last mod file date 2 bytes (fileinfo) 143 - crc-32 4 bytes (fileinfo) 144 - compressed size 4 bytes (fileinfo) 145 - uncompressed size 4 bytes (fileinfo) 146 - file name length 2 bytes (fileinfo) 147 - extra field length 2 bytes 0 (fileinfo) 148 - file comment length 2 bytes 0 149 - disk number start 2 bytes 0 150 - internal file attributes 2 bytes 0 151 - external file attributes 4 bytes 32 : 'archive' bit set 152 - relative offset of local header 4 bytes 153 - file name (variable size) 154 - extra field (variable size) 155 - file comment (variable size) 156 */ 157 $cdrecord = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".$fileinfo; 158 $cdrecord .= "\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00"; 159 $cdrecord .= pack('V', $this ->centralDirOffset ); 160 $cdrecord .= $zipFileName; 161 162 $this->centralDirectory[] = $cdrecord; 163 164 $this ->centralDirOffset += strlen($filerecord); 165 80 public function addContentFile($zipfilename,$content,$filetime = 0){ 81 $this->_zipfile->addFile($content,$zipfilename,$filetime); 166 82 } 167 83 168 169 84 /** 170 * create the conten uof the zip file85 * create the content of the zip file 171 86 * @return string the content of the zip file 172 87 */ 173 88 public function getContent(){ 174 175 $centraldir = implode('', $this->centralDirectory); 176 $c = pack('v', count($this ->centralDirectory)); 177 178 /* 179 zip file : 180 - file records 181 - central dir 182 - end of central dir signature 4 bytes (0x06054b50) 183 - number of this disk 2 bytes (0 here) 184 - number of the disk with the 185 start of the central directory 2 bytes (0 here) 186 - total number of entries in the 187 central directory on this disk 2 bytes 188 - total number of entries in 189 the central directory 2 bytes 190 - size of the central directory 4 bytes 191 - offset of start of central directory with respect to 192 the starting disk number 4 bytes 193 - .ZIP file comment length 2 bytes 194 - .ZIP file comment (variable size) 195 */ 196 return implode('', $this->fileRecords).$centraldir."\x50\x4b\x05\x06\x00\x00\x00\x00".$c.$c. 197 pack('V', strlen($centraldir)).pack('V', $this ->centralDirOffset)."\x00\x00"; 89 return $this->_zipfile->file(); 198 90 } 199 }200 91 92 } 201 93 ?>
