From 960133c0dff86d9dbeb062116a75dfc6817e1bd3 Mon Sep 17 00:00:00 2001 From: jf-cbd Date: Tue, 13 May 2025 16:05:39 +0200 Subject: [PATCH 1/4] =?UTF-8?q?N=C2=B08379=20-=20fix=20backup=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2.x/itop-backup/dbrestore.class.inc.php | 9 +------ datamodels/2.x/itop-backup/status.php | 10 +------ setup/backup.class.inc.php | 26 +++++++++++-------- setup/setuputils.class.inc.php | 17 ++++++------ 4 files changed, 25 insertions(+), 37 deletions(-) diff --git a/datamodels/2.x/itop-backup/dbrestore.class.inc.php b/datamodels/2.x/itop-backup/dbrestore.class.inc.php index d274047fa..34944710b 100644 --- a/datamodels/2.x/itop-backup/dbrestore.class.inc.php +++ b/datamodels/2.x/itop-backup/dbrestore.class.inc.php @@ -53,14 +53,7 @@ class DBRestore extends DBBackup $sUser = self::EscapeShellArg($this->sDBUser); $sPwd = self::EscapeShellArg($this->sDBPwd); $sDBName = self::EscapeShellArg($this->sDBName); - if (empty($this->sMySQLBinDir)) - { - $sMySQLExe = 'mysql'; - } - else - { - $sMySQLExe = '"'.$this->sMySQLBinDir.'/mysql"'; - } + $sMySQLExe = DBBackup::MakeSafeMySQLCommand($this->sMySQLBinDir, 'mysql'); if (is_null($this->iDBPort)) { $sPortOption = ''; diff --git a/datamodels/2.x/itop-backup/status.php b/datamodels/2.x/itop-backup/status.php index feeeb9b1b..6f11a2d52 100644 --- a/datamodels/2.x/itop-backup/status.php +++ b/datamodels/2.x/itop-backup/status.php @@ -56,15 +56,7 @@ try // $sMySQLBinDir = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''); $sMySQLBinDir = utils::ReadParam('mysql_bindir', $sMySQLBinDir, true); - if (empty($sMySQLBinDir)) - { - $sMySQLDump = 'mysqldump'; - } - else - { - //echo 'Info - Found mysql_bindir: '.$sMySQLBinDir; - $sMySQLDump = '"'.$sMySQLBinDir.'/mysqldump"'; - } + $sMySQLDump = DBBackup::MakeSafeMySQLCommand($sMySQLBinDir, 'mysqldump'); $sCommand = "$sMySQLDump -V 2>&1"; $aOutput = array(); diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index d03650edc..295b8dff1 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -104,6 +104,8 @@ class DBBackup /** @var string */ protected $sDBName; /** @var string */ + protected $sMySQLBinDir = ''; + /** @var string */ protected $sDBSubName; /** @@ -131,7 +133,6 @@ class DBBackup $this->sDBSubName = $oConfig->get('db_subname'); } - protected $sMySQLBinDir = ''; /** * Create a normalized backup name, depending on the current date/time and Database @@ -299,8 +300,9 @@ class DBBackup } $this->LogInfo("Starting backup of $this->sDBHost/$this->sDBName(suffix:'$this->sDBSubName')"); + $sMySQLBinDir = utils::ReadParam('mysql_bindir', $this->sMySQLBinDir, true); - $sMySQLDump = $this->GetMysqldumpCommand(); + $sMySQLDump = $this->MakeSafeMySQLCommand($sMySQLBinDir, 'mysqldump'); // Store the results in a temporary file $sTmpFileName = self::EscapeShellArg($sBackupFileName); @@ -557,20 +559,22 @@ EOF; /** * @return string the command to launch mysqldump (without its params) + * @throws \BackupException */ - private function GetMysqldumpCommand() + public static function MakeSafeMySQLCommand($sMySQLBinDir, string $sCmd) { - $sMySQLBinDir = utils::ReadParam('mysql_bindir', $this->sMySQLBinDir, true); - if (empty($sMySQLBinDir)) - { - $sMysqldumpCommand = 'mysqldump'; + if (empty($sMySQLBinDir)) { + $sMySQLCommand = $sCmd; } - else - { - $sMysqldumpCommand = '"'.$sMySQLBinDir.'/mysqldump"'; + else { + $sMySQLBinDir = escapeshellcmd($sMySQLBinDir); + $sMySQLCommand = '"'.$sMySQLBinDir.'/$sCmd"'; + if (!file_exists($sMySQLCommand)) { + throw new BackupException("$sCmd not found in $sMySQLBinDir"); + } } - return $sMysqldumpCommand; + return $sMySQLCommand; } } diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 93fcece77..9386085a7 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -484,16 +484,15 @@ class SetupUtils { $sMySQLBinDir = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''); } - - if (empty($sMySQLBinDir)) - { - $sMySQLDump = 'mysqldump'; - } - else - { - SetupPage::log('Info - Found mysql_bindir: '.$sMySQLBinDir); - $sMySQLDump = '"'.$sMySQLBinDir.'/mysqldump"'; + try { + $sMySQLDump = DBBackup::MakeSafeMySQLCommand($sMySQLBinDir, 'mysqldump'); + } catch (Exception $e) { + $aResult[] = new CheckResult(CheckResult::ERROR, $e->getMessage()); + return $aResult; } + if (!empty($sMySQLBinDir)) { + SetupPage::log('Info - Found mysql_bindir: '.$sMySQLBinDir); + } $sCommand = "$sMySQLDump -V 2>&1"; $aOutput = array(); From e77e0eec9fc085469c3865d9aea834f3ae44d95c Mon Sep 17 00:00:00 2001 From: bdalsass Date: Mon, 12 May 2025 16:16:34 +0200 Subject: [PATCH 2/4] =?UTF-8?q?N=C2=B08355=20-=20render=5Fdashboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/dashboard.class.inc.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 0c311225d..4af25fe71 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -529,10 +529,7 @@ EOF */ public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true) { - if (!array_key_exists('dashboard_div_id', $aExtraParams)) - { - $aExtraParams['dashboard_div_id'] = utils::Sanitize($this->GetId(), '', 'element_identifier'); - } + $aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER); $oPage->add('
'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'
'); @@ -1059,7 +1056,7 @@ EOF $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js'); $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js'); $sEditMenu = "
    • "; - + $aActions = array(); $sFile = addslashes($this->sDefinitionFile); $sJSExtraParams = json_encode($aExtraParams); @@ -1188,7 +1185,7 @@ EOF $oPage->add('
'); $oPage->add('
'); // For exchanging messages between the panes, same as in the designer $oPage->add('
'); - + $sDialogTitle = Dict::S('UI:DashboardEdit:Title'); $sOkButtonLabel = Dict::S('UI:Button:Save'); $sCancelButtonLabel = Dict::S('UI:Button:Cancel'); From 81791dd25384c5594910d7e1cab9b212104d61f3 Mon Sep 17 00:00:00 2001 From: bdalsass Date: Tue, 13 May 2025 10:57:19 +0200 Subject: [PATCH 3/4] =?UTF-8?q?N=C2=B08313=20-=20edit=20dashboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/dashboard.class.inc.php | 5 +++-- application/utils.inc.php | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 4af25fe71..3dc75ddf0 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -999,7 +999,7 @@ EOF $sSelectorHtml .= ''; $sSelectorHtml = addslashes($sSelectorHtml); $sFile = addslashes($this->GetDefinitionFile()); - $sReloadURL = $this->GetReloadURL(); + $sReloadURL = json_encode($this->GetReloadURL()); $oPage->add_ready_script( <<GetReloadURL()); $oPage->add_script( <<sTitle); $sFile = json_encode($this->GetDefinitionFile()); $sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php'; - $sReloadURL = $this->GetReloadURL(); + $sReloadURL = json_encode($this->GetReloadURL()); $sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage')); $sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage')); diff --git a/application/utils.inc.php b/application/utils.inc.php index 642d83d5c..9673b39bb 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -432,8 +432,8 @@ class utils // For URL case static::ENUM_SANITIZATION_FILTER_URL: - // N°6350 - returns only valid URLs - $retValue = filter_var($value, FILTER_VALIDATE_URL); + $retValue = filter_var($value, FILTER_SANITIZE_URL); + $retValue = filter_var($retValue, FILTER_VALIDATE_URL); break; default: From 38683c20b16ebb545aaf08af1efd9ea91a75ed5e Mon Sep 17 00:00:00 2001 From: bdalsass Date: Tue, 13 May 2025 16:19:26 +0200 Subject: [PATCH 4/4] =?UTF-8?q?N=C2=B08313=20-=20edit=20dashboard=20(fix?= =?UTF-8?q?=20broken=20test)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/php-unit-tests/unitary-tests/application/utilsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php-unit-tests/unitary-tests/application/utilsTest.php b/tests/php-unit-tests/unitary-tests/application/utilsTest.php index 6622de767..b5bcf8567 100644 --- a/tests/php-unit-tests/unitary-tests/application/utilsTest.php +++ b/tests/php-unit-tests/unitary-tests/application/utilsTest.php @@ -495,7 +495,7 @@ class utilsTest extends ItopTestCase 'good element_identifier' => ['element_identifier', 'AD05nb', 'AD05nb'], 'bad element_identifier' => ['element_identifier', 'AD05nb+', 'AD05nb'], 'good url' => ['url', 'https://www.w3schools.com', 'https://www.w3schools.com'], - 'bad url' => ['url', 'https://www.w3schoo��ls.co�m', null], + 'bad url' => ['url', 'https//www.w3schools.com', null], 'raw_data' => ['raw_data', '\s😃😃😃', '\s😃😃😃'], ]; }