In PHP 7.4, neither ZipArchive::setMtimeIndex
nor ZipArchive::setMtimeName
is available.
When creating Zip archives from files in PHP 7.4, files mtime
and permissions are applied to the corresponding Zip entries’ attributes. When calling ZipArchive::addFile, permissions and mtime
are those from the source file..
Unfortunately, it is not the case when creating directories in the Zip archive, because those are created empty and not read from the filesystem.
I created a fixDirAttributes
to fix the mtime and permissions for directories within a Zip archive. But his cannot work with PHP 7.4.
Do you know a way to fix the mtime
of a Zip archive directories in PHP 7.4?
Here is my code to reproduce the issue:
#!/usr/bin/env php7.4
<?php
if (!file_exists('myDir')) mkdir('myDir');
file_put_contents('myDir/test.txt', 'test');
chmod('myDir/test.txt', 0740);
chmod('myDir', 0750);
touch('myDir/test.txt', mktime(10, 10, 0, 1, 1, 2024));
touch('myDir', mktime(5, 42, 0, 1, 1, 2024));
if (file_exists('test.zip')) unlink('test.zip');
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === true) {
$zip->addEmptyDir("myDir");
fixDirAttributes($zip, 'myDir', 'myDir'); // Directory already existe in current dir ./myDir
$zip->addFile('myDir/text.txt', 'myDir/text.txt'); // file exist in ./myDir dir
$zip->close();
echo "Okn";
} else {
echo "KOn";
}
function fixDirAttributes(ZipArchive $zip, string $dirPath, string $pathInZip)
{
$indexInZip = $zip->locateName('/' === mb_substr($pathInZip, -1) ? $pathInZip : $pathInZip . '/');
if (false !== $indexInZip) {
if (method_exists($zip, 'setMtimeIndex')) { // PHP >= 8.0.0, PECL zip >= 1.16.0
$zip->setMtimeIndex($indexInZip, filemtime($dirPath));
}
$filePerms = fileperms($dirPath);
if (false !== $filePerms) { // filePerms supported
$zip->setExternalAttributesIndex($indexInZip, ZipArchive::OPSYS_DEFAULT, $filePerms << 16);
}
}
}