mirror of
https://github.com/Ne-Lexa/php-zip.git
synced 2025-07-25 17:51:13 +02:00
fix bug issues #9
This commit is contained in:
@@ -255,11 +255,8 @@ abstract class ZipAbstractEntry implements ZipEntry
|
|||||||
*/
|
*/
|
||||||
public function isZip64ExtensionsRequired()
|
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()
|
return 0xffffffff <= $this->getCompressedSize()
|
||||||
|| 0xffffffff <= $this->getSize()
|
|| 0xffffffff <= $this->getSize();
|
||||||
|| 0xffffffff <= sprintf('%u', $this->getOffset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,7 +429,10 @@ abstract class ZipAbstractEntry implements ZipEntry
|
|||||||
*/
|
*/
|
||||||
public function getMethod()
|
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) {
|
if (self::UNKNOWN === $method) {
|
||||||
$this->method = $method;
|
$this->method = $method;
|
||||||
|
$this->setInit(self::BIT_METHOD, false);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
if (0x0000 > $method || $method > 0xffff) {
|
if (0x0000 > $method || $method > 0xffff) {
|
||||||
throw new ZipException('method out of range');
|
throw new ZipException('method out of range: ' . $method);
|
||||||
}
|
}
|
||||||
switch ($method) {
|
switch ($method) {
|
||||||
case self::METHOD_WINZIP_AES:
|
case self::METHOD_WINZIP_AES:
|
||||||
$this->method = $method;
|
|
||||||
$this->setInit(self::BIT_METHOD, true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ZipFileInterface::METHOD_STORED:
|
case ZipFileInterface::METHOD_STORED:
|
||||||
case ZipFileInterface::METHOD_DEFLATED:
|
case ZipFileInterface::METHOD_DEFLATED:
|
||||||
case ZipFileInterface::METHOD_BZIP2:
|
case ZipFileInterface::METHOD_BZIP2:
|
||||||
|
@@ -18,7 +18,7 @@ interface ZipEntry
|
|||||||
// Bit masks for initialized fields.
|
// Bit masks for initialized fields.
|
||||||
const BIT_PLATFORM = 1,
|
const BIT_PLATFORM = 1,
|
||||||
BIT_METHOD = 2 /* 1 << 1 */,
|
BIT_METHOD = 2 /* 1 << 1 */,
|
||||||
BIT_CRC = 2 /* 1 << 2 */,
|
BIT_CRC = 4 /* 1 << 2 */,
|
||||||
BIT_DATE_TIME = 64 /* 1 << 6 */,
|
BIT_DATE_TIME = 64 /* 1 << 6 */,
|
||||||
BIT_EXTERNAL_ATTR = 128 /* 1 << 7*/
|
BIT_EXTERNAL_ATTR = 128 /* 1 << 7*/
|
||||||
;
|
;
|
||||||
|
@@ -223,7 +223,6 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
|||||||
| ($entry->isDataDescriptorRequired() ? ZipEntry::GPBF_DATA_DESCRIPTOR : 0)
|
| ($entry->isDataDescriptorRequired() ? ZipEntry::GPBF_DATA_DESCRIPTOR : 0)
|
||||||
| ($utf8 ? ZipEntry::GPBF_UTF8 : 0);
|
| ($utf8 ? ZipEntry::GPBF_UTF8 : 0);
|
||||||
|
|
||||||
$skipCrc = false;
|
|
||||||
$entryContent = null;
|
$entryContent = null;
|
||||||
$extraFieldsCollection = $entry->getExtraFieldsCollection();
|
$extraFieldsCollection = $entry->getExtraFieldsCollection();
|
||||||
if (!($entry instanceof ZipChangesEntry && !$entry->isChangedContent())) {
|
if (!($entry instanceof ZipChangesEntry && !$entry->isChangedContent())) {
|
||||||
@@ -233,57 +232,14 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
|||||||
$entry->setSize(strlen($entryContent));
|
$entry->setSize(strlen($entryContent));
|
||||||
$entry->setCrc(crc32($entryContent));
|
$entry->setCrc(crc32($entryContent));
|
||||||
|
|
||||||
if (
|
if ($encrypted && ZipEntry::METHOD_WINZIP_AES === $method) {
|
||||||
$encrypted &&
|
/**
|
||||||
(
|
* @var WinZipAesEntryExtraField $field
|
||||||
ZipEntry::METHOD_WINZIP_AES === $method ||
|
*/
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128 ||
|
$field = $extraFieldsCollection->get(WinZipAesEntryExtraField::getHeaderId());
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192 ||
|
if (null !== $field) {
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
|
$method = $field->getMethod();
|
||||||
)
|
$entry->setMethod($method);
|
||||||
) {
|
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,14 +293,23 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($encrypted) {
|
if ($encrypted) {
|
||||||
if (
|
if (in_array($entry->getEncryptionMethod(), [
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128 ||
|
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192 ||
|
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
|
||||||
$entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
|
ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
|
||||||
) {
|
], true)) {
|
||||||
if ($skipCrc) {
|
$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);
|
$entry->setCrc(0);
|
||||||
}
|
}
|
||||||
|
$extraFieldsCollection->add($field);
|
||||||
$entry->setMethod(ZipEntry::METHOD_WINZIP_AES);
|
$entry->setMethod(ZipEntry::METHOD_WINZIP_AES);
|
||||||
|
|
||||||
$winZipAesEngine = new WinZipAesEngine($entry);
|
$winZipAesEngine = new WinZipAesEngine($entry);
|
||||||
@@ -375,6 +340,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
|
|||||||
* @param ZipEntry $entry
|
* @param ZipEntry $entry
|
||||||
* @param string $content
|
* @param string $content
|
||||||
* @return string
|
* @return string
|
||||||
|
* @throws ZipException
|
||||||
*/
|
*/
|
||||||
protected function determineBestCompressionMethod(ZipEntry $entry, $content)
|
protected function determineBestCompressionMethod(ZipEntry $entry, $content)
|
||||||
{
|
{
|
||||||
|
@@ -346,4 +346,28 @@ class ZipPasswordTest extends ZipFileAddDirTest
|
|||||||
|
|
||||||
$zipFile->close();
|
$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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user