log(LogLevel::DEBUG, __CLASS__ . " :: New instance"); if ( !class_exists('\ZipArchive')) { $this->setError('Your server does not support the ZipArchive extension. Please use a different Archiver Engine and retry backing up your site'); } parent::__construct(); } /** * Common code which gets called on instance creation or wake-up (unserialization) * * @codeCoverageIgnore * * @return void */ public function __bootstrap_code() { parent::__bootstrap_code(); // So that the first run doesn't crash! if (empty($this->_dataFileName)) { return; } // Try to reopen the ZIP $this->zip = new \ZipArchive; if ( !file_exists($this->_dataFileName)) { $res = $this->zip->open($this->_dataFileName, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); } else { $res = $this->zip->open($this->_dataFileName); } if ($res !== true) { switch ($res) { case \ZipArchive::ER_EXISTS: $this->setError("The archive {$this->_dataFileName} already exists"); break; case \ZipArchive::ER_INCONS: $this->setError("Inconsistent archive {$this->_dataFileName} detected"); break; case \ZipArchive::ER_INVAL: $this->setError("Invalid archive {$this->_dataFileName} detected"); break; case \ZipArchive::ER_MEMORY: $this->setError("Not enough memory to process archive {$this->_dataFileName}"); break; case \ZipArchive::ER_NOENT: $this->setError("Unexpected ZipArchive::ER_NOENT error processing archive {$this->_dataFileName}"); break; case \ZipArchive::ER_NOZIP: $this->setError("File {$this->_dataFileName} is not a ZIP archive!"); break; case \ZipArchive::ER_OPEN: $this->setError("Could not open archive file {$this->_dataFileName} for writing"); break; case \ZipArchive::ER_READ: $this->setError("Could not read from archive file {$this->_dataFileName}"); break; case \ZipArchive::ER_SEEK: $this->setError("Could not seek into position while processing archive file {$this->_dataFileName}"); break; } } } /** * Initialises the archiver class, creating the archive from an existent * installer's JPA archive. * * @param string $sourceJPAPath Absolute path to an installer's JPA archive * @param string $targetArchivePath Absolute path to the generated archive * @param array $options A named key array of options (optional). This is currently not supported * * @return void */ public function initialize($targetArchivePath, $options = array()) { Factory::getLog()->log(LogLevel::DEBUG, __CLASS__ . " :: initialize - archive $targetArchivePath"); // Get names of temporary files $this->_dataFileName = $targetArchivePath; // Try to kill the archive if it exists Factory::getLog()->log(LogLevel::DEBUG, __CLASS__ . " :: Killing old archive"); $fp = fopen($this->_dataFileName, "wb"); if ( !($fp === false)) { ftruncate($fp, 0); fclose($fp); } else { @unlink($this->_dataFileName); } $this->runningSum = 0; // Make sure we open the file $this->__bootstrap_code(); } /** * In this engine, we have no finalization, really * * @return void */ public function finalize() { $this->zip->close(); if (function_exists('chmod')) { chmod($this->_dataFileName, 0666); } } /** * Returns a string with the extension (including the dot) of the files produced * by this class. * * @return string */ public function getExtension() { return '.zip'; } /** * The most basic file transaction: add a single entry (file or directory) to * the archive. * * @param bool $isVirtual If true, the next parameter contains file data instead of a file name * @param string $sourceNameOrData Absolute file name to read data from or the file data itself is $isVirtual is * true * @param string $targetName The (relative) file name under which to store the file in the archive * * @return bool True on success, false otherwise */ protected function _addFile($isVirtual, &$sourceNameOrData, $targetName) { if (!is_object($this->zip)) { return false; } if (!$isVirtual) { Factory::getLog()->log(LogLevel::DEBUG, __CLASS__ . " :: Adding $sourceNameOrData"); if (is_dir($sourceNameOrData)) { $result = $this->zip->addEmptyDir($targetName); } else { $this->runningSum += filesize($sourceNameOrData); $result = $this->zip->addFile($sourceNameOrData, $targetName); } } else { Factory::getLog()->log(LogLevel::DEBUG, ' Virtual add:' . $targetName . ' (' . strlen($sourceNameOrData) . ')'); $this->runningSum += strlen($sourceNameOrData); if (empty($sourceNameOrData)) { $result = $this->zip->addEmptyDir($targetName); } else { $result = $this->zip->addFromString($targetName, $sourceNameOrData); } } $this->zip->close(); $this->__bootstrap_code(); return true; } }