mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 10:38:45 +02:00
New functionality: a rudimentary configuration editor (admins only)
SVN:trunk[3401]
This commit is contained in:
217
datamodels/2.x/itop-config/config.php
Normal file
217
datamodels/2.x/itop-config/config.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
// Copyright (C) 2013 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Monitor the backup
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
require_once('../../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
|
||||
|
||||
function TestConfig($sContents, $oP)
|
||||
{
|
||||
try
|
||||
{
|
||||
ini_set('display_errors', 1);
|
||||
ob_start();
|
||||
eval('?'.'>'.trim($sContents));
|
||||
$sNoise = trim(ob_get_contents());
|
||||
ob_end_clean();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// well, never reach in case of parsing error :-(
|
||||
throw new Exception('Error in configuration: '.$e->getMessage());
|
||||
}
|
||||
if (strlen($sNoise) > 0)
|
||||
{
|
||||
if (preg_match("/(Error|Parse error|Notice|Warning): (.+) in \S+ : eval\(\)'d code on line (\d+)/i", strip_tags($sNoise), $aMatches))
|
||||
{
|
||||
$sMessage = $aMatches[2];
|
||||
$sLine = $aMatches[3];
|
||||
$iLine = (int) $sLine;
|
||||
|
||||
// Highlight the line
|
||||
$aLines = explode("\n", $sContents);
|
||||
$iStart = 0;
|
||||
for ($i = 0 ; $i < $iLine - 1; $i++) $iStart += strlen($aLines[$i]);
|
||||
$iEnd = $iStart + strlen($aLines[$iLine - 1]);
|
||||
$iTotalLines = count($aLines);
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
setCursorPos($('#new_config')[0], $iStart, $iEnd);
|
||||
$('#new_config')[0].focus();
|
||||
var iScroll = Math.floor($('#new_config')[0].scrollHeight * ($iLine - 20) / $iTotalLines);
|
||||
$('#new_config').scrollTop(iScroll);
|
||||
EOF
|
||||
);
|
||||
|
||||
$sMessage = Dict::Format('config-parse-error', $sMessage, $sLine);
|
||||
throw new Exception($sMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
|
||||
throw new Exception('Syntax error in configuration file: <tt>'.$sNoise.'</tt>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
//
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
//$sOperation = utils::ReadParam('operation', 'menu');
|
||||
//$oAppContext = new ApplicationContext();
|
||||
|
||||
$oP = new iTopWebPage(Dict::S('config-edit-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
$oP->add("<h1>".Dict::S('config-edit-title')."</h1>");
|
||||
|
||||
$oP->add_style(
|
||||
<<<EOF
|
||||
textarea {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
}
|
||||
.current_line {
|
||||
display: none;
|
||||
margin-left: 20px;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
$sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php';
|
||||
|
||||
if ($sOperation == 'save')
|
||||
{
|
||||
$sConfig = utils::ReadParam('new_config', '', false, 'raw_data');
|
||||
$sOrginalConfig = utils::ReadParam('prev_config', '', false, 'raw_data');
|
||||
if ($sConfig == $sOrginalConfig)
|
||||
{
|
||||
$oP->add('<div id="save_result" class="header_message">'.Dict::S('config-no-change').'</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
TestConfig($sConfig, $oP); // throws exceptions
|
||||
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
file_put_contents($sConfigFile, $sConfig);
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
$oP->p('<div id="save_result" class="header_message message_ok">'.Dict::S('Successfully recorded.').'</div>');
|
||||
$sOrginalConfig = 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>');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
$sOrginalConfig = $sConfig;
|
||||
}
|
||||
|
||||
$sConfigEscaped = htmlentities($sConfig, ENT_QUOTES, 'UTF-8');
|
||||
$sOriginalConfigEscaped = htmlentities($sOrginalConfig, ENT_QUOTES, 'UTF-8');
|
||||
$oP->p(Dict::S('config-edit-intro'));
|
||||
$oP->add("<form method=\"POST\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"save\">");
|
||||
$oP->add("<input type=\"submit\" value=\"".Dict::S('config-apply')."\"><button onclick=\"ResetConfig(); return false;\">".Dict::S('config-cancel')."</button>");
|
||||
$oP->add("<span class=\"current_line\">".Dict::Format('config-current-line', "<span class=\"line_number\"></span>")."</span>");
|
||||
$oP->add("<input type=\"hidden\" id=\"prev_config\" name=\"prev_config\" value=\"$sOriginalConfigEscaped\">");
|
||||
$oP->add("<textarea id =\"new_config\" name=\"new_config\" onkeyup=\"UpdateLineNumber();\" onmouseup=\"UpdateLineNumber();\">$sConfigEscaped</textarea>");
|
||||
$oP->add("<input type=\"submit\" value=\"".Dict::S('config-apply')."\"><button onclick=\"ResetConfig(); return false;\">".Dict::S('config-cancel')."</button>");
|
||||
$oP->add("<span class=\"current_line\">".Dict::Format('config-current-line', "<span class=\"line_number\"></span>")."</span>");
|
||||
$oP->add("</form>");
|
||||
|
||||
$sConfirmCancel = addslashes(Dict::S('config-confirm-cancel'));
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
function UpdateLineNumber()
|
||||
{
|
||||
var oTextArea = $('#new_config')[0];
|
||||
$('.line_number').html(oTextArea.value.substr(0, oTextArea.selectionStart).split("\\n").length);
|
||||
$('.current_line').show();
|
||||
}
|
||||
function ResetConfig()
|
||||
{
|
||||
if ($('#new_config').val() != $('#prev_config').val())
|
||||
{
|
||||
if (confirm('$sConfirmCancel'))
|
||||
{
|
||||
$('#new_config').val($('#prev_config').val());
|
||||
}
|
||||
}
|
||||
$('.current_line').hide();
|
||||
$('#save_result').hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
function setCursorPos(input, start, end) {
|
||||
if (arguments.length < 3) end = start;
|
||||
if ("selectionStart" in input) {
|
||||
setTimeout(function() {
|
||||
input.selectionStart = start;
|
||||
input.selectionEnd = end;
|
||||
}, 1);
|
||||
}
|
||||
else if (input.createTextRange) {
|
||||
var rng = input.createTextRange();
|
||||
rng.moveStart("character", start);
|
||||
rng.collapse();
|
||||
rng.moveEnd("character", end - start);
|
||||
rng.select();
|
||||
}
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
?>
|
||||
20
datamodels/2.x/itop-config/de.dict.itop-config.php
Normal file
20
datamodels/2.x/itop-config/de.dict.itop-config.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Konfiguration',
|
||||
'config-edit-title' => 'Konfigurations-Editor',
|
||||
'config-edit-intro' => 'Seien sie bei der Bearbeitung der Konfigurationsdatei sehr vorsichtig. Normalerweise sollten es aureichen die Einträge im oberen Teil der Konfiguration zu bearbeiten (Bsp.: die globalen Konfigurations- und Moduleinstellungen).',
|
||||
'config-apply' => 'Anwenden',
|
||||
'config-cancel' => 'Zurücksetzen',
|
||||
'config-confirm-cancel' => 'Ihre Änderungen werden nicht gespeichert.',
|
||||
'config-no-change' => 'Keine Änderungen: Die Datei wurde nicht verändert.',
|
||||
'config-parse-error' => 'Zeile %2$d: %1$s.<br/>Die Datei wurde nicht aktualisiert.',
|
||||
'config-current-line' => 'Editiere Zeile: %1$s',
|
||||
));
|
||||
21
datamodels/2.x/itop-config/en.dict.itop-config.php
Normal file
21
datamodels/2.x/itop-config/en.dict.itop-config.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Configuration File Editor',
|
||||
'config-edit-intro' => 'Be very cautious when editing the configuration file. In particular, only the upper items (i.e. the global configuration and modules settings) should be edited.',
|
||||
'config-apply' => 'Apply',
|
||||
'config-cancel' => 'Reset',
|
||||
'config-confirm-cancel' => 'Your changes will be lost.',
|
||||
'config-no-change' => 'No change: the file has been left unchanged.',
|
||||
'config-parse-error' => 'Line %2$d: %1$s.<br/>The file has NOT been updated.',
|
||||
'config-current-line' => 'Editing line: %1$s',
|
||||
));
|
||||
?>
|
||||
21
datamodels/2.x/itop-config/fr.dict.itop-config.php
Normal file
21
datamodels/2.x/itop-config/fr.dict.itop-config.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Editeur du Fichier de Configuration',
|
||||
'config-edit-intro' => 'Attention: une configuration incorrecte peut rendre iTop indisponible. En particulier, vous ne devriez éditer QUE les deux premiers éléments, à savoir la configuration globale et la configuration des modules.',
|
||||
'config-save' => 'Appliquer',
|
||||
'config-restore' => 'Réinitialiser',
|
||||
'config-confirm-cancel' => 'Vos modifications seront perdues.',
|
||||
'config-no-change' => 'Aucun changement : le fichier n\'a pas été altéré.',
|
||||
'config-parse-error' => 'Ligne %2$d: %1$s.<br/>Le fichier n\'a PAS été modifié.',
|
||||
'config-current-line' => 'Ligne en édition : %1$s',
|
||||
));
|
||||
?>
|
||||
30
datamodels/2.x/itop-config/main.itop-config.php
Normal file
30
datamodels/2.x/itop-config/main.itop-config.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// Copyright (C) 2013 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
//require_once(APPROOT.'setup/setuputils.class.inc.php');
|
||||
|
||||
class ItopConfigEditor extends ModuleHandlerAPI
|
||||
{
|
||||
public static function OnMenuCreation()
|
||||
{
|
||||
if (UserRights::IsAdministrator())
|
||||
{
|
||||
$oAdminMenu = new MenuGroup('AdminTools', 80 /* fRank */);
|
||||
new WebPageMenuNode('ConfigEditor', utils::GetAbsoluteUrlModulesRoot().'itop-config/config.php', $oAdminMenu->GetIndex(), 18 /* fRank */);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
datamodels/2.x/itop-config/module.itop-config.php
Normal file
53
datamodels/2.x/itop-config/module.itop-config.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config/1.0.1',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Configuration editor',
|
||||
'category' => 'Application management',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'main.itop-config.php',
|
||||
//'model.itop-config.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
//'webservices.itop-config.php',
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.itop-config.php',
|
||||
'fr.dict.itop-config.php',
|
||||
//'de.dict.itop-config.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
//'data.struct.itop-config.xml',
|
||||
),
|
||||
'data.sample' => array(
|
||||
//'data.sample.itop-config.xml',
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user