/** * Creates a new dump part */ protected function getNextDumpPart() { // On database dump only mode we mustn't create part files! if (AEUtilScripting::getScriptingParameter('db.saveasname', 'normal') == 'output') { return false; } // If the archiver is still processing, quit $finished = true; $configuration = AEFactory::getConfiguration(); $archiver = AEFactory::getArchiverEngine(); if ($configuration->get('volatile.engine.archiver.processingfile', false)) { return false; } // We have to add the dump file to the archive $this->closeFile(); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Adding the SQL dump part to the archive"); $archiver->addFileRenamed($this->tempFile, $this->saveAsName); if ($this->getError()) { return false; } $finished = !$configuration->get('volatile.engine.archiver.processingfile', false); if (!$finished) { return false; } // Return if the file didn't finish getting added to the archive // Remove the old file AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Removing dump part's temporary file"); AEUtilTempfiles::unregisterAndDeleteTempFile($this->tempFile, true); // Create the new dump part $this->partNumber++; $this->getBackupFilePaths($this->partNumber); $null = null; $this->writeline($null); 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 */ public function finalize() { // 1. Get size of central directory clearstatcache(); $cdOffset = @filesize($this->_dataFileName); $this->_totalDataSize += $cdOffset; $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, _AKEEBA_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); } else { // Calcuate size of Central Directory + EOCD records $comment_length = function_exists('mb_strlen') ? mb_strlen($this->_comment, '8bit') : strlen($this->_comment); $total_cd_eocd_size = $cdSize + 22 + $comment_length; // 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, _AKEEBA_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, _AKEEBA_DIRECTORY_READ_CHUNK); $this->_fwrite($dataFP, $chunk); if ($this->getError()) { return; } } unset($chunk); fclose($cdFP); } } AEUtilTempfiles::unregisterAndDeleteTempFile($this->_ctrlDirFileName); // 3. Write the rest of headers to the end of the ZIP file fclose($dataFP); clearstatcache(); $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', $cdOffset)); /* Offset to start of central dir. */ $sizeOfComment = $comment_length = function_exists('mb_strlen') ? mb_strlen($this->_comment, '8bit') : 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') { AEUtilLogger::WriteLog(_AE_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"); } 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 */ protected function _addFile($isVirtual, &$sourceNameOrData, $targetName) { // Are we connected to a server? if (!is_resource($this->_sftphandle)) { if (!$this->_connectSFTP()) { 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 = AEUtilTempfiles::createRegisterTempFile(); if (function_exists('file_put_contents')) { // Easy writing using file_put_contents if (@file_put_contents($tempFileName, $sourceNameOrData) === false) { $this->setError('Could not store virtual file ' . $targetName . ' to ' . $tempFileName . ' using file_put_contents() before uploading.'); return false; } } else { // The long way, using fopen() and fwrite() $fp = @fopen($tempFileName, 'wb'); if ($fp === false) { $this->setError('Could not store virtual file ' . $targetName . ' to ' . $tempFileName . ' using fopen() before uploading.'); return false; } else { $result = @fwrite($fp, $sourceNameOrData); if ($result === false) { $this->setError('Could not store virtual file ' . $targetName . ' to ' . $tempFileName . ' using fwrite() before uploading.'); return false; } @fclose($fp); } } // Upload the temporary file under the final name $res = $this->_upload($tempFileName, $targetName); // Remove the temporary file AEUtilTempfiles::unregisterAndDeleteTempFile($tempFileName, true); return $res; } else { // Upload a file return $this->_upload($sourceNameOrData, $targetName); } } }