diff --git a/etc/phing-grammar.rng b/etc/phing-grammar.rng index 57919974f..03139d18b 100644 --- a/etc/phing-grammar.rng +++ b/etc/phing-grammar.rng @@ -7242,6 +7242,11 @@ + + + + + diff --git a/src/Phing/Task/Ext/Archive/ZipTask.php b/src/Phing/Task/Ext/Archive/ZipTask.php index c1bcddfe5..51c7f2b12 100644 --- a/src/Phing/Task/Ext/Archive/ZipTask.php +++ b/src/Phing/Task/Ext/Archive/ZipTask.php @@ -59,6 +59,8 @@ class ZipTask extends MatchingTask private $ignoreLinks = false; + private $saveFileAttributes = false; + /** * File path prefix in zip archive * @@ -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. @@ -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. * @@ -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); @@ -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()); @@ -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); @@ -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); + } + } }