2
0
Эх сурвалжийг харах

refactoring zip64, add property softwareVersion, internal attrs, extracted os

Ne-Lexa 6 жил өмнө
parent
commit
95e3312e60

+ 0 - 5
composer.json

@@ -25,11 +25,6 @@
         "ext-zlib": "*",
         "psr/http-message": "^1.0"
     },
-    "config": {
-        "platform": {
-            "php": "5.5"
-        }
-    },
     "require-dev": {
         "phpunit/phpunit": "^4.8|^5.7",
         "zendframework/zend-diactoros": "^1.4"

+ 1 - 1
src/PhpZip/Crypto/WinZipAesEngine.php

@@ -49,9 +49,9 @@ class WinZipAesEngine implements ZipEncryptionEngine
      *
      * @param string $content Input stream buffer
      *
-     * @throws ZipCryptoException
      * @throws ZipException
      * @throws ZipAuthenticationException
+     * @throws ZipCryptoException
      *
      * @return string
      */

+ 4 - 4
src/PhpZip/Extra/Fields/WinZipAesEntryExtraField.php

@@ -4,7 +4,7 @@ namespace PhpZip\Extra\Fields;
 
 use PhpZip\Exception\ZipException;
 use PhpZip\Extra\ExtraField;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * WinZip AES Extra Field.
@@ -49,9 +49,9 @@ class WinZipAesEntryExtraField implements ExtraField
     ];
 
     protected static $encryptionMethods = [
-        self::KEY_STRENGTH_128BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
-        self::KEY_STRENGTH_192BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
-        self::KEY_STRENGTH_256BIT => ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
+        self::KEY_STRENGTH_128BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128,
+        self::KEY_STRENGTH_192BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192,
+        self::KEY_STRENGTH_256BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256,
     ];
 
     /**

+ 0 - 43
src/PhpZip/Mapper/OffsetPositionMapper.php

@@ -1,43 +0,0 @@
-<?php
-
-namespace PhpZip\Mapper;
-
-/**
- * Adds a offset value to the given position.
- *
- * @author Ne-Lexa alexey@nelexa.ru
- * @license MIT
- */
-class OffsetPositionMapper extends PositionMapper
-{
-    /** @var int */
-    private $offset;
-
-    /**
-     * @param int $offset
-     */
-    public function __construct($offset)
-    {
-        $this->offset = (int) $offset;
-    }
-
-    /**
-     * @param int $position
-     *
-     * @return int
-     */
-    public function map($position)
-    {
-        return parent::map($position) + $this->offset;
-    }
-
-    /**
-     * @param int $position
-     *
-     * @return int
-     */
-    public function unmap($position)
-    {
-        return parent::unmap($position) - $this->offset;
-    }
-}

+ 0 - 32
src/PhpZip/Mapper/PositionMapper.php

@@ -1,32 +0,0 @@
-<?php
-
-namespace PhpZip\Mapper;
-
-/**
- * Maps a given position.
- *
- * @author Ne-Lexa alexey@nelexa.ru
- * @license MIT
- */
-class PositionMapper
-{
-    /**
-     * @param int $position
-     *
-     * @return int
-     */
-    public function map($position)
-    {
-        return $position;
-    }
-
-    /**
-     * @param int $position
-     *
-     * @return int
-     */
-    public function unmap($position)
-    {
-        return $position;
-    }
-}

+ 51 - 17
src/PhpZip/Model/EndOfCentralDirectory.php

@@ -3,7 +3,7 @@
 namespace PhpZip\Model;
 
 /**
- * Read End of Central Directory.
+ * End of Central Directory.
  *
  * @author Ne-Lexa alexey@nelexa.ru
  * @license MIT
@@ -11,13 +11,13 @@ namespace PhpZip\Model;
 class EndOfCentralDirectory
 {
     /** Zip64 End Of Central Directory Record. */
-    const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG = 0x06064B50;
+    const ZIP64_END_OF_CD_RECORD_SIG = 0x06064B50;
 
     /** Zip64 End Of Central Directory Locator. */
-    const ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG = 0x07064B50;
+    const ZIP64_END_OF_CD_LOCATOR_SIG = 0x07064B50;
 
     /** End Of Central Directory Record signature. */
-    const END_OF_CENTRAL_DIRECTORY_RECORD_SIG = 0x06054B50;
+    const END_OF_CD_SIG = 0x06054B50;
 
     /**
      * The minimum length of the End Of Central Directory Record.
@@ -49,7 +49,7 @@ class EndOfCentralDirectory
      * end of central directory record 8
      * total number of disks           4.
      */
-    const ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_LEN = 20;
+    const ZIP64_END_OF_CD_LOCATOR_LEN = 20;
 
     /**
      * The minimum length of the Zip64 End Of Central Directory Record.
@@ -74,35 +74,45 @@ class EndOfCentralDirectory
      */
     const ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN = 56;
 
-    /** @var string|null the archive comment */
-    private $comment;
+    /** @var int Count files. */
+    private $entryCount;
+
+    /** @var int Central Directory Offset. */
+    private $cdOffset;
 
     /** @var int */
-    private $entryCount;
+    private $cdSize;
 
-    /** @var bool */
+    /** @var string|null The archive comment. */
+    private $comment;
+
+    /** @var bool Zip64 extension */
     private $zip64;
 
     /**
      * EndOfCentralDirectory constructor.
      *
-     * @param int         $entryCount
-     * @param string|null $comment
-     * @param bool        $zip64
+     * @param int        $entryCount
+     * @param int        $cdOffset
+     * @param int        $cdSize
+     * @param bool       $zip64
+     * @param mixed|null $comment
      */
-    public function __construct($entryCount, $comment, $zip64 = false)
+    public function __construct($entryCount, $cdOffset, $cdSize, $zip64, $comment = null)
     {
         $this->entryCount = $entryCount;
-        $this->comment = $comment;
+        $this->cdOffset = $cdOffset;
+        $this->cdSize = $cdSize;
         $this->zip64 = $zip64;
+        $this->comment = $comment;
     }
 
     /**
-     * @return string|null
+     * @param string|null $comment
      */
-    public function getComment()
+    public function setComment($comment)
     {
-        return $this->comment;
+        $this->comment = $comment;
     }
 
     /**
@@ -113,6 +123,30 @@ class EndOfCentralDirectory
         return $this->entryCount;
     }
 
+    /**
+     * @return int
+     */
+    public function getCdOffset()
+    {
+        return $this->cdOffset;
+    }
+
+    /**
+     * @return int
+     */
+    public function getCdSize()
+    {
+        return $this->cdSize;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getComment()
+    {
+        return $this->comment;
+    }
+
     /**
      * @return bool
      */

+ 2 - 0
src/PhpZip/Model/Entry/OutputOffsetEntry.php

@@ -9,6 +9,8 @@ use PhpZip\Model\ZipEntry;
  *
  * @author Ne-Lexa alexey@nelexa.ru
  * @license MIT
+ *
+ * @internal
  */
 class OutputOffsetEntry
 {

+ 185 - 48
src/PhpZip/Model/Entry/ZipAbstractEntry.php

@@ -10,7 +10,7 @@ use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
 use PhpZip\Model\ZipEntry;
 use PhpZip\Util\DateTimeConverter;
 use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * Abstract ZIP entry.
@@ -26,16 +26,22 @@ abstract class ZipAbstractEntry implements ZipEntry
     private $name;
 
     /** @var int Made by platform */
-    private $platform = self::UNKNOWN;
+    private $createdOS = self::UNKNOWN;
+
+    /** @var int Extracted by platform */
+    private $extractedOS = self::UNKNOWN;
+
+    /** @var int */
+    private $softwareVersion = self::UNKNOWN;
 
     /** @var int */
-    private $versionNeededToExtract = 20;
+    private $versionNeededToExtract = self::UNKNOWN;
 
     /** @var int Compression method */
     private $method = self::UNKNOWN;
 
     /** @var int */
-    private $general = 0;
+    private $generalPurposeBitFlags = 0;
 
     /** @var int Dos time */
     private $dosTime = self::UNKNOWN;
@@ -49,11 +55,14 @@ abstract class ZipAbstractEntry implements ZipEntry
     /** @var int Uncompressed size */
     private $size = self::UNKNOWN;
 
+    /** @var int Internal attributes */
+    private $internalAttributes = 0;
+
     /** @var int External attributes */
     private $externalAttributes = 0;
 
     /** @var int relative Offset Of Local File Header */
-    private $offset = self::UNKNOWN;
+    private $offset = 0;
 
     /**
      * Collections of Extra Fields.
@@ -73,17 +82,17 @@ abstract class ZipAbstractEntry implements ZipEntry
     /**
      * Encryption method.
      *
-     * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
+     * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
      *
      * @var int
      */
-    private $encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL;
+    private $encryptionMethod = ZipFile::ENCRYPTION_METHOD_TRADITIONAL;
 
     /** @var int */
-    private $compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
+    private $compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION;
 
     /**
      * ZipAbstractEntry constructor.
@@ -101,7 +110,9 @@ abstract class ZipAbstractEntry implements ZipEntry
     public function setEntry(ZipEntry $entry)
     {
         $this->setName($entry->getName());
-        $this->setPlatform($entry->getPlatform());
+        $this->setSoftwareVersion($entry->getSoftwareVersion());
+        $this->setCreatedOS($entry->getCreatedOS());
+        $this->setExtractedOS($entry->getExtractedOS());
         $this->setVersionNeededToExtract($entry->getVersionNeededToExtract());
         $this->setMethod($entry->getMethod());
         $this->setGeneralPurposeBitFlags($entry->getGeneralPurposeBitFlags());
@@ -109,6 +120,7 @@ abstract class ZipAbstractEntry implements ZipEntry
         $this->setCrc($entry->getCrc());
         $this->setCompressedSize($entry->getCompressedSize());
         $this->setSize($entry->getSize());
+        $this->setInternalAttributes($entry->getInternalAttributes());
         $this->setExternalAttributes($entry->getExternalAttributes());
         $this->setOffset($entry->getOffset());
         $this->setExtra($entry->getExtra());
@@ -163,20 +175,48 @@ abstract class ZipAbstractEntry implements ZipEntry
     public function setGeneralPurposeBitFlag($mask, $bit)
     {
         if ($bit) {
-            $this->general |= $mask;
+            $this->generalPurposeBitFlags |= $mask;
         } else {
-            $this->general &= ~$mask;
+            $this->generalPurposeBitFlags &= ~$mask;
         }
 
         return $this;
     }
 
     /**
-     * @return int platform
+     * @return int Get platform
+     *
+     * @deprecated Use {@see ZipEntry::getCreatedOS()}
      */
     public function getPlatform()
     {
-        return $this->platform;
+        @trigger_error('ZipEntry::getPlatform() is deprecated. Use ZipEntry::getCreatedOS()', \E_USER_DEPRECATED);
+
+        return $this->getCreatedOS();
+    }
+
+    /**
+     * @param int $platform
+     *
+     * @throws ZipException
+     *
+     * @return ZipEntry
+     *
+     * @deprecated Use {@see ZipEntry::setCreatedOS()}
+     */
+    public function setPlatform($platform)
+    {
+        @trigger_error('ZipEntry::setPlatform() is deprecated. Use ZipEntry::setCreatedOS()', \E_USER_DEPRECATED);
+
+        return $this->setCreatedOS($platform);
+    }
+
+    /**
+     * @return int platform
+     */
+    public function getCreatedOS()
+    {
+        return $this->createdOS;
     }
 
     /**
@@ -188,16 +228,63 @@ abstract class ZipAbstractEntry implements ZipEntry
      *
      * @return ZipEntry
      */
-    public function setPlatform($platform)
+    public function setCreatedOS($platform)
     {
-        if ($platform !== self::UNKNOWN) {
-            if ($platform < 0x00 || $platform > 0xff) {
-                throw new ZipException('Platform out of range');
-            }
-            $this->platform = $platform;
-        } else {
-            $this->platform = 0; // ms-dos
+        $platform = (int) $platform;
+
+        if ($platform < 0x00 || $platform > 0xff) {
+            throw new ZipException('Platform out of range');
         }
+        $this->createdOS = $platform;
+
+        return $this;
+    }
+
+    /**
+     * @return int
+     */
+    public function getExtractedOS()
+    {
+        return $this->extractedOS;
+    }
+
+    /**
+     * Set extracted OS.
+     *
+     * @param int $platform
+     *
+     * @throws ZipException
+     *
+     * @return ZipEntry
+     */
+    public function setExtractedOS($platform)
+    {
+        $platform = (int) $platform;
+
+        if ($platform < 0x00 || $platform > 0xff) {
+            throw new ZipException('Platform out of range');
+        }
+        $this->extractedOS = $platform;
+
+        return $this;
+    }
+
+    /**
+     * @return int
+     */
+    public function getSoftwareVersion()
+    {
+        return $this->softwareVersion;
+    }
+
+    /**
+     * @param int $softwareVersion
+     *
+     * @return ZipEntry
+     */
+    public function setSoftwareVersion($softwareVersion)
+    {
+        $this->softwareVersion = (int) $softwareVersion;
 
         return $this;
     }
@@ -209,6 +296,24 @@ abstract class ZipAbstractEntry implements ZipEntry
      */
     public function getVersionNeededToExtract()
     {
+        if ($this->versionNeededToExtract === self::UNKNOWN) {
+            $method = $this->getMethod();
+
+            if ($method === self::METHOD_WINZIP_AES) {
+                return 51;
+            }
+
+            if ($method === ZipFile::METHOD_BZIP2) {
+                return 46;
+            }
+
+            if ($this->isZip64ExtensionsRequired()) {
+                return 45;
+            }
+
+            return $method === ZipFile::METHOD_DEFLATED || $this->isDirectory() ? 20 : 10;
+        }
+
         return $this->versionNeededToExtract;
     }
 
@@ -300,7 +405,7 @@ abstract class ZipAbstractEntry implements ZipEntry
      */
     public function setOffset($offset)
     {
-        $this->offset = $offset;
+        $this->offset = (int) $offset;
 
         return $this;
     }
@@ -312,7 +417,7 @@ abstract class ZipAbstractEntry implements ZipEntry
      */
     public function getGeneralPurposeBitFlags()
     {
-        return $this->general & 0xffff;
+        return $this->generalPurposeBitFlags & 0xffff;
     }
 
     /**
@@ -331,20 +436,20 @@ abstract class ZipAbstractEntry implements ZipEntry
         if ($general < 0x0000 || $general > 0xffff) {
             throw new ZipException('general out of range');
         }
-        $this->general = $general;
+        $this->generalPurposeBitFlags = $general;
 
-        if ($this->method === ZipFileInterface::METHOD_DEFLATED) {
+        if ($this->method === ZipFile::METHOD_DEFLATED) {
             $bit1 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG1);
             $bit2 = $this->getGeneralPurposeBitFlag(self::GPBF_COMPRESSION_FLAG2);
 
             if ($bit1 && !$bit2) {
-                $this->compressionLevel = ZipFileInterface::LEVEL_BEST_COMPRESSION;
+                $this->compressionLevel = ZipFile::LEVEL_BEST_COMPRESSION;
             } elseif (!$bit1 && $bit2) {
-                $this->compressionLevel = ZipFileInterface::LEVEL_FAST;
+                $this->compressionLevel = ZipFile::LEVEL_FAST;
             } elseif ($bit1 && $bit2) {
-                $this->compressionLevel = ZipFileInterface::LEVEL_SUPER_FAST;
+                $this->compressionLevel = ZipFile::LEVEL_SUPER_FAST;
             } else {
-                $this->compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION;
+                $this->compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION;
             }
         }
 
@@ -370,7 +475,7 @@ abstract class ZipAbstractEntry implements ZipEntry
      */
     public function getGeneralPurposeBitFlag($mask)
     {
-        return ($this->general & $mask) !== 0;
+        return ($this->generalPurposeBitFlags & $mask) !== 0;
     }
 
     /**
@@ -447,9 +552,9 @@ abstract class ZipAbstractEntry implements ZipEntry
         }
         switch ($method) {
             case self::METHOD_WINZIP_AES:
-            case ZipFileInterface::METHOD_STORED:
-            case ZipFileInterface::METHOD_DEFLATED:
-            case ZipFileInterface::METHOD_BZIP2:
+            case ZipFile::METHOD_STORED:
+            case ZipFile::METHOD_DEFLATED:
+            case ZipFile::METHOD_BZIP2:
                 $this->method = $method;
                 break;
 
@@ -490,6 +595,8 @@ abstract class ZipAbstractEntry implements ZipEntry
      * @param int $dosTime
      *
      * @throws ZipException
+     *
+     * @return ZipEntry
      */
     public function setDosTime($dosTime)
     {
@@ -499,6 +606,8 @@ abstract class ZipAbstractEntry implements ZipEntry
             throw new ZipException('DosTime out of range');
         }
         $this->dosTime = $dosTime;
+
+        return $this;
     }
 
     /**
@@ -547,6 +656,30 @@ abstract class ZipAbstractEntry implements ZipEntry
         return $this;
     }
 
+    /**
+     * Sets the internal file attributes.
+     *
+     * @param int $attributes the internal file attributes
+     *
+     * @return ZipEntry
+     */
+    public function setInternalAttributes($attributes)
+    {
+        $this->internalAttributes = (int) $attributes;
+
+        return $this;
+    }
+
+    /**
+     * Returns the internal file attributes.
+     *
+     * @return int the internal file attributes
+     */
+    public function getInternalAttributes()
+    {
+        return $this->internalAttributes;
+    }
+
     /**
      * Returns true if and only if this ZIP entry represents a directory entry
      * (i.e. end with '/').
@@ -589,10 +722,14 @@ abstract class ZipAbstractEntry implements ZipEntry
      * @param string $data the byte array holding the serialized Extra Fields
      *
      * @throws ZipException if the serialized Extra Fields exceed 64 KB
+     *
+     * @return ZipEntry
      */
     public function setExtra($data)
     {
         $this->extraFieldsCollection = ExtraFieldsFactory::createExtraFieldCollections($data, $this);
+
+        return $this;
     }
 
     /**
@@ -713,19 +850,19 @@ abstract class ZipAbstractEntry implements ZipEntry
      *
      * @return ZipEntry
      *
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
-     * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
+     * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
      */
     public function setEncryptionMethod($encryptionMethod)
     {
         if ($encryptionMethod !== null) {
             if (
-                $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
+                $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+                && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+                && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
+                && $encryptionMethod !== ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
             ) {
                 throw new ZipException('Invalid encryption method');
             }
@@ -748,14 +885,14 @@ abstract class ZipAbstractEntry implements ZipEntry
      *
      * @return ZipEntry
      */
-    public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
+    public function setCompressionLevel($compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION)
     {
-        if ($compressionLevel < ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ||
-            $compressionLevel > ZipFileInterface::LEVEL_BEST_COMPRESSION
+        if ($compressionLevel < ZipFile::LEVEL_DEFAULT_COMPRESSION ||
+            $compressionLevel > ZipFile::LEVEL_BEST_COMPRESSION
         ) {
             throw new InvalidArgumentException(
                 'Invalid compression level. Minimum level ' .
-                ZipFileInterface::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFileInterface::LEVEL_BEST_COMPRESSION
+                ZipFile::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFile::LEVEL_BEST_COMPRESSION
             );
         }
         $this->compressionLevel = $compressionLevel;

+ 2 - 0
src/PhpZip/Model/Entry/ZipChangesEntry.php

@@ -10,6 +10,8 @@ use PhpZip\Exception\ZipException;
  *
  * @author Ne-Lexa alexey@nelexa.ru
  * @license MIT
+ *
+ * @internal
  */
 class ZipChangesEntry extends ZipAbstractEntry
 {

+ 0 - 20
src/PhpZip/Model/Entry/ZipNewEntry.php

@@ -3,7 +3,6 @@
 namespace PhpZip\Model\Entry;
 
 use PhpZip\Exception\InvalidArgumentException;
-use PhpZip\ZipFileInterface;
 
 /**
  * @author Ne-Lexa alexey@nelexa.ru
@@ -50,25 +49,6 @@ class ZipNewEntry extends ZipAbstractEntry
         return $this->content;
     }
 
-    /**
-     * Version needed to extract.
-     *
-     * @return int
-     */
-    public function getVersionNeededToExtract()
-    {
-        $method = $this->getMethod();
-
-        return $method === self::METHOD_WINZIP_AES ? 51 :
-            (
-                $method === ZipFileInterface::METHOD_BZIP2 ? 46 :
-                (
-                    $this->isZip64ExtensionsRequired() ? 45 :
-                    ($method === ZipFileInterface::METHOD_DEFLATED || $this->isDirectory() ? 20 : 10)
-                )
-            );
-    }
-
     /**
      * Clone extra fields.
      */

+ 78 - 11
src/PhpZip/Model/ZipEntry.php

@@ -4,7 +4,7 @@ namespace PhpZip\Model;
 
 use PhpZip\Exception\ZipException;
 use PhpZip\Extra\ExtraFieldsCollection;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * ZIP file entry.
@@ -16,9 +16,6 @@ use PhpZip\ZipFileInterface;
  */
 interface ZipEntry
 {
-    // Bit masks for initialized fields.
-    const BIT_EXTERNAL_ATTR = 128;
-
     /** The unknown value for numeric properties. */
     const UNKNOWN = -1;
 
@@ -118,20 +115,68 @@ interface ZipEntry
 
     /**
      * @return int Get platform
+     *
+     * @deprecated Use {@see ZipEntry::getCreatedOS()}
      */
     public function getPlatform();
 
     /**
-     * Set platform.
-     *
      * @param int $platform
      *
      * @throws ZipException
      *
      * @return ZipEntry
+     *
+     * @deprecated Use {@see ZipEntry::setCreatedOS()}
      */
     public function setPlatform($platform);
 
+    /**
+     * Returns created OS.
+     *
+     * @return int Get platform
+     */
+    public function getCreatedOS();
+
+    /**
+     * Set created OS.
+     *
+     * @param int $platform
+     *
+     * @throws ZipException
+     *
+     * @return ZipEntry
+     */
+    public function setCreatedOS($platform);
+
+    /**
+     * @return int
+     */
+    public function getExtractedOS();
+
+    /**
+     * Set extracted OS.
+     *
+     * @param int $platform
+     *
+     * @throws ZipException
+     *
+     * @return ZipEntry
+     */
+    public function setExtractedOS($platform);
+
+    /**
+     * @return int
+     */
+    public function getSoftwareVersion();
+
+    /**
+     * @param int $softwareVersion
+     *
+     * @return ZipEntry
+     */
+    public function setSoftwareVersion($softwareVersion);
+
     /**
      * Version needed to extract.
      *
@@ -323,6 +368,8 @@ interface ZipEntry
      * @param int $dosTime
      *
      * @throws ZipException
+     *
+     * @return ZipEntry
      */
     public function setDosTime($dosTime);
 
@@ -333,6 +380,24 @@ interface ZipEntry
      */
     public function getExternalAttributes();
 
+    /**
+     * Sets the internal file attributes.
+     *
+     * @param int $attributes the internal file attributes
+     *
+     * @throws ZipException
+     *
+     * @return ZipEntry
+     */
+    public function setInternalAttributes($attributes);
+
+    /**
+     * Returns the internal file attributes.
+     *
+     * @return int the internal file attributes
+     */
+    public function getInternalAttributes();
+
     /**
      * Sets the external file attributes.
      *
@@ -368,6 +433,8 @@ interface ZipEntry
      * @param string $data the byte array holding the serialized Extra Fields
      *
      * @throws ZipException if the serialized Extra Fields exceed 64 KB
+     *
+     * @return ZipEntry
      */
     public function setExtra($data);
 
@@ -439,10 +506,10 @@ interface ZipEntry
      *
      * @return ZipEntry
      *
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256
-     * @see ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128
-     * @see ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256
+     * @see ZipFile::ENCRYPTION_METHOD_TRADITIONAL
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128
+     * @see ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192
      */
     public function setEncryptionMethod($encryptionMethod);
 
@@ -460,7 +527,7 @@ interface ZipEntry
      *
      * @return ZipEntry
      */
-    public function setCompressionLevel($compressionLevel = ZipFileInterface::LEVEL_DEFAULT_COMPRESSION);
+    public function setCompressionLevel($compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION);
 
     /**
      * @return int

+ 7 - 7
src/PhpZip/Model/ZipInfo.php

@@ -6,7 +6,7 @@ use PhpZip\Exception\ZipException;
 use PhpZip\Extra\Fields\NtfsExtraField;
 use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
 use PhpZip\Util\FilesUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * Zip info.
@@ -132,7 +132,7 @@ class ZipInfo
 
     private static $valuesCompressionMethod = [
         ZipEntry::UNKNOWN => 'unknown',
-        ZipFileInterface::METHOD_STORED => 'no compression',
+        ZipFile::METHOD_STORED => 'no compression',
         1 => 'shrink',
         2 => 'reduce level 1',
         3 => 'reduce level 2',
@@ -140,7 +140,7 @@ class ZipInfo
         5 => 'reduce level 4',
         6 => 'implode',
         7 => 'reserved for Tokenizing compression algorithm',
-        ZipFileInterface::METHOD_DEFLATED => 'deflate',
+        ZipFile::METHOD_DEFLATED => 'deflate',
         9 => 'deflate64',
         10 => 'PKWARE Data Compression Library Imploding (old IBM TERSE)',
         11 => 'reserved by PKWARE',
@@ -252,10 +252,10 @@ class ZipInfo
         $attributes = str_repeat(' ', 12);
         $externalAttributes = $entry->getExternalAttributes();
         $xattr = (($externalAttributes >> 16) & 0xFFFF);
-        switch ($entry->getPlatform()) {
+        switch ($entry->getCreatedOS()) {
             case self::MADE_BY_MS_DOS:
             case self::MADE_BY_WINDOWS_NTFS:
-                if ($entry->getPlatform() !== self::MADE_BY_MS_DOS ||
+                if ($entry->getCreatedOS() !== self::MADE_BY_MS_DOS ||
                     ($xattr & self::UNX_IRWXU) !==
                     (self::UNX_IRUSR |
                         (!($externalAttributes & 1) << 7) |
@@ -420,8 +420,8 @@ class ZipInfo
      */
     public static function getPlatformName(ZipEntry $entry)
     {
-        if (isset(self::$valuesMadeBy[$entry->getPlatform()])) {
-            return self::$valuesMadeBy[$entry->getPlatform()];
+        if (isset(self::$valuesMadeBy[$entry->getCreatedOS()])) {
+            return self::$valuesMadeBy[$entry->getCreatedOS()];
         }
 
         return 'unknown';

+ 3 - 3
src/PhpZip/Model/ZipModel.php

@@ -7,7 +7,7 @@ use PhpZip\Exception\ZipEntryNotFoundException;
 use PhpZip\Exception\ZipException;
 use PhpZip\Model\Entry\ZipChangesEntry;
 use PhpZip\Model\Entry\ZipSourceEntry;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * Zip Model.
@@ -203,8 +203,8 @@ class ZipModel implements \Countable
     /**
      * @param string|ZipEntry $entry
      *
-     * @throws ZipException
      * @throws ZipEntryNotFoundException
+     * @throws ZipException
      *
      * @return ZipChangesEntry|ZipEntry
      */
@@ -352,7 +352,7 @@ class ZipModel implements \Countable
     /**
      * @param int $encryptionMethod
      */
-    public function setEncryptionMethod($encryptionMethod = ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256)
+    public function setEncryptionMethod($encryptionMethod = ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256)
     {
         $this->matcher()->all()->setEncryptionMethod($encryptionMethod);
     }

+ 247 - 243
src/PhpZip/Stream/ZipInputStream.php

@@ -14,15 +14,13 @@ use PhpZip\Extra\ExtraFieldsCollection;
 use PhpZip\Extra\ExtraFieldsFactory;
 use PhpZip\Extra\Fields\ApkAlignmentExtraField;
 use PhpZip\Extra\Fields\WinZipAesEntryExtraField;
-use PhpZip\Mapper\OffsetPositionMapper;
-use PhpZip\Mapper\PositionMapper;
 use PhpZip\Model\EndOfCentralDirectory;
 use PhpZip\Model\Entry\ZipSourceEntry;
 use PhpZip\Model\ZipEntry;
 use PhpZip\Model\ZipModel;
 use PhpZip\Util\PackUtil;
 use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * Read zip file.
@@ -35,15 +33,6 @@ class ZipInputStream implements ZipInputStreamInterface
     /** @var resource */
     protected $in;
 
-    /** @var PositionMapper */
-    protected $mapper;
-
-    /** @var int the number of bytes in the preamble of this ZIP file */
-    protected $preamble = 0;
-
-    /** @var int the number of bytes in the postamble of this ZIP file */
-    protected $postamble = 0;
-
     /** @var ZipModel */
     protected $zipModel;
 
@@ -58,7 +47,6 @@ class ZipInputStream implements ZipInputStreamInterface
             throw new RuntimeException('$in must be resource');
         }
         $this->in = $in;
-        $this->mapper = new PositionMapper();
     }
 
     /**
@@ -95,8 +83,8 @@ class ZipInputStream implements ZipInputStreamInterface
 
         if (
             $signature !== ZipEntry::LOCAL_FILE_HEADER_SIG
-            && $signature !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG
-            && $signature !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG
+            && $signature !== EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG
+            && $signature !== EndOfCentralDirectory::END_OF_CD_SIG
         ) {
             throw new ZipException(
                 'Expected Local File Header or (ZIP64) End Of Central Directory Record! Signature: ' . $signature
@@ -111,145 +99,179 @@ class ZipInputStream implements ZipInputStreamInterface
      */
     protected function readEndOfCentralDirectory()
     {
+        if (!$this->findEndOfCentralDirectory()) {
+            throw new ZipException('Invalid zip file. The end of the central directory could not be found.');
+        }
+
+        $positionECD = ftell($this->in) - 4;
+        $buffer = fread($this->in, fstat($this->in)['size'] - $positionECD);
+
+        $unpack = unpack(
+            'vdiskNo/vcdDiskNo/vcdEntriesDisk/' .
+            'vcdEntries/VcdSize/VcdPos/vcommentLength',
+            substr($buffer, 0, 18)
+        );
+
+        if (
+            $unpack['diskNo'] !== 0 ||
+            $unpack['cdDiskNo'] !== 0 ||
+            $unpack['cdEntriesDisk'] !== $unpack['cdEntries']
+        ) {
+            throw new ZipException(
+                'ZIP file spanning/splitting is not supported!'
+            );
+        }
+        // .ZIP file comment       (variable sizeECD)
         $comment = null;
-        // Search for End of central directory record.
-        $stats = fstat($this->in);
-        $size = $stats['size'];
-        $max = $size - EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN;
+
+        if ($unpack['commentLength'] > 0) {
+            $comment = substr($buffer, 18, $unpack['commentLength']);
+        }
+
+        // Check for ZIP64 End Of Central Directory Locator exists.
+        $zip64ECDLocatorPosition = $positionECD - EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_LEN;
+        fseek($this->in, $zip64ECDLocatorPosition);
+        // zip64 end of central dir locator
+        // signature                       4 bytes  (0x07064b50)
+        if ($zip64ECDLocatorPosition > 0 && unpack(
+            'V',
+            fread($this->in, 4)
+        )[1] === EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_SIG) {
+            $positionECD = $this->findZip64ECDPosition();
+            $endCentralDirectory = $this->readZip64EndOfCentralDirectory($positionECD);
+            $endCentralDirectory->setComment($comment);
+        } else {
+            $endCentralDirectory = new EndOfCentralDirectory(
+                $unpack['cdEntries'],
+                $unpack['cdPos'],
+                $unpack['cdSize'],
+                false,
+                $comment
+            );
+        }
+
+        return $endCentralDirectory;
+    }
+
+    /**
+     * @throws ZipException
+     *
+     * @return bool
+     */
+    protected function findEndOfCentralDirectory()
+    {
+        $max = fstat($this->in)['size'] - EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN;
+
+        if ($max < 0) {
+            throw new ZipException('Too short to be a zip file');
+        }
         $min = $max >= 0xffff ? $max - 0xffff : 0;
-        for ($endOfCentralDirRecordPos = $max; $endOfCentralDirRecordPos >= $min; $endOfCentralDirRecordPos--) {
-            fseek($this->in, $endOfCentralDirRecordPos, \SEEK_SET);
+        // Search for End of central directory record.
+        for ($position = $max; $position >= $min; $position--) {
+            fseek($this->in, $position);
             // end of central dir signature    4 bytes  (0x06054b50)
-            if (unpack('V', fread($this->in, 4))[1] !== EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
+            if (unpack('V', fread($this->in, 4))[1] !== EndOfCentralDirectory::END_OF_CD_SIG) {
                 continue;
             }
 
-            // number of this disk                        - 2 bytes
-            // number of the disk with the start of the
-            //        central directory                   - 2 bytes
-            // total number of entries in the central
-            //        directory on this disk              - 2 bytes
-            // total number of entries in the central
-            //        directory                           - 2 bytes
-            // size of the central directory              - 4 bytes
-            // offset of start of central directory with
-            //        respect to the starting disk number - 4 bytes
-            // ZIP file comment length                    - 2 bytes
-            $data = unpack(
-                'vdiskNo/vcdDiskNo/vcdEntriesDisk/vcdEntries/VcdSize/VcdPos/vcommentLength',
-                fread($this->in, 18)
-            );
+            return true;
+        }
 
-            if ($data['diskNo'] !== 0 || $data['cdDiskNo'] !== 0 || $data['cdEntriesDisk'] !== $data['cdEntries']) {
-                throw new ZipException(
-                    'ZIP file spanning/splitting is not supported!'
-                );
-            }
-            // .ZIP file comment       (variable size)
-            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);
-
-            // Check for ZIP64 End Of Central Directory Locator.
-            $endOfCentralDirLocatorPos = $endOfCentralDirRecordPos - EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_LEN;
-
-            fseek($this->in, $endOfCentralDirLocatorPos, \SEEK_SET);
-            // zip64 end of central dir locator
-            // signature                       4 bytes  (0x07064b50)
-            if (
-                $endOfCentralDirLocatorPos < 0 ||
-                ftell($this->in) === $size ||
-                unpack(
-                    'V',
-                    fread($this->in, 4)
-                )[1] !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG
-            ) {
-                // Seek and check first CFH, probably requiring an offset mapper.
-                $offset = $endOfCentralDirRecordPos - $data['cdSize'];
-                fseek($this->in, $offset, \SEEK_SET);
-                $offset -= $data['cdPos'];
-
-                if ($offset !== 0) {
-                    $this->mapper = new OffsetPositionMapper($offset);
-                }
-                $entryCount = $data['cdEntries'];
+        return false;
+    }
 
-                return new EndOfCentralDirectory($entryCount, $comment);
-            }
+    /**
+     * Read Zip64 end of central directory locator and returns
+     * Zip64 end of central directory position.
+     *
+     * number of the disk with the
+     * start of the zip64 end of
+     * central directory               4 bytes
+     * relative offset of the zip64
+     * end of central directory record 8 bytes
+     * total number of disks           4 bytes
+     *
+     * @throws ZipException
+     *
+     * @return int Zip64 End Of Central Directory position
+     */
+    protected function findZip64ECDPosition()
+    {
+        $diskNo = unpack('V', fread($this->in, 4))[1];
+        $zip64ECDPos = PackUtil::unpackLongLE(fread($this->in, 8));
+        $totalDisks = unpack('V', fread($this->in, 4))[1];
 
-            // number of the disk with the
-            // start of the zip64 end of
-            // central directory               4 bytes
-            $zip64EndOfCentralDirectoryRecordDisk = unpack('V', fread($this->in, 4))[1];
-            // relative offset of the zip64
-            // end of central directory record 8 bytes
-            $zip64EndOfCentralDirectoryRecordPos = PackUtil::unpackLongLE(fread($this->in, 8));
-            // total number of disks           4 bytes
-            $totalDisks = unpack('V', fread($this->in, 4))[1];
-
-            if ($zip64EndOfCentralDirectoryRecordDisk !== 0 || $totalDisks !== 1) {
-                throw new ZipException('ZIP file spanning/splitting is not supported!');
-            }
-            fseek($this->in, $zip64EndOfCentralDirectoryRecordPos, \SEEK_SET);
-            // zip64 end of central dir
-            // signature                       4 bytes  (0x06064b50)
-            $zip64EndOfCentralDirSig = unpack('V', fread($this->in, 4))[1];
+        if ($diskNo !== 0 || $totalDisks > 1) {
+            throw new ZipException('ZIP file spanning/splitting is not supported!');
+        }
 
-            if ($zip64EndOfCentralDirSig !== EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG) {
-                throw new ZipException('Expected ZIP64 End Of Central Directory Record!');
-            }
-            // size of zip64 end of central
-            // directory record                8 bytes
-            // version made by                 2 bytes
-            // version needed to extract       2 bytes
-            fseek($this->in, 12, \SEEK_CUR);
-            // number of this disk             4 bytes
-            $diskNo = unpack('V', fread($this->in, 4))[1];
-            // number of the disk with the
-            // start of the central directory  4 bytes
-            $cdDiskNo = unpack('V', fread($this->in, 4))[1];
-            // total number of entries in the
-            // central directory on this disk  8 bytes
-            $cdEntriesDisk = PackUtil::unpackLongLE(fread($this->in, 8));
-            // total number of entries in the
-            // central directory               8 bytes
-            $cdEntries = PackUtil::unpackLongLE(fread($this->in, 8));
-
-            if ($diskNo !== 0 || $cdDiskNo !== 0 || $cdEntriesDisk !== $cdEntries) {
-                throw new ZipException('ZIP file spanning/splitting is not supported!');
-            }
+        return $zip64ECDPos;
+    }
 
-            if ($cdEntries < 0 || $cdEntries > 0x7fffffff) {
-                throw new ZipException('Total Number Of Entries In The Central Directory out of range!');
-            }
-            // size of the central directory   8 bytes
-            fseek($this->in, 8, \SEEK_CUR);
-            // offset of start of central
-            // directory with respect to
-            // the starting disk number        8 bytes
-            $cdPos = PackUtil::unpackLongLE(fread($this->in, 8));
-            // zip64 extensible data sector    (variable size)
-            fseek($this->in, $cdPos, \SEEK_SET);
-            $this->preamble = $zip64EndOfCentralDirectoryRecordPos;
-            $entryCount = $cdEntries;
-            $zip64 = true;
-
-            return new EndOfCentralDirectory($entryCount, $comment, $zip64);
-        }
-        // Start recovering file entries from min.
-        $this->preamble = $min;
-        $this->postamble = $size - $min;
-
-        return new EndOfCentralDirectory(0, $comment);
+    /**
+     * Read zip64 end of central directory locator and zip64 end
+     * of central directory record.
+     *
+     * zip64 end of central dir
+     * signature                       4 bytes  (0x06064b50)
+     * size of zip64 end of central
+     * directory record                8 bytes
+     * version made by                 2 bytes
+     * version needed to extract       2 bytes
+     * number of this disk             4 bytes
+     * number of the disk with the
+     * start of the central directory  4 bytes
+     * total number of entries in the
+     * central directory on this disk  8 bytes
+     * total number of entries in the
+     * central directory               8 bytes
+     * size of the central directory   8 bytes
+     * offset of start of central
+     * directory with respect to
+     * the starting disk number        8 bytes
+     * zip64 extensible data sector    (variable size)
+     *
+     * @param int $zip64ECDPosition
+     *
+     * @throws ZipException
+     *
+     * @return EndOfCentralDirectory
+     */
+    protected function readZip64EndOfCentralDirectory($zip64ECDPosition)
+    {
+        fseek($this->in, $zip64ECDPosition);
+
+        $buffer = fread($this->in, 56 /* zip64 end of cd rec length */);
+
+        if (unpack('V', $buffer)[1] !== EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG) {
+            throw new ZipException('Expected ZIP64 End Of Central Directory Record!');
+        }
+
+        $data = unpack(
+            'VdiskNo/VcdDiskNo',
+            substr($buffer, 16)
+        );
+        $cdEntriesDisk = PackUtil::unpackLongLE(substr($buffer, 24, 8));
+        $entryCount = PackUtil::unpackLongLE(substr($buffer, 32, 8));
+        $cdSize = PackUtil::unpackLongLE(substr($buffer, 40, 8));
+        $cdPos = PackUtil::unpackLongLE(substr($buffer, 48, 8));
+
+        if ($data['diskNo'] !== 0 || $data['cdDiskNo'] !== 0 || $entryCount !== $cdEntriesDisk) {
+            throw new ZipException('ZIP file spanning/splitting is not supported!');
+        }
+
+        if ($entryCount < 0 || $entryCount > 0x7fffffff) {
+            throw new ZipException('Total Number Of Entries In The Central Directory out of range!');
+        }
+
+        // skip zip64 extensible data sector (variable sizeEndCD)
+
+        return new EndOfCentralDirectory(
+            $entryCount,
+            $cdPos,
+            $cdSize,
+            true
+        );
     }
 
     /**
@@ -268,123 +290,109 @@ class ZipInputStream implements ZipInputStreamInterface
      */
     protected function mountCentralDirectory(EndOfCentralDirectory $endOfCentralDirectory)
     {
-        $numEntries = $endOfCentralDirectory->getEntryCount();
         $entries = [];
 
-        for (; $numEntries > 0; $numEntries--) {
-            $entry = $this->readEntry();
-            // Re-load virtual offset after ZIP64 Extended Information
-            // Extra Field may have been parsed, map it to the real
-            // offset and conditionally update the preamble size from it.
-            $lfhOff = $this->mapper->map($entry->getOffset());
+        fseek($this->in, $endOfCentralDirectory->getCdOffset());
 
-            if ($lfhOff < $this->preamble) {
-                $this->preamble = $lfhOff;
-            }
-            $entries[$entry->getName()] = $entry;
-        }
-
-        if (($numEntries % 0x10000) !== 0) {
-            throw new ZipException(
-                'Expected ' . abs($numEntries) .
-                ($numEntries > 0 ? ' more' : ' less') .
-                ' entries in the Central Directory!'
-            );
+        if (!($cdStream = fopen('php://temp', 'w+b'))) {
+            throw new ZipException('Temp resource can not open from write');
         }
-
-        if ($this->preamble + $this->postamble >= fstat($this->in)['size']) {
-            $this->checkZipFileSignature();
+        stream_copy_to_stream($this->in, $cdStream, $endOfCentralDirectory->getCdSize());
+        rewind($cdStream);
+        for ($numEntries = $endOfCentralDirectory->getEntryCount(); $numEntries > 0; $numEntries--) {
+            $entry = $this->readCentralDirectoryEntry($cdStream);
+            $entries[$entry->getName()] = $entry;
         }
+        fclose($cdStream);
 
         return $entries;
     }
 
     /**
+     * Read central directory entry.
+     *
+     * central file header signature   4 bytes  (0x02014b50)
+     * version made by                 2 bytes
+     * version needed to extract       2 bytes
+     * general purpose bit flag        2 bytes
+     * compression method              2 bytes
+     * last mod file time              2 bytes
+     * last mod file date              2 bytes
+     * crc-32                          4 bytes
+     * compressed size                 4 bytes
+     * uncompressed size               4 bytes
+     * file name length                2 bytes
+     * extra field length              2 bytes
+     * file comment length             2 bytes
+     * disk number start               2 bytes
+     * internal file attributes        2 bytes
+     * external file attributes        4 bytes
+     * relative offset of local header 4 bytes
+     *
+     * file name (variable size)
+     * extra field (variable size)
+     * file comment (variable size)
+     *
+     * @param resource $stream
+     *
      * @throws ZipException
      *
      * @return ZipEntry
      */
-    public function readEntry()
+    public function readCentralDirectoryEntry($stream)
     {
-        // central file header signature   4 bytes  (0x02014b50)
-        $fileHeaderSig = unpack('V', fread($this->in, 4))[1];
-
-        if ($fileHeaderSig !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
-            throw new InvalidArgumentException('Corrupt zip file. Can not read zip entry.');
-        }
-
-        // version made by                 2 bytes
-        // version needed to extract       2 bytes
-        // general purpose bit flag        2 bytes
-        // compression method              2 bytes
-        // last mod file time              2 bytes
-        // last mod file date              2 bytes
-        // crc-32                          4 bytes
-        // compressed size                 4 bytes
-        // uncompressed size               4 bytes
-        // file name length                2 bytes
-        // extra field length              2 bytes
-        // file comment length             2 bytes
-        // disk number start               2 bytes
-        // internal file attributes        2 bytes
-        // external file attributes        4 bytes
-        // relative offset of local header 4 bytes
+        if (unpack('V', fread($stream, 4))[1] !== ZipOutputStreamInterface::CENTRAL_FILE_HEADER_SIG) {
+            throw new ZipException('Corrupt zip file. Cannot read central dir entry.');
+        }
+
         $data = unpack(
-            'vversionMadeBy/vversionNeededToExtract/vgpbf/' .
-            'vrawMethod/VrawTime/VrawCrc/VrawCompressedSize/' .
-            'VrawSize/vfileLength/vextraLength/vcommentLength/' .
-            'VrawInternalAttributes/VrawExternalAttributes/VlfhOff',
-            fread($this->in, 42)
+            'vversionMadeBy/vversionNeededToExtract/' .
+            'vgeneralPurposeBitFlag/vcompressionMethod/' .
+            'VlastModFile/Vcrc/VcompressedSize/' .
+            'VuncompressedSize/vfileNameLength/vextraFieldLength/' .
+            'vfileCommentLength/vdiskNumberStart/vinternalFileAttributes/' .
+            'VexternalFileAttributes/VoffsetLocalHeader',
+            fread($stream, 42)
         );
 
-//        $utf8 = ($data['gpbf'] & ZipEntry::GPBF_UTF8) !== 0;
+        $createdOS = ($data['versionMadeBy'] & 0xFF00) >> 8;
+        $softwareVersion = $data['versionMadeBy'] & 0x00FF;
 
-        // See appendix D of PKWARE's ZIP File Format Specification.
-        $name = '';
-        $offset = 0;
+        $extractOS = ($data['versionNeededToExtract'] & 0xFF00) >> 8;
+        $extractVersion = $data['versionNeededToExtract'] & 0x00FF;
 
-        while ($offset < $data['fileLength']) {
-            $read = min(8192 /* chunk size */, $data['fileLength'] - $offset);
-            $name .= fread($this->in, $read);
-            $offset += $read;
-        }
+        $name = fread($stream, $data['fileNameLength']);
 
-        $entry = new ZipSourceEntry($this);
-        $entry->setName($name);
-        $entry->setVersionNeededToExtract($data['versionNeededToExtract']);
-        $entry->setPlatform($data['versionMadeBy'] >> 8);
-        $entry->setMethod($data['rawMethod']);
-        $entry->setGeneralPurposeBitFlags($data['gpbf']);
-        $entry->setDosTime($data['rawTime']);
-        $entry->setCrc($data['rawCrc']);
-        $entry->setCompressedSize($data['rawCompressedSize']);
-        $entry->setSize($data['rawSize']);
-        $entry->setExternalAttributes($data['rawExternalAttributes']);
-        $entry->setOffset($data['lfhOff']); // must be unmapped!
-        if ($data['extraLength'] > 0) {
-            $extra = '';
-            $offset = 0;
+        $extra = '';
 
-            while ($offset < $data['extraLength']) {
-                $read = min(8192 /* chunk size */, $data['extraLength'] - $offset);
-                $extra .= fread($this->in, $read);
-                $offset += $read;
-            }
-            $entry->setExtra($extra);
+        if ($data['extraFieldLength'] > 0) {
+            $extra = fread($stream, $data['extraFieldLength']);
         }
 
-        if ($data['commentLength'] > 0) {
-            $comment = '';
-            $offset = 0;
+        $comment = null;
 
-            while ($offset < $data['commentLength']) {
-                $read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
-                $comment .= fread($this->in, $read);
-                $offset += $read;
-            }
-            $entry->setComment($comment);
+        if ($data['fileCommentLength'] > 0) {
+            $comment = fread($stream, $data['fileCommentLength']);
         }
 
+        $entry = new ZipSourceEntry($this);
+        $entry->setName($name);
+        $entry->setCreatedOS($createdOS);
+        $entry->setSoftwareVersion($softwareVersion);
+        $entry->setVersionNeededToExtract($extractVersion);
+        $entry->setExtractedOS($extractOS);
+        $entry->setMethod($data['compressionMethod']);
+        $entry->setGeneralPurposeBitFlags($data['generalPurposeBitFlag']);
+        $entry->setDosTime($data['lastModFile']);
+        $entry->setCrc($data['crc']);
+        $entry->setCompressedSize($data['compressedSize']);
+        $entry->setSize($data['uncompressedSize']);
+        $entry->setInternalAttributes($data['internalFileAttributes']);
+        $entry->setExternalAttributes($data['externalFileAttributes']);
+        $entry->setOffset($data['offsetLocalHeader']);
+        $entry->setComment($comment);
+        $entry->setExtra($extra);
+
         return $entry;
     }
 
@@ -410,9 +418,8 @@ class ZipInputStream implements ZipInputStreamInterface
             throw new ZipException('Can not password from entry ' . $entry->getName());
         }
 
-        $pos = $entry->getOffset();
+        $startPos = $pos = $entry->getOffset();
 
-        $startPos = $pos = $this->mapper->map($pos);
         fseek($this->in, $startPos);
 
         // local file header signature     4 bytes  (0x04034b50)
@@ -465,7 +472,7 @@ class ZipInputStream implements ZipInputStreamInterface
                 // Traditional PKWARE Decryption
                 $zipCryptoEngine = new TraditionalPkwareEncryptionEngine($entry);
                 $content = $zipCryptoEngine->decrypt($content);
-                $entry->setEncryptionMethod(ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+                $entry->setEncryptionMethod(ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
             }
 
             if (!$skipCheckCrc) {
@@ -500,15 +507,15 @@ class ZipInputStream implements ZipInputStreamInterface
         }
 
         switch ($method) {
-            case ZipFileInterface::METHOD_STORED:
+            case ZipFile::METHOD_STORED:
                 break;
 
-            case ZipFileInterface::METHOD_DEFLATED:
+            case ZipFile::METHOD_DEFLATED:
                 /** @noinspection PhpUsageOfSilenceOperatorInspection */
                 $content = @gzinflate($content);
                 break;
 
-            case ZipFileInterface::METHOD_BZIP2:
+            case ZipFile::METHOD_BZIP2:
                 if (!\extension_loaded('bz2')) {
                     throw new ZipException('Extension bzip2 not install');
                 }
@@ -589,8 +596,6 @@ class ZipInputStream implements ZipInputStreamInterface
             throw new ZipException(sprintf('Missing local header offset for entry %s', $entry->getName()));
         }
 
-        $pos = $this->mapper->map($pos);
-
         $nameLength = \strlen($entry->getName());
 
         fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);
@@ -625,7 +630,7 @@ class ZipInputStream implements ZipInputStreamInterface
         if (
             $this->zipModel->isZipAlign() &&
             !$entry->isEncrypted() &&
-            $entry->getMethod() === ZipFileInterface::METHOD_STORED
+            $entry->getMethod() === ZipFile::METHOD_STORED
         ) {
             if (StringUtil::endsWith($entry->getName(), '.so')) {
                 $dataAlignmentMultiple = ApkAlignmentExtraField::ANDROID_COMMON_PAGE_ALIGNMENT_BYTES;
@@ -688,7 +693,6 @@ class ZipInputStream implements ZipInputStreamInterface
     public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out)
     {
         $offset = $entry->getOffset();
-        $offset = $this->mapper->map($offset);
         $nameLength = \strlen($entry->getName());
 
         fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, \SEEK_SET);

+ 7 - 1
src/PhpZip/Stream/ZipInputStreamInterface.php

@@ -20,9 +20,15 @@ interface ZipInputStreamInterface
     public function readZip();
 
     /**
+     * Read central directory entry.
+     *
+     * @param resource $stream
+     *
+     * @throws ZipException
+     *
      * @return ZipEntry
      */
-    public function readEntry();
+    public function readCentralDirectoryEntry($stream);
 
     /**
      * @param ZipEntry $entry

+ 94 - 67
src/PhpZip/Stream/ZipOutputStream.php

@@ -19,7 +19,7 @@ use PhpZip\Model\ZipEntry;
 use PhpZip\Model\ZipModel;
 use PhpZip\Util\PackUtil;
 use PhpZip\Util\StringUtil;
-use PhpZip\ZipFileInterface;
+use PhpZip\ZipFile;
 
 /**
  * Write zip file.
@@ -97,7 +97,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
         if (
             $this->zipModel->isZipAlign() &&
             !$entry->isEncrypted() &&
-            $entry->getMethod() === ZipFileInterface::METHOD_STORED
+            $entry->getMethod() === ZipFile::METHOD_STORED
         ) {
             $dataAlignmentMultiple = $this->zipModel->getZipAlign();
 
@@ -144,7 +144,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
                 // local file header signature     4 bytes  (0x04034b50)
                 ZipEntry::LOCAL_FILE_HEADER_SIG,
                 // version needed to extract       2 bytes
-                $entry->getVersionNeededToExtract(),
+                ($entry->getExtractedOS() << 8) | $entry->getVersionNeededToExtract(),
                 // general purpose bit flag        2 bytes
                 $entry->getGeneralPurposeBitFlags(),
                 // compression method              2 bytes
@@ -221,8 +221,12 @@ class ZipOutputStream implements ZipOutputStreamInterface
      */
     protected function entryCommitChangesAndReturnContent(ZipEntry $entry)
     {
-        if ($entry->getPlatform() === ZipEntry::UNKNOWN) {
-            $entry->setPlatform(ZipEntry::PLATFORM_UNIX);
+        if ($entry->getCreatedOS() === ZipEntry::UNKNOWN) {
+            $entry->setCreatedOS(ZipEntry::PLATFORM_UNIX);
+        }
+
+        if ($entry->getExtractedOS() === ZipEntry::UNKNOWN) {
+            $entry->setExtractedOS(ZipEntry::PLATFORM_UNIX);
         }
 
         if ($entry->getTime() === ZipEntry::UNKNOWN) {
@@ -265,16 +269,15 @@ class ZipOutputStream implements ZipOutputStreamInterface
                 }
 
                 switch ($method) {
-                    case ZipFileInterface::METHOD_STORED:
+                    case ZipFile::METHOD_STORED:
                         break;
 
-                    case ZipFileInterface::METHOD_DEFLATED:
+                    case ZipFile::METHOD_DEFLATED:
                         $entryContent = gzdeflate($entryContent, $entry->getCompressionLevel());
                         break;
 
-                    case ZipFileInterface::METHOD_BZIP2:
-                        $compressionLevel = $entry->getCompressionLevel(
-                        ) === ZipFileInterface::LEVEL_DEFAULT_COMPRESSION ?
+                    case ZipFile::METHOD_BZIP2:
+                        $compressionLevel = $entry->getCompressionLevel() === ZipFile::LEVEL_DEFAULT_COMPRESSION ?
                             ZipEntry::LEVEL_DEFAULT_BZIP2_COMPRESSION :
                             $entry->getCompressionLevel();
                         /** @noinspection PhpComposerExtensionStubsInspection */
@@ -294,19 +297,19 @@ class ZipOutputStream implements ZipOutputStreamInterface
                         throw new ZipException($entry->getName() . ' (unsupported compression method ' . $method . ')');
                 }
 
-                if ($method === ZipFileInterface::METHOD_DEFLATED) {
+                if ($method === ZipFile::METHOD_DEFLATED) {
                     $bit1 = false;
                     $bit2 = false;
                     switch ($entry->getCompressionLevel()) {
-                        case ZipFileInterface::LEVEL_BEST_COMPRESSION:
+                        case ZipFile::LEVEL_BEST_COMPRESSION:
                             $bit1 = true;
                             break;
 
-                        case ZipFileInterface::LEVEL_FAST:
+                        case ZipFile::LEVEL_FAST:
                             $bit2 = true;
                             break;
 
-                        case ZipFileInterface::LEVEL_SUPER_FAST:
+                        case ZipFile::LEVEL_SUPER_FAST:
                             $bit1 = true;
                             $bit2 = true;
                             break;
@@ -320,9 +323,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
                     if (\in_array(
                         $entry->getEncryptionMethod(),
                         [
-                            ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128,
-                            ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192,
-                            ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256,
+                            ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128,
+                            ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192,
+                            ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256,
                         ],
                         true
                     )) {
@@ -334,7 +337,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
                         $field->setMethod($method);
                         $size = $entry->getSize();
 
-                        if ($size >= 20 && $method !== ZipFileInterface::METHOD_BZIP2) {
+                        if ($size >= 20 && $method !== ZipFile::METHOD_BZIP2) {
                             $field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_1);
                         } else {
                             $field->setVendorVersion(WinZipAesEntryExtraField::VV_AE_2);
@@ -345,7 +348,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
 
                         $winZipAesEngine = new WinZipAesEngine($entry);
                         $entryContent = $winZipAesEngine->encrypt($entryContent);
-                    } elseif ($entry->getEncryptionMethod() === ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL) {
+                    } elseif ($entry->getEncryptionMethod() === ZipFile::ENCRYPTION_METHOD_TRADITIONAL) {
                         $zipCryptoEngine = new TraditionalPkwareEncryptionEngine($entry);
                         $entryContent = $zipCryptoEngine->encrypt($entryContent);
                     }
@@ -382,11 +385,11 @@ class ZipOutputStream implements ZipOutputStreamInterface
             $entryContent = gzdeflate($content, $entry->getCompressionLevel());
 
             if (\strlen($entryContent) < \strlen($content)) {
-                $entry->setMethod(ZipFileInterface::METHOD_DEFLATED);
+                $entry->setMethod(ZipFile::METHOD_DEFLATED);
 
                 return $entryContent;
             }
-            $entry->setMethod(ZipFileInterface::METHOD_STORED);
+            $entry->setMethod(ZipFile::METHOD_STORED);
         }
 
         return $content;
@@ -418,9 +421,9 @@ class ZipOutputStream implements ZipOutputStreamInterface
                 // central file header signature   4 bytes  (0x02014b50)
                 self::CENTRAL_FILE_HEADER_SIG,
                 // version made by                 2 bytes
-                ($entry->getPlatform() << 8) | 63,
+                ($entry->getCreatedOS() << 8) | $entry->getSoftwareVersion(),
                 // version needed to extract       2 bytes
-                $entry->getVersionNeededToExtract(),
+                ($entry->getExtractedOS() << 8) | $entry->getVersionNeededToExtract(),
                 // general purpose bit flag        2 bytes
                 $entry->getGeneralPurposeBitFlags(),
                 // compression method              2 bytes
@@ -442,7 +445,7 @@ class ZipOutputStream implements ZipOutputStreamInterface
                 // disk number start               2 bytes
                 0,
                 // internal file attributes        2 bytes
-                0,
+                $entry->getInternalAttributes(),
                 // external file attributes        4 bytes
                 $entry->getExternalAttributes(),
                 // relative offset of local header 4 bytes
@@ -468,75 +471,99 @@ class ZipOutputStream implements ZipOutputStreamInterface
      */
     protected function writeEndOfCentralDirectoryRecord($centralDirectoryOffset)
     {
-        $centralDirectoryOffset = (int) $centralDirectoryOffset;
-        $centralDirectoryEntriesCount = \count($this->zipModel);
+        $cdEntriesCount = \count($this->zipModel);
+
         $position = ftell($this->out);
         $centralDirectorySize = $position - $centralDirectoryOffset;
-        $centralDirectoryEntriesZip64 = $centralDirectoryEntriesCount > 0xffff;
-        $centralDirectorySizeZip64 = $centralDirectorySize > 0xffffffff;
-        $centralDirectoryOffsetZip64 = $centralDirectoryOffset > 0xffffffff;
-        $centralDirectoryEntries16 = $centralDirectoryEntriesZip64 ? 0xffff : $centralDirectoryEntriesCount;
-        $centralDirectorySize32 = $centralDirectorySizeZip64 ? 0xffffffff : $centralDirectorySize;
-        $centralDirectoryOffset32 = $centralDirectoryOffsetZip64 ? 0xffffffff : $centralDirectoryOffset;
-        $zip64 // ZIP64 extensions?
-            = $centralDirectoryEntriesZip64
-            || $centralDirectorySizeZip64
-            || $centralDirectoryOffsetZip64;
-
-        if ($zip64) {
-            // [zip64 end of central directory record]
-            // relative offset of the zip64 end of central directory record
-            $zip64EndOfCentralDirectoryOffset = $position;
-            // zip64 end of central dir
+
+        $cdEntriesZip64 = $cdEntriesCount > 0xFFFF;
+        $cdSizeZip64 = $centralDirectorySize > 0xFFFFFFFF;
+        $cdOffsetZip64 = $centralDirectoryOffset > 0xFFFFFFFF;
+
+        $zip64Required = $cdEntriesZip64 || $cdSizeZip64 || $cdOffsetZip64;
+
+        if ($zip64Required) {
+            $zip64EndOfCentralDirectoryOffset = ftell($this->out);
+
+            // find max software version, version needed to extract and most common platform
+            list($softwareVersion, $versionNeededToExtract) = array_reduce(
+                $this->zipModel->getEntries(),
+                static function (array $carry, ZipEntry $entry) {
+                    $carry[0] = max($carry[0], $entry->getSoftwareVersion() & 0xFF);
+                    $carry[1] = max($carry[1], $entry->getVersionNeededToExtract() & 0xFF);
+
+                    return $carry;
+                },
+                [10 /* simple file min ver */, 45 /* zip64 ext min ver */]
+            );
+
+            $createdOS = $extractedOS = ZipEntry::PLATFORM_FAT;
+            $versionMadeBy = ($createdOS << 8) | max($softwareVersion, 45 /* zip64 ext min ver */);
+            $versionExtractedBy = ($extractedOS << 8) | max($versionNeededToExtract, 45 /* zip64 ext min ver */);
+
             // signature                       4 bytes  (0x06064b50)
-            fwrite($this->out, pack('V', EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG));
+            fwrite($this->out, pack('V', EndOfCentralDirectory::ZIP64_END_OF_CD_RECORD_SIG));
             // size of zip64 end of central
             // directory record                8 bytes
+            fwrite($this->out, PackUtil::packLongLE(44));
             fwrite(
                 $this->out,
-                PackUtil::packLongLE(EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_MIN_LEN - 12)
+                pack(
+                    'vvVV',
+                    // version made by                 2 bytes
+                    $versionMadeBy & 0xFFFF,
+                    // version needed to extract       2 bytes
+                    $versionExtractedBy & 0xFFFF,
+                    // number of this disk             4 bytes
+                    0,
+                    // number of the disk with the
+                    // start of the central directory  4 bytes
+                    0
+                )
             );
-            // version made by                 2 bytes
-            // version needed to extract       2 bytes
-            //                                 due to potential use of BZIP2 compression
-            // number of this disk             4 bytes
-            // number of the disk with the
-            // start of the central directory  4 bytes
-            fwrite($this->out, pack('vvVV', 63, 46, 0, 0));
             // total number of entries in the
             // central directory on this disk  8 bytes
-            fwrite($this->out, PackUtil::packLongLE($centralDirectoryEntriesCount));
+            fwrite($this->out, PackUtil::packLongLE($cdEntriesCount));
             // total number of entries in the
             // central directory               8 bytes
-            fwrite($this->out, PackUtil::packLongLE($centralDirectoryEntriesCount));
+            fwrite($this->out, PackUtil::packLongLE($cdEntriesCount));
             // size of the central directory   8 bytes
             fwrite($this->out, PackUtil::packLongLE($centralDirectorySize));
             // offset of start of central
             // directory with respect to
             // the starting disk number        8 bytes
             fwrite($this->out, PackUtil::packLongLE($centralDirectoryOffset));
-            // zip64 extensible data sector    (variable size)
-
-            // [zip64 end of central directory locator]
-            // signature                       4 bytes  (0x07064b50)
-            // number of the disk with the
-            // start of the zip64 end of
-            // central directory               4 bytes
-            fwrite($this->out, pack('VV', EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG, 0));
+
+            // write zip64 end of central directory locator
+            fwrite(
+                $this->out,
+                pack(
+                    'VV',
+                    // zip64 end of central dir locator
+                    // signature                       4 bytes  (0x07064b50)
+                    EndOfCentralDirectory::ZIP64_END_OF_CD_LOCATOR_SIG,
+                    // number of the disk with the
+                    // start of the zip64 end of
+                    // central directory               4 bytes
+                    0
+                )
+            );
             // relative offset of the zip64
             // end of central directory record 8 bytes
             fwrite($this->out, PackUtil::packLongLE($zip64EndOfCentralDirectoryOffset));
             // total number of disks           4 bytes
             fwrite($this->out, pack('V', 1));
         }
+
         $comment = $this->zipModel->getArchiveComment();
-        $commentLength = \strlen($comment);
+        $commentLength = $comment !== null ? \strlen($comment) : 0;
+
         fwrite(
             $this->out,
             pack(
                 'VvvvvVVv',
                 // end of central dir signature    4 bytes  (0x06054b50)
-                EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG,
+                EndOfCentralDirectory::END_OF_CD_SIG,
                 // number of this disk             2 bytes
                 0,
                 // number of the disk with the
@@ -544,16 +571,16 @@ class ZipOutputStream implements ZipOutputStreamInterface
                 0,
                 // total number of entries in the
                 // central directory on this disk  2 bytes
-                $centralDirectoryEntries16,
+                $cdEntriesZip64 ? 0xFFFF : $cdEntriesCount,
                 // total number of entries in
                 // the central directory           2 bytes
-                $centralDirectoryEntries16,
+                $cdEntriesZip64 ? 0xFFFF : $cdEntriesCount,
                 // size of the central directory   4 bytes
-                $centralDirectorySize32,
+                $cdSizeZip64 ? 0xFFFFFFFF : $centralDirectorySize,
                 // offset of start of central
                 // directory with respect to
                 // the starting disk number        4 bytes
-                $centralDirectoryOffset32,
+                $cdOffsetZip64 ? 0xFFFFFFFF : $centralDirectoryOffset,
                 // .ZIP file comment length        2 bytes
                 $commentLength
             )

+ 33 - 33
src/PhpZip/ZipFile.php

@@ -234,8 +234,8 @@ class ZipFile implements ZipFileInterface
      * @param string      $entryName
      * @param string|null $comment
      *
-     * @throws ZipEntryNotFoundException
      * @throws ZipException
+     * @throws ZipEntryNotFoundException
      *
      * @return ZipFileInterface
      */
@@ -277,8 +277,8 @@ class ZipFile implements ZipFileInterface
      *
      * @param string|ZipEntry $entryName
      *
-     * @throws ZipException
      * @throws ZipEntryNotFoundException
+     * @throws ZipException
      *
      * @return ZipInfo
      */
@@ -398,9 +398,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFromString($localName, $contents, $compressionMethod = null)
     {
@@ -454,9 +454,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFile($filename, $localName = null, $compressionMethod = null)
     {
@@ -520,9 +520,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFromStream($stream, $localName, $compressionMethod = null)
     {
@@ -655,9 +655,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null)
     {
@@ -693,9 +693,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFilesFromIterator(
         \Iterator $iterator,
@@ -1091,10 +1091,10 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
-     * @see ZipFileInterface::LEVEL_SUPER_FAST
-     * @see ZipFileInterface::LEVEL_FAST
-     * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+     * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+     * @see ZipFile::LEVEL_SUPER_FAST
+     * @see ZipFile::LEVEL_FAST
+     * @see ZipFile::LEVEL_BEST_COMPRESSION
      */
     public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION)
     {
@@ -1123,16 +1123,16 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
-     * @see ZipFileInterface::LEVEL_SUPER_FAST
-     * @see ZipFileInterface::LEVEL_FAST
-     * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+     * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+     * @see ZipFile::LEVEL_SUPER_FAST
+     * @see ZipFile::LEVEL_FAST
+     * @see ZipFile::LEVEL_BEST_COMPRESSION
      */
     public function setCompressionLevelEntry($entryName, $compressionLevel)
     {
         if ($compressionLevel !== null) {
-            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 ' .
@@ -1158,9 +1158,9 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function setCompressionMethodEntry($entryName, $compressionMethod)
     {
@@ -1204,7 +1204,7 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::setReadPassword()
+     * @deprecated using ZipFile::setReadPassword()
      */
     public function withReadPassword($password)
     {
@@ -1254,7 +1254,7 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::setPassword()
+     * @deprecated using ZipFile::setPassword()
      */
     public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256)
     {
@@ -1311,7 +1311,7 @@ class ZipFile implements ZipFileInterface
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::disableEncryption()
+     * @deprecated using ZipFile::disableEncryption()
      */
     public function withoutPassword()
     {

+ 29 - 29
src/PhpZip/ZipFileInterface.php

@@ -233,9 +233,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFromString($localName, $contents, $compressionMethod = null);
 
@@ -250,9 +250,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFile($filename, $localName = null, $compressionMethod = null);
 
@@ -267,9 +267,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFromStream($stream, $localName, $compressionMethod = null);
 
@@ -306,9 +306,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addDirRecursive($inputDir, $localPath = '/', $compressionMethod = null);
 
@@ -323,9 +323,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function addFilesFromIterator(\Iterator $iterator, $localPath = '/', $compressionMethod = null);
 
@@ -456,10 +456,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::LEVEL_SUPER_FAST
-     * @see ZipFileInterface::LEVEL_FAST
-     * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
-     * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+     * @see ZipFile::LEVEL_SUPER_FAST
+     * @see ZipFile::LEVEL_FAST
+     * @see ZipFile::LEVEL_BEST_COMPRESSION
+     * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
      */
     public function setCompressionLevel($compressionLevel = self::LEVEL_DEFAULT_COMPRESSION);
 
@@ -471,10 +471,10 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
-     * @see ZipFileInterface::LEVEL_SUPER_FAST
-     * @see ZipFileInterface::LEVEL_FAST
-     * @see ZipFileInterface::LEVEL_BEST_COMPRESSION
+     * @see ZipFile::LEVEL_DEFAULT_COMPRESSION
+     * @see ZipFile::LEVEL_SUPER_FAST
+     * @see ZipFile::LEVEL_FAST
+     * @see ZipFile::LEVEL_BEST_COMPRESSION
      */
     public function setCompressionLevelEntry($entryName, $compressionLevel);
 
@@ -486,9 +486,9 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @see ZipFileInterface::METHOD_STORED
-     * @see ZipFileInterface::METHOD_DEFLATED
-     * @see ZipFileInterface::METHOD_BZIP2
+     * @see ZipFile::METHOD_STORED
+     * @see ZipFile::METHOD_DEFLATED
+     * @see ZipFile::METHOD_BZIP2
      */
     public function setCompressionMethodEntry($entryName, $compressionMethod);
 
@@ -510,7 +510,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::setReadPassword()
+     * @deprecated using ZipFile::setReadPassword()
      */
     public function withReadPassword($password);
 
@@ -541,7 +541,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::setPassword()
+     * @deprecated using ZipFile::setPassword()
      */
     public function withNewPassword($password, $encryptionMethod = self::ENCRYPTION_METHOD_WINZIP_AES_256);
 
@@ -571,7 +571,7 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      *
      * @return ZipFileInterface
      *
-     * @deprecated using ZipFileInterface::disableEncryption()
+     * @deprecated using ZipFile::disableEncryption()
      */
     public function withoutPassword();
 

+ 6 - 11
tests/PhpZip/PhpZipExtResourceTest.php

@@ -127,7 +127,10 @@ class PhpZipExtResourceTest extends ZipTestCase
     public function testBug70752()
     {
         if (\PHP_INT_SIZE === 4) { // php 32 bit
-            $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+            $this->setExpectedException(
+                RuntimeException::class,
+                'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+            );
         } else { // php 64 bit
             $this->setExpectedException(
                 ZipAuthenticationException::class,
@@ -163,19 +166,11 @@ class PhpZipExtResourceTest extends ZipTestCase
      */
     public function testPecl12414()
     {
-        $filename = __DIR__ . '/php-zip-ext-test-resources/pecl12414.zip';
+        $this->setExpectedException(ZipException::class, 'Corrupt zip file. Cannot read central dir entry.');
 
-        $entryName = 'MYLOGOV2.GFX';
+        $filename = __DIR__ . '/php-zip-ext-test-resources/pecl12414.zip';
 
         $zipFile = new ZipFile();
         $zipFile->openFile($filename);
-
-        $info = $zipFile->getEntryInfo($entryName);
-        static::assertTrue($info->getSize() > 0);
-
-        $contents = $zipFile[$entryName];
-        static::assertSame(\strlen($contents), $info->getSize());
-
-        $zipFile->close();
     }
 }

+ 5 - 5
tests/PhpZip/ZipAlignTest.php

@@ -54,7 +54,7 @@ class ZipAlignTest extends ZipTestCase
             $zipFile->addFromString(
                 'entry' . $i . '.txt',
                 CryptoUtil::randomBytes(mt_rand(100, 4096)),
-                ZipFileInterface::METHOD_STORED
+                ZipFile::METHOD_STORED
             );
         }
         $zipFile->saveAsFile($this->outputFilename);
@@ -95,7 +95,7 @@ class ZipAlignTest extends ZipTestCase
             $zipFile->addFromString(
                 'entry' . $i . '.txt',
                 CryptoUtil::randomBytes(mt_rand(100, 4096)),
-                ZipFileInterface::METHOD_STORED
+                ZipFile::METHOD_STORED
             );
         }
         $zipFile->setZipAlign(4);
@@ -123,7 +123,7 @@ class ZipAlignTest extends ZipTestCase
             $zipFile->addFromString(
                 'entry' . $i . '.txt',
                 CryptoUtil::randomBytes(mt_rand(100, 4096)),
-                ZipFileInterface::METHOD_STORED
+                ZipFile::METHOD_STORED
             );
         }
         $zipFile->saveAsFile($this->outputFilename);
@@ -149,8 +149,8 @@ class ZipAlignTest extends ZipTestCase
                 'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
                 CryptoUtil::randomBytes(mt_rand(100, 4096)),
                 $isStored ?
-                    ZipFileInterface::METHOD_STORED :
-                    ZipFileInterface::METHOD_DEFLATED
+                    ZipFile::METHOD_STORED :
+                    ZipFile::METHOD_DEFLATED
             );
         }
         $zipFile->setZipAlign(4);

+ 25 - 25
tests/PhpZip/ZipFileTest.php

@@ -909,12 +909,12 @@ class ZipFileTest extends ZipTestCase
         $entries = [
             '1' => [
                 'data' => CryptoUtil::randomBytes(255),
-                'method' => ZipFileInterface::METHOD_STORED,
+                'method' => ZipFile::METHOD_STORED,
                 'expected' => 'No compression',
             ],
             '2' => [
                 'data' => CryptoUtil::randomBytes(255),
-                'method' => ZipFileInterface::METHOD_DEFLATED,
+                'method' => ZipFile::METHOD_DEFLATED,
                 'expected' => 'Deflate',
             ],
         ];
@@ -922,7 +922,7 @@ class ZipFileTest extends ZipTestCase
         if (\extension_loaded('bz2')) {
             $entries['3'] = [
                 'data' => CryptoUtil::randomBytes(255),
-                'method' => ZipFileInterface::METHOD_BZIP2,
+                'method' => ZipFile::METHOD_BZIP2,
                 'expected' => 'Bzip2',
             ];
         }
@@ -938,7 +938,7 @@ class ZipFileTest extends ZipTestCase
         static::assertCorrectZipArchive($this->outputFilename);
 
         $zipFile->openFile($this->outputFilename);
-        $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_COMPRESSION);
+        $zipFile->setCompressionLevel(ZipFile::LEVEL_BEST_COMPRESSION);
         $zipAllInfo = $zipFile->getAllInfo();
 
         foreach ($zipAllInfo as $entryName => $info) {
@@ -1693,14 +1693,14 @@ class ZipFileTest extends ZipTestCase
             $files['file' . $i . '.txt'] = CryptoUtil::randomBytes(255);
         }
 
-        $methods = [ZipFileInterface::METHOD_STORED, ZipFileInterface::METHOD_DEFLATED];
+        $methods = [ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED];
 
         if (\extension_loaded('bz2')) {
-            $methods[] = ZipFileInterface::METHOD_BZIP2;
+            $methods[] = ZipFile::METHOD_BZIP2;
         }
 
         $zipFile = new ZipFile();
-        $zipFile->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED);
+        $zipFile->setCompressionLevel(ZipFile::LEVEL_BEST_SPEED);
 
         foreach ($files as $entryName => $content) {
             $zipFile->addFromString($entryName, $content, $methods[array_rand($methods)]);
@@ -1985,14 +1985,14 @@ class ZipFileTest extends ZipTestCase
     {
         $zipFile = new ZipFile();
         $zipFile
-            ->addFromString('file', 'content', ZipFileInterface::METHOD_DEFLATED)
-            ->setCompressionLevelEntry('file', ZipFileInterface::LEVEL_BEST_COMPRESSION)
-            ->addFromString('file2', 'content', ZipFileInterface::METHOD_DEFLATED)
-            ->setCompressionLevelEntry('file2', ZipFileInterface::LEVEL_FAST)
-            ->addFromString('file3', 'content', ZipFileInterface::METHOD_DEFLATED)
-            ->setCompressionLevelEntry('file3', ZipFileInterface::LEVEL_SUPER_FAST)
-            ->addFromString('file4', 'content', ZipFileInterface::METHOD_DEFLATED)
-            ->setCompressionLevelEntry('file4', ZipFileInterface::LEVEL_DEFAULT_COMPRESSION)
+            ->addFromString('file', 'content', ZipFile::METHOD_DEFLATED)
+            ->setCompressionLevelEntry('file', ZipFile::LEVEL_BEST_COMPRESSION)
+            ->addFromString('file2', 'content', ZipFile::METHOD_DEFLATED)
+            ->setCompressionLevelEntry('file2', ZipFile::LEVEL_FAST)
+            ->addFromString('file3', 'content', ZipFile::METHOD_DEFLATED)
+            ->setCompressionLevelEntry('file3', ZipFile::LEVEL_SUPER_FAST)
+            ->addFromString('file4', 'content', ZipFile::METHOD_DEFLATED)
+            ->setCompressionLevelEntry('file4', ZipFile::LEVEL_DEFAULT_COMPRESSION)
             ->saveAsFile($this->outputFilename)
             ->close()
         ;
@@ -2003,22 +2003,22 @@ class ZipFileTest extends ZipTestCase
         static::assertSame(
             $zipFile->getEntryInfo('file')
                 ->getCompressionLevel(),
-            ZipFileInterface::LEVEL_BEST_COMPRESSION
+            ZipFile::LEVEL_BEST_COMPRESSION
         );
         static::assertSame(
             $zipFile->getEntryInfo('file2')
                 ->getCompressionLevel(),
-            ZipFileInterface::LEVEL_FAST
+            ZipFile::LEVEL_FAST
         );
         static::assertSame(
             $zipFile->getEntryInfo('file3')
                 ->getCompressionLevel(),
-            ZipFileInterface::LEVEL_SUPER_FAST
+            ZipFile::LEVEL_SUPER_FAST
         );
         static::assertSame(
             $zipFile->getEntryInfo('file4')
                 ->getCompressionLevel(),
-            ZipFileInterface::LEVEL_DEFAULT_COMPRESSION
+            ZipFile::LEVEL_DEFAULT_COMPRESSION
         );
         $zipFile->close();
     }
@@ -2054,10 +2054,10 @@ class ZipFileTest extends ZipTestCase
     {
         $zipFile = new ZipFile();
         for ($i = 0; $i < 10; $i++) {
-            $zipFile->addFromString('file' . $i, 'content', ZipFileInterface::METHOD_DEFLATED);
+            $zipFile->addFromString('file' . $i, 'content', ZipFile::METHOD_DEFLATED);
         }
         $zipFile
-            ->setCompressionLevel(ZipFileInterface::LEVEL_BEST_SPEED)
+            ->setCompressionLevel(ZipFile::LEVEL_BEST_SPEED)
             ->saveAsFile($this->outputFilename)
             ->close()
         ;
@@ -2069,7 +2069,7 @@ class ZipFileTest extends ZipTestCase
         array_walk(
             $infoList,
             function (ZipInfo $zipInfo) {
-                $this->assertSame($zipInfo->getCompressionLevel(), ZipFileInterface::LEVEL_BEST_SPEED);
+                $this->assertSame($zipInfo->getCompressionLevel(), ZipFile::LEVEL_BEST_SPEED);
             }
         );
         $zipFile->close();
@@ -2082,13 +2082,13 @@ class ZipFileTest extends ZipTestCase
     public function testCompressionMethodEntry()
     {
         $zipFile = new ZipFile();
-        $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+        $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
         $zipFile->saveAsFile($this->outputFilename);
         $zipFile->close();
 
         $zipFile->openFile($this->outputFilename);
         static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'No compression');
-        $zipFile->setCompressionMethodEntry('file', ZipFileInterface::METHOD_DEFLATED);
+        $zipFile->setCompressionMethodEntry('file', ZipFile::METHOD_DEFLATED);
         static::assertSame($zipFile->getEntryInfo('file')->getMethodName(), 'Deflate');
 
         $zipFile->rewrite();
@@ -2103,7 +2103,7 @@ class ZipFileTest extends ZipTestCase
         $this->setExpectedException(ZipUnsupportMethodException::class, 'Unsupported method');
 
         $zipFile = new ZipFile();
-        $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+        $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
         $zipFile->setCompressionMethodEntry('file', 99);
     }
 

+ 10 - 2
tests/PhpZip/ZipMatcherTest.php

@@ -38,8 +38,16 @@ class ZipMatcherTest extends TestCase
         $matcher->match('~^[2][1-5]|[3][6-9]|40$~s');
         static::assertCount(10, $matcher);
         $actualMatches = [
-            '21', '22', '23', '24', '25',
-            '36', '37', '38', '39', '40',
+            '21',
+            '22',
+            '23',
+            '24',
+            '25',
+            '36',
+            '37',
+            '38',
+            '39',
+            '40',
         ];
         static::assertSame($matcher->getMatches(), $actualMatches);
         $matcher->setPassword('qwerty');

+ 29 - 16
tests/PhpZip/ZipPasswordTest.php

@@ -22,11 +22,15 @@ class ZipPasswordTest extends ZipFileAddDirTest
      * Test archive password.
      *
      * @throws ZipException
+     * @noinspection PhpRedundantCatchClauseInspection
      */
     public function testSetPassword()
     {
         if (\PHP_INT_SIZE === 4) { // php 32 bit
-            $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+            $this->setExpectedException(
+                RuntimeException::class,
+                'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+            );
         }
 
         $password = base64_encode(CryptoUtil::randomBytes(100));
@@ -35,7 +39,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
         // create encryption password with ZipCrypto
         $zipFile = new ZipFile();
         $zipFile->addDir(__DIR__);
-        $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+        $zipFile->setPassword($password, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
         $zipFile->saveAsFile($this->outputFilename);
         $zipFile->close();
 
@@ -66,7 +70,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
         }
 
         // change encryption method to WinZip Aes and update file
-        $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+        $zipFile->setPassword($password, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
         $zipFile->saveAsFile($this->outputFilename);
         $zipFile->close();
 
@@ -121,14 +125,17 @@ class ZipPasswordTest extends ZipFileAddDirTest
     public function testTraditionalEncryption()
     {
         if (\PHP_INT_SIZE === 4) { // php 32 bit
-            $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+            $this->setExpectedException(
+                RuntimeException::class,
+                'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+            );
         }
 
         $password = base64_encode(CryptoUtil::randomBytes(50));
 
         $zip = new ZipFile();
         $zip->addDirRecursive($this->outputDirname);
-        $zip->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
+        $zip->setPassword($password, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
         $zip->saveAsFile($this->outputFilename);
         $zip->close();
 
@@ -187,10 +194,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
     public function winZipKeyStrengthProvider()
     {
         return [
-            [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
-            [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
-            [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES, 256],
-            [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
+            [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
+            [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
+            [ZipFile::ENCRYPTION_METHOD_WINZIP_AES, 256],
+            [ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
         ];
     }
 
@@ -201,7 +208,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
     public function testEncryptionEntries()
     {
         if (\PHP_INT_SIZE === 4) { // php 32 bit
-            $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+            $this->setExpectedException(
+                RuntimeException::class,
+                'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+            );
         }
 
         $password1 = '353442434235424234';
@@ -209,8 +219,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
 
         $zip = new ZipFile();
         $zip->addDir($this->outputDirname);
-        $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
-        $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+        $zip->setPasswordEntry('.hidden', $password1, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
+        $zip->setPasswordEntry('text file.txt', $password2, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
         $zip->saveAsFile($this->outputFilename);
         $zip->close();
 
@@ -248,7 +258,10 @@ class ZipPasswordTest extends ZipFileAddDirTest
     public function testEncryptionEntriesWithDefaultPassword()
     {
         if (\PHP_INT_SIZE === 4) { // php 32 bit
-            $this->setExpectedException(RuntimeException::class, 'Traditional PKWARE Encryption is not supported in 32-bit PHP.');
+            $this->setExpectedException(
+                RuntimeException::class,
+                'Traditional PKWARE Encryption is not supported in 32-bit PHP.'
+            );
         }
 
         $password1 = '353442434235424234';
@@ -258,8 +271,8 @@ class ZipPasswordTest extends ZipFileAddDirTest
         $zip = new ZipFile();
         $zip->addDir($this->outputDirname);
         $zip->setPassword($defaultPassword);
-        $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
-        $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
+        $zip->setPasswordEntry('.hidden', $password1, ZipFile::ENCRYPTION_METHOD_TRADITIONAL);
+        $zip->setPasswordEntry('text file.txt', $password2, ZipFile::ENCRYPTION_METHOD_WINZIP_AES);
         $zip->saveAsFile($this->outputFilename);
         $zip->close();
 
@@ -350,7 +363,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
         $this->setExpectedException(ZipException::class, 'Invalid encryption method');
 
         $zipFile = new ZipFile();
-        $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
+        $zipFile->addFromString('file', 'content', ZipFile::METHOD_STORED);
         $zipFile->setPasswordEntry('file', 'pass', 99);
     }
 

+ 1 - 1
tests/PhpZip/ZipTestCase.php

@@ -129,7 +129,7 @@ abstract class ZipTestCase extends TestCase
 
             static::assertContains('Empty zipfile', $output);
         }
-        $actualEmptyZipData = pack('VVVVVv', EndOfCentralDirectory::END_OF_CENTRAL_DIRECTORY_RECORD_SIG, 0, 0, 0, 0, 0);
+        $actualEmptyZipData = pack('VVVVVv', EndOfCentralDirectory::END_OF_CD_SIG, 0, 0, 0, 0, 0);
         static::assertStringEqualsFile($filename, $actualEmptyZipData);
     }