add new feature: import/export of settings

Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann (d00p) 2018-01-28 14:33:00 +01:00
parent d8a3015303
commit 840b5ea229
8 changed files with 191 additions and 3 deletions

View File

@ -290,6 +290,38 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
}
eval("echo \"" . getTemplate("settings/integritycheck") . "\";");
}
elseif ($page == 'importexport' && $userinfo['change_serversettings'] == '1')
{
if (isset($_GET['action']) && $_GET['action'] == "export") {
// export
try {
$json_export = SImExporter::export();
} catch(Exception $e) {
dynamic_error($e->getMessage());
}
header('Content-disposition: attachment; filename=Froxlor_settings-'.$version.'-'.$dbversion.'_'.date('d.m.Y').'.json');
header('Content-type: application/json');
echo $json_export;
exit;
} elseif (isset($_GET['action']) && $_GET['action'] == "import") {
// import
if (isset($_POST['send']) && $_POST['send'] == 'send') {
// get uploaded file
if (isset($_FILES["import_file"]["tmp_name"])) {
$imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]);
try {
SImExporter::import($imp_content);
} catch(Exception $e) {
dynamic_error($e->getMessage());
}
standard_success('settingsimported', '', array('filename' => 'admin_settings.php'));
}
dynamic_error("Upload failed");
}
} else {
eval("echo \"" . getTemplate("settings/importexport/index") . "\";");
}
}
elseif ($page == 'testmail')
{
if (isset($_POST['send']) && $_POST['send'] == 'send')

View File

@ -0,0 +1,114 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2018 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Michael Kaufmann <d00p@froxlor.org>
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
* @since 0.9.39
*
*/
/**
* Class SImExporter
*
* Import/Export settings to JSON
*
* @copyright (c) the authors
* @author Michael Kaufmann <d00p@froxlor.org>
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*/
class SImExporter
{
/**
* settings which are not being exported
*
* @var array
*/
private static $_no_export = [
'panel.adminmail',
'admin.show_news_feed',
'system.lastaccountnumber',
'system.lastguid',
'system.ipaddress',
'system.last_traffic_run',
'system.hostname',
'system.mysql_access_host',
'system.lastcronrun',
'system.defaultip',
'system.last_tasks_run',
'system.last_archive_run',
'system.leprivatekey',
'system.lepublickey'
];
public static function export()
{
$result_stmt = Database::query("
SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY `settingid` ASC
");
$_data = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$index = $row['settinggroup'] . "." . $row['varname'];
if (! in_array($index, self::$_no_export)) {
$_data[$index] = $row['value'];
}
}
// add checksum for validation
$_data['_sha'] = sha1(var_export($_data, true));
$_export = json_encode($_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
if (! $_export) {
throw new Exception("Error exporting settings: " . json_last_error_msg());
}
return $_export;
}
public static function import($json_str = null)
{
// decode data
$_data = json_decode($json_str, true);
if ($_data) {
// get validity check data
$_sha = isset($_data['_sha']) ? $_data['_sha'] : false;
$_version = isset($_data['panel.version']) ? $_data['panel.version'] : false;
$_dbversion = isset($_data['panel.db_version']) ? $_data['panel.db_version'] : false;
// check if we have everything we need
if (! $_sha || ! $_version || ! $_dbversion) {
throw new Exception("Invalid froxlor settings data. Unable to import.");
}
// validate import file
unset($_data['_sha']);
// compare
if ($_sha != sha1(var_export($_data, true))) {
throw new Exception("SHA check of import data failed. Unable to import.");
}
// do not import version info - but we need that to possibily update settings
// when there were changes in the variable-name or similar
unset($_data['panel.version']);
unset($_data['panel.db_version']);
/*
// store new data
foreach ($_data as $index => $value) {
Settings::Set($index, $value);
}
// save to DB
Settings::Flush();
*/
// all good
return true;
}
throw new Exception("Invalid JSON data: " . json_last_error_msg());
}
}

View File

@ -63,3 +63,15 @@ function standard_error($errors = '', $replacer = '') {
eval("echo \"" . getTemplate('misc/error', '1') . "\";");
exit;
}
function dynamic_error($message) {
global $userinfo, $s, $header, $footer, $lng, $theme;
$_SESSION['requestData'] = $_POST;
$link = '';
if (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) !== false) {
$link = '<a href="'.htmlentities($_SERVER['HTTP_REFERER']).'">'.$lng['panel']['back'].'</a>';
}
$error = $message;
eval("echo \"" . getTemplate('misc/error', '1') . "\";");
exit;
}

View File

@ -2101,4 +2101,5 @@ $lng['phpfpm']['ini_values'] = 'Enter possible <strong>php_value</strong>s for p
$lng['phpfpm']['ini_admin_flags'] = 'Enter possible <strong>php_admin_flag</strong>s for php.ini. One entry per line';
$lng['phpfpm']['ini_admin_values'] = 'Enter possible <strong>php_admin_value</strong>s for php.ini. One entry per line';
$lng['serversettings']['phpfpm_settings']['envpath'] = 'Paths to add to the PATH environment. Leave empty for no PATH environment variable';
$lng['admin']['configfiles']['importexport'] = 'Import/Export';
$lng['success']['settingsimported'] = 'Settings imported successfully';

View File

@ -1752,3 +1752,4 @@ $lng['phpfpm']['ini_values'] = 'Mögliche <strong>php_value</strong>s für die p
$lng['phpfpm']['ini_admin_flags'] = 'Mögliche <strong>php_admin_flag</strong>s für die php.ini. Pro Zeile eine Direktive';
$lng['phpfpm']['ini_admin_values'] = 'Mögliche <strong>php_admin_value</strong>s für die php.ini. Pro Zeile eine Direktive';
$lng['serversettings']['phpfpm_settings']['envpath'] = 'Pfade für die PATH Umgebungsvariable. Leerlassen, um keine PATH Umgebungsvariable zu setzen.';
$lng['success']['settingsimported'] = 'Einstellungnen erfolgreich importiert';

View File

@ -0,0 +1,26 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="" />&nbsp;
{$lng['admin']['configfiles']['importexport']}
</h2>
</header>
<section>
<a href="{$linker->getLink(array('section' => 'settings', 'page' => $page, 'action' => 'export'))}">
<input class="yesbutton" type="button" value="Download/Export {$lng['admin']['serversettings']}" />
</a>
</section>
<br><br>
<section>
<form action="{$linker->getLink(array('section' => 'settings', 'page' => $page, 'action' => 'import'))}" method="post" enctype="multipart/form-data">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="send" value="send" />
<input type="file" name="import_file" id="import_file" placeholder="Chose file for import" />
<input type="submit" value="Import">
</form>
</section>
</article>
$footer

View File

@ -3,7 +3,8 @@
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="" />&nbsp;
{$lng['admin']['serversettings']} &nbsp;
[<a href="$filename?page=overview&amp;part=&amp;s=$s">{$lng['admin']['configfiles']['compactoverview']}</a>]
[<a href="$filename?page=overview&amp;part=&amp;s=$s">{$lng['admin']['configfiles']['compactoverview']}</a>] &nbsp;
[<a href="$filename?page=importexport&amp;s=$s">{$lng['admin']['configfiles']['importexport']}</a>]
</h2>
</header>

View File

@ -3,7 +3,8 @@
<h2>
<img src="templates/{$theme}/assets/img/icons/settings_big.png" alt="" />&nbsp;
{$lng['admin']['serversettings']} &nbsp;
[<a href="$filename?page=overview&amp;part=all&amp;s=$s">{$lng['admin']['configfiles']['overview']}</a>]
[<a href="$filename?page=overview&amp;part=all&amp;s=$s">{$lng['admin']['configfiles']['overview']}</a>] &nbsp;
[<a href="$filename?page=importexport&amp;s=$s">{$lng['admin']['configfiles']['importexport']}</a>]
</h2>
</header>