1
0
mirror of https://github.com/Ne-Lexa/php-zip.git synced 2025-08-16 20:24:11 +02:00

10 Commits
3.1.6 ... 3.1.8

Author SHA1 Message Date
wapplay
9934a860c1 Merge branch 'release/3.1.8' 2018-10-21 19:31:21 +03:00
wapplay
c9f597308e cs fix 2018-10-21 19:30:45 +03:00
wapplay
837454ba7e Added additional check for correct decompression 2018-10-21 19:25:13 +03:00
wapplay
680a9d92c1 Merge branch 'hotfix/3.1.7' 2018-10-21 01:54:45 +03:00
wapplay
04a92e7904 Merge tag '3.1.7' into develop
Tagging hotfix 3.1.7 3.1.7
2018-10-21 01:54:45 +03:00
wapplay
e4e3a7504e Test streamWrapper extract (issue #24) 2018-10-21 01:54:30 +03:00
wapplay
d8bb1be43b Fix #24 Change fread for variable size reads 2018-10-21 01:32:01 +03:00
Ne-Lexa
c163f0583e update pull request template 2018-10-18 10:46:49 +03:00
Ne-Lexa
116a617744 added github templates 2018-10-18 10:42:57 +03:00
Ne-Lexa
e207086a75 Merge tag '3.1.6' into develop
Tagging version 3.1.6 3.1.6
2018-10-11 10:54:30 +03:00
11 changed files with 236 additions and 24 deletions

23
.github/ISSUE_TEMPLATE/1_Bug_report.md vendored Normal file
View File

@@ -0,0 +1,23 @@
---
name: 🔴 Bug Report
about: Report errors and problems
---
| Q | A
| -----------------------------| ---
| Library version(s) affected: | x.y.z
| PHP version(s): | x.y.z
| OS (with bit depth): | <!-- ex. Ubuntu 18.04 64-bit -->
**Description**
<!-- A clear and concise description of the problem. -->
**How to reproduce**
<!-- Code to reproduce the problem. -->
**Possible Solution**
<!--- Optional: only if you have suggestions on a fix/reason for the bug -->
**Additional context**
<!-- Optional: any other context about the problem: error messages, stack trace, zip files, etc. -->

View File

@@ -0,0 +1,12 @@
---
name: 🚀 Feature Request
about: Ideas for new features and improvements
---
**Description**
<!-- A clear and concise description of the new feature. -->
**Example**
<!-- A simple example of the new feature in action (include PHP code)
If the new feature changes an existing feature, include a simple before/after comparison. -->

12
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,12 @@
| Q | A
| ------------- | ---
| Bug fix? | yes/no
| New feature? | yes/no <!-- don't forget to update CHANGELOG.md file -->
<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
Do NOT send pull request to `master` branch.
Please send to `develop` branch instead.
Any PR to `master` branch will NOT be merged.
-->

View File

@@ -148,7 +148,10 @@ class TraditionalPkwareEncryptionEngine implements ZipEncryptionEngine
$checkByte = ($this->entry->getCrc() >> 24) & 0xff;
}
if ($byte !== $checkByte) {
throw new ZipAuthenticationException("Bad password for entry " . $this->entry->getName());
throw new ZipAuthenticationException(sprintf(
'Invalid password for zip entry "%s"',
$this->entry->getName()
));
}
$outputContent = "";

View File

@@ -25,14 +25,14 @@ class ZipNewFileEntry extends ZipAbstractEntry
public function __construct($file)
{
parent::__construct();
if ($file === null){
if ($file === null) {
throw new InvalidArgumentException("file is null");
}
$file = (string)$file;
if (!is_file($file)){
if (!is_file($file)) {
throw new ZipException("File $file does not exist.");
}
if (!is_readable($file)){
if (!is_readable($file)) {
throw new ZipException("The '$file' file could not be read. Check permissions.");
}
$this->file = $file;
@@ -45,9 +45,9 @@ class ZipNewFileEntry extends ZipAbstractEntry
*/
public function getEntryContent()
{
if (!is_file($this->file)){
if (!is_file($this->file)) {
throw new RuntimeException("File {$this->file} does not exist.");
}
return file_get_contents($this->file);
}
}
}

View File

@@ -7,7 +7,7 @@ use PhpZip\Crypto\WinZipAesEngine;
use PhpZip\Exception\Crc32Exception;
use PhpZip\Exception\InvalidArgumentException;
use PhpZip\Exception\RuntimeException;
use PhpZip\Exception\ZipCryptoException;
use PhpZip\Exception\ZipAuthenticationException;
use PhpZip\Exception\ZipException;
use PhpZip\Exception\ZipUnsupportMethodException;
use PhpZip\Extra\ExtraFieldsCollection;
@@ -144,8 +144,14 @@ class ZipInputStream implements ZipInputStreamInterface
);
}
// .ZIP file comment (variable size)
if (0 < $data['commentLength']) {
$comment = fread($this->in, $data['commentLength']);
if ($data['commentLength'] > 0) {
$comment = '';
$offset = 0;
while ($offset < $data['commentLength']) {
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
$comment .= fread($this->in, $read);
$offset += $read;
}
}
$this->preamble = $endOfCentralDirRecordPos;
$this->postamble = $size - ftell($this->in);
@@ -314,7 +320,13 @@ class ZipInputStream implements ZipInputStreamInterface
// $utf8 = ($data['gpbf'] & ZipEntry::GPBF_UTF8) !== 0;
// See appendix D of PKWARE's ZIP File Format Specification.
$name = fread($this->in, $data['fileLength']);
$name = '';
$offset = 0;
while ($offset < $data['fileLength']) {
$read = min(8192 /* chunk size */, $data['fileLength'] - $offset);
$name .= fread($this->in, $read);
$offset += $read;
}
$entry = new ZipSourceEntry($this);
$entry->setName($name);
@@ -329,10 +341,24 @@ class ZipInputStream implements ZipInputStreamInterface
$entry->setExternalAttributes($data['rawExternalAttributes']);
$entry->setOffset($data['lfhOff']); // must be unmapped!
if ($data['extraLength'] > 0) {
$entry->setExtra(fread($this->in, $data['extraLength']));
$extra = '';
$offset = 0;
while ($offset < $data['extraLength']) {
$read = min(8192 /* chunk size */, $data['extraLength'] - $offset);
$extra .= fread($this->in, $read);
$offset += $read;
}
$entry->setExtra($extra);
}
if ($data['commentLength'] > 0) {
$entry->setComment(fread($this->in, $data['commentLength']));
$comment = '';
$offset = 0;
while ($offset < $data['commentLength']) {
$read = min(8192 /* chunk size */, $data['commentLength'] - $offset);
$comment .= fread($this->in, $read);
$offset += $read;
}
$entry->setComment($comment);
}
return $entry;
}
@@ -382,10 +408,14 @@ class ZipInputStream implements ZipInputStreamInterface
// Get raw entry content
$compressedSize = $entry->getCompressedSize();
$compressedSize = PHP_INT_SIZE === 4 ? sprintf('%u', $compressedSize) : $compressedSize;
$content = '';
if ($compressedSize > 0) {
$content = fread($this->in, $compressedSize);
} else {
$content = '';
$offset = 0;
while ($offset < $compressedSize) {
$read = min(8192 /* chunk size */, $compressedSize - $offset);
$content .= fread($this->in, $read);
$offset += $read;
}
}
$skipCheckCrc = false;
@@ -440,7 +470,7 @@ class ZipInputStream implements ZipInputStreamInterface
case ZipFileInterface::METHOD_STORED:
break;
case ZipFileInterface::METHOD_DEFLATED:
$content = gzinflate($content);
$content = @gzinflate($content);
break;
case ZipFileInterface::METHOD_BZIP2:
if (!extension_loaded('bz2')) {
@@ -448,18 +478,38 @@ class ZipInputStream implements ZipInputStreamInterface
}
/** @noinspection PhpComposerExtensionStubsInspection */
$content = bzdecompress($content);
if (is_int($content)) { // decompress error
$content = false;
}
break;
default:
throw new ZipUnsupportMethodException($entry->getName() .
" (compression method " . $method . " is not supported)");
}
if ($content === false) {
if ($isEncrypted) {
throw new ZipAuthenticationException(sprintf(
'Invalid password for zip entry "%s"',
$entry->getName()
));
}
throw new ZipException(sprintf(
'Failed to get the contents of the zip entry "%s"',
$entry->getName()
));
}
if (!$skipCheckCrc) {
$localCrc = crc32($content);
$localCrc = PHP_INT_SIZE === 4 ? sprintf('%u', $localCrc) : $localCrc;
$crc = PHP_INT_SIZE === 4 ? sprintf('%u', $entry->getCrc()) : $entry->getCrc();
if ($crc != $localCrc) {
if ($isEncrypted) {
throw new ZipCryptoException("Wrong password");
throw new ZipAuthenticationException(sprintf(
'Invalid password for zip entry "%s"',
$entry->getName()
));
}
throw new Crc32Exception($entry->getName(), $crc, $localCrc);
}
@@ -498,7 +548,13 @@ class ZipInputStream implements ZipInputStreamInterface
if ($sourceExtraLength > 0) {
// read Local File Header extra fields
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength, SEEK_SET);
$extra = fread($this->in, $sourceExtraLength);
$extra = '';
$offset = 0;
while ($offset < $sourceExtraLength) {
$read = min(8192 /* chunk size */, $sourceExtraLength - $offset);
$extra .= fread($this->in, $read);
$offset += $read;
}
$extraFieldsCollection = ExtraFieldsFactory::createExtraFieldCollections($extra, $entry);
if (isset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]) && $this->zipModel->isZipAlign()) {
unset($extraFieldsCollection[ApkAlignmentExtraField::getHeaderId()]);

View File

@@ -2,6 +2,7 @@
namespace PhpZip\Stream;
use PhpZip\Exception\ZipException;
use PhpZip\Model\ZipEntry;
use PhpZip\Model\ZipModel;
@@ -26,6 +27,7 @@ interface ZipInputStreamInterface
/**
* @param ZipEntry $entry
* @return string
* @throws ZipException
*/
public function readEntryContent(ZipEntry $entry);

View File

@@ -562,7 +562,7 @@ class ZipFile implements ZipFileInterface
throw new InvalidArgumentException('The input directory is not specified');
}
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
@@ -594,7 +594,7 @@ class ZipFile implements ZipFileInterface
throw new InvalidArgumentException('The input directory is not specified');
}
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
@@ -713,7 +713,7 @@ class ZipFile implements ZipFileInterface
throw new InvalidArgumentException('The input directory is not specified');
}
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
$globPattern = (string)$globPattern;
if (empty($globPattern)) {
@@ -813,7 +813,7 @@ class ZipFile implements ZipFileInterface
throw new InvalidArgumentException('The input directory is not specified');
}
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;

View File

@@ -0,0 +1,104 @@
<?php
namespace PhpZip;
use PhpZip\Exception\ZipException;
use PhpZip\Util\CryptoUtil;
class Issue24Test extends ZipTestCase
{
/**
* This method is called before the first test of this test class is run.
*/
public static function setUpBeforeClass()
{
stream_wrapper_register("dummyfs", DummyFileSystemStream::class);
}
/**
* @throws ZipException
*/
public function testDummyFS()
{
$fileContents = str_repeat(base64_encode(CryptoUtil::randomBytes(12000)), 100);
// create zip file
$zip = new ZipFile();
$zip->addFromString(
'file.txt',
$fileContents,
ZipFile::METHOD_DEFLATED
);
$zip->saveAsFile($this->outputFilename);
$zip->close();
$this->assertCorrectZipArchive($this->outputFilename);
$stream = fopen('dummyfs://localhost/' . $this->outputFilename, 'rb');
$this->assertNotFalse($stream);
$zip->openFromStream($stream);
$this->assertEquals($zip->getListFiles(), ['file.txt']);
$this->assertEquals($zip['file.txt'], $fileContents);
$zip->close();
}
}
/**
* Try to load using dummy stream
*/
class DummyFileSystemStream
{
/**
* @var resource
*/
private $fp;
public function stream_open($path, $mode, $options, &$opened_path)
{
// echo "DummyFileSystemStream->stream_open($path, $mode, $options)" . PHP_EOL;
$parsedUrl = parse_url($path);
$path = $parsedUrl['path'];
$this->fp = fopen($path, $mode);
return true;
}
public function stream_read($count)
{
// echo "DummyFileSystemStream->stream_read($count)" . PHP_EOL;
$position = ftell($this->fp);
// echo "Loading chunk " . $position . " to " . ($position + $count - 1) . PHP_EOL;
$ret = fread($this->fp, $count);
// echo "String length: " . strlen($ret) . PHP_EOL;
return $ret;
}
public function stream_tell()
{
// echo "DummyFileSystemStream->stream_tell()" . PHP_EOL;
return ftell($this->fp);
}
public function stream_eof()
{
// echo "DummyFileSystemStream->stream_eof()" . PHP_EOL;
$isfeof = feof($this->fp);
return $isfeof;
}
public function stream_seek($offset, $whence)
{
// echo "DummyFileSystemStream->stream_seek($offset, $whence)" . PHP_EOL;
fseek($this->fp, $offset, $whence);
}
public function stream_stat()
{
// echo "DummyFileSystemStream->stream_stat()" . PHP_EOL;
return fstat($this->fp);
}
}

View File

@@ -101,7 +101,7 @@ class PhpZipExtResourceTest extends ZipTestCase
* Bug #70752 (Depacking with wrong password leaves 0 length files)
* @see https://github.com/php/php-src/blob/master/ext/zip/tests/bug70752.phpt
* @expectedException \PhpZip\Exception\ZipAuthenticationException
* @expectedExceptionMessage Bad password for entry bug70752.txt
* @expectedExceptionMessage nvalid password for zip entry "bug70752.txt"
* @throws ZipException
*/
public function testBug70752()

View File

@@ -43,7 +43,7 @@ class ZipPasswordTest extends ZipFileAddDirTest
$zipFile[$entryName];
$this->fail("Expected Exception has not been raised.");
} catch (ZipAuthenticationException $ae) {
$this->assertContains('Bad password for entry', $ae->getMessage());
$this->assertContains('Invalid password for zip entry', $ae->getMessage());
}
}