/** * Creates a randomly-named temporary file, registers it with the temporary * files management and returns its absolute path * @return string The temporary file name */ function createRegisterTempFile() { // Create a randomly named file in the temp directory $registry =& JoomlapackModelRegistry::getInstance(); $tempFile = tempnam($registry->getTemporaryDirectory(), 'jp'); // Register it and return its absolute path $tempName = basename($tempFile); return JoomlapackCUBETempfiles::registerTempFile($tempName); }
/** * Finalises the archive by compressing it. Overrides parent's method * @return boolean TRUE on success, FALSE on failure */ function finalize() { // Get gzip's binary location $registry = JoomlapackModelRegistry::getInstance(); $gzip = escapeshellcmd($registry->get('gzipbinary')); // Construct and run command line $command = "{$gzip} " . escapeshellcmd($this->_tempFilename); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackPackerTARGZ :: Calling gzip. The command line is:"); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, $command); $result = shell_exec($command); // Normally, gzip should be silent as a fish. If anything was sput out, // there must have been an error. if (strlen(trim($result)) > 0) { $errorMessage = "Error calling gzip: " . $result . " \n Command line was: \n " . $command . " \n Please check file permissions and examine the result message for any hints regarding the problem tar faced archiving your files."; $this->setError($errorMessage); return false; } // Now, unregister the temp file (which no longer exists), register the gzipped file as // a new temp file and try to move it JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_tempFilename); $this->_tempFilename = JoomlapackCUBETempfiles::registerTempFile(basename($this->_archiveFilename)); copy($this->_tempFilename, $this->_archiveFilename); JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_tempFilename); // If no errors occured, return true return true; }
/** * Creates the ZIP file out of its pieces. * Official ZIP file format: http://www.pkware.com/appnote.txt * * @return boolean TRUE on success, FALSE on failure */ function finalize() { // 1. Get size of central directory clearstatcache(); $cdSize = @filesize($this->_ctrlDirFileName); // 2. Append Central Directory to data file and remove the CD temp file afterwards $dataFP = fopen($this->_dataFileName, "ab"); $cdFP = fopen($this->_ctrlDirFileName, "rb"); if ($dataFP === false) { $this->setError('Could not open ZIP data file ' . $this->_dataFileName . ' for reading'); return false; } if ($cdFP === false) { // Already glued, return fclose($dataFP); return false; } if (!$this->_useSplitZIP) { while (!feof($cdFP)) { $chunk = fread($cdFP, _JoomlapackPackerZIP_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); } else { // Calcuate size of Central Directory + EOCD records $total_cd_eocd_size = $cdSize + 22 + strlen($this->_comment); // Free space on the part clearstatcache(); $current_part_size = @filesize($this->_dataFileName); $free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size); if ($free_space < $total_cd_eocd_size && $total_cd_eocd_size > 65536) { // Not enough space on archive for CD + EOCD, will go on separate part // Create new final part if (!$this->_createNewPart(true)) { // Die if we couldn't create the new part $this->setError('Could not create new ZIP part file ' . basename($this->_dataFileName)); return false; } else { // Close the old data file fclose($dataFP); // Open data file for output $dataFP = @fopen($this->_dataFileName, "ab"); if ($dataFP === false) { $this->setError("Could not open archive file {$this->_dataFileName} for append!"); return false; } // Write the CD record while (!feof($cdFP)) { $chunk = fread($cdFP, _JoomlapackPackerZIP_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); } } else { // Glue the CD + EOCD on the same part if they fit, or anyway if they are less than 64Kb. // NOTE: WE *MUST NOT* CREATE FRAGMENTS SMALLER THAN 64Kb!!!! while (!feof($cdFP)) { $chunk = fread($cdFP, _JoomlapackPackerZIP_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); } } JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_ctrlDirFileName); // 3. Write the rest of headers to the end of the ZIP file fclose($dataFP); clearstatcache(); $dataSize = @filesize($this->_dataFileName) - $cdSize; $dataFP = fopen($this->_dataFileName, "ab"); if ($dataFP === false) { $this->setError('Could not open ' . $this->_dataFileName . ' for append'); return false; } $this->_fwrite($dataFP, $this->_ctrlDirEnd); if ($this->getError()) { return; } if ($this->_useSplitZIP) { // Split ZIP files, enter relevant disk number information $this->_fwrite($dataFP, pack('v', $this->_totalFragments - 1)); /* Number of this disk. */ $this->_fwrite($dataFP, pack('v', $this->_totalFragments - 1)); /* Disk with central directory start. */ } else { // Non-split ZIP files, the disk numbers MUST be 0 $this->_fwrite($dataFP, pack('V', 0)); } $this->_fwrite($dataFP, pack('v', $this->_totalFileEntries)); /* Total # of entries "on this disk". */ $this->_fwrite($dataFP, pack('v', $this->_totalFileEntries)); /* Total # of entries overall. */ $this->_fwrite($dataFP, pack('V', $cdSize)); /* Size of central directory. */ $this->_fwrite($dataFP, pack('V', $dataSize)); /* Offset to start of central dir. */ $sizeOfComment = strlen($this->_comment); // 2.0.b2 -- Write a ZIP file comment $this->_fwrite($dataFP, pack('v', $sizeOfComment)); /* ZIP file comment length. */ $this->_fwrite($dataFP, $this->_comment); fclose($dataFP); //sleep(2); // If Split ZIP and there is no .zip file, rename the last fragment to .ZIP if ($this->_useSplitZIP) { $extension = substr($this->_dataFileName, -3); if ($extension != '.zip') { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, 'Renaming last ZIP part to .ZIP extension'); $newName = $this->_dataFileNameBase . '.zip'; if (!@rename($this->_dataFileName, $newName)) { $this->setError('Could not rename last ZIP part to .ZIP extension.'); return false; } $this->_dataFileName = $newName; } } // If Split ZIP and only one fragment, change the signature if ($this->_useSplitZIP && $this->_totalFragments == 1) { $fp = fopen($this->_dataFileName, 'r+b'); $this->_fwrite($fp, "PK00"); } // @todo If Split ZIP, update CUBE with total number of fragments if (function_exists('chmod')) { @chmod($this->_dataFileName, 0755); } return true; }
/** * 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 True on success, false otherwise * @since 2.1 * @access protected * @abstract */ function _addFile($isVirtual, &$sourceNameOrData, $targetName) { if ($isVirtual) { // VIRTUAL FILES // Create and register temp file with the virtual contents $tempFileName = JoomlapackCUBETempfiles::registerTempFile(basename($targetName)); if (function_exists('file_put_contents')) { file_put_contents($tempFileName, $sourceNameOrData); } else { $tempHandler = fopen($tempFileName, 'wb'); $this->_fwrite($tempHandler, $sourceNameOrData); fclose($tempHandler); } // Calculate add / remove paths $removePath = dirname($tempFileName); $addPath = dirname($targetName); // Add the file $this->_tarObject->addModify($tempFileName, $addPath, $removePath, $tempFileName); // Remove the temporary file JoomlapackCUBETempfiles::unregisterAndDeleteTempFile(basename($targetName)); } else { // REGULAR FILES if ($targetName == '') { $targetName = $sourceNameOrData; } $this->_tarObject->addModify($sourceNameOrData, '', JPATH_SITE, $targetName); } }
/** * Find where to store the backup files */ function _getBackupFilePaths() { $configuration =& JoomlapackModelRegistry::getInstance(); switch ($configuration->get('BackupType')) { case 'dbonly': // On DB Only backups we use different naming, no matter what's the setting JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: Only dump database mode detected"); // Fix 2.0: Backup file name MUST be taken from the statitics record! $cube =& JoomlapackCUBE::getInstance(); $statID = $cube->_statID; $statModel = new JoomlapackModelStatistics($statID); $statModel->setId($statID); $statRecord =& $statModel->getStatistic(); $this->_tempFile = $statRecord->absolute_path; $this->_saveAsName = ''; break; case 'full': if ($this->_dumpFile != '') { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: Forced filename using dumpFile found."); // If the dumpFile was set, forcibly use this value $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . $this->_dumpFile))); $this->_saveAsName = 'installation/sql/' . $this->_dumpFile; } else { if ($this->_isJoomla) { // Joomla! Core Database, use the JoomlaPack way of figuring out the filenames JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: Core database"); $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . 'joomla.sql'))); $this->_saveAsName = 'installation/sql/joomla.sql'; } else { // External databases, we use the database's name JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: External database"); $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . $this->_database . '.sql'))); $this->_saveAsName = 'installation/sql/' . $this->_database . '.sql'; } } break; case 'extradbonly': if ($this->_dumpFile != '') { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: Forced filename using dumpFile found."); // If the dumpFile was set, forcibly use this value $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . $this->_dumpFile))); $this->_saveAsName = $this->_dumpFile; } else { if ($this->_isJoomla) { // Joomla! Core Database, use the JoomlaPack way of figuring out the filenames JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: Core database"); $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . 'joomla.sql'))); $this->_saveAsName = 'joomla.sql'; } else { // External databases, we use the database's name JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDumperDefault :: External database"); $this->_tempFile = JoomlapackCUBETempfiles::registerTempFile(dechex(crc32(microtime() . $this->_database . '.sql'))); $this->_saveAsName = $this->_database . '.sql'; } } break; } JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDomainDBBackup :: SQL temp file is " . $this->_tempFile); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackDomainDBBackup :: SQL file location in archive is " . $this->_saveAsName); }
function _finalise() { global $mainframe; // The backup is over. Did we encounter any errors? if ($this->getError()) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Can't finalise due to errors"); // Notify Super Administrators if it's a front-end backup if (!$mainframe->isAdmin()) { $this->_mailToSuperAdministrators($this->getError()); } // Oops! Have to reset() because of the error $this->reset(); } else { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Finalising backup started"); // Notify Super Administrators if it's a front-end backup if (!$mainframe->isAdmin()) { $this->_mailToSuperAdministrators(); } // Remove temp files JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Removing temporary files"); JoomlapackCUBETempfiles::deleteTempFiles(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Updating statistics"); // We finished normally. Fetch the stats record $this->statmodel = null; $this->statmodel = new JoomlapackModelStatistics($this->_statID); $this->statmodel->setId($this->_statID); $statRecord =& $this->statmodel->getStatistic(); jimport('joomla.utilities.date'); $jdate = new JDate(); $statRecord->backupend = $jdate->toMySQL(); $statRecord->status = 'complete'; $this->statmodel->save($statRecord); // Apply quotas $errorReporting = @error_reporting(0); $quotaFiles = $this->statmodel->getOldBackupsToDelete(); if (count($quotaFiles) > 0) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Applying quotas"); jimport('joomla.filesystem.file'); foreach ($quotaFiles as $file) { // Try to delete the file using either unlink() or, if it fails, the // Joomla!'s JFile::delete method (which might use FTP to do it!). if (!@unlink($file)) { // FIX 2.0: Using JFile::delete raised warnings which messed up XMLRPC output. After all, we write backup files from PHP, using FTP should not be necessary to delete them! JoomlapackLogger::WriteLog(_JP_LOG_WARNING, "Failed to remove old backup file " . $file); /* if(!@JFile::delete($file)) { // Warn if an existing file wasn't deleted when trying to apply quotas if( JFile::exists($file) ) JoomlapackLogger::WriteLog(_JP_LOG_WARNING, "Failed to remove old backup file ".$file ); } */ } } } @error_reporting($errorReporting); // Set internal variables and go to bed... er... I mean, return control to the user $this->_isFinished = true; $this->_activeDomain = 'finale'; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Finalising backup ended"); } }
/** * 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 True on success, false otherwise * @since 1.2.1 * @access protected * @abstract */ function _addFile($isVirtual, &$sourceNameOrData, $targetName) { // Are we connected to a server? if (!is_resource($this->_ftphandle)) { if (!$this->_connectFTP()) { return false; } } // See if it's a directory $isDir = $isVirtual ? false : is_dir($sourceNameOrData); if ($isDir) { // Just try to create the remote directory return $this->_makeDirectory($targetName); } else { // We have a file we need to upload if ($isVirtual) { // Create a temporary file, upload, rename it $tempFileName = JoomlapackCUBETempfiles::createRegisterTempFile(); if (function_exists('file_put_contents')) { if (@file_put_contents($tempFileName, $sourceNameOrData) === false) { $this->setError('Could not upload virtual file ' . $targetName); return false; } $res = $this->_upload($tempFileName, $targetName); JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($tempFileName, true); return $res; } } else { // Upload a file return $this->_upload($sourceNameOrData, $targetName); } } }
/** * Creates the ZIP file out of its pieces. * Official ZIP file format: http://www.pkware.com/appnote.txt * * @return boolean TRUE on success, FALSE on failure */ function finalize() { // 1. Get size of central directory clearstatcache(); $cdSize = filesize($this->_ctrlDirFileName); // 2. Append Central Directory to data file and remove the CD temp file afterwards $dataFP = fopen($this->_dataFileName, "ab"); $cdFP = fopen($this->_ctrlDirFileName, "rb"); if ($dataFP === false) { $this->setError('Could not open ZIP data file ' . $this->_dataFileName . ' for reading'); return false; } if ($cdFP === false) { // Already glued, return fclose($dataFP); return false; } while (!feof($cdFP)) { $chunk = fread($cdFP, _JoomlapackPackerZIP_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); JoomlapackCUBETempfiles::unregisterAndDeleteTempFile($this->_ctrlDirFileName); // 3. Write the rest of headers to the end of the ZIP file fclose($dataFP); clearstatcache(); $dataSize = filesize($this->_dataFileName) - $cdSize; $dataFP = fopen($this->_dataFileName, "ab"); if ($dataFP === false) { $this->setError('Could not open ' . $this->_dataFileName . ' for append'); return false; } $this->_fwrite($dataFP, $this->_ctrlDirEnd); if ($this->getError()) { return; } $this->_fwrite($dataFP, pack('v', $this->_totalFileEntries)); /* Total # of entries "on this disk". */ $this->_fwrite($dataFP, pack('v', $this->_totalFileEntries)); /* Total # of entries overall. */ $this->_fwrite($dataFP, pack('V', $cdSize)); /* Size of central directory. */ $this->_fwrite($dataFP, pack('V', $dataSize)); /* Offset to start of central dir. */ $sizeOfComment = strlen($this->_comment); // 2.0.b2 -- Write a ZIP file comment $this->_fwrite($dataFP, pack('v', $sizeOfComment)); /* ZIP file comment length. */ $this->_fwrite($dataFP, $this->_comment); fclose($dataFP); //sleep(2); if (function_exists('chmod')) { @chmod($this->_dataFileName, 0755); } return true; }