From 647b669eb90faca9e0de705bbca5179ff520de3a Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Mon, 14 Nov 2022 18:18:10 +0100 Subject: [PATCH 1/7] =?UTF-8?q?N=C2=B05619=20-=20Hide=20newsroom=20menu=20?= =?UTF-8?q?when=20no=20provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php | 6 ++++++ .../UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php b/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php index 1b11b869d..2f4e76227 100644 --- a/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php +++ b/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php @@ -49,6 +49,12 @@ class NewsroomMenuFactory return $oMenu; } + public static function HasProviders() + { + $aProviders = MetaModel::EnumPlugins('iNewsroomProvider'); + return count($aProviders) > 0; + } + /** * Prepare parameters for the newsroom JS widget * diff --git a/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php b/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php index 744541d6d..513ca903b 100644 --- a/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php +++ b/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php @@ -48,7 +48,7 @@ class NavigationMenuFactory { $oNewsroomMenu = null; - if (MetaModel::GetConfig()->Get('newsroom_enabled')) + if (MetaModel::GetConfig()->Get('newsroom_enabled') && NewsroomMenuFactory::HasProviders()) { $oNewsroomMenu = NewsroomMenuFactory::MakeNewsroomMenuForNavigationMenu(); } From d3f8e1c472afdc6ef10cf14367e100a80e1e8c3c Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Mon, 14 Nov 2022 18:28:18 +0100 Subject: [PATCH 2/7] =?UTF-8?q?Revert=20"N=C2=B05619=20-=20Hide=20newsroom?= =?UTF-8?q?=20menu=20when=20no=20provider"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 647b669eb90faca9e0de705bbca5179ff520de3a. --- .../PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php | 6 ------ .../UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php b/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php index 2f4e76227..1b11b869d 100644 --- a/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php +++ b/sources/application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php @@ -49,12 +49,6 @@ class NewsroomMenuFactory return $oMenu; } - public static function HasProviders() - { - $aProviders = MetaModel::EnumPlugins('iNewsroomProvider'); - return count($aProviders) > 0; - } - /** * Prepare parameters for the newsroom JS widget * diff --git a/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php b/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php index 513ca903b..744541d6d 100644 --- a/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php +++ b/sources/application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php @@ -48,7 +48,7 @@ class NavigationMenuFactory { $oNewsroomMenu = null; - if (MetaModel::GetConfig()->Get('newsroom_enabled') && NewsroomMenuFactory::HasProviders()) + if (MetaModel::GetConfig()->Get('newsroom_enabled')) { $oNewsroomMenu = NewsroomMenuFactory::MakeNewsroomMenuForNavigationMenu(); } From d03bd706e2ba6c6f180b7eb502bee0e5a6f6c627 Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Wed, 29 Mar 2023 16:53:38 +0200 Subject: [PATCH 3/7] Support of extra files (configurable) in the backup. --- .../2.x/itop-backup/dbrestore.class.inc.php | 29 +++++ setup/backup.class.inc.php | 20 ++++ test/setup/DBBackupDataTest.php | 105 ++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 test/setup/DBBackupDataTest.php diff --git a/datamodels/2.x/itop-backup/dbrestore.class.inc.php b/datamodels/2.x/itop-backup/dbrestore.class.inc.php index 55b811daf..259c72990 100644 --- a/datamodels/2.x/itop-backup/dbrestore.class.inc.php +++ b/datamodels/2.x/itop-backup/dbrestore.class.inc.php @@ -187,6 +187,12 @@ class DBRestore extends DBBackup @chmod($sConfigFile, 0770); // Allow overwriting the file rename($sDataDir.'/config-itop.php', $sConfigFile); @chmod($sConfigFile, 0440); // Read-only + + $aExtraFiles = $this->ListExtraFiles($sDataDir); + foreach($aExtraFiles as $sSourceFilePath => $sDestinationFilePath) { + SetupUtils::builddir(dirname($sDestinationFilePath)); + rename($sSourceFilePath, $sDestinationFilePath); + } try { SetupUtils::rrmdir($sDataDir); @@ -211,4 +217,27 @@ class DBRestore extends DBBackup $oRestoreMutex->Unlock(); } } + + /** + * List the 'extra files' found in the decompressed archive + * (i.e. files other than config-itop.php, delta.xml, itop-dump.sql or production-modules/* + * @param string $sDataDir + * @return string[] + */ + protected function ListExtraFiles(string $sDataDir) + { + $aExtraFiles = []; + $aStandardFiles = ['config-itop.php', 'itop-dump.sql', 'production-modules', 'delta.xml']; + $oDirectoryIterator = new RecursiveDirectoryIterator($sDataDir, FilesystemIterator::CURRENT_AS_FILEINFO|FilesystemIterator::SKIP_DOTS); + $oIterator = new RecursiveIteratorIterator($oDirectoryIterator); + foreach ($oIterator as $oFileInfo) + { + if (in_array($oFileInfo->getFilename(), $aStandardFiles)) continue; + if (strncmp($oFileInfo->getPathname(), $sDataDir.'/production-modules', strlen($sDataDir.'/production-modules')) == 0) continue; + + $aExtraFiles[$oFileInfo->getPathname()] = APPROOT.substr($oFileInfo->getPathname(), strlen($sDataDir)); + } + + return $aExtraFiles; + } } diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index 854c7594b..a8d6f6849 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -247,6 +247,26 @@ class DBBackup SetupUtils::copydir($sExtraDir, $sFile); $aRet[] = $sFile; } + $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); + foreach($aExtraFiles as $sExtraFileOrDir) + { + $sExtraFullPath = APPROOT.'/'.$sExtraFileOrDir; + if (is_dir($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding directory '$sExtraFileOrDir'"); + SetupUtils::copydir($sExtraFullPath, $sFile); + $aRet[] = $sFile; + } + elseif (file_exists($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding file '$sExtraFileOrDir'"); + @mkdir(dirname($sFile), 0755, true); + copy($sExtraFullPath, $sFile); + $aRet[] = $sFile; + } + } $sDataFile = $sTmpFolder.'/itop-dump.sql'; $this->DoBackup($sDataFile); $aRet[] = $sDataFile; diff --git a/test/setup/DBBackupDataTest.php b/test/setup/DBBackupDataTest.php new file mode 100644 index 000000000..aed8fe73c --- /dev/null +++ b/test/setup/DBBackupDataTest.php @@ -0,0 +1,105 @@ +SetModuleSetting('itop-backup', 'extra_files', array_keys($aExtraFiles)); + + foreach($aExtraFiles as $sExtraFile => $bExists) + { + if ($bExists) + { + @mkdir(dirname(APPROOT.'/'.$sExtraFile), 0755, true); + file_put_contents(APPROOT.'/'.$sExtraFile, 'Hello World!'); + } + } + + $aFiles = $this->InvokeNonPublicMethod('DBBackup', 'PrepareFilesToBackup', $oBackup, [APPROOT.'/conf/production/config-itop.php', $sTmpDir]); + SetupUtils::rrmdir($sTmpDir); + $aExpectedFiles = [ + $sTmpDir.'/config-itop.php', + $sTmpDir.'/itop-dump.sql', + ]; + foreach($aExtraFiles as $sRelFile => $bExists) + { + if ($bExists) + { + $aExpectedFiles[] = $sTmpDir.'/'.$sRelFile; + } + } + sort($aFiles); + sort($aExpectedFiles); + $this->assertEquals($aFiles, $aExpectedFiles); + + // Cleanup + foreach($aExtraFiles as $sExtraFile => $bExists) + { + if ($bExists) + { + unlink(APPROOT.'/'.$sExtraFile); + } + } + } + + /** + * @dataProvider prepareFilesToBackupProvider + */ + function testRestoreListExtraFiles($aFilesToCreate, $aExpectedRelativeExtraFiles) + { + require_once(APPROOT.'/env-production/itop-backup/dbrestore.class.inc.php'); + + $sTmpDir = sys_get_temp_dir().'/testRestoreListExtraFiles-'.time(); + + foreach($aFilesToCreate as $sRelativeName) + { + $sDir = $sTmpDir.'/'.dirname($sRelativeName); + if(!is_dir($sDir)) + { + mkdir($sDir, 0755, true); + } + file_put_contents($sTmpDir.'/'.$sRelativeName, 'Hello world.'); + } + $aExpectedExtraFiles = []; + foreach($aExpectedRelativeExtraFiles as $sRelativeName) + { + $aExpectedExtraFiles[$sTmpDir.'/'.$sRelativeName] = APPROOT.'/'.$sRelativeName; + } + + $oRestore = new DBRestore(MetaModel::GetConfig()); + $aExtraFiles = $this->InvokeNonPublicMethod('DBRestore', 'ListExtraFiles', $oRestore, [$sTmpDir]); + + asort($aExtraFiles); + asort($aExpectedExtraFiles); + $this->assertEquals($aExpectedExtraFiles, $aExtraFiles); + SetupUtils::rrmdir($sTmpDir); + } + + function prepareFilesToBackupProvider() + { + return [ + 'no extra file' => ['aFilesToCreate' => ['config-itop.php', 'itop-dump.sql', 'delta.xml'], 'aExpectedExtraFiles' => []], + 'no extra file (2)' => ['aFilesToCreate' => ['config-itop.php', 'itop-dump.sql', 'delta.xml', 'production-modules/test/module.test.php'], 'aExpectedExtraFiles' => []], + 'one extra file' => ['aFilesToCreate' => ['config-itop.php', 'itop-dump.sql', 'delta.xml', 'production-modules/test/module.test.php', 'collectors/ldap/conf/params.local.xml'], 'aExpectedExtraFiles' => ['collectors/ldap/conf/params.local.xml']], + ]; + } + +} From 034ca26d01e0edeb0ef81a37d3638a396da1f63d Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Mon, 3 Apr 2023 11:54:01 +0200 Subject: [PATCH 4/7] Do NOT backup unsafe files. --- setup/backup.class.inc.php | 18 +++++++++++++----- test/setup/DBBackupDataTest.php | 23 ++++++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index a8d6f6849..92bc7b2cc 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -205,11 +205,12 @@ class DBBackup * * @param string $sSourceConfigFile * @param string $sTmpFolder + * @param bool $bSkipSQLDumpForTesting * * @return array list of files to archive * @throws \Exception */ - protected function PrepareFilesToBackup($sSourceConfigFile, $sTmpFolder) + protected function PrepareFilesToBackup($sSourceConfigFile, $sTmpFolder, $bSkipSQLDumpForTesting = false) { $aRet = array(); if (is_dir($sTmpFolder)) @@ -250,7 +251,11 @@ class DBBackup $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); foreach($aExtraFiles as $sExtraFileOrDir) { - $sExtraFullPath = APPROOT.'/'.$sExtraFileOrDir; + $sExtraFullPath = realpath(APPROOT.'/'.$sExtraFileOrDir); + if (strncmp(APPROOT, $sExtraFullPath, strlen(APPROOT)) !== 0) + { + throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); + } if (is_dir($sExtraFullPath)) { $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; @@ -267,9 +272,12 @@ class DBBackup $aRet[] = $sFile; } } - $sDataFile = $sTmpFolder.'/itop-dump.sql'; - $this->DoBackup($sDataFile); - $aRet[] = $sDataFile; + if (!$bSkipSQLDumpForTesting) + { + $sDataFile = $sTmpFolder.'/itop-dump.sql'; + $this->DoBackup($sDataFile); + $aRet[] = $sDataFile; + } return $aRet; } diff --git a/test/setup/DBBackupDataTest.php b/test/setup/DBBackupDataTest.php index aed8fe73c..af9595445 100644 --- a/test/setup/DBBackupDataTest.php +++ b/test/setup/DBBackupDataTest.php @@ -18,7 +18,7 @@ class DBBackupDataTest extends ItopDataTestCase /** * @dataProvider prepareFilesToBackupProvider */ - public function testPrepareFilesToBackup($aExtraFiles) + public function testPrepareFilesToBackup(array $aExtraFiles, bool $bUnsafeFileException) { $sTmpDir = sys_get_temp_dir().'/testPrepareFilesToBackup-'.time(); $oBackup = new DBBackup(MetaModel::GetConfig()); @@ -33,11 +33,14 @@ class DBBackupDataTest extends ItopDataTestCase } } - $aFiles = $this->InvokeNonPublicMethod('DBBackup', 'PrepareFilesToBackup', $oBackup, [APPROOT.'/conf/production/config-itop.php', $sTmpDir]); + if ($bUnsafeFileException) + { + $this->expectExceptionMessage("Backup: Aborting, resource '$sExtraFile'. Considered as UNSAFE because not inside the iTop directory."); + } + $aFiles = $this->InvokeNonPublicMethod('DBBackup', 'PrepareFilesToBackup', $oBackup, [APPROOT.'/conf/production/config-itop.php', $sTmpDir, true]); SetupUtils::rrmdir($sTmpDir); $aExpectedFiles = [ $sTmpDir.'/config-itop.php', - $sTmpDir.'/itop-dump.sql', ]; foreach($aExtraFiles as $sRelFile => $bExists) { @@ -59,9 +62,19 @@ class DBBackupDataTest extends ItopDataTestCase } } } + + function prepareFilesToBackupProvider() + { + return [ + 'no_extra_file' => ['aExtraFiles' => [], false], + 'one_extra_file' => ['aExtraFiles' => ['foo.txt' => true], false], + 'three_extra_file_and_dir' => ['aExtraFiles' => ['foo.txt' => true, 'gabu/zomeu.xml' => true, 'meuh.html' => true], false], + 'one_unsafe_file' => ['aExtraFiles' => ['../foo.txt' => true], true], + ]; + } /** - * @dataProvider prepareFilesToBackupProvider + * @dataProvider restoreListExtraFilesProvider */ function testRestoreListExtraFiles($aFilesToCreate, $aExpectedRelativeExtraFiles) { @@ -93,7 +106,7 @@ class DBBackupDataTest extends ItopDataTestCase SetupUtils::rrmdir($sTmpDir); } - function prepareFilesToBackupProvider() + function restoreListExtraFilesProvider() { return [ 'no extra file' => ['aFilesToCreate' => ['config-itop.php', 'itop-dump.sql', 'delta.xml'], 'aExpectedExtraFiles' => []], From 955aefc05bead6334bc601043cba04608047af53 Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Tue, 4 Apr 2023 14:26:31 +0200 Subject: [PATCH 5/7] Ignore non-existing files. --- setup/backup.class.inc.php | 2 ++ test/setup/DBBackupDataTest.php | 1 + 2 files changed, 3 insertions(+) diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index 92bc7b2cc..1ec7c7ada 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -251,6 +251,8 @@ class DBBackup $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); foreach($aExtraFiles as $sExtraFileOrDir) { + if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) continue; // Ignore non-existing files + $sExtraFullPath = realpath(APPROOT.'/'.$sExtraFileOrDir); if (strncmp(APPROOT, $sExtraFullPath, strlen(APPROOT)) !== 0) { diff --git a/test/setup/DBBackupDataTest.php b/test/setup/DBBackupDataTest.php index af9595445..02ec0734a 100644 --- a/test/setup/DBBackupDataTest.php +++ b/test/setup/DBBackupDataTest.php @@ -69,6 +69,7 @@ class DBBackupDataTest extends ItopDataTestCase 'no_extra_file' => ['aExtraFiles' => [], false], 'one_extra_file' => ['aExtraFiles' => ['foo.txt' => true], false], 'three_extra_file_and_dir' => ['aExtraFiles' => ['foo.txt' => true, 'gabu/zomeu.xml' => true, 'meuh.html' => true], false], + 'two_extra_file_but_only_one_exists' => ['aExtraFiles' => ['foo.txt' => true, 'meuh.html' => false], false], 'one_unsafe_file' => ['aExtraFiles' => ['../foo.txt' => true], true], ]; } From 001194835fd6524193b5b7f7c88424f4a0a1d5bb Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Thu, 6 Apr 2023 10:50:47 +0200 Subject: [PATCH 6/7] Config file may not exist during unattended setup/backup --- setup/backup.class.inc.php | 49 ++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index 1ec7c7ada..bbf0adfab 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -227,7 +227,7 @@ class DBBackup { $sFile = $sTmpFolder.'/config-itop.php'; $this->LogInfo("backup: adding resource '$sSourceConfigFile'"); - copy($sSourceConfigFile, $sFile); + @copy($sSourceConfigFile, $sFile); // During unattended install config file may be absent $aRet[] = $sFile; } @@ -248,30 +248,33 @@ class DBBackup SetupUtils::copydir($sExtraDir, $sFile); $aRet[] = $sFile; } - $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); - foreach($aExtraFiles as $sExtraFileOrDir) + if (MetaModel::GetConfig() !== null) // During unattended install config file may be absent { - if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) continue; // Ignore non-existing files - - $sExtraFullPath = realpath(APPROOT.'/'.$sExtraFileOrDir); - if (strncmp(APPROOT, $sExtraFullPath, strlen(APPROOT)) !== 0) + $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); + foreach($aExtraFiles as $sExtraFileOrDir) { - throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); - } - if (is_dir($sExtraFullPath)) - { - $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; - $this->LogInfo("backup: adding directory '$sExtraFileOrDir'"); - SetupUtils::copydir($sExtraFullPath, $sFile); - $aRet[] = $sFile; - } - elseif (file_exists($sExtraFullPath)) - { - $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; - $this->LogInfo("backup: adding file '$sExtraFileOrDir'"); - @mkdir(dirname($sFile), 0755, true); - copy($sExtraFullPath, $sFile); - $aRet[] = $sFile; + if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) continue; // Ignore non-existing files + + $sExtraFullPath = realpath(APPROOT.'/'.$sExtraFileOrDir); + if (strncmp(APPROOT, $sExtraFullPath, strlen(APPROOT)) !== 0) + { + throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); + } + if (is_dir($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding directory '$sExtraFileOrDir'"); + SetupUtils::copydir($sExtraFullPath, $sFile); + $aRet[] = $sFile; + } + elseif (file_exists($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding file '$sExtraFileOrDir'"); + @mkdir(dirname($sFile), 0755, true); + copy($sExtraFullPath, $sFile); + $aRet[] = $sFile; + } } } if (!$bSkipSQLDumpForTesting) From 08ebac1b5c2683012e09244f98f5c19a25700415 Mon Sep 17 00:00:00 2001 From: "denis.flaven@combodo.com" Date: Wed, 10 May 2023 17:42:50 +0200 Subject: [PATCH 7/7] Fix PR remarks --- datamodels/2.x/itop-backup/dbrestore.class.inc.php | 8 ++++++-- setup/backup.class.inc.php | 8 +++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/datamodels/2.x/itop-backup/dbrestore.class.inc.php b/datamodels/2.x/itop-backup/dbrestore.class.inc.php index 259c72990..fdb92aca1 100644 --- a/datamodels/2.x/itop-backup/dbrestore.class.inc.php +++ b/datamodels/2.x/itop-backup/dbrestore.class.inc.php @@ -232,8 +232,12 @@ class DBRestore extends DBBackup $oIterator = new RecursiveIteratorIterator($oDirectoryIterator); foreach ($oIterator as $oFileInfo) { - if (in_array($oFileInfo->getFilename(), $aStandardFiles)) continue; - if (strncmp($oFileInfo->getPathname(), $sDataDir.'/production-modules', strlen($sDataDir.'/production-modules')) == 0) continue; + if (in_array($oFileInfo->getFilename(), $aStandardFiles)) { + continue; + } + if (strncmp($oFileInfo->getPathname(), $sDataDir.'/production-modules', strlen($sDataDir.'/production-modules')) == 0) { + continue; + } $aExtraFiles[$oFileInfo->getPathname()] = APPROOT.substr($oFileInfo->getPathname(), strlen($sDataDir)); } diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index bbf0adfab..86c0045bb 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -253,10 +253,12 @@ class DBBackup $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); foreach($aExtraFiles as $sExtraFileOrDir) { - if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) continue; // Ignore non-existing files + if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) { + continue; // Ignore non-existing files + } - $sExtraFullPath = realpath(APPROOT.'/'.$sExtraFileOrDir); - if (strncmp(APPROOT, $sExtraFullPath, strlen(APPROOT)) !== 0) + $sExtraFullPath = utils::RealPath(APPROOT.'/'.$sExtraFileOrDir, APPROOT); + if ($sExtraFullPath === false) { throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); }