1
0
mirror of https://github.com/Ne-Lexa/php-zip.git synced 2025-08-24 07:52:48 +02:00

9 Commits
3.1.2 ... 3.1.5

Author SHA1 Message Date
Ne-Lexa
251ce11bdc Merge branch 'hotfix/3.1.5' 2018-04-25 12:44:11 +03:00
Ne-Lexa
f969e59319 Updated ZipFile::outputAsResponse() to conform to PSR standard 2018-04-25 12:43:37 +03:00
Frederik Buus Sauer
6808e4ffdc Lowered requirement to support PHP 5.5 2018-04-12 11:25:12 +02:00
Frederik Buus Sauer
91f08b9f55 Updated composer.json regarding unit tests, and corrected PSR implementation 2018-04-12 11:10:45 +02:00
Ne-Lexa
d0cf7f7d1d Merge branch 'hotfix/3.1.4' 2018-02-01 09:52:40 +03:00
Ne-Lexa
9f0d151f5e Fixed installing the package on the MAC (illegal byte sequence unzip).
close issue #11
2018-02-01 09:52:35 +03:00
Ne-Lexa
171d4a8e4c Merge branch 'hotfix/3.1.3' 2017-12-06 15:43:25 +03:00
Ne-Lexa
aa09b24d02 added an additional test of the encrypted archive 2017-12-06 15:28:17 +03:00
Ne-Lexa
c34f90ac18 fix bug issues #9 2017-12-06 15:09:50 +03:00
11 changed files with 137 additions and 122 deletions

View File

@@ -1,45 +1,47 @@
{
"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": {
"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"
},
"minimum-stability": "stable"
}

View File

@@ -255,11 +255,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();
}
/**
@@ -432,7 +429,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;
}
/**
@@ -446,17 +446,14 @@ abstract class ZipAbstractEntry implements ZipEntry
{
if (self::UNKNOWN === $method) {
$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:

View File

@@ -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*/
;

View File

@@ -224,7 +224,7 @@ class ZipModel implements \Countable
if (isset($this->outEntries[$entryName])) {
return $this->outEntries[$entryName];
}
throw new ZipNotFoundEntry('Zip entry ' . $entryName . ' not found');
throw new ZipNotFoundEntry('Zip entry "' . $entryName . '" not found');
}
/**

View File

@@ -223,7 +223,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 +232,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 && ZipEntry::METHOD_WINZIP_AES === $method) {
/**
* @var WinZipAesEntryExtraField $field
*/
$field = $extraFieldsCollection->get(WinZipAesEntryExtraField::getHeaderId());
if (null !== $field) {
$method = $field->getMethod();
}
}
@@ -337,14 +292,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 (20 <= $size && ZipFileInterface::METHOD_BZIP2 !== $method) {
$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,6 +339,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
* @param ZipEntry $entry
* @param string $content
* @return string
* @throws ZipException
*/
protected function determineBestCompressionMethod(ZipEntry $entry, $content)
{

View File

@@ -1299,11 +1299,11 @@ 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);
}
/**

View File

@@ -75,7 +75,6 @@ class PhpZipExtResourceTest extends ZipTestCase
{
return [
[__DIR__ . '/php-zip-ext-test-resources/bug40228.zip'],
[__DIR__ . '/php-zip-ext-test-resources/bug40228私はガラスを食べられます.zip'],
];
}

View File

@@ -7,6 +7,7 @@ use PhpZip\Model\ZipInfo;
use PhpZip\Util\CryptoUtil;
use PhpZip\Util\FilesUtil;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
/**
* ZipFile test
@@ -1672,7 +1673,7 @@ class ZipFileTest extends ZipTestCase
/**
* @expectedException \PhpZip\Exception\ZipNotFoundEntry
* @expectedExceptionMessage Zip entry bad entry name not found
* @expectedExceptionMessage Zip entry "bad entry name" not found
*/
public function testNotFoundEntry()
{
@@ -1786,9 +1787,10 @@ class ZipFileTest extends ZipTestCase
$zipFile[$i] = $i;
}
$filename = 'file.jar';
$response = $this->getMock(ResponseInterface::class);
$response = $zipFile->outputAsResponse($response, $filename);
$response = $zipFile->outputAsResponse(new Response(), $filename);
$this->assertInstanceOf(ResponseInterface::class, $response);
$this->assertEquals('application/java-archive', $response->getHeaderLine('content-type'));
$this->assertEquals('attachment; filename="file.jar"', $response->getHeaderLine('content-disposition'));
}
public function testCompressionLevel()

View File

@@ -346,4 +346,54 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile->close();
}
/**
* @see https://github.com/Ne-Lexa/php-zip/issues/9
*/
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();
}
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();
}
}

Binary file not shown.