diff --git a/datamodels/2.x/itop-backup/dbrestore.class.inc.php b/datamodels/2.x/itop-backup/dbrestore.class.inc.php index b8809d11a5..c74e2838ca 100644 --- a/datamodels/2.x/itop-backup/dbrestore.class.inc.php +++ b/datamodels/2.x/itop-backup/dbrestore.class.inc.php @@ -99,8 +99,10 @@ class DBRestore extends DBBackup } /** - * @param $sFile A file with the extension .zip or .tar.gz + * @param string $sFile A file with the extension .zip or .tar.gz * @param string $sEnvironment Target environment + * + * @throws \Exception */ public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production') { @@ -111,7 +113,7 @@ class DBRestore extends DBBackup { $this->LogInfo('zip file detected'); $oArchive = new ZipArchiveEx(); - $res = $oArchive->open($sFile); + $oArchive->open($sFile); } elseif (substr($sNormalizedFile, -7) == '.tar.gz') { @@ -125,21 +127,22 @@ class DBRestore extends DBBackup // Load the database // - $sDataDir = tempnam(SetupUtils::GetTmpDir(), 'itop-'); - unlink($sDataDir); // I need a directory, not a file... + $sDataDir = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax()); + SetupUtils::builddir($sDataDir); // Here is the directory - $oArchive->extractFileTo($sDataDir, 'itop-dump.sql'); + $oArchive->extractTo($sDataDir); + $sDataFile = $sDataDir.'/itop-dump.sql'; $this->LoadDatabase($sDataFile); - SetupUtils::rrmdir($sDataDir); // Update the code // $sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml'; - if ($oArchive->hasFile('delta.xml') !== false) + + if (is_file($sDataDir.'/delta.xml')) { // Extract and rename delta.xml => .delta.xml; - file_put_contents($sDeltaFile, $oArchive->getFromName('delta.xml')); + rename($sDataDir.'/delta.xml', $sDeltaFile); } else { @@ -149,16 +152,18 @@ class DBRestore extends DBBackup { SetupUtils::rrmdir(APPROOT.'data/production-modules/'); } - if ($oArchive->hasDir('production-modules/') !== false) + if (is_dir($sDataDir.'/production-modules')) { - $oArchive->extractDirTo(APPROOT.'data/', 'production-modules/'); + rename($sDataDir.'/production-modules', APPROOT.'data/production-modules/'); } $sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php'; @chmod($sConfigFile, 0770); // Allow overwriting the file - $oArchive->extractFileTo(APPROOT.'conf/'.$sEnvironment, 'config-itop.php'); + rename($sDataDir.'/config-itop.php', $sConfigFile); @chmod($sConfigFile, 0444); // Read-only + SetupUtils::rrmdir($sDataDir); + $oEnvironment = new RunTimeEnvironment($sEnvironment); $oEnvironment->CompileFrom($sEnvironment); } diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index f2f202ee99..7df8b46f9c 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -626,6 +626,17 @@ class TarGzArchive implements BackupArchive return false; } + /** + * @param string $p_path + * @param null $aEntries + * + * @return bool + */ + public function extractTo($p_path = '', $aEntries = null) + { + return $this->oArchive->extract($p_path); + } + /** * @param string $sDestinationDir * @param string $sArchiveFile diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 46c21427a6..32ac4a9f57 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -588,13 +588,7 @@ class SetupUtils throw new Exception("Attempting to delete directory: '$dir'"); } self::tidydir($dir); - if (@rmdir($dir) === false) - { - // Magic trick for windows - // sometimes the folder is empty but rmdir fails - closedir(opendir($dir)); - @rmdir($dir); - } + self::rmdir_safe($dir); } /** @@ -617,13 +611,7 @@ class SetupUtils if(is_dir($dir.'/'.$file)) { self::tidydir($dir.'/'.$file); - if (@rmdir($dir.'/'.$file) === false) - { - // Magic trick for windows - // sometimes the folder is empty but rmdir fails - closedir(opendir($dir.'/'.$file)); - @rmdir($dir.'/'.$file); - } + self::rmdir_safe($dir.'/'.$file); } else { @@ -657,6 +645,24 @@ class SetupUtils } } + public static function rmdir_safe($dir) + { + // avoid unnecessary warning + // Try 100 times... + $i = 100; + while ((@rmdir($dir) === false) && $i > 0) + { + // Magic trick for windows + // sometimes the folder is empty but rmdir fails + closedir(opendir($dir)); + $i--; + } + if ($i == 0) + { + rmdir($dir); + } + } + /** * Helper to copy a directory to a target directory, skipping .SVN files (for developer's comfort!) * Returns true if successfull @@ -768,14 +774,14 @@ class SetupUtils self::tidydir($sSource); if($bRemoveSource === true) { - rmdir($sSource); + self::rmdir_safe($sSource); } /** * We have tried the following implementation (based on a rename/mv) * But this does not work on some OSes. - * More info: https://bugs.php.net/bug.php?id=54097 - * + * More info: https://bugs.php.net/bug.php?id=54097 + * $aFiles = scandir($sSource); if(sizeof($aFiles) > 0) { diff --git a/setup/tar.php b/setup/tar.php index fb4305f59f..b075897153 100644 --- a/setup/tar.php +++ b/setup/tar.php @@ -1,21 +1,42 @@ -// +/** + * File::CSV + * + * PHP versions 4 and 5 + * + * Copyright (c) 1997-2008, + * Vincent Blavet + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category File_Formats + * @package Archive_Tar + * @author Vincent Blavet + * @author Combodo + * @copyright 1997-2018 The Authors + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Archive_Tar + */ define('ARCHIVE_TAR_ATT_SEPARATOR', 90001); define('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); @@ -1188,8 +1209,19 @@ class ArchiveTar return false; } - while (($v_buffer = fread($v_file, 512)) != '') { - $v_binary_data = pack("a512", "$v_buffer"); + $iLen = 1024*1024; + while (($v_buffer = fread($v_file, $iLen)) != '') { + $iBufferLen = strlen("$v_buffer"); + if ($iBufferLen != $iLen) + { + $iPack = ((int)($iBufferLen / 512) + 1) * 512; + $sPack = sprintf('a%d', $iPack); + } + else + { + $sPack = sprintf('a%d', $iLen); + } + $v_binary_data = pack($sPack, "$v_buffer"); $this->_writeBlock($v_binary_data); }