Explorar o código

Merge tag '3.2.1' into develop

Tagging hotfix 3.2.1 3.2.1
Ne-Lexa %!s(int64=6) %!d(string=hai) anos
pai
achega
e0da8c94be

+ 1 - 1
.gitignore

@@ -2,4 +2,4 @@
 *.iml
 /.idea
 /composer.lock
-/.php_cs.cache
+/*.cache

+ 18 - 0
.phpstorm.meta.php

@@ -107,4 +107,22 @@ namespace PHPSTORM_META {
         \PhpZip\Constants\GeneralPurposeBitFlag::UTF8
     );
     expectedArguments(\PhpZip\Model\ZipEntry::setGeneralPurposeBitFlags(), 0, argumentsSet('zip_gpbf'));
+
+    registerArgumentsSet(
+        "winzip_aes_vendor_version",
+        \PhpZip\Model\Extra\Fields\WinZipAesExtraField::VERSION_AE1,
+        \PhpZip\Model\Extra\Fields\WinZipAesExtraField::VERSION_AE2
+    );
+    registerArgumentsSet(
+        "winzip_aes_key_strength",
+        \PhpZip\Model\Extra\Fields\WinZipAesExtraField::KEY_STRENGTH_256BIT,
+        \PhpZip\Model\Extra\Fields\WinZipAesExtraField::KEY_STRENGTH_128BIT,
+        \PhpZip\Model\Extra\Fields\WinZipAesExtraField::KEY_STRENGTH_192BIT
+    );
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::__construct(), 0, argumentsSet('winzip_aes_vendor_version'));
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::__construct(), 1, argumentsSet('winzip_aes_key_strength'));
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::__construct(), 2, argumentsSet('compression_methods'));
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::setVendorVersion(), 0, argumentsSet('winzip_aes_vendor_version'));
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::setKeyStrength(), 0, argumentsSet('winzip_aes_key_strength'));
+    expectedArguments(\PhpZip\Model\Extra\Fields\WinZipAesExtraField::setCompressionMethod(), 0, argumentsSet('compression_methods'));
 }

+ 16 - 18
src/IO/ZipReader.php

@@ -366,7 +366,7 @@ class ZipReader
             /** @var UnicodePathExtraField|null $unicodePathExtraField */
             $unicodePathExtraField = $zipEntry->getExtraField(UnicodePathExtraField::HEADER_ID);
 
-            if ($unicodePathExtraField !== null) {
+            if ($unicodePathExtraField !== null && $unicodePathExtraField->getCrc32() === crc32($entryName)) {
                 $unicodePath = $unicodePathExtraField->getUnicodeValue();
 
                 if ($unicodePath !== null) {
@@ -543,25 +543,23 @@ class ZipReader
                 /** @var string|ZipExtraField|null $className */
                 $className = ZipExtraDriver::getClassNameOrNull($headerId);
 
-                if ($className !== null) {
-                    try {
-                        $extraField = $local ?
-                            \call_user_func([$className, 'unpackLocalFileData'], $bufferData, $zipEntry) :
-                            \call_user_func([$className, 'unpackCentralDirData'], $bufferData, $zipEntry);
-                    } catch (\Throwable $e) {
-                        throw new \RuntimeException(
-                            sprintf(
-                                'Error parse %s extra field 0x%04X',
-                                $local ? 'local' : 'central directory',
-                                $headerId
-                            )
-                        );
+                try {
+                    if ($className !== null) {
+                        try {
+                            $extraField = $local ?
+                                \call_user_func([$className, 'unpackLocalFileData'], $bufferData, $zipEntry) :
+                                \call_user_func([$className, 'unpackCentralDirData'], $bufferData, $zipEntry);
+                        } catch (\Throwable $e) {
+                            // skip errors while parsing invalid data
+                            continue;
+                        }
+                    } else {
+                        $extraField = new UnrecognizedExtraField($headerId, $bufferData);
                     }
-                } else {
-                    $extraField = new UnrecognizedExtraField($headerId, $bufferData);
+                    $collection->add($extraField);
+                } finally {
+                    $pos += $data['dataSize'];
                 }
-                $collection->add($extraField);
-                $pos += $data['dataSize'];
             }
         }
 

+ 12 - 16
src/Model/Extra/Fields/AbstractUnicodeExtraField.php

@@ -30,22 +30,20 @@ abstract class AbstractUnicodeExtraField implements ZipExtraField
     }
 
     /**
-     * @param string $unicodeValue
-     *
-     * @return static
+     * @return int the CRC32 checksum of the filename or comment as
+     *             encoded in the central directory of the zip file
      */
-    public static function create($unicodeValue)
+    public function getCrc32()
     {
-        return new static(crc32($unicodeValue), $unicodeValue);
+        return $this->crc32;
     }
 
     /**
-     * @return int the CRC32 checksum of the filename or comment as
-     *             encoded in the central directory of the zip file
+     * @param int $crc32
      */
-    public function getCrc32()
+    public function setCrc32($crc32)
     {
-        return $this->crc32;
+        $this->crc32 = (int) $crc32;
     }
 
     /**
@@ -62,7 +60,6 @@ abstract class AbstractUnicodeExtraField implements ZipExtraField
     public function setUnicodeValue($unicodeValue)
     {
         $this->unicodeValue = $unicodeValue;
-        $this->crc32 = crc32($unicodeValue);
     }
 
     /**
@@ -78,19 +75,18 @@ abstract class AbstractUnicodeExtraField implements ZipExtraField
     public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
     {
         if (\strlen($buffer) < 5) {
-            throw new ZipException('UniCode path extra data must have at least 5 bytes.');
+            throw new ZipException('Unicode path extra data must have at least 5 bytes.');
         }
 
-        $version = unpack('C', $buffer)[1];
+        $data = unpack('Cversion/Vcrc32', $buffer);
 
-        if ($version !== self::DEFAULT_VERSION) {
-            throw new ZipException(sprintf('Unsupported version [%d] for UniCode path extra data.', $version));
+        if ($data['version'] !== self::DEFAULT_VERSION) {
+            throw new ZipException(sprintf('Unsupported version [%d] for Unicode path extra data.', $data['version']));
         }
 
-        $crc32 = unpack('V', substr($buffer, 1))[1];
         $unicodeValue = substr($buffer, 5);
 
-        return new static($crc32, $unicodeValue);
+        return new static($data['crc32'], $unicodeValue);
     }
 
     /**

+ 12 - 10
src/Model/Extra/Fields/AsiExtraField.php

@@ -79,10 +79,10 @@ class AsiExtraField implements ZipExtraField
      */
     public function __construct($mode, $uid = self::USER_GID_PID, $gid = self::USER_GID_PID, $link = '')
     {
-        $this->mode = (int) $mode;
-        $this->uid = (int) $uid;
-        $this->gid = (int) $gid;
-        $this->link = (string) $link;
+        $this->mode = $mode;
+        $this->uid = $uid;
+        $this->gid = $gid;
+        $this->link = $link;
     }
 
     /**
@@ -121,7 +121,7 @@ class AsiExtraField implements ZipExtraField
         $link = '';
 
         if ($data['linkSize'] > 0) {
-            $link = substr($buffer, 8);
+            $link = substr($buffer, 10);
         }
 
         return new self($data['mode'], $data['uid'], $data['gid'], $link);
@@ -191,7 +191,7 @@ class AsiExtraField implements ZipExtraField
      */
     public function setLink($link)
     {
-        $this->link = $link;
+        $this->link = (string) $link;
         $this->mode = $this->getPermissionsMode($this->mode);
     }
 
@@ -214,11 +214,13 @@ class AsiExtraField implements ZipExtraField
      */
     protected function getPermissionsMode($mode)
     {
-        $type = UnixStat::UNX_IFMT;
+        $type = 0;
 
         if ($this->isLink()) {
             $type = UnixStat::UNX_IFLNK;
-        } elseif ($this->isDirectory()) {
+        } elseif (($mode & UnixStat::UNX_IFREG) !== 0) {
+            $type = UnixStat::UNX_IFREG;
+        } elseif (($mode & UnixStat::UNX_IFDIR) !== 0) {
             $type = UnixStat::UNX_IFDIR;
         }
 
@@ -264,7 +266,7 @@ class AsiExtraField implements ZipExtraField
      */
     public function setUserId($uid)
     {
-        $this->uid = $uid;
+        $this->uid = (int) $uid;
     }
 
     /**
@@ -280,7 +282,7 @@ class AsiExtraField implements ZipExtraField
      */
     public function setGroupId($gid)
     {
-        $this->gid = $gid;
+        $this->gid = (int) $gid;
     }
 
     /**

+ 21 - 0
src/Model/Extra/Fields/ExtendedTimestampExtraField.php

@@ -359,6 +359,25 @@ class ExtendedTimestampExtraField implements ZipExtraField
     public function setModifyTime($unixTime)
     {
         $this->modifyTime = $unixTime;
+        $this->updateFlags();
+    }
+
+    private function updateFlags()
+    {
+        $flags = 0;
+
+        if ($this->modifyTime !== null) {
+            $flags |= self::MODIFY_TIME_BIT;
+        }
+
+        if ($this->accessTime !== null) {
+            $flags |= self::ACCESS_TIME_BIT;
+        }
+
+        if ($this->createTime !== null) {
+            $flags |= self::CREATE_TIME_BIT;
+        }
+        $this->flags = $flags;
     }
 
     /**
@@ -370,6 +389,7 @@ class ExtendedTimestampExtraField implements ZipExtraField
     public function setAccessTime($unixTime)
     {
         $this->accessTime = $unixTime;
+        $this->updateFlags();
     }
 
     /**
@@ -381,6 +401,7 @@ class ExtendedTimestampExtraField implements ZipExtraField
     public function setCreateTime($unixTime)
     {
         $this->createTime = $unixTime;
+        $this->updateFlags();
     }
 
     /**

+ 11 - 22
src/Model/Extra/Fields/NewUnixExtraField.php

@@ -115,25 +115,6 @@ class NewUnixExtraField implements ZipExtraField
         return new self($data['version'], $gid, $uid);
     }
 
-    /**
-     * Converts a signed byte into an unsigned integer representation
-     * (e.g., -1 becomes 255).
-     *
-     * @param int $b byte to convert to int
-     *
-     * @return int representation of the provided byte
-     *
-     * @since 1.5
-     */
-    public static function signedByteToUnsignedInt($b)
-    {
-        if ($b >= 0) {
-            return $b;
-        }
-
-        return 256 + $b;
-    }
-
     /**
      * Populate data from this array as if it was in central directory data.
      *
@@ -160,10 +141,10 @@ class NewUnixExtraField implements ZipExtraField
         return pack(
             'CCVCV',
             $this->version,
-            4, // GIDSize
-            $this->gid,
             4, // UIDSize
-            $this->uid
+            $this->uid,
+            4, // GIDSize
+            $this->gid
         );
     }
 
@@ -233,6 +214,14 @@ class NewUnixExtraField implements ZipExtraField
         $this->gid = $gid & 0xffffffff;
     }
 
+    /**
+     * @return int
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
     /**
      * @return string
      */

+ 121 - 40
src/Model/Extra/Fields/NtfsExtraField.php

@@ -3,6 +3,7 @@
 namespace PhpZip\Model\Extra\Fields;
 
 use PhpZip\Exception\InvalidArgumentException;
+use PhpZip\Exception\ZipException;
 use PhpZip\Model\Extra\ZipExtraField;
 use PhpZip\Model\ZipEntry;
 use PhpZip\Util\PackUtil;
@@ -10,7 +11,7 @@ use PhpZip\Util\PackUtil;
 /**
  * NTFS Extra Field.
  *
- * @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
+ * @see     https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
  *
  * @license MIT
  */
@@ -31,42 +32,45 @@ class NtfsExtraField implements ZipExtraField
      *          A.M. January 1, 1601 Coordinated Universal Time (UTC).
      *          this is the offset of Windows time 0 to Unix epoch in 100-nanosecond intervals.
      */
-    const EPOCH_OFFSET = -11644473600;
+    const EPOCH_OFFSET = -116444736000000000;
 
     /** @var int Modify ntfs time */
-    private $modifyTime;
+    private $modifyNtfsTime;
 
     /** @var int Access ntfs time */
-    private $accessTime;
+    private $accessNtfsTime;
 
     /** @var int Create ntfs time */
-    private $createTime;
+    private $createNtfsTime;
 
     /**
-     * @param int $modifyTime
-     * @param int $accessTime
-     * @param int $createTime
+     * @param int $modifyNtfsTime
+     * @param int $accessNtfsTime
+     * @param int $createNtfsTime
      */
-    public function __construct($modifyTime, $accessTime, $createTime)
+    public function __construct($modifyNtfsTime, $accessNtfsTime, $createNtfsTime)
     {
-        $this->modifyTime = (int) $modifyTime;
-        $this->accessTime = (int) $accessTime;
-        $this->createTime = (int) $createTime;
+        $this->modifyNtfsTime = (int) $modifyNtfsTime;
+        $this->accessNtfsTime = (int) $accessNtfsTime;
+        $this->createNtfsTime = (int) $createNtfsTime;
     }
 
     /**
-     * @param \DateTimeInterface $mtime
-     * @param \DateTimeInterface $atime
-     * @param \DateTimeInterface $ctime
+     * @param \DateTimeInterface $modifyDateTime
+     * @param \DateTimeInterface $accessDateTime
+     * @param \DateTimeInterface $createNtfsTime
      *
      * @return NtfsExtraField
      */
-    public static function create(\DateTimeInterface $mtime, \DateTimeInterface $atime, \DateTimeInterface $ctime)
-    {
+    public static function create(
+        \DateTimeInterface $modifyDateTime,
+        \DateTimeInterface $accessDateTime,
+        \DateTimeInterface $createNtfsTime
+    ) {
         return new self(
-            self::dateTimeToNtfsTime($mtime),
-            self::dateTimeToNtfsTime($atime),
-            self::dateTimeToNtfsTime($ctime)
+            self::dateTimeToNtfsTime($modifyDateTime),
+            self::dateTimeToNtfsTime($accessDateTime),
+            self::dateTimeToNtfsTime($createNtfsTime)
         );
     }
 
@@ -88,10 +92,16 @@ class NtfsExtraField implements ZipExtraField
      * @param string        $buffer the buffer to read data from
      * @param ZipEntry|null $entry
      *
+     * @throws ZipException
+     *
      * @return NtfsExtraField
      */
     public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
     {
+        if (\PHP_INT_SIZE === 4) {
+            throw new ZipException('not supported for php-32bit');
+        }
+
         $buffer = substr($buffer, 4);
 
         $modifyTime = 0;
@@ -121,6 +131,8 @@ class NtfsExtraField implements ZipExtraField
      * @param string        $buffer the buffer to read data from
      * @param ZipEntry|null $entry
      *
+     * @throws ZipException
+     *
      * @return NtfsExtraField
      */
     public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
@@ -138,13 +150,61 @@ class NtfsExtraField implements ZipExtraField
     {
         $data = pack('Vvv', 0, self::TIME_ATTR_TAG, self::TIME_ATTR_SIZE);
         // refactoring will be needed when php 5.5 support ends
-        $data .= PackUtil::packLongLE($this->modifyTime);
-        $data .= PackUtil::packLongLE($this->accessTime);
-        $data .= PackUtil::packLongLE($this->createTime);
+        $data .= PackUtil::packLongLE($this->modifyNtfsTime);
+        $data .= PackUtil::packLongLE($this->accessNtfsTime);
+        $data .= PackUtil::packLongLE($this->createNtfsTime);
 
         return $data;
     }
 
+    /**
+     * @return int
+     */
+    public function getModifyNtfsTime()
+    {
+        return $this->modifyNtfsTime;
+    }
+
+    /**
+     * @param int $modifyNtfsTime
+     */
+    public function setModifyNtfsTime($modifyNtfsTime)
+    {
+        $this->modifyNtfsTime = (int) $modifyNtfsTime;
+    }
+
+    /**
+     * @return int
+     */
+    public function getAccessNtfsTime()
+    {
+        return $this->accessNtfsTime;
+    }
+
+    /**
+     * @param int $accessNtfsTime
+     */
+    public function setAccessNtfsTime($accessNtfsTime)
+    {
+        $this->accessNtfsTime = (int) $accessNtfsTime;
+    }
+
+    /**
+     * @return int
+     */
+    public function getCreateNtfsTime()
+    {
+        return $this->createNtfsTime;
+    }
+
+    /**
+     * @param int $createNtfsTime
+     */
+    public function setCreateNtfsTime($createNtfsTime)
+    {
+        $this->createNtfsTime = (int) $createNtfsTime;
+    }
+
     /**
      * The actual data to put into central directory - without Header-ID or
      * length specifier.
@@ -161,7 +221,7 @@ class NtfsExtraField implements ZipExtraField
      */
     public function getModifyDateTime()
     {
-        return self::ntfsTimeToDateTime($this->modifyTime);
+        return self::ntfsTimeToDateTime($this->modifyNtfsTime);
     }
 
     /**
@@ -169,7 +229,7 @@ class NtfsExtraField implements ZipExtraField
      */
     public function setModifyDateTime(\DateTimeInterface $modifyTime)
     {
-        $this->modifyTime = self::dateTimeToNtfsTime($modifyTime);
+        $this->modifyNtfsTime = self::dateTimeToNtfsTime($modifyTime);
     }
 
     /**
@@ -177,7 +237,7 @@ class NtfsExtraField implements ZipExtraField
      */
     public function getAccessDateTime()
     {
-        return self::ntfsTimeToDateTime($this->accessTime);
+        return self::ntfsTimeToDateTime($this->accessNtfsTime);
     }
 
     /**
@@ -185,7 +245,7 @@ class NtfsExtraField implements ZipExtraField
      */
     public function setAccessDateTime(\DateTimeInterface $accessTime)
     {
-        $this->accessTime = self::dateTimeToNtfsTime($accessTime);
+        $this->accessNtfsTime = self::dateTimeToNtfsTime($accessTime);
     }
 
     /**
@@ -193,7 +253,7 @@ class NtfsExtraField implements ZipExtraField
      */
     public function getCreateDateTime()
     {
-        return self::ntfsTimeToDateTime($this->createTime);
+        return self::ntfsTimeToDateTime($this->createNtfsTime);
     }
 
     /**
@@ -201,7 +261,17 @@ class NtfsExtraField implements ZipExtraField
      */
     public function setCreateDateTime(\DateTimeInterface $createTime)
     {
-        $this->createTime = self::dateTimeToNtfsTime($createTime);
+        $this->createNtfsTime = self::dateTimeToNtfsTime($createTime);
+    }
+
+    /**
+     * @param float $timestamp Float timestamp
+     *
+     * @return int
+     */
+    public static function timestampToNtfsTime($timestamp)
+    {
+        return (int) (((float) $timestamp * 10000000) - self::EPOCH_OFFSET);
     }
 
     /**
@@ -211,23 +281,34 @@ class NtfsExtraField implements ZipExtraField
      */
     public static function dateTimeToNtfsTime(\DateTimeInterface $dateTime)
     {
-        return $dateTime->getTimestamp() * 10000000 + self::EPOCH_OFFSET;
+        return self::timestampToNtfsTime((float) $dateTime->format('U.u'));
     }
 
     /**
-     * @param int $time
+     * @param int $ntfsTime
+     *
+     * @return float Float unix timestamp
+     */
+    public static function ntfsTimeToTimestamp($ntfsTime)
+    {
+        return (float) (($ntfsTime + self::EPOCH_OFFSET) / 10000000);
+    }
+
+    /**
+     * @param int $ntfsTime
      *
      * @return \DateTimeInterface
      */
-    public static function ntfsTimeToDateTime($time)
+    public static function ntfsTimeToDateTime($ntfsTime)
     {
-        $timestamp = (int) ($time / 10000000 + self::EPOCH_OFFSET);
+        $timestamp = self::ntfsTimeToTimestamp($ntfsTime);
+        $dateTime = \DateTimeImmutable::createFromFormat('U.u', sprintf('%.6f', $timestamp));
 
-        try {
-            return new \DateTimeImmutable('@' . $timestamp);
-        } catch (\Exception $e) {
-            throw new InvalidArgumentException('Cannot create date/time object for timestamp ' . $timestamp, 1, $e);
+        if ($dateTime === false) {
+            throw new InvalidArgumentException('Cannot create date/time object for timestamp ' . $timestamp);
         }
+
+        return $dateTime;
     }
 
     /**
@@ -238,17 +319,17 @@ class NtfsExtraField implements ZipExtraField
         $args = [self::HEADER_ID];
         $format = '0x%04x NtfsExtra:';
 
-        if ($this->modifyTime !== 0) {
+        if ($this->modifyNtfsTime !== 0) {
             $format .= ' Modify:[%s]';
             $args[] = $this->getModifyDateTime()->format(\DATE_ATOM);
         }
 
-        if ($this->accessTime !== 0) {
+        if ($this->accessNtfsTime !== 0) {
             $format .= ' Access:[%s]';
             $args[] = $this->getAccessDateTime()->format(\DATE_ATOM);
         }
 
-        if ($this->createTime !== 0) {
+        if ($this->createNtfsTime !== 0) {
             $format .= ' Create:[%s]';
             $args[] = $this->getCreateDateTime()->format(\DATE_ATOM);
         }

+ 3 - 2
src/Model/Extra/Fields/UnrecognizedExtraField.php

@@ -2,6 +2,7 @@
 
 namespace PhpZip\Model\Extra\Fields;
 
+use PhpZip\Exception\RuntimeException;
 use PhpZip\Model\Extra\ZipExtraField;
 use PhpZip\Model\ZipEntry;
 
@@ -56,7 +57,7 @@ class UnrecognizedExtraField implements ZipExtraField
      */
     public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
     {
-        throw new \RuntimeException('Unsupport parse');
+        throw new RuntimeException('Unsupport parse');
     }
 
     /**
@@ -67,7 +68,7 @@ class UnrecognizedExtraField implements ZipExtraField
      */
     public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
     {
-        throw new \RuntimeException('Unsupport parse');
+        throw new RuntimeException('Unsupport parse');
     }
 
     /**

+ 2 - 2
src/Model/Extra/Fields/WinZipAesExtraField.php

@@ -256,7 +256,7 @@ class WinZipAesExtraField implements ZipExtraField
         $vendorVersion = (int) $vendorVersion;
 
         if (!\in_array($vendorVersion, self::$allowVendorVersions, true)) {
-            throw new \InvalidArgumentException(
+            throw new InvalidArgumentException(
                 sprintf(
                     'Unsupport WinZip AES vendor version: %d',
                     $vendorVersion
@@ -294,7 +294,7 @@ class WinZipAesExtraField implements ZipExtraField
         $keyStrength = (int) $keyStrength;
 
         if (!isset(self::$encryptionStrengths[$keyStrength])) {
-            throw new \InvalidArgumentException(
+            throw new InvalidArgumentException(
                 sprintf(
                     'Key strength %d not support value. Allow values: %s',
                     $keyStrength,

+ 10 - 4
src/Model/ZipEntry.php

@@ -963,9 +963,12 @@ class ZipEntry
     {
         $dosTime = (int) $dosTime;
 
-        if ($dosTime < 0x00000000 || $dosTime > 0xffffffff) {
-            throw new InvalidArgumentException('DosTime out of range');
+        if (\PHP_INT_SIZE === 8) {
+            if ($dosTime < 0x00000000 || $dosTime > 0xffffffff) {
+                throw new InvalidArgumentException('DosTime out of range');
+            }
         }
+
         $this->dosTime = $dosTime;
 
         return $this;
@@ -1010,9 +1013,12 @@ class ZipEntry
     {
         $this->externalAttributes = (int) $externalAttributes;
 
-        if ($externalAttributes < 0x00000000 || $externalAttributes > 0xffffffff) {
-            throw new InvalidArgumentException('external attributes out of range: ' . $externalAttributes);
+        if (\PHP_INT_SIZE === 8) {
+            if ($externalAttributes < 0x00000000 || $externalAttributes > 0xffffffff) {
+                throw new InvalidArgumentException('external attributes out of range: ' . $externalAttributes);
+            }
         }
+
         $this->externalAttributes = $externalAttributes;
 
         return $this;

+ 5 - 5
src/Model/ZipEntryMatcher.php

@@ -89,7 +89,10 @@ class ZipEntryMatcher implements \Countable
      */
     public function all()
     {
-        $this->matches = array_keys($this->zipContainer->getEntries());
+        $this->matches = array_map(
+            'strval',
+            array_keys($this->zipContainer->getEntries())
+        );
 
         return $this;
     }
@@ -192,10 +195,7 @@ class ZipEntryMatcher implements \Countable
      *
      * @see http://php.net/manual/en/countable.count.php
      *
-     * @return int The custom count as an integer.
-     *             </p>
-     *             <p>
-     *             The return value is cast to an integer.
+     * @return int the custom count as an integer
      *
      * @since 5.1.0
      */

+ 13 - 1
tests/ZipEntryTest.php

@@ -266,7 +266,7 @@ class ZipEntryTest extends TestCase
         $dosEntryName = DosCodePage::fromUTF8($entryName, $charset);
         static::assertSame(DosCodePage::toUTF8($dosEntryName, $charset), $entryName);
 
-        $unicodePathExtraField = UnicodePathExtraField::create($entryName);
+        $unicodePathExtraField = new UnicodePathExtraField(crc32($dosEntryName), $entryName);
 
         $zipEntry = new ZipEntry($dosEntryName, $charset);
         static::assertSame($zipEntry->getName(), $dosEntryName);
@@ -800,6 +800,12 @@ class ZipEntryTest extends TestCase
      */
     public function testInvalidDosTime($dosTime)
     {
+        if (\PHP_INT_SIZE === 4) {
+            static::markTestSkipped('only 64 bit test');
+
+            return;
+        }
+
         $this->setExpectedException(InvalidArgumentException::class, 'DosTime out of range');
 
         $zipEntry = new ZipEntry('entry');
@@ -951,6 +957,12 @@ class ZipEntryTest extends TestCase
      */
     public function testInvalidExternalAttributes($externalAttributes)
     {
+        if (\PHP_INT_SIZE === 4) {
+            static::markTestSkipped('only 64 bit test');
+
+            return;
+        }
+
         $this->setExpectedException(InvalidArgumentException::class, 'external attributes out of range');
 
         $zipEntry = new ZipEntry('entry');