<?php if (function_exists('zip_open') && function_exists('zip_read') && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { class N2ZipReader { public static function read($path) { $zip = zip_open($path); if (!is_resource($zip)) { return array(); } $data = array(); while ($entry = zip_read($zip)) { zip_entry_open($zip, $entry, "r"); self::recursiveRead($data, explode('/', zip_entry_name($entry)), zip_entry_read($entry, zip_entry_filesize($entry))); zip_entry_close($entry); } zip_close($zip); return $data; } private static function recursiveRead(&$data, $parts, $content) { if (count($parts) == 1) { $data[$parts[0]] = $content; } else { if (!isset($data[$parts[0]])) { $data[$parts[0]] = array(); } self::recursiveRead($data[array_shift($parts)], $parts, $content); } } } } else { class N2ZipReader { private $fileHandle, $file; public function __construct($file) { $this->file = $file; } public static function read($path) { $zip = new N2ZipReader($path); return $zip->extract(); } function extract() { $extractedData = array(); if ( ! is_readable(dirname($this->file))) { N2Message::error(sprintf(n2_('%s is not readable'), dirname($this->file) ) ); return false; } if (!$this->file || !is_file($this->file)) return false; $filesize = sprintf('%u', filesize($this->file)); $this->fileHandle = fopen($this->file, 'rb'); $fileData = fread($this->fileHandle, $filesize); $EofCentralDirData = $this->_findEOFCentralDirectoryRecord($filesize); if (!is_array($EofCentralDirData)) return false; $centralDirectoryHeaderOffset = $EofCentralDirData['centraldiroffset']; for ($i = 0; $i < $EofCentralDirData['totalentries']; $i++) { rewind($this->fileHandle); fseek($this->fileHandle, $centralDirectoryHeaderOffset); $centralDirectoryData = $this->_readCentralDirectoryData(); $centralDirectoryHeaderOffset += 46 + $centralDirectoryData['filenamelength'] + $centralDirectoryData['extrafieldlength'] + $centralDirectoryData['commentlength']; if (!is_array($centralDirectoryData) || substr($centralDirectoryData['filename'], -1) == '/') continue; $data = $this->_readLocalFileHeaderAndData($centralDirectoryData); if (!$data) continue; $dir = dirname($centralDirectoryData['filename']); $fileName = basename($centralDirectoryData['filename']); if ($dir != '.' && $dir != '') { if (!isset($extractedData[$dir])) { $extractedData[$dir] = array(); } $extractedData[$dir][$fileName] = $data; } else { $extractedData[$fileName] = $data; } } fclose($this->fileHandle); return $extractedData; } function _findEOFCentralDirectoryRecord($filesize) { fseek($this->fileHandle, $filesize - 22); $EofCentralDirSignature = unpack('Vsignature', fread($this->fileHandle, 4)); if ($EofCentralDirSignature['signature'] != 0x06054b50) { $maxLength = 65535 + 22; $maxLength > $filesize && $maxLength = $filesize; fseek($this->fileHandle, $filesize - $maxLength); $searchPos = ftell($this->fileHandle); while ($searchPos < $filesize) { fseek($this->fileHandle, $searchPos); $sigData = unpack('Vsignature', fread($this->fileHandle, 4)); if ($sigData['signature'] == 0x06054b50) { break; } $searchPos++; } } $EofCentralDirData = unpack('vdisknum/vdiskstart/vcentraldirnum/vtotalentries/Vcentraldirsize/Vcentraldiroffset/vcommentlength', fread($this->fileHandle, 18)); return $EofCentralDirData; } function _readCentralDirectoryData() { $centralDirectorySignature = unpack('Vsignature', fread($this->fileHandle, 4)); if ($centralDirectorySignature['signature'] != 0x02014b50) return false; $centralDirectoryData = fread($this->fileHandle, 42); $centralDirectoryData = unpack('vmadeversion/vextractversion/vflag/vcompressmethod/vmodtime/vmoddate/Vcrc/Vcompressedsize/Vuncompressedsize/vfilenamelength/vextrafieldlength/vcommentlength/vdiskstart/vinternal/Vexternal/Vlocalheaderoffset', $centralDirectoryData); $centralDirectoryData['filenamelength'] && $centralDirectoryData['filename'] = fread($this->fileHandle, $centralDirectoryData['filenamelength']); return $centralDirectoryData; } function _readLocalFileHeaderAndData($centralDirectoryData) { fseek($this->fileHandle, $centralDirectoryData['localheaderoffset']); $localFileHeaderSignature = unpack('Vsignature', fread($this->fileHandle, 4)); if ($localFileHeaderSignature['signature'] != 0x04034b50) return false; $localFileHeaderData = fread($this->fileHandle, 26); $localFileHeaderData = unpack('vextractversion/vflag/vcompressmethod/vmodtime/vmoddate/Vcrc/Vcompressedsize/Vuncompressedsize/vfilenamelength/vextrafieldlength', $localFileHeaderData); $localFileHeaderData['filenamelength'] && $localFileHeaderData['filename'] = fread($this->fileHandle, $localFileHeaderData['filenamelength']); if (!$this->_checkLocalFileHeaderAndCentralDir($localFileHeaderData, $centralDirectoryData)) return false; if ($localFileHeaderData['flag'] & 1) return false; $compressedData = fread($this->fileHandle, $localFileHeaderData['compressedsize']); $data = $this->_unCompressData($compressedData, $localFileHeaderData['compressmethod']); if (crc32($data) != $localFileHeaderData['crc'] || strlen($data) != $localFileHeaderData['uncompressedsize']) return false; return $data; } function _unCompressData($data, $compressMethod) { if (!$compressMethod) return $data; switch ($compressMethod) { case 8 : $data = gzinflate($data); break; default : return false; break; } return $data; } function _checkLocalFileHeaderAndCentralDir($localFileHeaderData, $centralDirectoryData) { return true; } } }