📄 正在查看:twcms/kongphp/ext/kp_zip.class.php
大小:8,026 字节 · 修改:2014-01-23 01:42:52 · 行数:316
1<?php
2/**
3 * Copyright (C) 2013-2014 www.kongphp.com All rights reserved.
4 * Licensed http://www.gnu.org/licenses/lgpl.html
5 * Author: wuzhaohuan <kongphp@gmail.com>
6 */
7
8class kp_zip {
9 // 解压
10 public static function unzip($zipFile, $toDir) {
11 $unzip = new php_unzip();
12 foreach($unzip->ReadFile($zipFile) as $row) {
13 $file = $toDir.'/'.$row['Path'].'/'.$row['Name'];
14 $parentDir = dirname($file);
15 !is_dir($parentDir) && mkdir($parentDir, 0777, TRUE);
16 if(file_put_contents($file, $row['Data']) !== FALSE) {
17 touch($file, $row['Time'], $row['Time']);
18 }
19 }
20 return TRUE;
21 }
22
23 // 压缩 $filePath 目录或文件
24 public static function zip($filePath, $zipFile) {
25 $zip = new php_zip();
26 if(is_dir($filePath)) {
27 $zip->addDir($filePath);
28 }else{
29 $zip->addFile(file_get_contents($filePath), basename($filePath), filemtime($filePath));
30 }
31 return file_put_contents($zipFile, $zip->file());
32 }
33}
34
35class php_zip {
36 var $datasec = array();
37 var $ctrl_dir = array();
38 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
39 var $old_offset = 0;
40
41 function unix2DosTime($unixtime = 0) {
42 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
43
44 if($timearray['year'] < 1980) {
45 $timearray['year'] = 1980;
46 $timearray['mon'] = 1;
47 $timearray['mday'] = 1;
48 $timearray['hours'] = 0;
49 $timearray['minutes'] = 0;
50 $timearray['seconds'] = 0;
51 }
52
53 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
54 ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
55 }
56
57 function addDir($dir) {
58 static $rootDir;
59
60 if(empty($rootDir)) $rootDir = $dir.'/';
61 $dh = opendir($dir);
62 while(($file = readdir($dh)) !== FALSE) {
63 if($file == '.' || $file == '..') continue;
64 $fullpath = $dir.'/'.$file;
65 if(is_dir($fullpath)) {
66 $this->addDir($fullpath);
67 }else{
68 $this->addFile(file_get_contents($fullpath), str_replace($rootDir, '', $fullpath), filemtime($fullpath));
69 }
70 }
71 closedir($dh);
72 }
73
74 function addFile($data, $name, $time = 0) {
75 $name = str_replace('\\', '/', $name);
76
77 $dtime = dechex($this->unix2DosTime($time));
78 $hexdtime = '\x' . $dtime[6] . $dtime[7]
79 . '\x' . $dtime[4] . $dtime[5]
80 . '\x' . $dtime[2] . $dtime[3]
81 . '\x' . $dtime[0] . $dtime[1];
82 eval('$hexdtime = "' . $hexdtime . '";');
83
84 $fr = "\x50\x4b\x03\x04";
85 $fr .= "\x14\x00";
86 $fr .= "\x00\x00";
87 $fr .= "\x08\x00";
88 $fr .= $hexdtime;
89
90 $unc_len = strlen($data);
91 $crc = crc32($data);
92 $zdata = gzcompress($data);
93 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
94 $c_len = strlen($zdata);
95 $fr .= pack('V', $crc);
96 $fr .= pack('V', $c_len);
97 $fr .= pack('V', $unc_len);
98 $fr .= pack('v', strlen($name));
99 $fr .= pack('v', 0);
100 $fr .= $name;
101
102 $fr .= $zdata;
103
104 $this -> datasec[] = $fr;
105
106 $cdrec = "\x50\x4b\x01\x02";
107 $cdrec .= "\x00\x00";
108 $cdrec .= "\x14\x00";
109 $cdrec .= "\x00\x00";
110 $cdrec .= "\x08\x00";
111 $cdrec .= $hexdtime;
112 $cdrec .= pack('V', $crc);
113 $cdrec .= pack('V', $c_len);
114 $cdrec .= pack('V', $unc_len);
115 $cdrec .= pack('v', strlen($name) );
116 $cdrec .= pack('v', 0 );
117 $cdrec .= pack('v', 0 );
118 $cdrec .= pack('v', 0 );
119 $cdrec .= pack('v', 0 );
120 $cdrec .= pack('V', 32 );
121
122 $cdrec .= pack('V', $this -> old_offset );
123 $this -> old_offset += strlen($fr);
124
125 $cdrec .= $name;
126
127 $this -> ctrl_dir[] = $cdrec;
128 }
129
130 function file() {
131 $data = implode('', $this -> datasec);
132 $ctrldir = implode('', $this -> ctrl_dir);
133
134 return
135 $data .
136 $ctrldir .
137 $this -> eof_ctrl_dir .
138 pack('v', sizeof($this -> ctrl_dir)) .
139 pack('v', sizeof($this -> ctrl_dir)) .
140 pack('V', strlen($ctrldir)) .
141 pack('V', strlen($data)) .
142 "\x00\x00";
143 }
144}
145
146class php_unzip {
147 var $Comment = '';
148 var $Entries = array();
149 var $Name = '';
150 var $Size = 0;
151 var $Time = 0;
152
153 function Count() {
154 return count($this->Entries);
155 }
156
157 function GetData($in_Index) {
158 return $this->Entries[$in_Index]->Data;
159 }
160
161 function GetEntry($in_Index) {
162 return $this->Entries[$in_Index];
163 }
164
165 function GetError($in_Index) {
166 return $this->Entries[$in_Index]->Error;
167 }
168
169 function GetErrorMsg($in_Index) {
170 return $this->Entries[$in_Index]->ErrorMsg;
171 }
172
173 function GetName($in_Index) {
174 return $this->Entries[$in_Index]->Name;
175 }
176
177 function GetPath($in_Index) {
178 return $this->Entries[$in_Index]->Path;
179 }
180
181 function GetTime($in_Index) {
182 return $this->Entries[$in_Index]->Time;
183 }
184
185 function ReadFile($in_FileName) {
186 $this->Entries = array();
187 $this->Name = $in_FileName;
188 $this->Time = filemtime($in_FileName);
189 $this->Size = filesize($in_FileName);
190
191 $oF = fopen($in_FileName, 'rb');
192 $vZ = fread($oF, $this->Size);
193 fclose($oF);
194
195 $aE = explode("\x50\x4b\x05\x06", $vZ);
196
197 $aP = unpack('x16/v1CL', $aE[1]);
198 $this->Comment = substr($aE[1], 18, $aP['CL']);
199 $this->Comment = strtr($this->Comment, array("\r\n" => "\n",
200 "\r" => "\n"));
201
202 $aE = explode("\x50\x4b\x01\x02", $vZ);
203 $aE = explode("\x50\x4b\x03\x04", $aE[0]);
204 array_shift($aE);
205
206 foreach($aE as $vZ) {
207 $aI = array();
208 $aI['E'] = 0;
209 $aI['EM'] = '';
210 $aP = unpack('v1VN/v1GPF/v1CM/v1FT/v1FD/V1CRC/V1CS/V1UCS/v1FNL', $vZ);
211 $bE = ($aP['GPF'] && 0x0001) ? TRUE : FALSE;
212 $nF = $aP['FNL'];
213
214 if($aP['GPF'] & 0x0008) {
215 $aP1 = unpack('V1CRC/V1CS/V1UCS', substr($vZ, -12));
216
217 $aP['CRC'] = $aP1['CRC'];
218 $aP['CS'] = $aP1['CS'];
219 $aP['UCS'] = $aP1['UCS'];
220
221 $vZ = substr($vZ, 0, -12);
222 }
223
224 $aI['N'] = substr($vZ, 26, $nF);
225
226 if(substr($aI['N'], -1) == '/') {
227 continue;
228 }
229
230 $aI['P'] = dirname($aI['N']);
231 $aI['P'] = $aI['P'] == '.' ? '' : $aI['P'];
232 $aI['N'] = basename($aI['N']);
233
234 $vZ = substr($vZ, 26 + $nF);
235
236 if(strlen($vZ) != $aP['CS']) {
237 $aI['E'] = 1;
238 $aI['EM'] = 'Compressed size is not equal with the value in header information.';
239 } else {
240 if($bE) {
241 $aI['E'] = 5;
242 $aI['EM'] = 'File is encrypted, which is not supported from this class.';
243 } else {
244 switch($aP['CM']) {
245 case 0:
246 break;
247
248 case 8:
249 $vZ = gzinflate($vZ);
250 break;
251
252 case 12:
253 if(! extension_loaded('bz2')) {
254 if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
255 @dl('php_bz2.dll');
256 } else {
257 @dl('bz2.so');
258 }
259 }
260
261 if(extension_loaded('bz2')) {
262 $vZ = bzdecompress($vZ);
263 } else {
264 $aI['E'] = 7;
265 $aI['EM'] = "PHP BZIP2 extension not available.";
266 }
267
268 break;
269
270 default:
271 $aI['E'] = 6;
272 $aI['EM'] = "De-/Compression method {$aP['CM']} is not supported.";
273 }
274
275 if(! $aI['E']) {
276 if($vZ === FALSE) {
277 $aI['E'] = 2;
278 $aI['EM'] = 'Decompression of data failed.';
279 } else {
280 if(strlen($vZ) != $aP['UCS']) {
281 $aI['E'] = 3;
282 $aI['EM'] = 'Uncompressed size is not equal with the value in header information.';
283 } else {
284 if(crc32($vZ) != $aP['CRC']) {
285 $aI['E'] = 4;
286 $aI['EM'] = 'CRC32 checksum is not equal with the value in header information.';
287 }
288 }
289 }
290 }
291 }
292 }
293
294 $aI['D'] = $vZ;
295
296 $aI['T'] = mktime(($aP['FT'] & 0xf800) >> 11,
297 ($aP['FT'] & 0x07e0) >> 5,
298 ($aP['FT'] & 0x001f) << 1,
299 ($aP['FD'] & 0x01e0) >> 5,
300 ($aP['FD'] & 0x001f),
301 (($aP['FD'] & 0xfe00) >> 9) + 1980);
302
303 $this->Entries[] = array(
304 'Data' => $aI['D'],
305 'Error' => $aI['E'],
306 'ErrorMsg' => $aI['EM'],
307 'Name' => $aI['N'],
308 'Path' => $aI['P'],
309 'Time' => $aI['T']
310 );
311 }
312
313 return $this->Entries;
314 }
315}
316