mirror of
https://github.com/Ne-Lexa/php-zip.git
synced 2025-05-03 13:34:03 +02:00
350 lines
13 KiB
PHP
350 lines
13 KiB
PHP
<?php
|
|
|
|
namespace PhpZip;
|
|
|
|
use PhpZip\Exception\ZipAuthenticationException;
|
|
use PhpZip\Model\ZipInfo;
|
|
use PhpZip\Util\CryptoUtil;
|
|
|
|
/**
|
|
* Tests with zip password.
|
|
*/
|
|
class ZipPasswordTest extends ZipFileAddDirTest
|
|
{
|
|
/**
|
|
* Test archive password.
|
|
*/
|
|
public function testSetPassword()
|
|
{
|
|
if (PHP_INT_SIZE === 4) {
|
|
$this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
|
|
}
|
|
|
|
$password = base64_encode(CryptoUtil::randomBytes(100));
|
|
$badPassword = "bad password";
|
|
|
|
// create encryption password with ZipCrypto
|
|
$zipFile = new ZipFile();
|
|
$zipFile->addDir(__DIR__);
|
|
$zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
|
|
$zipFile->saveAsFile($this->outputFilename);
|
|
$zipFile->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, $password);
|
|
|
|
// check bad password for ZipCrypto
|
|
$zipFile->openFile($this->outputFilename);
|
|
$zipFile->setReadPassword($badPassword);
|
|
foreach ($zipFile->getListFiles() as $entryName) {
|
|
try {
|
|
$zipFile[$entryName];
|
|
self::fail("Expected Exception has not been raised.");
|
|
} catch (ZipAuthenticationException $ae) {
|
|
self::assertNotNull($ae);
|
|
}
|
|
}
|
|
|
|
// check correct password for ZipCrypto
|
|
$zipFile->setReadPassword($password);
|
|
foreach ($zipFile->getAllInfo() as $info) {
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('ZipCrypto', $info->getMethodName());
|
|
$decryptContent = $zipFile[$info->getName()];
|
|
self::assertNotEmpty($decryptContent);
|
|
self::assertContains('<?php', $decryptContent);
|
|
}
|
|
|
|
// change encryption method to WinZip Aes and update file
|
|
$zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
|
|
$zipFile->saveAsFile($this->outputFilename);
|
|
$zipFile->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, $password);
|
|
|
|
// check from WinZip AES encryption
|
|
$zipFile->openFile($this->outputFilename);
|
|
// set bad password WinZip AES
|
|
$zipFile->setReadPassword($badPassword);
|
|
foreach ($zipFile->getListFiles() as $entryName) {
|
|
try {
|
|
$zipFile[$entryName];
|
|
self::fail("Expected Exception has not been raised.");
|
|
} catch (ZipAuthenticationException $ae) {
|
|
self::assertNotNull($ae);
|
|
}
|
|
}
|
|
|
|
// set correct password WinZip AES
|
|
$zipFile->setReadPassword($password);
|
|
foreach ($zipFile->getAllInfo() as $info) {
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('WinZip', $info->getMethodName());
|
|
$decryptContent = $zipFile[$info->getName()];
|
|
self::assertNotEmpty($decryptContent);
|
|
self::assertContains('<?php', $decryptContent);
|
|
}
|
|
|
|
// clear password
|
|
$zipFile->addFromString('file1', '');
|
|
$zipFile->disableEncryption();
|
|
$zipFile->addFromString('file2', '');
|
|
$zipFile->saveAsFile($this->outputFilename);
|
|
$zipFile->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename);
|
|
|
|
// check remove password
|
|
$zipFile->openFile($this->outputFilename);
|
|
foreach ($zipFile->getAllInfo() as $info) {
|
|
self::assertFalse($info->isEncrypted());
|
|
}
|
|
$zipFile->close();
|
|
}
|
|
|
|
public function testTraditionalEncryption()
|
|
{
|
|
if (PHP_INT_SIZE === 4) {
|
|
$this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
|
|
}
|
|
|
|
$password = base64_encode(CryptoUtil::randomBytes(50));
|
|
|
|
$zip = new ZipFile();
|
|
$zip->addDirRecursive($this->outputDirname);
|
|
$zip->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
|
|
$zip->saveAsFile($this->outputFilename);
|
|
$zip->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, $password);
|
|
|
|
$zip->openFile($this->outputFilename);
|
|
$zip->setReadPassword($password);
|
|
self::assertFilesResult($zip, array_keys(self::$files));
|
|
foreach ($zip->getAllInfo() as $info) {
|
|
if (!$info->isFolder()) {
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('ZipCrypto', $info->getMethodName());
|
|
}
|
|
}
|
|
$zip->close();
|
|
}
|
|
|
|
/**
|
|
* @dataProvider winZipKeyStrengthProvider
|
|
* @param int $encryptionMethod
|
|
* @param int $bitSize
|
|
*/
|
|
public function testWinZipAesEncryption($encryptionMethod, $bitSize)
|
|
{
|
|
$password = base64_encode(CryptoUtil::randomBytes(50));
|
|
|
|
$zip = new ZipFile();
|
|
$zip->addDirRecursive($this->outputDirname);
|
|
$zip->setPassword($password, $encryptionMethod);
|
|
$zip->saveAsFile($this->outputFilename);
|
|
$zip->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, $password);
|
|
|
|
$zip->openFile($this->outputFilename);
|
|
$zip->setReadPassword($password);
|
|
self::assertFilesResult($zip, array_keys(self::$files));
|
|
foreach ($zip->getAllInfo() as $info) {
|
|
if (!$info->isFolder()) {
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertEquals($info->getEncryptionMethod(), $encryptionMethod);
|
|
self::assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
|
|
}
|
|
}
|
|
$zip->close();
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function winZipKeyStrengthProvider()
|
|
{
|
|
return [
|
|
[ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
|
|
[ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
|
|
[ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES, 256],
|
|
[ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
|
|
];
|
|
}
|
|
|
|
public function testEncryptionEntries()
|
|
{
|
|
if (PHP_INT_SIZE === 4) {
|
|
$this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
|
|
}
|
|
|
|
$password1 = '353442434235424234';
|
|
$password2 = 'adgerhvrwjhqqehtqhkbqrgewg';
|
|
|
|
$zip = new ZipFile();
|
|
$zip->addDir($this->outputDirname);
|
|
$zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
|
|
$zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
|
|
$zip->saveAsFile($this->outputFilename);
|
|
$zip->close();
|
|
|
|
$zip->openFile($this->outputFilename);
|
|
$zip->setReadPasswordEntry('.hidden', $password1);
|
|
$zip->setReadPasswordEntry('text file.txt', $password2);
|
|
self::assertFilesResult($zip, [
|
|
'.hidden',
|
|
'text file.txt',
|
|
'Текстовый документ.txt',
|
|
'empty dir/',
|
|
]);
|
|
|
|
$info = $zip->getEntryInfo('.hidden');
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('ZipCrypto', $info->getMethodName());
|
|
|
|
$info = $zip->getEntryInfo('text file.txt');
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('WinZip AES', $info->getMethodName());
|
|
|
|
self::assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
|
|
self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
|
|
|
$zip->close();
|
|
}
|
|
|
|
public function testEncryptionEntriesWithDefaultPassword()
|
|
{
|
|
if (PHP_INT_SIZE === 4) {
|
|
$this->markTestSkipped('Skip test for 32-bit system. Not support Traditional PKWARE Encryption.');
|
|
}
|
|
|
|
$password1 = '353442434235424234';
|
|
$password2 = 'adgerhvrwjhqqehtqhkbqrgewg';
|
|
$defaultPassword = ' f f f f f ffff f5 ';
|
|
|
|
$zip = new ZipFile();
|
|
$zip->addDir($this->outputDirname);
|
|
$zip->setPassword($defaultPassword);
|
|
$zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
|
|
$zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
|
|
$zip->saveAsFile($this->outputFilename);
|
|
$zip->close();
|
|
|
|
$zip->openFile($this->outputFilename);
|
|
$zip->setReadPassword($defaultPassword);
|
|
$zip->setReadPasswordEntry('.hidden', $password1);
|
|
$zip->setReadPasswordEntry('text file.txt', $password2);
|
|
self::assertFilesResult($zip, [
|
|
'.hidden',
|
|
'text file.txt',
|
|
'Текстовый документ.txt',
|
|
'empty dir/',
|
|
]);
|
|
|
|
$info = $zip->getEntryInfo('.hidden');
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('ZipCrypto', $info->getMethodName());
|
|
|
|
$info = $zip->getEntryInfo('text file.txt');
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('WinZip AES', $info->getMethodName());
|
|
|
|
$info = $zip->getEntryInfo('Текстовый документ.txt');
|
|
self::assertTrue($info->isEncrypted());
|
|
self::assertContains('WinZip AES', $info->getMethodName());
|
|
|
|
self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
|
|
|
|
$zip->close();
|
|
}
|
|
|
|
/**
|
|
* @expectedException \PhpZip\Exception\ZipException
|
|
* @expectedExceptionMessage Invalid encryption method
|
|
*/
|
|
public function testSetEncryptionMethodInvalid()
|
|
{
|
|
$zipFile = new ZipFile();
|
|
$encryptionMethod = 9999;
|
|
$zipFile->setPassword('pass', $encryptionMethod);
|
|
$zipFile['entry'] = 'content';
|
|
$zipFile->outputAsString();
|
|
}
|
|
|
|
public function testEntryPassword()
|
|
{
|
|
$zipFile = new ZipFile();
|
|
$zipFile->setPassword('pass');
|
|
$zipFile['file'] = 'content';
|
|
self::assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
|
|
for ($i = 1; $i <= 10; $i++) {
|
|
$zipFile['file' . $i] = 'content';
|
|
if ($i < 6) {
|
|
$zipFile->setPasswordEntry('file' . $i, 'pass');
|
|
self::assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
|
} else {
|
|
self::assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
|
|
}
|
|
}
|
|
$zipFile->disableEncryptionEntry('file3');
|
|
self::assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
|
|
self::asserttrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
|
$zipFile->disableEncryption();
|
|
$infoList = $zipFile->getAllInfo();
|
|
array_walk($infoList, function (ZipInfo $zipInfo) {
|
|
self::assertFalse($zipInfo->isEncrypted());
|
|
});
|
|
$zipFile->close();
|
|
}
|
|
|
|
/**
|
|
* @expectedException \PhpZip\Exception\ZipException
|
|
* @expectedExceptionMessage Invalid encryption method
|
|
*/
|
|
public function testInvalidEncryptionMethodEntry()
|
|
{
|
|
$zipFile = new ZipFile();
|
|
$zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
|
|
$zipFile->setPasswordEntry('file', 'pass', 99);
|
|
}
|
|
|
|
public function testArchivePasswordUpdateWithoutSetReadPassword()
|
|
{
|
|
$zipFile = new ZipFile();
|
|
$zipFile['file1'] = 'content';
|
|
$zipFile['file2'] = 'content';
|
|
$zipFile['file3'] = 'content';
|
|
$zipFile->setPassword('password');
|
|
$zipFile->saveAsFile($this->outputFilename);
|
|
$zipFile->close();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, 'password');
|
|
|
|
$zipFile->openFile($this->outputFilename);
|
|
self::assertCount(3, $zipFile);
|
|
foreach ($zipFile->getAllInfo() as $info) {
|
|
self::assertTrue($info->isEncrypted());
|
|
}
|
|
unset($zipFile['file3']);
|
|
$zipFile['file4'] = 'content';
|
|
$zipFile->rewrite();
|
|
|
|
self::assertCorrectZipArchive($this->outputFilename, 'password');
|
|
|
|
self::assertCount(3, $zipFile);
|
|
self::assertFalse(isset($zipFile['file3']));
|
|
self::assertTrue(isset($zipFile['file4']));
|
|
self::assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
|
|
self::assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
|
|
self::assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
|
|
self::assertEquals($zipFile['file4'], 'content');
|
|
|
|
$zipFile->extractTo($this->outputDirname, ['file4']);
|
|
|
|
self::assertTrue(file_exists($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'));
|
|
self::assertEquals(file_get_contents($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'), $zipFile['file4']);
|
|
|
|
$zipFile->close();
|
|
}
|
|
}
|