Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(Task/Ext/Archive/ZipTask): Preseves directories' permissions in zip #1820

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions etc/phing-grammar.rng
Original file line number Diff line number Diff line change
Expand Up @@ -7242,6 +7242,11 @@
<data type="boolean"/>
</attribute>
</optional>
<optional>
<attribute name="savefileattributes" a:defaultValue="false">
<data type="boolean"/>
</attribute>
</optional>
</interleave>
<zeroOrMore>
<ref name="fileset"/>
Expand Down
55 changes: 54 additions & 1 deletion src/Phing/Task/Ext/Archive/ZipTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class ZipTask extends MatchingTask

private $ignoreLinks = false;

private $saveFileAttributes = false;

/**
* File path prefix in zip archive
*
Expand All @@ -72,6 +74,21 @@ class ZipTask extends MatchingTask
* @var string $comment
*/
private $comment = '';
private string $mtimeDummy;

/**
* Removes all external attributes from the Zip archive.
*
* @param \ZipArchive $zip The Zip archive
*
* @return void
*/
private static function clearExternalAttributes(\ZipArchive $zip)
{
for ($i = 0, $count = $zip->count(); $i < $count; ++$i) {
$zip->setExternalAttributesIndex($i, \ZipArchive::OPSYS_DOS, 0);
}
}

/**
* Add a new fileset.
Expand Down Expand Up @@ -150,6 +167,17 @@ public function setIgnoreLinks($bool)
$this->ignoreLinks = (bool) $bool;
}

/**
* Set the save file attributes flag.
*
* @param bool $bool Flag if file attributes should be saved
* @return void
*/
public function setSaveFileAttributes($bool)
{
$this->saveFileAttributes = (bool) $bool;
}

/**
* Add a comment to the zip archive.
*
Expand Down Expand Up @@ -220,6 +248,10 @@ public function main()

$this->log("Building zip: " . $this->zipFile->__toString(), Project::MSG_INFO);

if (false === $this->mtimeDummy = tempnam(sys_get_temp_dir(), 'mtimeDummy')) {
throw new Exception('Could not create temp file');
}

$zip = new ZipArchive();
$res = $zip->open($this->zipFile->getAbsolutePath(), ZipArchive::CREATE);

Expand All @@ -236,7 +268,12 @@ public function main()

$this->addFilesetsToArchive($zip);

if (!$this->saveFileAttributes) {
self::clearExternalAttributes($zip);
}

$zip->close();
unlink($this->mtimeDummy);
} catch (IOException $ioe) {
$msg = "Problem creating ZIP: " . $ioe->getMessage();
throw new BuildException($msg, $ioe, $this->getLocation());
Expand Down Expand Up @@ -305,7 +342,7 @@ private function addFilesetsToArchive($zip)

if ($f->isDirectory()) {
if ($pathInZip != '.') {
$zip->addEmptyDir($pathInZip);
$this->addDirToZip($zip, $f->getAbsolutePath(), $pathInZip . '/');
}
} else {
$zip->addFile($f->getAbsolutePath(), $pathInZip);
Expand All @@ -314,4 +351,20 @@ private function addFilesetsToArchive($zip)
}
}
}

/**
* @param \ZipArchive $zip
* @param string $dirPath
* @param string $entryName
*
* @return void
*/
private function addDirToZip(\ZipArchive $zip, string $dirPath, string $entryName)
{
touch($this->mtimeDummy, filemtime($dirPath)); // Save directory's mtime to dummmy
$zip->addFile($this->mtimeDummy, $entryName); // Add empty dummy as a directory
if (false !== $filePerms = fileperms($dirPath)) { // filePerms supported
$zip->setExternalAttributesName($entryName, \ZipArchive::OPSYS_UNIX, $filePerms << 16);
}
}
}