extraFieldsCollection = new ExtraFieldsCollection(); } /** * @param ZipEntry $entry * * @throws ZipException */ public function setEntry(ZipEntry $entry) { $this->setName($entry->getName()); $this->setSoftwareVersion($entry->getSoftwareVersion()); $this->setCreatedOS($entry->getCreatedOS()); $this->setExtractedOS($entry->getExtractedOS()); $this->setVersionNeededToExtract($entry->getVersionNeededToExtract()); $this->setMethod($entry->getMethod()); $this->setGeneralPurposeBitFlags($entry->getGeneralPurposeBitFlags()); $this->setDosTime($entry->getDosTime()); $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()); $this->setComment($entry->getComment()); $this->setPassword($entry->getPassword()); $this->setEncryptionMethod($entry->getEncryptionMethod()); $this->setCompressionLevel($entry->getCompressionLevel()); $this->setEncrypted($entry->isEncrypted()); } /** * Returns the ZIP entry name. * * @return string */ public function getName() { return $this->name; } /** * Set entry name. * * @param string $name New entry name * * @throws ZipException * * @return ZipEntry */ public function setName($name) { $length = \strlen($name); if ($length < 0x0000 || $length > 0xffff) { throw new ZipException('Illegal zip entry name parameter'); } $this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true); $this->name = $name; $this->externalAttributes = $this->isDirectory() ? 0x10 : 0; return $this; } /** * Sets the indexed General Purpose Bit Flag. * * @param int $mask * @param bool $bit * * @return ZipEntry */ public function setGeneralPurposeBitFlag($mask, $bit) { if ($bit) { $this->generalPurposeBitFlags |= $mask; } else { $this->generalPurposeBitFlags &= ~$mask; } return $this; } /** * @return int Get platform * * @deprecated Use {@see ZipEntry::getCreatedOS()} */ public function getPlatform() { @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; } /** * Set platform. * * @param int $platform * * @throws ZipException * * @return ZipEntry */ public function setCreatedOS($platform) { $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; } /** * Version needed to extract. * * @return int */ 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; } /** * Set version needed to extract. * * @param int $version * * @return ZipEntry */ public function setVersionNeededToExtract($version) { $this->versionNeededToExtract = $version; return $this; } /** * @return bool */ public function isZip64ExtensionsRequired() { return $this->getCompressedSize() >= 0xffffffff || $this->getSize() >= 0xffffffff; } /** * Returns the compressed size of this entry. * * @see int */ public function getCompressedSize() { return $this->compressedSize; } /** * Sets the compressed size of this entry. * * @param int $compressedSize the Compressed Size * * @return ZipEntry */ public function setCompressedSize($compressedSize) { $this->compressedSize = $compressedSize; return $this; } /** * Returns the uncompressed size of this entry. * * @see ZipEntry::setCompressedSize */ public function getSize() { return $this->size; } /** * Sets the uncompressed size of this entry. * * @param int $size the (Uncompressed) Size * * @return ZipEntry */ public function setSize($size) { $this->size = $size; return $this; } /** * Return relative Offset Of Local File Header. * * @return int */ public function getOffset() { return $this->offset; } /** * @param int $offset * * @return ZipEntry */ public function setOffset($offset) { $this->offset = (int) $offset; return $this; } /** * Returns the General Purpose Bit Flags. * * @return int */ public function getGeneralPurposeBitFlags() { return $this->generalPurposeBitFlags & 0xffff; } /** * Sets the General Purpose Bit Flags. * * @param mixed $general * * @throws ZipException * * @return ZipEntry * * @var int general */ public function setGeneralPurposeBitFlags($general) { if ($general < 0x0000 || $general > 0xffff) { throw new ZipException('general out of range'); } $this->generalPurposeBitFlags = $general; 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 = ZipFile::LEVEL_BEST_COMPRESSION; } elseif (!$bit1 && $bit2) { $this->compressionLevel = ZipFile::LEVEL_FAST; } elseif ($bit1 && $bit2) { $this->compressionLevel = ZipFile::LEVEL_SUPER_FAST; } else { $this->compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION; } } return $this; } /** * Returns true if and only if this ZIP entry is encrypted. * * @return bool */ public function isEncrypted() { return $this->getGeneralPurposeBitFlag(self::GPBF_ENCRYPTED); } /** * Returns the indexed General Purpose Bit Flag. * * @param int $mask * * @return bool */ public function getGeneralPurposeBitFlag($mask) { return ($this->generalPurposeBitFlags & $mask) !== 0; } /** * Sets the encryption property to false and removes any other * encryption artifacts. * * @throws ZipException * * @return ZipEntry */ public function disableEncryption() { $this->setEncrypted(false); $headerId = WinZipAesEntryExtraField::getHeaderId(); if (isset($this->extraFieldsCollection[$headerId])) { /** @var WinZipAesEntryExtraField $field */ $field = $this->extraFieldsCollection[$headerId]; if ($this->getMethod() === self::METHOD_WINZIP_AES) { $this->setMethod($field === null ? self::UNKNOWN : $field->getMethod()); } unset($this->extraFieldsCollection[$headerId]); } $this->password = null; return $this; } /** * Sets the encryption flag for this ZIP entry. * * @param bool $encrypted * * @return ZipEntry */ public function setEncrypted($encrypted) { $encrypted = (bool) $encrypted; $this->setGeneralPurposeBitFlag(self::GPBF_ENCRYPTED, $encrypted); return $this; } /** * Returns the compression method for this entry. * * @return int */ public function getMethod() { return $this->method; } /** * Sets the compression method for this entry. * * @param int $method * * @throws ZipException if method is not STORED, DEFLATED, BZIP2 or UNKNOWN * * @return ZipEntry */ public function setMethod($method) { if ($method === self::UNKNOWN) { $this->method = $method; return $this; } if ($method < 0x0000 || $method > 0xffff) { throw new ZipException('method out of range: ' . $method); } switch ($method) { case self::METHOD_WINZIP_AES: case ZipFile::METHOD_STORED: case ZipFile::METHOD_DEFLATED: case ZipFile::METHOD_BZIP2: $this->method = $method; break; default: throw new ZipException($this->name . " (unsupported compression method {$method})"); } return $this; } /** * Get Unix Timestamp. * * @return int */ public function getTime() { if ($this->getDosTime() === self::UNKNOWN) { return self::UNKNOWN; } return DateTimeConverter::toUnixTimestamp($this->getDosTime()); } /** * Get Dos Time. * * @return int */ public function getDosTime() { return $this->dosTime; } /** * Set Dos Time. * * @param int $dosTime * * @throws ZipException * * @return ZipEntry */ public function setDosTime($dosTime) { $dosTime = (int) $dosTime; if ($dosTime < 0x00000000 || $dosTime > 0xffffffff) { throw new ZipException('DosTime out of range'); } $this->dosTime = $dosTime; return $this; } /** * Set time from unix timestamp. * * @param int $unixTimestamp * * @throws ZipException * * @return ZipEntry */ public function setTime($unixTimestamp) { $known = $unixTimestamp !== self::UNKNOWN; if ($known) { $this->dosTime = DateTimeConverter::toDosTime($unixTimestamp); } else { $this->dosTime = 0; } return $this; } /** * Returns the external file attributes. * * @return int the external file attributes */ public function getExternalAttributes() { return $this->externalAttributes; } /** * Sets the external file attributes. * * @param int $externalAttributes the external file attributes * * @return ZipEntry */ public function setExternalAttributes($externalAttributes) { $this->externalAttributes = $externalAttributes; 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 '/'). * * @return bool */ public function isDirectory() { return StringUtil::endsWith($this->name, '/'); } /** * @return ExtraFieldsCollection */ public function &getExtraFieldsCollection() { return $this->extraFieldsCollection; } /** * Returns a protective copy of the serialized Extra Fields. * * @throws ZipException * * @return string */ public function getExtra() { return ExtraFieldsFactory::createSerializedData($this->extraFieldsCollection); } /** * Sets the serialized Extra Fields by making a protective copy. * Note that this method parses the serialized Extra Fields according to * the ZIP File Format Specification and limits its size to 64 KB. * Therefore, this property cannot not be used to hold arbitrary * (application) data. * Consider storing such data in a separate entry instead. * * @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; } /** * Returns comment entry. * * @return string */ public function getComment() { return $this->comment !== null ? $this->comment : ''; } /** * Set entry comment. * * @param string|null $comment * * @throws ZipException * * @return ZipEntry */ public function setComment($comment) { if ($comment !== null) { $commentLength = \strlen($comment); if ($commentLength < 0x0000 || $commentLength > 0xffff) { throw new ZipException('Comment too long'); } $this->setGeneralPurposeBitFlag(self::GPBF_UTF8, true); } $this->comment = $comment; return $this; } /** * @return bool */ public function isDataDescriptorRequired() { return ($this->getCrc() | $this->getCompressedSize() | $this->getSize()) === self::UNKNOWN; } /** * Return crc32 content or 0 for WinZip AES v2. * * @return int */ public function getCrc() { return $this->crc; } /** * Set crc32 content. * * @param int $crc * * @return ZipEntry */ public function setCrc($crc) { $this->crc = (int) $crc; return $this; } /** * @return string */ public function getPassword() { return $this->password; } /** * Set password and encryption method from entry. * * @param string $password * @param int|null $encryptionMethod * * @throws ZipException * * @return ZipEntry */ public function setPassword($password, $encryptionMethod = null) { $this->password = $password; if ($encryptionMethod !== null) { $this->setEncryptionMethod($encryptionMethod); } if (!empty($this->password)) { $this->setEncrypted(true); } else { $this->disableEncryption(); } return $this; } /** * @return int */ public function getEncryptionMethod() { return $this->encryptionMethod; } /** * Set encryption method. * * @param int $encryptionMethod * * @throws ZipException * * @return ZipEntry * * @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 !== 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'); } $this->encryptionMethod = $encryptionMethod; } return $this; } /** * @return int */ public function getCompressionLevel() { return $this->compressionLevel; } /** * @param int $compressionLevel * * @return ZipEntry */ public function setCompressionLevel($compressionLevel = ZipFile::LEVEL_DEFAULT_COMPRESSION) { if ($compressionLevel < ZipFile::LEVEL_DEFAULT_COMPRESSION || $compressionLevel > ZipFile::LEVEL_BEST_COMPRESSION ) { throw new InvalidArgumentException( 'Invalid compression level. Minimum level ' . ZipFile::LEVEL_DEFAULT_COMPRESSION . '. Maximum level ' . ZipFile::LEVEL_BEST_COMPRESSION ); } $this->compressionLevel = $compressionLevel; return $this; } /** * Clone extra fields. */ public function __clone() { $this->extraFieldsCollection = clone $this->extraFieldsCollection; } }