Skip to content

Commit d67fc4d

Browse files
committed
Merge branch 'hotfix/3.1.1'
2 parents 0788892 + ba2e314 commit d67fc4d

File tree

4 files changed

+178
-122
lines changed

4 files changed

+178
-122
lines changed

src/PhpZip/Stream/ZipInputStream.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,11 @@ public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out)
481481
$pos = PHP_INT_SIZE === 4 ? sprintf('%u', $pos) : $pos;
482482
$pos = $this->mapper->map($pos);
483483

484-
$extraLength = strlen($entry->getExtra());
485484
$nameLength = strlen($entry->getName());
486485

486+
fseek($this->in, $pos + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, SEEK_SET);
487+
$extraLength = unpack('v', fread($this->in, 2))[1];
488+
487489
$length = ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $extraLength + $nameLength;
488490

489491
$padding = 0;
@@ -505,7 +507,7 @@ public function copyEntry(ZipEntry $entry, ZipOutputStreamInterface $out)
505507
} else {
506508
stream_copy_to_stream($this->in, $out->getStream(), $length);
507509
}
508-
$this->copyEntryData($entry, $out);
510+
stream_copy_to_stream($this->in, $out->getStream(), $entry->getCompressedSize());
509511
if ($entry->getGeneralPurposeBitFlag(ZipEntry::GPBF_DATA_DESCRIPTOR)) {
510512
$length = 12;
511513
if ($entry->isZip64ExtensionsRequired()) {
@@ -524,11 +526,13 @@ public function copyEntryData(ZipEntry $entry, ZipOutputStreamInterface $out)
524526
$offset = $entry->getOffset();
525527
$offset = PHP_INT_SIZE === 4 ? sprintf('%u', $offset) : $offset;
526528
$offset = $this->mapper->map($offset);
527-
$position = $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN +
528-
strlen($entry->getName()) + strlen($entry->getExtra());
529-
$length = $entry->getCompressedSize();
530-
fseek($this->in, $position, SEEK_SET);
531-
stream_copy_to_stream($this->in, $out->getStream(), $length);
529+
$nameLength = strlen($entry->getName());
530+
531+
fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN - 2, SEEK_SET);
532+
$extraLength = unpack('v', fread($this->in, 2))[1];
533+
534+
fseek($this->in, $offset + ZipEntry::LOCAL_FILE_HEADER_MIN_LEN + $nameLength + $extraLength, SEEK_SET);
535+
stream_copy_to_stream($this->in, $out->getStream(), $entry->getCompressedSize());
532536
}
533537

534538
public function __destruct()

tests/PhpZip/ZipAlignTest.php

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?php
2+
3+
namespace PhpZip;
4+
5+
use PhpZip\Util\CryptoUtil;
6+
7+
/**
8+
* Test ZipAlign
9+
*/
10+
class ZipAlignTest extends ZipTestCase
11+
{
12+
public function testApkAlignedAndReSave()
13+
{
14+
$filename = __DIR__ . '/resources/test.apk';
15+
16+
self::assertCorrectZipArchive($filename);
17+
self::doZipAlignVerify($this->outputFilename);
18+
19+
$zipFile = new ZipFile();
20+
$zipFile->openFile($filename);
21+
$zipFile->saveAsFile($this->outputFilename);
22+
$zipFile->close();
23+
24+
self::assertCorrectZipArchive($this->outputFilename);
25+
self::doZipAlignVerify($this->outputFilename);
26+
}
27+
28+
public function testApkAlignedAndSetZipAlignAndReSave()
29+
{
30+
$filename = __DIR__ . '/resources/test.apk';
31+
32+
self::assertCorrectZipArchive($filename);
33+
self::doZipAlignVerify($this->outputFilename);
34+
35+
$zipFile = new ZipFile();
36+
$zipFile->openFile($filename);
37+
$zipFile->setZipAlign(4);
38+
$zipFile->saveAsFile($this->outputFilename);
39+
$zipFile->close();
40+
41+
self::assertCorrectZipArchive($this->outputFilename);
42+
self::doZipAlignVerify($this->outputFilename);
43+
}
44+
45+
/**
46+
* Test zip alignment.
47+
*/
48+
public function testZipAlignSourceZip()
49+
{
50+
$zipFile = new ZipFile();
51+
for ($i = 0; $i < 100; $i++) {
52+
$zipFile->addFromString(
53+
'entry' . $i . '.txt',
54+
CryptoUtil::randomBytes(mt_rand(100, 4096)),
55+
ZipFileInterface::METHOD_STORED
56+
);
57+
}
58+
$zipFile->saveAsFile($this->outputFilename);
59+
$zipFile->close();
60+
61+
self::assertCorrectZipArchive($this->outputFilename);
62+
63+
$result = self::doZipAlignVerify($this->outputFilename);
64+
if ($result === null) {
65+
return;
66+
} // zip align not installed
67+
68+
// check not zip align
69+
self::assertFalse($result);
70+
71+
$zipFile->openFile($this->outputFilename);
72+
$zipFile->setZipAlign(4);
73+
$zipFile->saveAsFile($this->outputFilename);
74+
$zipFile->close();
75+
76+
self::assertCorrectZipArchive($this->outputFilename);
77+
78+
$result = self::doZipAlignVerify($this->outputFilename, true);
79+
self::assertNotNull($result);
80+
81+
// check zip align
82+
self::assertTrue($result);
83+
}
84+
85+
public function testZipAlignNewFiles()
86+
{
87+
$zipFile = new ZipFile();
88+
for ($i = 0; $i < 100; $i++) {
89+
$zipFile->addFromString(
90+
'entry' . $i . '.txt',
91+
CryptoUtil::randomBytes(mt_rand(100, 4096)),
92+
ZipFileInterface::METHOD_STORED
93+
);
94+
}
95+
$zipFile->setZipAlign(4);
96+
$zipFile->saveAsFile($this->outputFilename);
97+
$zipFile->close();
98+
99+
self::assertCorrectZipArchive($this->outputFilename);
100+
101+
$result = self::doZipAlignVerify($this->outputFilename);
102+
if ($result === null) {
103+
return;
104+
} // zip align not installed
105+
// check not zip align
106+
self::assertTrue($result);
107+
}
108+
109+
public function testZipAlignFromModifiedZipArchive()
110+
{
111+
$zipFile = new ZipFile();
112+
for ($i = 0; $i < 100; $i++) {
113+
$zipFile->addFromString(
114+
'entry' . $i . '.txt',
115+
CryptoUtil::randomBytes(mt_rand(100, 4096)),
116+
ZipFileInterface::METHOD_STORED
117+
);
118+
}
119+
$zipFile->saveAsFile($this->outputFilename);
120+
$zipFile->close();
121+
122+
self::assertCorrectZipArchive($this->outputFilename);
123+
124+
$result = self::doZipAlignVerify($this->outputFilename);
125+
if ($result === null) {
126+
return;
127+
} // zip align not installed
128+
129+
// check not zip align
130+
self::assertFalse($result);
131+
132+
$zipFile->openFile($this->outputFilename);
133+
$zipFile->deleteFromRegex("~entry2[\d]+\.txt$~s");
134+
for ($i = 0; $i < 100; $i++) {
135+
$isStored = (bool)mt_rand(0, 1);
136+
137+
$zipFile->addFromString(
138+
'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
139+
CryptoUtil::randomBytes(mt_rand(100, 4096)),
140+
$isStored ?
141+
ZipFileInterface::METHOD_STORED :
142+
ZipFileInterface::METHOD_DEFLATED
143+
);
144+
}
145+
$zipFile->setZipAlign(4);
146+
$zipFile->saveAsFile($this->outputFilename);
147+
$zipFile->close();
148+
149+
self::assertCorrectZipArchive($this->outputFilename);
150+
151+
$result = self::doZipAlignVerify($this->outputFilename, true);
152+
self::assertNotNull($result);
153+
154+
// check zip align
155+
self::assertTrue($result);
156+
}
157+
}

tests/PhpZip/ZipFileTest.php

Lines changed: 10 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,11 @@ public function testRename()
404404
$zipFile->openFile($this->outputFilename);
405405
$zipFile->rename($oldName, $newName);
406406
$zipFile->addFromString('file1.txt', 'content');
407-
$zipFile->rename('file1.txt', 'file2.txt');
407+
$zipFile->addFromString('file2.txt', 'content');
408+
$zipFile->addFromString('file3.txt', 'content');
409+
$zipFile->rename('file1.txt', 'file_long_name.txt');
410+
$zipFile->rename('file2.txt', 'file4.txt');
411+
$zipFile->rename('file3.txt', 'fi.txt');
408412
$zipFile->saveAsFile($this->outputFilename);
409413
$zipFile->close();
410414

@@ -414,7 +418,11 @@ public function testRename()
414418
self::assertFalse(isset($zipFile[$oldName]));
415419
self::assertTrue(isset($zipFile[$newName]));
416420
self::assertFalse(isset($zipFile['file1.txt']));
417-
self::assertTrue(isset($zipFile['file2.txt']));
421+
self::assertFalse(isset($zipFile['file2.txt']));
422+
self::assertFalse(isset($zipFile['file3.txt']));
423+
self::assertTrue(isset($zipFile['file_long_name.txt']));
424+
self::assertTrue(isset($zipFile['file4.txt']));
425+
self::assertTrue(isset($zipFile['fi.txt']));
418426
$zipFile->close();
419427
}
420428

@@ -1737,119 +1745,6 @@ public function testRewriteNullStream()
17371745
$zipFile->rewrite();
17381746
}
17391747

1740-
/**
1741-
* Test zip alignment.
1742-
*/
1743-
public function testZipAlignSourceZip()
1744-
{
1745-
$zipFile = new ZipFile();
1746-
for ($i = 0; $i < 100; $i++) {
1747-
$zipFile->addFromString(
1748-
'entry' . $i . '.txt',
1749-
CryptoUtil::randomBytes(mt_rand(100, 4096)),
1750-
ZipFileInterface::METHOD_STORED
1751-
);
1752-
}
1753-
$zipFile->saveAsFile($this->outputFilename);
1754-
$zipFile->close();
1755-
1756-
self::assertCorrectZipArchive($this->outputFilename);
1757-
1758-
$result = self::doZipAlignVerify($this->outputFilename);
1759-
if ($result === null) {
1760-
return;
1761-
} // zip align not installed
1762-
1763-
// check not zip align
1764-
self::assertFalse($result);
1765-
1766-
$zipFile->openFile($this->outputFilename);
1767-
$zipFile->setZipAlign(4);
1768-
$zipFile->saveAsFile($this->outputFilename);
1769-
$zipFile->close();
1770-
1771-
self::assertCorrectZipArchive($this->outputFilename);
1772-
1773-
$result = self::doZipAlignVerify($this->outputFilename, true);
1774-
self::assertNotNull($result);
1775-
1776-
// check zip align
1777-
self::assertTrue($result);
1778-
}
1779-
1780-
public function testZipAlignNewFiles()
1781-
{
1782-
$zipFile = new ZipFile();
1783-
for ($i = 0; $i < 100; $i++) {
1784-
$zipFile->addFromString(
1785-
'entry' . $i . '.txt',
1786-
CryptoUtil::randomBytes(mt_rand(100, 4096)),
1787-
ZipFileInterface::METHOD_STORED
1788-
);
1789-
}
1790-
$zipFile->setZipAlign(4);
1791-
$zipFile->saveAsFile($this->outputFilename);
1792-
$zipFile->close();
1793-
1794-
self::assertCorrectZipArchive($this->outputFilename);
1795-
1796-
$result = self::doZipAlignVerify($this->outputFilename);
1797-
if ($result === null) {
1798-
return;
1799-
} // zip align not installed
1800-
// check not zip align
1801-
self::assertTrue($result);
1802-
}
1803-
1804-
public function testZipAlignFromModifiedZipArchive()
1805-
{
1806-
$zipFile = new ZipFile();
1807-
for ($i = 0; $i < 100; $i++) {
1808-
$zipFile->addFromString(
1809-
'entry' . $i . '.txt',
1810-
CryptoUtil::randomBytes(mt_rand(100, 4096)),
1811-
ZipFileInterface::METHOD_STORED
1812-
);
1813-
}
1814-
$zipFile->saveAsFile($this->outputFilename);
1815-
$zipFile->close();
1816-
1817-
self::assertCorrectZipArchive($this->outputFilename);
1818-
1819-
$result = self::doZipAlignVerify($this->outputFilename);
1820-
if ($result === null) {
1821-
return;
1822-
} // zip align not installed
1823-
1824-
// check not zip align
1825-
self::assertFalse($result);
1826-
1827-
$zipFile->openFile($this->outputFilename);
1828-
$zipFile->deleteFromRegex("~entry2[\d]+\.txt$~s");
1829-
for ($i = 0; $i < 100; $i++) {
1830-
$isStored = (bool)mt_rand(0, 1);
1831-
1832-
$zipFile->addFromString(
1833-
'entry_new_' . ($isStored ? 'stored' : 'deflated') . '_' . $i . '.txt',
1834-
CryptoUtil::randomBytes(mt_rand(100, 4096)),
1835-
$isStored ?
1836-
ZipFileInterface::METHOD_STORED :
1837-
ZipFileInterface::METHOD_DEFLATED
1838-
);
1839-
}
1840-
$zipFile->setZipAlign(4);
1841-
$zipFile->saveAsFile($this->outputFilename);
1842-
$zipFile->close();
1843-
1844-
self::assertCorrectZipArchive($this->outputFilename);
1845-
1846-
$result = self::doZipAlignVerify($this->outputFilename, true);
1847-
self::assertNotNull($result);
1848-
1849-
// check zip align
1850-
self::assertTrue($result);
1851-
}
1852-
18531748
public function testFilename0()
18541749
{
18551750
$zipFile = new ZipFile();

tests/PhpZip/resources/test.apk

1.56 MB
Binary file not shown.

0 commit comments

Comments
 (0)