File indexing completed on 2024-12-22 05:36:41
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Filter 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * @see Zend_Filter_Compress_CompressAbstract 0024 */ 0025 // require_once 'Zend/Filter/Compress/CompressAbstract.php'; 0026 0027 /** 0028 * Compression adapter for zip 0029 * 0030 * @category Zend 0031 * @package Zend_Filter 0032 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0033 * @license http://framework.zend.com/license/new-bsd New BSD License 0034 */ 0035 class Zend_Filter_Compress_Zip extends Zend_Filter_Compress_CompressAbstract 0036 { 0037 /** 0038 * Compression Options 0039 * array( 0040 * 'archive' => Archive to use 0041 * 'password' => Password to use 0042 * 'target' => Target to write the files to 0043 * ) 0044 * 0045 * @var array 0046 */ 0047 protected $_options = array( 0048 'archive' => null, 0049 'target' => null, 0050 ); 0051 0052 /** 0053 * Class constructor 0054 * 0055 * @param string|array $options (Optional) Options to set 0056 */ 0057 public function __construct($options = null) 0058 { 0059 if (!extension_loaded('zip')) { 0060 // require_once 'Zend/Filter/Exception.php'; 0061 throw new Zend_Filter_Exception('This filter needs the zip extension'); 0062 } 0063 parent::__construct($options); 0064 } 0065 0066 /** 0067 * Returns the set archive 0068 * 0069 * @return string 0070 */ 0071 public function getArchive() 0072 { 0073 return $this->_options['archive']; 0074 } 0075 0076 /** 0077 * Sets the archive to use for de-/compression 0078 * 0079 * @param string $archive Archive to use 0080 * @return Zend_Filter_Compress_Rar 0081 */ 0082 public function setArchive($archive) 0083 { 0084 $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive); 0085 $this->_options['archive'] = (string) $archive; 0086 0087 return $this; 0088 } 0089 0090 /** 0091 * Returns the set targetpath 0092 * 0093 * @return string 0094 */ 0095 public function getTarget() 0096 { 0097 return $this->_options['target']; 0098 } 0099 0100 /** 0101 * Sets the target to use 0102 * 0103 * @param string $target 0104 * @return Zend_Filter_Compress_Rar 0105 */ 0106 public function setTarget($target) 0107 { 0108 if (!file_exists(dirname($target))) { 0109 // require_once 'Zend/Filter/Exception.php'; 0110 throw new Zend_Filter_Exception("The directory '$target' does not exist"); 0111 } 0112 0113 $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target); 0114 $this->_options['target'] = (string) $target; 0115 return $this; 0116 } 0117 0118 /** 0119 * Compresses the given content 0120 * 0121 * @param string $content 0122 * @return string Compressed archive 0123 */ 0124 public function compress($content) 0125 { 0126 $zip = new ZipArchive(); 0127 $res = $zip->open($this->getArchive(), ZipArchive::CREATE | ZipArchive::OVERWRITE); 0128 0129 if ($res !== true) { 0130 // require_once 'Zend/Filter/Exception.php'; 0131 throw new Zend_Filter_Exception($this->_errorString($res)); 0132 } 0133 0134 if (file_exists($content)) { 0135 $content = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); 0136 $basename = substr($content, strrpos($content, DIRECTORY_SEPARATOR) + 1); 0137 if (is_dir($content)) { 0138 $index = strrpos($content, DIRECTORY_SEPARATOR) + 1; 0139 $content .= DIRECTORY_SEPARATOR; 0140 $stack = array($content); 0141 while (!empty($stack)) { 0142 $current = array_pop($stack); 0143 $files = array(); 0144 0145 $dir = dir($current); 0146 while (false !== ($node = $dir->read())) { 0147 if (($node == '.') || ($node == '..')) { 0148 continue; 0149 } 0150 0151 if (is_dir($current . $node)) { 0152 array_push($stack, $current . $node . DIRECTORY_SEPARATOR); 0153 } 0154 0155 if (is_file($current . $node)) { 0156 $files[] = $node; 0157 } 0158 } 0159 0160 $local = substr($current, $index); 0161 $zip->addEmptyDir(substr($local, 0, -1)); 0162 0163 foreach ($files as $file) { 0164 $zip->addFile($current . $file, $local . $file); 0165 if ($res !== true) { 0166 // require_once 'Zend/Filter/Exception.php'; 0167 throw new Zend_Filter_Exception($this->_errorString($res)); 0168 } 0169 } 0170 } 0171 } else { 0172 $res = $zip->addFile($content, $basename); 0173 if ($res !== true) { 0174 // require_once 'Zend/Filter/Exception.php'; 0175 throw new Zend_Filter_Exception($this->_errorString($res)); 0176 } 0177 } 0178 } else { 0179 $file = $this->getTarget(); 0180 if (!is_dir($file)) { 0181 $file = basename($file); 0182 } else { 0183 $file = "zip.tmp"; 0184 } 0185 0186 $res = $zip->addFromString($file, $content); 0187 if ($res !== true) { 0188 // require_once 'Zend/Filter/Exception.php'; 0189 throw new Zend_Filter_Exception($this->_errorString($res)); 0190 } 0191 } 0192 0193 $zip->close(); 0194 return $this->_options['archive']; 0195 } 0196 0197 /** 0198 * Decompresses the given content 0199 * 0200 * @param string $content 0201 * @return string 0202 */ 0203 public function decompress($content) 0204 { 0205 $archive = $this->getArchive(); 0206 if (file_exists($content)) { 0207 $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content)); 0208 } elseif (empty($archive) || !file_exists($archive)) { 0209 // require_once 'Zend/Filter/Exception.php'; 0210 throw new Zend_Filter_Exception('ZIP Archive not found'); 0211 } 0212 0213 $zip = new ZipArchive(); 0214 $res = $zip->open($archive); 0215 0216 $target = $this->getTarget(); 0217 0218 if (!empty($target) && !is_dir($target)) { 0219 $target = dirname($target); 0220 } 0221 0222 if (!empty($target)) { 0223 $target = rtrim($target, '/\\') . DIRECTORY_SEPARATOR; 0224 } 0225 0226 if (empty($target) || !is_dir($target)) { 0227 // require_once 'Zend/Filter/Exception.php'; 0228 throw new Zend_Filter_Exception('No target for ZIP decompression set'); 0229 } 0230 0231 if ($res !== true) { 0232 // require_once 'Zend/Filter/Exception.php'; 0233 throw new Zend_Filter_Exception($this->_errorString($res)); 0234 } 0235 0236 if (version_compare(PHP_VERSION, '5.2.8', '<')) { 0237 for ($i = 0; $i < $zip->numFiles; $i++) { 0238 $statIndex = $zip->statIndex($i); 0239 $currName = $statIndex['name']; 0240 if (($currName{0} == '/') || 0241 (substr($currName, 0, 2) == '..') || 0242 (substr($currName, 0, 4) == './..') 0243 ) 0244 { 0245 // require_once 'Zend/Filter/Exception.php'; 0246 throw new Zend_Filter_Exception('Upward directory traversal was detected inside ' . $archive 0247 . ' please use PHP 5.2.8 or greater to take advantage of path resolution features of ' 0248 . 'the zip extension in this decompress() method.' 0249 ); 0250 } 0251 } 0252 } 0253 0254 $res = @$zip->extractTo($target); 0255 if ($res !== true) { 0256 // require_once 'Zend/Filter/Exception.php'; 0257 throw new Zend_Filter_Exception($this->_errorString($res)); 0258 } 0259 0260 $zip->close(); 0261 return $target; 0262 } 0263 0264 /** 0265 * Returns the proper string based on the given error constant 0266 * 0267 * @param string $error 0268 */ 0269 protected function _errorString($error) 0270 { 0271 switch($error) { 0272 case ZipArchive::ER_MULTIDISK : 0273 return 'Multidisk ZIP Archives not supported'; 0274 0275 case ZipArchive::ER_RENAME : 0276 return 'Failed to rename the temporary file for ZIP'; 0277 0278 case ZipArchive::ER_CLOSE : 0279 return 'Failed to close the ZIP Archive'; 0280 0281 case ZipArchive::ER_SEEK : 0282 return 'Failure while seeking the ZIP Archive'; 0283 0284 case ZipArchive::ER_READ : 0285 return 'Failure while reading the ZIP Archive'; 0286 0287 case ZipArchive::ER_WRITE : 0288 return 'Failure while writing the ZIP Archive'; 0289 0290 case ZipArchive::ER_CRC : 0291 return 'CRC failure within the ZIP Archive'; 0292 0293 case ZipArchive::ER_ZIPCLOSED : 0294 return 'ZIP Archive already closed'; 0295 0296 case ZipArchive::ER_NOENT : 0297 return 'No such file within the ZIP Archive'; 0298 0299 case ZipArchive::ER_EXISTS : 0300 return 'ZIP Archive already exists'; 0301 0302 case ZipArchive::ER_OPEN : 0303 return 'Can not open ZIP Archive'; 0304 0305 case ZipArchive::ER_TMPOPEN : 0306 return 'Failure creating temporary ZIP Archive'; 0307 0308 case ZipArchive::ER_ZLIB : 0309 return 'ZLib Problem'; 0310 0311 case ZipArchive::ER_MEMORY : 0312 return 'Memory allocation problem while working on a ZIP Archive'; 0313 0314 case ZipArchive::ER_CHANGED : 0315 return 'ZIP Entry has been changed'; 0316 0317 case ZipArchive::ER_COMPNOTSUPP : 0318 return 'Compression method not supported within ZLib'; 0319 0320 case ZipArchive::ER_EOF : 0321 return 'Premature EOF within ZIP Archive'; 0322 0323 case ZipArchive::ER_INVAL : 0324 return 'Invalid argument for ZLIB'; 0325 0326 case ZipArchive::ER_NOZIP : 0327 return 'Given file is no zip archive'; 0328 0329 case ZipArchive::ER_INTERNAL : 0330 return 'Internal error while working on a ZIP Archive'; 0331 0332 case ZipArchive::ER_INCONS : 0333 return 'Inconsistent ZIP archive'; 0334 0335 case ZipArchive::ER_REMOVE : 0336 return 'Can not remove ZIP Archive'; 0337 0338 case ZipArchive::ER_DELETED : 0339 return 'ZIP Entry has been deleted'; 0340 0341 default : 0342 return 'Unknown error within ZIP Archive'; 0343 } 0344 } 0345 0346 /** 0347 * Returns the adapter name 0348 * 0349 * @return string 0350 */ 0351 public function toString() 0352 { 0353 return 'Zip'; 0354 } 0355 }