2
/* $Id: unzip.lib.php 9747 2006-11-19 20:57:24Z nijel $ */
5
* ZIP file unpack classes. Contributed to the phpMyAdmin project.
8
* @package File-Formats-ZIP
10
* @filesource unzip.lib.php
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
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
25
* Unzip class, which retrieves entries from ZIP files.
27
* Supports only the compression modes
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}
40
* @package File-Formats-ZIP
43
* @author Holger Boskugel <vbwebprofi@gmx.de>
44
* @uses SimpleUnzipEntry
45
* @example example.unzip.php Two examples
50
* Array to store file entries
61
* Array to store file entries
68
var $Entries = array();
71
* Name of the ZIP file
81
* Size of the ZIP file
91
* Time of the ZIP file (unix timestamp)
101
* Contructor of the class
103
* @param string File name
104
* @return SimpleUnzip Instanced class
106
* @uses SimpleUnzip::ReadFile() Opens file on new if specified
109
function SimpleUnzip($in_FileName = '')
111
if ($in_FileName !== '') {
112
SimpleUnzip::ReadFile($in_FileName);
114
} // end of the 'SimpleUnzip' constructor
119
* @return integer Count of ZIP entries
126
return count($this->Entries);
127
} // end of the 'Count()' method
130
* Gets data of the specified ZIP entry
132
* @param integer Index of the ZIP entry
133
* @return mixed Data for the ZIP entry
134
* @uses SimpleUnzipEntry::$Data
138
function GetData($in_Index)
140
return $this->Entries[$in_Index]->Data;
141
} // end of the 'GetData()' method
144
* Gets an entry of the ZIP file
146
* @param integer Index of the ZIP entry
147
* @return SimpleUnzipEntry Entry of the ZIP file
152
function GetEntry($in_Index)
154
return $this->Entries[$in_Index];
155
} // end of the 'GetEntry()' method
158
* Gets error code for the specified ZIP entry
160
* @param integer Index of the ZIP entry
161
* @return integer Error code for the ZIP entry
162
* @uses SimpleUnzipEntry::$Error
166
function GetError($in_Index)
168
return $this->Entries[$in_Index]->Error;
169
} // end of the 'GetError()' method
172
* Gets error message for the specified ZIP entry
174
* @param integer Index of the ZIP entry
175
* @return string Error message for the ZIP entry
176
* @uses SimpleUnzipEntry::$ErrorMsg
180
function GetErrorMsg($in_Index)
182
return $this->Entries[$in_Index]->ErrorMsg;
183
} // end of the 'GetErrorMsg()' method
186
* Gets file name for the specified ZIP entry
188
* @param integer Index of the ZIP entry
189
* @return string File name for the ZIP entry
190
* @uses SimpleUnzipEntry::$Name
194
function GetName($in_Index)
196
return $this->Entries[$in_Index]->Name;
197
} // end of the 'GetName()' method
200
* Gets path of the file for the specified ZIP entry
202
* @param integer Index of the ZIP entry
203
* @return string Path of the file for the ZIP entry
204
* @uses SimpleUnzipEntry::$Path
208
function GetPath($in_Index)
210
return $this->Entries[$in_Index]->Path;
211
} // end of the 'GetPath()' method
214
* Gets file time for the specified ZIP entry
216
* @param integer Index of the ZIP entry
217
* @return integer File time for the ZIP entry (unix timestamp)
218
* @uses SimpleUnzipEntry::$Time
222
function GetTime($in_Index)
224
return $this->Entries[$in_Index]->Time;
225
} // end of the 'GetTime()' method
228
* Reads ZIP file and extracts the entries
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
236
function ReadFile($in_FileName)
238
$this->Entries = array();
240
// Get file parameters
241
$this->Name = $in_FileName;
242
$this->Time = filemtime($in_FileName);
243
$this->Size = filesize($in_FileName);
246
$oF = fopen($in_FileName, 'rb');
247
$vZ = fread($oF, $this->Size);
251
// Cut end of central directory
252
$aE = explode("\x50\x4b\x05\x06", $vZ);
254
// Easiest way, but not sure if format changes
255
//$this->Comment = substr($aE[1], 18);
258
$aP = unpack('x16/v1CL', $aE[1]);
259
$this->Comment = substr($aE[1], 18, $aP['CL']);
261
// Translates end of line from other operating systems
262
$this->Comment = strtr($this->Comment, array("\r\n" => "\n",
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
273
// Loop through the entries
274
foreach ($aE as $vZ) {
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;
284
// Special case : value block after the compressed data
285
if ($aP['GPF'] & 0x0008) {
286
$aP1 = unpack('V1CRC/V1CS/V1UCS', substr($vZ, -12));
288
$aP['CRC'] = $aP1['CRC'];
289
$aP['CS'] = $aP1['CS'];
290
$aP['UCS'] = $aP1['UCS'];
292
$vZ = substr($vZ, 0, -12);
295
// Getting stored filename
296
$aI['N'] = substr($vZ, 26, $nF);
298
if (substr($aI['N'], -1) == '/') {
299
// is a directory entry - will be skipped
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']);
308
$vZ = substr($vZ, 26 + $nF);
310
if (strlen($vZ) != $aP['CS']) {
312
$aI['EM'] = 'Compressed size is not equal with the value in header information.';
316
$aI['EM'] = 'File is encrypted, which is not supported from this class.';
320
// Here is nothing to do, the file ist flat.
324
$vZ = gzinflate($vZ);
329
if (! extension_loaded('bz2')) {
330
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
337
if (extension_loaded('bz2')) {
339
$vZ = bzdecompress($vZ);
343
$aI['EM'] = "PHP BZIP2 extension not available.";
351
$aI['EM'] = "De-/Compression method {$aP['CM']} is not supported.";
359
$aI['EM'] = 'Decompression of data failed.';
361
if (strlen($vZ) != $aP['UCS']) {
363
$aI['EM'] = 'Uncompressed size is not equal with the value in header information.';
365
if (crc32($vZ) != $aP['CRC']) {
367
$aI['EM'] = 'CRC32 checksum is not equal with the value in header information.';
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);
387
$this->Entries[] = &new SimpleUnzipEntry($aI);
388
} // end for each entries
390
return $this->Entries;
391
} // end of the 'ReadFile()' method
392
} // end of the 'SimpleUnzip' class
395
* Entry of the ZIP file.
397
* @category phpPublic
398
* @package File-Formats-ZIP
401
* @author Holger Boskugel <vbwebprofi@gmx.de>
402
* @example example.unzip.php Two examples
404
class SimpleUnzipEntry {
406
* Data of the file entry
410
* @see SimpleUnzipEntry()
416
* Error of the file entry
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.
429
* @see SimpleUnzipEntry()
435
* Error message of the file entry
439
* @see SimpleUnzipEntry()
445
* File name of the file entry
449
* @see SimpleUnzipEntry()
455
* File path of the file entry
459
* @see SimpleUnzipEntry()
465
* File time of the file entry (unix timestamp)
469
* @see SimpleUnzipEntry()
475
* Contructor of the class
477
* @param array Entry datas
478
* @return SimpleUnzipEntry Instanced class
482
function SimpleUnzipEntry($in_Entry)
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