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