From f82a57e662c80aa8505b44215316648604febbf7 Mon Sep 17 00:00:00 2001 From: wapplay Date: Sat, 7 Dec 2019 19:40:36 +0300 Subject: [PATCH] fix duplicates --- .../TraditionalPkwareEncryptionEngine.php | 6 +- src/PhpZip/Model/Entry/ZipAbstractEntry.php | 6 +- src/PhpZip/Model/ZipInfo.php | 19 ++- .../IgnoreFilesRecursiveFilterIterator.php | 1 + src/PhpZip/ZipFile.php | 134 +++++++++--------- tests/PhpZip/Issue24Test.php | 2 + tests/PhpZip/ZipAlignTest.php | 1 + tests/PhpZip/ZipTestCase.php | 2 + 8 files changed, 91 insertions(+), 80 deletions(-) diff --git a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php index bc8ab45..4045545 100644 --- a/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php +++ b/src/PhpZip/Crypto/TraditionalPkwareEncryptionEngine.php @@ -366,9 +366,9 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine $headerBytes = array_values(unpack('C*', substr($content, 0, self::STD_DEC_HDR_SIZE))); $byte = 0; - foreach ($headerBytes as &$byte) { - $byte = ($byte ^ $this->decryptByte()) & 0xff; - $this->updateKeys($byte); + for ($i = 0; $i < self::STD_DEC_HDR_SIZE; $i++) { + $headerBytes[$i] = ($headerBytes[$i] ^ $this->decryptByte()) & 0xff; + $this->updateKeys($headerBytes[$i]); } if ($this->entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) { diff --git a/src/PhpZip/Model/Entry/ZipAbstractEntry.php b/src/PhpZip/Model/Entry/ZipAbstractEntry.php index f8dcc1a..8736baa 100644 --- a/src/PhpZip/Model/Entry/ZipAbstractEntry.php +++ b/src/PhpZip/Model/Entry/ZipAbstractEntry.php @@ -187,6 +187,7 @@ abstract class ZipAbstractEntry implements ZipEntry * @return int Get platform * * @deprecated Use {@see ZipEntry::getCreatedOS()} + * @noinspection PhpUsageOfSilenceOperatorInspection */ public function getPlatform() { @@ -198,11 +199,12 @@ abstract class ZipAbstractEntry implements ZipEntry /** * @param int $platform * - * @throws ZipException - * * @return ZipEntry * + * @throws ZipException + * * @deprecated Use {@see ZipEntry::setCreatedOS()} + * @noinspection PhpUsageOfSilenceOperatorInspection */ public function setPlatform($platform) { diff --git a/src/PhpZip/Model/ZipInfo.php b/src/PhpZip/Model/ZipInfo.php index 0e959b2..235efef 100644 --- a/src/PhpZip/Model/ZipInfo.php +++ b/src/PhpZip/Model/ZipInfo.php @@ -107,7 +107,7 @@ class ZipInfo const UNX_IXOTH = 00001; // Unix execute permission: other - private static $valuesMadeBy = [ + private static $platformNames = [ self::MADE_BY_MS_DOS => 'FAT', self::MADE_BY_AMIGA => 'Amiga', self::MADE_BY_OPEN_VMS => 'OpenVMS', @@ -130,7 +130,7 @@ class ZipInfo self::MADE_BY_OS_X => 'Mac OS X', ]; - private static $valuesCompressionMethod = [ + private static $compressionMethodNames = [ ZipEntry::UNKNOWN => 'unknown', ZipFile::METHOD_STORED => 'no compression', 1 => 'shrink', @@ -214,6 +214,7 @@ class ZipInfo * @param ZipEntry $entry * * @throws ZipException + * @noinspection PhpMissingBreakStatementInspection */ public function __construct(ZipEntry $entry) { @@ -364,9 +365,7 @@ class ZipInfo $field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId()); if ($field !== null) { - /** - * @var WinZipAesEntryExtraField $field - */ + /** @var WinZipAesEntryExtraField $field */ $method = $field->getMethod(); } } @@ -389,7 +388,7 @@ class ZipInfo if ($entry->isEncrypted()) { if ($entry->getMethod() === ZipEntry::METHOD_WINZIP_AES) { - $return .= ucfirst(self::$valuesCompressionMethod[$entry->getMethod()]); + $return .= ucfirst(self::$compressionMethodNames[$entry->getMethod()]); /** @var WinZipAesEntryExtraField|null $field */ $field = $entry->getExtraFieldsCollection()->get(WinZipAesEntryExtraField::getHeaderId()); @@ -404,8 +403,8 @@ class ZipInfo $return .= ' '; } - if (isset(self::$valuesCompressionMethod[$compressionMethod])) { - $return .= ucfirst(self::$valuesCompressionMethod[$compressionMethod]); + if (isset(self::$compressionMethodNames[$compressionMethod])) { + $return .= ucfirst(self::$compressionMethodNames[$compressionMethod]); } else { $return .= 'unknown'; } @@ -420,8 +419,8 @@ class ZipInfo */ public static function getPlatformName(ZipEntry $entry) { - if (isset(self::$valuesMadeBy[$entry->getCreatedOS()])) { - return self::$valuesMadeBy[$entry->getCreatedOS()]; + if (isset(self::$platformNames[$entry->getCreatedOS()])) { + return self::$platformNames[$entry->getCreatedOS()]; } return 'unknown'; diff --git a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php index 8935127..580805b 100644 --- a/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php +++ b/src/PhpZip/Util/Iterator/IgnoreFilesRecursiveFilterIterator.php @@ -66,6 +66,7 @@ class IgnoreFilesRecursiveFilterIterator extends \RecursiveFilterIterator /** * @return IgnoreFilesRecursiveFilterIterator + * @noinspection PhpMissingParentCallCommonInspection */ public function getChildren() { diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php index 52969f9..a91e013 100644 --- a/src/PhpZip/ZipFile.php +++ b/src/PhpZip/ZipFile.php @@ -740,16 +740,7 @@ class ZipFile implements ZipFileInterface natcasesort($files); $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); - } elseif (is_file($file)) { - $this->addFile($file, $relativePath, $compressionMethod); - } - } + $this->doAddFiles($path, $files, $localPath, $compressionMethod); return $this; } @@ -824,25 +815,7 @@ class ZipFile implements ZipFileInterface return $this; } - if (!empty($localPath) && \is_string($localPath)) { - $localPath = trim($localPath, '/\\') . '/'; - } else { - $localPath = '/'; - } - - /** - * @var string $file - */ - foreach ($filesFound as $file) { - $filename = str_replace($inputDir, $localPath, $file); - $filename = ltrim($filename, '\\/'); - - if (is_dir($file) && FilesUtil::isEmptyDir($file)) { - $this->addEmptyDir($filename); - } elseif (is_file($file)) { - $this->addFile($file, $filename, $compressionMethod); - } - } + $this->doAddFiles($inputDir, $filesFound, $localPath, $compressionMethod); return $this; } @@ -932,18 +905,34 @@ class ZipFile implements ZipFileInterface return $this; } - if (!empty($localPath) && \is_string($localPath)) { - $localPath = trim($localPath, '\\/') . '/'; + $this->doAddFiles($inputDir, $files, $localPath, $compressionMethod); + + return $this; + } + + /** + * @param string $fileSystemDir + * @param array $files + * @param string $zipPath + * @param int|null $compressionMethod + * + * @throws ZipException + */ + private function doAddFiles($fileSystemDir, array $files, $zipPath, $compressionMethod = null) + { + $fileSystemDir = rtrim($fileSystemDir, '/\\') . \DIRECTORY_SEPARATOR; + + if (!empty($zipPath) && \is_string($zipPath)) { + $zipPath = trim($zipPath, '\\/') . '/'; } else { - $localPath = '/'; + $zipPath = '/'; } - $inputDir = rtrim($inputDir, '/\\') . \DIRECTORY_SEPARATOR; /** * @var string $file */ foreach ($files as $file) { - $filename = str_replace($inputDir, $localPath, $file); + $filename = str_replace($fileSystemDir, $zipPath, $file); $filename = ltrim($filename, '\\/'); if (is_dir($file) && FilesUtil::isEmptyDir($file)) { @@ -952,8 +941,6 @@ class ZipFile implements ZipFileInterface $this->addFile($file, $filename, $compressionMethod); } } - - return $this; } /** @@ -1443,26 +1430,25 @@ class ZipFile implements ZipFileInterface * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline * * @throws ZipException + * + * @return string */ public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true) { $outputFilename = (string) $outputFilename; - if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) { - $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION)); - - if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) { - $mimeType = self::$defaultMimeTypes[$ext]; - } + if ($mimeType === null) { + $mimeType = $this->getMimeTypeByFilename($outputFilename); } - if (empty($mimeType)) { - $mimeType = self::$defaultMimeTypes['zip']; + if (!($handle = fopen('php://temp', 'w+b'))) { + throw new InvalidArgumentException('php://temp cannot open for write.'); } - - $content = $this->outputAsString(); + $this->writeZipToStream($handle); $this->close(); + $size = fstat($handle)['size']; + $headerContentDisposition = 'Content-Disposition: ' . ($attachment ? 'attachment' : 'inline'); if (!empty($outputFilename)) { @@ -1471,9 +1457,32 @@ class ZipFile implements ZipFileInterface header($headerContentDisposition); header('Content-Type: ' . $mimeType); - header('Content-Length: ' . \strlen($content)); + header('Content-Length: ' . $size); - exit($content); + rewind($handle); + + try { + return stream_get_contents($handle, -1, 0); + } finally { + fclose($handle); + } + } + + /** + * @param string $outputFilename + * + * @return string + */ + protected function getMimeTypeByFilename($outputFilename) + { + $outputFilename = (string) $outputFilename; + $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION)); + + if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) { + return self::$defaultMimeTypes[$ext]; + } + + return self::$defaultMimeTypes['zip']; } /** @@ -1492,22 +1501,15 @@ class ZipFile implements ZipFileInterface { $outputFilename = (string) $outputFilename; - if (empty($mimeType) || (!\is_string($mimeType) && !empty($outputFilename))) { - $ext = strtolower(pathinfo($outputFilename, \PATHINFO_EXTENSION)); - - if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) { - $mimeType = self::$defaultMimeTypes[$ext]; - } + if ($mimeType === null) { + $mimeType = $this->getMimeTypeByFilename($outputFilename); } - if (empty($mimeType)) { - $mimeType = self::$defaultMimeTypes['zip']; - } - - if (!($handle = fopen('php://memory', 'w+b'))) { - throw new InvalidArgumentException('Memory can not open from write.'); + if (!($handle = fopen('php://temp', 'w+b'))) { + throw new InvalidArgumentException('php://temp cannot open for write.'); } $this->writeZipToStream($handle); + $this->close(); rewind($handle); $contentDispositionValue = ($attachment ? 'attachment' : 'inline'); @@ -1548,15 +1550,17 @@ class ZipFile implements ZipFileInterface */ public function outputAsString() { - if (!($handle = fopen('php://memory', 'w+b'))) { - throw new InvalidArgumentException('Memory can not open from write.'); + if (!($handle = fopen('php://temp', 'w+b'))) { + throw new InvalidArgumentException('php://temp cannot open for write.'); } $this->writeZipToStream($handle); rewind($handle); - $content = stream_get_contents($handle); - fclose($handle); - return $content; + try { + return stream_get_contents($handle); + } finally { + fclose($handle); + } } /** diff --git a/tests/PhpZip/Issue24Test.php b/tests/PhpZip/Issue24Test.php index 6e33163..4250470 100644 --- a/tests/PhpZip/Issue24Test.php +++ b/tests/PhpZip/Issue24Test.php @@ -13,6 +13,8 @@ class Issue24Test extends ZipTestCase { /** * This method is called before the first test of this test class is run. + * + * @noinspection PhpMissingParentCallCommonInspection */ public static function setUpBeforeClass() { diff --git a/tests/PhpZip/ZipAlignTest.php b/tests/PhpZip/ZipAlignTest.php index f6b8f4f..427a5d4 100644 --- a/tests/PhpZip/ZipAlignTest.php +++ b/tests/PhpZip/ZipAlignTest.php @@ -45,6 +45,7 @@ class ZipAlignTest extends ZipTestCase * Test zip alignment. * * @throws ZipException + * @throws \Exception */ public function testZipAlignSourceZip() { diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php index 3710459..ab61665 100644 --- a/tests/PhpZip/ZipTestCase.php +++ b/tests/PhpZip/ZipTestCase.php @@ -19,6 +19,8 @@ abstract class ZipTestCase extends TestCase /** * Before test. + * + * @noinspection PhpMissingParentCallCommonInspection */ protected function setUp() {