mirror of
https://github.com/Ne-Lexa/php-zip.git
synced 2025-08-15 11:44:56 +02:00
Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9934a860c1 | ||
|
c9f597308e | ||
|
837454ba7e | ||
|
680a9d92c1 | ||
|
04a92e7904 | ||
|
e4e3a7504e | ||
|
d8bb1be43b | ||
|
c163f0583e | ||
|
116a617744 | ||
|
e207086a75 | ||
|
9bb20cc15e | ||
|
7e84f97473 | ||
|
a13f4cc32f | ||
|
c863c18869 | ||
|
ad3bac6f96 | ||
|
d2e94ac9cd | ||
|
3f0c6a7bd8 | ||
|
062762ed09 | ||
|
e1866215a6 | ||
|
f9e6a73587 | ||
|
59773d62a8 | ||
|
9417d7dc95 | ||
|
45905eacf0 | ||
|
aa8846b944 | ||
|
6058c289a4 | ||
|
251ce11bdc | ||
|
f969e59319 | ||
|
6808e4ffdc | ||
|
91f08b9f55 | ||
|
8de3a70571 | ||
|
bdd5423f67 | ||
|
d0cf7f7d1d | ||
|
9f0d151f5e | ||
|
e58cf0f337 | ||
|
171d4a8e4c | ||
|
aa09b24d02 | ||
|
c34f90ac18 | ||
|
fb1a9ced88 | ||
|
a1da1f0069 | ||
|
f29fed2753 | ||
|
03998d79a9 |
23
.github/ISSUE_TEMPLATE/1_Bug_report.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/1_Bug_report.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: 🔴 Bug Report
|
||||
about: Report errors and problems
|
||||
|
||||
---
|
||||
|
||||
| Q | A
|
||||
| -----------------------------| ---
|
||||
| Library version(s) affected: | x.y.z
|
||||
| PHP version(s): | x.y.z
|
||||
| OS (with bit depth): | <!-- ex. Ubuntu 18.04 64-bit -->
|
||||
|
||||
**Description**
|
||||
<!-- A clear and concise description of the problem. -->
|
||||
|
||||
**How to reproduce**
|
||||
<!-- Code to reproduce the problem. -->
|
||||
|
||||
**Possible Solution**
|
||||
<!--- Optional: only if you have suggestions on a fix/reason for the bug -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Optional: any other context about the problem: error messages, stack trace, zip files, etc. -->
|
12
.github/ISSUE_TEMPLATE/2_Feature_request.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/2_Feature_request.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
about: Ideas for new features and improvements
|
||||
|
||||
---
|
||||
|
||||
**Description**
|
||||
<!-- A clear and concise description of the new feature. -->
|
||||
|
||||
**Example**
|
||||
<!-- A simple example of the new feature in action (include PHP code)
|
||||
If the new feature changes an existing feature, include a simple before/after comparison. -->
|
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
| Q | A
|
||||
| ------------- | ---
|
||||
| Bug fix? | yes/no
|
||||
| New feature? | yes/no <!-- don't forget to update CHANGELOG.md file -->
|
||||
|
||||
<!--
|
||||
Write a short README entry for your feature/bugfix here (replace this comment block.)
|
||||
|
||||
Do NOT send pull request to `master` branch.
|
||||
Please send to `develop` branch instead.
|
||||
Any PR to `master` branch will NOT be merged.
|
||||
-->
|
@@ -4,6 +4,7 @@ php:
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- nightly
|
||||
|
||||
# cache vendor dirs
|
||||
|
38
README.RU.md
38
README.RU.md
@@ -78,21 +78,29 @@
|
||||
```php
|
||||
// создание нового архива
|
||||
$zipFile = new \PhpZip\ZipFile();
|
||||
$zipFile
|
||||
->addFromString("zip/entry/filename", "Is file content") // добавить запись из строки
|
||||
->addFile("/path/to/file", "data/tofile") // добавить запись из файла
|
||||
->addDir(__DIR__, "to/path/") // добавить файлы из директории
|
||||
->saveAsFile($outputFilename) // сохранить архив в файл
|
||||
->close(); // закрыть архив
|
||||
|
||||
// открытие архива, извлечение файлов, удаление файлов, добавление файлов, установка пароля и вывод архива в браузер.
|
||||
$zipFile
|
||||
->openFile($outputFilename) // открыть архив из файла
|
||||
->extractTo($outputDirExtract) // извлечь файлы в заданную директорию
|
||||
->deleteFromRegex('~^\.~') // удалить все скрытые (Unix) файлы
|
||||
->addFromString('dir/file.txt', 'Test file') // добавить новую запись из строки
|
||||
->setPassword('password') // установить пароль на все записи
|
||||
->outputAsAttachment('library.jar'); // вывести в браузер без сохранения в файл
|
||||
try{
|
||||
$zipFile
|
||||
->addFromString("zip/entry/filename", "Is file content") // добавить запись из строки
|
||||
->addFile("/path/to/file", "data/tofile") // добавить запись из файла
|
||||
->addDir(__DIR__, "to/path/") // добавить файлы из директории
|
||||
->saveAsFile($outputFilename) // сохранить архив в файл
|
||||
->close(); // закрыть архив
|
||||
|
||||
// открытие архива, извлечение файлов, удаление файлов, добавление файлов, установка пароля и вывод архива в браузер.
|
||||
$zipFile
|
||||
->openFile($outputFilename) // открыть архив из файла
|
||||
->extractTo($outputDirExtract) // извлечь файлы в заданную директорию
|
||||
->deleteFromRegex('~^\.~') // удалить все скрытые (Unix) файлы
|
||||
->addFromString('dir/file.txt', 'Test file') // добавить новую запись из строки
|
||||
->setPassword('password') // установить пароль на все записи
|
||||
->outputAsAttachment('library.jar'); // вывести в браузер без сохранения в файл
|
||||
}
|
||||
catch(\PhpZip\Exception\ZipException $e){
|
||||
// обработка исключения
|
||||
}
|
||||
finally{
|
||||
$zipFile->close();
|
||||
}
|
||||
```
|
||||
Другие примеры можно посмотреть в папке `tests/`.
|
||||
|
||||
|
38
README.md
38
README.md
@@ -78,21 +78,29 @@ Latest stable version: [;
|
||||
$zipFile
|
||||
->addFromString("zip/entry/filename", "Is file content") // add an entry from the string
|
||||
->addFile("/path/to/file", "data/tofile") // add an entry from the file
|
||||
->addDir(__DIR__, "to/path/") // add files from the directory
|
||||
->saveAsFile($outputFilename) // save the archive to a file
|
||||
->close(); // close archive
|
||||
|
||||
// open archive, extract, add files, set password and output to browser.
|
||||
$zipFile
|
||||
->openFile($outputFilename) // open archive from file
|
||||
->extractTo($outputDirExtract) // extract files to the specified directory
|
||||
->deleteFromRegex('~^\.~') // delete all hidden (Unix) files
|
||||
->addFromString('dir/file.txt', 'Test file') // add a new entry from the string
|
||||
->setPassword('password') // set password for all entries
|
||||
->outputAsAttachment('library.jar'); // output to the browser without saving to a file
|
||||
try{
|
||||
$zipFile
|
||||
->addFromString("zip/entry/filename", "Is file content") // add an entry from the string
|
||||
->addFile("/path/to/file", "data/tofile") // add an entry from the file
|
||||
->addDir(__DIR__, "to/path/") // add files from the directory
|
||||
->saveAsFile($outputFilename) // save the archive to a file
|
||||
->close(); // close archive
|
||||
|
||||
// open archive, extract, add files, set password and output to browser.
|
||||
$zipFile
|
||||
->openFile($outputFilename) // open archive from file
|
||||
->extractTo($outputDirExtract) // extract files to the specified directory
|
||||
->deleteFromRegex('~^\.~') // delete all hidden (Unix) files
|
||||
->addFromString('dir/file.txt', 'Test file') // add a new entry from the string
|
||||
->setPassword('password') // set password for all entries
|
||||
->outputAsAttachment('library.jar'); // output to the browser without saving to a file
|
||||
}
|
||||
catch(\PhpZip\Exception\ZipException $e){
|
||||
// handle exception
|
||||
}
|
||||
finally{
|
||||
$zipFile->close();
|
||||
}
|
||||
```
|
||||
Other examples can be found in the `tests/` folder
|
||||
|
||||
|
@@ -1,45 +1,49 @@
|
||||
{
|
||||
"name": "nelexa/zip",
|
||||
"description": "PhpZip is a php-library for extended work with ZIP-archives. Open, create, update, delete, extract and get info tool. Supports appending to existing ZIP files, WinZip AES encryption, Traditional PKWARE Encryption, ZipAlign tool, BZIP2 compression, external file attributes and ZIP64 extensions. Alternative ZipArchive. It does not require php-zip extension.",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"zip",
|
||||
"unzip",
|
||||
"archive",
|
||||
"extract",
|
||||
"winzip",
|
||||
"zipalign",
|
||||
"ziparchive"
|
||||
],
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.8"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ne-Lexa",
|
||||
"email": "alexey@nelexa.ru",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": "^5.5 || ^7.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpZip\\": "src/PhpZip"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"PhpZip\\": "tests/PhpZip"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"ext-openssl": "Needed to support encrypt zip entries or use ext-mcrypt",
|
||||
"ext-mcrypt": "Needed to support encrypt zip entries or use ext-openssl",
|
||||
"ext-bz2": "Needed to support BZIP2 compression"
|
||||
}
|
||||
"name": "nelexa/zip",
|
||||
"type": "library",
|
||||
"description": "PhpZip is a php-library for extended work with ZIP-archives. Open, create, update, delete, extract and get info tool. Supports appending to existing ZIP files, WinZip AES encryption, Traditional PKWARE Encryption, ZipAlign tool, BZIP2 compression, external file attributes and ZIP64 extensions. Alternative ZipArchive. It does not require php-zip extension.",
|
||||
"keywords": [
|
||||
"zip",
|
||||
"unzip",
|
||||
"archive",
|
||||
"extract",
|
||||
"winzip",
|
||||
"zipalign",
|
||||
"ziparchive"
|
||||
],
|
||||
"homepage": "https://github.com/Ne-Lexa/php-zip",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ne-Lexa",
|
||||
"email": "alexey@nelexa.ru",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": "^5.5 || ^7.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8|~5.7",
|
||||
"zendframework/zend-diactoros": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpZip\\": "src/PhpZip"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"PhpZip\\": "tests/PhpZip"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"ext-openssl": "Needed to support encrypt zip entries or use ext-mcrypt",
|
||||
"ext-mcrypt": "Needed to support encrypt zip entries or use ext-openssl",
|
||||
"ext-bz2": "Needed to support BZIP2 compression",
|
||||
"ext-fileinfo": "Needed to get mime-type file"
|
||||
},
|
||||
"minimum-stability": "stable"
|
||||
}
|
||||
|
@@ -148,7 +148,10 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
|
||||
$checkByte = ($this->entry->getCrc() >> 24) & 0xff;
|
||||
}
|
||||
if ($byte !== $checkByte) {
|
||||
throw new ZipAuthenticationException("Bad password for entry " . $this->entry->getName());
|
||||
throw new ZipAuthenticationException(sprintf(
|
||||
'Invalid password for zip entry "%s"',
|
||||
$this->entry->getName()
|
||||
));
|
||||
}
|
||||
|
||||
$outputContent = "";
|
||||
@@ -176,6 +179,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
|
||||
*
|
||||
* @param string $data
|
||||
* @return string
|
||||
* @throws ZipCryptoException
|
||||
*/
|
||||
public function encrypt($data)
|
||||
{
|
||||
@@ -202,7 +206,7 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
|
||||
*/
|
||||
private function encryptData($content)
|
||||
{
|
||||
if (null === $content) {
|
||||
if ($content === null) {
|
||||
throw new ZipCryptoException('content is null');
|
||||
}
|
||||
$buff = '';
|
||||
|
@@ -5,6 +5,7 @@ namespace PhpZip\Crypto;
|
||||
use PhpZip\Exception\RuntimeException;
|
||||
use PhpZip\Exception\ZipAuthenticationException;
|
||||
use PhpZip\Exception\ZipCryptoException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\Util\CryptoUtil;
|
||||
@@ -49,6 +50,7 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
* @return string
|
||||
* @throws ZipAuthenticationException
|
||||
* @throws ZipCryptoException
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
public function decrypt($content)
|
||||
{
|
||||
@@ -129,26 +131,26 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
" (authenticated WinZip AES entry content has been tampered with)");
|
||||
}
|
||||
|
||||
return self::aesCtrSegmentIntegerCounter(false, $content, $key, $iv);
|
||||
return self::aesCtrSegmentIntegerCounter($content, $key, $iv, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decryption or encryption AES-CTR with Segment Integer Count (SIC).
|
||||
*
|
||||
* @param bool $encrypted If true encryption else decryption
|
||||
* @param string $str Data
|
||||
* @param string $key Key
|
||||
* @param string $iv IV
|
||||
* @param bool $encrypted If true encryption else decryption
|
||||
* @return string
|
||||
*/
|
||||
private static function aesCtrSegmentIntegerCounter($encrypted = true, $str, $key, $iv)
|
||||
private static function aesCtrSegmentIntegerCounter($str, $key, $iv, $encrypted = true)
|
||||
{
|
||||
$numOfBlocks = ceil(strlen($str) / 16);
|
||||
$ctrStr = '';
|
||||
for ($i = 0; $i < $numOfBlocks; ++$i) {
|
||||
for ($j = 0; $j < 16; ++$j) {
|
||||
$n = ord($iv[$j]);
|
||||
if (0x100 === ++$n) {
|
||||
if (++$n === 0x100) {
|
||||
// overflow, set this one to 0, increment next
|
||||
$iv[$j] = chr(0);
|
||||
} else {
|
||||
@@ -172,14 +174,16 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
* @param string $key Aes key
|
||||
* @param string $iv Aes IV
|
||||
* @return string Encrypted data
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private static function encryptCtr($data, $key, $iv)
|
||||
{
|
||||
if (extension_loaded("openssl")) {
|
||||
$numBits = strlen($key) * 8;
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return openssl_encrypt($data, 'AES-' . $numBits . '-CTR', $key, OPENSSL_RAW_DATA, $iv);
|
||||
} elseif (extension_loaded("mcrypt")) {
|
||||
/** @noinspection PhpDeprecationInspection */
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, "ctr", $iv);
|
||||
} else {
|
||||
throw new RuntimeException('Extension openssl or mcrypt not loaded');
|
||||
@@ -193,14 +197,16 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
* @param string $key Aes key
|
||||
* @param string $iv Aes IV
|
||||
* @return string Raw data
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private static function decryptCtr($data, $key, $iv)
|
||||
{
|
||||
if (extension_loaded("openssl")) {
|
||||
$numBits = strlen($key) * 8;
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return openssl_decrypt($data, 'AES-' . $numBits . '-CTR', $key, OPENSSL_RAW_DATA, $iv);
|
||||
} elseif (extension_loaded("mcrypt")) {
|
||||
/** @noinspection PhpDeprecationInspection */
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, "ctr", $iv);
|
||||
} else {
|
||||
throw new RuntimeException('Extension openssl or mcrypt not loaded');
|
||||
@@ -212,12 +218,15 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
*
|
||||
* @param string $content
|
||||
* @return string
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
public function encrypt($content)
|
||||
{
|
||||
// Init key strength.
|
||||
$password = $this->entry->getPassword();
|
||||
assert($password !== null);
|
||||
if ($password === null) {
|
||||
throw new ZipException('No password was set for the entry "'.$this->entry->getName().'"');
|
||||
}
|
||||
|
||||
// WinZip 99-character limit
|
||||
// @see https://sourceforge.net/p/p7zip/discussion/383044/thread/c859a2f0/
|
||||
@@ -226,8 +235,6 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
$keyStrengthBits = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($this->entry->getEncryptionMethod());
|
||||
$keyStrengthBytes = $keyStrengthBits / 8;
|
||||
|
||||
assert(self::AES_BLOCK_SIZE_BITS <= $keyStrengthBits);
|
||||
|
||||
$salt = CryptoUtil::randomBytes($keyStrengthBytes / 2);
|
||||
|
||||
$keyParam = hash_pbkdf2("sha1", $password, $salt, self::ITERATION_COUNT, (2 * $keyStrengthBits + self::PWD_VERIFIER_BITS) / 8, true);
|
||||
@@ -239,7 +246,7 @@ class WinZipAesEngine implements ZipEncryptionEngine
|
||||
|
||||
$key = substr($keyParam, 0, $keyStrengthBytes);
|
||||
|
||||
$content = self::aesCtrSegmentIntegerCounter(true, $content, $key, $iv);
|
||||
$content = self::aesCtrSegmentIntegerCounter($content, $key, $iv, true);
|
||||
|
||||
$mac = hash_hmac('sha1', $content, $sha1HMacParam, true);
|
||||
|
||||
|
@@ -37,8 +37,14 @@ class Crc32Exception extends ZipException
|
||||
*/
|
||||
public function __construct($name, $expected, $actual)
|
||||
{
|
||||
parent::__construct($name . " (expected CRC32 value 0x" .
|
||||
dechex($expected) . ", but is actually 0x" . dechex($actual) . ")");
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
"%s (expected CRC32 value 0x%x, but is actually 0x%x)",
|
||||
$name,
|
||||
$expected,
|
||||
$actual
|
||||
)
|
||||
);
|
||||
assert($expected != $actual);
|
||||
$this->expectedCrc = $expected;
|
||||
$this->actualCrc = $actual;
|
||||
|
@@ -4,10 +4,11 @@ namespace PhpZip\Exception;
|
||||
|
||||
/**
|
||||
* Runtime exception.
|
||||
* Exception thrown if an error which can only be found on runtime occurs.
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
class RuntimeException extends ZipException
|
||||
class RuntimeException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
|
38
src/PhpZip/Exception/ZipEntryNotFoundException.php
Normal file
38
src/PhpZip/Exception/ZipEntryNotFoundException.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Exception;
|
||||
|
||||
/**
|
||||
* Thrown if entry not found.
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
class ZipEntryNotFoundException extends ZipException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $entryName;
|
||||
|
||||
/**
|
||||
* ZipEntryNotFoundException constructor.
|
||||
* @param string $entryName
|
||||
*/
|
||||
public function __construct($entryName)
|
||||
{
|
||||
parent::__construct(sprintf(
|
||||
"Zip Entry \"%s\" was not found in the archive.",
|
||||
$entryName
|
||||
));
|
||||
$this->entryName = $entryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEntryName()
|
||||
{
|
||||
return $this->entryName;
|
||||
}
|
||||
}
|
@@ -7,8 +7,8 @@ namespace PhpZip\Exception;
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
* @see \Exception
|
||||
* @deprecated Rename class exception, using ZipEntryNotFoundException
|
||||
*/
|
||||
class ZipNotFoundEntry extends ZipException
|
||||
class ZipNotFoundEntry extends ZipEntryNotFoundException
|
||||
{
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@ namespace PhpZip\Exception;
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
* @see \Exception
|
||||
* @deprecated Rename exception class, using ZipUnsupportMethodException
|
||||
*/
|
||||
class ZipUnsupportMethod extends ZipException
|
||||
class ZipUnsupportMethod extends ZipUnsupportMethodException
|
||||
{
|
||||
}
|
||||
|
7
src/PhpZip/Exception/ZipUnsupportMethodException.php
Normal file
7
src/PhpZip/Exception/ZipUnsupportMethodException.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Exception;
|
||||
|
||||
class ZipUnsupportMethodException extends RuntimeException
|
||||
{
|
||||
}
|
@@ -129,6 +129,7 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
|
||||
* </p>
|
||||
* @return mixed Can return all value types.
|
||||
* @since 5.0.0
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
@@ -145,13 +146,15 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
|
||||
* The value to set.
|
||||
* </p>
|
||||
* @return void
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($value instanceof ExtraField) {
|
||||
assert($offset == $value::getHeaderId());
|
||||
if ($offset !== $value::getHeaderId()) {
|
||||
throw new InvalidArgumentException("Value header id !== array access key");
|
||||
}
|
||||
$this->add($value);
|
||||
} else {
|
||||
throw new InvalidArgumentException('value is not instanceof ' . ExtraField::class);
|
||||
@@ -166,6 +169,7 @@ class ExtraFieldsCollection implements \Countable, \ArrayAccess, \Iterator
|
||||
* </p>
|
||||
* @return void
|
||||
* @since 5.0.0
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
|
@@ -38,7 +38,7 @@ class ExtraFieldsFactory
|
||||
public static function createExtraFieldCollections($extra, ZipEntry $entry = null)
|
||||
{
|
||||
$extraFieldsCollection = new ExtraFieldsCollection();
|
||||
if (null !== $extra) {
|
||||
if ($extra !== null) {
|
||||
$extraLength = strlen($extra);
|
||||
if ($extraLength > 0xffff) {
|
||||
throw new ZipException("Extra Fields too large: " . $extraLength);
|
||||
@@ -63,6 +63,11 @@ class ExtraFieldsFactory
|
||||
return $extraFieldsCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExtraFieldsCollection $extraFieldsCollection
|
||||
* @return string
|
||||
* @throws ZipException
|
||||
*/
|
||||
public static function createSerializedData(ExtraFieldsCollection $extraFieldsCollection)
|
||||
{
|
||||
$extraData = '';
|
||||
@@ -102,7 +107,7 @@ class ExtraFieldsFactory
|
||||
if (isset(self::getRegistry()[$headerId])) {
|
||||
$extraClassName = self::getRegistry()[$headerId];
|
||||
$extraField = new $extraClassName;
|
||||
if ($extraField::getHeaderId() !== $headerId) {
|
||||
if ($headerId !== $extraField::getHeaderId()) {
|
||||
throw new ZipException('Runtime error support headerId ' . $headerId);
|
||||
}
|
||||
} else {
|
||||
@@ -118,7 +123,7 @@ class ExtraFieldsFactory
|
||||
*/
|
||||
protected static function getRegistry()
|
||||
{
|
||||
if (null === self::$registry) {
|
||||
if (self::$registry === null) {
|
||||
self::$registry[WinZipAesEntryExtraField::getHeaderId()] = WinZipAesEntryExtraField::class;
|
||||
self::$registry[NtfsExtraField::getHeaderId()] = NtfsExtraField::class;
|
||||
self::$registry[Zip64ExtraField::getHeaderId()] = Zip64ExtraField::class;
|
||||
|
@@ -61,7 +61,6 @@ class ApkAlignmentExtraField implements ExtraField
|
||||
/**
|
||||
* Initializes this Extra Field by deserializing a Data Block.
|
||||
* @param string $data
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function deserialize($data)
|
||||
{
|
||||
|
@@ -44,7 +44,7 @@ class JarMarkerExtraField implements ExtraField
|
||||
*/
|
||||
public function deserialize($data)
|
||||
{
|
||||
if (0 !== strlen($data)) {
|
||||
if (strlen($data) !== 0) {
|
||||
throw new ZipException("JarMarker doesn't expect any data");
|
||||
}
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ class NtfsExtraField implements ExtraField
|
||||
public function deserialize($data)
|
||||
{
|
||||
$unpack = unpack('vtag/vsizeAttr', substr($data, 0, 4));
|
||||
if (24 === $unpack['sizeAttr']) {
|
||||
if ($unpack['sizeAttr'] === 24) {
|
||||
$tagData = substr($data, 4, $unpack['sizeAttr']);
|
||||
$this->mtime = PackUtil::unpackLongLE(substr($tagData, 0, 8)) / 10000000 - 11644473600;
|
||||
$this->atime = PackUtil::unpackLongLE(substr($tagData, 8, 8)) / 10000000 - 11644473600;
|
||||
@@ -70,7 +70,7 @@ class NtfsExtraField implements ExtraField
|
||||
public function serialize()
|
||||
{
|
||||
$serialize = '';
|
||||
if (null !== $this->mtime && null !== $this->atime && null !== $this->ctime) {
|
||||
if ($this->mtime !== null && $this->atime !== null && $this->ctime !== null) {
|
||||
$mtimeLong = ($this->mtime + 11644473600) * 10000000;
|
||||
$atimeLong = ($this->atime + 11644473600) * 10000000;
|
||||
$ctimeLong = ($this->ctime + 11644473600) * 10000000;
|
||||
|
@@ -119,6 +119,7 @@ class WinZipAesEntryExtraField implements ExtraField
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getKeyStrength()
|
||||
{
|
||||
@@ -153,6 +154,7 @@ class WinZipAesEntryExtraField implements ExtraField
|
||||
* Internal encryption method.
|
||||
*
|
||||
* @return int
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getEncryptionMethod()
|
||||
{
|
||||
|
@@ -29,7 +29,7 @@ class Zip64ExtraField implements ExtraField
|
||||
*/
|
||||
public function __construct(ZipEntry $entry = null)
|
||||
{
|
||||
if (null !== $entry) {
|
||||
if ($entry !== null) {
|
||||
$this->setEntry($entry);
|
||||
}
|
||||
}
|
||||
@@ -57,11 +57,10 @@ class Zip64ExtraField implements ExtraField
|
||||
/**
|
||||
* Serializes a Data Block.
|
||||
* @return string
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
if (null === $this->entry) {
|
||||
if ($this->entry === null) {
|
||||
throw new RuntimeException("entry is null");
|
||||
}
|
||||
$data = '';
|
||||
@@ -86,11 +85,11 @@ class Zip64ExtraField implements ExtraField
|
||||
/**
|
||||
* Initializes this Extra Field by deserializing a Data Block.
|
||||
* @param string $data
|
||||
* @throws RuntimeException
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
public function deserialize($data)
|
||||
{
|
||||
if (null === $this->entry) {
|
||||
if ($this->entry === null) {
|
||||
throw new RuntimeException("entry is null");
|
||||
}
|
||||
$off = 0;
|
||||
|
@@ -109,6 +109,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setEntry(ZipEntry $entry)
|
||||
{
|
||||
@@ -212,7 +213,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
protected function isInit($mask)
|
||||
{
|
||||
return 0 !== ($this->init & $mask);
|
||||
return ($this->init & $mask) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,11 +256,8 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function isZip64ExtensionsRequired()
|
||||
{
|
||||
// Offset MUST be considered in decision about ZIP64 format - see
|
||||
// description of Data Descriptor in ZIP File Format Specification!
|
||||
return 0xffffffff <= $this->getCompressedSize()
|
||||
|| 0xffffffff <= $this->getSize()
|
||||
|| 0xffffffff <= sprintf('%u', $this->getOffset());
|
||||
|| 0xffffffff <= $this->getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,7 +275,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*
|
||||
* @param int $compressedSize The Compressed Size.
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setCompressedSize($compressedSize)
|
||||
{
|
||||
@@ -300,7 +297,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*
|
||||
* @param int $size The (Uncompressed) Size.
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setSize($size)
|
||||
{
|
||||
@@ -321,7 +317,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
/**
|
||||
* @param int $offset
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setOffset($offset)
|
||||
{
|
||||
@@ -385,7 +380,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function getGeneralPurposeBitFlag($mask)
|
||||
{
|
||||
return 0 !== ($this->general & $mask);
|
||||
return ($this->general & $mask) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,6 +388,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
* encryption artifacts.
|
||||
*
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function disableEncryption()
|
||||
{
|
||||
@@ -404,7 +400,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
$field = $this->extraFieldsCollection[$headerId];
|
||||
if (self::METHOD_WINZIP_AES === $this->getMethod()) {
|
||||
$this->setMethod(null === $field ? self::UNKNOWN : $field->getMethod());
|
||||
$this->setMethod($field === null ? self::UNKNOWN : $field->getMethod());
|
||||
}
|
||||
unset($this->extraFieldsCollection[$headerId]);
|
||||
}
|
||||
@@ -432,7 +428,10 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->isInit(self::BIT_METHOD) ? $this->method & 0xffff : self::UNKNOWN;
|
||||
$isInit = $this->isInit(self::BIT_METHOD);
|
||||
return $isInit ?
|
||||
$this->method & 0xffff :
|
||||
self::UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,19 +443,16 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function setMethod($method)
|
||||
{
|
||||
if (self::UNKNOWN === $method) {
|
||||
if ($method === self::UNKNOWN) {
|
||||
$this->method = $method;
|
||||
$this->setInit(self::BIT_METHOD, false);
|
||||
return $this;
|
||||
}
|
||||
if (0x0000 > $method || $method > 0xffff) {
|
||||
throw new ZipException('method out of range');
|
||||
throw new ZipException('method out of range: ' . $method);
|
||||
}
|
||||
switch ($method) {
|
||||
case self::METHOD_WINZIP_AES:
|
||||
$this->method = $method;
|
||||
$this->setInit(self::BIT_METHOD, true);
|
||||
break;
|
||||
|
||||
case ZipFileInterface::METHOD_STORED:
|
||||
case ZipFileInterface::METHOD_DEFLATED:
|
||||
case ZipFileInterface::METHOD_BZIP2:
|
||||
@@ -513,6 +509,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*
|
||||
* @param int $unixTimestamp
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setTime($unixTimestamp)
|
||||
{
|
||||
@@ -544,7 +541,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*
|
||||
* @param int $externalAttributes the external file attributes.
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setExternalAttributes($externalAttributes)
|
||||
{
|
||||
@@ -622,7 +618,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function setComment($comment)
|
||||
{
|
||||
if (null !== $comment) {
|
||||
if ($comment !== null) {
|
||||
$commentLength = strlen($comment);
|
||||
if (0x0000 > $commentLength || $commentLength > 0xffff) {
|
||||
throw new ZipException("Comment too long");
|
||||
@@ -638,7 +634,7 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*/
|
||||
public function isDataDescriptorRequired()
|
||||
{
|
||||
return self::UNKNOWN == ($this->getCrc() | $this->getCompressedSize() | $this->getSize());
|
||||
return ($this->getCrc() | $this->getCompressedSize() | $this->getSize()) == self::UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,7 +652,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
*
|
||||
* @param int $crc
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setCrc($crc)
|
||||
{
|
||||
@@ -679,11 +674,12 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
* @param string $password
|
||||
* @param null|int $encryptionMethod
|
||||
* @return ZipEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setPassword($password, $encryptionMethod = null)
|
||||
{
|
||||
$this->password = $password;
|
||||
if (null !== $encryptionMethod) {
|
||||
if ($encryptionMethod !== null) {
|
||||
$this->setEncryptionMethod($encryptionMethod);
|
||||
}
|
||||
if (!empty($this->password)) {
|
||||
@@ -718,10 +714,10 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
{
|
||||
if (null !== $encryptionMethod) {
|
||||
if (
|
||||
ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL !== $encryptionMethod
|
||||
&& ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128 !== $encryptionMethod
|
||||
&& ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192 !== $encryptionMethod
|
||||
&& ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256 !== $encryptionMethod
|
||||
$encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
|
||||
&& $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
|
||||
&& $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
|
||||
&& $encryptionMethod !== ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
|
||||
) {
|
||||
throw new ZipException('Invalid encryption method');
|
||||
}
|
||||
@@ -741,7 +737,6 @@ abstract class ZipAbstractEntry implements ZipEntry
|
||||
/**
|
||||
* @param int $compressionLevel
|
||||
* @return ZipEntry
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
|
||||
{
|
||||
|
@@ -20,6 +20,8 @@ class ZipChangesEntry extends ZipAbstractEntry
|
||||
/**
|
||||
* ZipChangesEntry constructor.
|
||||
* @param ZipSourceEntry $entry
|
||||
* @throws ZipException
|
||||
* @throws \PhpZip\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __construct(ZipSourceEntry $entry)
|
||||
{
|
||||
|
@@ -3,13 +3,9 @@
|
||||
namespace PhpZip\Model\Entry;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\ZipFileInterface;
|
||||
|
||||
/**
|
||||
* Abstract class for new zip entry.
|
||||
*
|
||||
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
@@ -27,7 +23,6 @@ class ZipNewEntry extends ZipAbstractEntry
|
||||
/**
|
||||
* ZipNewEntry constructor.
|
||||
* @param string|resource|null $content
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($content = null)
|
||||
{
|
||||
@@ -42,12 +37,12 @@ class ZipNewEntry extends ZipAbstractEntry
|
||||
* Returns an string content of the given entry.
|
||||
*
|
||||
* @return null|string
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getEntryContent()
|
||||
{
|
||||
if (is_resource($this->content)) {
|
||||
return stream_get_contents($this->content, -1, 0);
|
||||
rewind($this->content);
|
||||
return stream_get_contents($this->content);
|
||||
}
|
||||
return $this->content;
|
||||
}
|
||||
@@ -81,7 +76,7 @@ class ZipNewEntry extends ZipAbstractEntry
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (!$this->clone && null !== $this->content && is_resource($this->content)) {
|
||||
if (!$this->clone && $this->content !== null && is_resource($this->content)) {
|
||||
fclose($this->content);
|
||||
$this->content = null;
|
||||
}
|
||||
|
53
src/PhpZip/Model/Entry/ZipNewFileEntry.php
Normal file
53
src/PhpZip/Model/Entry/ZipNewFileEntry.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Entry;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\RuntimeException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
/**
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
class ZipNewFileEntry extends ZipAbstractEntry
|
||||
{
|
||||
/**
|
||||
* @var string Filename
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* ZipNewEntry constructor.
|
||||
* @param string $file
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function __construct($file)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($file === null) {
|
||||
throw new InvalidArgumentException("file is null");
|
||||
}
|
||||
$file = (string)$file;
|
||||
if (!is_file($file)) {
|
||||
throw new ZipException("File $file does not exist.");
|
||||
}
|
||||
if (!is_readable($file)) {
|
||||
throw new ZipException("The '$file' file could not be read. Check permissions.");
|
||||
}
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an string content of the given entry.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getEntryContent()
|
||||
{
|
||||
if (!is_file($this->file)) {
|
||||
throw new RuntimeException("File {$this->file} does not exist.");
|
||||
}
|
||||
return file_get_contents($this->file);
|
||||
}
|
||||
}
|
@@ -57,22 +57,23 @@ class ZipSourceEntry extends ZipAbstractEntry
|
||||
* Returns an string content of the given entry.
|
||||
*
|
||||
* @return string
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getEntryContent()
|
||||
{
|
||||
if (null === $this->entryContent) {
|
||||
if ($this->entryContent === null) {
|
||||
// In order not to unpack again, we cache the content in memory or on disk
|
||||
$content = $this->inputStream->readEntryContent($this);
|
||||
if ($this->getSize() < self::MAX_SIZE_CACHED_CONTENT_IN_MEMORY) {
|
||||
$this->entryContent = $content;
|
||||
} else {
|
||||
$this->entryContent = fopen('php://temp', 'rb');
|
||||
$this->entryContent = fopen('php://temp', 'r+b');
|
||||
fwrite($this->entryContent, $content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
if (is_resource($this->entryContent)) {
|
||||
return stream_get_contents($this->entryContent, -1, 0);
|
||||
rewind($this->entryContent);
|
||||
return stream_get_contents($this->entryContent);
|
||||
}
|
||||
return $this->entryContent;
|
||||
}
|
||||
@@ -88,7 +89,7 @@ class ZipSourceEntry extends ZipAbstractEntry
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (!$this->clone && null !== $this->entryContent && is_resource($this->entryContent)) {
|
||||
if (!$this->clone && $this->entryContent !== null && is_resource($this->entryContent)) {
|
||||
fclose($this->entryContent);
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ interface ZipEntry
|
||||
// Bit masks for initialized fields.
|
||||
const BIT_PLATFORM = 1,
|
||||
BIT_METHOD = 2 /* 1 << 1 */,
|
||||
BIT_CRC = 2 /* 1 << 2 */,
|
||||
BIT_CRC = 4 /* 1 << 2 */,
|
||||
BIT_DATE_TIME = 64 /* 1 << 6 */,
|
||||
BIT_EXTERNAL_ATTR = 128 /* 1 << 7*/
|
||||
;
|
||||
|
@@ -145,7 +145,7 @@ class ZipEntryMatcher implements \Countable
|
||||
$entry = $this->zipModel->getEntry($entry);
|
||||
if (!$entry->isDirectory()) {
|
||||
$entry = $this->zipModel->getEntryForChanges($entry);
|
||||
$entry->clearEncryption();
|
||||
$entry->disableEncryption();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpMissingBreakStatementInspection */
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
@@ -186,6 +186,7 @@ class ZipInfo
|
||||
* ZipInfo constructor.
|
||||
*
|
||||
* @param ZipEntry $entry
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
public function __construct(ZipEntry $entry)
|
||||
{
|
||||
@@ -232,8 +233,6 @@ class ZipInfo
|
||||
$xattr = (($externalAttributes >> 16) & 0xFFFF);
|
||||
switch ($entry->getPlatform()) {
|
||||
case self::MADE_BY_MS_DOS:
|
||||
// no break
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case self::MADE_BY_WINDOWS_NTFS:
|
||||
if ($entry->getPlatform() != self::MADE_BY_MS_DOS ||
|
||||
($xattr & 0700) !=
|
||||
@@ -323,6 +322,7 @@ class ZipInfo
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
* @return int
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
private static function getMethodId(ZipEntry $entry)
|
||||
{
|
||||
@@ -344,6 +344,7 @@ class ZipInfo
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
* @return string
|
||||
* @throws \PhpZip\Exception\ZipException
|
||||
*/
|
||||
private static function getEntryMethodName(ZipEntry $entry)
|
||||
{
|
||||
|
@@ -3,8 +3,8 @@
|
||||
namespace PhpZip\Model;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipEntryNotFoundException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Exception\ZipNotFoundEntry;
|
||||
use PhpZip\Model\Entry\ZipChangesEntry;
|
||||
use PhpZip\Model\Entry\ZipSourceEntry;
|
||||
use PhpZip\ZipFileInterface;
|
||||
@@ -74,11 +74,10 @@ class ZipModel implements \Countable
|
||||
|
||||
/**
|
||||
* @param string $comment
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setArchiveComment($comment)
|
||||
{
|
||||
if (null !== $comment && strlen($comment) !== 0) {
|
||||
if ($comment !== null && strlen($comment) !== 0) {
|
||||
$comment = (string)$comment;
|
||||
$length = strlen($comment);
|
||||
if (0x0000 > $length || $length > 0xffff) {
|
||||
@@ -97,6 +96,7 @@ class ZipModel implements \Countable
|
||||
* Specify a password for extracting files.
|
||||
*
|
||||
* @param null|string $password
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setReadPassword($password)
|
||||
{
|
||||
@@ -110,12 +110,13 @@ class ZipModel implements \Countable
|
||||
/**
|
||||
* @param string $entryName
|
||||
* @param string $password
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setReadPasswordEntry($entryName, $password)
|
||||
{
|
||||
if (!isset($this->inputEntries[$entryName])) {
|
||||
throw new ZipNotFoundEntry('Not found entry ' . $entryName);
|
||||
throw new ZipEntryNotFoundException($entryName);
|
||||
}
|
||||
if ($this->inputEntries[$entryName]->isEncrypted()) {
|
||||
$this->inputEntries[$entryName]->setPassword($password);
|
||||
@@ -181,8 +182,7 @@ class ZipModel implements \Countable
|
||||
/**
|
||||
* @param string|ZipEntry $old
|
||||
* @param string|ZipEntry $new
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function renameEntry($old, $new)
|
||||
{
|
||||
@@ -202,6 +202,8 @@ class ZipModel implements \Countable
|
||||
/**
|
||||
* @param string|ZipEntry $entry
|
||||
* @return ZipChangesEntry|ZipEntry
|
||||
* @throws ZipException
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function getEntryForChanges($entry)
|
||||
{
|
||||
@@ -216,7 +218,7 @@ class ZipModel implements \Countable
|
||||
/**
|
||||
* @param string|ZipEntry $entryName
|
||||
* @return ZipEntry
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function getEntry($entryName)
|
||||
{
|
||||
@@ -224,7 +226,7 @@ class ZipModel implements \Countable
|
||||
if (isset($this->outEntries[$entryName])) {
|
||||
return $this->outEntries[$entryName];
|
||||
}
|
||||
throw new ZipNotFoundEntry('Zip entry ' . $entryName . ' not found');
|
||||
throw new ZipEntryNotFoundException($entryName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +329,6 @@ class ZipModel implements \Countable
|
||||
|
||||
/**
|
||||
* @param int $encryptionMethod
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setEncryptionMethod($encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256)
|
||||
{
|
||||
|
@@ -7,9 +7,9 @@ use PhpZip\Crypto\WinZipAesEngine;
|
||||
use PhpZip\Exception\Crc32Exception;
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\RuntimeException;
|
||||
use PhpZip\Exception\ZipCryptoException;
|
||||
use PhpZip\Exception\ZipAuthenticationException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Exception\ZipUnsupportMethod;
|
||||
use PhpZip\Exception\ZipUnsupportMethodException;
|
||||
use PhpZip\Extra\ExtraFieldsCollection;
|
||||
use PhpZip\Extra\ExtraFieldsFactory;
|
||||
use PhpZip\Extra\Fields\ApkAlignmentExtraField;
|
||||
@@ -56,7 +56,6 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
/**
|
||||
* ZipInputStream constructor.
|
||||
* @param resource $in
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct($in)
|
||||
{
|
||||
@@ -69,6 +68,7 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
|
||||
/**
|
||||
* @return ZipModel
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function readZip()
|
||||
{
|
||||
@@ -144,8 +144,14 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
);
|
||||
}
|
||||
// .ZIP file comment (variable size)
|
||||
if (0 < $data['commentLength']) {
|
||||
$comment = fread($this->in, $data['commentLength']);
|
||||
if ($data['commentLength'] > 0) {
|
||||
$comment = '';
|
||||
$offset = 0;
|
||||
while ($offset < $data['commentLength']) {
|
||||
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
|
||||
$comment .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
}
|
||||
$this->preamble = $endOfCentralDirRecordPos;
|
||||
$this->postamble = $size - ftell($this->in);
|
||||
@@ -165,7 +171,7 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
$offset = $endOfCentralDirRecordPos - $data['cdSize'];
|
||||
fseek($this->in, $offset, SEEK_SET);
|
||||
$offset -= $data['cdPos'];
|
||||
if (0 !== $offset) {
|
||||
if ($offset !== 0) {
|
||||
$this->mapper = new OffsetPositionMapper($offset);
|
||||
}
|
||||
$entryCount = $data['cdEntries'];
|
||||
@@ -262,14 +268,13 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
$entries[$entry->getName()] = $entry;
|
||||
}
|
||||
|
||||
if (0 !== $numEntries % 0x10000) {
|
||||
if (($numEntries % 0x10000) !== 0) {
|
||||
throw new ZipException("Expected " . abs($numEntries) .
|
||||
($numEntries > 0 ? " more" : " less") .
|
||||
" entries in the Central Directory!");
|
||||
}
|
||||
|
||||
if ($this->preamble + $this->postamble >= fstat($this->in)['size']) {
|
||||
assert(0 === $numEntries);
|
||||
$this->checkZipFileSignature();
|
||||
}
|
||||
|
||||
@@ -278,13 +283,13 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
|
||||
/**
|
||||
* @return ZipEntry
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function readEntry()
|
||||
{
|
||||
// central file header signature 4 bytes (0x02014b50)
|
||||
$fileHeaderSig = unpack('V', fread($this->in, 4))[1];
|
||||
if (ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG !== $fileHeaderSig) {
|
||||
if ($fileHeaderSig !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
|
||||
throw new InvalidArgumentException("Corrupt zip file. Can not read zip entry.");
|
||||
}
|
||||
|
||||
@@ -312,10 +317,16 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
fread($this->in, 42)
|
||||
);
|
||||
|
||||
// $utf8 = 0 !== ($data['gpbf'] & self::GPBF_UTF8);
|
||||
// $utf8 = ($data['gpbf'] & ZipEntry::GPBF_UTF8) !== 0;
|
||||
|
||||
// See appendix D of PKWARE's ZIP File Format Specification.
|
||||
$name = fread($this->in, $data['fileLength']);
|
||||
$name = '';
|
||||
$offset = 0;
|
||||
while ($offset < $data['fileLength']) {
|
||||
$read = min(8192 /* chunk size */, $data['fileLength'] - $offset);
|
||||
$name .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
|
||||
$entry = new ZipSourceEntry($this);
|
||||
$entry->setName($name);
|
||||
@@ -329,11 +340,25 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
$entry->setSize($data['rawSize']);
|
||||
$entry->setExternalAttributes($data['rawExternalAttributes']);
|
||||
$entry->setOffset($data['lfhOff']); // must be unmapped!
|
||||
if (0 < $data['extraLength']) {
|
||||
$entry->setExtra(fread($this->in, $data['extraLength']));
|
||||
if ($data['extraLength'] > 0) {
|
||||
$extra = '';
|
||||
$offset = 0;
|
||||
while ($offset < $data['extraLength']) {
|
||||
$read = min(8192 /* chunk size */, $data['extraLength'] - $offset);
|
||||
$extra .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
$entry->setExtra($extra);
|
||||
}
|
||||
if (0 < $data['commentLength']) {
|
||||
$entry->setComment(fread($this->in, $data['commentLength']));
|
||||
if ($data['commentLength'] > 0) {
|
||||
$comment = '';
|
||||
$offset = 0;
|
||||
while ($offset < $data['commentLength']) {
|
||||
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
|
||||
$comment .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
$entry->setComment($comment);
|
||||
}
|
||||
return $entry;
|
||||
}
|
||||
@@ -352,19 +377,20 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
throw new InvalidArgumentException('entry must be ' . ZipSourceEntry::class);
|
||||
}
|
||||
$isEncrypted = $entry->isEncrypted();
|
||||
if ($isEncrypted && null === $entry->getPassword()) {
|
||||
if ($isEncrypted && $entry->getPassword() === null) {
|
||||
throw new ZipException("Can not password from entry " . $entry->getName());
|
||||
}
|
||||
|
||||
$pos = $entry->getOffset();
|
||||
assert(ZipEntry::UNKNOWN !== $pos);
|
||||
$pos = PHP_INT_SIZE === 4 ? sprintf('%u', $pos) : $pos;
|
||||
$pos = PHP_INT_SIZE === 4
|
||||
? sprintf('%u', $pos) // PHP 32-Bit
|
||||
: $pos; // PHP 64-Bit
|
||||
|
||||
$startPos = $pos = $this->mapper->map($pos);
|
||||
fseek($this->in, $startPos);
|
||||
|
||||
// local file header signature 4 bytes (0x04034b50)
|
||||
if (ZipEntry::LOCAL_FILE_HEADER_SIG !== unpack('V', fread($this->in, 4))[1]) {
|
||||
if (unpack('V', fread($this->in, 4))[1] !== ZipEntry::LOCAL_FILE_HEADER_SIG) {
|
||||
throw new ZipException($entry->getName() . " (expected Local File Header)");
|
||||
}
|
||||
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_FILE_NAME_LENGTH_POS);
|
||||
@@ -382,15 +408,19 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
// Get raw entry content
|
||||
$compressedSize = $entry->getCompressedSize();
|
||||
$compressedSize = PHP_INT_SIZE === 4 ? sprintf('%u', $compressedSize) : $compressedSize;
|
||||
$content = '';
|
||||
if ($compressedSize > 0) {
|
||||
$content = fread($this->in, $compressedSize);
|
||||
} else {
|
||||
$content = '';
|
||||
$offset = 0;
|
||||
while ($offset < $compressedSize) {
|
||||
$read = min(8192 /* chunk size */, $compressedSize - $offset);
|
||||
$content .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
}
|
||||
|
||||
$skipCheckCrc = false;
|
||||
if ($isEncrypted) {
|
||||
if (ZipEntry::METHOD_WINZIP_AES === $method) {
|
||||
if ($method === ZipEntry::METHOD_WINZIP_AES) {
|
||||
// Strong Encryption Specification - WinZip AES
|
||||
$winZipAesEngine = new WinZipAesEngine($entry);
|
||||
$content = $winZipAesEngine->decrypt($content);
|
||||
@@ -418,7 +448,7 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
// but older apps might not.
|
||||
fseek($this->in, $pos + $compressedSize);
|
||||
$localCrc = unpack('V', fread($this->in, 4))[1];
|
||||
if (ZipEntry::DATA_DESCRIPTOR_SIG === $localCrc) {
|
||||
if ($localCrc === ZipEntry::DATA_DESCRIPTOR_SIG) {
|
||||
$localCrc = unpack('V', fread($this->in, 4))[1];
|
||||
}
|
||||
} else {
|
||||
@@ -440,25 +470,46 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
case ZipFileInterface::METHOD_STORED:
|
||||
break;
|
||||
case ZipFileInterface::METHOD_DEFLATED:
|
||||
$content = gzinflate($content);
|
||||
$content = @gzinflate($content);
|
||||
break;
|
||||
case ZipFileInterface::METHOD_BZIP2:
|
||||
if (!extension_loaded('bz2')) {
|
||||
throw new ZipException('Extension bzip2 not install');
|
||||
}
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$content = bzdecompress($content);
|
||||
if (is_int($content)) { // decompress error
|
||||
$content = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ZipUnsupportMethod($entry->getName() .
|
||||
throw new ZipUnsupportMethodException($entry->getName() .
|
||||
" (compression method " . $method . " is not supported)");
|
||||
}
|
||||
|
||||
if ($content === false) {
|
||||
if ($isEncrypted) {
|
||||
throw new ZipAuthenticationException(sprintf(
|
||||
'Invalid password for zip entry "%s"',
|
||||
$entry->getName()
|
||||
));
|
||||
}
|
||||
throw new ZipException(sprintf(
|
||||
'Failed to get the contents of the zip entry "%s"',
|
||||
$entry->getName()
|
||||
));
|
||||
}
|
||||
|
||||
if (!$skipCheckCrc) {
|
||||
$localCrc = crc32($content);
|
||||
$localCrc = PHP_INT_SIZE === 4 ? sprintf('%u', $localCrc) : $localCrc;
|
||||
$crc = PHP_INT_SIZE === 4 ? sprintf('%u', $entry->getCrc()) : $entry->getCrc();
|
||||
if ($crc != $localCrc) {
|
||||
if ($isEncrypted) {
|
||||
throw new ZipCryptoException("Wrong password");
|
||||
throw new ZipAuthenticationException(sprintf(
|
||||
'Invalid password for zip entry "%s"',
|
||||
$entry->getName()
|
||||
));
|
||||
}
|
||||
throw new Crc32Exception($entry->getName(), $crc, $localCrc);
|
||||
}
|
||||
@@ -480,6 +531,7 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
*
|
||||
* @param ZipEntry $entry
|
||||
* @param ZipOutputStreamInterface $out
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out)
|
||||
{
|
||||
@@ -496,7 +548,13 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
if ($sourceExtraLength > 0) {
|
||||
// read Local File Header extra fields
|
||||
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength, SEEK_SET);
|
||||
$extra = fread($this->in, $sourceExtraLength);
|
||||
$extra = '';
|
||||
$offset = 0;
|
||||
while ($offset < $sourceExtraLength) {
|
||||
$read = min(8192 /* chunk size */, $sourceExtraLength - $offset);
|
||||
$extra .= fread($this->in, $read);
|
||||
$offset += $read;
|
||||
}
|
||||
$extraFieldsCollection = ExtraFieldsFactory::createExtraFieldCollections($extra, $entry);
|
||||
if (isset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]) && $this->zipModel->isZipAlign()) {
|
||||
unset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]);
|
||||
@@ -552,7 +610,6 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
fseek($this->in, $sourceExtraLength, SEEK_CUR);
|
||||
} else {
|
||||
$copyInToOutLength += ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $sourceExtraLength + $nameLength;
|
||||
;
|
||||
}
|
||||
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
|
||||
// crc-32 4 bytes
|
||||
@@ -595,7 +652,7 @@ class ZipInputStream implements ZipInputStreamInterface
|
||||
|
||||
public function close()
|
||||
{
|
||||
if ($this->in != null) {
|
||||
if ($this->in !== null) {
|
||||
fclose($this->in);
|
||||
$this->in = null;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpZip\Stream;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\Model\ZipModel;
|
||||
|
||||
@@ -26,6 +27,7 @@ interface ZipInputStreamInterface
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
* @return string
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function readEntryContent(ZipEntry $entry);
|
||||
|
||||
|
@@ -22,8 +22,7 @@ use PhpZip\Util\StringUtil;
|
||||
use PhpZip\ZipFileInterface;
|
||||
|
||||
/**
|
||||
* Write
|
||||
* ip file
|
||||
* Write zip file
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
@@ -43,7 +42,6 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
* ZipOutputStream constructor.
|
||||
* @param resource $out
|
||||
* @param ZipModel $zipModel
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($out, ZipModel $zipModel)
|
||||
{
|
||||
@@ -54,6 +52,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
$this->zipModel = $zipModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function writeZip()
|
||||
{
|
||||
$entries = $this->zipModel->getEntries();
|
||||
@@ -123,7 +124,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
}
|
||||
|
||||
$size = $nameLength + $extraLength;
|
||||
if (0xffff < $size) {
|
||||
if ($size > 0xffff) {
|
||||
throw new ZipException(
|
||||
$entry->getName() . " (the total size of " . $size .
|
||||
" bytes for the name, extra fields and comment " .
|
||||
@@ -168,7 +169,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
|
||||
if ($entry instanceof ZipChangesEntry && !$entry->isChangedContent()) {
|
||||
$entry->getSourceEntry()->getInputStream()->copyEntryData($entry->getSourceEntry(), $this);
|
||||
} elseif (null !== $entryContent) {
|
||||
} elseif ($entryContent !== null) {
|
||||
fwrite($this->out, $entryContent);
|
||||
}
|
||||
|
||||
@@ -186,7 +187,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
} else {
|
||||
fwrite($this->out, pack('VV', $entry->getCompressedSize(), $entry->getSize()));
|
||||
}
|
||||
} elseif ($entry->getCompressedSize() != $compressedSize) {
|
||||
} elseif ($compressedSize != $entry->getCompressedSize()) {
|
||||
throw new ZipException(
|
||||
$entry->getName() . " (expected compressed entry size of "
|
||||
. $entry->getCompressedSize() . " bytes, " .
|
||||
@@ -202,10 +203,10 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
*/
|
||||
protected function entryCommitChangesAndReturnContent(ZipEntry $entry)
|
||||
{
|
||||
if (ZipEntry::UNKNOWN === $entry->getPlatform()) {
|
||||
if ($entry->getPlatform() === ZipEntry::UNKNOWN) {
|
||||
$entry->setPlatform(ZipEntry::PLATFORM_UNIX);
|
||||
}
|
||||
if (ZipEntry::UNKNOWN === $entry->getTime()) {
|
||||
if ($entry->getTime() === ZipEntry::UNKNOWN) {
|
||||
$entry->setTime(time());
|
||||
}
|
||||
$method = $entry->getMethod();
|
||||
@@ -214,7 +215,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
// See appendix D of PKWARE's ZIP File Format Specification.
|
||||
$utf8 = true;
|
||||
|
||||
if ($encrypted && null === $entry->getPassword()) {
|
||||
if ($encrypted && $entry->getPassword() === null) {
|
||||
throw new ZipException("Can not password from entry " . $entry->getName());
|
||||
}
|
||||
|
||||
@@ -223,7 +224,6 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
| ($entry->isDataDescriptorRequired() ? ZipEntry::GPBF_DATA_DESCRIPTOR : 0)
|
||||
| ($utf8 ? ZipEntry::GPBF_UTF8 : 0);
|
||||
|
||||
$skipCrc = false;
|
||||
$entryContent = null;
|
||||
$extraFieldsCollection = $entry->getExtraFieldsCollection();
|
||||
if (!($entry instanceof ZipChangesEntry && !$entry->isChangedContent())) {
|
||||
@@ -233,57 +233,13 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
$entry->setSize(strlen($entryContent));
|
||||
$entry->setCrc(crc32($entryContent));
|
||||
|
||||
if (
|
||||
$encrypted &&
|
||||
(
|
||||
ZipEntry::METHOD_WINZIP_AES === $method ||
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128 ||
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192 ||
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
|
||||
)
|
||||
) {
|
||||
$field = null;
|
||||
$method = $entry->getMethod();
|
||||
$keyStrength = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($entry->getEncryptionMethod()); // size bits
|
||||
|
||||
$compressedSize = $entry->getCompressedSize();
|
||||
|
||||
if (ZipEntry::METHOD_WINZIP_AES === $method) {
|
||||
/**
|
||||
* @var WinZipAesEntryExtraField $field
|
||||
*/
|
||||
$field = $extraFieldsCollection->get(WinZipAesEntryExtraField::getHeaderId());
|
||||
if (null !== $field) {
|
||||
$method = $field->getMethod();
|
||||
if (ZipEntry::UNKNOWN !== $compressedSize) {
|
||||
$compressedSize -= $field->getKeyStrength() / 2 // salt value
|
||||
+ 2 // password verification value
|
||||
+ 10; // authentication code
|
||||
}
|
||||
$entry->setMethod($method);
|
||||
}
|
||||
}
|
||||
if (null === $field) {
|
||||
$field = ExtraFieldsFactory::createWinZipAesEntryExtra();
|
||||
}
|
||||
$field->setKeyStrength($keyStrength);
|
||||
$field->setMethod($method);
|
||||
$size = $entry->getSize();
|
||||
if (20 <= $size && ZipFileInterface::METHOD_BZIP2 !== $method) {
|
||||
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_1);
|
||||
} else {
|
||||
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_2);
|
||||
$skipCrc = true;
|
||||
}
|
||||
$extraFieldsCollection->add($field);
|
||||
if (ZipEntry::UNKNOWN !== $compressedSize) {
|
||||
$compressedSize += $field->getKeyStrength() / 2 // salt value
|
||||
+ 2 // password verification value
|
||||
+ 10; // authentication code
|
||||
$entry->setCompressedSize($compressedSize);
|
||||
}
|
||||
if ($skipCrc) {
|
||||
$entry->setCrc(0);
|
||||
if ($encrypted && $method === ZipEntry::METHOD_WINZIP_AES) {
|
||||
/**
|
||||
* @var WinZipAesEntryExtraField $field
|
||||
*/
|
||||
$field = $extraFieldsCollection->get(WinZipAesEntryExtraField::getHeaderId());
|
||||
if ($field !== null) {
|
||||
$method = $field->getMethod();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +255,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
$compressionLevel = $entry->getCompressionLevel() === ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ?
|
||||
ZipEntry::LEVEL_DEFAULT_BZIP2_COMPRESSION :
|
||||
$entry->getCompressionLevel();
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$entryContent = bzcompress($entryContent, $compressionLevel);
|
||||
if (is_int($entryContent)) {
|
||||
throw new ZipException('Error bzip2 compress. Error code: ' . $entryContent);
|
||||
@@ -314,7 +271,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
throw new ZipException($entry->getName() . " (unsupported compression method " . $method . ")");
|
||||
}
|
||||
|
||||
if (ZipFileInterface::METHOD_DEFLATED === $method) {
|
||||
if ($method === ZipFileInterface::METHOD_DEFLATED) {
|
||||
$bit1 = false;
|
||||
$bit2 = false;
|
||||
switch ($entry->getCompressionLevel()) {
|
||||
@@ -337,14 +294,23 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
}
|
||||
|
||||
if ($encrypted) {
|
||||
if (
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128 ||
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192 ||
|
||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
|
||||
) {
|
||||
if ($skipCrc) {
|
||||
if (in_array($entry->getEncryptionMethod(), [
|
||||
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
|
||||
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
|
||||
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
|
||||
], true)) {
|
||||
$keyStrength = WinZipAesEntryExtraField::getKeyStrangeFromEncryptionMethod($entry->getEncryptionMethod()); // size bits
|
||||
$field = ExtraFieldsFactory::createWinZipAesEntryExtra();
|
||||
$field->setKeyStrength($keyStrength);
|
||||
$field->setMethod($method);
|
||||
$size = $entry->getSize();
|
||||
if ($size >= 20 && $method !== ZipFileInterface::METHOD_BZIP2) {
|
||||
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_1);
|
||||
} else {
|
||||
$field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_2);
|
||||
$entry->setCrc(0);
|
||||
}
|
||||
$extraFieldsCollection->add($field);
|
||||
$entry->setMethod(ZipEntry::METHOD_WINZIP_AES);
|
||||
|
||||
$winZipAesEngine = new WinZipAesEngine($entry);
|
||||
@@ -375,10 +341,11 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
* @param ZipEntry $entry
|
||||
* @param string $content
|
||||
* @return string
|
||||
* @throws ZipException
|
||||
*/
|
||||
protected function determineBestCompressionMethod(ZipEntry $entry, $content)
|
||||
{
|
||||
if (null !== $content) {
|
||||
if ($content !== null) {
|
||||
$entryContent = gzdeflate($content, $entry->getCompressionLevel());
|
||||
if (strlen($entryContent) < strlen($content)) {
|
||||
$entry->setMethod(ZipFileInterface::METHOD_DEFLATED);
|
||||
@@ -393,8 +360,6 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
* Writes a Central File Header record.
|
||||
*
|
||||
* @param OutputOffsetEntry $outEntry
|
||||
* @throws RuntimeException
|
||||
* @internal param OutPosEntry $entry
|
||||
*/
|
||||
protected function writeCentralDirectoryHeader(OutputOffsetEntry $outEntry)
|
||||
{
|
||||
@@ -403,7 +368,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
$size = $entry->getSize();
|
||||
// This test MUST NOT include the CRC-32 because VV_AE_2 sets it to
|
||||
// UNKNOWN!
|
||||
if (ZipEntry::UNKNOWN === ($compressedSize | $size)) {
|
||||
if (($compressedSize | $size) === ZipEntry::UNKNOWN) {
|
||||
throw new RuntimeException("invalid entry");
|
||||
}
|
||||
$extra = $entry->getExtra();
|
||||
@@ -450,11 +415,11 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
||||
);
|
||||
// file name (variable size)
|
||||
fwrite($this->out, $entry->getName());
|
||||
if (0 < $extraSize) {
|
||||
if ($extraSize > 0) {
|
||||
// extra field (variable size)
|
||||
fwrite($this->out, $extra);
|
||||
}
|
||||
if (0 < $commentLength) {
|
||||
if ($commentLength > 0) {
|
||||
// file comment (variable size)
|
||||
fwrite($this->out, $entry->getComment());
|
||||
}
|
||||
|
@@ -15,16 +15,22 @@ class CryptoUtil
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
final public static function randomBytes($length)
|
||||
{
|
||||
$length = (int)$length;
|
||||
if (function_exists('random_bytes')) {
|
||||
return random_bytes($length);
|
||||
try {
|
||||
return random_bytes($length);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException("Could not generate a random string.");
|
||||
}
|
||||
} elseif (function_exists('openssl_random_pseudo_bytes')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
} elseif (function_exists('mcrypt_create_iv')) {
|
||||
/** @noinspection PhpDeprecationInspection */
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return mcrypt_create_iv($length);
|
||||
} else {
|
||||
throw new RuntimeException('Extension openssl or mcrypt not loaded');
|
||||
|
@@ -12,7 +12,6 @@ use PhpZip\Util\StringUtil;
|
||||
*/
|
||||
class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
|
||||
/**
|
||||
* Ignore list files
|
||||
*
|
||||
@@ -65,6 +64,7 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
return new self($this->getInnerIterator()->getChildren(), $this->ignoreFiles);
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace PhpZip\Util;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
/**
|
||||
* Pack util
|
||||
*
|
||||
@@ -35,7 +33,6 @@ class PackUtil
|
||||
/**
|
||||
* @param string|int $value
|
||||
* @return int
|
||||
* @throws ZipException
|
||||
*/
|
||||
public static function unpackLongLE($value)
|
||||
{
|
||||
|
@@ -28,4 +28,29 @@ class StringUtil
|
||||
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0
|
||||
&& strpos($haystack, $needle, $temp) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
public static function cp866toUtf8($str)
|
||||
{
|
||||
if (function_exists('iconv')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return iconv('CP866', 'UTF-8//IGNORE', $str);
|
||||
} elseif (function_exists('mb_convert_encoding')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
return mb_convert_encoding($str, 'UTF-8', 'CP866');
|
||||
} elseif (class_exists('UConverter')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$converter = new \UConverter('UTF-8', 'CP866');
|
||||
return $converter->convert($str, false);
|
||||
} else {
|
||||
static $cp866Utf8Pairs;
|
||||
if (empty($cp866Utf8Pairs)) {
|
||||
$cp866Utf8Pairs = require __DIR__ . '/encodings/cp866-utf8.php';
|
||||
}
|
||||
return strtr($str, $cp866Utf8Pairs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
src/PhpZip/Util/encodings/cp866-utf8.php
Normal file
BIN
src/PhpZip/Util/encodings/cp866-utf8.php
Normal file
Binary file not shown.
@@ -3,10 +3,11 @@
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipEntryNotFoundException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Exception\ZipNotFoundEntry;
|
||||
use PhpZip\Exception\ZipUnsupportMethod;
|
||||
use PhpZip\Exception\ZipUnsupportMethodException;
|
||||
use PhpZip\Model\Entry\ZipNewEntry;
|
||||
use PhpZip\Model\Entry\ZipNewFileEntry;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\Model\ZipEntryMatcher;
|
||||
use PhpZip\Model\ZipInfo;
|
||||
@@ -34,8 +35,7 @@ use Psr\Http\Message\ResponseInterface;
|
||||
class ZipFile implements ZipFileInterface
|
||||
{
|
||||
/**
|
||||
* Allow compression methods.
|
||||
* @var int[]
|
||||
* @var int[] Allow compression methods.
|
||||
*/
|
||||
private static $allowCompressionMethods = [
|
||||
self::METHOD_STORED,
|
||||
@@ -45,8 +45,7 @@ class ZipFile implements ZipFileInterface
|
||||
];
|
||||
|
||||
/**
|
||||
* Allow encryption methods.
|
||||
* @var int[]
|
||||
* @var int[] Allow encryption methods.
|
||||
*/
|
||||
private static $allowEncryptionMethods = [
|
||||
self::ENCRYPTION_METHOD_TRADITIONAL,
|
||||
@@ -56,9 +55,7 @@ class ZipFile implements ZipFileInterface
|
||||
];
|
||||
|
||||
/**
|
||||
* Default mime types.
|
||||
*
|
||||
* @var array
|
||||
* @var array Default mime types.
|
||||
*/
|
||||
private static $defaultMimeTypes = [
|
||||
'zip' => 'application/zip',
|
||||
@@ -69,9 +66,7 @@ class ZipFile implements ZipFileInterface
|
||||
];
|
||||
|
||||
/**
|
||||
* Input seekable input stream.
|
||||
*
|
||||
* @var ZipInputStreamInterface
|
||||
* @var ZipInputStreamInterface Input seekable input stream.
|
||||
*/
|
||||
protected $inputStream;
|
||||
/**
|
||||
@@ -92,13 +87,12 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $filename
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException if file doesn't exists.
|
||||
* @throws ZipException if can't open file.
|
||||
* @throws ZipException if can't open file.
|
||||
*/
|
||||
public function openFile($filename)
|
||||
{
|
||||
if (!file_exists($filename)) {
|
||||
throw new InvalidArgumentException("File $filename can't exists.");
|
||||
throw new ZipException("File $filename does not exist.");
|
||||
}
|
||||
if (!($handle = @fopen($filename, 'rb'))) {
|
||||
throw new ZipException("File $filename can't open.");
|
||||
@@ -112,13 +106,12 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $data
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException if data not available.
|
||||
* @throws ZipException if can't open temp stream.
|
||||
* @throws ZipException if can't open temp stream.
|
||||
*/
|
||||
public function openFromString($data)
|
||||
{
|
||||
if (null === $data || strlen($data) === 0) {
|
||||
throw new InvalidArgumentException("Data not available");
|
||||
if ($data === null || strlen($data) === 0) {
|
||||
throw new InvalidArgumentException("Empty string passed");
|
||||
}
|
||||
if (!($handle = fopen('php://temp', 'r+b'))) {
|
||||
throw new ZipException("Can't open temp stream.");
|
||||
@@ -134,8 +127,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param resource $handle
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException Invalid stream resource
|
||||
* or resource cannot seekable stream
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function openFromStream($handle)
|
||||
{
|
||||
@@ -143,11 +135,11 @@ class ZipFile implements ZipFileInterface
|
||||
throw new InvalidArgumentException("Invalid stream resource.");
|
||||
}
|
||||
$type = get_resource_type($handle);
|
||||
if ('stream' !== $type) {
|
||||
if ($type !== 'stream') {
|
||||
throw new InvalidArgumentException("Invalid resource type - $type.");
|
||||
}
|
||||
$meta = stream_get_meta_data($handle);
|
||||
if ('dir' === $meta['stream_type']) {
|
||||
if ($meta['stream_type'] === 'dir') {
|
||||
throw new InvalidArgumentException("Invalid stream type - {$meta['stream_type']}.");
|
||||
}
|
||||
if (!$meta['seekable']) {
|
||||
@@ -189,7 +181,6 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param null|string $comment
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException Length comment out of range
|
||||
*/
|
||||
public function setArchiveComment($comment = null)
|
||||
{
|
||||
@@ -204,7 +195,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $entryName
|
||||
* @return bool
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function isDirectory($entryName)
|
||||
{
|
||||
@@ -216,7 +207,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $entryName
|
||||
* @return string
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function getEntryComment($entryName)
|
||||
{
|
||||
@@ -229,7 +220,8 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string $entryName
|
||||
* @param string|null $comment
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipException
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function setEntryComment($entryName, $comment = null)
|
||||
{
|
||||
@@ -242,6 +234,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $entryName
|
||||
* @return string
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getEntryContents($entryName)
|
||||
{
|
||||
@@ -264,7 +257,8 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string|ZipEntry $entryName
|
||||
* @return ZipInfo
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function getEntryInfo($entryName)
|
||||
{
|
||||
@@ -347,7 +341,7 @@ class ZipFile implements ZipFileInterface
|
||||
chmod($dir, 0755);
|
||||
touch($dir, $entry->getTime());
|
||||
}
|
||||
if (false === file_put_contents($file, $entry->getEntryContent())) {
|
||||
if (file_put_contents($file, $entry->getEntryContent()) === false) {
|
||||
throw new ZipException('Can not extract file ' . $entry->getName());
|
||||
}
|
||||
touch($file, $entry->getTime());
|
||||
@@ -361,34 +355,36 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string $localName Zip entry name.
|
||||
* @param string $contents String contents.
|
||||
* @param int|null $compressionMethod Compression method.
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* Use {@see ZipFile::METHOD_STORED}, {@see ZipFile::METHOD_DEFLATED} or {@see ZipFile::METHOD_BZIP2}.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException If incorrect data or entry name.
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipException
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
*/
|
||||
public function addFromString($localName, $contents, $compressionMethod = null)
|
||||
{
|
||||
if (null === $contents) {
|
||||
if ($contents === null) {
|
||||
throw new InvalidArgumentException("Contents is null");
|
||||
}
|
||||
$localName = (string)$localName;
|
||||
if (null === $localName || 0 === strlen($localName)) {
|
||||
throw new InvalidArgumentException("Incorrect entry name " . $localName);
|
||||
if ($localName === null) {
|
||||
throw new InvalidArgumentException("Entry name is null");
|
||||
}
|
||||
$localName = ltrim((string)$localName, "\\/");
|
||||
if (strlen($localName) === 0) {
|
||||
throw new InvalidArgumentException("Empty entry name");
|
||||
}
|
||||
$contents = (string)$contents;
|
||||
$length = strlen($contents);
|
||||
if (null === $compressionMethod) {
|
||||
if ($compressionMethod === null) {
|
||||
if ($length >= 512) {
|
||||
$compressionMethod = ZipEntry::UNKNOWN;
|
||||
} else {
|
||||
$compressionMethod = ZipFileInterface::METHOD_STORED;
|
||||
$compressionMethod = self::METHOD_STORED;
|
||||
}
|
||||
} elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
|
||||
throw new ZipUnsupportMethod('Unsupported compression method ' . $compressionMethod);
|
||||
throw new ZipUnsupportMethodException('Unsupported compression method ' . $compressionMethod);
|
||||
}
|
||||
$externalAttributes = 0100644 << 16;
|
||||
|
||||
@@ -411,49 +407,54 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipException
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
*/
|
||||
public function addFile($filename, $localName = null, $compressionMethod = null)
|
||||
{
|
||||
if (null === $filename) {
|
||||
throw new InvalidArgumentException("Filename is null");
|
||||
}
|
||||
if (!is_file($filename)) {
|
||||
throw new InvalidArgumentException("File $filename is not exists");
|
||||
}
|
||||
$entry = new ZipNewFileEntry($filename);
|
||||
|
||||
if (null === $compressionMethod) {
|
||||
if ($compressionMethod === null) {
|
||||
if (function_exists('mime_content_type')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$mimeType = @mime_content_type($filename);
|
||||
$type = strtok($mimeType, '/');
|
||||
if ('image' === $type) {
|
||||
$compressionMethod = ZipFileInterface::METHOD_STORED;
|
||||
} elseif ('text' === $type && filesize($filename) < 150) {
|
||||
$compressionMethod = ZipFileInterface::METHOD_STORED;
|
||||
if ($type === 'image') {
|
||||
$compressionMethod = self::METHOD_STORED;
|
||||
} elseif ($type === 'text' && filesize($filename) < 150) {
|
||||
$compressionMethod = self::METHOD_STORED;
|
||||
} else {
|
||||
$compressionMethod = ZipEntry::UNKNOWN;
|
||||
}
|
||||
} elseif (@filesize($filename) >= 512) {
|
||||
} elseif (filesize($filename) >= 512) {
|
||||
$compressionMethod = ZipEntry::UNKNOWN;
|
||||
} else {
|
||||
$compressionMethod = ZipFileInterface::METHOD_STORED;
|
||||
$compressionMethod = self::METHOD_STORED;
|
||||
}
|
||||
} elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
|
||||
throw new ZipUnsupportMethod('Unsupported method ' . $compressionMethod);
|
||||
throw new ZipUnsupportMethodException('Unsupported compression method ' . $compressionMethod);
|
||||
}
|
||||
|
||||
if (!($handle = @fopen($filename, 'rb'))) {
|
||||
throw new InvalidArgumentException('File ' . $filename . ' can not open.');
|
||||
}
|
||||
if (null === $localName) {
|
||||
if ($localName === null) {
|
||||
$localName = basename($filename);
|
||||
}
|
||||
$this->addFromStream($handle, $localName, $compressionMethod);
|
||||
$this->zipModel->getEntry($localName)->setTime(filemtime($filename));
|
||||
$localName = ltrim((string)$localName, "\\/");
|
||||
if (strlen($localName) === 0) {
|
||||
throw new InvalidArgumentException("Empty entry name");
|
||||
}
|
||||
|
||||
$stat = stat($filename);
|
||||
$mode = sprintf('%o', $stat['mode']);
|
||||
$externalAttributes = (octdec($mode) & 0xffff) << 16;
|
||||
|
||||
$entry->setName($localName);
|
||||
$entry->setMethod($compressionMethod);
|
||||
$entry->setTime($stat['mtime']);
|
||||
$entry->setExternalAttributes($externalAttributes);
|
||||
|
||||
$this->zipModel->addEntry($entry);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -466,8 +467,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipException
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -475,22 +475,25 @@ class ZipFile implements ZipFileInterface
|
||||
public function addFromStream($stream, $localName, $compressionMethod = null)
|
||||
{
|
||||
if (!is_resource($stream)) {
|
||||
throw new InvalidArgumentException("stream is not resource");
|
||||
throw new InvalidArgumentException("Stream is not resource");
|
||||
}
|
||||
$localName = (string)$localName;
|
||||
if (empty($localName)) {
|
||||
throw new InvalidArgumentException("Incorrect entry name " . $localName);
|
||||
if ($localName === null) {
|
||||
throw new InvalidArgumentException("Entry name is null");
|
||||
}
|
||||
$localName = ltrim((string)$localName, "\\/");
|
||||
if (strlen($localName) === 0) {
|
||||
throw new InvalidArgumentException("Empty entry name");
|
||||
}
|
||||
$fstat = fstat($stream);
|
||||
$length = $fstat['size'];
|
||||
if (null === $compressionMethod) {
|
||||
if ($compressionMethod === null) {
|
||||
if ($length >= 512) {
|
||||
$compressionMethod = ZipEntry::UNKNOWN;
|
||||
} else {
|
||||
$compressionMethod = ZipFileInterface::METHOD_STORED;
|
||||
$compressionMethod = self::METHOD_STORED;
|
||||
}
|
||||
} elseif (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
|
||||
throw new ZipUnsupportMethod('Unsupported method ' . $compressionMethod);
|
||||
throw new ZipUnsupportMethodException('Unsupported method ' . $compressionMethod);
|
||||
}
|
||||
|
||||
$mode = sprintf('%o', $fstat['mode']);
|
||||
@@ -511,21 +514,24 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $dirName
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function addEmptyDir($dirName)
|
||||
{
|
||||
$dirName = (string)$dirName;
|
||||
if (strlen($dirName) === 0) {
|
||||
throw new InvalidArgumentException("DirName empty");
|
||||
if ($dirName === null) {
|
||||
throw new InvalidArgumentException("Dir name is null");
|
||||
}
|
||||
$dirName = rtrim($dirName, '/') . '/';
|
||||
$dirName = ltrim((string)$dirName, "\\/");
|
||||
if (strlen($dirName) === 0) {
|
||||
throw new InvalidArgumentException("Empty dir name");
|
||||
}
|
||||
$dirName = rtrim($dirName, '\\/') . '/';
|
||||
$externalAttributes = 040755 << 16;
|
||||
|
||||
$entry = new ZipNewEntry();
|
||||
$entry->setName($dirName);
|
||||
$entry->setTime(time());
|
||||
$entry->setMethod(ZipFileInterface::METHOD_STORED);
|
||||
$entry->setMethod(self::METHOD_STORED);
|
||||
$entry->setSize(0);
|
||||
$entry->setCompressedSize(0);
|
||||
$entry->setCrc(0);
|
||||
@@ -544,16 +550,19 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function addDir($inputDir, $localPath = "/", $compressionMethod = null)
|
||||
{
|
||||
if ($inputDir === null) {
|
||||
throw new InvalidArgumentException('Input dir is null');
|
||||
}
|
||||
$inputDir = (string)$inputDir;
|
||||
if (null === $inputDir || strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('Input dir empty');
|
||||
if (strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('The input directory is not specified');
|
||||
}
|
||||
if (!is_dir($inputDir)) {
|
||||
throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists');
|
||||
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
|
||||
}
|
||||
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
|
||||
|
||||
@@ -570,20 +579,22 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipException
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
*/
|
||||
public function addDirRecursive($inputDir, $localPath = "/", $compressionMethod = null)
|
||||
{
|
||||
if ($inputDir === null) {
|
||||
throw new InvalidArgumentException('Input dir is null');
|
||||
}
|
||||
$inputDir = (string)$inputDir;
|
||||
if (null === $inputDir || strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('Input dir empty');
|
||||
if (strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('The input directory is not specified');
|
||||
}
|
||||
if (!is_dir($inputDir)) {
|
||||
throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists');
|
||||
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
|
||||
}
|
||||
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
|
||||
|
||||
@@ -600,8 +611,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipException
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -612,8 +622,8 @@ class ZipFile implements ZipFileInterface
|
||||
$compressionMethod = null
|
||||
) {
|
||||
$localPath = (string)$localPath;
|
||||
if (null !== $localPath && 0 !== strlen($localPath)) {
|
||||
$localPath = rtrim($localPath, '/');
|
||||
if (strlen($localPath) !== 0) {
|
||||
$localPath = trim($localPath, '\\/');
|
||||
} else {
|
||||
$localPath = "";
|
||||
}
|
||||
@@ -628,10 +638,10 @@ class ZipFile implements ZipFileInterface
|
||||
$files = [];
|
||||
foreach ($iterator as $file) {
|
||||
if ($file instanceof \SplFileInfo) {
|
||||
if ('..' === $file->getBasename()) {
|
||||
if ($file->getBasename() === '..') {
|
||||
continue;
|
||||
}
|
||||
if ('.' === $file->getBasename()) {
|
||||
if ($file->getBasename() === '.') {
|
||||
$files[] = dirname($file->getPathname());
|
||||
} else {
|
||||
$files[] = $file->getPathname();
|
||||
@@ -646,9 +656,9 @@ class ZipFile implements ZipFileInterface
|
||||
$path = array_shift($files);
|
||||
foreach ($files as $file) {
|
||||
$relativePath = str_replace($path, $localPath, $file);
|
||||
$relativePath = ltrim($relativePath, '/');
|
||||
if (is_dir($file)) {
|
||||
FilesUtil::isEmptyDir($file) && $this->addEmptyDir($relativePath);
|
||||
$relativePath = ltrim($relativePath, '\\/');
|
||||
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
|
||||
$this->addEmptyDir($relativePath);
|
||||
} elseif (is_file($file)) {
|
||||
$this->addFile($file, $relativePath, $compressionMethod);
|
||||
}
|
||||
@@ -666,7 +676,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function addFilesFromGlob($inputDir, $globPattern, $localPath = '/', $compressionMethod = null)
|
||||
@@ -685,7 +695,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
private function addGlob(
|
||||
@@ -695,27 +705,30 @@ class ZipFile implements ZipFileInterface
|
||||
$recursive = true,
|
||||
$compressionMethod = null
|
||||
) {
|
||||
if ($inputDir === null) {
|
||||
throw new InvalidArgumentException('Input dir is null');
|
||||
}
|
||||
$inputDir = (string)$inputDir;
|
||||
if (null === $inputDir || 0 === strlen($inputDir)) {
|
||||
throw new InvalidArgumentException('Input dir empty');
|
||||
if (strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('The input directory is not specified');
|
||||
}
|
||||
if (!is_dir($inputDir)) {
|
||||
throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists');
|
||||
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
|
||||
}
|
||||
$globPattern = (string)$globPattern;
|
||||
if (empty($globPattern)) {
|
||||
throw new InvalidArgumentException("glob pattern empty");
|
||||
throw new InvalidArgumentException('The glob pattern is not specified');
|
||||
}
|
||||
|
||||
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
|
||||
$globPattern = $inputDir . $globPattern;
|
||||
|
||||
$filesFound = FilesUtil::globFileSearch($globPattern, GLOB_BRACE, $recursive);
|
||||
if (false === $filesFound || empty($filesFound)) {
|
||||
if ($filesFound === false || empty($filesFound)) {
|
||||
return $this;
|
||||
}
|
||||
if (!empty($localPath) && is_string($localPath)) {
|
||||
$localPath = rtrim($localPath, '/') . '/';
|
||||
$localPath = trim($localPath, '/\\') . '/';
|
||||
} else {
|
||||
$localPath = "/";
|
||||
}
|
||||
@@ -725,9 +738,9 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
foreach ($filesFound as $file) {
|
||||
$filename = str_replace($inputDir, $localPath, $file);
|
||||
$filename = ltrim($filename, '/');
|
||||
if (is_dir($file)) {
|
||||
FilesUtil::isEmptyDir($file) && $this->addEmptyDir($filename);
|
||||
$filename = ltrim($filename, '\\/');
|
||||
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
|
||||
$this->addEmptyDir($filename);
|
||||
} elseif (is_file($file)) {
|
||||
$this->addFile($file, $filename, $compressionMethod);
|
||||
}
|
||||
@@ -745,7 +758,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function addFilesFromGlobRecursive($inputDir, $globPattern, $localPath = '/', $compressionMethod = null)
|
||||
@@ -763,6 +776,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipException
|
||||
* @internal param bool $recursive Recursive search.
|
||||
*/
|
||||
public function addFilesFromRegex($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null)
|
||||
@@ -781,7 +795,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
private function addRegex(
|
||||
$inputDir,
|
||||
@@ -792,23 +806,23 @@ class ZipFile implements ZipFileInterface
|
||||
) {
|
||||
$regexPattern = (string)$regexPattern;
|
||||
if (empty($regexPattern)) {
|
||||
throw new InvalidArgumentException("regex pattern empty");
|
||||
throw new InvalidArgumentException('The regex pattern is not specified');
|
||||
}
|
||||
$inputDir = (string)$inputDir;
|
||||
if (null === $inputDir || 0 === strlen($inputDir)) {
|
||||
throw new InvalidArgumentException('Input dir empty');
|
||||
if (strlen($inputDir) === 0) {
|
||||
throw new InvalidArgumentException('The input directory is not specified');
|
||||
}
|
||||
if (!is_dir($inputDir)) {
|
||||
throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists');
|
||||
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
|
||||
}
|
||||
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
|
||||
|
||||
$files = FilesUtil::regexFileSearch($inputDir, $regexPattern, $recursive);
|
||||
if (false === $files || empty($files)) {
|
||||
if (empty($files)) {
|
||||
return $this;
|
||||
}
|
||||
if (!empty($localPath) && is_string($localPath)) {
|
||||
$localPath = rtrim($localPath, '/') . '/';
|
||||
$localPath = trim($localPath, '\\/') . '/';
|
||||
} else {
|
||||
$localPath = "/";
|
||||
}
|
||||
@@ -819,9 +833,9 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
foreach ($files as $file) {
|
||||
$filename = str_replace($inputDir, $localPath, $file);
|
||||
$filename = ltrim($filename, '/');
|
||||
if (is_dir($file)) {
|
||||
FilesUtil::isEmptyDir($file) && $this->addEmptyDir($filename);
|
||||
$filename = ltrim($filename, '\\/');
|
||||
if (is_dir($file) && FilesUtil::isEmptyDir($file)) {
|
||||
$this->addEmptyDir($filename);
|
||||
} elseif (is_file($file)) {
|
||||
$this->addFile($file, $filename, $compressionMethod);
|
||||
}
|
||||
@@ -839,6 +853,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipException
|
||||
* @internal param bool $recursive Recursive search.
|
||||
*/
|
||||
public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null)
|
||||
@@ -866,14 +881,15 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string $oldName Old entry name.
|
||||
* @param string $newName New entry name.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function rename($oldName, $newName)
|
||||
{
|
||||
if (null === $oldName || null === $newName) {
|
||||
if ($oldName === null || $newName === null) {
|
||||
throw new InvalidArgumentException("name is null");
|
||||
}
|
||||
$oldName = ltrim((string)$oldName, '\\/');
|
||||
$newName = ltrim((string)$newName, '\\/');
|
||||
if ($oldName !== $newName) {
|
||||
$this->zipModel->renameEntry($oldName, $newName);
|
||||
}
|
||||
@@ -885,13 +901,13 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $entryName Zip Entry name.
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipNotFoundEntry If entry not found.
|
||||
* @throws ZipEntryNotFoundException If entry not found.
|
||||
*/
|
||||
public function deleteFromName($entryName)
|
||||
{
|
||||
$entryName = (string)$entryName;
|
||||
$entryName = ltrim((string)$entryName, '\\/');
|
||||
if (!$this->zipModel->deleteEntry($entryName)) {
|
||||
throw new ZipNotFoundEntry("Entry " . $entryName . ' not found!');
|
||||
throw new ZipEntryNotFoundException($entryName);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
@@ -901,13 +917,12 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $globPattern Glob pattern
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function deleteFromGlob($globPattern)
|
||||
{
|
||||
if (null === $globPattern || !is_string($globPattern) || empty($globPattern)) {
|
||||
throw new InvalidArgumentException("Glob pattern is empty");
|
||||
if ($globPattern === null || !is_string($globPattern) || empty($globPattern)) {
|
||||
throw new InvalidArgumentException("The glob pattern is not specified");
|
||||
}
|
||||
$globPattern = '~' . FilesUtil::convertGlobToRegEx($globPattern) . '~si';
|
||||
$this->deleteFromRegex($globPattern);
|
||||
@@ -919,12 +934,11 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $regexPattern Regex pattern
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function deleteFromRegex($regexPattern)
|
||||
{
|
||||
if (null === $regexPattern || !is_string($regexPattern) || empty($regexPattern)) {
|
||||
throw new InvalidArgumentException("Regex pattern is empty.");
|
||||
if ($regexPattern === null || !is_string($regexPattern) || empty($regexPattern)) {
|
||||
throw new InvalidArgumentException("The regex pattern is not specified");
|
||||
}
|
||||
$this->matcher()->match($regexPattern)->delete();
|
||||
return $this;
|
||||
@@ -945,19 +959,18 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param int $compressionLevel
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
|
||||
* @see ZipFileInterface::LEVEL_SUPER_FAST
|
||||
* @see ZipFileInterface::LEVEL_FAST
|
||||
* @see ZipFileInterface::LEVEL_BEST_COMPRESSION
|
||||
*/
|
||||
public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
|
||||
public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION)
|
||||
{
|
||||
if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
|
||||
$compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
|
||||
if ($compressionLevel < self::LEVEL_DEFAULT_COMPRESSION ||
|
||||
$compressionLevel > self::LEVEL_BEST_COMPRESSION
|
||||
) {
|
||||
throw new InvalidArgumentException('Invalid compression level. Minimum level ' .
|
||||
ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION);
|
||||
self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION);
|
||||
}
|
||||
$this->matcher()->all()->invoke(function ($entry) use ($compressionLevel) {
|
||||
$this->setCompressionLevelEntry($entry, $compressionLevel);
|
||||
@@ -977,15 +990,15 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
public function setCompressionLevelEntry($entryName, $compressionLevel)
|
||||
{
|
||||
if (null !== $compressionLevel) {
|
||||
if ($compressionLevel !== null) {
|
||||
if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
|
||||
$compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
|
||||
) {
|
||||
throw new InvalidArgumentException('Invalid compression level. Minimum level ' .
|
||||
ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION);
|
||||
self::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . self::LEVEL_BEST_COMPRESSION);
|
||||
}
|
||||
$entry = $this->zipModel->getEntry($entryName);
|
||||
if ($entry->getCompressionLevel() !== $compressionLevel) {
|
||||
if ($compressionLevel !== $entry->getCompressionLevel()) {
|
||||
$entry = $this->zipModel->getEntryForChanges($entry);
|
||||
$entry->setCompressionLevel($compressionLevel);
|
||||
}
|
||||
@@ -1005,10 +1018,10 @@ class ZipFile implements ZipFileInterface
|
||||
public function setCompressionMethodEntry($entryName, $compressionMethod)
|
||||
{
|
||||
if (!in_array($compressionMethod, self::$allowCompressionMethods, true)) {
|
||||
throw new ZipUnsupportMethod('Unsupported method ' . $compressionMethod);
|
||||
throw new ZipUnsupportMethodException('Unsupported method ' . $compressionMethod);
|
||||
}
|
||||
$entry = $this->zipModel->getEntry($entryName);
|
||||
if ($entry->getMethod() !== $compressionMethod) {
|
||||
if ($compressionMethod !== $entry->getMethod()) {
|
||||
$this->zipModel
|
||||
->getEntryForChanges($entry)
|
||||
->setMethod($compressionMethod);
|
||||
@@ -1034,6 +1047,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $password Password
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipException
|
||||
* @deprecated using ZipFileInterface::setReadPassword()
|
||||
*/
|
||||
public function withReadPassword($password)
|
||||
@@ -1046,6 +1060,7 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $password Password
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setReadPassword($password)
|
||||
{
|
||||
@@ -1059,6 +1074,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string $entryName
|
||||
* @param string $password Password
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setReadPasswordEntry($entryName, $password)
|
||||
{
|
||||
@@ -1073,6 +1089,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @param int|null $encryptionMethod Encryption method
|
||||
* @return ZipFileInterface
|
||||
* @deprecated using ZipFileInterface::setPassword()
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
|
||||
{
|
||||
@@ -1090,9 +1107,9 @@ class ZipFile implements ZipFileInterface
|
||||
public function setPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
|
||||
{
|
||||
$this->zipModel->setWritePassword($password);
|
||||
if (null !== $encryptionMethod) {
|
||||
if (!in_array($encryptionMethod, self::$allowEncryptionMethods)) {
|
||||
throw new ZipException('Invalid encryption method');
|
||||
if ($encryptionMethod !== null) {
|
||||
if (!in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
|
||||
throw new ZipException('Invalid encryption method "' . $encryptionMethod . '"');
|
||||
}
|
||||
$this->zipModel->setEncryptionMethod($encryptionMethod);
|
||||
}
|
||||
@@ -1110,9 +1127,9 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
public function setPasswordEntry($entryName, $password, $encryptionMethod = null)
|
||||
{
|
||||
if (null !== $encryptionMethod) {
|
||||
if (!in_array($encryptionMethod, self::$allowEncryptionMethods)) {
|
||||
throw new ZipException('Invalid encryption method');
|
||||
if ($encryptionMethod !== null) {
|
||||
if (!in_array($encryptionMethod, self::$allowEncryptionMethods, true)) {
|
||||
throw new ZipException('Invalid encryption method "' . $encryptionMethod . '"');
|
||||
}
|
||||
}
|
||||
$this->matcher()->add($entryName)->setPassword($password, $encryptionMethod);
|
||||
@@ -1187,7 +1204,6 @@ class ZipFile implements ZipFileInterface
|
||||
*
|
||||
* @param string $filename Output filename
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function saveAsFile($filename)
|
||||
@@ -1201,6 +1217,9 @@ class ZipFile implements ZipFileInterface
|
||||
$this->saveAsStream($handle);
|
||||
|
||||
if (!@rename($tempFilename, $filename)) {
|
||||
if (is_file($tempFilename)) {
|
||||
unlink($tempFilename);
|
||||
}
|
||||
throw new ZipException('Can not move ' . $tempFilename . ' to ' . $filename);
|
||||
}
|
||||
return $this;
|
||||
@@ -1231,7 +1250,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string $outputFilename Output filename
|
||||
* @param string|null $mimeType Mime-Type
|
||||
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true)
|
||||
{
|
||||
@@ -1270,7 +1289,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @param string|null $mimeType Mime-Type
|
||||
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||
* @return ResponseInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true)
|
||||
{
|
||||
@@ -1299,18 +1318,21 @@ class ZipFile implements ZipFileInterface
|
||||
}
|
||||
|
||||
$stream = new ResponseStream($handle);
|
||||
$response->withHeader('Content-Type', $mimeType);
|
||||
$response->withHeader('Content-Disposition', $contentDispositionValue);
|
||||
$response->withHeader('Content-Length', $stream->getSize());
|
||||
$response->withBody($stream);
|
||||
return $response;
|
||||
return $response
|
||||
->withHeader('Content-Type', $mimeType)
|
||||
->withHeader('Content-Disposition', $contentDispositionValue)
|
||||
->withHeader('Content-Length', $stream->getSize())
|
||||
->withBody($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $handle
|
||||
* @param resource $handle
|
||||
* @throws ZipException
|
||||
*/
|
||||
protected function writeZipToStream($handle)
|
||||
{
|
||||
$this->onBeforeSave();
|
||||
|
||||
$output = new ZipOutputStream($handle, $this->zipModel);
|
||||
$output->writeZip();
|
||||
}
|
||||
@@ -1318,7 +1340,7 @@ class ZipFile implements ZipFileInterface
|
||||
/**
|
||||
* Returns the zip archive as a string.
|
||||
* @return string
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function outputAsString()
|
||||
{
|
||||
@@ -1332,12 +1354,19 @@ class ZipFile implements ZipFileInterface
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event before save or output.
|
||||
*/
|
||||
protected function onBeforeSave()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Close zip archive and release input stream.
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if (null !== $this->inputStream) {
|
||||
if ($this->inputStream !== null) {
|
||||
$this->inputStream->close();
|
||||
$this->inputStream = null;
|
||||
$this->zipModel = new ZipModel();
|
||||
@@ -1351,22 +1380,22 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
public function rewrite()
|
||||
{
|
||||
if (null === $this->inputStream) {
|
||||
if ($this->inputStream === null) {
|
||||
throw new ZipException('input stream is null');
|
||||
}
|
||||
$meta = stream_get_meta_data($this->inputStream->getStream());
|
||||
$content = $this->outputAsString();
|
||||
$this->close();
|
||||
if ('plainfile' === $meta['wrapper_type']) {
|
||||
if ($meta['wrapper_type'] === 'plainfile') {
|
||||
/**
|
||||
* @var resource $uri
|
||||
*/
|
||||
$uri = $meta['uri'];
|
||||
if (file_put_contents($uri, $content) === false) {
|
||||
throw new ZipException("Can not overwrite the zip file in the {$uri} file.");
|
||||
throw new ZipException("Can not overwrite the zip file in the $uri file.");
|
||||
}
|
||||
if (!($handle = @fopen($uri, 'rb'))) {
|
||||
throw new ZipException("File {$uri} can't open.");
|
||||
throw new ZipException("File $uri can't open.");
|
||||
}
|
||||
return $this->openFromStream($handle);
|
||||
}
|
||||
@@ -1386,7 +1415,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetset.php
|
||||
* @param string $entryName The offset to assign the value to.
|
||||
* @param mixed $contents The value to set.
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
* @see ZipFile::addFromString
|
||||
* @see ZipFile::addEmptyDir
|
||||
* @see ZipFile::addFile
|
||||
@@ -1394,10 +1423,10 @@ class ZipFile implements ZipFileInterface
|
||||
*/
|
||||
public function offsetSet($entryName, $contents)
|
||||
{
|
||||
if (null === $entryName) {
|
||||
if ($entryName === null) {
|
||||
throw new InvalidArgumentException('entryName is null');
|
||||
}
|
||||
$entryName = (string)$entryName;
|
||||
$entryName = ltrim((string)$entryName, "\\/");
|
||||
if (strlen($entryName) === 0) {
|
||||
throw new InvalidArgumentException('entryName is empty');
|
||||
}
|
||||
@@ -1414,8 +1443,7 @@ class ZipFile implements ZipFileInterface
|
||||
} elseif (is_resource($contents)) {
|
||||
$this->addFromStream($contents, $entryName);
|
||||
} else {
|
||||
$contents = (string)$contents;
|
||||
$this->addFromString($entryName, $contents);
|
||||
$this->addFromString($entryName, (string)$contents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,7 +1451,7 @@ class ZipFile implements ZipFileInterface
|
||||
* Offset to unset
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
|
||||
* @param string $entryName The offset to unset.
|
||||
* @throws ZipUnsupportMethod
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function offsetUnset($entryName)
|
||||
{
|
||||
@@ -1435,6 +1463,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @link http://php.net/manual/en/iterator.current.php
|
||||
* @return mixed Can return any type.
|
||||
* @since 5.0.0
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
@@ -1446,7 +1475,7 @@ class ZipFile implements ZipFileInterface
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetget.php
|
||||
* @param string $entryName The offset to retrieve.
|
||||
* @return string|null
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function offsetGet($entryName)
|
||||
{
|
||||
|
@@ -2,10 +2,8 @@
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipEntryNotFoundException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Exception\ZipNotFoundEntry;
|
||||
use PhpZip\Exception\ZipUnsupportMethod;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\Model\ZipEntryMatcher;
|
||||
use PhpZip\Model\ZipInfo;
|
||||
@@ -87,7 +85,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $filename
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException if file doesn't exists.
|
||||
* @throws ZipException if can't open file.
|
||||
*/
|
||||
public function openFile($filename);
|
||||
@@ -97,7 +94,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $data
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException if data not available.
|
||||
* @throws ZipException if can't open temp stream.
|
||||
*/
|
||||
public function openFromString($data);
|
||||
@@ -107,8 +103,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param resource $handle
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException Invalid stream resource
|
||||
* or resource cannot seekable stream
|
||||
*/
|
||||
public function openFromStream($handle);
|
||||
|
||||
@@ -129,7 +123,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param null|string $comment
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException Length comment out of range
|
||||
*/
|
||||
public function setArchiveComment($comment = null);
|
||||
|
||||
@@ -140,7 +133,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $entryName
|
||||
* @return bool
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function isDirectory($entryName);
|
||||
|
||||
@@ -149,7 +142,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $entryName
|
||||
* @return string
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function getEntryComment($entryName);
|
||||
|
||||
@@ -159,7 +152,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* @param string $entryName
|
||||
* @param string|null $comment
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function setEntryComment($entryName, $comment = null);
|
||||
|
||||
@@ -184,7 +177,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string|ZipEntry $entryName
|
||||
* @return ZipInfo
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function getEntryInfo($entryName);
|
||||
|
||||
@@ -222,8 +215,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException If incorrect data or entry name.
|
||||
* @throws ZipUnsupportMethod
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -239,8 +230,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -256,8 +245,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -269,7 +256,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $dirName
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function addEmptyDir($dirName);
|
||||
|
||||
@@ -282,7 +268,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function addDir($inputDir, $localPath = "/", $compressionMethod = null);
|
||||
|
||||
@@ -295,8 +280,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -312,8 +295,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipUnsupportMethod
|
||||
* @see ZipFileInterface::METHOD_STORED
|
||||
* @see ZipFileInterface::METHOD_DEFLATED
|
||||
* @see ZipFileInterface::METHOD_BZIP2
|
||||
@@ -330,7 +311,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function addFilesFromGlob($inputDir, $globPattern, $localPath = '/', $compressionMethod = null);
|
||||
@@ -345,7 +325,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
|
||||
* If null, then auto choosing method.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function addFilesFromGlobRecursive($inputDir, $globPattern, $localPath = '/', $compressionMethod = null);
|
||||
@@ -393,8 +372,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* @param string $oldName Old entry name.
|
||||
* @param string $newName New entry name.
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipNotFoundEntry
|
||||
* @throws ZipEntryNotFoundException
|
||||
*/
|
||||
public function rename($oldName, $newName);
|
||||
|
||||
@@ -403,7 +381,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $entryName Zip Entry name.
|
||||
* @return ZipFileInterface
|
||||
* @throws ZipNotFoundEntry If entry not found.
|
||||
* @throws ZipEntryNotFoundException If entry not found.
|
||||
*/
|
||||
public function deleteFromName($entryName);
|
||||
|
||||
@@ -412,7 +390,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $globPattern Glob pattern
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
|
||||
*/
|
||||
public function deleteFromGlob($globPattern);
|
||||
@@ -422,7 +399,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $regexPattern Regex pattern
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function deleteFromRegex($regexPattern);
|
||||
|
||||
@@ -576,7 +552,6 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
*
|
||||
* @param string $filename Output filename
|
||||
* @return ZipFileInterface
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function saveAsFile($filename);
|
||||
@@ -608,14 +583,12 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
||||
* @param string|null $mimeType Mime-Type
|
||||
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||
* @return ResponseInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true);
|
||||
|
||||
/**
|
||||
* Returns the zip archive as a string.
|
||||
* @return string
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function outputAsString();
|
||||
|
||||
|
104
tests/PhpZip/Issue24Test.php
Normal file
104
tests/PhpZip/Issue24Test.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Util\CryptoUtil;
|
||||
|
||||
class Issue24Test extends ZipTestCase
|
||||
{
|
||||
/**
|
||||
* This method is called before the first test of this test class is run.
|
||||
*/
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
stream_wrapper_register("dummyfs", DummyFileSystemStream::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testDummyFS()
|
||||
{
|
||||
$fileContents = str_repeat(base64_encode(CryptoUtil::randomBytes(12000)), 100);
|
||||
|
||||
// create zip file
|
||||
$zip = new ZipFile();
|
||||
$zip->addFromString(
|
||||
'file.txt',
|
||||
$fileContents,
|
||||
ZipFile::METHOD_DEFLATED
|
||||
);
|
||||
$zip->saveAsFile($this->outputFilename);
|
||||
$zip->close();
|
||||
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$stream = fopen('dummyfs://localhost/' . $this->outputFilename, 'rb');
|
||||
$this->assertNotFalse($stream);
|
||||
$zip->openFromStream($stream);
|
||||
$this->assertEquals($zip->getListFiles(), ['file.txt']);
|
||||
$this->assertEquals($zip['file.txt'], $fileContents);
|
||||
$zip->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load using dummy stream
|
||||
*/
|
||||
class DummyFileSystemStream
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $fp;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_open($path, $mode, $options)" . PHP_EOL;
|
||||
|
||||
$parsedUrl = parse_url($path);
|
||||
$path = $parsedUrl['path'];
|
||||
$this->fp = fopen($path, $mode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_read($count)" . PHP_EOL;
|
||||
$position = ftell($this->fp);
|
||||
|
||||
// echo "Loading chunk " . $position . " to " . ($position + $count - 1) . PHP_EOL;
|
||||
$ret = fread($this->fp, $count);
|
||||
|
||||
// echo "String length: " . strlen($ret) . PHP_EOL;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_tell()" . PHP_EOL;
|
||||
return ftell($this->fp);
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_eof()" . PHP_EOL;
|
||||
$isfeof = feof($this->fp);
|
||||
return $isfeof;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_seek($offset, $whence)" . PHP_EOL;
|
||||
fseek($this->fp, $offset, $whence);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
// echo "DummyFileSystemStream->stream_stat()" . PHP_EOL;
|
||||
return fstat($this->fp);
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipAuthenticationException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
/**
|
||||
* Some tests from the official extension of php-zip.
|
||||
@@ -12,6 +12,7 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
/**
|
||||
* Bug #7214 (zip_entry_read() binary safe)
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug7214.phpt
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBinaryNull()
|
||||
{
|
||||
@@ -21,16 +22,17 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
$zipFile->openFile($filename);
|
||||
foreach ($zipFile as $name => $contents) {
|
||||
$info = $zipFile->getEntryInfo($name);
|
||||
self::assertEquals(strlen($contents), $info->getSize());
|
||||
$this->assertEquals(strlen($contents), $info->getSize());
|
||||
}
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($filename);
|
||||
$this->assertCorrectZipArchive($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug #8009 (cannot add again same entry to an archive)
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug8009.phpt
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBug8009()
|
||||
{
|
||||
@@ -42,13 +44,13 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertCount(2, $zipFile);
|
||||
self::assertTrue(isset($zipFile['1.txt']));
|
||||
self::assertTrue(isset($zipFile['2.txt']));
|
||||
self::assertEquals($zipFile['2.txt'], $zipFile['1.txt']);
|
||||
$this->assertCount(2, $zipFile);
|
||||
$this->assertTrue(isset($zipFile['1.txt']));
|
||||
$this->assertTrue(isset($zipFile['2.txt']));
|
||||
$this->assertEquals($zipFile['2.txt'], $zipFile['1.txt']);
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
@@ -58,24 +60,24 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug40228-mb.phpt
|
||||
* @dataProvider provideBug40228
|
||||
* @param string $filename
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBug40228($filename)
|
||||
{
|
||||
self::assertTrue(mkdir($this->outputDirname, 0755, true));
|
||||
$this->assertTrue(mkdir($this->outputDirname, 0755, true));
|
||||
|
||||
$zipFile = new ZipFile();
|
||||
$zipFile->openFile($filename);
|
||||
$zipFile->extractTo($this->outputDirname);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertTrue(is_dir($this->outputDirname . '/test/empty'));
|
||||
$this->assertTrue(is_dir($this->outputDirname . '/test/empty'));
|
||||
}
|
||||
|
||||
public function provideBug40228()
|
||||
{
|
||||
return [
|
||||
[__DIR__ . '/php-zip-ext-test-resources/bug40228.zip'],
|
||||
[__DIR__ . '/php-zip-ext-test-resources/bug40228私はガラスを食べられます.zip'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -84,6 +86,7 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug49072.phpt
|
||||
* @expectedException \PhpZip\Exception\Crc32Exception
|
||||
* @expectedExceptionMessage file1
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBug49072()
|
||||
{
|
||||
@@ -98,22 +101,23 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
* Bug #70752 (Depacking with wrong password leaves 0 length files)
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug70752.phpt
|
||||
* @expectedException \PhpZip\Exception\ZipAuthenticationException
|
||||
* @expectedExceptionMessage Bad password for entry bug70752.txt
|
||||
* @expectedExceptionMessage nvalid password for zip entry "bug70752.txt"
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBug70752()
|
||||
{
|
||||
$filename = __DIR__ . '/php-zip-ext-test-resources/bug70752.zip';
|
||||
|
||||
self::assertTrue(mkdir($this->outputDirname, 0755, true));
|
||||
$this->assertTrue(mkdir($this->outputDirname, 0755, true));
|
||||
|
||||
$zipFile = new ZipFile();
|
||||
try {
|
||||
$zipFile->openFile($filename);
|
||||
$zipFile->setReadPassword('bar');
|
||||
$zipFile->extractTo($this->outputDirname);
|
||||
self::markTestIncomplete('failed test');
|
||||
} catch (ZipAuthenticationException $exception) {
|
||||
self::assertFalse(file_exists($this->outputDirname . '/bug70752.txt'));
|
||||
$this->markTestIncomplete('failed test');
|
||||
} catch (ZipException $exception) {
|
||||
$this->assertFalse(file_exists($this->outputDirname . '/bug70752.txt'));
|
||||
$zipFile->close();
|
||||
throw $exception;
|
||||
}
|
||||
@@ -122,6 +126,7 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
/**
|
||||
* Bug #12414 ( extracting files from damaged archives)
|
||||
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/pecl12414.phpt
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testPecl12414()
|
||||
{
|
||||
@@ -133,10 +138,10 @@ class PhpZipExtResourceTest extends ZipTestCase
|
||||
$zipFile->openFile($filename);
|
||||
|
||||
$info = $zipFile->getEntryInfo($entryName);
|
||||
self::assertTrue($info->getSize() > 0);
|
||||
$this->assertTrue($info->getSize() > 0);
|
||||
|
||||
$contents = $zipFile[$entryName];
|
||||
self::assertEquals(strlen($contents), $info->getSize());
|
||||
$this->assertEquals(strlen($contents), $info->getSize());
|
||||
|
||||
$zipFile->close();
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Util\CryptoUtil;
|
||||
|
||||
/**
|
||||
@@ -9,14 +10,17 @@ use PhpZip\Util\CryptoUtil;
|
||||
*/
|
||||
class ZipAlignTest extends ZipTestCase
|
||||
{
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testApkAlignedAndSetZipAlignAndReSave()
|
||||
{
|
||||
$filename = __DIR__ . '/resources/test.apk';
|
||||
|
||||
self::assertCorrectZipArchive($filename);
|
||||
$result = self::doZipAlignVerify($filename);
|
||||
$this->assertCorrectZipArchive($filename);
|
||||
$result = $this->assertVerifyZipAlign($filename);
|
||||
if (null !== $result) {
|
||||
self::assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
$zipFile = new ZipFile();
|
||||
@@ -25,15 +29,16 @@ class ZipAlignTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$result = self::doZipAlignVerify($this->outputFilename, true);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename, true);
|
||||
if (null !== $result) {
|
||||
self::assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test zip alignment.
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testZipAlignSourceZip()
|
||||
{
|
||||
@@ -48,30 +53,33 @@ class ZipAlignTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$result = self::doZipAlignVerify($this->outputFilename);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename);
|
||||
if ($result === null) {
|
||||
return;
|
||||
} // zip align not installed
|
||||
|
||||
// check not zip align
|
||||
self::assertFalse($result);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
$zipFile->setZipAlign(4);
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$result = self::doZipAlignVerify($this->outputFilename, true);
|
||||
self::assertNotNull($result);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename, true);
|
||||
$this->assertNotNull($result);
|
||||
|
||||
// check zip align
|
||||
self::assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testZipAlignNewFiles()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
@@ -86,16 +94,19 @@ class ZipAlignTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$result = self::doZipAlignVerify($this->outputFilename);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename);
|
||||
if ($result === null) {
|
||||
return;
|
||||
} // zip align not installed
|
||||
// check not zip align
|
||||
self::assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testZipAlignFromModifiedZipArchive()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
@@ -109,15 +120,15 @@ class ZipAlignTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$result = self::doZipAlignVerify($this->outputFilename);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename);
|
||||
if ($result === null) {
|
||||
return;
|
||||
} // zip align not installed
|
||||
|
||||
// check not zip align
|
||||
self::assertFalse($result);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
$zipFile->deleteFromRegex("~entry2[\d]+\.txt$~s");
|
||||
@@ -136,12 +147,12 @@ class ZipAlignTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$result = self::doZipAlignVerify($this->outputFilename, true);
|
||||
self::assertNotNull($result);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename, true);
|
||||
$this->assertNotNull($result);
|
||||
|
||||
// check zip align
|
||||
self::assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
47
tests/PhpZip/ZipEventTest.php
Normal file
47
tests/PhpZip/ZipEventTest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
class ZipFileExtended extends ZipFile
|
||||
{
|
||||
protected function onBeforeSave()
|
||||
{
|
||||
parent::onBeforeSave();
|
||||
$this->setZipAlign(4);
|
||||
$this->deleteFromRegex('~^META\-INF/~i');
|
||||
}
|
||||
}
|
||||
|
||||
class ZipEventTest extends ZipTestCase
|
||||
{
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testBeforeSave()
|
||||
{
|
||||
$zipFile = new ZipFileExtended();
|
||||
$zipFile->openFile(__DIR__ . '/resources/test.apk');
|
||||
$this->assertTrue(isset($zipFile['META-INF/MANIFEST.MF']));
|
||||
$this->assertTrue(isset($zipFile['META-INF/CERT.SF']));
|
||||
$this->assertTrue(isset($zipFile['META-INF/CERT.RSA']));
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$this->assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
|
||||
$this->assertFalse(isset($zipFile['META-INF/CERT.SF']));
|
||||
$this->assertFalse(isset($zipFile['META-INF/CERT.RSA']));
|
||||
$zipFile->close();
|
||||
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
$result = $this->assertVerifyZipAlign($this->outputFilename);
|
||||
if (null !== $result) {
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
$this->assertFalse(isset($zipFile['META-INF/MANIFEST.MF']));
|
||||
$this->assertFalse(isset($zipFile['META-INF/CERT.SF']));
|
||||
$this->assertFalse(isset($zipFile['META-INF/CERT.RSA']));
|
||||
$zipFile->close();
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Util\Iterator\IgnoreFilesFilterIterator;
|
||||
use PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator;
|
||||
|
||||
@@ -72,6 +73,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
self::assertEmpty($actualResultFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddDirWithLocalPath()
|
||||
{
|
||||
$localPath = 'to/path';
|
||||
@@ -81,10 +85,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -93,6 +97,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddDirWithoutLocalPath()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
@@ -100,10 +107,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -112,6 +119,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromIterator()
|
||||
{
|
||||
$localPath = 'to/project';
|
||||
@@ -123,10 +133,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -135,6 +145,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromIteratorEmptyLocalPath()
|
||||
{
|
||||
$localPath = '';
|
||||
@@ -146,10 +159,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -158,6 +171,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromRecursiveIterator()
|
||||
{
|
||||
$localPath = 'to/project';
|
||||
@@ -169,13 +185,16 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddRecursiveDirWithLocalPath()
|
||||
{
|
||||
$localPath = 'to/path';
|
||||
@@ -185,13 +204,16 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddRecursiveDirWithoutLocalPath()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
@@ -199,13 +221,16 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, array_keys(self::$files));
|
||||
$this->assertFilesResult($zipFile, array_keys(self::$files));
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromIteratorWithIgnoreFiles()
|
||||
{
|
||||
$localPath = 'to/project';
|
||||
@@ -222,16 +247,19 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
], $localPath);
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromRecursiveIteratorWithIgnoreFiles()
|
||||
{
|
||||
$localPath = 'to/project';
|
||||
@@ -250,10 +278,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
'empty dir/',
|
||||
@@ -268,6 +296,7 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
|
||||
/**
|
||||
* Create archive and add files from glob pattern
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromGlob()
|
||||
{
|
||||
@@ -278,10 +307,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
], $localPath);
|
||||
@@ -290,6 +319,7 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
|
||||
/**
|
||||
* Create archive and add recursively files from glob pattern
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromGlobRecursive()
|
||||
{
|
||||
@@ -300,10 +330,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
'category/list.txt',
|
||||
@@ -317,6 +347,7 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
|
||||
/**
|
||||
* Create archive and add files from regex pattern
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromRegex()
|
||||
{
|
||||
@@ -327,10 +358,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
], $localPath);
|
||||
@@ -339,6 +370,7 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
|
||||
/**
|
||||
* Create archive and add files recursively from regex pattern
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testAddFilesFromRegexRecursive()
|
||||
{
|
||||
@@ -349,10 +381,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, [
|
||||
$this->assertFilesResult($zipFile, [
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
'category/list.txt',
|
||||
@@ -364,6 +396,9 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testArrayAccessAddDir()
|
||||
{
|
||||
$localPath = 'path/to';
|
||||
@@ -374,10 +409,10 @@ class ZipFileAddDirTest extends ZipTestCase
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$this->assertFilesResult($zipFile, array_keys(self::$files), $localPath);
|
||||
$zipFile->close();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
$matcher = $zipFile->matcher();
|
||||
self::assertInstanceOf(ZipEntryMatcher::class, $matcher);
|
||||
$this->assertInstanceOf(ZipEntryMatcher::class, $matcher);
|
||||
|
||||
$this->assertTrue(is_array($matcher->getMatches()));
|
||||
$this->assertCount(0, $matcher);
|
||||
@@ -40,7 +40,7 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$matcher->setPassword('qwerty');
|
||||
$info = $zipFile->getAllInfo();
|
||||
array_walk($info, function (ZipInfo $zipInfo) use ($actualMatches) {
|
||||
self::assertEquals($zipInfo->isEncrypted(), in_array($zipInfo->getName(), $actualMatches));
|
||||
$this->assertEquals($zipInfo->isEncrypted(), in_array($zipInfo->getName(), $actualMatches));
|
||||
});
|
||||
|
||||
$matcher->all();
|
||||
@@ -86,12 +86,12 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
];
|
||||
|
||||
foreach ($renameEntriesArray as $name) {
|
||||
self::assertTrue(isset($zipFile[$name]));
|
||||
$this->assertTrue(isset($zipFile[$name]));
|
||||
}
|
||||
|
||||
$matcher = $zipFile->matcher();
|
||||
$matcher->match('~^file_(1|5)\d+~');
|
||||
self::assertEquals($matcher->getMatches(), $renameEntriesArray);
|
||||
$this->assertEquals($matcher->getMatches(), $renameEntriesArray);
|
||||
|
||||
$matcher->invoke(function ($entryName) use ($zipFile) {
|
||||
$newName = preg_replace('~\.(jpe?g)$~i', '.no_optimize.$1', $entryName);
|
||||
@@ -99,11 +99,11 @@ class ZipMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
});
|
||||
|
||||
foreach ($renameEntriesArray as $name) {
|
||||
self::assertFalse(isset($zipFile[$name]));
|
||||
$this->assertFalse(isset($zipFile[$name]));
|
||||
|
||||
$pathInfo = pathinfo($name);
|
||||
$newName = $pathInfo['filename'].'.no_optimize.'.$pathInfo['extension'];
|
||||
self::assertTrue(isset($zipFile[$newName]));
|
||||
$this->assertTrue(isset($zipFile[$newName]));
|
||||
}
|
||||
|
||||
$zipFile->close();
|
||||
|
@@ -3,6 +3,8 @@
|
||||
namespace PhpZip;
|
||||
|
||||
use PhpZip\Exception\ZipAuthenticationException;
|
||||
use PhpZip\Exception\ZipEntryNotFoundException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\ZipInfo;
|
||||
use PhpZip\Util\CryptoUtil;
|
||||
|
||||
@@ -13,6 +15,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
{
|
||||
/**
|
||||
* Test archive password.
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testSetPassword()
|
||||
{
|
||||
@@ -30,7 +33,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, $password);
|
||||
$this->assertCorrectZipArchive($this->outputFilename, $password);
|
||||
|
||||
// check bad password for ZipCrypto
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
@@ -38,20 +41,20 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
foreach ($zipFile->getListFiles() as $entryName) {
|
||||
try {
|
||||
$zipFile[$entryName];
|
||||
self::fail("Expected Exception has not been raised.");
|
||||
$this->fail("Expected Exception has not been raised.");
|
||||
} catch (ZipAuthenticationException $ae) {
|
||||
self::assertNotNull($ae);
|
||||
$this->assertContains('Invalid password for zip entry', $ae->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// check correct password for ZipCrypto
|
||||
$zipFile->setReadPassword($password);
|
||||
foreach ($zipFile->getAllInfo() as $info) {
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('ZipCrypto', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('ZipCrypto', $info->getMethodName());
|
||||
$decryptContent = $zipFile[$info->getName()];
|
||||
self::assertNotEmpty($decryptContent);
|
||||
self::assertContains('<?php', $decryptContent);
|
||||
$this->assertNotEmpty($decryptContent);
|
||||
$this->assertContains('<?php', $decryptContent);
|
||||
}
|
||||
|
||||
// change encryption method to WinZip Aes and update file
|
||||
@@ -59,7 +62,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, $password);
|
||||
$this->assertCorrectZipArchive($this->outputFilename, $password);
|
||||
|
||||
// check from WinZip AES encryption
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
@@ -68,20 +71,20 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
foreach ($zipFile->getListFiles() as $entryName) {
|
||||
try {
|
||||
$zipFile[$entryName];
|
||||
self::fail("Expected Exception has not been raised.");
|
||||
$this->fail("Expected Exception has not been raised.");
|
||||
} catch (ZipAuthenticationException $ae) {
|
||||
self::assertNotNull($ae);
|
||||
$this->assertNotNull($ae);
|
||||
}
|
||||
}
|
||||
|
||||
// set correct password WinZip AES
|
||||
$zipFile->setReadPassword($password);
|
||||
foreach ($zipFile->getAllInfo() as $info) {
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('WinZip', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('WinZip', $info->getMethodName());
|
||||
$decryptContent = $zipFile[$info->getName()];
|
||||
self::assertNotEmpty($decryptContent);
|
||||
self::assertContains('<?php', $decryptContent);
|
||||
$this->assertNotEmpty($decryptContent);
|
||||
$this->assertContains('<?php', $decryptContent);
|
||||
}
|
||||
|
||||
// clear password
|
||||
@@ -91,16 +94,19 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename);
|
||||
$this->assertCorrectZipArchive($this->outputFilename);
|
||||
|
||||
// check remove password
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
foreach ($zipFile->getAllInfo() as $info) {
|
||||
self::assertFalse($info->isEncrypted());
|
||||
$this->assertFalse($info->isEncrypted());
|
||||
}
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testTraditionalEncryption()
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
@@ -115,15 +121,15 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zip->saveAsFile($this->outputFilename);
|
||||
$zip->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, $password);
|
||||
$this->assertCorrectZipArchive($this->outputFilename, $password);
|
||||
|
||||
$zip->openFile($this->outputFilename);
|
||||
$zip->setReadPassword($password);
|
||||
self::assertFilesResult($zip, array_keys(self::$files));
|
||||
$this->assertFilesResult($zip, array_keys(self::$files));
|
||||
foreach ($zip->getAllInfo() as $info) {
|
||||
if (!$info->isFolder()) {
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('ZipCrypto', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('ZipCrypto', $info->getMethodName());
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
@@ -133,6 +139,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
* @dataProvider winZipKeyStrengthProvider
|
||||
* @param int $encryptionMethod
|
||||
* @param int $bitSize
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testWinZipAesEncryption($encryptionMethod, $bitSize)
|
||||
{
|
||||
@@ -144,16 +151,16 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zip->saveAsFile($this->outputFilename);
|
||||
$zip->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, $password);
|
||||
$this->assertCorrectZipArchive($this->outputFilename, $password);
|
||||
|
||||
$zip->openFile($this->outputFilename);
|
||||
$zip->setReadPassword($password);
|
||||
self::assertFilesResult($zip, array_keys(self::$files));
|
||||
$this->assertFilesResult($zip, array_keys(self::$files));
|
||||
foreach ($zip->getAllInfo() as $info) {
|
||||
if (!$info->isFolder()) {
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertEquals($info->getEncryptionMethod(), $encryptionMethod);
|
||||
self::assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertEquals($info->getEncryptionMethod(), $encryptionMethod);
|
||||
$this->assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
@@ -172,6 +179,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testEncryptionEntries()
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
@@ -191,7 +202,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zip->openFile($this->outputFilename);
|
||||
$zip->setReadPasswordEntry('.hidden', $password1);
|
||||
$zip->setReadPasswordEntry('text file.txt', $password2);
|
||||
self::assertFilesResult($zip, [
|
||||
$this->assertFilesResult($zip, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -199,19 +210,23 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
]);
|
||||
|
||||
$info = $zip->getEntryInfo('.hidden');
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('ZipCrypto', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('ZipCrypto', $info->getMethodName());
|
||||
|
||||
$info = $zip->getEntryInfo('text file.txt');
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('WinZip AES', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('WinZip AES', $info->getMethodName());
|
||||
|
||||
self::assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
|
||||
self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
||||
$this->assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
|
||||
$this->assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testEncryptionEntriesWithDefaultPassword()
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
@@ -234,7 +249,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zip->setReadPassword($defaultPassword);
|
||||
$zip->setReadPasswordEntry('.hidden', $password1);
|
||||
$zip->setReadPasswordEntry('text file.txt', $password2);
|
||||
self::assertFilesResult($zip, [
|
||||
$this->assertFilesResult($zip, [
|
||||
'.hidden',
|
||||
'text file.txt',
|
||||
'Текстовый документ.txt',
|
||||
@@ -242,18 +257,18 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
]);
|
||||
|
||||
$info = $zip->getEntryInfo('.hidden');
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('ZipCrypto', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('ZipCrypto', $info->getMethodName());
|
||||
|
||||
$info = $zip->getEntryInfo('text file.txt');
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('WinZip AES', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('WinZip AES', $info->getMethodName());
|
||||
|
||||
$info = $zip->getEntryInfo('Текстовый документ.txt');
|
||||
self::assertTrue($info->isEncrypted());
|
||||
self::assertContains('WinZip AES', $info->getMethodName());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
$this->assertContains('WinZip AES', $info->getMethodName());
|
||||
|
||||
self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
||||
$this->assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
@@ -271,28 +286,32 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->outputAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testEntryPassword()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
$zipFile->setPassword('pass');
|
||||
$zipFile['file'] = 'content';
|
||||
self::assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
|
||||
$this->assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
$zipFile['file' . $i] = 'content';
|
||||
if ($i < 6) {
|
||||
$zipFile->setPasswordEntry('file' . $i, 'pass');
|
||||
self::assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
||||
$this->assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
||||
} else {
|
||||
self::assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
||||
$this->assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
||||
}
|
||||
}
|
||||
$zipFile->disableEncryptionEntry('file3');
|
||||
self::assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
|
||||
self::asserttrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
||||
$this->assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
|
||||
$this->asserttrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
||||
$zipFile->disableEncryption();
|
||||
$infoList = $zipFile->getAllInfo();
|
||||
array_walk($infoList, function (ZipInfo $zipInfo) {
|
||||
self::assertFalse($zipInfo->isEncrypted());
|
||||
$this->assertFalse($zipInfo->isEncrypted());
|
||||
});
|
||||
$zipFile->close();
|
||||
}
|
||||
@@ -308,6 +327,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->setPasswordEntry('file', 'pass', 99);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testArchivePasswordUpdateWithoutSetReadPassword()
|
||||
{
|
||||
$zipFile = new ZipFile();
|
||||
@@ -318,31 +341,86 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
$zipFile->close();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, 'password');
|
||||
$this->assertCorrectZipArchive($this->outputFilename, 'password');
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
self::assertCount(3, $zipFile);
|
||||
$this->assertCount(3, $zipFile);
|
||||
foreach ($zipFile->getAllInfo() as $info) {
|
||||
self::assertTrue($info->isEncrypted());
|
||||
$this->assertTrue($info->isEncrypted());
|
||||
}
|
||||
unset($zipFile['file3']);
|
||||
$zipFile['file4'] = 'content';
|
||||
$zipFile->rewrite();
|
||||
|
||||
self::assertCorrectZipArchive($this->outputFilename, 'password');
|
||||
$this->assertCorrectZipArchive($this->outputFilename, 'password');
|
||||
|
||||
self::assertCount(3, $zipFile);
|
||||
self::assertFalse(isset($zipFile['file3']));
|
||||
self::assertTrue(isset($zipFile['file4']));
|
||||
self::assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
|
||||
self::assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
||||
self::assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
|
||||
self::assertEquals($zipFile['file4'], 'content');
|
||||
$this->assertCount(3, $zipFile);
|
||||
$this->assertFalse(isset($zipFile['file3']));
|
||||
$this->assertTrue(isset($zipFile['file4']));
|
||||
$this->assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
|
||||
$this->assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
||||
$this->assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
|
||||
$this->assertEquals($zipFile['file4'], 'content');
|
||||
|
||||
$zipFile->extractTo($this->outputDirname, ['file4']);
|
||||
|
||||
self::assertTrue(file_exists($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'));
|
||||
self::assertEquals(file_get_contents($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'), $zipFile['file4']);
|
||||
$this->assertTrue(file_exists($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'));
|
||||
$this->assertEquals(file_get_contents($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'), $zipFile['file4']);
|
||||
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/Ne-Lexa/php-zip/issues/9
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testIssues9()
|
||||
{
|
||||
$contents = str_pad('', 1000, 'test;test2;test3' . PHP_EOL, STR_PAD_RIGHT);
|
||||
$password = base64_encode(CryptoUtil::randomBytes(20));
|
||||
|
||||
$encryptMethod = ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256;
|
||||
$zipFile = new ZipFile();
|
||||
$zipFile
|
||||
->addFromString('codes.csv', $contents)
|
||||
->setPassword($password, $encryptMethod)
|
||||
->saveAsFile($this->outputFilename)
|
||||
->close();
|
||||
|
||||
$this->assertCorrectZipArchive($this->outputFilename, $password);
|
||||
|
||||
$zipFile->openFile($this->outputFilename);
|
||||
$zipFile->setReadPassword($password);
|
||||
$this->assertEquals($zipFile['codes.csv'], $contents);
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function testReadAesEncryptedAndRewriteArchive()
|
||||
{
|
||||
$file = __DIR__ . '/resources/aes_password_archive.zip';
|
||||
$password = '1234567890';
|
||||
|
||||
$zipFile = new ZipFile();
|
||||
$zipFile->openFile($file);
|
||||
$zipFile->setReadPassword($password);
|
||||
$zipFile->setEntryComment('contents.txt', 'comment'); // change entry, but not changed contents
|
||||
$zipFile->saveAsFile($this->outputFilename);
|
||||
|
||||
$zipFile2 = new ZipFile();
|
||||
$zipFile2->openFile($this->outputFilename);
|
||||
$zipFile2->setReadPassword($password);
|
||||
$this->assertEquals($zipFile2->getListFiles(), $zipFile->getListFiles());
|
||||
foreach ($zipFile as $name => $contents) {
|
||||
$this->assertNotEmpty($name);
|
||||
$this->assertNotEmpty($contents);
|
||||
$this->assertContains('test contents', $contents);
|
||||
$this->assertEquals($zipFile2[$name], $contents);
|
||||
}
|
||||
$zipFile2->close();
|
||||
|
||||
$zipFile->close();
|
||||
}
|
||||
|
@@ -79,7 +79,9 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$command = "7z t -p" . escapeshellarg($password) . " " . escapeshellarg($filename);
|
||||
exec($command, $output, $returnCode);
|
||||
|
||||
/**
|
||||
* @var array $output
|
||||
*/
|
||||
$output = implode(PHP_EOL, $output);
|
||||
|
||||
self::assertEquals($returnCode, 0);
|
||||
@@ -121,7 +123,7 @@ class ZipTestCase extends \PHPUnit_Framework_TestCase
|
||||
* @param bool $showErrors
|
||||
* @return bool|null If null - can not install zipalign
|
||||
*/
|
||||
public static function doZipAlignVerify($filename, $showErrors = false)
|
||||
public static function assertVerifyZipAlign($filename, $showErrors = false)
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR !== '\\' && `which zipalign`) {
|
||||
exec("zipalign -c -v 4 " . escapeshellarg($filename), $output, $returnCode);
|
||||
|
Binary file not shown.
BIN
tests/PhpZip/resources/aes_password_archive.zip
Normal file
BIN
tests/PhpZip/resources/aes_password_archive.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user