System: Configuration: Defaults - refactor to mvc and add "components" which offers a configuration reset function per model (when not installed, it uses the version tags to identify them). closes https://github.com/opnsense/core/issues/8768

This commit is contained in:
Ad Schellevis 2025-10-16 21:10:00 +02:00
parent 420a9cc2ec
commit c485a33ab7
10 changed files with 525 additions and 121 deletions

6
plist
View file

@ -199,6 +199,7 @@
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/forms/dialogZone.xml
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/BackupController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/DefaultsController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/HasyncController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/HasyncStatusController.php
@ -210,6 +211,7 @@
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/TunablesController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/BackupController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/DashboardController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/DefaultsController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/FirmwareController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/HaltController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/HasyncController.php
@ -520,6 +522,7 @@
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Backend.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Config.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/ConfigException.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/ConfigMaintenance.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/File.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/FileObject.php
/usr/local/opnsense/mvc/app/library/OPNsense/Core/SanitizeFilter.php
@ -888,6 +891,7 @@
/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/vouchers.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/backup_history.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/dashboard.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/defaults.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/firmware.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/halt.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/hasync.volt
@ -1316,6 +1320,7 @@
/usr/local/opnsense/scripts/system/certctl.py
/usr/local/opnsense/scripts/system/cpu.py
/usr/local/opnsense/scripts/system/crl_fetch.py
/usr/local/opnsense/scripts/system/factory_defaults.php
/usr/local/opnsense/scripts/system/flush_config_history
/usr/local/opnsense/scripts/system/get_locales.php
/usr/local/opnsense/scripts/system/get_timezones.php
@ -2438,7 +2443,6 @@
/usr/local/www/csrf.inc
/usr/local/www/diag_authentication.php
/usr/local/www/diag_backup.php
/usr/local/www/diag_defaults.php
/usr/local/www/fbegin.inc
/usr/local/www/firewall_nat.php
/usr/local/www/firewall_nat_edit.php

View file

@ -0,0 +1,133 @@
<?php
/*
* Copyright (C) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Core\Api;
use OPNsense\Base\ApiControllerBase;
use OPNsense\Core\ACL;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
use OPNsense\Core\ConfigMaintenance;
/**
* Class DefaultsController
* @package OPNsense\Core\Api
*/
class DefaultsController extends ApiControllerBase
{
/**
* when the user-config-readonly privilege is set, raise an error
*/
private function throwReadOnly()
{
if ((new ACL())->hasPrivilege($this->getUserName(), 'user-config-readonly')) {
throw new UserException(
sprintf("User %s denied for write access (user-config-readonly set)", $this->getUserName())
);
}
}
/**
* return defaults
*/
public function getAction()
{
$default_ip = '192.168.1.1';
if (is_file('/usr/local/etc/config.xml')) {
$cfg = Config::getInstance()->toArrayFromFile('/usr/local/etc/config.xml');
if (is_array($cfg) &&
!empty($cfg['interfaces']) &&
!empty($cfg['interfaces']['lan']) &&
!empty($cfg['interfaces']['lan']['ipaddr'])
) {
$default_ip = $cfg['interfaces']['lan']['ipaddr'];
}
}
return ['default_ip' => $default_ip];
}
/**
* reset to defaults
*/
public function factoryDefaultsAction()
{
$this->throwReadOnly();
if (!$this->request->isPost()) {
return ['status' => 'failed'];
}
/* schedule factory defaults so we can safely respond to the client */
(new Backend())->configdRun('system reset_factory_defaults', true);
return ['status' => 'ok'];
}
/**
* return used configuration items
*/
public function getInstalledSectionsAction()
{
$result = ['items' => []];
$cm = new ConfigMaintenance();
foreach($cm->traverseConfig() as $item) {
$result['items'][] = $item;
}
return $result;
}
/**
* reset a (list of) section(s)
*/
public function resetAction()
{
$this->throwReadOnly();
if (
!$this->request->isPost() ||
!is_array($this->request->getPost('items')) ||
empty($this->request->getPost('items'))
) {
return ['status' => 'failed'];
}
$cm = new ConfigMaintenance();
$modelmap = $cm->getMap();
foreach ($this->request->getPost('items') as $section) {
if (isset($modelmap[$section])) {
/* installed model flush */
$mdl = new $modelmap[$section]['class'](true);
$mdl->Default();
$mdl->serializeToConfig(false, true);
} else {
$cm->delItem($section);
}
}
Config::getInstance()->save();
return ['status' => 'ok'];
}
}

View file

@ -0,0 +1,41 @@
<?php
/*
* Copyright (C) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Core;
/**
* Class DefaultsController
* @package OPNsense\Core
*/
class DefaultsController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
$this->view->pick('OPNsense/Core/defaults');
}
}

View file

@ -0,0 +1,145 @@
<?php
/*
* Copyright (C) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Core;
use OPNsense\Core\AppConfig;
use OPNsense\Core\Syslog;
class ConfigMaintenance
{
private $modelmap = [];
private $foundrefs = [];
public function __construct()
{
$this->modelmap = $this->loadModels();
}
/**
* collect all installed modules
*/
private function loadModels()
{
$modelfiles = [];
$model_dir = dirname((new \ReflectionClass("OPNsense\\Base\\BaseModel"))->getFileName()) . "/../../";
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($model_dir)) as $x) {
$pinfo = pathinfo(realpath($x->getPathname()));
$xmlname = sprintf("%s/%s.xml", $pinfo['dirname'], $pinfo['filename']);
$classname = str_replace('/', '\\', explode('.', str_replace($model_dir, '', $x->getPathname()))[0]);
if (file_exists($xmlname) && isset($pinfo['extension']) && $pinfo['extension'] == 'php') {
$parent = (new \ReflectionClass($classname))->getParentClass();
if ($parent && $parent->name == 'OPNsense\Base\BaseModel') {
$modelfiles[$xmlname] = $classname;
}
}
}
$map = [];
foreach ($modelfiles as $filename => $classname) {
$model_xml = simplexml_load_file($filename);
if ($model_xml !== false && str_starts_with($model_xml->mount, '/')) {
$mount = str_replace('/', '.', ltrim(rtrim($model_xml->mount, '+'), '/'));
$map[$mount] = [
'filename' => $filename,
'class' => $classname,
'description' => trim((string)$model_xml->description ?? '')
];
}
}
return $map;
}
/**
* collect all "flushable" configuration items (models)
*/
public function traverseConfig($node=null, $path='')
{
if ($node === null) {
$node = (Config::getInstance())->object();
$this->foundrefs = [];
}
foreach ($node->children() as $xmlNode) {
if ($xmlNode->count() > 0) {
$this_path = ltrim($path . '.' . $xmlNode->getName(), '.');
if (in_array($this_path, $this->foundrefs)) {
continue;
} elseif (isset($this->modelmap[$this_path]) || !empty($xmlNode->attributes()['version'])) {
/* found a registered model or a container with a version tag (likely model, but not installed) */
$this->foundrefs[] = $this_path;
if (isset($this->modelmap[$this_path])) {
yield [
'id' => $this_path,
'description' => $this->modelmap[$this_path]['description']
];
} else {
$tmp = explode('.', $this_path);
yield [
'id' => $this_path,
'description' => end($tmp)
];
}
} else {
yield from $this->traverseConfig($xmlNode, $this_path);
}
}
}
}
/**
* del model item, requires a version attribute to identify itself as a model.
*/
public function delItem($item, $node=null, $path='')
{
if ($node === null) {
$node = (Config::getInstance())->object();
}
foreach ($node->children() as $xmlNode) {
if ($xmlNode->count() > 0) {
$this_path = ltrim($path . '.' . $xmlNode->getName(), '.');
if (!empty($xmlNode->attributes()['version'])) {
if ($this_path == $item) {
unset($xmlNode[0]);
return true;
}
} else {
$this->delItem($item, $xmlNode, $this_path);
}
}
}
return false;
}
/**
* retrieve model map
*/
public function getMap()
{
return $this->modelmap;
}
}

View file

@ -60,7 +60,8 @@
<page-diagnostics-factorydefaults>
<name>Diagnostics: Factory defaults</name>
<patterns>
<pattern>diag_defaults.php*</pattern>
<pattern>ui/core/defaults</pattern>
<pattern>api/core/defaults/*</pattern>
</patterns>
</page-diagnostics-factorydefaults>
<page-diagnostics-haltsystem>

View file

@ -28,7 +28,7 @@
</Access>
<Configuration cssClass="fa fa-history fa-fw">
<Backups url="/diag_backup.php"/>
<Defaults url="/diag_defaults.php"/>
<Defaults url="/ui/core/defaults"/>
<History url="/ui/core/backup/history/this"/>
<Wizard url="/ui/core/initial_setup"/>
</Configuration>

View file

@ -0,0 +1,151 @@
{#
# Copyright (c) 2025 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#}
<script>
$( document ).ready(function() {
/* update default address and show form */
ajaxGet('/api/core/defaults/get', {}, function(data){
if (data.default_ip) {
$("#ip_placeholder").text($("#ip_placeholder").text().replace('%s', data.default_ip));
$("#defaults_form").show();
}
});
/* full system defauls */
$("#system_defaults").click(function(){
BootstrapDialog.show({
type:BootstrapDialog.TYPE_INFO,
title: '{{ lang._('Configuration defaults') }}',
closable: false,
message: '{{ lang._('The system will install the configuration defaults now and power off when finished.') }}',
onshow: function (dialogRef) {
ajaxCall('/api/core/defaults/factory_defaults');
},
});
});
function load_section()
{
ajaxGet('/api/core/defaults/get_installed_sections', {}, function(data){
if (data.items) {
$("#sections").empty();
data.items.forEach(function (item, index) {
$("#sections").append($("<option/>").val(item.id).text(
item.description + ' [' + item.id + ']'
));
});
$("#sections").selectpicker('refresh');
}
});
}
load_section();
$("#reset_sections").click(function(event){
event.preventDefault();
BootstrapDialog.show({
type:BootstrapDialog.TYPE_DANGER,
title: "{{ lang._('Reset') }}",
message: "{{ lang._('Are you sure you want to reset selected configuration sections?\n Removing parts of the configuration does not warrant consistency and may lead to unexpected behavior.')}}",
buttons: [
{
label: "{{ lang._('No') }}",
action: function(dialogRef) {
dialogRef.close();
}
},
{
label: "{{ lang._('Yes') }}",
action: function(dialogRef) {
ajaxCall('/api/core/defaults/reset', {'items': $("#sections").val()}, function(){
dialogRef.close();
load_section();
});
}
}
]
});
});
});
</script>
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
<li class="active"><a id="systemtab" data-toggle="tab" href="#full_defaults">{{ lang._('Full') }}</a></li>
<li id="componentstab"><a data-toggle="tab" href="#components">{{ lang._('Components') }}</a></li>
</ul>
<div class="tab-content content-box">
<div id="full_defaults" class="tab-pane fade in active">
<div class="container-fluid">
<div class="row">
<section class="col-xs-12" style="display: none;" id="defaults_form">
<br/>
<p><strong> {{ lang._('If you click "Yes", the system will:') }}</strong></p>
<ul>
<li>{{ lang._('Reset to factory defaults') }}</li>
<li id="ip_placeholder">{{ lang._('LAN IP address will be reset to %s') }}</li>
<li>{{ lang._('System will be configured as a DHCP server on the default LAN interface') }}</li>
<li>{{ lang._('WAN interface will be set to obtain an address automatically from a DHCP server') }}</li>
<li>{{ lang._('Admin user name and password will be reset') }}</li>
<li>{{ lang._('Shut down after changes are complete') }}</li>
</ul>
<p><strong>{{ lang._('Are you sure you want to proceed?') }}</strong></p>
<div class="btn-group">
<button id="system_defaults" class="btn btn-primary">{{ lang._('Yes')}}</button>
<a href="/" class="btn btn-default">{{ lang._('No')}}</a>
<br/><br/><br/>
</section>
</div>
</div>
</div>
<div id="components" class="tab-pane fade in">
<table class="table table-condensed table-striped">
<br/>
<thead>
<tr>
<th colspan="2">
{{ lang._('Danger zone, only reset configuration sections if you understand the impact.') }}
</th>
</tr>
<tr>
<th>{{ lang._('Sections')}}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select id="sections" data-size="10" data-width="100%" data-live-search="true" multiple="multiple"></select>
</td>
<td>
<button id="reset_sections" class="btn btn-primary">{{ lang._('Reset')}}</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>

View file

@ -0,0 +1,41 @@
#!/usr/local/bin/php
<?php
/*
* Copyright (C) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once 'config.inc';
require_once 'system.inc';
require_once 'util.inc';
echo "waiting before shutdown..";
for ($i=0; $i < 5; ++$i) {
echo ".";
sleep(1);
}
echo "down\n";
reset_factory_defaults();

View file

@ -102,6 +102,12 @@ type:script
description:Halt and power off the system
message:Halting system
[reset_factory_defaults]
command:/usr/local/opnsense/scripts/system/factory_defaults.php
parameters:
type:script_output
message:Revert to system defaults and power down the system
[sensors]
command:sysctl -aF | awk -F ": " '$2 ~ "^IK" { print $1 }' | grep -v -e "\._" -e "\.ctt" -e "\.[pt][m012]" -e "\.tjmax" | sort
parameters:

View file

@ -1,118 +0,0 @@
<?php
/*
* Copyright (C) 2014 Deciso B.V.
* Copyright (C) 2004-2009 Scott Ullrich <sullrich@gmail.com>
* Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
require_once("system.inc");
$input_errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['Submit'])) {
$user = getUserEntry($_SESSION['Username']);
if (userHasPrivilege($user, 'user-config-readonly')) {
$input_errors[] = gettext('You do not have the permission to perform this action.');
}
}
}
$default_config_ip = '192.168.1.1'; /* failsafe default */
if (is_file('/usr/local/etc/config.xml')) {
try {
$restore_conf = load_config_from_file('/usr/local/etc/config.xml');
if (
is_array($restore_conf) &&
!empty($restore_conf['interfaces']) &&
!empty($restore_conf['interfaces']['lan']) &&
!empty($restore_conf['interfaces']['lan']['ipaddr'])
) {
$default_config_ip = $restore_conf['interfaces']['lan']['ipaddr'];
}
} catch (Exception $e) { }
}
include("head.inc");
?>
<body>
<?php
include("fbegin.inc");
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['Submit']) && !count($input_errors)): ?>
<script>
$(document).ready(function() {
BootstrapDialog.show({
type:BootstrapDialog.TYPE_INFO,
title: '<?= html_safe(gettext('Your device is powering off')) ?>',
closable: false,
message: '<?= html_safe(gettext('The system has been reset to factory defaults and is shutting down.')) ?>',
});
});
</script>
<?php endif ?>
<section class="page-content-main">
<div class="container-fluid">
<div class="row">
<?php if (count($input_errors)) print_input_errors($input_errors); ?>
<section class="col-xs-12">
<form method="post">
<p><strong> <?=gettext('If you click "Yes", the system will:')?></strong></p>
<ul>
<li><?= gettext('Reset to factory defaults') ?></li>
<li><?= sprintf(gettext('LAN IP address will be reset to %s'), $default_config_ip) ?></li>
<li><?= gettext('System will be configured as a DHCP server on the default LAN interface') ?></li>
<li><?= gettext('WAN interface will be set to obtain an address automatically from a DHCP server') ?></li>
<li><?= gettext('Admin user name and password will be reset') ?></li>
<li><?= gettext('Shut down after changes are complete') ?></li>
</ul>
<p><strong><?=gettext("Are you sure you want to proceed?");?></strong></p>
<div class="btn-group">
<input type="submit" name="Submit" class="btn btn-primary" value="<?= html_safe(gettext('Yes')) ?>" />
<a href="/" class="btn btn-default"><?=gettext("No");?></a>
</div>
</form>
</section>
</div>
</div>
</section>
<?php
include("foot.inc");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['Submit'])) {
if (!count($input_errors)) {
reset_factory_defaults(false);
}
}
}