mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-22 00:32:16 +02:00
N°2847 - Add Title component
* Add id to button factory * Rework of Configuration File Editor page
This commit is contained in:
@@ -24,6 +24,10 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\Alert\AlertFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Component\Title\TitleFactory;
|
||||
use Combodo\iTop\Config\Validator\iTopConfigAstValidator;
|
||||
use Combodo\iTop\Config\Validator\iTopConfigSyntaxValidator;
|
||||
|
||||
@@ -59,8 +63,7 @@ function DBPasswordInNewConfigIsOk($sSafeContent)
|
||||
{
|
||||
$bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER));
|
||||
|
||||
if ($bIsWindows && (preg_match("@'db_pwd' => '[^%!\"]+',@U", $sSafeContent) === 0))
|
||||
{
|
||||
if ($bIsWindows && (preg_match("@'db_pwd' => '[^%!\"]+',@U", $sSafeContent) === 0)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -82,112 +85,108 @@ $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/mode-php.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/theme-eclipse.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/ext-searchbox.js');
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
$iEditorTopMargin = 0;
|
||||
$iEditorTopMargin = 2;
|
||||
|
||||
$oP->add("<h1>".Dict::S('config-edit-title')."</h1>");
|
||||
$oP->AddUiBlock(TitleFactory::MakeForPage(Dict::S('config-edit-title')));
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">Sorry, iTop is in <b>demonstration mode</b>: the configuration file cannot be edited.</div>");
|
||||
}
|
||||
else if (MetaModel::GetModuleSetting('itop-config', 'config_editor', '') == 'disabled')
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">iTop interactive edition of the configuration as been disabled. See <tt>'config_editor' => 'disabled'</tt> in the configuration file.</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php';
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
$oAlert = AlertFactory::MakeForInformation('', "Sorry, iTop is in <b>demonstration mode</b>: the configuration file cannot be edited.");
|
||||
$oP->AddUiBlock($oAlert);
|
||||
} else {
|
||||
if (MetaModel::GetModuleSetting('itop-config', 'config_editor', '') == 'disabled') {
|
||||
$oAlert = AlertFactory::MakeForWarning('', "iTop interactive edition of the configuration as been disabled. See <tt>'config_editor' => 'disabled'</tt> in the configuration file.");
|
||||
$oP->AddUiBlock($oAlert);
|
||||
} else {
|
||||
$sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php';
|
||||
|
||||
$iEditorTopMargin += 9;
|
||||
$sConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
$sOriginalConfig = $sConfig;
|
||||
$iEditorTopMargin += 9;
|
||||
$sConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
$sOriginalConfig = $sConfig;
|
||||
|
||||
if (!empty($sOperation))
|
||||
{
|
||||
$iEditorTopMargin += 5;
|
||||
$sConfig = utils::ReadParam('new_config', '', false, 'raw_data');
|
||||
$sOriginalConfig = utils::ReadParam('prev_config', '', false, 'raw_data');
|
||||
}
|
||||
if (!empty($sOperation)) {
|
||||
$iEditorTopMargin += 5;
|
||||
$sConfig = utils::ReadParam('new_config', '', false, 'raw_data');
|
||||
$sOriginalConfig = utils::ReadParam('prev_config', '', false, 'raw_data');
|
||||
}
|
||||
|
||||
if ($sOperation == 'revert')
|
||||
{
|
||||
$oP->add('<div id="save_result" class="header_message message_info">'.Dict::S('config-reverted').'</div>');
|
||||
}
|
||||
if ($sOperation == 'save')
|
||||
{
|
||||
$sTransactionId = utils::ReadParam('transaction_id', '', false, 'transaction_id');
|
||||
if (!utils::IsTransactionValid($sTransactionId, true))
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">Error: invalid Transaction ID. The configuration was <b>NOT</b> modified.</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($sConfig == $sOriginalConfig)
|
||||
{
|
||||
$oP->add('<div id="save_result" class="header_message">'.Dict::S('config-no-change').'</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
TestConfig($sConfig, $oP); // throws exceptions
|
||||
if ($sOperation == 'revert') {
|
||||
$oAlert = AlertFactory::MakeForWarning('', Dict::S('config-reverted'));
|
||||
$oP->AddUiBlock($oAlert);
|
||||
}
|
||||
if ($sOperation == 'save') {
|
||||
$sTransactionId = utils::ReadParam('transaction_id', '', false, 'transaction_id');
|
||||
if (!utils::IsTransactionValid($sTransactionId, true)) {
|
||||
$oAlert = AlertFactory::MakeForFailure('', 'Error: invalid Transaction ID. The configuration was <b>NOT</b> modified.');
|
||||
$oP->AddUiBlock($oAlert);
|
||||
} else {
|
||||
if ($sConfig == $sOriginalConfig) {
|
||||
$oAlert = AlertFactory::MakeForInformation('', Dict::S('config-no-change'));
|
||||
$oP->AddUiBlock($oAlert);
|
||||
} else {
|
||||
try {
|
||||
TestConfig($sConfig, $oP); // throws exceptions
|
||||
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
$sTmpFile = tempnam(SetupUtils::GetTmpDir(), 'itop-cfg-');
|
||||
// Don't write the file as-is since it would allow to inject any kind of PHP code.
|
||||
// Instead write the interpreted version of the file
|
||||
// Note:
|
||||
// The actual raw PHP code will anyhow be interpreted exactly twice: once in TestConfig() above
|
||||
// and a second time during the load of the Config object below.
|
||||
// If you are really concerned about an iTop administrator crafting some malicious
|
||||
// PHP code inside the config file, then turn off the interactive configuration
|
||||
// editor by adding the configuration parameter:
|
||||
// 'itop-config' => array(
|
||||
// 'config_editor' => 'disabled',
|
||||
// )
|
||||
file_put_contents($sTmpFile, $sConfig);
|
||||
$oTempConfig = new Config($sTmpFile, true);
|
||||
$oTempConfig->WriteToFile($sConfigFile);
|
||||
@unlink($sTmpFile);
|
||||
@chmod($sConfigFile, 0440); // Read-only
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
$sTmpFile = tempnam(SetupUtils::GetTmpDir(), 'itop-cfg-');
|
||||
// Don't write the file as-is since it would allow to inject any kind of PHP code.
|
||||
// Instead write the interpreted version of the file
|
||||
// Note:
|
||||
// The actual raw PHP code will anyhow be interpreted exactly twice: once in TestConfig() above
|
||||
// and a second time during the load of the Config object below.
|
||||
// If you are really concerned about an iTop administrator crafting some malicious
|
||||
// PHP code inside the config file, then turn off the interactive configuration
|
||||
// editor by adding the configuration parameter:
|
||||
// 'itop-config' => array(
|
||||
// 'config_editor' => 'disabled',
|
||||
// )
|
||||
file_put_contents($sTmpFile, $sConfig);
|
||||
$oTempConfig = new Config($sTmpFile, true);
|
||||
$oTempConfig->WriteToFile($sConfigFile);
|
||||
@unlink($sTmpFile);
|
||||
@chmod($sConfigFile, 0440); // Read-only
|
||||
|
||||
if (DBPasswordInNewConfigIsOk($sConfig))
|
||||
{
|
||||
$oP->p('<div id="save_result" class="header_message message_ok">'.Dict::S('config-saved').'</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p('<div id="save_result" class="header_message message_info">'.Dict::S('config-saved-warning-db-password').'</div>');
|
||||
}
|
||||
$sOriginalConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oP->p('<div id="save_result" class="header_message message_error">'.$e->getMessage().'</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DBPasswordInNewConfigIsOk($sConfig)) {
|
||||
$oAlert = AlertFactory::MakeForSuccess('', Dict::S('config-saved'));
|
||||
} else {
|
||||
$oAlert = AlertFactory::MakeForInformation('', Dict::S('config-saved-warning-db-password'));
|
||||
}
|
||||
$oP->AddUiBlock($oAlert);
|
||||
$sOriginalConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
} catch (Exception $e) {
|
||||
$oAlert = AlertFactory::MakeForDanger('', $e->getMessage());
|
||||
$oP->AddUiBlock($oAlert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sConfigEscaped = htmlentities($sConfig, ENT_QUOTES, 'UTF-8');
|
||||
$sOriginalConfigEscaped = htmlentities($sOriginalConfig, ENT_QUOTES, 'UTF-8');
|
||||
$oP->p(Dict::S('config-edit-intro'));
|
||||
$oP->add("<form method=\"POST\">");
|
||||
$oP->add("<input id=\"operation\" type=\"hidden\" name=\"operation\" value=\"save\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">");
|
||||
$oP->add("<input id=\"submit_button\" type=\"submit\" value=\"".Dict::S('config-apply')."\" title=\"".Dict::S('config-apply-title')."\"><button id=\"cancel_button\" disabled=\"disabled\" onclick=\"return ResetConfig();\">".Dict::S('config-cancel')."</button>");
|
||||
$oP->add("<input type=\"hidden\" id=\"prev_config\" name=\"prev_config\" value=\"$sOriginalConfigEscaped\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"new_config\" value=\"$sConfigEscaped\">");
|
||||
$oP->add("<div id =\"new_config\" style=\"position: absolute; top: ".$iEditorTopMargin."em; bottom: 0; left: 5px; right: 5px;\"></div>");
|
||||
$oP->add("</form>");
|
||||
|
||||
$sConfirmCancel = addslashes(Dict::S('config-confirm-cancel'));
|
||||
$oP->add_script(
|
||||
<<<'JS'
|
||||
$sConfigEscaped = htmlentities($sConfig, ENT_QUOTES, 'UTF-8');
|
||||
$sOriginalConfigEscaped = htmlentities($sOriginalConfig, ENT_QUOTES, 'UTF-8');
|
||||
$oP->AddUiBlock(new Html('<p>'.Dict::S('config-edit-intro').'</p>'));
|
||||
|
||||
$oP->add("<form method=\"POST\">");
|
||||
$oP->add("<input id=\"operation\" type=\"hidden\" name=\"operation\" value=\"save\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">");
|
||||
|
||||
// - Cancel button
|
||||
$oCancelButton = ButtonFactory::MakeForSecondaryAction(Dict::S('config-cancel'), 'cancel_button', null, true, 'cancel_button');
|
||||
$oCancelButton->SetOnClickJsCode("return ResetConfig();");
|
||||
$oP->AddUiBlock($oCancelButton);
|
||||
|
||||
// - Submit button
|
||||
$oSubmitButton = ButtonFactory::MakeForValidationAction(Dict::S('config-apply'), null, Dict::S('config-apply'), true, 'submit_button');
|
||||
$oP->AddUiBlock($oSubmitButton);
|
||||
|
||||
$oP->add("<input type=\"hidden\" id=\"prev_config\" name=\"prev_config\" value=\"$sOriginalConfigEscaped\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"new_config\" value=\"$sConfigEscaped\">");
|
||||
$oP->add("<div id =\"new_config\" style=\"position: absolute; top: ".$iEditorTopMargin."em; bottom: 0; left: 5px; right: 5px;\"></div>");
|
||||
$oP->add("</form>");
|
||||
|
||||
$oP->add_script(
|
||||
<<<'JS'
|
||||
var EditorUtils = (function() {
|
||||
var STORAGE_RANGE_KEY = 'cfgEditorRange';
|
||||
var STORAGE_LINE_KEY = 'cfgEditorFirstline';
|
||||
@@ -301,30 +300,30 @@ $editorForm.submit(function() {
|
||||
EditorUtils.restoreEditorDisplay(editor);
|
||||
editor.focus();
|
||||
JS
|
||||
);
|
||||
);
|
||||
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
$sConfirmCancel = addslashes(Dict::S('config-confirm-cancel'));
|
||||
$oP->add_script(<<<JS
|
||||
function ResetConfig()
|
||||
{
|
||||
var editor = ace.edit("new_config");
|
||||
$("#operation").attr('value', 'revert');
|
||||
if (editor.getValue() != $('#prev_config').val())
|
||||
var prevConfig = $('#prev_config');
|
||||
if (editor.getValue() != prevConfig.val())
|
||||
{
|
||||
if (confirm('$sConfirmCancel'))
|
||||
{
|
||||
$('input[name="new_config"]').val($('#prev_config').val());
|
||||
$('input[name="new_config"]').val(prevConfig.val());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
JS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user