root / admin / unzip.lib.php @ 2bbc108b289beecb44d7d1991520c3653799c41a
Historique | Voir | Annoter | Télécharger (15,68 ko)
1 | <?PHP
|
---|---|
2 | /* $Id: unzip.lib.php,v 1.2 2006/01/17 17:02:31 cybot_tm Exp $ */
|
3 | |
4 | /**
|
5 | * ZIP file unpack classes. Contributed to the phpMyAdmin project. |
6 | * |
7 | * @category phpPublic |
8 | * @package File-Formats-ZIP |
9 | * @subpackage Unzip |
10 | * @filesource unzip.lib.php |
11 | * @version 1.0.1 |
12 | * |
13 | * @author Holger Boskugel <vbwebprofi@gmx.de> |
14 | * @copyright Copyright © 2003, Holger Boskugel, Berlin, Germany |
15 | * @license http://opensource.org/licenses/gpl-license.php GNU Public License |
16 | * |
17 | * @history |
18 | * 2003-12-02 - HB : Patched : naming bug : Time/Size of file |
19 | * Added : ZIP file comment |
20 | * Added : Check BZIP2 support of PHP |
21 | * 2003-11-29 - HB * Initial version |
22 | */ |
23 | |
24 | /**
|
25 | * Unzip class, which retrieves entries from ZIP files. |
26 | * |
27 | * Supports only the compression modes |
28 | * - 0 : Stored, |
29 | * - 8 : Deflated and |
30 | * - 12 : BZIP2 |
31 | * |
32 | * Based on :<BR> |
33 | * <BR> |
34 | * {@link http://www.pkware.com/products/enterprise/white_papers/appnote.html |
35 | * * Official ZIP file format}<BR> |
36 | * {@link http://msdn.microsoft.com/library/en-us/w98ddk/hh/w98ddk/storage_5l4m.asp |
37 | * * Microsoft DOS date/time format} |
38 | * |
39 | * @category phpPublic |
40 | * @package File-Formats-ZIP |
41 | * @subpackage Unzip |
42 | * @version 1.0.1 |
43 | * @author Holger Boskugel <vbwebprofi@gmx.de> |
44 | * @uses SimpleUnzipEntry |
45 | * @example example.unzip.php Two examples |
46 | */ |
47 | class SimpleUnzip { |
48 | // 2003-12-02 - HB >
|
49 | /**
|
50 | * Array to store file entries |
51 | * |
52 | * @var string |
53 | * @access public |
54 | * @see ReadFile() |
55 | * @since 1.0.1 |
56 | */ |
57 | var $Comment = ''; |
58 | // 2003-12-02 - HB <
|
59 | |
60 | /**
|
61 | * Array to store file entries |
62 | * |
63 | * @var array |
64 | * @access public |
65 | * @see ReadFile() |
66 | * @since 1.0 |
67 | */ |
68 | var $Entries = array(); |
69 | |
70 | /**
|
71 | * Name of the ZIP file |
72 | * |
73 | * @var string |
74 | * @access public |
75 | * @see ReadFile() |
76 | * @since 1.0 |
77 | */ |
78 | var $Name = ''; |
79 | |
80 | /**
|
81 | * Size of the ZIP file |
82 | * |
83 | * @var integer |
84 | * @access public |
85 | * @see ReadFile() |
86 | * @since 1.0 |
87 | */ |
88 | var $Size = 0; |
89 | |
90 | /**
|
91 | * Time of the ZIP file (unix timestamp) |
92 | * |
93 | * @var integer |
94 | * @access public |
95 | * @see ReadFile() |
96 | * @since 1.0 |
97 | */ |
98 | var $Time = 0; |
99 | |
100 | /**
|
101 | * Contructor of the class |
102 | * |
103 | * @param string File name |
104 | * @return SimpleUnzip Instanced class |
105 | * @access public |
106 | * @uses SimpleUnzip::ReadFile() Opens file on new if specified |
107 | * @since 1.0 |
108 | */ |
109 | function SimpleUnzip($in_FileName = '') |
110 | { |
111 | if ($in_FileName !== '') { |
112 | SimpleUnzip::ReadFile($in_FileName); |
113 | } |
114 | } // end of the 'SimpleUnzip' constructor
|
115 | |
116 | /**
|
117 | * Counts the entries |
118 | * |
119 | * @return integer Count of ZIP entries |
120 | * @access public |
121 | * @uses $Entries |
122 | * @since 1.0 |
123 | */ |
124 | function Count() |
125 | { |
126 | return count($this->Entries); |
127 | } // end of the 'Count()' method
|
128 | |
129 | /**
|
130 | * Gets data of the specified ZIP entry |
131 | * |
132 | * @param integer Index of the ZIP entry |
133 | * @return mixed Data for the ZIP entry |
134 | * @uses SimpleUnzipEntry::$Data |
135 | * @access public |
136 | * @since 1.0 |
137 | */ |
138 | function GetData($in_Index) |
139 | { |
140 | return $this->Entries[$in_Index]->Data; |
141 | } // end of the 'GetData()' method
|
142 | |
143 | /**
|
144 | * Gets an entry of the ZIP file |
145 | * |
146 | * @param integer Index of the ZIP entry |
147 | * @return SimpleUnzipEntry Entry of the ZIP file |
148 | * @uses $Entries |
149 | * @access public |
150 | * @since 1.0 |
151 | */ |
152 | function GetEntry($in_Index) |
153 | { |
154 | return $this->Entries[$in_Index]; |
155 | } // end of the 'GetEntry()' method
|
156 | |
157 | /**
|
158 | * Gets error code for the specified ZIP entry |
159 | * |
160 | * @param integer Index of the ZIP entry |
161 | * @return integer Error code for the ZIP entry |
162 | * @uses SimpleUnzipEntry::$Error |
163 | * @access public |
164 | * @since 1.0 |
165 | */ |
166 | function GetError($in_Index) |
167 | { |
168 | return $this->Entries[$in_Index]->Error; |
169 | } // end of the 'GetError()' method
|
170 | |
171 | /**
|
172 | * Gets error message for the specified ZIP entry |
173 | * |
174 | * @param integer Index of the ZIP entry |
175 | * @return string Error message for the ZIP entry |
176 | * @uses SimpleUnzipEntry::$ErrorMsg |
177 | * @access public |
178 | * @since 1.0 |
179 | */ |
180 | function GetErrorMsg($in_Index) |
181 | { |
182 | return $this->Entries[$in_Index]->ErrorMsg; |
183 | } // end of the 'GetErrorMsg()' method
|
184 | |
185 | /**
|
186 | * Gets file name for the specified ZIP entry |
187 | * |
188 | * @param integer Index of the ZIP entry |
189 | * @return string File name for the ZIP entry |
190 | * @uses SimpleUnzipEntry::$Name |
191 | * @access public |
192 | * @since 1.0 |
193 | */ |
194 | function GetName($in_Index) |
195 | { |
196 | return $this->Entries[$in_Index]->Name; |
197 | } // end of the 'GetName()' method
|
198 | |
199 | /**
|
200 | * Gets path of the file for the specified ZIP entry |
201 | * |
202 | * @param integer Index of the ZIP entry |
203 | * @return string Path of the file for the ZIP entry |
204 | * @uses SimpleUnzipEntry::$Path |
205 | * @access public |
206 | * @since 1.0 |
207 | */ |
208 | function GetPath($in_Index) |
209 | { |
210 | return $this->Entries[$in_Index]->Path; |
211 | } // end of the 'GetPath()' method
|
212 | |
213 | /**
|
214 | * Gets file time for the specified ZIP entry |
215 | * |
216 | * @param integer Index of the ZIP entry |
217 | * @return integer File time for the ZIP entry (unix timestamp) |
218 | * @uses SimpleUnzipEntry::$Time |
219 | * @access public |
220 | * @since 1.0 |
221 | */ |
222 | function GetTime($in_Index) |
223 | { |
224 | return $this->Entries[$in_Index]->Time; |
225 | } // end of the 'GetTime()' method
|
226 | |
227 | /**
|
228 | * Reads ZIP file and extracts the entries |
229 | * |
230 | * @param string File name of the ZIP archive |
231 | * @return array ZIP entry list (see also class variable {@link $Entries $Entries}) |
232 | * @uses SimpleUnzipEntry For the entries |
233 | * @access public |
234 | * @since 1.0 |
235 | */ |
236 | function ReadFile($in_FileName) |
237 | { |
238 | $this->Entries = array(); |
239 | |
240 | // Get file parameters
|
241 | $this->Name = $in_FileName; |
242 | $this->Time = filemtime($in_FileName); |
243 | $this->Size = filesize($in_FileName); |
244 | |
245 | // Read file
|
246 | $oF = fopen($in_FileName, 'rb'); |
247 | $vZ = fread($oF, $this->Size); |
248 | fclose($oF); |
249 | |
250 | // 2003-12-02 - HB >
|
251 | // Cut end of central directory
|
252 | $aE = explode("\x50\x4b\x05\x06", $vZ); |
253 | |
254 | // Easiest way, but not sure if format changes
|
255 | //$this->Comment = substr($aE[1], 18);
|
256 | |
257 | // Normal way
|
258 | $aP = unpack('x16/v1CL', $aE[1]); |
259 | $this->Comment = substr($aE[1], 18, $aP['CL']); |
260 | |
261 | // Translates end of line from other operating systems
|
262 | $this->Comment = strtr($this->Comment, array("\r\n" => "\n", |
263 | "\r" => "\n")); |
264 | // 2003-12-02 - HB <
|
265 | |
266 | // Cut the entries from the central directory
|
267 | $aE = explode("\x50\x4b\x01\x02", $vZ); |
268 | // Explode to each part
|
269 | $aE = explode("\x50\x4b\x03\x04", $aE[0]); |
270 | // Shift out spanning signature or empty entry
|
271 | array_shift($aE); |
272 | |
273 | // Loop through the entries
|
274 | foreach ($aE as $vZ) { |
275 | $aI = array(); |
276 | $aI['E'] = 0; |
277 | $aI['EM'] = ''; |
278 | // Retrieving local file header information
|
279 | $aP = unpack('v1VN/v1GPF/v1CM/v1FT/v1FD/V1CRC/V1CS/V1UCS/v1FNL', $vZ); |
280 | // Check if data is encrypted
|
281 | $bE = ($aP['GPF'] && 0x0001) ? TRUE : FALSE; |
282 | $nF = $aP['FNL']; |
283 | |
284 | // Special case : value block after the compressed data
|
285 | if ($aP['GPF'] & 0x0008) { |
286 | $aP1 = unpack('V1CRC/V1CS/V1UCS', substr($vZ, -12)); |
287 | |
288 | $aP['CRC'] = $aP1['CRC']; |
289 | $aP['CS'] = $aP1['CS']; |
290 | $aP['UCS'] = $aP1['UCS']; |
291 | |
292 | $vZ = substr($vZ, 0, -12); |
293 | } |
294 | |
295 | // Getting stored filename
|
296 | $aI['N'] = substr($vZ, 26, $nF); |
297 | |
298 | if (substr($aI['N'], -1) == '/') { |
299 | // is a directory entry - will be skipped
|
300 | continue;
|
301 | } |
302 | |
303 | // Truncate full filename in path and filename
|
304 | $aI['P'] = dirname($aI['N']); |
305 | $aI['P'] = $aI['P'] == '.' ? '' : $aI['P']; |
306 | $aI['N'] = basename($aI['N']); |
307 | |
308 | $vZ = substr($vZ, 26 + $nF); |
309 | |
310 | if (strlen($vZ) != $aP['CS']) { |
311 | $aI['E'] = 1; |
312 | $aI['EM'] = 'Compressed size is not equal with the value in header information.'; |
313 | } else {
|
314 | if ($bE) { |
315 | $aI['E'] = 5; |
316 | $aI['EM'] = 'File is encrypted, which is not supported from this class.'; |
317 | } else {
|
318 | switch($aP['CM']) { |
319 | case 0: // Stored |
320 | // Here is nothing to do, the file ist flat.
|
321 | break;
|
322 | |
323 | case 8: // Deflated |
324 | $vZ = gzinflate($vZ); |
325 | break;
|
326 | |
327 | case 12: // BZIP2 |
328 | // 2003-12-02 - HB >
|
329 | if (! extension_loaded('bz2')) { |
330 | if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { |
331 | @dl('php_bz2.dll'); |
332 | } else {
|
333 | @dl('bz2.so'); |
334 | } |
335 | } |
336 | |
337 | if (extension_loaded('bz2')) { |
338 | // 2003-12-02 - HB <
|
339 | $vZ = bzdecompress($vZ); |
340 | // 2003-12-02 - HB >
|
341 | } else {
|
342 | $aI['E'] = 7; |
343 | $aI['EM'] = "PHP BZIP2 extension not available."; |
344 | } |
345 | // 2003-12-02 - HB <
|
346 | |
347 | break;
|
348 | |
349 | default:
|
350 | $aI['E'] = 6; |
351 | $aI['EM'] = "De-/Compression method {$aP['CM']} is not supported."; |
352 | } |
353 | |
354 | // 2003-12-02 - HB >
|
355 | if (! $aI['E']) { |
356 | // 2003-12-02 - HB <
|
357 | if ($vZ === FALSE) { |
358 | $aI['E'] = 2; |
359 | $aI['EM'] = 'Decompression of data failed.'; |
360 | } else {
|
361 | if (strlen($vZ) != $aP['UCS']) { |
362 | $aI['E'] = 3; |
363 | $aI['EM'] = 'Uncompressed size is not equal with the value in header information.'; |
364 | } else {
|
365 | if (crc32($vZ) != $aP['CRC']) { |
366 | $aI['E'] = 4; |
367 | $aI['EM'] = 'CRC32 checksum is not equal with the value in header information.'; |
368 | } |
369 | } |
370 | } |
371 | // 2003-12-02 - HB >
|
372 | } |
373 | // 2003-12-02 - HB <
|
374 | } |
375 | } |
376 | |
377 | $aI['D'] = $vZ; |
378 | |
379 | // DOS to UNIX timestamp
|
380 | $aI['T'] = mktime(($aP['FT'] & 0xf800) >> 11, |
381 | ($aP['FT'] & 0x07e0) >> 5, |
382 | ($aP['FT'] & 0x001f) << 1, |
383 | ($aP['FD'] & 0x01e0) >> 5, |
384 | ($aP['FD'] & 0x001f), |
385 | (($aP['FD'] & 0xfe00) >> 9) + 1980); |
386 | |
387 | $this->Entries[] = &new SimpleUnzipEntry($aI); |
388 | } // end for each entries
|
389 | |
390 | return $this->Entries; |
391 | } // end of the 'ReadFile()' method
|
392 | } // end of the 'SimpleUnzip' class
|
393 | |
394 | /**
|
395 | * Entry of the ZIP file. |
396 | * |
397 | * @category phpPublic |
398 | * @package File-Formats-ZIP |
399 | * @subpackage Unzip |
400 | * @version 1.0 |
401 | * @author Holger Boskugel <vbwebprofi@gmx.de> |
402 | * @example example.unzip.php Two examples |
403 | */ |
404 | class SimpleUnzipEntry { |
405 | /**
|
406 | * Data of the file entry |
407 | * |
408 | * @var mixed |
409 | * @access public |
410 | * @see SimpleUnzipEntry() |
411 | * @since 1.0 |
412 | */ |
413 | var $Data = ''; |
414 | |
415 | /**
|
416 | * Error of the file entry |
417 | * |
418 | * - 0 : No error raised.<BR> |
419 | * - 1 : Compressed size is not equal with the value in header information.<BR> |
420 | * - 2 : Decompression of data failed.<BR> |
421 | * - 3 : Uncompressed size is not equal with the value in header information.<BR> |
422 | * - 4 : CRC32 checksum is not equal with the value in header information.<BR> |
423 | * - 5 : File is encrypted, which is not supported from this class.<BR> |
424 | * - 6 : De-/Compression method ... is not supported.<BR> |
425 | * - 7 : PHP BZIP2 extension not available. |
426 | * |
427 | * @var integer |
428 | * @access public |
429 | * @see SimpleUnzipEntry() |
430 | * @since 1.0 |
431 | */ |
432 | var $Error = 0; |
433 | |
434 | /**
|
435 | * Error message of the file entry |
436 | * |
437 | * @var string |
438 | * @access public |
439 | * @see SimpleUnzipEntry() |
440 | * @since 1.0 |
441 | */ |
442 | var $ErrorMsg = ''; |
443 | |
444 | /**
|
445 | * File name of the file entry |
446 | * |
447 | * @var string |
448 | * @access public |
449 | * @see SimpleUnzipEntry() |
450 | * @since 1.0 |
451 | */ |
452 | var $Name = ''; |
453 | |
454 | /**
|
455 | * File path of the file entry |
456 | * |
457 | * @var string |
458 | * @access public |
459 | * @see SimpleUnzipEntry() |
460 | * @since 1.0 |
461 | */ |
462 | var $Path = ''; |
463 | |
464 | /**
|
465 | * File time of the file entry (unix timestamp) |
466 | * |
467 | * @var integer |
468 | * @access public |
469 | * @see SimpleUnzipEntry() |
470 | * @since 1.0 |
471 | */ |
472 | var $Time = 0; |
473 | |
474 | /**
|
475 | * Contructor of the class |
476 | * |
477 | * @param array Entry datas |
478 | * @return SimpleUnzipEntry Instanced class |
479 | * @access public |
480 | * @since 1.0 |
481 | */ |
482 | function SimpleUnzipEntry($in_Entry) |
483 | { |
484 | $this->Data = $in_Entry['D']; |
485 | $this->Error = $in_Entry['E']; |
486 | $this->ErrorMsg = $in_Entry['EM']; |
487 | $this->Name = $in_Entry['N']; |
488 | $this->Path = $in_Entry['P']; |
489 | $this->Time = $in_Entry['T']; |
490 | } // end of the 'SimpleUnzipEntry' constructor
|
491 | } // end of the 'SimpleUnzipEntry' class
|
492 | ?>
|