Vendor bunch upload of nelexa library
This commit is contained in:
81
vendor/nelexa/zip/src/Model/Data/ZipFileData.php
vendored
Normal file
81
vendor/nelexa/zip/src/Model/Data/ZipFileData.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Data;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\ZipData;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Class ZipFileData.
|
||||
*/
|
||||
class ZipFileData implements ZipData
|
||||
{
|
||||
/** @var \SplFileInfo */
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* ZipStringData constructor.
|
||||
*
|
||||
* @param ZipEntry $zipEntry
|
||||
* @param \SplFileInfo $fileInfo
|
||||
*
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function __construct(ZipEntry $zipEntry, \SplFileInfo $fileInfo)
|
||||
{
|
||||
if (!$fileInfo->isFile()) {
|
||||
throw new ZipException('$fileInfo is not a file.');
|
||||
}
|
||||
|
||||
if (!$fileInfo->isReadable()) {
|
||||
throw new ZipException('$fileInfo is not readable.');
|
||||
}
|
||||
|
||||
$this->file = $fileInfo;
|
||||
$zipEntry->setUncompressedSize($fileInfo->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return resource returns stream data
|
||||
*/
|
||||
public function getDataAsStream()
|
||||
{
|
||||
if (!$this->file->isReadable()) {
|
||||
throw new ZipException(sprintf('The %s file is no longer readable.', $this->file->getPathname()));
|
||||
}
|
||||
|
||||
return fopen($this->file->getPathname(), 'rb');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return string returns data as string
|
||||
*/
|
||||
public function getDataAsString()
|
||||
{
|
||||
if (!$this->file->isReadable()) {
|
||||
throw new ZipException(sprintf('The %s file is no longer readable.', $this->file->getPathname()));
|
||||
}
|
||||
|
||||
return file_get_contents($this->file->getPathname());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $outStream
|
||||
*
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function copyDataToStream($outStream)
|
||||
{
|
||||
try {
|
||||
$stream = $this->getDataAsStream();
|
||||
stream_copy_to_stream($stream, $outStream);
|
||||
} finally {
|
||||
fclose($stream);
|
||||
}
|
||||
}
|
||||
}
|
132
vendor/nelexa/zip/src/Model/Data/ZipNewData.php
vendored
Normal file
132
vendor/nelexa/zip/src/Model/Data/ZipNewData.php
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Data;
|
||||
|
||||
use PhpZip\Model\ZipData;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\ZipFile;
|
||||
|
||||
/**
|
||||
* The class contains a streaming resource with new content added to the ZIP archive.
|
||||
*/
|
||||
class ZipNewData implements ZipData
|
||||
{
|
||||
/**
|
||||
* A static variable allows closing the stream in the destructor
|
||||
* only if it is its sole holder.
|
||||
*
|
||||
* @var array<int, int> array of resource ids and the number of class clones
|
||||
*/
|
||||
private static $guardClonedStream = [];
|
||||
|
||||
/** @var ZipEntry */
|
||||
private $zipEntry;
|
||||
|
||||
/** @var resource */
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* ZipStringData constructor.
|
||||
*
|
||||
* @param ZipEntry $zipEntry
|
||||
* @param string|resource $data
|
||||
*/
|
||||
public function __construct(ZipEntry $zipEntry, $data)
|
||||
{
|
||||
$this->zipEntry = $zipEntry;
|
||||
|
||||
if (\is_string($data)) {
|
||||
$zipEntry->setUncompressedSize(\strlen($data));
|
||||
|
||||
if (!($handle = fopen('php://temp', 'w+b'))) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \RuntimeException('A temporary resource cannot be opened for writing.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
fwrite($handle, $data);
|
||||
rewind($handle);
|
||||
$this->stream = $handle;
|
||||
} elseif (\is_resource($data)) {
|
||||
$this->stream = $data;
|
||||
}
|
||||
|
||||
$resourceId = (int) $this->stream;
|
||||
self::$guardClonedStream[$resourceId] =
|
||||
isset(self::$guardClonedStream[$resourceId]) ?
|
||||
self::$guardClonedStream[$resourceId] + 1 :
|
||||
0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource returns stream data
|
||||
*/
|
||||
public function getDataAsStream()
|
||||
{
|
||||
if (!\is_resource($this->stream)) {
|
||||
throw new \LogicException(sprintf('Resource has been closed (entry=%s).', $this->zipEntry->getName()));
|
||||
}
|
||||
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string returns data as string
|
||||
*/
|
||||
public function getDataAsString()
|
||||
{
|
||||
$stream = $this->getDataAsStream();
|
||||
$pos = ftell($stream);
|
||||
|
||||
try {
|
||||
rewind($stream);
|
||||
|
||||
return stream_get_contents($stream);
|
||||
} finally {
|
||||
fseek($stream, $pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $outStream
|
||||
*/
|
||||
public function copyDataToStream($outStream)
|
||||
{
|
||||
$stream = $this->getDataAsStream();
|
||||
rewind($stream);
|
||||
stream_copy_to_stream($stream, $outStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://php.net/manual/en/language.oop5.cloning.php
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$resourceId = (int) $this->stream;
|
||||
self::$guardClonedStream[$resourceId] =
|
||||
isset(self::$guardClonedStream[$resourceId]) ?
|
||||
self::$guardClonedStream[$resourceId] + 1 :
|
||||
1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream will be closed when closing the zip archive.
|
||||
*
|
||||
* The method implements protection against closing the stream of the cloned object.
|
||||
*
|
||||
* @see ZipFile::close()
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$resourceId = (int) $this->stream;
|
||||
|
||||
if (isset(self::$guardClonedStream[$resourceId]) && self::$guardClonedStream[$resourceId] > 0) {
|
||||
self::$guardClonedStream[$resourceId]--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (\is_resource($this->stream)) {
|
||||
fclose($this->stream);
|
||||
}
|
||||
}
|
||||
}
|
172
vendor/nelexa/zip/src/Model/Data/ZipSourceFileData.php
vendored
Normal file
172
vendor/nelexa/zip/src/Model/Data/ZipSourceFileData.php
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Data;
|
||||
|
||||
use PhpZip\Exception\Crc32Exception;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\IO\ZipReader;
|
||||
use PhpZip\Model\ZipData;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Class ZipFileData.
|
||||
*/
|
||||
class ZipSourceFileData implements ZipData
|
||||
{
|
||||
/** @var ZipReader */
|
||||
private $zipReader;
|
||||
|
||||
/** @var resource|null */
|
||||
private $stream;
|
||||
|
||||
/** @var ZipEntry */
|
||||
private $sourceEntry;
|
||||
|
||||
/** @var int */
|
||||
private $offset;
|
||||
|
||||
/** @var int */
|
||||
private $uncompressedSize;
|
||||
|
||||
/** @var int */
|
||||
private $compressedSize;
|
||||
|
||||
/**
|
||||
* ZipFileData constructor.
|
||||
*
|
||||
* @param ZipReader $zipReader
|
||||
* @param ZipEntry $zipEntry
|
||||
* @param int $offsetData
|
||||
*/
|
||||
public function __construct(ZipReader $zipReader, ZipEntry $zipEntry, $offsetData)
|
||||
{
|
||||
$this->zipReader = $zipReader;
|
||||
$this->offset = $offsetData;
|
||||
$this->sourceEntry = $zipEntry;
|
||||
$this->compressedSize = $zipEntry->getCompressedSize();
|
||||
$this->uncompressedSize = $zipEntry->getUncompressedSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRecompressData(ZipEntry $entry)
|
||||
{
|
||||
return $this->sourceEntry->getCompressionLevel() !== $entry->getCompressionLevel() ||
|
||||
$this->sourceEntry->getCompressionMethod() !== $entry->getCompressionMethod() ||
|
||||
$this->sourceEntry->isEncrypted() !== $entry->isEncrypted() ||
|
||||
$this->sourceEntry->getEncryptionMethod() !== $entry->getEncryptionMethod() ||
|
||||
$this->sourceEntry->getPassword() !== $entry->getPassword() ||
|
||||
$this->sourceEntry->getCompressedSize() !== $entry->getCompressedSize() ||
|
||||
$this->sourceEntry->getUncompressedSize() !== $entry->getUncompressedSize() ||
|
||||
$this->sourceEntry->getCrc() !== $entry->getCrc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return resource returns stream data
|
||||
*/
|
||||
public function getDataAsStream()
|
||||
{
|
||||
if (!\is_resource($this->stream)) {
|
||||
$this->stream = $this->zipReader->getEntryStream($this);
|
||||
}
|
||||
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return string returns data as string
|
||||
*/
|
||||
public function getDataAsString()
|
||||
{
|
||||
$autoClosable = $this->stream === null;
|
||||
|
||||
$stream = $this->getDataAsStream();
|
||||
$pos = ftell($stream);
|
||||
|
||||
try {
|
||||
rewind($stream);
|
||||
|
||||
return stream_get_contents($stream);
|
||||
} finally {
|
||||
if ($autoClosable) {
|
||||
fclose($stream);
|
||||
$this->stream = null;
|
||||
} else {
|
||||
fseek($stream, $pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $outputStream Output stream
|
||||
*
|
||||
* @throws ZipException
|
||||
* @throws Crc32Exception
|
||||
*/
|
||||
public function copyDataToStream($outputStream)
|
||||
{
|
||||
if (\is_resource($this->stream)) {
|
||||
rewind($this->stream);
|
||||
stream_copy_to_stream($this->stream, $outputStream);
|
||||
} else {
|
||||
$this->zipReader->copyUncompressedDataToStream($this, $outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $outputStream Output stream
|
||||
*/
|
||||
public function copyCompressedDataToStream($outputStream)
|
||||
{
|
||||
$this->zipReader->copyCompressedDataToStream($this, $outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZipEntry
|
||||
*/
|
||||
public function getSourceEntry()
|
||||
{
|
||||
return $this->sourceEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCompressedSize()
|
||||
{
|
||||
return $this->compressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUncompressedSize()
|
||||
{
|
||||
return $this->uncompressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getOffset()
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (\is_resource($this->stream)) {
|
||||
fclose($this->stream);
|
||||
}
|
||||
}
|
||||
}
|
93
vendor/nelexa/zip/src/Model/EndOfCentralDirectory.php
vendored
Normal file
93
vendor/nelexa/zip/src/Model/EndOfCentralDirectory.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
/**
|
||||
* End of Central Directory.
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
class EndOfCentralDirectory
|
||||
{
|
||||
/** @var int Count files. */
|
||||
private $entryCount;
|
||||
|
||||
/** @var int Central Directory Offset. */
|
||||
private $cdOffset;
|
||||
|
||||
/** @var int */
|
||||
private $cdSize;
|
||||
|
||||
/** @var string|null The archive comment. */
|
||||
private $comment;
|
||||
|
||||
/** @var bool Zip64 extension */
|
||||
private $zip64;
|
||||
|
||||
/**
|
||||
* EndOfCentralDirectory constructor.
|
||||
*
|
||||
* @param int $entryCount
|
||||
* @param int $cdOffset
|
||||
* @param int $cdSize
|
||||
* @param bool $zip64
|
||||
* @param string|null $comment
|
||||
*/
|
||||
public function __construct($entryCount, $cdOffset, $cdSize, $zip64, $comment = null)
|
||||
{
|
||||
$this->entryCount = $entryCount;
|
||||
$this->cdOffset = $cdOffset;
|
||||
$this->cdSize = $cdSize;
|
||||
$this->zip64 = $zip64;
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $comment
|
||||
*/
|
||||
public function setComment($comment)
|
||||
{
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getEntryCount()
|
||||
{
|
||||
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
|
||||
*/
|
||||
public function isZip64()
|
||||
{
|
||||
return $this->zip64;
|
||||
}
|
||||
}
|
276
vendor/nelexa/zip/src/Model/Extra/ExtraFieldsCollection.php
vendored
Normal file
276
vendor/nelexa/zip/src/Model/Extra/ExtraFieldsCollection.php
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra;
|
||||
|
||||
/**
|
||||
* Represents a collection of Extra Fields as they may
|
||||
* be present at several locations in ZIP files.
|
||||
*/
|
||||
class ExtraFieldsCollection implements \ArrayAccess, \Countable, \Iterator
|
||||
{
|
||||
/**
|
||||
* The map of Extra Fields.
|
||||
* Maps from Header ID to Extra Field.
|
||||
* Must not be null, but may be empty if no Extra Fields are used.
|
||||
* The map is sorted by Header IDs in ascending order.
|
||||
*
|
||||
* @var ZipExtraField[]
|
||||
*/
|
||||
protected $collection = [];
|
||||
|
||||
/**
|
||||
* Returns the number of Extra Fields in this collection.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return \count($this->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Extra Field with the given Header ID or null
|
||||
* if no such Extra Field exists.
|
||||
*
|
||||
* @param int $headerId the requested Header ID
|
||||
*
|
||||
* @return ZipExtraField|null the Extra Field with the given Header ID or
|
||||
* if no such Extra Field exists
|
||||
*/
|
||||
public function get($headerId)
|
||||
{
|
||||
$this->validateHeaderId($headerId);
|
||||
|
||||
return isset($this->collection[$headerId]) ? $this->collection[$headerId] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $headerId
|
||||
*/
|
||||
private function validateHeaderId($headerId)
|
||||
{
|
||||
if ($headerId < 0 || $headerId > 0xffff) {
|
||||
throw new \InvalidArgumentException('$headerId out of range');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given Extra Field in this collection.
|
||||
*
|
||||
* @param ZipExtraField $extraField the Extra Field to store in this collection
|
||||
*
|
||||
* @return ZipExtraField the Extra Field previously associated with the Header ID of
|
||||
* of the given Extra Field or null if no such Extra Field existed
|
||||
*/
|
||||
public function add(ZipExtraField $extraField)
|
||||
{
|
||||
$headerId = $extraField->getHeaderId();
|
||||
|
||||
$this->validateHeaderId($headerId);
|
||||
$this->collection[$headerId] = $extraField;
|
||||
|
||||
return $extraField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipExtraField[] $extraFields
|
||||
*/
|
||||
public function addAll(array $extraFields)
|
||||
{
|
||||
foreach ($extraFields as $extraField) {
|
||||
$this->add($extraField);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExtraFieldsCollection $collection
|
||||
*/
|
||||
public function addCollection(self $collection)
|
||||
{
|
||||
$this->addAll($collection->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZipExtraField[]
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Extra Field exists.
|
||||
*
|
||||
* @param int $headerId the requested Header ID
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($headerId)
|
||||
{
|
||||
return isset($this->collection[$headerId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Extra Field with the given Header ID.
|
||||
*
|
||||
* @param int $headerId the requested Header ID
|
||||
*
|
||||
* @return ZipExtraField|null the Extra Field with the given Header ID or null
|
||||
* if no such Extra Field exists
|
||||
*/
|
||||
public function remove($headerId)
|
||||
{
|
||||
$this->validateHeaderId($headerId);
|
||||
|
||||
if (isset($this->collection[$headerId])) {
|
||||
$ef = $this->collection[$headerId];
|
||||
unset($this->collection[$headerId]);
|
||||
|
||||
return $ef;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a offset exists.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetexists.php
|
||||
*
|
||||
* @param int $offset an offset to check for
|
||||
*
|
||||
* @return bool true on success or false on failure
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->collection[(int) $offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to retrieve.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetget.php
|
||||
*
|
||||
* @param int $offset the offset to retrieve
|
||||
*
|
||||
* @return ZipExtraField|null
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->collection[$offset]) ? $this->collection[$offset] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to set.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetset.php
|
||||
*
|
||||
* @param mixed $offset the offset to assign the value to
|
||||
* @param ZipExtraField $value the value to set
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (!$value instanceof ZipExtraField) {
|
||||
throw new \InvalidArgumentException('value is not instanceof ' . ZipExtraField::class);
|
||||
}
|
||||
$this->add($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to unset.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetunset.php
|
||||
*
|
||||
* @param mixed $offset the offset to unset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element.
|
||||
*
|
||||
* @see http://php.net/manual/en/iterator.current.php
|
||||
*
|
||||
* @return ZipExtraField
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element.
|
||||
*
|
||||
* @see http://php.net/manual/en/iterator.next.php
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
next($this->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element.
|
||||
*
|
||||
* @see http://php.net/manual/en/iterator.key.php
|
||||
*
|
||||
* @return int scalar on success, or null on failure
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid.
|
||||
*
|
||||
* @see http://php.net/manual/en/iterator.valid.php
|
||||
*
|
||||
* @return bool The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return key($this->collection) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element.
|
||||
*
|
||||
* @see http://php.net/manual/en/iterator.rewind.php
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->collection);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->collection = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$formats = [];
|
||||
|
||||
foreach ($this->collection as $key => $value) {
|
||||
$formats[] = (string) $value;
|
||||
}
|
||||
|
||||
return implode("\n", $formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* If clone extra fields.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
foreach ($this->collection as $k => $v) {
|
||||
$this->collection[$k] = clone $v;
|
||||
}
|
||||
}
|
||||
}
|
133
vendor/nelexa/zip/src/Model/Extra/Fields/AbstractUnicodeExtraField.php
vendored
Normal file
133
vendor/nelexa/zip/src/Model/Extra/Fields/AbstractUnicodeExtraField.php
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* A common base class for Unicode extra information extra fields.
|
||||
*/
|
||||
abstract class AbstractUnicodeExtraField implements ZipExtraField
|
||||
{
|
||||
const DEFAULT_VERSION = 0x01;
|
||||
|
||||
/** @var int */
|
||||
private $crc32;
|
||||
|
||||
/** @var string */
|
||||
private $unicodeValue;
|
||||
|
||||
/**
|
||||
* @param int $crc32
|
||||
* @param string $unicodeValue
|
||||
*/
|
||||
public function __construct($crc32, $unicodeValue)
|
||||
{
|
||||
$this->crc32 = (int) $crc32;
|
||||
$this->unicodeValue = (string) $unicodeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int the CRC32 checksum of the filename or comment as
|
||||
* encoded in the central directory of the zip file
|
||||
*/
|
||||
public function getCrc32()
|
||||
{
|
||||
return $this->crc32;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $crc32
|
||||
*/
|
||||
public function setCrc32($crc32)
|
||||
{
|
||||
$this->crc32 = (int) $crc32;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUnicodeValue()
|
||||
{
|
||||
return $this->unicodeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $unicodeValue the UTF-8 encoded name to set
|
||||
*/
|
||||
public function setUnicodeValue($unicodeValue)
|
||||
{
|
||||
$this->unicodeValue = $unicodeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
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.');
|
||||
}
|
||||
|
||||
$data = unpack('Cversion/Vcrc32', $buffer);
|
||||
|
||||
if ($data['version'] !== self::DEFAULT_VERSION) {
|
||||
throw new ZipException(sprintf('Unsupported version [%d] for Unicode path extra data.', $data['version']));
|
||||
}
|
||||
|
||||
$unicodeValue = substr($buffer, 5);
|
||||
|
||||
return new static($data['crc32'], $unicodeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return pack(
|
||||
'CV',
|
||||
self::DEFAULT_VERSION,
|
||||
$this->crc32
|
||||
) .
|
||||
$this->unicodeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
}
|
176
vendor/nelexa/zip/src/Model/Extra/Fields/ApkAlignmentExtraField.php
vendored
Normal file
176
vendor/nelexa/zip/src/Model/Extra/Fields/ApkAlignmentExtraField.php
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Apk Alignment Extra Field.
|
||||
*
|
||||
* @see https://android.googlesource.com/platform/tools/apksig/+/master/src/main/java/com/android/apksig/ApkSigner.java
|
||||
* @see https://developer.android.com/studio/command-line/zipalign
|
||||
*/
|
||||
class ApkAlignmentExtraField implements ZipExtraField
|
||||
{
|
||||
/**
|
||||
* @var int Extensible data block/field header ID used for storing
|
||||
* information about alignment of uncompressed entries as
|
||||
* well as for aligning the entries's data. See ZIP
|
||||
* appnote.txt section 4.5 Extensible data fields.
|
||||
*/
|
||||
const HEADER_ID = 0xd935;
|
||||
|
||||
/**
|
||||
* @var int minimum size (in bytes) of the extensible data block/field used
|
||||
* for alignment of uncompressed entries
|
||||
*/
|
||||
const MIN_SIZE = 6;
|
||||
|
||||
/** @var int */
|
||||
const ALIGNMENT_BYTES = 4;
|
||||
|
||||
/** @var int */
|
||||
const COMMON_PAGE_ALIGNMENT_BYTES = 4096;
|
||||
|
||||
/** @var int */
|
||||
private $multiple;
|
||||
|
||||
/** @var int */
|
||||
private $padding;
|
||||
|
||||
/**
|
||||
* @param int $multiple
|
||||
* @param int $padding
|
||||
*/
|
||||
public function __construct($multiple, $padding)
|
||||
{
|
||||
$this->multiple = $multiple;
|
||||
$this->padding = $padding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMultiple()
|
||||
{
|
||||
return $this->multiple;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPadding()
|
||||
{
|
||||
return $this->padding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $multiple
|
||||
*/
|
||||
public function setMultiple($multiple)
|
||||
{
|
||||
$this->multiple = (int) $multiple;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $padding
|
||||
*/
|
||||
public function setPadding($padding)
|
||||
{
|
||||
$this->padding = (int) $padding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return ApkAlignmentExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
|
||||
if ($length < 2) {
|
||||
// This is APK alignment field.
|
||||
// FORMAT:
|
||||
// * uint16 alignment multiple (in bytes)
|
||||
// * remaining bytes -- padding to achieve alignment of data which starts after
|
||||
// the extra field
|
||||
throw new ZipException(
|
||||
'Minimum 6 bytes of the extensible data block/field used for alignment of uncompressed entries.'
|
||||
);
|
||||
}
|
||||
$multiple = unpack('v', $buffer)[1];
|
||||
$padding = $length - 2;
|
||||
|
||||
return new self($multiple, $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return ApkAlignmentExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return pack('vx' . $this->padding, $this->multiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x APK Alignment: Multiple=%d Padding=%d',
|
||||
self::HEADER_ID,
|
||||
$this->multiple,
|
||||
$this->padding
|
||||
);
|
||||
}
|
||||
}
|
302
vendor/nelexa/zip/src/Model/Extra/Fields/AsiExtraField.php
vendored
Normal file
302
vendor/nelexa/zip/src/Model/Extra/Fields/AsiExtraField.php
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Constants\UnixStat;
|
||||
use PhpZip\Exception\Crc32Exception;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* ASi Unix Extra Field:
|
||||
* ====================.
|
||||
*
|
||||
* The following is the layout of the ASi extra block for Unix. The
|
||||
* local-header and central-header versions are identical.
|
||||
* (Last Revision 19960916)
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (Unix3) 0x756e Short tag for this extra block type ("nu")
|
||||
* TSize Short total data size for this block
|
||||
* CRC Long CRC-32 of the remaining data
|
||||
* Mode Short file permissions
|
||||
* SizDev Long symlink'd size OR major/minor dev num
|
||||
* UID Short user ID
|
||||
* GID Short group ID
|
||||
* (var.) variable symbolic link filename
|
||||
*
|
||||
* Mode is the standard Unix st_mode field from struct stat, containing
|
||||
* user/group/other permissions, setuid/setgid and symlink info, etc.
|
||||
*
|
||||
* If Mode indicates that this file is a symbolic link, SizDev is the
|
||||
* size of the file to which the link points. Otherwise, if the file
|
||||
* is a device, SizDev contains the standard Unix st_rdev field from
|
||||
* struct stat (includes the major and minor numbers of the device).
|
||||
* SizDev is undefined in other cases.
|
||||
*
|
||||
* If Mode indicates that the file is a symbolic link, the final field
|
||||
* will be the name of the file to which the link points. The file-
|
||||
* name length can be inferred from TSize.
|
||||
*
|
||||
* [Note that TSize may incorrectly refer to the data size not counting
|
||||
* the CRC; i.e., it may be four bytes too small.]
|
||||
*
|
||||
* @see ftp://ftp.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip Info-ZIP version Specification
|
||||
*/
|
||||
class AsiExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id */
|
||||
const HEADER_ID = 0x756e;
|
||||
|
||||
const USER_GID_PID = 1000;
|
||||
|
||||
/** Bits used for permissions (and sticky bit). */
|
||||
const PERM_MASK = 07777;
|
||||
|
||||
/** @var int Standard Unix stat(2) file mode. */
|
||||
private $mode;
|
||||
|
||||
/** @var int User ID. */
|
||||
private $uid;
|
||||
|
||||
/** @var int Group ID. */
|
||||
private $gid;
|
||||
|
||||
/**
|
||||
* @var string File this entry points to, if it is a symbolic link.
|
||||
* Empty string - if entry is not a symbolic link.
|
||||
*/
|
||||
private $link;
|
||||
|
||||
/**
|
||||
* AsiExtraField constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @param int $uid
|
||||
* @param int $gid
|
||||
* @param string $link
|
||||
*/
|
||||
public function __construct($mode, $uid = self::USER_GID_PID, $gid = self::USER_GID_PID, $link = '')
|
||||
{
|
||||
$this->mode = $mode;
|
||||
$this->uid = $uid;
|
||||
$this->gid = $gid;
|
||||
$this->link = $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws Crc32Exception
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$givenChecksum = unpack('V', $buffer)[1];
|
||||
$buffer = substr($buffer, 4);
|
||||
$realChecksum = crc32($buffer);
|
||||
|
||||
if ($givenChecksum !== $realChecksum) {
|
||||
throw new Crc32Exception('Asi Unix Extra Filed Data', $givenChecksum, $realChecksum);
|
||||
}
|
||||
|
||||
$data = unpack('vmode/VlinkSize/vuid/vgid', $buffer);
|
||||
$link = '';
|
||||
|
||||
if ($data['linkSize'] > 0) {
|
||||
$link = substr($buffer, 10);
|
||||
}
|
||||
|
||||
return new self($data['mode'], $data['uid'], $data['gid'], $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws Crc32Exception
|
||||
*
|
||||
* @return AsiExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
$data = pack(
|
||||
'vVvv',
|
||||
$this->mode,
|
||||
\strlen($this->link),
|
||||
$this->uid,
|
||||
$this->gid
|
||||
) . $this->link;
|
||||
|
||||
return pack('V', crc32($data)) . $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of linked file.
|
||||
*
|
||||
* @return string name of the file this entry links to if it is a
|
||||
* symbolic link, the empty string otherwise
|
||||
*/
|
||||
public function getLink()
|
||||
{
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that this entry is a symbolic link to the given filename.
|
||||
*
|
||||
* @param string $link name of the file this entry links to, empty
|
||||
* string if it is not a symbolic link
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
$this->link = (string) $link;
|
||||
$this->mode = $this->getPermissionsMode($this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this entry a symbolic link?
|
||||
*
|
||||
* @return bool true if this is a symbolic link
|
||||
*/
|
||||
public function isLink()
|
||||
{
|
||||
return !empty($this->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file mode for given permissions with the correct file type.
|
||||
*
|
||||
* @param int $mode the mode
|
||||
*
|
||||
* @return int the type with the mode
|
||||
*/
|
||||
protected function getPermissionsMode($mode)
|
||||
{
|
||||
$type = 0;
|
||||
|
||||
if ($this->isLink()) {
|
||||
$type = UnixStat::UNX_IFLNK;
|
||||
} elseif (($mode & UnixStat::UNX_IFREG) !== 0) {
|
||||
$type = UnixStat::UNX_IFREG;
|
||||
} elseif (($mode & UnixStat::UNX_IFDIR) !== 0) {
|
||||
$type = UnixStat::UNX_IFDIR;
|
||||
}
|
||||
|
||||
return $type | ($mode & self::PERM_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this entry a directory?
|
||||
*
|
||||
* @return bool true if this entry is a directory
|
||||
*/
|
||||
public function isDirectory()
|
||||
{
|
||||
return ($this->mode & UnixStat::UNX_IFDIR) !== 0 && !$this->isLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mode
|
||||
*/
|
||||
public function setMode($mode)
|
||||
{
|
||||
$this->mode = $this->getPermissionsMode($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
*/
|
||||
public function setUserId($uid)
|
||||
{
|
||||
$this->uid = (int) $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGroupId()
|
||||
{
|
||||
return $this->gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $gid
|
||||
*/
|
||||
public function setGroupId($gid)
|
||||
{
|
||||
$this->gid = (int) $gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x ASI: Mode=%o UID=%d GID=%d Link="%s',
|
||||
self::HEADER_ID,
|
||||
$this->mode,
|
||||
$this->uid,
|
||||
$this->gid,
|
||||
$this->link
|
||||
);
|
||||
}
|
||||
}
|
446
vendor/nelexa/zip/src/Model/Extra/Fields/ExtendedTimestampExtraField.php
vendored
Normal file
446
vendor/nelexa/zip/src/Model/Extra/Fields/ExtendedTimestampExtraField.php
vendored
Normal file
@ -0,0 +1,446 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Extended Timestamp Extra Field:
|
||||
* ==============================.
|
||||
*
|
||||
* The following is the layout of the extended-timestamp extra block.
|
||||
* (Last Revision 19970118)
|
||||
*
|
||||
* Local-header version:
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (time) 0x5455 Short tag for this extra block type ("UT")
|
||||
* TSize Short total data size for this block
|
||||
* Flags Byte info bits
|
||||
* (ModTime) Long time of last modification (UTC/GMT)
|
||||
* (AcTime) Long time of last access (UTC/GMT)
|
||||
* (CrTime) Long time of original creation (UTC/GMT)
|
||||
*
|
||||
* Central-header version:
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (time) 0x5455 Short tag for this extra block type ("UT")
|
||||
* TSize Short total data size for this block
|
||||
* Flags Byte info bits (refers to local header!)
|
||||
* (ModTime) Long time of last modification (UTC/GMT)
|
||||
*
|
||||
* The central-header extra field contains the modification time only,
|
||||
* or no timestamp at all. TSize is used to flag its presence or
|
||||
* absence. But note:
|
||||
*
|
||||
* If "Flags" indicates that Modtime is present in the local header
|
||||
* field, it MUST be present in the central header field, too!
|
||||
* This correspondence is required because the modification time
|
||||
* value may be used to support trans-timezone freshening and
|
||||
* updating operations with zip archives.
|
||||
*
|
||||
* The time values are in standard Unix signed-long format, indicating
|
||||
* the number of seconds since 1 January 1970 00:00:00. The times
|
||||
* are relative to Coordinated Universal Time (UTC), also sometimes
|
||||
* referred to as Greenwich Mean Time (GMT). To convert to local time,
|
||||
* the software must know the local timezone offset from UTC/GMT.
|
||||
*
|
||||
* The lower three bits of Flags in both headers indicate which time-
|
||||
* stamps are present in the LOCAL extra field:
|
||||
*
|
||||
* bit 0 if set, modification time is present
|
||||
* bit 1 if set, access time is present
|
||||
* bit 2 if set, creation time is present
|
||||
* bits 3-7 reserved for additional timestamps; not set
|
||||
*
|
||||
* Those times that are present will appear in the order indicated, but
|
||||
* any combination of times may be omitted. (Creation time may be
|
||||
* present without access time, for example.) TSize should equal
|
||||
* (1 + 4*(number of set bits in Flags)), as the block is currently
|
||||
* defined. Other timestamps may be added in the future.
|
||||
*
|
||||
* @see ftp://ftp.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip Info-ZIP version Specification
|
||||
*/
|
||||
class ExtendedTimestampExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id */
|
||||
const HEADER_ID = 0x5455;
|
||||
|
||||
/**
|
||||
* @var int the bit set inside the flags by when the last modification time
|
||||
* is present in this extra field
|
||||
*/
|
||||
const MODIFY_TIME_BIT = 1;
|
||||
|
||||
/**
|
||||
* @var int the bit set inside the flags by when the last access time is
|
||||
* present in this extra field
|
||||
*/
|
||||
const ACCESS_TIME_BIT = 2;
|
||||
|
||||
/**
|
||||
* @var int the bit set inside the flags by when the original creation time
|
||||
* is present in this extra field
|
||||
*/
|
||||
const CREATE_TIME_BIT = 4;
|
||||
|
||||
/**
|
||||
* @var int The 3 boolean fields (below) come from this flags byte. The remaining 5 bits
|
||||
* are ignored according to the current version of the spec (December 2012).
|
||||
*/
|
||||
private $flags;
|
||||
|
||||
/** @var int|null Modify time */
|
||||
private $modifyTime;
|
||||
|
||||
/** @var int|null Access time */
|
||||
private $accessTime;
|
||||
|
||||
/** @var int|null Create time */
|
||||
private $createTime;
|
||||
|
||||
/**
|
||||
* @param int $flags
|
||||
* @param int|null $modifyTime
|
||||
* @param int|null $accessTime
|
||||
* @param int|null $createTime
|
||||
*/
|
||||
public function __construct($flags, $modifyTime, $accessTime, $createTime)
|
||||
{
|
||||
$this->flags = (int) $flags;
|
||||
$this->modifyTime = $modifyTime;
|
||||
$this->accessTime = $accessTime;
|
||||
$this->createTime = $createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $modifyTime
|
||||
* @param int|null $accessTime
|
||||
* @param int|null $createTime
|
||||
*
|
||||
* @return ExtendedTimestampExtraField
|
||||
*/
|
||||
public static function create($modifyTime, $accessTime, $createTime)
|
||||
{
|
||||
$flags = 0;
|
||||
|
||||
if ($modifyTime !== null) {
|
||||
$modifyTime = (int) $modifyTime;
|
||||
$flags |= self::MODIFY_TIME_BIT;
|
||||
}
|
||||
|
||||
if ($accessTime !== null) {
|
||||
$accessTime = (int) $accessTime;
|
||||
$flags |= self::ACCESS_TIME_BIT;
|
||||
}
|
||||
|
||||
if ($createTime !== null) {
|
||||
$createTime = (int) $createTime;
|
||||
$flags |= self::CREATE_TIME_BIT;
|
||||
}
|
||||
|
||||
return new self($flags, $modifyTime, $accessTime, $createTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return ExtendedTimestampExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
$flags = unpack('C', $buffer)[1];
|
||||
$offset = 1;
|
||||
|
||||
$modifyTime = null;
|
||||
$accessTime = null;
|
||||
$createTime = null;
|
||||
|
||||
if (($flags & self::MODIFY_TIME_BIT) === self::MODIFY_TIME_BIT) {
|
||||
$modifyTime = unpack('V', substr($buffer, $offset, 4))[1];
|
||||
$offset += 4;
|
||||
}
|
||||
|
||||
// Notice the extra length check in case we are parsing the shorter
|
||||
// central data field (for both access and create timestamps).
|
||||
if ((($flags & self::ACCESS_TIME_BIT) === self::ACCESS_TIME_BIT) && $offset + 4 <= $length) {
|
||||
$accessTime = unpack('V', substr($buffer, $offset, 4))[1];
|
||||
$offset += 4;
|
||||
}
|
||||
|
||||
if ((($flags & self::CREATE_TIME_BIT) === self::CREATE_TIME_BIT) && $offset + 4 <= $length) {
|
||||
$createTime = unpack('V', substr($buffer, $offset, 4))[1];
|
||||
}
|
||||
|
||||
return new self($flags, $modifyTime, $accessTime, $createTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return ExtendedTimestampExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
if (($this->flags & self::MODIFY_TIME_BIT) === self::MODIFY_TIME_BIT && $this->modifyTime !== null) {
|
||||
$data .= pack('V', $this->modifyTime);
|
||||
}
|
||||
|
||||
if (($this->flags & self::ACCESS_TIME_BIT) === self::ACCESS_TIME_BIT && $this->accessTime !== null) {
|
||||
$data .= pack('V', $this->accessTime);
|
||||
}
|
||||
|
||||
if (($this->flags & self::CREATE_TIME_BIT) === self::CREATE_TIME_BIT && $this->createTime !== null) {
|
||||
$data .= pack('V', $this->createTime);
|
||||
}
|
||||
|
||||
return pack('C', $this->flags) . $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* Note: even if bit1 and bit2 are set, the Central data will still
|
||||
* not contain access/create fields: only local data ever holds those!
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
$cdLength = 1 + ($this->modifyTime !== null ? 4 : 0);
|
||||
|
||||
return substr($this->packLocalFileData(), 0, $cdLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets flags byte.
|
||||
*
|
||||
* The flags byte tells us which of the three datestamp fields are
|
||||
* present in the data:
|
||||
* bit0 - modify time
|
||||
* bit1 - access time
|
||||
* bit2 - create time
|
||||
*
|
||||
* Only first 3 bits of flags are used according to the
|
||||
* latest version of the spec (December 2012).
|
||||
*
|
||||
* @return int flags byte indicating which of the
|
||||
* three datestamp fields are present
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modify time (seconds since epoch) of this zip entry,
|
||||
* or null if no such timestamp exists in the zip entry.
|
||||
*
|
||||
* @return int|null modify time (seconds since epoch) or null
|
||||
*/
|
||||
public function getModifyTime()
|
||||
{
|
||||
return $this->modifyTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access time (seconds since epoch) of this zip entry,
|
||||
* or null if no such timestamp exists in the zip entry.
|
||||
*
|
||||
* @return int|null access time (seconds since epoch) or null
|
||||
*/
|
||||
public function getAccessTime()
|
||||
{
|
||||
return $this->accessTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the create time (seconds since epoch) of this zip entry,
|
||||
* or null if no such timestamp exists in the zip entry.
|
||||
*
|
||||
* Note: modern linux file systems (e.g., ext2)
|
||||
* do not appear to store a "create time" value, and so
|
||||
* it's usually omitted altogether in the zip extra
|
||||
* field. Perhaps other unix systems track this.
|
||||
*
|
||||
* @return int|null create time (seconds since epoch) or null
|
||||
*/
|
||||
public function getCreateTime()
|
||||
{
|
||||
return $this->createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modify time as a \DateTimeInterface
|
||||
* of this zip entry, or null if no such timestamp exists in the zip entry.
|
||||
* The milliseconds are always zeroed out, since the underlying data
|
||||
* offers only per-second precision.
|
||||
*
|
||||
* @return \DateTimeInterface|null modify time as \DateTimeInterface or null
|
||||
*/
|
||||
public function getModifyDateTime()
|
||||
{
|
||||
return self::timestampToDateTime($this->modifyTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access time as a \DateTimeInterface
|
||||
* of this zip entry, or null if no such timestamp exists in the zip entry.
|
||||
* The milliseconds are always zeroed out, since the underlying data
|
||||
* offers only per-second precision.
|
||||
*
|
||||
* @return \DateTimeInterface|null access time as \DateTimeInterface or null
|
||||
*/
|
||||
public function getAccessDateTime()
|
||||
{
|
||||
return self::timestampToDateTime($this->accessTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the create time as a a \DateTimeInterface
|
||||
* of this zip entry, or null if no such timestamp exists in the zip entry.
|
||||
* The milliseconds are always zeroed out, since the underlying data
|
||||
* offers only per-second precision.
|
||||
*
|
||||
* Note: modern linux file systems (e.g., ext2)
|
||||
* do not appear to store a "create time" value, and so
|
||||
* it's usually omitted altogether in the zip extra
|
||||
* field. Perhaps other unix systems track $this->.
|
||||
*
|
||||
* @return \DateTimeInterface|null create time as \DateTimeInterface or null
|
||||
*/
|
||||
public function getCreateDateTime()
|
||||
{
|
||||
return self::timestampToDateTime($this->createTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the modify time (seconds since epoch) of this zip entry
|
||||
* using a integer.
|
||||
*
|
||||
* @param int|null $unixTime unix time of the modify time (seconds per epoch) or null
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the access time (seconds since epoch) of this zip entry
|
||||
* using a integer.
|
||||
*
|
||||
* @param int|null $unixTime Unix time of the access time (seconds per epoch) or null
|
||||
*/
|
||||
public function setAccessTime($unixTime)
|
||||
{
|
||||
$this->accessTime = $unixTime;
|
||||
$this->updateFlags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the create time (seconds since epoch) of this zip entry
|
||||
* using a integer.
|
||||
*
|
||||
* @param int|null $unixTime Unix time of the create time (seconds per epoch) or null
|
||||
*/
|
||||
public function setCreateTime($unixTime)
|
||||
{
|
||||
$this->createTime = $unixTime;
|
||||
$this->updateFlags();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $timestamp
|
||||
*
|
||||
* @return \DateTimeInterface|null
|
||||
*/
|
||||
private static function timestampToDateTime($timestamp)
|
||||
{
|
||||
try {
|
||||
return $timestamp !== null ? new \DateTimeImmutable('@' . $timestamp) : null;
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$args = [self::HEADER_ID];
|
||||
$format = '0x%04x ExtendedTimestamp:';
|
||||
|
||||
if ($this->modifyTime !== null) {
|
||||
$format .= ' Modify:[%s]';
|
||||
$args[] = date(\DATE_W3C, $this->modifyTime);
|
||||
}
|
||||
|
||||
if ($this->accessTime !== null) {
|
||||
$format .= ' Access:[%s]';
|
||||
$args[] = date(\DATE_W3C, $this->accessTime);
|
||||
}
|
||||
|
||||
if ($this->createTime !== null) {
|
||||
$format .= ' Create:[%s]';
|
||||
$args[] = date(\DATE_W3C, $this->createTime);
|
||||
}
|
||||
|
||||
return vsprintf($format, $args);
|
||||
}
|
||||
}
|
118
vendor/nelexa/zip/src/Model/Extra/Fields/JarMarkerExtraField.php
vendored
Normal file
118
vendor/nelexa/zip/src/Model/Extra/Fields/JarMarkerExtraField.php
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipContainer;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Jar Marker Extra Field.
|
||||
* An executable Java program can be packaged in a JAR file with all the libraries it uses.
|
||||
* Executable JAR files can easily be distinguished from the files packed in the JAR file
|
||||
* by the extra field in the first file, which is hexadecimal in the 0xCAFE bytes series.
|
||||
* If this extra field is added as the very first extra field of
|
||||
* the archive, Solaris will consider it an executable jar file.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
class JarMarkerExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id. */
|
||||
const HEADER_ID = 0xCAFE;
|
||||
|
||||
/**
|
||||
* @param ZipContainer $container
|
||||
*/
|
||||
public static function setJarMarker(ZipContainer $container)
|
||||
{
|
||||
$zipEntries = $container->getEntries();
|
||||
|
||||
if (!empty($zipEntries)) {
|
||||
foreach ($zipEntries as $zipEntry) {
|
||||
$zipEntry->removeExtraField(self::HEADER_ID);
|
||||
}
|
||||
// set jar execute bit
|
||||
reset($zipEntries);
|
||||
$zipEntry = current($zipEntries);
|
||||
$zipEntry->getCdExtraFields()[] = new self();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return JarMarkerExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
if (!empty($buffer)) {
|
||||
throw new ZipException("JarMarker doesn't expect any data");
|
||||
}
|
||||
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return JarMarkerExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf('0x%04x Jar Marker', self::HEADER_ID);
|
||||
}
|
||||
}
|
237
vendor/nelexa/zip/src/Model/Extra/Fields/NewUnixExtraField.php
vendored
Normal file
237
vendor/nelexa/zip/src/Model/Extra/Fields/NewUnixExtraField.php
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Info-ZIP New Unix Extra Field:
|
||||
* ====================================.
|
||||
*
|
||||
* Currently stores Unix UIDs/GIDs up to 32 bits.
|
||||
* (Last Revision 20080509)
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (UnixN) 0x7875 Short tag for this extra block type ("ux")
|
||||
* TSize Short total data size for this block
|
||||
* Version 1 byte version of this extra field, currently 1
|
||||
* UIDSize 1 byte Size of UID field
|
||||
* UID Variable UID for this entry
|
||||
* GIDSize 1 byte Size of GID field
|
||||
* GID Variable GID for this entry
|
||||
*
|
||||
* Currently Version is set to the number 1. If there is a need
|
||||
* to change this field, the version will be incremented. Changes
|
||||
* may not be backward compatible so this extra field should not be
|
||||
* used if the version is not recognized.
|
||||
*
|
||||
* UIDSize is the size of the UID field in bytes. This size should
|
||||
* match the size of the UID field on the target OS.
|
||||
*
|
||||
* UID is the UID for this entry in standard little endian format.
|
||||
*
|
||||
* GIDSize is the size of the GID field in bytes. This size should
|
||||
* match the size of the GID field on the target OS.
|
||||
*
|
||||
* GID is the GID for this entry in standard little endian format.
|
||||
*
|
||||
* If both the old 16-bit Unix extra field (tag 0x7855, Info-ZIP Unix)
|
||||
* and this extra field are present, the values in this extra field
|
||||
* supercede the values in that extra field.
|
||||
*/
|
||||
class NewUnixExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int header id */
|
||||
const HEADER_ID = 0x7875;
|
||||
|
||||
/** ID of the first non-root user created on a unix system. */
|
||||
const USER_GID_PID = 1000;
|
||||
|
||||
/** @var int version of this extra field, currently 1 */
|
||||
private $version = 1;
|
||||
|
||||
/** @var int User id */
|
||||
private $uid;
|
||||
|
||||
/** @var int Group id */
|
||||
private $gid;
|
||||
|
||||
/**
|
||||
* NewUnixExtraField constructor.
|
||||
*
|
||||
* @param int $version
|
||||
* @param int $uid
|
||||
* @param int $gid
|
||||
*/
|
||||
public function __construct($version = 1, $uid = self::USER_GID_PID, $gid = self::USER_GID_PID)
|
||||
{
|
||||
$this->version = (int) $version;
|
||||
$this->uid = (int) $uid;
|
||||
$this->gid = (int) $gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return NewUnixExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
|
||||
if ($length < 3) {
|
||||
throw new ZipException(sprintf('X7875_NewUnix length is too short, only %s bytes', $length));
|
||||
}
|
||||
$offset = 0;
|
||||
$data = unpack('Cversion/CuidSize', $buffer);
|
||||
$offset += 2;
|
||||
$uidSize = $data['uidSize'];
|
||||
$gid = self::readSizeIntegerLE(substr($buffer, $offset, $uidSize), $uidSize);
|
||||
$offset += $uidSize;
|
||||
$gidSize = unpack('C', $buffer[$offset])[1];
|
||||
$offset++;
|
||||
$uid = self::readSizeIntegerLE(substr($buffer, $offset, $gidSize), $gidSize);
|
||||
|
||||
return new self($data['version'], $gid, $uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return NewUnixExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return pack(
|
||||
'CCVCV',
|
||||
$this->version,
|
||||
4, // UIDSize
|
||||
$this->uid,
|
||||
4, // GIDSize
|
||||
$this->gid
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @param int $size
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function readSizeIntegerLE($data, $size)
|
||||
{
|
||||
$format = [
|
||||
1 => 'C', // unsigned byte
|
||||
2 => 'v', // unsigned short LE
|
||||
4 => 'V', // unsigned int LE
|
||||
];
|
||||
|
||||
if (!isset($format[$size])) {
|
||||
throw new ZipException(sprintf('Invalid size bytes: %d', $size));
|
||||
}
|
||||
|
||||
return unpack($format[$size], $data)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUid()
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
*/
|
||||
public function setUid($uid)
|
||||
{
|
||||
$this->uid = $uid & 0xffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGid()
|
||||
{
|
||||
return $this->gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $gid
|
||||
*/
|
||||
public function setGid($gid)
|
||||
{
|
||||
$this->gid = $gid & 0xffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x NewUnix: UID=%d GID=%d',
|
||||
self::HEADER_ID,
|
||||
$this->uid,
|
||||
$this->gid
|
||||
);
|
||||
}
|
||||
}
|
339
vendor/nelexa/zip/src/Model/Extra/Fields/NtfsExtraField.php
vendored
Normal file
339
vendor/nelexa/zip/src/Model/Extra/Fields/NtfsExtraField.php
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* NTFS Extra Field.
|
||||
*
|
||||
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
class NtfsExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id */
|
||||
const HEADER_ID = 0x000a;
|
||||
|
||||
/** @var int Tag ID */
|
||||
const TIME_ATTR_TAG = 0x0001;
|
||||
|
||||
/** @var int Attribute size */
|
||||
const TIME_ATTR_SIZE = 24; // 3 * 8
|
||||
|
||||
/**
|
||||
* @var int A file time is a 64-bit value that represents the number of
|
||||
* 100-nanosecond intervals that have elapsed since 12:00
|
||||
* 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 = -116444736000000000;
|
||||
|
||||
/** @var int Modify ntfs time */
|
||||
private $modifyNtfsTime;
|
||||
|
||||
/** @var int Access ntfs time */
|
||||
private $accessNtfsTime;
|
||||
|
||||
/** @var int Create ntfs time */
|
||||
private $createNtfsTime;
|
||||
|
||||
/**
|
||||
* @param int $modifyNtfsTime
|
||||
* @param int $accessNtfsTime
|
||||
* @param int $createNtfsTime
|
||||
*/
|
||||
public function __construct($modifyNtfsTime, $accessNtfsTime, $createNtfsTime)
|
||||
{
|
||||
$this->modifyNtfsTime = (int) $modifyNtfsTime;
|
||||
$this->accessNtfsTime = (int) $accessNtfsTime;
|
||||
$this->createNtfsTime = (int) $createNtfsTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $modifyDateTime
|
||||
* @param \DateTimeInterface $accessDateTime
|
||||
* @param \DateTimeInterface $createNtfsTime
|
||||
*
|
||||
* @return NtfsExtraField
|
||||
*/
|
||||
public static function create(
|
||||
\DateTimeInterface $modifyDateTime,
|
||||
\DateTimeInterface $accessDateTime,
|
||||
\DateTimeInterface $createNtfsTime
|
||||
) {
|
||||
return new self(
|
||||
self::dateTimeToNtfsTime($modifyDateTime),
|
||||
self::dateTimeToNtfsTime($accessDateTime),
|
||||
self::dateTimeToNtfsTime($createNtfsTime)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @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;
|
||||
$accessTime = 0;
|
||||
$createTime = 0;
|
||||
|
||||
while ($buffer || $buffer !== '') {
|
||||
$unpack = unpack('vtag/vsizeAttr', $buffer);
|
||||
|
||||
if ($unpack['tag'] === self::TIME_ATTR_TAG && $unpack['sizeAttr'] === self::TIME_ATTR_SIZE) {
|
||||
// refactoring will be needed when php 5.5 support ends
|
||||
$modifyTime = PackUtil::unpackLongLE(substr($buffer, 4, 8));
|
||||
$accessTime = PackUtil::unpackLongLE(substr($buffer, 12, 8));
|
||||
$createTime = PackUtil::unpackLongLE(substr($buffer, 20, 8));
|
||||
|
||||
break;
|
||||
}
|
||||
$buffer = substr($buffer, 4 + $unpack['sizeAttr']);
|
||||
}
|
||||
|
||||
return new self($modifyTime, $accessTime, $createTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
$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->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.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getModifyDateTime()
|
||||
{
|
||||
return self::ntfsTimeToDateTime($this->modifyNtfsTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $modifyTime
|
||||
*/
|
||||
public function setModifyDateTime(\DateTimeInterface $modifyTime)
|
||||
{
|
||||
$this->modifyNtfsTime = self::dateTimeToNtfsTime($modifyTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getAccessDateTime()
|
||||
{
|
||||
return self::ntfsTimeToDateTime($this->accessNtfsTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $accessTime
|
||||
*/
|
||||
public function setAccessDateTime(\DateTimeInterface $accessTime)
|
||||
{
|
||||
$this->accessNtfsTime = self::dateTimeToNtfsTime($accessTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getCreateDateTime()
|
||||
{
|
||||
return self::ntfsTimeToDateTime($this->createNtfsTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $createTime
|
||||
*/
|
||||
public function setCreateDateTime(\DateTimeInterface $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $dateTime
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function dateTimeToNtfsTime(\DateTimeInterface $dateTime)
|
||||
{
|
||||
return self::timestampToNtfsTime((float) $dateTime->format('U.u'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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($ntfsTime)
|
||||
{
|
||||
$timestamp = self::ntfsTimeToTimestamp($ntfsTime);
|
||||
$dateTime = \DateTimeImmutable::createFromFormat('U.u', sprintf('%.6f', $timestamp));
|
||||
|
||||
if ($dateTime === false) {
|
||||
throw new InvalidArgumentException('Cannot create date/time object for timestamp ' . $timestamp);
|
||||
}
|
||||
|
||||
return $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$args = [self::HEADER_ID];
|
||||
$format = '0x%04x NtfsExtra:';
|
||||
|
||||
if ($this->modifyNtfsTime !== 0) {
|
||||
$format .= ' Modify:[%s]';
|
||||
$args[] = $this->getModifyDateTime()->format(\DATE_ATOM);
|
||||
}
|
||||
|
||||
if ($this->accessNtfsTime !== 0) {
|
||||
$format .= ' Access:[%s]';
|
||||
$args[] = $this->getAccessDateTime()->format(\DATE_ATOM);
|
||||
}
|
||||
|
||||
if ($this->createNtfsTime !== 0) {
|
||||
$format .= ' Create:[%s]';
|
||||
$args[] = $this->getCreateDateTime()->format(\DATE_ATOM);
|
||||
}
|
||||
|
||||
return vsprintf($format, $args);
|
||||
}
|
||||
}
|
327
vendor/nelexa/zip/src/Model/Extra/Fields/OldUnixExtraField.php
vendored
Normal file
327
vendor/nelexa/zip/src/Model/Extra/Fields/OldUnixExtraField.php
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Info-ZIP Unix Extra Field (type 1):
|
||||
* ==================================.
|
||||
*
|
||||
* The following is the layout of the old Info-ZIP extra block for
|
||||
* Unix. It has been replaced by the extended-timestamp extra block
|
||||
* (0x5455) and the Unix type 2 extra block (0x7855).
|
||||
* (Last Revision 19970118)
|
||||
*
|
||||
* Local-header version:
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (Unix1) 0x5855 Short tag for this extra block type ("UX")
|
||||
* TSize Short total data size for this block
|
||||
* AcTime Long time of last access (UTC/GMT)
|
||||
* ModTime Long time of last modification (UTC/GMT)
|
||||
* UID Short Unix user ID (optional)
|
||||
* GID Short Unix group ID (optional)
|
||||
*
|
||||
* Central-header version:
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (Unix1) 0x5855 Short tag for this extra block type ("UX")
|
||||
* TSize Short total data size for this block
|
||||
* AcTime Long time of last access (GMT/UTC)
|
||||
* ModTime Long time of last modification (GMT/UTC)
|
||||
*
|
||||
* The file access and modification times are in standard Unix signed-
|
||||
* long format, indicating the number of seconds since 1 January 1970
|
||||
* 00:00:00. The times are relative to Coordinated Universal Time
|
||||
* (UTC), also sometimes referred to as Greenwich Mean Time (GMT). To
|
||||
* convert to local time, the software must know the local timezone
|
||||
* offset from UTC/GMT. The modification time may be used by non-Unix
|
||||
* systems to support inter-timezone freshening and updating of zip
|
||||
* archives.
|
||||
*
|
||||
* The local-header extra block may optionally contain UID and GID
|
||||
* info for the file. The local-header TSize value is the only
|
||||
* indication of this. Note that Unix UIDs and GIDs are usually
|
||||
* specific to a particular machine, and they generally require root
|
||||
* access to restore.
|
||||
*
|
||||
* This extra field type is obsolete, but it has been in use since
|
||||
* mid-1994. Therefore future archiving software should continue to
|
||||
* support it.
|
||||
*/
|
||||
class OldUnixExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id */
|
||||
const HEADER_ID = 0x5855;
|
||||
|
||||
/** @var int|null Access timestamp */
|
||||
private $accessTime;
|
||||
|
||||
/** @var int|null Modify timestamp */
|
||||
private $modifyTime;
|
||||
|
||||
/** @var int|null User id */
|
||||
private $uid;
|
||||
|
||||
/** @var int|null Group id */
|
||||
private $gid;
|
||||
|
||||
/**
|
||||
* @param int|null $accessTime
|
||||
* @param int|null $modifyTime
|
||||
* @param int|null $uid
|
||||
* @param int|null $gid
|
||||
*/
|
||||
public function __construct($accessTime, $modifyTime, $uid, $gid)
|
||||
{
|
||||
$this->accessTime = $accessTime;
|
||||
$this->modifyTime = $modifyTime;
|
||||
$this->uid = $uid;
|
||||
$this->gid = $gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return OldUnixExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
|
||||
$accessTime = $modifyTime = $uid = $gid = null;
|
||||
|
||||
if ($length >= 4) {
|
||||
$accessTime = unpack('V', $buffer)[1];
|
||||
}
|
||||
|
||||
if ($length >= 8) {
|
||||
$modifyTime = unpack('V', substr($buffer, 4, 4))[1];
|
||||
}
|
||||
|
||||
if ($length >= 10) {
|
||||
$uid = unpack('v', substr($buffer, 8, 2))[1];
|
||||
}
|
||||
|
||||
if ($length >= 12) {
|
||||
$gid = unpack('v', substr($buffer, 10, 2))[1];
|
||||
}
|
||||
|
||||
return new self($accessTime, $modifyTime, $uid, $gid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return OldUnixExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
|
||||
$accessTime = $modifyTime = null;
|
||||
|
||||
if ($length >= 4) {
|
||||
$accessTime = unpack('V', $buffer)[1];
|
||||
}
|
||||
|
||||
if ($length >= 8) {
|
||||
$modifyTime = unpack('V', substr($buffer, 4, 4))[1];
|
||||
}
|
||||
|
||||
return new self($accessTime, $modifyTime, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
if ($this->accessTime !== null) {
|
||||
$data .= pack('V', $this->accessTime);
|
||||
|
||||
if ($this->modifyTime !== null) {
|
||||
$data .= pack('V', $this->modifyTime);
|
||||
|
||||
if ($this->uid !== null) {
|
||||
$data .= pack('v', $this->uid);
|
||||
|
||||
if ($this->gid !== null) {
|
||||
$data .= pack('v', $this->gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
if ($this->accessTime !== null) {
|
||||
$data .= pack('V', $this->accessTime);
|
||||
|
||||
if ($this->modifyTime !== null) {
|
||||
$data .= pack('V', $this->modifyTime);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getAccessTime()
|
||||
{
|
||||
return $this->accessTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $accessTime
|
||||
*/
|
||||
public function setAccessTime($accessTime)
|
||||
{
|
||||
$this->accessTime = $accessTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface|null
|
||||
*/
|
||||
public function getAccessDateTime()
|
||||
{
|
||||
try {
|
||||
return $this->accessTime === null ? null :
|
||||
new \DateTimeImmutable('@' . $this->accessTime);
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getModifyTime()
|
||||
{
|
||||
return $this->modifyTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $modifyTime
|
||||
*/
|
||||
public function setModifyTime($modifyTime)
|
||||
{
|
||||
$this->modifyTime = $modifyTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface|null
|
||||
*/
|
||||
public function getModifyDateTime()
|
||||
{
|
||||
try {
|
||||
return $this->modifyTime === null ? null :
|
||||
new \DateTimeImmutable('@' . $this->modifyTime);
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUid()
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $uid
|
||||
*/
|
||||
public function setUid($uid)
|
||||
{
|
||||
$this->uid = $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getGid()
|
||||
{
|
||||
return $this->gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $gid
|
||||
*/
|
||||
public function setGid($gid)
|
||||
{
|
||||
$this->gid = $gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$args = [self::HEADER_ID];
|
||||
$format = '0x%04x OldUnix:';
|
||||
|
||||
if (($modifyTime = $this->getModifyDateTime()) !== null) {
|
||||
$format .= ' Modify:[%s]';
|
||||
$args[] = $modifyTime->format(\DATE_ATOM);
|
||||
}
|
||||
|
||||
if (($accessTime = $this->getAccessDateTime()) !== null) {
|
||||
$format .= ' Access:[%s]';
|
||||
$args[] = $accessTime->format(\DATE_ATOM);
|
||||
}
|
||||
|
||||
if ($this->uid !== null) {
|
||||
$format .= ' UID=%d';
|
||||
$args[] = $this->uid;
|
||||
}
|
||||
|
||||
if ($this->gid !== null) {
|
||||
$format .= ' GID=%d';
|
||||
$args[] = $this->gid;
|
||||
}
|
||||
|
||||
return vsprintf($format, $args);
|
||||
}
|
||||
}
|
76
vendor/nelexa/zip/src/Model/Extra/Fields/UnicodeCommentExtraField.php
vendored
Normal file
76
vendor/nelexa/zip/src/Model/Extra/Fields/UnicodeCommentExtraField.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
/**
|
||||
* Info-ZIP Unicode Comment Extra Field (0x6375):.
|
||||
*
|
||||
* Stores the UTF-8 version of the file comment as stored in the
|
||||
* central directory header. (Last Revision 20070912)
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (UCom) 0x6375 Short tag for this extra block type ("uc")
|
||||
* TSize Short total data size for this block
|
||||
* Version 1 byte version of this extra field, currently 1
|
||||
* ComCRC32 4 bytes Comment Field CRC32 Checksum
|
||||
* UnicodeCom Variable UTF-8 version of the entry comment
|
||||
*
|
||||
* Currently Version is set to the number 1. If there is a need
|
||||
* to change this field, the version will be incremented. Changes
|
||||
* may not be backward compatible so this extra field should not be
|
||||
* used if the version is not recognized.
|
||||
*
|
||||
* The ComCRC32 is the standard zip CRC32 checksum of the File Comment
|
||||
* field in the central directory header. This is used to verify that
|
||||
* the comment field has not changed since the Unicode Comment extra field
|
||||
* was created. This can happen if a utility changes the File Comment
|
||||
* field but does not update the UTF-8 Comment extra field. If the CRC
|
||||
* check fails, this Unicode Comment extra field should be ignored and
|
||||
* the File Comment field in the header should be used instead.
|
||||
*
|
||||
* The UnicodeCom field is the UTF-8 version of the File Comment field
|
||||
* in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte
|
||||
* order mark (BOM) is used. The length of this field is determined by
|
||||
* subtracting the size of the previous fields from TSize. If both the
|
||||
* File Name and Comment fields are UTF-8, the new General Purpose Bit
|
||||
* Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate
|
||||
* both the header File Name and Comment fields are UTF-8 and, in this
|
||||
* case, the Unicode Path and Unicode Comment extra fields are not
|
||||
* needed and should not be created. Note that, for backward
|
||||
* compatibility, bit 11 should only be used if the native character set
|
||||
* of the paths and comments being zipped up are already in UTF-8. It is
|
||||
* expected that the same file comment storage method, either general
|
||||
* purpose bit 11 or extra fields, be used in both the Local and Central
|
||||
* Directory Header for a file.
|
||||
*
|
||||
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.6.8
|
||||
*/
|
||||
class UnicodeCommentExtraField extends AbstractUnicodeExtraField
|
||||
{
|
||||
const HEADER_ID = 0x6375;
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x UnicodeComment: "%s"',
|
||||
self::HEADER_ID,
|
||||
$this->getUnicodeValue()
|
||||
);
|
||||
}
|
||||
}
|
77
vendor/nelexa/zip/src/Model/Extra/Fields/UnicodePathExtraField.php
vendored
Normal file
77
vendor/nelexa/zip/src/Model/Extra/Fields/UnicodePathExtraField.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
/**
|
||||
* Info-ZIP Unicode Path Extra Field (0x7075):
|
||||
* ==========================================.
|
||||
*
|
||||
* Stores the UTF-8 version of the file name field as stored in the
|
||||
* local header and central directory header. (Last Revision 20070912)
|
||||
*
|
||||
* Value Size Description
|
||||
* ----- ---- -----------
|
||||
* (UPath) 0x7075 Short tag for this extra block type ("up")
|
||||
* TSize Short total data size for this block
|
||||
* Version 1 byte version of this extra field, currently 1
|
||||
* NameCRC32 4 bytes File Name Field CRC32 Checksum
|
||||
* UnicodeName Variable UTF-8 version of the entry File Name
|
||||
*
|
||||
* Currently Version is set to the number 1. If there is a need
|
||||
* to change this field, the version will be incremented. Changes
|
||||
* may not be backward compatible so this extra field should not be
|
||||
* used if the version is not recognized.
|
||||
*
|
||||
* The NameCRC32 is the standard zip CRC32 checksum of the File Name
|
||||
* field in the header. This is used to verify that the header
|
||||
* File Name field has not changed since the Unicode Path extra field
|
||||
* was created. This can happen if a utility renames the File Name but
|
||||
* does not update the UTF-8 path extra field. If the CRC check fails,
|
||||
* this UTF-8 Path Extra Field should be ignored and the File Name field
|
||||
* in the header should be used instead.
|
||||
*
|
||||
* The UnicodeName is the UTF-8 version of the contents of the File Name
|
||||
* field in the header. As UnicodeName is defined to be UTF-8, no UTF-8
|
||||
* byte order mark (BOM) is used. The length of this field is determined
|
||||
* by subtracting the size of the previous fields from TSize. If both
|
||||
* the File Name and Comment fields are UTF-8, the new General Purpose
|
||||
* Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to
|
||||
* indicate that both the header File Name and Comment fields are UTF-8
|
||||
* and, in this case, the Unicode Path and Unicode Comment extra fields
|
||||
* are not needed and should not be created. Note that, for backward
|
||||
* compatibility, bit 11 should only be used if the native character set
|
||||
* of the paths and comments being zipped up are already in UTF-8. It is
|
||||
* expected that the same file name storage method, either general
|
||||
* purpose bit 11 or extra fields, be used in both the Local and Central
|
||||
* Directory Header for a file.
|
||||
*
|
||||
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.6.9
|
||||
*/
|
||||
class UnicodePathExtraField extends AbstractUnicodeExtraField
|
||||
{
|
||||
const HEADER_ID = 0x7075;
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x UnicodePath: "%s"',
|
||||
self::HEADER_ID,
|
||||
$this->getUnicodeValue()
|
||||
);
|
||||
}
|
||||
}
|
116
vendor/nelexa/zip/src/Model/Extra/Fields/UnrecognizedExtraField.php
vendored
Normal file
116
vendor/nelexa/zip/src/Model/Extra/Fields/UnrecognizedExtraField.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Exception\RuntimeException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Simple placeholder for all those extra fields we don't want to deal with.
|
||||
*/
|
||||
class UnrecognizedExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int */
|
||||
private $headerId;
|
||||
|
||||
/** @var string extra field data without Header-ID or length specifier */
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* UnrecognizedExtraField constructor.
|
||||
*
|
||||
* @param int $headerId
|
||||
* @param string $data
|
||||
*/
|
||||
public function __construct($headerId, $data)
|
||||
{
|
||||
$this->headerId = (int) $headerId;
|
||||
$this->data = (string) $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $headerId
|
||||
*/
|
||||
public function setHeaderId($headerId)
|
||||
{
|
||||
$this->headerId = $headerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return $this->headerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
throw new RuntimeException('Unsupport parse');
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
throw new RuntimeException('Unsupport parse');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = (string) $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$args = [$this->headerId, $this->data];
|
||||
$format = '0x%04x Unrecognized Extra Field: "%s"';
|
||||
|
||||
return vsprintf($format, $args);
|
||||
}
|
||||
}
|
387
vendor/nelexa/zip/src/Model/Extra/Fields/WinZipAesExtraField.php
vendored
Normal file
387
vendor/nelexa/zip/src/Model/Extra/Fields/WinZipAesExtraField.php
vendored
Normal file
@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Constants\ZipCompressionMethod;
|
||||
use PhpZip\Constants\ZipEncryptionMethod;
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Exception\ZipUnsupportMethodException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* WinZip AES Extra Field.
|
||||
*
|
||||
* @see http://www.winzip.com/win/en/aes_tips.htm AES Coding Tips for Developers
|
||||
*/
|
||||
class WinZipAesExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int Header id */
|
||||
const HEADER_ID = 0x9901;
|
||||
|
||||
/**
|
||||
* @var int Data size (currently 7, but subject to possible increase
|
||||
* in the future)
|
||||
*/
|
||||
const DATA_SIZE = 7;
|
||||
|
||||
/**
|
||||
* @var int The vendor ID field should always be set to the two ASCII
|
||||
* characters "AE"
|
||||
*/
|
||||
const VENDOR_ID = 0x4541; // 'A' | ('E' << 8)
|
||||
|
||||
/**
|
||||
* @var int Entries of this type do include the standard ZIP CRC-32 value.
|
||||
* For use with {@see WinZipAesExtraField::setVendorVersion()}.
|
||||
*/
|
||||
const VERSION_AE1 = 1;
|
||||
|
||||
/**
|
||||
* @var int Entries of this type do not include the standard ZIP CRC-32 value.
|
||||
* For use with {@see WinZipAesExtraField::setVendorVersion().
|
||||
*/
|
||||
const VERSION_AE2 = 2;
|
||||
|
||||
/** @var int integer mode value indicating AES encryption 128-bit strength */
|
||||
const KEY_STRENGTH_128BIT = 0x01;
|
||||
|
||||
/** @var int integer mode value indicating AES encryption 192-bit strength */
|
||||
const KEY_STRENGTH_192BIT = 0x02;
|
||||
|
||||
/** @var int integer mode value indicating AES encryption 256-bit strength */
|
||||
const KEY_STRENGTH_256BIT = 0x03;
|
||||
|
||||
/** @var int[] */
|
||||
private static $allowVendorVersions = [
|
||||
self::VERSION_AE1,
|
||||
self::VERSION_AE2,
|
||||
];
|
||||
|
||||
/** @var array<int, int> */
|
||||
private static $encryptionStrengths = [
|
||||
self::KEY_STRENGTH_128BIT => 128,
|
||||
self::KEY_STRENGTH_192BIT => 192,
|
||||
self::KEY_STRENGTH_256BIT => 256,
|
||||
];
|
||||
|
||||
/** @var array<int, int> */
|
||||
private static $MAP_KEY_STRENGTH_METHODS = [
|
||||
self::KEY_STRENGTH_128BIT => ZipEncryptionMethod::WINZIP_AES_128,
|
||||
self::KEY_STRENGTH_192BIT => ZipEncryptionMethod::WINZIP_AES_192,
|
||||
self::KEY_STRENGTH_256BIT => ZipEncryptionMethod::WINZIP_AES_256,
|
||||
];
|
||||
|
||||
/** @var int Integer version number specific to the zip vendor */
|
||||
private $vendorVersion = self::VERSION_AE1;
|
||||
|
||||
/** @var int Integer mode value indicating AES encryption strength */
|
||||
private $keyStrength = self::KEY_STRENGTH_256BIT;
|
||||
|
||||
/** @var int The actual compression method used to compress the file */
|
||||
private $compressionMethod;
|
||||
|
||||
/**
|
||||
* @param int $vendorVersion Integer version number specific to the zip vendor
|
||||
* @param int $keyStrength Integer mode value indicating AES encryption strength
|
||||
* @param int $compressionMethod The actual compression method used to compress the file
|
||||
*
|
||||
* @throws ZipUnsupportMethodException
|
||||
*/
|
||||
public function __construct($vendorVersion, $keyStrength, $compressionMethod)
|
||||
{
|
||||
$this->setVendorVersion($vendorVersion);
|
||||
$this->setKeyStrength($keyStrength);
|
||||
$this->setCompressionMethod($compressionMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
*
|
||||
* @throws ZipUnsupportMethodException
|
||||
*
|
||||
* @return WinZipAesExtraField
|
||||
*/
|
||||
public static function create(ZipEntry $entry)
|
||||
{
|
||||
$keyStrength = array_search($entry->getEncryptionMethod(), self::$MAP_KEY_STRENGTH_METHODS, true);
|
||||
|
||||
if ($keyStrength === false) {
|
||||
throw new InvalidArgumentException('Not support encryption method ' . $entry->getEncryptionMethod());
|
||||
}
|
||||
|
||||
// WinZip 11 will continue to use AE-2, with no CRC, for very small files
|
||||
// of less than 20 bytes. It will also use AE-2 for files compressed in
|
||||
// BZIP2 format, because this format has internal integrity checks
|
||||
// equivalent to a CRC check built in.
|
||||
//
|
||||
// https://www.winzip.com/win/en/aes_info.html
|
||||
$vendorVersion = (
|
||||
$entry->getUncompressedSize() < 20 ||
|
||||
$entry->getCompressionMethod() === ZipCompressionMethod::BZIP2
|
||||
) ?
|
||||
self::VERSION_AE2 :
|
||||
self::VERSION_AE1;
|
||||
|
||||
$field = new self($vendorVersion, $keyStrength, $entry->getCompressionMethod());
|
||||
|
||||
$entry->getLocalExtraFields()->add($field);
|
||||
$entry->getCdExtraFields()->add($field);
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return WinZipAesExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$size = \strlen($buffer);
|
||||
|
||||
if ($size !== self::DATA_SIZE) {
|
||||
throw new ZipException(
|
||||
sprintf(
|
||||
'WinZip AES Extra data invalid size: %d. Must be %d',
|
||||
$size,
|
||||
self::DATA_SIZE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$data = unpack('vvendorVersion/vvendorId/ckeyStrength/vcompressionMethod', $buffer);
|
||||
|
||||
if ($data['vendorId'] !== self::VENDOR_ID) {
|
||||
throw new ZipException(
|
||||
sprintf(
|
||||
'Vendor id invalid: %d. Must be %d',
|
||||
$data['vendorId'],
|
||||
self::VENDOR_ID
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return new self(
|
||||
$data['vendorVersion'],
|
||||
$data['keyStrength'],
|
||||
$data['compressionMethod']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return WinZipAesExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
return self::unpackLocalFileData($buffer, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
return pack(
|
||||
'vvcv',
|
||||
$this->vendorVersion,
|
||||
self::VENDOR_ID,
|
||||
$this->keyStrength,
|
||||
$this->compressionMethod
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
return $this->packLocalFileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vendor version.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @see WinZipAesExtraField::VERSION_AE2
|
||||
* @see WinZipAesExtraField::VERSION_AE1
|
||||
*/
|
||||
public function getVendorVersion()
|
||||
{
|
||||
return $this->vendorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vendor version.
|
||||
*
|
||||
* @param int $vendorVersion the vendor version
|
||||
*
|
||||
* @see WinZipAesExtraField::VERSION_AE2
|
||||
* @see WinZipAesExtraField::VERSION_AE1
|
||||
*/
|
||||
public function setVendorVersion($vendorVersion)
|
||||
{
|
||||
$vendorVersion = (int) $vendorVersion;
|
||||
|
||||
if (!\in_array($vendorVersion, self::$allowVendorVersions, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Unsupport WinZip AES vendor version: %d',
|
||||
$vendorVersion
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->vendorVersion = $vendorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns vendor id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getVendorId()
|
||||
{
|
||||
return self::VENDOR_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getKeyStrength()
|
||||
{
|
||||
return $this->keyStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set key strength.
|
||||
*
|
||||
* @param int $keyStrength
|
||||
*/
|
||||
public function setKeyStrength($keyStrength)
|
||||
{
|
||||
$keyStrength = (int) $keyStrength;
|
||||
|
||||
if (!isset(self::$encryptionStrengths[$keyStrength])) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Key strength %d not support value. Allow values: %s',
|
||||
$keyStrength,
|
||||
implode(', ', array_keys(self::$encryptionStrengths))
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->keyStrength = $keyStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCompressionMethod()
|
||||
{
|
||||
return $this->compressionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $compressionMethod
|
||||
*
|
||||
* @throws ZipUnsupportMethodException
|
||||
*/
|
||||
public function setCompressionMethod($compressionMethod)
|
||||
{
|
||||
$compressionMethod = (int) $compressionMethod;
|
||||
ZipCompressionMethod::checkSupport($compressionMethod);
|
||||
$this->compressionMethod = $compressionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getEncryptionStrength()
|
||||
{
|
||||
return self::$encryptionStrengths[$this->keyStrength];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getEncryptionMethod()
|
||||
{
|
||||
$keyStrength = $this->getKeyStrength();
|
||||
|
||||
if (!isset(self::$MAP_KEY_STRENGTH_METHODS[$keyStrength])) {
|
||||
throw new InvalidArgumentException('Invalid encryption method');
|
||||
}
|
||||
|
||||
return self::$MAP_KEY_STRENGTH_METHODS[$keyStrength];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isV1()
|
||||
{
|
||||
return $this->vendorVersion === self::VERSION_AE1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isV2()
|
||||
{
|
||||
return $this->vendorVersion === self::VERSION_AE2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSaltSize()
|
||||
{
|
||||
return (int) ($this->getEncryptionStrength() / 8 / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'0x%04x WINZIP AES: VendorVersion=%d KeyStrength=0x%02x CompressionMethod=%s',
|
||||
__CLASS__,
|
||||
$this->vendorVersion,
|
||||
$this->keyStrength,
|
||||
$this->compressionMethod
|
||||
);
|
||||
}
|
||||
}
|
311
vendor/nelexa/zip/src/Model/Extra/Fields/Zip64ExtraField.php
vendored
Normal file
311
vendor/nelexa/zip/src/Model/Extra/Fields/Zip64ExtraField.php
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra\Fields;
|
||||
|
||||
use PhpZip\Constants\ZipConstants;
|
||||
use PhpZip\Exception\RuntimeException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\Extra\ZipExtraField;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
use PhpZip\Util\PackUtil;
|
||||
|
||||
/**
|
||||
* ZIP64 Extra Field.
|
||||
*
|
||||
* @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
|
||||
*/
|
||||
class Zip64ExtraField implements ZipExtraField
|
||||
{
|
||||
/** @var int The Header ID for a ZIP64 Extended Information Extra Field. */
|
||||
const HEADER_ID = 0x0001;
|
||||
|
||||
/** @var int|null */
|
||||
private $uncompressedSize;
|
||||
|
||||
/** @var int|null */
|
||||
private $compressedSize;
|
||||
|
||||
/** @var int|null */
|
||||
private $localHeaderOffset;
|
||||
|
||||
/** @var int|null */
|
||||
private $diskStart;
|
||||
|
||||
/**
|
||||
* Zip64ExtraField constructor.
|
||||
*
|
||||
* @param int|null $uncompressedSize
|
||||
* @param int|null $compressedSize
|
||||
* @param int|null $localHeaderOffset
|
||||
* @param int|null $diskStart
|
||||
*/
|
||||
public function __construct(
|
||||
$uncompressedSize = null,
|
||||
$compressedSize = null,
|
||||
$localHeaderOffset = null,
|
||||
$diskStart = null
|
||||
) {
|
||||
$this->uncompressedSize = $uncompressedSize;
|
||||
$this->compressedSize = $compressedSize;
|
||||
$this->localHeaderOffset = $localHeaderOffset;
|
||||
$this->diskStart = $diskStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId()
|
||||
{
|
||||
return self::HEADER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException on error
|
||||
*
|
||||
* @return Zip64ExtraField
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
$length = \strlen($buffer);
|
||||
|
||||
if ($length === 0) {
|
||||
// no local file data at all, may happen if an archive
|
||||
// only holds a ZIP64 extended information extra field
|
||||
// inside the central directory but not inside the local
|
||||
// file header
|
||||
return new self();
|
||||
}
|
||||
|
||||
if ($length < 16) {
|
||||
throw new ZipException(
|
||||
'Zip64 extended information must contain both size values in the local file header.'
|
||||
);
|
||||
}
|
||||
|
||||
$uncompressedSize = PackUtil::unpackLongLE(substr($buffer, 0, 8));
|
||||
$compressedSize = PackUtil::unpackLongLE(substr($buffer, 8, 8));
|
||||
|
||||
return new self($uncompressedSize, $compressedSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return Zip64ExtraField
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
|
||||
{
|
||||
if ($entry === null) {
|
||||
throw new RuntimeException('zipEntry is null');
|
||||
}
|
||||
|
||||
$length = \strlen($buffer);
|
||||
$remaining = $length;
|
||||
|
||||
$uncompressedSize = null;
|
||||
$compressedSize = null;
|
||||
$localHeaderOffset = null;
|
||||
$diskStart = null;
|
||||
|
||||
if ($entry->getUncompressedSize() === ZipConstants::ZIP64_MAGIC) {
|
||||
if ($remaining < 8) {
|
||||
throw new ZipException('ZIP64 extension corrupt (no uncompressed size).');
|
||||
}
|
||||
$uncompressedSize = PackUtil::unpackLongLE(substr($buffer, $length - $remaining, 8));
|
||||
$remaining -= 8;
|
||||
}
|
||||
|
||||
if ($entry->getCompressedSize() === ZipConstants::ZIP64_MAGIC) {
|
||||
if ($remaining < 8) {
|
||||
throw new ZipException('ZIP64 extension corrupt (no compressed size).');
|
||||
}
|
||||
$compressedSize = PackUtil::unpackLongLE(substr($buffer, $length - $remaining, 8));
|
||||
$remaining -= 8;
|
||||
}
|
||||
|
||||
if ($entry->getLocalHeaderOffset() === ZipConstants::ZIP64_MAGIC) {
|
||||
if ($remaining < 8) {
|
||||
throw new ZipException('ZIP64 extension corrupt (no relative local header offset).');
|
||||
}
|
||||
$localHeaderOffset = PackUtil::unpackLongLE(substr($buffer, $length - $remaining, 8));
|
||||
$remaining -= 8;
|
||||
}
|
||||
|
||||
if ($remaining === 4) {
|
||||
$diskStart = unpack('V', substr($buffer, $length - $remaining, 4))[1];
|
||||
}
|
||||
|
||||
return new self($uncompressedSize, $compressedSize, $localHeaderOffset, $diskStart);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData()
|
||||
{
|
||||
if ($this->uncompressedSize !== null || $this->compressedSize !== null) {
|
||||
if ($this->uncompressedSize === null || $this->compressedSize === null) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Zip64 extended information must contain both size values in the local file header.'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->packSizes();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function packSizes()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
if ($this->uncompressedSize !== null) {
|
||||
$data .= PackUtil::packLongLE($this->uncompressedSize);
|
||||
}
|
||||
|
||||
if ($this->compressedSize !== null) {
|
||||
$data .= PackUtil::packLongLE($this->compressedSize);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData()
|
||||
{
|
||||
$data = $this->packSizes();
|
||||
|
||||
if ($this->localHeaderOffset !== null) {
|
||||
$data .= PackUtil::packLongLE($this->localHeaderOffset);
|
||||
}
|
||||
|
||||
if ($this->diskStart !== null) {
|
||||
$data .= pack('V', $this->diskStart);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUncompressedSize()
|
||||
{
|
||||
return $this->uncompressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $uncompressedSize
|
||||
*/
|
||||
public function setUncompressedSize($uncompressedSize)
|
||||
{
|
||||
$this->uncompressedSize = $uncompressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCompressedSize()
|
||||
{
|
||||
return $this->compressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $compressedSize
|
||||
*/
|
||||
public function setCompressedSize($compressedSize)
|
||||
{
|
||||
$this->compressedSize = $compressedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLocalHeaderOffset()
|
||||
{
|
||||
return $this->localHeaderOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $localHeaderOffset
|
||||
*/
|
||||
public function setLocalHeaderOffset($localHeaderOffset)
|
||||
{
|
||||
$this->localHeaderOffset = $localHeaderOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getDiskStart()
|
||||
{
|
||||
return $this->diskStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $diskStart
|
||||
*/
|
||||
public function setDiskStart($diskStart)
|
||||
{
|
||||
$this->diskStart = $diskStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$args = [self::HEADER_ID];
|
||||
$format = '0x%04x ZIP64: ';
|
||||
$formats = [];
|
||||
|
||||
if ($this->uncompressedSize !== null) {
|
||||
$formats[] = 'SIZE=%d';
|
||||
$args[] = $this->uncompressedSize;
|
||||
}
|
||||
|
||||
if ($this->compressedSize !== null) {
|
||||
$formats[] = 'COMP_SIZE=%d';
|
||||
$args[] = $this->compressedSize;
|
||||
}
|
||||
|
||||
if ($this->localHeaderOffset !== null) {
|
||||
$formats[] = 'OFFSET=%d';
|
||||
$args[] = $this->localHeaderOffset;
|
||||
}
|
||||
|
||||
if ($this->diskStart !== null) {
|
||||
$formats[] = 'DISK_START=%d';
|
||||
$args[] = $this->diskStart;
|
||||
}
|
||||
$format .= implode(' ', $formats);
|
||||
|
||||
return vsprintf($format, $args);
|
||||
}
|
||||
}
|
107
vendor/nelexa/zip/src/Model/Extra/ZipExtraDriver.php
vendored
Normal file
107
vendor/nelexa/zip/src/Model/Extra/ZipExtraDriver.php
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra;
|
||||
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Model\Extra\Fields\ApkAlignmentExtraField;
|
||||
use PhpZip\Model\Extra\Fields\AsiExtraField;
|
||||
use PhpZip\Model\Extra\Fields\ExtendedTimestampExtraField;
|
||||
use PhpZip\Model\Extra\Fields\JarMarkerExtraField;
|
||||
use PhpZip\Model\Extra\Fields\NewUnixExtraField;
|
||||
use PhpZip\Model\Extra\Fields\NtfsExtraField;
|
||||
use PhpZip\Model\Extra\Fields\OldUnixExtraField;
|
||||
use PhpZip\Model\Extra\Fields\UnicodeCommentExtraField;
|
||||
use PhpZip\Model\Extra\Fields\UnicodePathExtraField;
|
||||
use PhpZip\Model\Extra\Fields\WinZipAesExtraField;
|
||||
use PhpZip\Model\Extra\Fields\Zip64ExtraField;
|
||||
|
||||
/**
|
||||
* Class ZipExtraManager.
|
||||
*/
|
||||
final class ZipExtraDriver
|
||||
{
|
||||
/**
|
||||
* @var array<int, string>
|
||||
* @psalm-var array<int, class-string<\PhpZip\Model\Extra\ZipExtraField>>
|
||||
*/
|
||||
private static $implementations = [
|
||||
ApkAlignmentExtraField::HEADER_ID => ApkAlignmentExtraField::class,
|
||||
AsiExtraField::HEADER_ID => AsiExtraField::class,
|
||||
ExtendedTimestampExtraField::HEADER_ID => ExtendedTimestampExtraField::class,
|
||||
JarMarkerExtraField::HEADER_ID => JarMarkerExtraField::class,
|
||||
NewUnixExtraField::HEADER_ID => NewUnixExtraField::class,
|
||||
NtfsExtraField::HEADER_ID => NtfsExtraField::class,
|
||||
OldUnixExtraField::HEADER_ID => OldUnixExtraField::class,
|
||||
UnicodeCommentExtraField::HEADER_ID => UnicodeCommentExtraField::class,
|
||||
UnicodePathExtraField::HEADER_ID => UnicodePathExtraField::class,
|
||||
WinZipAesExtraField::HEADER_ID => WinZipAesExtraField::class,
|
||||
Zip64ExtraField::HEADER_ID => Zip64ExtraField::class,
|
||||
];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipExtraField $extraField ZipExtraField object or class name
|
||||
*/
|
||||
public static function register($extraField)
|
||||
{
|
||||
if (!is_a($extraField, ZipExtraField::class, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'$extraField "%s" is not implements interface %s',
|
||||
(string) $extraField,
|
||||
ZipExtraField::class
|
||||
)
|
||||
);
|
||||
}
|
||||
self::$implementations[\call_user_func([$extraField, 'getHeaderId'])] = $extraField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string|ZipExtraField $extraType ZipExtraField object or class name or extra header id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function unregister($extraType)
|
||||
{
|
||||
$headerId = null;
|
||||
|
||||
if (\is_int($extraType)) {
|
||||
$headerId = $extraType;
|
||||
} elseif (is_a($extraType, ZipExtraField::class, true)) {
|
||||
$headerId = \call_user_func([$extraType, 'getHeaderId']);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset(self::$implementations[$headerId])) {
|
||||
unset(self::$implementations[$headerId]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $headerId
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getClassNameOrNull($headerId)
|
||||
{
|
||||
$headerId = (int) $headerId;
|
||||
|
||||
if ($headerId < 0 || $headerId > 0xffff) {
|
||||
throw new \InvalidArgumentException('$headerId out of range: ' . $headerId);
|
||||
}
|
||||
|
||||
if (isset(self::$implementations[$headerId])) {
|
||||
return self::$implementations[$headerId];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
63
vendor/nelexa/zip/src/Model/Extra/ZipExtraField.php
vendored
Normal file
63
vendor/nelexa/zip/src/Model/Extra/ZipExtraField.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model\Extra;
|
||||
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* Extra Field in a Local or Central Header of a ZIP archive.
|
||||
* It defines the common properties of all Extra Fields and how to
|
||||
* serialize/unserialize them to/from byte arrays.
|
||||
*/
|
||||
interface ZipExtraField
|
||||
{
|
||||
/**
|
||||
* Returns the Header ID (type) of this Extra Field.
|
||||
* The Header ID is an unsigned short integer (two bytes)
|
||||
* which must be constant during the life cycle of this object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeaderId();
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in local file data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function unpackLocalFileData($buffer, ZipEntry $entry = null);
|
||||
|
||||
/**
|
||||
* Populate data from this array as if it was in central directory data.
|
||||
*
|
||||
* @param string $buffer the buffer to read data from
|
||||
* @param ZipEntry|null $entry
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function unpackCentralDirData($buffer, ZipEntry $entry = null);
|
||||
|
||||
/**
|
||||
* The actual data to put into local file data - without Header-ID
|
||||
* or length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packLocalFileData();
|
||||
|
||||
/**
|
||||
* The actual data to put into central directory - without Header-ID or
|
||||
* length specifier.
|
||||
*
|
||||
* @return string the data
|
||||
*/
|
||||
public function packCentralDirData();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
72
vendor/nelexa/zip/src/Model/ImmutableZipContainer.php
vendored
Normal file
72
vendor/nelexa/zip/src/Model/ImmutableZipContainer.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
/**
|
||||
* Class ImmutableZipContainer.
|
||||
*/
|
||||
class ImmutableZipContainer implements \Countable
|
||||
{
|
||||
/** @var ZipEntry[] */
|
||||
protected $entries;
|
||||
|
||||
/** @var string|null Archive comment */
|
||||
protected $archiveComment;
|
||||
|
||||
/**
|
||||
* ZipContainer constructor.
|
||||
*
|
||||
* @param ZipEntry[] $entries
|
||||
* @param string|null $archiveComment
|
||||
*/
|
||||
public function __construct(array $entries, $archiveComment)
|
||||
{
|
||||
$this->entries = $entries;
|
||||
$this->archiveComment = $archiveComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZipEntry[]
|
||||
*/
|
||||
public function &getEntries()
|
||||
{
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getArchiveComment()
|
||||
{
|
||||
return $this->archiveComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count elements of an object.
|
||||
*
|
||||
* @see https://php.net/manual/en/countable.count.php
|
||||
*
|
||||
* @return int The custom count as an integer.
|
||||
* The return value is cast to an integer.
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return \count($this->entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties.
|
||||
* Any properties that are references to other variables, will remain references.
|
||||
* Once the cloning is complete, if a __clone() method is defined,
|
||||
* then the newly created object's __clone() method will be called, to allow any necessary properties that need to
|
||||
* be changed. NOT CALLABLE DIRECTLY.
|
||||
*
|
||||
* @see https://php.net/manual/en/language.oop5.cloning.php
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
foreach ($this->entries as $key => $value) {
|
||||
$this->entries[$key] = clone $value;
|
||||
}
|
||||
}
|
||||
}
|
386
vendor/nelexa/zip/src/Model/ZipContainer.php
vendored
Normal file
386
vendor/nelexa/zip/src/Model/ZipContainer.php
vendored
Normal file
@ -0,0 +1,386 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
use PhpZip\Constants\ZipEncryptionMethod;
|
||||
use PhpZip\Exception\InvalidArgumentException;
|
||||
use PhpZip\Exception\ZipEntryNotFoundException;
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
/**
|
||||
* Class ZipContainer.
|
||||
*/
|
||||
class ZipContainer extends ImmutableZipContainer
|
||||
{
|
||||
/**
|
||||
* @var ImmutableZipContainer|null The source container contains zip entries from
|
||||
* an open zip archive. The source container makes
|
||||
* it possible to undo changes in the archive.
|
||||
* When cloning, this container is not cloned.
|
||||
*/
|
||||
private $sourceContainer;
|
||||
|
||||
/**
|
||||
* @var int|null Apk zipalign value
|
||||
*
|
||||
* @todo remove and use in ApkFileWriter
|
||||
*/
|
||||
private $zipAlign;
|
||||
|
||||
/**
|
||||
* MutableZipContainer constructor.
|
||||
*
|
||||
* @param ImmutableZipContainer|null $sourceContainer
|
||||
*/
|
||||
public function __construct(ImmutableZipContainer $sourceContainer = null)
|
||||
{
|
||||
$entries = [];
|
||||
$archiveComment = null;
|
||||
|
||||
if ($sourceContainer !== null) {
|
||||
foreach ($sourceContainer->getEntries() as $entryName => $entry) {
|
||||
$entries[$entryName] = clone $entry;
|
||||
}
|
||||
$archiveComment = $sourceContainer->getArchiveComment();
|
||||
}
|
||||
parent::__construct($entries, $archiveComment);
|
||||
$this->sourceContainer = $sourceContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ImmutableZipContainer|null
|
||||
*/
|
||||
public function getSourceContainer()
|
||||
{
|
||||
return $this->sourceContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
*/
|
||||
public function addEntry(ZipEntry $entry)
|
||||
{
|
||||
$this->entries[$entry->getName()] = $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteEntry($entry)
|
||||
{
|
||||
$entry = $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
|
||||
|
||||
if (isset($this->entries[$entry])) {
|
||||
unset($this->entries[$entry]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $old
|
||||
* @param string|ZipEntry $new
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @return ZipEntry New zip entry
|
||||
*/
|
||||
public function renameEntry($old, $new)
|
||||
{
|
||||
$old = $old instanceof ZipEntry ? $old->getName() : (string) $old;
|
||||
$new = $new instanceof ZipEntry ? $new->getName() : (string) $new;
|
||||
|
||||
if (isset($this->entries[$new])) {
|
||||
throw new InvalidArgumentException('New entry name ' . $new . ' is exists.');
|
||||
}
|
||||
|
||||
$entry = $this->getEntry($old);
|
||||
$newEntry = $entry->rename($new);
|
||||
|
||||
$this->deleteEntry($entry);
|
||||
$this->addEntry($newEntry);
|
||||
|
||||
return $newEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $entryName
|
||||
*
|
||||
* @throws ZipEntryNotFoundException
|
||||
*
|
||||
* @return ZipEntry
|
||||
*/
|
||||
public function getEntry($entryName)
|
||||
{
|
||||
$entry = $this->getEntryOrNull($entryName);
|
||||
|
||||
if ($entry !== null) {
|
||||
return $entry;
|
||||
}
|
||||
|
||||
throw new ZipEntryNotFoundException($entryName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $entryName
|
||||
*
|
||||
* @return ZipEntry|null
|
||||
*/
|
||||
public function getEntryOrNull($entryName)
|
||||
{
|
||||
$entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string) $entryName;
|
||||
|
||||
return isset($this->entries[$entryName]) ? $this->entries[$entryName] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $entryName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEntry($entryName)
|
||||
{
|
||||
$entryName = $entryName instanceof ZipEntry ? $entryName->getName() : (string) $entryName;
|
||||
|
||||
return isset($this->entries[$entryName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all entries.
|
||||
*/
|
||||
public function deleteAll()
|
||||
{
|
||||
$this->entries = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete entries by regex pattern.
|
||||
*
|
||||
* @param string $regexPattern Regex pattern
|
||||
*
|
||||
* @return ZipEntry[] Deleted entries
|
||||
*/
|
||||
public function deleteByRegex($regexPattern)
|
||||
{
|
||||
if (empty($regexPattern)) {
|
||||
throw new InvalidArgumentException('The regex pattern is not specified');
|
||||
}
|
||||
|
||||
/** @var ZipEntry[] $found */
|
||||
$found = [];
|
||||
|
||||
foreach ($this->entries as $entryName => $entry) {
|
||||
if (preg_match($regexPattern, $entryName)) {
|
||||
$found[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($found as $entry) {
|
||||
$this->deleteEntry($entry);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo all changes done in the archive.
|
||||
*/
|
||||
public function unchangeAll()
|
||||
{
|
||||
$this->entries = [];
|
||||
|
||||
if ($this->sourceContainer !== null) {
|
||||
foreach ($this->sourceContainer->getEntries() as $entry) {
|
||||
$this->entries[$entry->getName()] = clone $entry;
|
||||
}
|
||||
}
|
||||
$this->unchangeArchiveComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo change archive comment.
|
||||
*/
|
||||
public function unchangeArchiveComment()
|
||||
{
|
||||
$this->archiveComment = null;
|
||||
|
||||
if ($this->sourceContainer !== null) {
|
||||
$this->archiveComment = $this->sourceContainer->archiveComment;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert all changes done to an entry with the given name.
|
||||
*
|
||||
* @param string|ZipEntry $entry Entry name or ZipEntry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function unchangeEntry($entry)
|
||||
{
|
||||
$entry = $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
|
||||
|
||||
if (
|
||||
$this->sourceContainer !== null &&
|
||||
isset($this->entries[$entry], $this->sourceContainer->entries[$entry])
|
||||
) {
|
||||
$this->entries[$entry] = clone $this->sourceContainer->entries[$entry];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entries sort by name.
|
||||
*
|
||||
* Example:
|
||||
* ```php
|
||||
* $zipContainer->sortByName(static function (string $nameA, string $nameB): int {
|
||||
* return strcmp($nameA, $nameB);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param callable $cmp
|
||||
*/
|
||||
public function sortByName(callable $cmp)
|
||||
{
|
||||
uksort($this->entries, $cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entries sort by entry.
|
||||
*
|
||||
* Example:
|
||||
* ```php
|
||||
* $zipContainer->sortByEntry(static function (ZipEntry $a, ZipEntry $b): int {
|
||||
* return strcmp($a->getName(), $b->getName());
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param callable $cmp
|
||||
*/
|
||||
public function sortByEntry(callable $cmp)
|
||||
{
|
||||
uasort($this->entries, $cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $archiveComment
|
||||
*/
|
||||
public function setArchiveComment($archiveComment)
|
||||
{
|
||||
if ($archiveComment !== null && $archiveComment !== '') {
|
||||
$archiveComment = (string) $archiveComment;
|
||||
$length = \strlen($archiveComment);
|
||||
|
||||
if ($length > 0xffff) {
|
||||
throw new InvalidArgumentException('Length comment out of range');
|
||||
}
|
||||
}
|
||||
$this->archiveComment = $archiveComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZipEntryMatcher
|
||||
*/
|
||||
public function matcher()
|
||||
{
|
||||
return new ZipEntryMatcher($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a password for extracting files.
|
||||
*
|
||||
* @param string|null $password
|
||||
*/
|
||||
public function setReadPassword($password)
|
||||
{
|
||||
if ($this->sourceContainer !== null) {
|
||||
foreach ($this->sourceContainer->entries as $entry) {
|
||||
if ($entry->isEncrypted()) {
|
||||
$entry->setPassword($password);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entryName
|
||||
* @param string $password
|
||||
*
|
||||
* @throws ZipEntryNotFoundException
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function setReadPasswordEntry($entryName, $password)
|
||||
{
|
||||
if (!isset($this->sourceContainer->entries[$entryName])) {
|
||||
throw new ZipEntryNotFoundException($entryName);
|
||||
}
|
||||
|
||||
if ($this->sourceContainer->entries[$entryName]->isEncrypted()) {
|
||||
$this->sourceContainer->entries[$entryName]->setPassword($password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getZipAlign()
|
||||
{
|
||||
return $this->zipAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $zipAlign
|
||||
*/
|
||||
public function setZipAlign($zipAlign)
|
||||
{
|
||||
$this->zipAlign = $zipAlign === null ? null : (int) $zipAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isZipAlign()
|
||||
{
|
||||
return $this->zipAlign !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $writePassword
|
||||
*/
|
||||
public function setWritePassword($writePassword)
|
||||
{
|
||||
$this->matcher()->all()->setPassword($writePassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove password.
|
||||
*/
|
||||
public function removePassword()
|
||||
{
|
||||
$this->matcher()->all()->setPassword(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry $entryName
|
||||
*/
|
||||
public function removePasswordEntry($entryName)
|
||||
{
|
||||
$this->matcher()->add($entryName)->setPassword(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $encryptionMethod
|
||||
*/
|
||||
public function setEncryptionMethod($encryptionMethod = ZipEncryptionMethod::WINZIP_AES_256)
|
||||
{
|
||||
$this->matcher()->all()->setEncryptionMethod($encryptionMethod);
|
||||
}
|
||||
}
|
28
vendor/nelexa/zip/src/Model/ZipData.php
vendored
Normal file
28
vendor/nelexa/zip/src/Model/ZipData.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
|
||||
/**
|
||||
* Interface ZipData.
|
||||
*/
|
||||
interface ZipData
|
||||
{
|
||||
/**
|
||||
* @return string returns data as string
|
||||
*/
|
||||
public function getDataAsString();
|
||||
|
||||
/**
|
||||
* @return resource returns stream data
|
||||
*/
|
||||
public function getDataAsStream();
|
||||
|
||||
/**
|
||||
* @param resource $outStream
|
||||
*
|
||||
* @throws ZipException
|
||||
*/
|
||||
public function copyDataToStream($outStream);
|
||||
}
|
1573
vendor/nelexa/zip/src/Model/ZipEntry.php
vendored
Normal file
1573
vendor/nelexa/zip/src/Model/ZipEntry.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
206
vendor/nelexa/zip/src/Model/ZipEntryMatcher.php
vendored
Normal file
206
vendor/nelexa/zip/src/Model/ZipEntryMatcher.php
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
/**
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*/
|
||||
class ZipEntryMatcher implements \Countable
|
||||
{
|
||||
/** @var ZipContainer */
|
||||
protected $zipContainer;
|
||||
|
||||
/** @var array */
|
||||
protected $matches = [];
|
||||
|
||||
/**
|
||||
* ZipEntryMatcher constructor.
|
||||
*
|
||||
* @param ZipContainer $zipContainer
|
||||
*/
|
||||
public function __construct(ZipContainer $zipContainer)
|
||||
{
|
||||
$this->zipContainer = $zipContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|ZipEntry|string[]|ZipEntry[] $entries
|
||||
*
|
||||
* @return ZipEntryMatcher
|
||||
*/
|
||||
public function add($entries)
|
||||
{
|
||||
$entries = (array) $entries;
|
||||
$entries = array_map(
|
||||
static function ($entry) {
|
||||
return $entry instanceof ZipEntry ? $entry->getName() : (string) $entry;
|
||||
},
|
||||
$entries
|
||||
);
|
||||
$this->matches = array_values(
|
||||
array_map(
|
||||
'strval',
|
||||
array_unique(
|
||||
array_merge(
|
||||
$this->matches,
|
||||
array_keys(
|
||||
array_intersect_key(
|
||||
$this->zipContainer->getEntries(),
|
||||
array_flip($entries)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $regexp
|
||||
*
|
||||
* @return ZipEntryMatcher
|
||||
*
|
||||
* @noinspection PhpUnusedParameterInspection
|
||||
*/
|
||||
public function match($regexp)
|
||||
{
|
||||
array_walk(
|
||||
$this->zipContainer->getEntries(),
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
* @param string $entryName
|
||||
*/
|
||||
function (ZipEntry $entry, $entryName) use ($regexp) {
|
||||
if (preg_match($regexp, $entryName)) {
|
||||
$this->matches[] = (string) $entryName;
|
||||
}
|
||||
}
|
||||
);
|
||||
$this->matches = array_unique($this->matches);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZipEntryMatcher
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
$this->matches = array_map(
|
||||
'strval',
|
||||
array_keys($this->zipContainer->getEntries())
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callable function for all select entries.
|
||||
*
|
||||
* Callable function signature:
|
||||
* function(string $entryName){}
|
||||
*
|
||||
* @param callable $callable
|
||||
*/
|
||||
public function invoke(callable $callable)
|
||||
{
|
||||
if (!empty($this->matches)) {
|
||||
array_walk(
|
||||
$this->matches,
|
||||
/** @param string $entryName */
|
||||
static function ($entryName) use ($callable) {
|
||||
$callable($entryName);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMatches()
|
||||
{
|
||||
return $this->matches;
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
array_walk(
|
||||
$this->matches,
|
||||
/** @param string $entryName */
|
||||
function ($entryName) {
|
||||
$this->zipContainer->deleteEntry($entryName);
|
||||
}
|
||||
);
|
||||
$this->matches = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $password
|
||||
* @param int|null $encryptionMethod
|
||||
*/
|
||||
public function setPassword($password, $encryptionMethod = null)
|
||||
{
|
||||
array_walk(
|
||||
$this->matches,
|
||||
/** @param string $entryName */
|
||||
function ($entryName) use ($password, $encryptionMethod) {
|
||||
$entry = $this->zipContainer->getEntry($entryName);
|
||||
|
||||
if (!$entry->isDirectory()) {
|
||||
$entry->setPassword($password, $encryptionMethod);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $encryptionMethod
|
||||
*/
|
||||
public function setEncryptionMethod($encryptionMethod)
|
||||
{
|
||||
array_walk(
|
||||
$this->matches,
|
||||
/** @param string $entryName */
|
||||
function ($entryName) use ($encryptionMethod) {
|
||||
$entry = $this->zipContainer->getEntry($entryName);
|
||||
|
||||
if (!$entry->isDirectory()) {
|
||||
$entry->setEncryptionMethod($encryptionMethod);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function disableEncryption()
|
||||
{
|
||||
array_walk(
|
||||
$this->matches,
|
||||
/** @param string $entryName */
|
||||
function ($entryName) {
|
||||
$entry = $this->zipContainer->getEntry($entryName);
|
||||
|
||||
if (!$entry->isDirectory()) {
|
||||
$entry->disableEncryption();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count elements of an object.
|
||||
*
|
||||
* @see http://php.net/manual/en/countable.count.php
|
||||
*
|
||||
* @return int the custom count as an integer
|
||||
*
|
||||
* @since 5.1.0
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return \count($this->matches);
|
||||
}
|
||||
}
|
266
vendor/nelexa/zip/src/Model/ZipInfo.php
vendored
Normal file
266
vendor/nelexa/zip/src/Model/ZipInfo.php
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
namespace PhpZip\Model;
|
||||
|
||||
use PhpZip\Constants\ZipCompressionMethod;
|
||||
use PhpZip\Constants\ZipEncryptionMethod;
|
||||
use PhpZip\Constants\ZipPlatform;
|
||||
use PhpZip\Util\FileAttribUtil;
|
||||
use PhpZip\Util\FilesUtil;
|
||||
|
||||
/**
|
||||
* Zip info.
|
||||
*
|
||||
* @author Ne-Lexa alexey@nelexa.ru
|
||||
* @license MIT
|
||||
*
|
||||
* @deprecated Use ZipEntry
|
||||
*/
|
||||
class ZipInfo
|
||||
{
|
||||
/** @var ZipEntry */
|
||||
private $entry;
|
||||
|
||||
/**
|
||||
* ZipInfo constructor.
|
||||
*
|
||||
* @param ZipEntry $entry
|
||||
*/
|
||||
public function __construct(ZipEntry $entry)
|
||||
{
|
||||
$this->entry = $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipEntry $entry
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated Use {@see ZipPlatform::getPlatformName()}
|
||||
*/
|
||||
public static function getPlatformName(ZipEntry $entry)
|
||||
{
|
||||
return ZipPlatform::getPlatformName($entry->getExtractedOS());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->entry->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isFolder()
|
||||
{
|
||||
return $this->entry->isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->entry->getUncompressedSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCompressedSize()
|
||||
{
|
||||
return $this->entry->getCompressedSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMtime()
|
||||
{
|
||||
return $this->entry->getMTime()->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCtime()
|
||||
{
|
||||
$ctime = $this->entry->getCTime();
|
||||
|
||||
return $ctime === null ? null : $ctime->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getAtime()
|
||||
{
|
||||
$atime = $this->entry->getATime();
|
||||
|
||||
return $atime === null ? null : $atime->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
$externalAttributes = $this->entry->getExternalAttributes();
|
||||
|
||||
if ($this->entry->getCreatedOS() === ZipPlatform::OS_UNIX) {
|
||||
$permission = (($externalAttributes >> 16) & 0xFFFF);
|
||||
|
||||
return FileAttribUtil::getUnixMode($permission);
|
||||
}
|
||||
|
||||
return FileAttribUtil::getDosMode($externalAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEncrypted()
|
||||
{
|
||||
return $this->entry->isEncrypted();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getComment()
|
||||
{
|
||||
return $this->entry->getComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCrc()
|
||||
{
|
||||
return $this->entry->getCrc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @deprecated use \PhpZip\Model\ZipInfo::getMethodName()
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethodName()
|
||||
{
|
||||
return ZipCompressionMethod::getCompressionMethodName($this->entry->getCompressionMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptionMethodName()
|
||||
{
|
||||
return ZipEncryptionMethod::getEncryptionMethodName($this->entry->getEncryptionMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPlatform()
|
||||
{
|
||||
return ZipPlatform::getPlatformName($this->entry->getExtractedOS());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->entry->getExtractVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getEncryptionMethod()
|
||||
{
|
||||
$encryptionMethod = $this->entry->getEncryptionMethod();
|
||||
|
||||
return $encryptionMethod === ZipEncryptionMethod::NONE ? null : $encryptionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCompressionLevel()
|
||||
{
|
||||
return $this->entry->getCompressionLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCompressionMethod()
|
||||
{
|
||||
return $this->entry->getCompressionMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getName(),
|
||||
'folder' => $this->isFolder(),
|
||||
'size' => $this->getSize(),
|
||||
'compressed_size' => $this->getCompressedSize(),
|
||||
'modified' => $this->getMtime(),
|
||||
'created' => $this->getCtime(),
|
||||
'accessed' => $this->getAtime(),
|
||||
'attributes' => $this->getAttributes(),
|
||||
'encrypted' => $this->isEncrypted(),
|
||||
'encryption_method' => $this->getEncryptionMethod(),
|
||||
'encryption_method_name' => $this->getEncryptionMethodName(),
|
||||
'comment' => $this->getComment(),
|
||||
'crc' => $this->getCrc(),
|
||||
'method_name' => $this->getMethodName(),
|
||||
'compression_method' => $this->getCompressionMethod(),
|
||||
'platform' => $this->getPlatform(),
|
||||
'version' => $this->getVersion(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$ctime = $this->entry->getCTime();
|
||||
$atime = $this->entry->getATime();
|
||||
$comment = $this->getComment();
|
||||
|
||||
return __CLASS__ . ' {'
|
||||
. 'Name="' . $this->getName() . '", '
|
||||
. ($this->isFolder() ? 'Folder, ' : '')
|
||||
. 'Size="' . FilesUtil::humanSize($this->getSize()) . '"'
|
||||
. ', Compressed size="' . FilesUtil::humanSize($this->getCompressedSize()) . '"'
|
||||
. ', Modified time="' . $this->entry->getMTime()->format(\DATE_W3C) . '", '
|
||||
. ($ctime !== null ? 'Created time="' . $ctime->format(\DATE_W3C) . '", ' : '')
|
||||
. ($atime !== null ? 'Accessed time="' . $atime->format(\DATE_W3C) . '", ' : '')
|
||||
. ($this->isEncrypted() ? 'Encrypted, ' : '')
|
||||
. ($comment !== null ? 'Comment="' . $comment . '", ' : '')
|
||||
. (!empty($this->crc) ? 'Crc=0x' . dechex($this->crc) . ', ' : '')
|
||||
. 'Method name="' . $this->getMethodName() . '", '
|
||||
. 'Attributes="' . $this->getAttributes() . '", '
|
||||
. 'Platform="' . $this->getPlatform() . '", '
|
||||
. 'Version=' . $this->getVersion()
|
||||
. '}';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user