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