Squashed commit of the following:

commit 0c60937253296d81c68d8cde50df6fd8fbe21442
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Mon Jul 1 15:00:43 2024 +0200

    dashboard: remove old widgets

commit 7a58bc05871388225412fa87bcc816aadf03237e
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Mon Jul 1 14:57:33 2024 +0200

    Dashboard: match ACLs with implied pages and restructure system controller layer

commit 65e97442d57eeb6fb0c714b4493c4667d76ac8b0
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Thu Jun 27 16:42:25 2024 +0200

    dashboard: update ACLs

commit e54a5b82b1f46158760346c45a4e80c5aaa182bf
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Fri Jun 14 16:25:40 2024 +0200

    dashboard: VisibleName not necessary anymore

commit fc45589318a98315e93399575a67de368be01353
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Fri Jun 14 16:15:06 2024 +0200

    dashboard: fix ACLs

commit 01f8e1c3e1357c61ed7e2db03fa5488d05535773
Author: Stephan de Wit <stephan.de.wit@deciso.com>
Date:   Fri Jun 14 14:03:30 2024 +0200

    dashboard: initial cleanup code
This commit is contained in:
Ad Schellevis 2024-07-07 11:26:09 +02:00
parent f587c307e3
commit cff24b7a8a
49 changed files with 341 additions and 4686 deletions

36
plist
View File

@ -2197,42 +2197,6 @@
/usr/local/www/vpn_ipsec_settings.php
/usr/local/www/vpn_openvpn_client.php
/usr/local/www/vpn_openvpn_server.php
/usr/local/www/widgets/api/get.php
/usr/local/www/widgets/api/plugins/system.inc
/usr/local/www/widgets/api/plugins/temperature.inc
/usr/local/www/widgets/include/carp_status.inc
/usr/local/www/widgets/include/cpu_usage.inc
/usr/local/www/widgets/include/gateways.inc
/usr/local/www/widgets/include/interface_list.inc
/usr/local/www/widgets/include/interface_statistics.inc
/usr/local/www/widgets/include/ipsec.inc
/usr/local/www/widgets/include/log.inc
/usr/local/www/widgets/include/monit.inc
/usr/local/www/widgets/include/ntp_status.inc
/usr/local/www/widgets/include/openvpn.inc
/usr/local/www/widgets/include/services_status.inc
/usr/local/www/widgets/include/system_log.inc
/usr/local/www/widgets/include/thermal_sensors.inc
/usr/local/www/widgets/include/traffic_graph.inc
/usr/local/www/widgets/include/wireguard.inc
/usr/local/www/widgets/widgets/carp_status.widget.php
/usr/local/www/widgets/widgets/cpu_usage.widget.php
/usr/local/www/widgets/widgets/gateways.widget.php
/usr/local/www/widgets/widgets/interface_list.widget.php
/usr/local/www/widgets/widgets/interface_statistics.widget.php
/usr/local/www/widgets/widgets/ipsec.widget.php
/usr/local/www/widgets/widgets/log.widget.php
/usr/local/www/widgets/widgets/monit.widget.php
/usr/local/www/widgets/widgets/ntp_status.widget.php
/usr/local/www/widgets/widgets/openvpn.widget.php
/usr/local/www/widgets/widgets/picture.widget.php
/usr/local/www/widgets/widgets/rss.widget.php
/usr/local/www/widgets/widgets/services_status.widget.php
/usr/local/www/widgets/widgets/system_information.widget.php
/usr/local/www/widgets/widgets/system_log.widget.php
/usr/local/www/widgets/widgets/thermal_sensors.widget.php
/usr/local/www/widgets/widgets/traffic_graphs.widget.php
/usr/local/www/widgets/widgets/wireguard.widget.php
/usr/local/www/wizard.php
/usr/local/www/xmlrpc.php
@sample /usr/local/etc/bogons.sample

View File

@ -41,28 +41,6 @@ use OPNsense\Core\Config;
*/
class SystemController extends ApiControllerBase
{
private function formatUptime($uptime)
{
$days = floor($uptime / (3600 * 24));
$hours = floor(($uptime % (3600 * 24)) / 3600);
$minutes = floor(($uptime % 3600) / 60);
$seconds = $uptime % 60;
if ($days > 0) {
$plural = $days > 1 ? gettext("days") : gettext("day");
return sprintf(
"%d %s, %02d:%02d:%02d",
$days,
$plural,
$hours,
$minutes,
$seconds
);
} else {
return sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
}
}
public function haltAction()
{
if ($this->request->isPost()) {
@ -208,154 +186,4 @@ class SystemController extends ApiControllerBase
return ["status" => "failed"];
}
public function systemInformationAction()
{
$config = Config::getInstance()->object();
$backend = new Backend();
$product = json_decode($backend->configdRun('firmware product'), true);
$current = explode('_', $product['product_version'])[0];
/* information from changelog, more accurate for production release */
$from_changelog = strpos($product['product_id'], '-devel') === false &&
!empty($product['product_latest']) &&
$product['product_latest'] != $current;
/* update status from last check, also includes major releases */
$from_check = !empty($product['product_check']['upgrade_sets']) ||
!empty($product['product_check']['downgrade_packages']) ||
!empty($product['product_check']['new_packages']) ||
!empty($product['product_check']['reinstall_packages']) ||
!empty($product['product_check']['remove_packages']) ||
!empty($product['product_check']['upgrade_packages']);
$versions = [
sprintf('%s %s-%s', $product['product_name'], $product['product_version'], $product['product_arch']),
php_uname('s') . ' ' . php_uname('r'),
trim($backend->configdRun('system openssl version')),
];
if (!empty($product['product_license']['valid_to'])) {
$versions[] = sprintf(gettext('Licensed until %s'), $product['product_license']['valid_to']);
}
$response = [
'name' => $config->system->hostname . '.' . $config->system->domain,
'versions' => $versions,
'updates' => ($from_changelog || $from_check)
? gettext('Click to view pending updates.')
: gettext('Click to check for updates.'),
];
return $response;
}
public function systemTimeAction()
{
$config = Config::getInstance()->object();
$boottime = json_decode((new Backend())->configdRun('system sysctl values kern.boottime'), true);
preg_match("/sec = (\d+)/", $boottime['kern.boottime'], $matches);
$last_change = date("D M j G:i:s T Y", !empty($config->revision->time) ? intval($config->revision->time) : 0);
$response = [
'uptime' => $this->formatUptime(time() - $matches[1]),
'datetime' => date("D M j G:i:s T Y"),
'config' => $last_change,
];
return $response;
}
public function systemResourcesAction()
{
$result = [];
$mem = json_decode((new Backend())->configdpRun('system sysctl values', implode(',', [
'hw.physmem',
'vm.stats.vm.v_page_count',
'vm.stats.vm.v_inactive_count',
'vm.stats.vm.v_cache_count',
'vm.stats.vm.v_free_count',
'kstat.zfs.misc.arcstats.size'
])), true);
if (!empty($mem['vm.stats.vm.v_page_count'])) {
$pc = $mem['vm.stats.vm.v_page_count'];
$ic = $mem['vm.stats.vm.v_inactive_count'];
$cc = $mem['vm.stats.vm.v_cache_count'];
$fc = $mem['vm.stats.vm.v_free_count'];
$result['memory']['total'] = $mem['hw.physmem'];
$result['memory']['total_frmt'] = sprintf('%d', $mem['hw.physmem'] / 1024 / 1024);
$result['memory']['used'] = round(((($pc - ($ic + $cc + $fc))) / $pc) * $mem['hw.physmem'], 0);
$result['memory']['used_frmt'] = sprintf('%d', $result['memory']['used'] / 1024 / 1024);
if (!empty($mem['kstat.zfs.misc.arcstats.size'])) {
$arc_size = $mem['kstat.zfs.misc.arcstats.size'];
$result['memory']['arc'] = $arc_size;
$result['memory']['arc_frmt'] = sprintf('%d', $arc_size / 1024 / 1024);
$result['memory']['arc_txt'] = sprintf(gettext('ARC size %d MB'), $arc_size / 1024 / 1024);
}
} else {
$result['memory']['used'] = gettext('N/A');
}
return $result;
}
public function systemDiskAction()
{
$result = [];
$disk_info = json_decode((new Backend())->configdRun('system diag disk'), true);
if (!empty($disk_info['storage-system-information'])) {
foreach ($disk_info['storage-system-information']['filesystem'] as $fs) {
if (!in_array(trim($fs['type']), ['cd9660', 'msdosfs', 'tmpfs', 'ufs', 'zfs'])) {
continue;
}
$result['devices'][] = [
'device' => $fs['name'],
'type' => trim($fs['type']),
'blocks' => $fs['blocks'],
'used' => $fs['used'],
'available' => $fs['available'],
'used_pct' => $fs['used-percent'],
'mountpoint' => $fs['mounted-on'],
];
}
}
return $result;
}
public function systemMbufAction()
{
return json_decode((new Backend())->configdRun('system show mbuf'), true);
}
public function systemSwapAction()
{
return json_decode((new Backend())->configdRun('system show swapinfo'), true);
}
public function systemTemperatureAction()
{
$result = [];
foreach (explode("\n", (new Backend())->configdRun('system temp')) as $temp) {
$parts = explode('=', $temp);
if (count($parts) >= 2) {
$tempItem = array();
$tempItem['device'] = $parts[0];
$tempItem['device_seq'] = filter_var($tempItem['device'], FILTER_SANITIZE_NUMBER_INT);
$tempItem['temperature'] = trim(str_replace('C', '', $parts[1]));
$tempItem['type'] = strpos($tempItem['device'], 'hw.acpi') !== false ? "zone" : "core";
$tempItem['type_translated'] = $tempItem['type'] == "zone" ? gettext("Zone") : gettext("Core");
$result[] = $tempItem;
}
}
return $result;
}
}

View File

@ -38,6 +38,28 @@ use OPNsense\Core\Backend;
*/
class SystemController extends ApiControllerBase
{
private function formatUptime($uptime)
{
$days = floor($uptime / (3600 * 24));
$hours = floor(($uptime % (3600 * 24)) / 3600);
$minutes = floor(($uptime % 3600) / 60);
$seconds = $uptime % 60;
if ($days > 0) {
$plural = $days > 1 ? gettext("days") : gettext("day");
return sprintf(
"%d %s, %02d:%02d:%02d",
$days,
$plural,
$hours,
$minutes,
$seconds
);
} else {
return sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
}
}
public function memoryAction()
{
$data = json_decode((new Backend())->configdRun('system show vmstat_mem'), true);
@ -64,4 +86,154 @@ class SystemController extends ApiControllerBase
}
return $data;
}
public function systemInformationAction()
{
$config = Config::getInstance()->object();
$backend = new Backend();
$product = json_decode($backend->configdRun('firmware product'), true);
$current = explode('_', $product['product_version'])[0];
/* information from changelog, more accurate for production release */
$from_changelog = strpos($product['product_id'], '-devel') === false &&
!empty($product['product_latest']) &&
$product['product_latest'] != $current;
/* update status from last check, also includes major releases */
$from_check = !empty($product['product_check']['upgrade_sets']) ||
!empty($product['product_check']['downgrade_packages']) ||
!empty($product['product_check']['new_packages']) ||
!empty($product['product_check']['reinstall_packages']) ||
!empty($product['product_check']['remove_packages']) ||
!empty($product['product_check']['upgrade_packages']);
$versions = [
sprintf('%s %s-%s', $product['product_name'], $product['product_version'], $product['product_arch']),
php_uname('s') . ' ' . php_uname('r'),
trim($backend->configdRun('system openssl version')),
];
if (!empty($product['product_license']['valid_to'])) {
$versions[] = sprintf(gettext('Licensed until %s'), $product['product_license']['valid_to']);
}
$response = [
'name' => $config->system->hostname . '.' . $config->system->domain,
'versions' => $versions,
'updates' => ($from_changelog || $from_check)
? gettext('Click to view pending updates.')
: gettext('Click to check for updates.'),
];
return $response;
}
public function systemTimeAction()
{
$config = Config::getInstance()->object();
$boottime = json_decode((new Backend())->configdRun('system sysctl values kern.boottime'), true);
preg_match("/sec = (\d+)/", $boottime['kern.boottime'], $matches);
$last_change = date("D M j G:i:s T Y", !empty($config->revision->time) ? intval($config->revision->time) : 0);
$response = [
'uptime' => $this->formatUptime(time() - $matches[1]),
'datetime' => date("D M j G:i:s T Y"),
'config' => $last_change,
];
return $response;
}
public function systemResourcesAction()
{
$result = [];
$mem = json_decode((new Backend())->configdpRun('system sysctl values', implode(',', [
'hw.physmem',
'vm.stats.vm.v_page_count',
'vm.stats.vm.v_inactive_count',
'vm.stats.vm.v_cache_count',
'vm.stats.vm.v_free_count',
'kstat.zfs.misc.arcstats.size'
])), true);
if (!empty($mem['vm.stats.vm.v_page_count'])) {
$pc = $mem['vm.stats.vm.v_page_count'];
$ic = $mem['vm.stats.vm.v_inactive_count'];
$cc = $mem['vm.stats.vm.v_cache_count'];
$fc = $mem['vm.stats.vm.v_free_count'];
$result['memory']['total'] = $mem['hw.physmem'];
$result['memory']['total_frmt'] = sprintf('%d', $mem['hw.physmem'] / 1024 / 1024);
$result['memory']['used'] = round(((($pc - ($ic + $cc + $fc))) / $pc) * $mem['hw.physmem'], 0);
$result['memory']['used_frmt'] = sprintf('%d', $result['memory']['used'] / 1024 / 1024);
if (!empty($mem['kstat.zfs.misc.arcstats.size'])) {
$arc_size = $mem['kstat.zfs.misc.arcstats.size'];
$result['memory']['arc'] = $arc_size;
$result['memory']['arc_frmt'] = sprintf('%d', $arc_size / 1024 / 1024);
$result['memory']['arc_txt'] = sprintf(gettext('ARC size %d MB'), $arc_size / 1024 / 1024);
}
} else {
$result['memory']['used'] = gettext('N/A');
}
return $result;
}
public function systemDiskAction()
{
$result = [];
$disk_info = json_decode((new Backend())->configdRun('system diag disk'), true);
if (!empty($disk_info['storage-system-information'])) {
foreach ($disk_info['storage-system-information']['filesystem'] as $fs) {
if (!in_array(trim($fs['type']), ['cd9660', 'msdosfs', 'tmpfs', 'ufs', 'zfs'])) {
continue;
}
$result['devices'][] = [
'device' => $fs['name'],
'type' => trim($fs['type']),
'blocks' => $fs['blocks'],
'used' => $fs['used'],
'available' => $fs['available'],
'used_pct' => $fs['used-percent'],
'mountpoint' => $fs['mounted-on'],
];
}
}
return $result;
}
public function systemMbufAction()
{
return json_decode((new Backend())->configdRun('system show mbuf'), true);
}
public function systemSwapAction()
{
return json_decode((new Backend())->configdRun('system show swapinfo'), true);
}
public function systemTemperatureAction()
{
$result = [];
foreach (explode("\n", (new Backend())->configdRun('system temp')) as $temp) {
$parts = explode('=', $temp);
if (count($parts) >= 2) {
$tempItem = array();
$tempItem['device'] = $parts[0];
$tempItem['device_seq'] = filter_var($tempItem['device'], FILTER_SANITIZE_NUMBER_INT);
$tempItem['temperature'] = trim(str_replace('C', '', $parts[1]));
$tempItem['type'] = strpos($tempItem['device'], 'hw.acpi') !== false ? "zone" : "core";
$tempItem['type_translated'] = $tempItem['type'] == "zone" ? gettext("Zone") : gettext("Core");
$result[] = $tempItem;
}
}
return $result;
}
}

View File

@ -12,6 +12,9 @@
<name>Lobby: Login / Logout / Dashboard</name>
<patterns>
<pattern>index.php*</pattern>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/systemInformation</pattern>
</patterns>
</page-system-login-logout>
<page-getserviceproviders>
@ -51,43 +54,98 @@
<name>Dashboard (all)</name>
<patterns>
<pattern>index.php*</pattern>
<pattern>widgets/widgets/*.widget.php*</pattern>
<pattern>widgets/api/get.php*</pattern>
<pattern>ui/core/dashboard</pattern>
<pattern>ui/js/widgets/*</pattern>
<pattern>ui/core/dashboard*</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/diagnostics/dns/reverse_lookup*</pattern>
<pattern>api/routes/gateway/status*</pattern>
<pattern>api/diagnostics/interface/get_vip_status</pattern>
<pattern>api/diagnostics/cpu_usage/*</pattern>
<pattern>api/diagnostics/firewall/streamLog</pattern>
<pattern>api/diagnostics/interface/getInterfaceNames</pattern>
<pattern>api/diagnostics/firewall/log</pattern>
<pattern>api/diagnostics/firewall/pf_states</pattern>
<pattern>api/routes/gateway/status</pattern>
<pattern>api/interfaces/overview/interfacesInfo</pattern>
<pattern>api/diagnostics/traffic/*</pattern>
<pattern>api/diagnostics/system/systemDisk</pattern>
<pattern>api/diagnostics/system/system_mbuf</pattern>
<pattern>api/diagnostics/system/systemResources</pattern>
<pattern>api/diagnostics/system/system_swap</pattern>
<pattern>api/diagnostics/system/systemInformation</pattern>
<pattern>api/diagnostics/system/systemTemperature</pattern>
<pattern>api/monit/status/get/xml</pattern>
<pattern>api/diagnostics/traffic/interface</pattern>
<pattern>api/diagnostics/log/core/*</pattern>
<pattern>api/ipsec/connections/*</pattern>
<pattern>api/ipsec/leases/*</pattern>
<pattern>api/ipsec/sessions/*</pattern>
</patterns>
</page-dashboard-all>
<page-dashboard-widgets>
<name>Dashboard (widgets only)</name>
<patterns>
<pattern>widgets/widgets/*.widget.php*</pattern>
<pattern>api/routes/gateway/status*</pattern>
<pattern>api/diagnostics/interface/getInterfaceNames</pattern>
<pattern>api/diagnostics/firewall/log</pattern>
<pattern>api/monit/status/get/xml</pattern>
</patterns>
</page-dashboard-widgets>
<page-dashboard-widget-interfaces>
<name>Dashboard: Interfaces overview widget</name>
<!--
Below are some sidgets that don't fully belong to existing components, if anyone asks to grant access
to specific users for these, it might be better to debate what is really needed besides the existing
dashboard-all role (e.g. dasboard-informational as role to goup these might also work for example).
<page-dashboard-widget-system-information>
<name>Dashboard: System Information widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/interfaces/overview/*</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/diagnostics/system/systemInformation</pattern>
</patterns>
</page-dashboard-widget-interfaces>
</page-dashboard-widget-system-information>
<page-dashboard-widget-cpu>
<name>Dashboard: CPU Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/diagnostics/cpu_usage/*</pattern>
</patterns>
</page-dashboard-widget-cpu>
<page-dashboard-widget-disk>
<name>Dashboard: Disk Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/systemDisk</pattern>
</patterns>
</page-dashboard-widget-disk>
<page-dashboard-widget-firewallstates>
<name>Dashboard: Firewall States Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/diagnostics/firewall/pf_states</pattern>
</patterns>
</page-dashboard-widget-firewallstates>
<page-dashboard-widget-mbuf>
<name>Dashboard: Mbuf Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/system_mbuf</pattern>
</patterns>
</page-dashboard-widget-mbuf>
<page-dashboard-widget-memory>
<name>Dashboard: Memory Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/systemResources</pattern>
</patterns>
</page-dashboard-widget-memory>
<page-dashboard-widget-swap>
<name>Dashboard: Swap Usage widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/system_swap</pattern>
</patterns>
</page-dashboard-widget-swap>
<page-dashboard-widget-thermal-sensors>
<name>Dashboard: Thermal Sensors widget</name>
<patterns>
<pattern>ui/core/dashboard</pattern>
<pattern>api/core/dashboard/*</pattern>
<pattern>api/core/system/systemTemperature</pattern>
</patterns>
</page-dashboard-widget-thermal-sensors> -->
<page-diagnostics-authentication>
<name>Diagnostics: Authentication</name>
<patterns>
@ -315,6 +373,7 @@
<name>Diagnostics: Logs: Firewall: Live View</name>
<patterns>
<pattern>ui/diagnostics/firewall/log*</pattern>
<pattern>api/diagnostics/firewall/streamLog</pattern>
<pattern>api/diagnostics/firewall/log*</pattern>
<pattern>api/diagnostics/interface/getInterfaceNames*</pattern>
<pattern>api/diagnostics/dns/reverse_lookup*</pattern>
@ -607,6 +666,7 @@
<patterns>
<pattern>ui/routing/configuration</pattern>
<pattern>api/routing/settings/*</pattern>
<pattern>api/routes/gateway/status</pattern>
</patterns>
</page-system-gateways>
<page-system-gatewaygroups>

View File

@ -1,16 +1,15 @@
<menu>
<Lobby order="10" cssClass="fa fa-laptop">
<Dashboard order="0" url="/index.php" cssClass="fa fa-dashboard fa-fw">
<Dashboard order="0" url="/ui/core/dashboard" cssClass="fa fa-dashboard fa-fw">
<Args url="/index.php*" visibility="hidden"/>
<Root url="/" visibility="hidden"/>
<RootArgs url="/?*" visibility="hidden"/>
</Dashboard>
<Dashboard_new order="1" VisibleName="Dashboard [new]" url="/ui/core/dashboard" cssClass="fa fa-dashboard fa-fw"/>
<License order="2" url="/ui/core/license" cssClass="fa fa-balance-scale fa-fw"/>
<Password order="3" url="/system_usermanager_passwordmg.php" cssClass="fa fa-key fa-fw">
<License order="1" url="/ui/core/license" cssClass="fa fa-balance-scale fa-fw"/>
<Password order="2" url="/system_usermanager_passwordmg.php" cssClass="fa fa-key fa-fw">
<Edit url="/system_usermanager_passwordmg.php*" visibility="hidden"/>
</Password>
<Logout order="4" url="/index.php?logout" cssClass="fa fa-sign-out fa-fw"/>
<Logout order="3" url="/index.php?logout" cssClass="fa fa-sign-out fa-fw"/>
</Lobby>
<Reporting order="15" cssClass="fa fa-area-chart">
<Settings order="10" url="/reporting_settings.php" cssClass="fa fa-cog fa-fw"/>

View File

@ -152,7 +152,7 @@ export default class Disk extends BaseGaugeWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/systemDisk');
const data = await this.ajaxGet('/api/diagnostics/system/systemDisk');
if (data.devices !== undefined) {
let set = this.detailed_chart.config.data;
let init = set.labels.length === 0;

View File

@ -41,7 +41,7 @@ export default class Mbuf extends BaseGaugeWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/system_mbuf');
const data = await this.ajaxGet('/api/diagnostics/system/system_mbuf');
let current = parseInt(data['mbuf-statistics']['cluster-total']);
let limit = parseInt(data['mbuf-statistics']['cluster-max']);
super.updateChart([current, (limit - current)]);

View File

@ -50,7 +50,7 @@ export default class Memory extends BaseGaugeWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/systemResources');
const data = await this.ajaxGet('/api/diagnostics/system/systemResources');
if (data.memory.total !== undefined) {
let used = parseInt(data.memory.used_frmt);
let arc = data.memory.hasOwnProperty('arc') ? parseInt(data.memory.arc_frmt) : 0;

View File

@ -12,7 +12,7 @@
<systeminformation>
<filename>SystemInformation.js</filename>
<endpoints>
<endpoint>/api/core/system/systemInformation</endpoint>
<endpoint>/api/diagnostics/system/systemInformation</endpoint>
</endpoints>
<translations>
<title>System Information</title>
@ -27,7 +27,7 @@
<interfaces>
<filename>Interfaces.js</filename>
<endpoints>
<endpoint>/api/interfaces/overview/*</endpoint>
<endpoint>/api/interfaces/overview/interfacesInfo</endpoint>
</endpoints>
<translations>
<title>Interfaces</title>
@ -49,7 +49,7 @@
<interfacestatistics>
<filename>InterfaceStatistics.js</filename>
<endpoints>
<endpoint>/api/interfaces/statistics/*</endpoint>
<endpoint>/api/diagnostics/traffic/interface</endpoint>
</endpoints>
<translations>
<title>Interface Statistics</title>
@ -76,7 +76,7 @@
<memory>
<filename>Memory.js</filename>
<endpoints>
<endpoint>/api/core/system/systemResources</endpoint>
<endpoint>/api/diagnostics/system/systemResources</endpoint>
</endpoints>
<translations>
<title>Memory usage</title>
@ -88,7 +88,7 @@
<disk>
<filename>Disk.js</filename>
<endpoints>
<endpoint>/api/core/system/systemDisk</endpoint>
<endpoint>/api/diagnostics/system/systemDisk</endpoint>
</endpoints>
<translations>
<title>Disk usage</title>
@ -133,7 +133,7 @@
<mbuf>
<filename>Mbuf.js</filename>
<endpoints>
<endpoint>/api/core/system/system_mbuf</endpoint>
<endpoint>/api/diagnostics/system/system_mbuf</endpoint>
</endpoints>
<translations>
<title>Mbuf Usage</title>
@ -144,7 +144,7 @@
<swap>
<filename>Swap.js</filename>
<endpoints>
<endpoint>/api/core/system/system_swap</endpoint>
<endpoint>/api/diagnostics/system/system_swap</endpoint>
</endpoints>
<translations>
<title>Swap Usage</title>
@ -180,7 +180,7 @@
<thermalsensors>
<filename>ThermalSensors.js</filename>
<endpoints>
<endpoint>/api/core/system/systemTemperature</endpoint>
<endpoint>/api/diagnostics/system/systemTemperature</endpoint>
</endpoints>
<translations>
<title>Thermal Sensors</title>
@ -215,7 +215,7 @@
<livelog>
<filename>LiveLog.js</filename>
<endpoints>
<endpoint>/api/diagnostics/log/*</endpoint>
<endpoint>/api/diagnostics/log/core/*</endpoint>
</endpoints>
<translations>
<title>Live Log</title>
@ -228,7 +228,8 @@
<ipsecleases>
<filename>IpsecLeases.js</filename>
<endpoints>
<endpoint>/api/ipsec/*</endpoint>
<endpoint>/api/ipsec/connections/*</endpoint>
<endpoint>/api/ipsec/leases/*</endpoint>
</endpoints>
<translations>
<title>IPsec Leases</title>
@ -242,7 +243,8 @@
<ipsectunnels>
<filename>IpsecTunnels.js</filename>
<endpoints>
<endpoint>/api/ipsec/*</endpoint>
<endpoint>/api/ipsec/connections/*</endpoint>
<endpoint>/api/ipsec/sessions/*</endpoint>
</endpoints>
<translations>
<title>IPsec Tunnels</title>

View File

@ -42,14 +42,13 @@ export default class Swap extends BaseGaugeWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/system_swap');
const data = await this.ajaxGet('/api/diagnostics/system/system_swap');
let total = 0;
let used = 0;
for (const swapDevice of data['swap']) {
total += parseInt(swapDevice.total);
used += parseInt(swapDevice.used);
}
super.updateChart([(used / 1024), (total - used) / 1024]);
}
}

View File

@ -42,14 +42,14 @@ export default class SystemInformation extends BaseTableWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/systemTime');
const data = await this.ajaxGet('/api/diagnostics/system/systemTime');
$('#datetime').text(data['datetime']);
$('#uptime').text(data['uptime']);
$('#config').text(data['config']);
}
async onMarkupRendered() {
const data = await this.ajaxGet('/api/core/system/systemInformation');
const data = await this.ajaxGet('/api/diagnostics/system/systemInformation');
let rows = [];
for (let [key, value] of Object.entries(data)) {
if (!key in this.translations) {

View File

@ -179,7 +179,7 @@ export default class ThermalSensors extends BaseWidget {
}
async onWidgetTick() {
const data = await this.ajaxGet('/api/core/system/systemTemperature');
const data = await this.ajaxGet('/api/diagnostics/system/systemTemperature');
if (!data || !data.length) {
$(`.${this.id}-chart-container`).html(`
<a href="/system_advanced_misc.php">${this.translations.unconfigured}</a>

View File

@ -30,404 +30,73 @@
require_once('guiconfig.inc');
// if no config entry found, initialize config entry
config_read_array('widgets');
$widgetCollection = array();
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = $config['widgets'];
legacy_html_escape_form_data($pconfig);
// set default dashboard view
$pconfig['sequence'] = !empty($pconfig['sequence']) ? $pconfig['sequence'] : '';
$pconfig['column_count'] = !empty($pconfig['column_count']) ? $pconfig['column_count'] : 2;
// build list of widgets
$widgetSeqParts = explode(",", $pconfig['sequence']);
foreach (glob('/usr/local/www/widgets/widgets/*.widget.php') as $php_file) {
$widgetItem = array();
$widgetItem['name'] = basename($php_file, '.widget.php');
$widgetItem['display_name'] = ucwords(str_replace("_", " ", $widgetItem['name']));
$widgetItem['filename'] = $php_file;
$widgetItem['state'] = "none";
/// default sort order
$widgetItem['sortKey'] = $widgetItem['name'] == 'system_information' ? "00000000" : "99999999" . $widgetItem['name'];
foreach ($widgetSeqParts as $seqPart) {
$tmp = explode(':', $seqPart);
if (count($tmp) == 3 && explode('-', $tmp[0])[0] == $widgetItem['name']) {
$widgetItem['state'] = $tmp[2];
$widgetItem['sortKey'] = $tmp[1];
}
}
$widgetCollection[] = $widgetItem;
}
// sort widgets
usort($widgetCollection, function ($item1, $item2) {
return strcmp(strtolower($item1['sortKey']), strtolower($item2['sortKey']));
});
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['origin']) && $_POST['origin'] == 'dashboard') {
if (!empty($_POST['sequence'])) {
$config['widgets']['sequence'] = $_POST['sequence'];
} elseif (isset($config['widgets']['sequence'])) {
unset($config['widgets']['sequence']);
}
if (!empty($_POST['column_count'])) {
$config['widgets']['column_count'] = filter_var($_POST['column_count'], FILTER_SANITIZE_NUMBER_INT);
} elseif(isset($config['widgets']['column_count'])) {
unset($config['widgets']['column_count']);
}
write_config('Widget configuration has been changed');
header(url_safe('Location: /index.php'));
exit;
}
// handle widget includes
foreach (glob("/usr/local/www/widgets/include/*.inc") as $filename) {
include($filename);
}
$product = product::getInstance();
include("head.inc");
?>
<body>
<?php
include("fbegin.inc");?>
<?php
?>
<?php
if (isset($config['trigger_initial_wizard']) || isset($_GET['wizard_done'])): ?>
<script>
$( document ).ready(function() {
$(".page-content-head:first").hide();
});
</script>
<header class="page-content-head">
<div class="container-fluid">
<?php
if (isset($config['trigger_initial_wizard'])): ?>
<h1><?= gettext("Starting initial configuration!") ?></h1>
<?php
else: ?>
<h1><?= gettext("Finished initial configuration!") ?></h1>
<?php
endif ?>
</div>
</header>
<section class="page-content-main">
<div class="container-fluid col-xs-12 col-sm-10 col-md-9">
<div class="row">
<section class="col-xs-12">
<div class="content-box wizard" style="padding: 20px;">
<div class="table-responsive">
<?php if (get_themed_filename('/images/default-logo.svg', true)): ?>
<img src="<?= cache_safe(get_themed_filename('/images/default-logo.svg')) ?>" border="0" alt="logo" style="max-width:380px;" />
<?php else: ?>
<img src="<?= cache_safe(get_themed_filename('/images/default-logo.png')) ?>" border="0" alt="logo" style="max-width:380px;" />
<?php endif ?>
<br />
<div class="content-box-main" style="padding-bottom:0px;">
<?php
if (isset($config['trigger_initial_wizard'])) {
echo '<p>' . sprintf(gettext('Welcome to %s!'), $product->name()) . "</p>\n";
echo '<p>' . gettext('One moment while we start the initial setup wizard.') . "</p>\n";
echo '<p class="__nomb">' . gettext('To bypass the wizard, click on the logo in the upper left corner.') . "</p>\n";
} else {
echo '<p>' . sprintf(gettext('Congratulations! %s is now configured.'), $product->name()) . "</p>\n";
echo '<p>' . sprintf(gettext(
'Please consider donating to the project to help us with our overhead costs. ' .
'See %sour website%s to donate or purchase available %s support services.'),
'<a target="_new" href="' . $product->website() . '">', '</a>', $product->name()) . "</p>\n";
echo '<p class="__nomb">' . sprintf(gettext('Click to %scontinue to the dashboard%s.'), '<a href="/">', '</a>') . ' ';
echo sprintf(gettext('Or click to %scheck for updates%s.'), '<a href="/ui/core/firmware#checkupdate">', '</a>'). "</p>\n";
}
?>
</div>
<div>
</div>
</section>
if (isset($config['trigger_initial_wizard']) || isset($_GET['wizard_done'])):
include("head.inc");
?>
<body>
<?php
include("fbegin.inc");
if (isset($config['trigger_initial_wizard']) || isset($_GET['wizard_done'])): ?>
<script>
$( document ).ready(function() {
$(".page-content-head:first").hide();
});
</script>
<header class="page-content-head">
<div class="container-fluid">
<?php
if (isset($config['trigger_initial_wizard'])): ?>
<h1><?= gettext("Starting initial configuration!") ?></h1>
<?php
else: ?>
<h1><?= gettext("Finished initial configuration!") ?></h1>
<?php
endif ?>
</div>
</div>
</section>
<?php
if (isset($config['trigger_initial_wizard'])): ?>
<meta http-equiv="refresh" content="5;url=/wizard.php?xml=system">
<?php
endif ?>
<?php
// normal dashboard
else:?>
<script src="<?= cache_safe('/ui/js/jquery-sortable.js') ?>"></script>
<script>
function addWidget(selectedDiv) {
$('#'+selectedDiv).show();
$('#add_widget_'+selectedDiv).hide();
$('#'+selectedDiv+'-config').val('show');
showSave();
}
function configureWidget(selectedDiv) {
let selectIntLink = '#' + selectedDiv + "-settings";
if ($(selectIntLink).css('display') == "none") {
$(selectIntLink).show();
} else {
$(selectIntLink).hide();
}
}
function showWidget(selectedDiv,swapButtons) {
$('#'+selectedDiv+'-container').show();
$('#'+selectedDiv+'-min').show();
$('#'+selectedDiv+'-max').hide();
$('#'+selectedDiv+'-config').val('show');
showSave();
}
function minimizeWidget(selectedDiv, swapButtons) {
$('#'+selectedDiv+'-container').hide();
$('#'+selectedDiv+'-min').hide();
$('#'+selectedDiv+'-max').show();
$('#'+selectedDiv+'-config').val('hide');
showSave();
}
function closeWidget(selectedDiv) {
$('#'+selectedDiv).hide();
$('#'+selectedDiv+'-config').val('close');
showSave();
}
function showSave() {
$('#updatepref').show();
}
function updatePref() {
var widgetInfo = [];
var index = 0;
$('.widgetdiv').each(function(key) {
if ($(this).is(':visible')) {
// only capture visible widgets
var index_str = "0000000" + index;
index_str = index_str.substr(index_str.length-8);
let col_index = $(this).parent().attr("id").split('_')[1];
widgetInfo.push($(this).attr('id')+'-container:'+index_str+'-'+col_index+':'+$('input[name='+$(this).attr('id')+'-config]').val());
index++;
}
});
$("#sequence").val(widgetInfo.join(','));
$("#iform").submit();
return false;
}
/**
* ajax update widget data, searches data-plugin attributes and use function in data-callback to update widget
*/
function process_widget_data()
{
var plugins = [];
var callbacks = [];
// collect plugins and callbacks
$("[data-plugin]").each(function(){
if (plugins.indexOf($(this).data('plugin')) < 0) {
plugins.push($(this).data('plugin'));
}
if ($(this).data('callback') != undefined) {
callbacks.push({'function' : $(this).data('callback'), 'plugin': $(this).data('plugin'), 'sender': $(this)});
}
});
// collect data for provided plugins
$.ajax("/widgets/api/get.php",{type: 'get', cache: false, dataType: "json", data: {'load': plugins.join(',')}})
.done(function(response) {
callbacks.map( function(callback) {
try {
if (response['data'][callback['plugin']] != undefined) {
window[callback['function']](callback['sender'], response['data'][callback['plugin']]);
}
} catch (err) {
console.log(err);
}
});
// schedule next update
setTimeout('process_widget_data()', 5000);
});
}
</script>
<script>
$( document ).ready(function() {
// rearrange widgets to stored column
$(".widgetdiv").each(function(){
var widget = $(this);
widget.find('script').each(function(){
$(this).remove();
});
var container = $(this).parent();
var target_col = widget.data('sortkey').split('-')[1];
if (target_col != undefined) {
if (container.attr('id').split('_')[1] != target_col) {
widget.remove().appendTo("#dashboard_"+target_col);
}
} else {
// dashboard_colx (source) is not visible, move other items to col4
widget.remove().appendTo("#dashboard_col4");
}
});
// show dashboard widgets after initial rendering
$("#dashboard_container").show();
// trigger WidgetsReady event
$("#dashboard_container").trigger("WidgetsReady");
// sortable widgets
$(".dashboard_grid_column").sortable({
handle: '.widget-sort-handle',
group: 'dashboard_grid_column',
itemSelector: '.widgetdiv',
containerSelector: '.dashboard_grid_column',
placeholder: '<div class="placeholder"><i class="fa fa-hand-o-right" aria-hidden="true"></i></div>',
afterMove: function (placeholder, container, closestItemOrContainer) {
showSave();
}
});
// select number of columns
$("#column_count").change(function(){
if ($("#column_count_input").val() != $("#column_count").val()) {
showSave();
}
$("#column_count_input").val($("#column_count").val());
$(".dashboard_grid_column").each(function(){
var widget_col = $(this);
$.each(widget_col.attr("class").split(' '), function(index, classname) {
if (classname.indexOf('col-md') > -1) {
widget_col.removeClass(classname);
}
});
widget_col.addClass('col-md-'+(12 / $("#column_count_input").val()));
});
});
$("#column_count").change();
// trigger initial ajax data poller
process_widget_data();
// in "Add Widget" dialog, hide widgets already on screen
$("#add_widget_btn").click(function(){
$(".widgetdiv").each(function(widget){
if ($(this).is(':visible')) {
$("#add_widget_" + $(this).attr('id')).hide();
} else {
$("#add_widget_" + $(this).attr('id')).show();
}
});
});
$('.selectpicker_widget').selectpicker('refresh');
});
</script>
<section class="page-content-main">
<form method="post" id="iform">
<input type="hidden" value="dashboard" name="origin" id="origin" />
<input type="hidden" value="" name="sequence" id="sequence" />
<input type="hidden" value="<?= $pconfig['column_count'];?>" name="column_count" id="column_count_input" />
</form>
<div class="container-fluid">
<div class="row">
<div class="col-md-12 col-xs-12">
<?php print_service_banner('bootup') ?>
<?php print_service_banner('livecd') ?>
</div>
</div>
<div id="dashboard_container" class="row" style="display:none">
<div class="col-xs-12 col-md-2 dashboard_grid_column hidden" id="dashboard_colx">
<?php
foreach ($widgetCollection as $widgetItem):
$widgettitle = $widgetItem['name'] . "_title";
$widgettitlelink = $widgetItem['name'] . "_title_link";
switch ($widgetItem['state']) {
case "show":
$divdisplay = "block";
$display = "block";
$inputdisplay = "show";
$mindiv = "inline";
break;
case "hide":
$divdisplay = "block";
$display = "none";
$inputdisplay = "hide";
$mindiv = "none";
break;
case "close":
$divdisplay = "none";
$display = "block";
$inputdisplay = "close";
$mindiv = "inline";
break;
default:
$divdisplay = "none";
$display = "block";
$inputdisplay = "none";
$mindiv = "inline";
break;
}?>
<section class="widgetdiv" data-sortkey="<?=$widgetItem['sortKey'] ?>" id="<?=$widgetItem['name'];?>" style="display:<?=$divdisplay;?>;">
<div class="content-box">
<header class="content-box-head container-fluid">
<ul class="list-inline __nomb">
<li><h3>
<?php
// XXX: ${$} is intentional here, the widgets leave global vars [widget_name]_title_link and [widget_name]_title
if (isset(${$widgettitlelink})):?>
<u><span onclick="location.href='/<?= html_safe(${$widgettitlelink}) ?>'" style="cursor:pointer">
<?php
endif;
echo empty(${$widgettitle}) ? $widgetItem['display_name'] : ${$widgettitle};
if (isset(${$widgettitlelink})):?>
</span></u>
<?php
endif;?>
</h3></li>
<li class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs disabled" id="<?= $widgetItem['name'] ?>-configure" onclick='return configureWidget("<?= $widgetItem['name'] ?>")' style="cursor:pointer"><i class="fa fa-pencil fa-fw"></i></button>
<button type="button" class="btn btn-default btn-xs" title="minimize" id="<?= $widgetItem['name'] ?>-min" onclick='return minimizeWidget("<?= $widgetItem['name'] ?>",true)' style="display:<?= $mindiv ?>;"><i class="fa fa-minus fa-fw"></i></button>
<button type="button" class="btn btn-default btn-xs" title="maximize" id="<?= $widgetItem['name'] ?>-max" onclick='return showWidget("<?= $widgetItem['name'] ?>",true)' style="display:<?= $mindiv == 'none' ? 'inline' : 'none' ?>;"><i class="fa fa-plus fa-fw"></i></button>
<button type="button" class="btn btn-default btn-xs" title="remove widget" onclick='return closeWidget("<?= $widgetItem['name'] ?>",true)'><i class="fa fa-remove fa-fw"></i></button>
</div>
</li>
</ul>
<div class="container-fluid widget-sort-handle">
</header>
<section class="page-content-main">
<div class="container-fluid col-xs-12 col-sm-10 col-md-9">
<div class="row">
<section class="col-xs-12">
<div class="content-box wizard" style="padding: 20px;">
<div class="table-responsive">
<?php if (get_themed_filename('/images/default-logo.svg', true)): ?>
<img src="<?= cache_safe(get_themed_filename('/images/default-logo.svg')) ?>" border="0" alt="logo" style="max-width:380px;" />
<?php else: ?>
<img src="<?= cache_safe(get_themed_filename('/images/default-logo.png')) ?>" border="0" alt="logo" style="max-width:380px;" />
<?php endif ?>
<br />
<div class="content-box-main" style="padding-bottom:0px;">
<?php
if (isset($config['trigger_initial_wizard'])) {
echo '<p>' . sprintf(gettext('Welcome to %s!'), $product->name()) . "</p>\n";
echo '<p>' . gettext('One moment while we start the initial setup wizard.') . "</p>\n";
echo '<p class="__nomb">' . gettext('To bypass the wizard, click on the logo in the upper left corner.') . "</p>\n";
} else {
echo '<p>' . sprintf(gettext('Congratulations! %s is now configured.'), $product->name()) . "</p>\n";
echo '<p>' . sprintf(gettext(
'Please consider donating to the project to help us with our overhead costs. ' .
'See %sour website%s to donate or purchase available %s support services.'),
'<a target="_new" href="' . $product->website() . '">', '</a>', $product->name()) . "</p>\n";
echo '<p class="__nomb">' . sprintf(gettext('Click to %scontinue to the dashboard%s.'), '<a href="/">', '</a>') . ' ';
echo sprintf(gettext('Or click to %scheck for updates%s.'), '<a href="/ui/core/firmware#checkupdate">', '</a>'). "</p>\n";
}
?>
</div>
</header>
<div class="content-box-main collapse in" id="<?= $widgetItem['name'] ?>-container" style="display:<?= $mindiv ?>">
<input type="hidden" value="<?= $inputdisplay ?>" id="<?= $widgetItem['name'] ?>-config" name="<?= $widgetItem['name'] ?>-config" />
<?php
if ($divdisplay != "block"):?>
<div id="<?= $widgetItem['name'] ?>-loader" style="display:<?= $display ?>;">
&nbsp;&nbsp;<i class="fa fa-refresh"></i> <?= gettext("Save to load widget") ?>
</div>
<?php
else:
include($widgetItem['filename']);
endif;
?>
</div>
<div>
</div>
</section>
<?php
endforeach;?>
</div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col1"></div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col2"></div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col3"></div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col4"></div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col5"></div>
<div class="col-md-2 dashboard_grid_column" id="dashboard_col6"></div>
</div>
</div>
</div>
</section>
<?php endif;
include("foot.inc");
</section>
<?php
if (isset($config['trigger_initial_wizard'])): ?>
<meta http-equiv="refresh" content="5;url=/wizard.php?xml=system">
<?php endif ;
include("foot.inc"); endif;
else:
header('Location: /ui/core/dashboard');
exit;
endif;

View File

@ -1,76 +0,0 @@
<?php
/*
Copyright (C) 2016 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.
*/
/*
Simple wrapper to retrieve data for widgets using legacy code.
Returns a json object containing a list of available plugins and for all requested plugins (parameter load) the
collected data.
*/
header("Content-Type: application/json");
header("Last-Modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
header("Expires: " . gmdate( "D, j M Y H:i:s", time() ) . " GMT" );
header("Cache-Control: no-store, no-cache, must-revalidate" );
header("Cache-Control: post-check=0, pre-check=0", FALSE);
header("Pragma: no-cache");
require_once("guiconfig.inc");
// require legacy scripts, so plugins don't have to load them
require_once("system.inc");
require_once("config.inc");
require_once("filter.inc");
require_once("interfaces.inc");
// parse request, load parameter contains all plugins that should be loaded for this request
if (!empty($_REQUEST['load'])) {
$loadPluginsList = explode(',', $_REQUEST['load']);
} else {
$loadPluginsList = [];
}
// add metadata
$result['system'] = product::getInstance()->name();
// available plugins
$result['plugins'] = [];
// collected data
$result['data'] = [];
// probe plugins
foreach (glob(__DIR__."/plugins/*.inc") as $filename) {
$pluginName = basename($filename, '.inc');
$result['plugins'][] = $pluginName;
if (in_array($pluginName, $loadPluginsList)) {
require $filename;
$pluginFunctionName = $pluginName."_api";
if (function_exists($pluginName."_api")) {
$result['data'][$pluginName] = $pluginFunctionName();
}
}
}
// output result
legacy_html_escape_form_data($result);
echo json_encode($result);

View File

@ -1,222 +0,0 @@
<?php
/*
* Copyright (C) 2016 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.
*/
function system_api_cpu_stats()
{
$cpustats = array();
// take a short snapshot to calculate cpu usage
$diff = array('user', 'nice', 'sys', 'intr', 'idle');
$cpuTicks1 = array_combine($diff, array_slice(explode(" ", get_single_sysctl('kern.cp_time')),0, 5));
usleep(100000);
$cpuTicks2 = array_combine($diff, array_slice(explode(" ", get_single_sysctl('kern.cp_time')),0, 5));
$totalStart = array_sum($cpuTicks1);
$totalEnd = array_sum($cpuTicks2);
if ($totalEnd <= $totalStart) {
// if for some reason the measurement is invalid, assume nothing has changed (all 0)
$totalEnd = $totalStart;
}
$totalDiff = $totalEnd - $totalStart;
if ($totalDiff != 0) {
$cpustats['used'] = floor(100 * ($totalDiff - ($cpuTicks2['idle'] - $cpuTicks1['idle'])) / $totalDiff);
$cpustats['user'] = floor(100 * (($cpuTicks2['user'] - $cpuTicks1['user'])) / $totalDiff);
$cpustats['nice'] = floor(100 * (($cpuTicks2['nice'] - $cpuTicks1['nice'])) / $totalDiff);
$cpustats['sys'] = floor(100 * (($cpuTicks2['sys'] - $cpuTicks1['sys'])) / $totalDiff);
$cpustats['intr'] = floor(100 * (($cpuTicks2['intr'] - $cpuTicks1['intr'])) / $totalDiff);
$cpustats['idle'] = floor(100 * (($cpuTicks2['idle'] - $cpuTicks1['idle'])) / $totalDiff);
} else {
$cpustats['used'] = "0";
$cpustats['user'] = "0";
$cpustats['nice'] = "0";
$cpustats['sys'] = "0";
$cpustats['intr'] = "0";
$cpustats['idle'] = "0";
}
// cpu model and count
$cpustats['model'] = get_single_sysctl('hw.model');
$cpustats['cpus'] = get_single_sysctl('kern.smp.cpus');
$cpustats['cores'] = get_single_sysctl('kern.smp.cores');
// cpu frequency
$tmp = get_single_sysctl('dev.cpu.0.freq_levels');
$cpustats['max.freq'] = !empty($tmp) ? explode("/", explode(" ", $tmp)[0])[0] : "-";
$tmp = get_single_sysctl('dev.cpu.0.freq');
$cpustats['cur.freq'] = !empty($tmp) ? $tmp : "-";
$cpustats['freq_translate'] = sprintf(gettext("Current: %s MHz, Max: %s MHz"), $cpustats['cur.freq'], $cpustats['max.freq']);
// system load
exec("/usr/bin/uptime | /usr/bin/sed 's/^.*: //'", $load_average);
$cpustats['load'] = explode(',', $load_average[0]);
return $cpustats;
}
function system_api_config()
{
global $config;
$result = array();
$result['last_change'] = isset($config['revision']['time']) ? intval($config['revision']['time']) : 0;
$result['last_change_frmt'] = date("D M j G:i:s T Y", $result['last_change']);
return $result;
}
function system_api_kernel()
{
global $config;
$result = array();
$result['pf'] = array();
$result['pf']['maxstates'] = !empty($config['system']['maximumstates']) ? $config['system']['maximumstates'] : default_state_size();
exec('/sbin/pfctl -si |grep "current entries" 2>/dev/null', $states);
$result['pf']['states'] = count($states) > 0 ? filter_var($states[0], FILTER_SANITIZE_NUMBER_INT) : 0;
$result['mbuf'] = array();
exec('/usr/bin/netstat -mb | /usr/bin/grep "mbuf clusters in use"', $mbufs);
$result['mbuf']['total'] = count($mbufs) > 0 ? explode('/', $mbufs[0])[2] : 0;
$result['mbuf']['max'] = count($mbufs) > 0 ? explode(' ', explode('/', $mbufs[0])[3])[0] : 0;
$totalMem = get_single_sysctl("vm.stats.vm.v_page_count");
$inactiveMem = get_single_sysctl("vm.stats.vm.v_inactive_count");
$cachedMem = get_single_sysctl("vm.stats.vm.v_cache_count");
$freeMem = get_single_sysctl("vm.stats.vm.v_free_count");
$result['memory']['total'] = get_single_sysctl('hw.physmem');
if ($totalMem != 0) {
$result['memory']['used'] = round(((($totalMem - ($inactiveMem + $cachedMem + $freeMem))) / $totalMem)*$result['memory']['total'], 0);
$arcMem = get_single_sysctl('kstat.zfs.misc.arcstats.size');
if (!empty($arcMem)) {
$result['memory']['arc'] = $arcMem;
$result['memory']['arc_txt'] = sprintf(gettext("ARC size %d MB"), $arcMem/1024/1024);
}
} else {
$result['memory']['used'] = gettext('N/A');
}
return $result;
}
function system_api_disk()
{
$result = array();
$result['swap'] = array();
exec("/usr/sbin/swapinfo -k", $swap_info);
foreach ($swap_info as $line) {
if (strpos($line,'/dev/') !== false) {
$parts = preg_split('/\s+/', $line);
$swapItem = array();
$swapItem['device'] = $parts[0];
$swapItem['total'] = $parts[1];
$swapItem['used'] = $parts[2];
$result['swap'][] = $swapItem;
}
}
$types = [ 'cd9660', 'msdosfs', 'tmpfs', 'ufs', 'zfs' ];
$result['devices'] = [];
exec('/bin/df -ahT', $disk_info);
foreach ($disk_info as $line) {
if (strpos($line, 'Filesystem') !== 0) {
$parts = preg_split('/\s+/', $line);
$diskItem = [];
$diskItem['device'] = $parts[0];
$diskItem['type'] = $parts[1];
$diskItem['size'] = $parts[2];
$diskItem['used'] = $parts[3];
$diskItem['available'] = $parts[4];
$diskItem['capacity'] = $parts[5];
$diskItem['mountpoint'] = $parts[6];
if (in_array($diskItem['type'], $types)) {
$result['devices'][] = $diskItem;
}
}
}
return $result;
}
function system_api_versions($product)
{
$result = [];
$result[] = sprintf('%s %s-%s', $product['product_name'], $product['product_version'], $product['product_arch']);
$result[] = php_uname('s') . ' ' . php_uname('r');
$result[] = shell_safe('/usr/local/bin/openssl version | cut -f -2 -d \' \'');
if (!empty($product['product_license']['valid_to'])) {
$result[] = gettext('Licensed until') . ' ' . $product['product_license']['valid_to'];
}
return $result;
}
function system_api_firmware($product)
{
$ret = gettext('Click to check for updates.');
$current = explode('_', $product['product_version'])[0];
/* information from changelog, more accurate for production release */
$from_changelog = strpos($product['product_id'], '-devel') === false &&
!empty($product['product_latest']) &&
$product['product_latest'] != $current;
/* update status from last check, also includes major releases */
$from_check = !empty($product['product_check']['upgrade_sets']) ||
!empty($product['product_check']['downgrade_packages']) ||
!empty($product['product_check']['new_packages']) ||
!empty($product['product_check']['reinstall_packages']) ||
!empty($product['product_check']['remove_packages']) ||
!empty($product['product_check']['upgrade_packages']);
if ($from_changelog || $from_check) {
$ret = gettext('Click to view pending updates.');
}
return $ret;
}
/**
* widget system data
*/
function system_api()
{
$result = array();
$product = json_decode(configd_run('firmware product'), true);
$result['versions'] = system_api_versions($product);
$result['cpu'] = system_api_cpu_stats();
$result['date_frmt'] = date("D M j G:i:s T Y");
$result['date_time'] = time();
preg_match("/sec = (\d+)/", get_single_sysctl("kern.boottime"), $matches);
$result['uptime'] = $result['date_time'] - $matches[1];
$result['config'] = system_api_config();
$result['kernel'] = system_api_kernel();
$result['disk'] = system_api_disk();
$result['firmware'] = system_api_firmware($product);
return $result;
}

View File

@ -1,54 +0,0 @@
<?php
/*
* Copyright (C) 2016 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.
*/
/**
* widget temperature data
*/
function temperature_api()
{
$result = array();
foreach (explode("\n", configd_run('system temp')) as $sysctl) {
$parts = explode('=', $sysctl);
if (count($parts) >= 2) {
$tempItem = array();
$tempItem['device'] = $parts[0];
$tempItem['device_seq'] = filter_var($tempItem['device'], FILTER_SANITIZE_NUMBER_INT);
$tempItem['temperature'] = trim(str_replace('C', '', $parts[1]));
$tempItem['type'] = strpos($tempItem['device'], 'hw.acpi') !== false ? "zone" : "core";
$tempItem['type_translated'] = $tempItem['type'] == "zone" ? gettext("Zone") : gettext("Core");
$result[] = $tempItem;
}
}
usort($result, function ($item1, $item2) {
return strcmp(strtolower($item1['device']), strtolower($item2['device']));
});
return $result;
}

View File

@ -1,4 +0,0 @@
<?php
$carp_status_title = gettext('CARP');
$carp_status_title_link = 'ui/diagnostics/interface/vip';

View File

@ -1,4 +0,0 @@
<?php
$cpu_usage_title = gettext('CPU usage');
$cpu_usage_title_link = 'ui/diagnostics/systemhealth';

View File

@ -1,4 +0,0 @@
<?php
$gateways_title = gettext('Gateways');
$gateways_title_link = 'ui/routing/configuration';

View File

@ -1,4 +0,0 @@
<?php
$interface_list_title = gettext('Interfaces');
$interface_list_title_link = 'interfaces_assign.php';

View File

@ -1,4 +0,0 @@
<?php
$interface_statistics_title = gettext('Interface Statistics');
$interface_statistics_title_link = 'ui/interfaces/overview';

View File

@ -1,4 +0,0 @@
<?php
$ipsec_title = gettext('IPsec');
$ipsec_title_link = 'ui/ipsec/sessions';

View File

@ -1,4 +0,0 @@
<?php
$log_title = gettext('Firewall Log');
$log_title_link = 'ui/diagnostics/firewall/log';

View File

@ -1,4 +0,0 @@
<?php
$monit_title = gettext('Monit');
$monit_title_link = 'ui/monit/status';

View File

@ -1,4 +0,0 @@
<?php
$ntp_status_title = gettext('Network Time');
$ntp_status_title_link = 'status_ntpd.php';

View File

@ -1,4 +0,0 @@
<?php
$openvpn_title = gettext('OpenVPN');
$openvpn_title_link = 'ui/openvpn/status';

View File

@ -1,4 +0,0 @@
<?php
$services_status_title = gettext('Services');
$services_status_title_link = 'ui/core/service';

View File

@ -1,4 +0,0 @@
<?php
$system_log_title = gettext('System Log');
$system_log_title_link = 'ui/diagnostics/log/core/system';

View File

@ -1,4 +0,0 @@
<?php
$thermal_sensors_title = gettext('Thermal Sensors');
$thermal_sensors_title_link = 'system_advanced_misc.php';

View File

@ -1,4 +0,0 @@
<?php
$traffic_graphs_title = gettext('Traffic Graph');
$traffic_graphs_title_link = 'ui/diagnostics/traffic';

View File

@ -1,4 +0,0 @@
<?php
$wireguard_title = gettext('WireGuard');
$wireguard_title_link = 'ui/wireguard/general';

View File

@ -1,96 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2007 Sam Wenham
* 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("interfaces.inc");
config_read_array('virtualip', 'vip');
?>
<table class="table table-striped table-condensed">
<?php
$interfaces_details = legacy_interfaces_details();
foreach ($config['virtualip']['vip'] as $carp):
if ($carp['mode'] != "carp") {
continue;
}
$intf = get_real_interface($carp['interface']);
if (
!empty($interfaces_details[$intf]) && !empty($interfaces_details[$intf]['carp'][$carp['vhid']])
) {
$status = $interfaces_details[$intf]['carp'][$carp['vhid']]['status'];
} else {
$status = null;
}
?>
<tr>
<td>
<i class="fa fa-exchange fa-fw text-success"></i>
<strong>
<a href="/system_hasync.php">
<span><?=htmlspecialchars(convert_friendly_interface_to_friendly_descr($carp['interface']) . "@{$carp['vhid']}");?></span>
</a>
</strong>
</td>
<td>
<?php
if (get_single_sysctl('net.inet.carp.allow') <= 0 ) {
$status_i18n = gettext("DISABLED");
echo "<span class=\"fa fa-remove fa-fw text-danger\" title=\"$status_i18n\" ></span>";
} elseif ($status == "MASTER") {
$status_i18n = gettext("MASTER");
echo "<span class=\"fa fa-play fa-fw text-success\" title=\"$status_i18n\" ></span>";
} elseif ($status == "BACKUP") {
$status_i18n = gettext("BACKUP");
echo "<span class=\"fa fa-play fa-fw text-muted\" title=\"$status_i18n\" ></span>";
} elseif ($status == "INIT") {
$status_i18n = gettext("INIT");
echo "<span class=\"fa fa-info-circle fa-fw\" title=\"$status_i18n\" ></span>";
} else {
$status_i18n = "";
}
if (!empty($carp['subnet'])):?>
&nbsp;
<?=htmlspecialchars($status_i18n);?> &nbsp;
<?=htmlspecialchars($carp['subnet']);?>
<?php
endif;?>
</td>
</tr>
<?php
endforeach;
if (count($config['virtualip']['vip']) == 0):?>
<tr>
<td>
<?= sprintf(gettext('No CARP Interfaces Defined. Click %shere%s to configure CARP.'), '<a href="carp_status.php">', '</a>'); ?>
</td>
</tr>
<?php
endif;?>
</table>

View File

@ -1,105 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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");
?>
<script src="<?= cache_safe('/ui/js/moment-with-locales.min.js') ?>"></script>
<script>
var cpu_widget_cpu_data = []; // reference to measures
var cpu_widget_cpu_chart = null; // reference to chart object
var cpu_widget_cpu_chart_data = null; // reference to chart data object
/**
* update cpu chart
*/
function cpu_widget_cpu_update(sender, data)
{
// push new measurement, keep a maximum of 100 measures in
cpu_widget_cpu_data.push([data['date_time'] * 1000, parseInt(data['cpu']['used'])]);
if (cpu_widget_cpu_data.length > 100) {
cpu_widget_cpu_data.shift();
} else if (cpu_widget_cpu_data.length == 1) {
cpu_widget_cpu_data.push([data['date_time'] * 1000, parseInt(data['cpu']['used'])]);
}
let chart_data = [];
cpu_widget_cpu_data.map(function(item){
chart_data.push(item);
});
cpu_widget_cpu_chart_data.datum([{'key':'cpu', 'values':chart_data}]).transition().duration(500).call(cpu_widget_cpu_chart);
}
function cpu_widget_update(sender, data)
{
// update cpu usage chart
cpu_widget_cpu_update(sender, data);
$("#cpu_widget_load").html(data['cpu']['load'].join(','));
}
/**
* page setup
*/
$(window).on("load", function() {
// draw cpu graph
nv.addGraph(function() {
cpu_widget_cpu_chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.useInteractiveGuideline(false)
.interactive(true)
.showLegend(false)
.showXAxis(false)
.clipEdge(true)
.margin({top:5,right:5,bottom:5,left:25});
cpu_widget_cpu_chart.yAxis.tickFormat(d3.format('.0'));
cpu_widget_cpu_chart.xAxis.tickFormat(function(d) {
return d3.time.format('%b %e %H:%M:%S')(new Date(d));
});
cpu_widget_cpu_chart.forceY([0, 100]);
cpu_widget_cpu_chart_data = d3.select("#cpu_widget_chart_cpu_usage svg").datum([{'key':'cpu', 'values':[[0, 0]]}]);
cpu_widget_cpu_chart_data.transition().duration(500).call(cpu_widget_cpu_chart);
});
});
</script>
<table class="table table-striped table-condensed" data-plugin="system" data-callback="cpu_widget_update">
<tbody>
<tr>
<td>
<div id="cpu_widget_chart_cpu_usage">
<svg style="height:250px;"></svg>
</div>
</td>
</tr>
</tbody>
</table>

View File

@ -1,161 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2008 Seth Mos <seth.mos@dds.nl>
*
* 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");
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = array();
$pconfig['gatewaysfilter'] = !empty($config['widgets']['gatewaysfilter']) ?
explode(',', $config['widgets']['gatewaysfilter']) : array();
$pconfig['gatewaysinvert'] = !empty($config['widgets']['gatewaysinvert']) ? '1' : '';
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
if (!empty($pconfig['gatewaysfilter'])) {
$config['widgets']['gatewaysfilter'] = implode(',', $pconfig['gatewaysfilter']);
} elseif (isset($config['widgets']['gatewaysfilter'])) {
unset($config['widgets']['gatewaysfilter']);
}
if (!empty($pconfig['gatewaysinvert'])) {
$config['widgets']['gatewaysinvert'] = 1;
} elseif (isset($config['widgets']['gatewaysinvert'])) {
unset($config['widgets']['gatewaysinvert']);
}
write_config("Saved Gateways Filter via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
$gateways = (new \OPNsense\Routing\Gateways())->gatewaysIndexedByName();
?>
<script>
$(window).on("load", function() {
function fetch_gateway_statuses(){
ajaxGet('/api/routes/gateway/status', {}, function(data, status) {
if (data.items !== undefined) {
$.each(data.items, function(key, gateway) {
let $gw_item = $("#gateways_widget_gw_"+gateway.name);
if ($gw_item.length == 0) {
$gw_item = $("<tr>").attr('id', "gateways_widget_gw_"+gateway.name);
$gw_item.append($("<td/>").append(
"<small><strong>~</strong><br/><div>~</div></small>")
);
$gw_item.append($("<td class='text-nowrap'/>").text("~"));
$gw_item.append($("<td class='text-nowrap'/>").text("~"));
$gw_item.append($("<td class='text-nowrap'/>").text("~"));
$gw_item.append(
$("<td/>").append(
$("<span class='label label-default'/>").text("<?= gettext('Unknown') ?>")
)
);
$("#gateway_widget_table").append($gw_item);
$gw_item.hide();
}
$gw_item.find('td:eq(0) > small > strong').text(gateway.name);
$gw_item.find('td:eq(0) > small > div').text(gateway.address);
$gw_item.find('td:eq(1)').text(gateway.delay);
$gw_item.find('td:eq(2)').text(gateway.stddev);
$gw_item.find('td:eq(3)').text(gateway.loss);
let status_color;
switch (gateway.status) {
case 'force_down':
case 'down':
status_color = 'danger';
break;
case 'loss':
case 'delay':
case 'delay+loss':
status_color = 'warning';
break;
case 'none':
status_color = 'success';
break;
default:
status_color = 'default';
break;
}
$gw_item.find('td:eq(4) > span').removeClass("label-danger label-warning label-success label");
if (status_color != '') {
$gw_item.find('td:eq(4) > span')
.addClass("label label-" + status_color)
.text(gateway.status_translated);
}
let show_item = $("#gatewaysinvert").val() == 'yes' ? false : true;
if ($("#gatewaysfilter").val() && $("#gatewaysfilter").val().includes(gateway.name)) {
show_item = !show_item;
}
if (show_item) {
$gw_item.show();
}
});
}
});
setTimeout(fetch_gateway_statuses, 5000);
}
fetch_gateway_statuses();
});
</script>
<div id="gateways-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/gateways.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<tr>
<td>
<select id="gatewaysinvert" name="gatewaysinvert" class="selectpicker_widget">
<option value="" <?= empty($pconfig['gatewaysinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Hide') ?></option>
<option value="yes" <?= !empty($pconfig['gatewaysinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Show') ?></option>
</select>
<select id="gatewaysfilter" name="gatewaysfilter[]" multiple="multiple" class="selectpicker_widget">
<?php foreach (array_keys($gateways) as $gwname): ?>
<option value="<?= html_safe($gwname) ?>" <?= in_array($gwname, $pconfig['gatewaysfilter']) ? 'selected="selected"' : '' ?>><?= html_safe($gwname) ?></option>
<?php endforeach;?>
</select>
<button id="submitd" name="submitd" type="submit" class="btn btn-primary" value="yes"><?= gettext('Save') ?></button>
</td>
</tr>
</table>
</form>
</div>
<!-- gateway table -->
<table id="gateway_widget_table" class="table table-striped table-condensed">
<tr>
<th><?=gettext('Name')?></th>
<th><?=gettext('RTT')?></th>
<th><?=gettext('RTTd')?></th>
<th><?=gettext('Loss')?></th>
<th><?=gettext('Status')?></th>
</tr>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#gateways-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,179 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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("widgets/include/interface_list.inc");
require_once("interfaces.inc");
$interfaces = get_configured_interface_with_descr();
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = array();
$pconfig['interfaceslistfilter'] = !empty($config['widgets']['interfaceslistfilter']) ?
explode(',', $config['widgets']['interfaceslistfilter']) : array();
$pconfig['interfaceslistinvert'] = !empty($config['widgets']['interfaceslistinvert']) ? '1' : '';
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
if (!empty($pconfig['interfaceslistfilter'])) {
$config['widgets']['interfaceslistfilter'] = implode(',', $pconfig['interfaceslistfilter']);
} elseif (isset($config['widgets']['interfaceslistfilter'])) {
unset($config['widgets']['interfaceslistfilter']);
}
if (!empty($pconfig['interfaceslistinvert'])) {
$config['widgets']['interfaceslistinvert'] = 1;
} elseif (isset($config['widgets']['interfaceslistinvert'])) {
unset($config['widgets']['interfaceslistinvert']);
}
write_config("Saved Interface List Filter via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
?>
<script>
ajaxGet('/api/interfaces/overview/interfacesInfo', {}, function(data, status) {
data.rows.map(function(interface_data) {
var tr_id = 'interface_widget_item_' + interface_data['identifier'];
if ($("#"+tr_id).length) {
let row = $("#"+tr_id);
let $link_status = $("#"+tr_id).find('#link_status');
let $if_status = $("#"+tr_id).find('#if_status');
$link_status.empty();
$if_status.empty();
let $status_symbol = $('<span></span>');
switch (interface_data['link_type']) {
case 'ppp':
$status_symbol.addClass('fa fa-mobile');
break;
case 'wireless':
$status_symbol.addClass('fa fa-signal');
break;
default:
$status_symbol.addClass('fa fa-exchange');
break;
}
$link_status.append($status_symbol.addClass('text-success'));
$if_status.append($('<span class="fa fa-arrow-up text-success" title="' + interface_data['status'] + '"></span>'));
switch (interface_data['status']) {
case 'up':
//case 'associated':
$("#"+tr_id).find('.text-danger').removeClass('text-danger').addClass('text-success');
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-arrow-up');
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-up');
break;
case 'down':
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-arrow-down');
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-down');
break;
default:
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-times');
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-times');
break;
}
let $name = $("#"+tr_id).find('#if_name');
$name.empty();
let $name_span = $('<span style="cursor:pointer" onclick="location.href=\'/interfaces.php?if=' + interface_data['identifier'] +
'\'"><strong><u>' + interface_data['description'] +'</strong></u></span>');
$name.append($name_span)
$media = $("#"+tr_id).find('#if_media');
$media.empty();
if (!'media' in interface_data) {
$media.html(interface_data['cell_mode']);
} else {
$media.html(interface_data['media']);
}
}
});
});
</script>
<div id="interface_list-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/interface_list.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<tr>
<td>
<select id="interfaceslistinvert" name="interfaceslistinvert" class="selectpicker_widget">
<option value="" <?= empty($pconfig['interfaceslistinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Hide') ?></option>
<option value="yes" <?= !empty($pconfig['interfaceslistinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Show') ?></option>
</select>
<select id="interfaceslistfilter" name="interfaceslistfilter[]" multiple="multiple" class="selectpicker_widget">
<?php foreach ($interfaces as $iface => $ifacename): ?>
<option value="<?= html_safe($iface) ?>" <?= in_array($iface, $pconfig['interfaceslistfilter']) ? 'selected="selected"' : '' ?>><?= html_safe($ifacename) ?></option>
<?php endforeach ?>
</select>
<button id="submitd" name="submitd" type="submit" class="btn btn-primary" value="yes"><?= gettext('Save') ?></button>
</td>
</tr>
</table>
</form>
</div>
<table class="table table-striped table-condensed">
<?php
foreach ($interfaces as $ident => $ifname):
$listed = in_array($ident, $pconfig['interfaceslistfilter']);
$listed = !empty($pconfig['interfaceslistinvert']) ? $listed : !$listed;
if (!$listed) {
continue;
}
list($primary4,, $bits4) = interfaces_primary_address($ident);
list($primary6,, $bits6) = interfaces_primary_address6($ident);
?>
<tr id="interface_widget_item_<?= html_safe($ident) ?>">
<td style="width:5%; word-break: break-word;" id="link_status"></td>
<td style="width:15%; word-break: break-word;" id="if_name"></td>
<td style="width:5%; word-break: break-word;" id="if_status"></td>
<td style="width:32%; word-break: break-word;" id="if_media"></td>
<td style="width:43%; word-break: break-word;">
<?= html_safe($primary4) ?>
<?= !empty($primary4) ? '<br/>' : '' ?>
<?= html_safe($primary6) ?>
</td>
</tr>
<?php endforeach ?>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#interface_list-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,164 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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("widgets/include/interface_list.inc");
require_once("interfaces.inc");
$interfaces = get_configured_interface_with_descr();
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = array();
$pconfig['interfacesstatisticsfilter'] = !empty($config['widgets']['interfacesstatisticsfilter']) ?
explode(',', $config['widgets']['interfacesstatisticsfilter']) : array();
$pconfig['interfacesstatisticsinvert'] = !empty($config['widgets']['interfacesstatisticsinvert']) ? '1' : '';
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
if (!empty($pconfig['interfacesstatisticsfilter'])) {
$config['widgets']['interfacesstatisticsfilter'] = implode(',', $pconfig['interfacesstatisticsfilter']);
} elseif (isset($config['widgets']['interfacesstatisticsfilter'])) {
unset($config['widgets']['interfacesstatisticsfilter']);
}
if (!empty($pconfig['interfacesstatisticsinvert'])) {
$config['widgets']['interfacesstatisticsinvert'] = 1;
} elseif (isset($config['widgets']['interfacesstatisticsinvert'])) {
unset($config['widgets']['interfacesstatisticsinvert']);
}
write_config("Saved Interface Statistics Filter via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
$ifvalues = array(
'pkg_in' => gettext('Packets In'),
'pkg_out' => gettext('Packets Out'),
'bytes_in' => gettext('Bytes In'),
'bytes_out' => gettext('Bytes Out'),
'errors_in' => gettext('Errors In'),
'errors_out' => gettext('Errors Out'),
'collisions' => gettext('Collisions'),
);
?>
<script>
function format_field(value) {
if (!isNaN(value) && value > 0) {
let fileSizeTypes = ["", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
let ndx = Math.floor(Math.log(value) / Math.log(1000) );
if (ndx > 0) {
return (value / Math.pow(1000, ndx)).toFixed(2) + ' ' + fileSizeTypes[ndx];
} else {
return value.toFixed(2);
}
} else {
return "0";
}
}
/**
* update interface statistics
*/
setInterval(function update_statistics() {
ajaxGet('/api/interfaces/overview/interfacesInfo/1', {}, function(data, status) {
data.rows.map(function(interface_data) {
let stats = interface_data['statistics'];
let inbytes = format_field(parseInt(stats['bytes received']));
let outbytes = format_field(parseInt(stats['bytes transmitted']));
// fill in stats, use column index to determine td location
var item_index = $("#interface_statistics_widget_intf_" + interface_data['identifier']).index();
if (item_index != -1) {
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(1)").html(parseInt(stats['packets received']).toLocaleString());
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(2)").html(parseInt(stats['packets transmitted']).toLocaleString());
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(3)").html(inbytes);
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(4)").html(outbytes);
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(5)").html(stats['input errors']);
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(6)").html(stats['output errors']);
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(7)").html(stats['collisions']);
}
});
});
return update_statistics;
}(), 5000);
</script>
<div id="interface_statistics-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/interface_statistics.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<tr>
<td>
<select id="interfacesstatisticsinvert" name="interfacesstatisticsinvert" class="selectpicker_widget">
<option value="" <?= empty($pconfig['interfacesstatisticsinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Hide') ?></option>
<option value="yes" <?= !empty($pconfig['interfacesstatisticsinvert']) ? 'selected="selected"' : '' ?>><?= gettext('Show') ?></option>
</select>
<select id="interfacesstatisticsfilter" name="interfacesstatisticsfilter[]" multiple="multiple" class="selectpicker_widget">
<?php foreach ($interfaces as $iface => $ifacename): ?>
<option value="<?= html_safe($iface) ?>" <?= in_array($iface, $pconfig['interfacesstatisticsfilter']) ? 'selected="selected"' : '' ?>><?= html_safe($ifacename) ?></option>
<?php endforeach;?>
</select>
<button id="submitd" name="submitd" type="submit" class="btn btn-primary" value="yes"><?= gettext('Save') ?></button>
</td>
</tr>
</table>
</form>
</div>
<table class="table table-striped table-condensed">
<tr>
<th>&nbsp;</th>
<?php foreach ($ifvalues as $ifkey => $iflabel): ?>
<th><strong><?= $iflabel ?></strong></th>
<?php endforeach ?>
</tr>
<?php foreach ($interfaces as $ifdescr => $ifname):
$listed = in_array($ifdescr, $pconfig['interfacesstatisticsfilter']);
$listed = !empty($pconfig['interfacesstatisticsinvert']) ? $listed : !$listed;
if (!$listed) {
continue;
} ?>
<tr id="interface_statistics_widget_intf_<?= html_safe($ifdescr) ?>">
<td style="word-break: break-word;"><strong><?= $ifname ?></strong></td>
<?php $infcount = 0;
while ($infcount++ < count($ifvalues)): ?>
<td style="word-break: break-word;">&#126;</td>
<?php endwhile ?>
</tr>
<?php endforeach ?>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#interface_statistics-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,235 +0,0 @@
<?php
/*
Copyright (C) 2014-2016 Deciso B.V.
Copyright (C) 2007 Scott Dale
Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
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");
$ipsec_detail_array = [];
$ipsec_tunnels = [];
$ipsec_leases = [];
$ipsec_leases = json_decode(configd_run("ipsec list leases"), true);
if (!is_array($ipsec_leases) || empty($ipsec_leases['leases'])) {
$ipsec_leases = [];
} else {
$ipsec_leases = $ipsec_leases['leases'];
}
$ipsec_status = json_decode(configd_run("ipsec list status"), true) ?? [];
// parse configured tunnels
foreach ($ipsec_status as $status_key => $status_value) {
if (isset($status_value['children']) && is_array($status_value['children'])) {
foreach($status_value['children'] as $child_status_key => $child_status_value) {
$ipsec_tunnels[$child_status_key] = array('active' => false,
'local-addrs' => $status_value['local-addrs'],
'remote-addrs' => $status_value['remote-addrs'],
);
$ipsec_tunnels[$child_status_key]['local-ts'] = implode(', ', $child_status_value['local-ts']);
$ipsec_tunnels[$child_status_key]['remote-ts'] = implode(', ', $child_status_value['remote-ts']);
}
}
foreach ($status_value['sas'] as $sas_key => $sas_value) {
foreach ($sas_value['child-sas'] as $child_sa_key => $child_sa_value) {
if (!isset($ipsec_tunnels[$child_sa_key])) {
/* XXX bug on strongSwan 5.5.2 appends -3 and -4 here? */
$child_sa_key = preg_replace('/-[^-]+$/', '', $child_sa_key);
}
if (isset($ipsec_tunnels[$child_sa_key])) {
$ipsec_tunnels[$child_sa_key]['active'] = true;
}
}
}
}
// Initialize variable aggregated_data and loop through the ipsec_leases array to fetch the data for user, address and online status. Used later for div ipsec-mobile. Additionally count the unique_users in the same foreach loop, used for mobile_users count.
$aggregated_data = [];
$unique_users = [];
foreach ($ipsec_leases as $lease) {
// For each unique user, initialize an empty array
if (!isset($aggregated_data[$lease['user']])) {
$aggregated_data[$lease['user']] = [];
}
// Add the lease data to this user's array of leases
$aggregated_data[$lease['user']][] = [
'address' => $lease['address'],
'online' => $lease['online']
];
// Count unique users in ipsec_leases array if lease is online
if ($lease['online']) {
$unique_users[$lease['user']] = true;
}
}
// Return the number of unique_users as mobile_users
$mobile_users = count($unique_users);
?>
<script>
$(document).ready(function() {
$(".ipsec-tab").unbind('click').click(function() {
$('.ipsec-tab').removeClass('activetab');
$(this).addClass('activetab');
$(".ipsec-tab-content").hide();
$("#"+$(this).attr('data-for')).show();
});
});
</script>
<style>
.dashboard_grid_column table {
table-layout: fixed;
}
#ipsec #ipsec-mobile, #ipsec #ipsec-tunnel, #ipsec #ipsec-overview {
background-color: #EEEEEE;
}
#ipsec .ipsec-tab {
background-color: #777777;
color: white;
}
#ipsec .ipsec-tab.activetab {
background-color: #EEEEEE;
color: black;
}
</style>
<div id="tabs">
<div data-for="ipsec-overview" class="ipsec-tab table-cell activetab" style="cursor: pointer; display:table-cell">
<strong>&nbsp;&nbsp;<?=gettext("Overview");?>&nbsp;&nbsp;</strong>
</div>
<div data-for="ipsec-tunnel" class="ipsec-tab table-cell" style="cursor: pointer; display:table-cell">
<strong>&nbsp;&nbsp;<?=gettext("Tunnels");?>&nbsp;&nbsp;</strong>
</div>
<div data-for="ipsec-mobile" class="ipsec-tab table-cell" style="cursor: pointer; display:table-cell">
<strong>&nbsp;&nbsp;<?=gettext("Mobile");?>&nbsp;&nbsp;</strong>
</div>
</div>
<div id="ipsec-overview" class="ipsec-tab-content" style="display:block;">
<table class="table table-striped">
<thead>
<tr>
<th><?= gettext('Active Tunnels');?></th>
<th><?= gettext('Inactive Tunnels');?></th>
<th><?= gettext('Mobile Users');?></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?php
$activetunnels = 0;
foreach ($ipsec_tunnels as $ipsec_key => $ipsec) {
$activetunnels += $ipsec['active'] === true;
}
echo $activetunnels;
?>
</td>
<td><?= (count($ipsec_tunnels) - $activetunnels); ?></td>
<td>
<!-- mobile_users were counted in the earlier loop where data was aggregated -->
<?=$mobile_users;?>
</td>
</tr>
</tbody>
</table>
</div>
<div id="ipsec-tunnel" class="ipsec-tab-content" style="display:none;">
<table class="table table-striped">
<thead>
<tr>
<th><?= gettext('Connection');?></th>
<th><?= gettext('Source');?></th>
<th><?= gettext('Destination');?></th>
<th><?= gettext('Status');?></th>
</tr>
</thead>
<tbody>
<?php foreach ($ipsec_tunnels as $ipsec_key => $ipsec): ?>
<tr>
<td>
<?=$ipsec['local-addrs'];?> <br/>
(<?=$ipsec['remote-addrs'];?>)
</td>
<td><?=$ipsec['local-ts'];?></td>
<td><?=$ipsec['remote-ts'];?></td>
<td>
<i class="fa fa-exchange fa-fw text-<?= $ipsec['active'] ? 'success' : 'danger' ?>"></i>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>
<div id="ipsec-mobile" class="ipsec-tab-content" style="display:none;">
<table class="table table-striped">
<thead>
<tr>
<th><?=gettext('User');?></th>
<th><?=gettext('IP');?></th>
<th><?=gettext('Status');?></th>
</tr>
</thead>
<tbody>
<?php
// Generate the user and IP addresses table rows using the aggregated_data variable that was populated earlier
foreach ($aggregated_data as $user => $user_data):?>
<tr>
<td><?=htmlspecialchars($user);?></td>
<td>
<table>
<?php foreach($user_data as $lease): ?>
<tr>
<td><?=htmlspecialchars($lease['address']);?></td>
</tr>
<?php endforeach; ?>
</table>
</td>
<td>
<table>
<?php foreach($user_data as $lease):?>
<tr>
<td>
<!-- Show the online and offline status of each lease a user has. -->
<i class="fa fa-exchange fa-fw text-<?=$lease['online'] ? 'success' : 'danger' ?>"></i>
</td>
</tr>
<?php endforeach; ?>
</table>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>

View File

@ -1,246 +0,0 @@
<?php
/*
* Copyright (C) 2014 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2009 Jim Pingle <jimp@pfsense.org>
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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("interfaces.inc");
$pconfig = $_POST;
if (is_numeric($pconfig['filterlogentries'] ?? null)) {
$config['widgets']['filterlogentries'] = $pconfig['filterlogentries'];
$config['widgets']['filterlogentriesupdateinterval'] = $pconfig['filterlogentriesupdateinterval'];
$acts = array();
if ($pconfig['actpass']) {
$acts[] = 'Pass';
}
if ($pconfig['actblock']) {
$acts[] = 'Block';
}
if ($pconfig['actreject']) {
$acts[] = 'Reject';
}
if (!empty($acts)) {
$config['widgets']['filterlogentriesacts'] = implode(' ', $acts);
} elseif (isset($config['widgets']['filterlogentriesacts'])) {
unset($config['widgets']['filterlogentriesacts']);
}
if (!empty($pconfig['filterlogentriesinterfaces'])) {
$config['widgets']['filterlogentriesinterfaces'] = implode(',', $pconfig['filterlogentriesinterfaces']);
} elseif (isset($config['widgets']['filterlogentriesinterfaces'])) {
unset($config['widgets']['filterlogentriesinterfaces']);
}
write_config('Saved Filter Log Entries via Dashboard');
header(url_safe('Location: /index.php'));
exit;
}
$nentries = isset($config['widgets']['filterlogentries']) ? $config['widgets']['filterlogentries'] : 5;
$updateinterval = isset($config['widgets']['filterlogentriesupdateinterval']) ? $config['widgets']['filterlogentriesupdateinterval'] : 2;
$nentriesacts = isset($config['widgets']['filterlogentriesacts']) ? explode(" ", $config['widgets']['filterlogentriesacts']) : array('Pass', 'Block', 'Reject');
$nentriesinterfaces = isset($config['widgets']['filterlogentriesinterfaces']) ? $config['widgets']['filterlogentriesinterfaces'] : '';
?>
<script>
$("#dashboard_container").on("WidgetsReady", function() {
// needed to display the widget settings menu
$("#log-configure").removeClass("disabled");
// icons
const field_type_icons = {'pass': 'fa-play', 'block': 'fa-ban', 'rdr': 'fa-exchange', 'nat': 'fa-exchange'};
var interface_descriptions = {};
var nentriesinterfaces = "<?= $nentriesinterfaces ?>".split(",");
ajaxGet('/api/diagnostics/interface/getInterfaceNames', {}, function(data, status) {
interface_descriptions = data;
$.each(interface_descriptions, function(i_d, i_name){
$('#filterlogentriesinterfaces').append($.inArray(i_d, nentriesinterfaces) > -1 ? $('<option>', {value:i_d, text:i_name, selected: "selected" }) : $('<option>', {value:i_d, text:i_name }));
});
$('#filterlogentriesinterfaces').selectpicker('refresh');
fetch_log();
});
function fetch_log(){
var record_spec = [];
// read heading, contains field specs
$("#filter-log-entries > thead > tr > th").each(function () {
record_spec.push({
'column-id': $(this).data('column-id'),
'type': $(this).data('type'),
'class': $(this).attr('class')
});
});
var last_digest = $("#filter-log-entries > tbody > tr:first > td:first").text();
ajaxGet('/api/diagnostics/firewall/log/', {'digest': last_digest, 'limit': 100}, function(data, status) {
var filtact = [];
if ($("#actpass").is(':checked')) {
filtact.push('pass');
}
if ($("#actblock").is(':checked') || $("#actreject").is(':checked')) {
filtact.push('block');
}
let record;
let showinterfaces = $("#filterlogentriesinterfaces").val();
while ((record=data.pop()) != null) {
var intf = record['interface'];
if (showinterfaces.length == 0 || $.inArray(intf, showinterfaces) > -1) {
if ((filtact.length == 0 || filtact.indexOf(record['action']) !== -1) && record['__digest__'] != last_digest) {
var log_tr = $("<tr>");
log_tr.hide();
$.each(record_spec, function(idx, field){
var log_td = $('<td style="word-break:break-word;">').addClass(field['class']);
var column_name = field['column-id'];
var content = null;
switch (field['type']) {
case 'icon':
var icon = field_type_icons[record[column_name]];
if (icon != undefined) {
// prepare popover content
let popContent = "@" + record.rulenr;
popContent += record.label.length > 0 ? " Label: " + record.label : '';
popContent += "<br><sub><?= gettext('click the Act icon to track this rule in Live View') ?></sub>"
log_td.html('<a target="_blank" href="/ui/diagnostics/firewall/log?rid=' + record.rid + '" type="button" data-toggle="popover" data-trigger="hover" \
data-html="true" data-title="<?= gettext('Matched rule') ?>" data-content="' + popContent + '"><i class="fa ' + icon + '" aria-hidden="true"></i></a>');
if (record[column_name] == 'pass') {
log_td.find('a').addClass('text-success');
} else {
log_td.find('a').addClass('text-danger');
}
}
break;
case 'time':
log_td.text(record[column_name].replace(/:[0-9]{2}$/, ''));
break;
case 'interface':
if (interface_descriptions[record[column_name]] != undefined) {
log_td.text(interface_descriptions[record[column_name]]);
} else {
log_td.text(record[column_name]);
}
break;
case 'source_address':
// may support ports, but needs IPv6 fixup
log_td.text(record[column_name]);
break;
case 'destination_address':
// may support ports, but needs IPv6 fixup
log_td.text(record[column_name]);
break;
case 'destination_port':
log_td.text(record[column_name]);
break;
default:
if (record[column_name] != undefined) {
log_td.text(record[column_name]);
}
}
log_tr.append(log_td);
});
$("#filter-log-entries > tbody > tr:first").before(log_tr);
}
}
}
//hide popover before elem remove
$('[data-toggle="popover"]').popover('hide');
$("#filter-log-entries > tbody > tr:gt("+(parseInt($("#filterlogentries").val() - 1))+")").remove();
$("#filter-log-entries > tbody > tr").show();
//enable popover with full width for long descriptions
$('[data-toggle="popover"]').popover({
container: 'body'
}).on('show.bs.popover', function() {
$(this).data("bs.popover").tip().css("max-width", "100%")
});
});
// schedule next fetch
var update_interval_ms = parseInt($("#filterlogentriesupdateinterval").val()) * 1000;
update_interval_ms = (isNaN(update_interval_ms) || update_interval_ms < 1000 || update_interval_ms > 60000) ? 5000 : update_interval_ms;
setTimeout(fetch_log, update_interval_ms);
}
});
</script>
<div id="log-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/log.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<tr>
<td>
<label for="filterlogentries"><?= gettext('Number of log entries:') ?></label><br/>
<select id="filterlogentries" name="filterlogentries" class="selectpicker_widget">
<?php for ($i = 1; $i <= 20; $i++): ?>
<option value="<?= html_safe($i) ?>" <?= $nentries == $i ? 'selected="selected"' : '' ?>><?= html_safe($i) ?></option>
<?php endfor ?>
</select><br/>
<label for="filterlogentriesupdateinterval"><?= gettext('Update interval in seconds:') ?></label><br/>
<select id="filterlogentriesupdateinterval" name="filterlogentriesupdateinterval" class="selectpicker_widget">
<?php for ($i = 1; $i <= 60; $i++): ?>
<option value="<?= html_safe($i) ?>" <?= $updateinterval == $i ? 'selected="selected"' : '' ?>><?= html_safe($i) ?></option>
<?php endfor ?>
</select><br/>
<label for="filterlogentriesinterfaces"><?= gettext('Interfaces to display:'); ?></label><br/>
<select id="filterlogentriesinterfaces" name="filterlogentriesinterfaces[]" class="selectpicker_widget" multiple="multiple" title=<?= gettext('All'); ?>>
</select><br/><br/>
<table style="width:348px">
<tr>
<td><label for="actblock"><input id="actblock" name="actblock" type="checkbox" value="Block" <?=in_array('Block', $nentriesacts) ? "checked=\"checked\"" : "";?> /><?= gettext('Block') ?></label></td>
<td><label for="actreject"><input id="actreject" name="actreject" type="checkbox" value="Reject" <?=in_array('Reject', $nentriesacts) ? "checked=\"checked\"" : "";?> /><?= gettext('Reject') ?></label></td>
<td><label for="actpass"><input id="actpass" name="actpass" type="checkbox" value="Pass" <?=in_array('Pass', $nentriesacts) ? "checked=\"checked\"" : "";?> /><?= gettext('Pass') ?></label></td>
<td><button name="submit_firewall_logs_widget" type="submit" class="btn btn-primary" value="yes"><?= gettext('Save') ?></button></td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</div>
<table class="table table-striped table-condensed" id="filter-log-entries">
<thead>
<tr>
<th data-column-id="__digest__" data-type="string" class="hidden"><?= gettext('Hash') ?></th>
<th data-column-id="action" data-type="icon" class="text-center"><?= gettext('Act') ?></th>
<th data-column-id="__timestamp__" data-type="time"><?= gettext('Time') ?></th>
<th data-column-id="interface" data-type="interface" class="text-center"><?= gettext('Interface') ?></th>
<th data-column-id="src" data-type="source_address"><?= gettext('Source') ?></th>
<th data-column-id="dst" data-type="destination_address"><?= gettext('Destination') ?></th>
<th data-column-id="dstport" data-type="destination_port"><?= gettext('Port') ?></th>
</tr>
</thead>
<tbody>
<tr></tr>
</tbody>
</table>

View File

@ -1,229 +0,0 @@
<?php
/*
* Copyright (C) 2018-2019 EURO-LOG AG
* 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("widgets/include/monit.inc");
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (isset($config['widgets']['monitheight']) && is_numeric($config['widgets']['monitheight'])) {
$pconfig['monitheight'] = $config['widgets']['monitheight'];
}
else {
$pconfig['monitheight'] = 9;
}
if (isset($config['widgets']['monitsearch'])) {
$pconfig['monitsearch'] = $config['widgets']['monitsearch'];
}
else {
unset($pconfig['monitsearch']);
}
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
if (isset($pconfig['monitheight']) && is_numeric($pconfig['monitheight'])) {
$config['widgets']['monitheight'] = $pconfig['monitheight'];
} else {
$config['widgets']['monitheight'] = 9;
}
if (isset($pconfig['monitsearch'])) {
$config['widgets']['monitsearch'] = $pconfig['monitsearch'];
} else {
unset($config['widgets']['monitsearch']);
}
write_config("Saved Monit Widget Settings via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
legacy_html_escape_form_data($pconfig);
?>
<style>
.monit-widget-table {
width: 100%
}
.monit-widget-table > thead,
.monit-widget-table > tbody,
.monit-widget-table > thead > tr,
.monit-widget-table > tbody > tr,
.monit-widget-table > thead > tr > th,
.monit-widget-table > tbody > tr > td {
display: block;
line-height: 1.5em;
}
.monit-widget-table > tbody > tr:after,
.monit-widget-table > thead > tr:after {
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
.monit-widget-table > tbody {
overflow-y: auto;
height: <?php echo ($pconfig['monitheight'] * 2) + 2; ?>em;
}
.monit-widget-table > tbody > tr > td,
.monit-widget-table > thead > tr > th {
width: 33%;
float: left;
}
</style>
<link rel="stylesheet" type="text/css" href="<?= cache_safe(get_themed_filename('/css/jquery.bootgrid.css')) ?>">
<script src="<?= cache_safe('/ui/js/jquery.bootgrid.js') ?>"></script>
<script>
$( document ).ready(function() {
const monitServiceTypes = [
"<?= gettext('Filesystem') ?>",
"<?= gettext('Directory') ?>",
"<?= gettext('File') ?>",
"<?= gettext('Process') ?>",
"<?= gettext('Host') ?>",
"<?= gettext('System') ?>",
"<?= gettext('Fifo') ?>",
"<?= gettext('Custom') ?>",
"<?= gettext('Network') ?>"
];
const monitStatusTypes = [
"<?= gettext('OK') ?>",
"<?= gettext('Failed') ?>",
"<?= gettext('Changed') ?>",
"<?= gettext('Not changed') ?>"
];
// avoid running code twice due to <script> location within <body>
if (typeof monitPollInit === 'undefined') {
monitPollInit = false;
} else {
monitPollInit = true;
}
function monitStatusPoll() {
var pollInterval = 10000;
ajaxCall("/api/monit/status/get/xml", {}, function(data, status) {
$("#grid-monit").bootgrid("clear");
if (data['result'] === 'ok') {
pollInterval = data['status']['server']['poll'] * 1000;
$.each(data['status']['service'], function(index, service) {
$("#grid-monit").bootgrid("append", [{
name: service['name'],
type: monitServiceTypes[service['@attributes']['type']],
status: monitStatusTypes[service['status']]
}]);
});
}
<?php
// apply search filter
if (!empty($pconfig['monitsearch'])) {
echo '$("#grid-monit").bootgrid("search", "' .$pconfig['monitsearch'] . '");';
}
?>
setTimeout(monitStatusPoll, pollInterval);
});
};
if (monitPollInit === false) {
$("#grid-monit").bootgrid({
navigation: 0,
rowCount: -1
}).on("loaded.rs.jquery.bootgrid", function() {
// set right margin according to the scrollbar width
let scrollWidth = $('.monit-widget-table > tbody')[0].offsetWidth - $('.monit-widget-table > tbody')[0].clientWidth;
$('.monit-widget-table > thead').css('margin-right', scrollWidth);
});
monitStatusPoll();
}
});
</script>
<div id="monit-settings" class="widgetconfigdiv" style="display:none;">
<form class="form-inline" action="/widgets/widgets/monit.widget.php" method="post" name="iformd">
<div class="table-responsive">
<table class="table table-striped table-condensed">
<tr>
<td>
<div class="control-label" id="control_label_monitheight">
<b><?= gettext('Rows') ?></b>
</div>
</td>
<td>
<input type="text" class="form-control" size="25" name="monitheight" id="monitheight" value="<?= $pconfig['monitheight'] ?>" />
</td>
</tr>
<tr>
<td>
<div class="control-label" id="control_label_monitsearch">
<b><?= gettext('Search') ?></b>
</div>
</td>
<td>
<input type="text" class="form-control" size="25" name="monitsearch" id="monitsearch" value="<?= $pconfig['monitsearch'] ?>" />
</td>
</tr>
<tr>
<td>
<button id="submitd" name="submitd" type="submit" class="btn btn-primary" value="yes">
<b><?= gettext('Save') ?></b>
</button>
</td>
<td> </td>
</tr>
</table>
</div>
</form>
</div>
<table id="grid-monit" class="table table-condensed table-hove table-striped table-responsive bootgrid-table monit-widget-table">
<thead>
<tr>
<th data-column-id="name"><?= gettext('Name') ?></th>
<th data-column-id="type"><?= gettext('Type') ?></th>
<th data-column-id="status"><?= gettext('Status') ?></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
</tfoot>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#monit-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,510 +0,0 @@
<?php
/*
Copyright (C) 2014 Deciso B.V.
Copyright (c) 2007 Scott Dale
Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
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("widgets/include/ntp_status.inc");
if ($_REQUEST['updateme']) {
//this block displays only on ajax refresh
exec("/usr/local/sbin/ntpq -pn | /usr/bin/tail +3", $ntpq_output);
$ntpq_counter = 0;
foreach ($ntpq_output as $line) {
if (substr($line, 0, 1) == "*") {
//Active NTP Peer
$line = substr($line, 1);
$peerinfo = preg_split("/[\s\t]+/", $line);
if ($peerinfo[2] == "1") {
$syncsource = $peerinfo[0] . " (stratum " . $peerinfo[2] . ", " . $peerinfo[1] . ")";
} else {
$syncsource = $peerinfo[0] . " (stratum " . $peerinfo[2] . ")";
}
$ntpq_counter++;
} elseif (substr($line, 0, 1) == "o") {
//Local PPS Peer
$line = substr($line, 1);
$peerinfo = preg_split("/[\s\t]+/", $line);
$syncsource = $peerinfo[1] . " (stratum " . $peerinfo[2] . ", PPS)";
$ntpq_counter++;
}
}
exec("/usr/local/sbin/ntpq -c clockvar", $ntpq_clockvar_output);
foreach ($ntpq_clockvar_output as $line) {
if (substr($line, 0, 9) == "timecode=") {
$tmp = explode('"', $line);
$tmp = $tmp[1];
if (substr($tmp, 0, 6) == '$GPRMC') {
$gps_vars = explode(",", $tmp);
$gps_ok = ($gps_vars[2] == "A");
if ($gps_ok) {
$gps_lat_deg = substr($gps_vars[3], 0, 2);
$gps_lat_min = substr($gps_vars[3], 2) / 60.0;
$gps_lon_deg = substr($gps_vars[5], 0, 3);
$gps_lon_min = substr($gps_vars[5], 3) / 60.0;
$gps_lat = $gps_lat_deg + $gps_lat_min;
$gps_lat = $gps_lat * (($gps_vars[4] == "N") ? 1 : -1);
$gps_lon = $gps_lon_deg + $gps_lon_min;
$gps_lon = $gps_lon * (($gps_vars[6] == "E") ? 1 : -1);
}
$gps_la = $gps_vars[4];
$gps_lo = $gps_vars[6];
} elseif (substr($tmp, 0, 6) == '$GPGGA') {
$gps_vars = explode(",", $tmp);
$gps_ok = $gps_vars[6];
if ($gps_ok) {
$gps_lat_deg = substr($gps_vars[2], 0, 2);
$gps_lat_min = substr($gps_vars[2], 2) / 60.0;
$gps_lon_deg = substr($gps_vars[4], 0, 3);
$gps_lon_min = substr($gps_vars[4], 3) / 60.0;
$gps_lat = $gps_lat_deg + $gps_lat_min;
$gps_lat = $gps_lat * (($gps_vars[3] == "N") ? 1 : -1);
$gps_lon = $gps_lon_deg + $gps_lon_min;
$gps_lon = $gps_lon * (($gps_vars[5] == "E") ? 1 : -1);
}
$gps_alt = $gps_vars[9];
$gps_alt_unit = $gps_vars[10];
$gps_sat = $gps_vars[7];
$gps_la = $gps_vars[3];
$gps_lo = $gps_vars[5];
} elseif (substr($tmp, 0, 6) == '$GPGLL') {
$gps_vars = explode(",", $tmp);
$gps_ok = ($gps_vars[6] == "A");
if ($gps_ok) {
$gps_lat_deg = substr($gps_vars[1], 0, 2);
$gps_lat_min = substr($gps_vars[1], 2) / 60.0;
$gps_lon_deg = substr($gps_vars[3], 0, 3);
$gps_lon_min = substr($gps_vars[3], 3) / 60.0;
$gps_lat = $gps_lat_deg + $gps_lat_min;
$gps_lat = $gps_lat * (($gps_vars[2] == "N") ? 1 : -1);
$gps_lon = $gps_lon_deg + $gps_lon_min;
$gps_lon = $gps_lon * (($gps_vars[4] == "E") ? 1 : -1);
}
$gps_la = $gps_vars[2];
$gps_lo = $gps_vars[4];
}
}
}
if (isset($config['ntpd']['gps']['type']) && ($config['ntpd']['gps']['type'] == 'SureGPS') && (isset($gps_ok))) {
//GSV message is only enabled by init commands in services_ntpd_gps.php for SureGPS board
$gpsport = fopen("/dev/gps0", "r+");
while ($gpsport) {
$buffer = fgets($gpsport);
if (substr($buffer, 0, 6)=='$GPGSV') {
//echo $buffer."\n";
$gpgsv = explode(',', $buffer);
$gps_satview = $gpgsv[3];
break;
}
}
}
?>
<table >
<tbody>
<tr>
<td style="width:40%">Sync Source</td>
<td style="width:60%">
<?php if ($ntpq_counter == 0) :
?>
<?= gettext('No active peers available') ?>
<?php
else :
?>
<?= $syncsource ?>
<?php
endif; ?>
</td>
</tr>
<?php if (($gps_ok) && ($gps_lat) && ($gps_lon)) :
?>
<tr>
<td style="width:40%"><?= gettext('Clock location') ?></td>
<td style="width:60%">
<a target="_gmaps" href="https://maps.google.com/?q=<?= html_safe($gps_lat) ?>,<?= html_safe($gps_lon) ?>">
<?php
echo sprintf("%.5f", $gps_lat) . " " . $gps_la . ", " . sprintf("%.5f", $gps_lon) . " " . $gps_lo; ?>
</a>
<?php if (isset($gps_alt)) {
echo " (" . $gps_alt . " " . $gps_alt_unit . " alt.)";
} ?>
</td>
</tr>
<?php if (isset($gps_sat) || isset($gps_satview)) :
?>
<tr>
<td style="width:40%"><?= gettext('Satellites') ?></td>
<td style="width:60%">
<?php
if (isset($gps_satview)) {
echo gettext('in view ') . intval($gps_satview);
}
if (isset($gps_sat) && isset($gps_satview)) {
echo ', ';
}
if (isset($gps_sat)) {
echo gettext('in use ') . $gps_sat;
}
?>
</td>
</tr>
<?php
endif; ?>
<?php
endif; ?>
</tbody>
</table>
<?php
exit;
}
/*** Clock -- beginning of server-side support code
by Andrew Shearer, http://www.shearersoftware.com/
v2.1.2-PHP, 2003-08-07. For updates and explanations, see
<http://www.shearersoftware.com/software/web-tools/clock/>. ***/
/* Prevent this page from being cached (though some browsers still
cache the page anyway, which is why we use cookies). This is
only important if the cookie is deleted while the page is still
cached (and for ancient browsers that don't know about Cache-Control).
If that's not an issue, you may be able to get away with
"Cache-Control: private" instead. */
/* Grab the current server time. */
$gDate = time();
/* Are the seconds shown by default? When changing this, also change the
JavaScript client code's definition of clockShowsSeconds below to match. */
$gClockShowsSeconds = true;
function getServerDateItems($inDate)
{
return date('Y,n,j,G,', $inDate).intval(date('i', $inDate)).','.intval(date('s', $inDate));
// year (4-digit),month,day,hours (0-23),minutes,seconds
// use intval to strip leading zero from minutes and seconds
// so JavaScript won't try to interpret them in octal
// (use intval instead of ltrim, which translates '00' to '')
}
function clockTimeString($inDate, $showSeconds)
{
return date($showSeconds ? 'G:i:s' : 'g:i', $inDate).' ';
}
/*** Clock -- end of server-side support code ***/
?>
<script>
<!--
/* set up variables used to init clock in BODY's onLoad handler;
should be done as early as possible */
var clockLocalStartTime = new Date();
var clockServerStartTime = new Date(<?= html_safe(getServerDateItems($gDate)) ?>);
/* stub functions for older browsers;
will be overridden by next JavaScript1.2 block */
function clockInit() {
}
//-->
</script>
<script>
<!--
/*** simpleFindObj, by Andrew Shearer
Efficiently finds an object by name/id, using whichever of the IE,
classic Netscape, or Netscape 6/W3C DOM methods is available.
The optional inLayer argument helps Netscape 4 find objects in
the named layer or floating DIV. */
function simpleFindObj(name, inLayer) {
return document[name] || (document.all && document.all[name])
|| (document.getElementById && document.getElementById(name))
|| (document.layers && inLayer && document.layers[inLayer].document[name]);
}
/*** Beginning of Clock 2.1.2, by Andrew Shearer
See: http://www.shearersoftware.com/software/web-tools/clock/
Redistribution is permitted with the above notice intact.
Client-side clock, based on computed time differential between browser &
server. The server time is inserted by server-side JavaScript, and local
time is subtracted from it by client-side JavaScript while the page is
loading.
Cookies: The local and remote times are saved in cookies named
localClock and remoteClock, so that when the page is loaded from local
cache (e.g. by the Back button) the clock will know that the embedded
server time is stale compared to the local time, since it already
matches its cookie. It can then base the calculations on both cookies,
without reloading the page from the server. (IE 4 & 5 for Windows didn't
respect Response.Expires = 0, so if cookies weren't used, the clock
would be wrong after going to another page then clicking Back. Netscape
& Mac IE were OK.)
Every so often (by default, one hour) the clock will reload the page, to
make sure the clock is in sync (as well as to update the rest of the
page content).
Compatibility: IE 4.x and 5.0, Netscape 4.x and 6.0, Mozilla 1.0. Mac & Windows.
History: 1.0 2000-05-09 GIF-image digits
2.0 2000-06-29 Uses text DIV layers (so 4.0 browsers req'd), &
cookies to work around Win IE stale-time bug
2.1 2002-10-12 Noted Mozilla 1.0 compatibility; released PHP version.
2.1.1 2002-10-20 Fixed octal bug in the PHP translation; the number of
minutes & seconds were misinterprets when less than 10
2.1.2 2003-08-07 The previous fix had introduced a bug when the
minutes or seconds were exactly 0. Thanks to Man Bui
for reporting the bug.
*/
var clockIncrementMillis = 1000;
var localTime;
var clockOffset;
var clockExpirationLocal;
var clockShowsSeconds = true;
var clockTimerID = null;
function clockInit(localDateObject, serverDateObject)
{
var origRemoteClock = parseInt(clockGetCookieData("remoteClock"));
var origLocalClock = parseInt(clockGetCookieData("localClock"));
var newRemoteClock = serverDateObject.getTime();
// May be stale (WinIE); will check against cookie later
// Can't use the millisec. ctor here because of client inconsistencies.
var newLocalClock = localDateObject.getTime();
var maxClockAge = 60 * 60 * 1000; // get new time from server every 1hr
if (newRemoteClock != origRemoteClock) {
// new clocks are up-to-date (newer than any cookies)
document.cookie = "remoteClock=" + newRemoteClock;
document.cookie = "localClock=" + newLocalClock;
clockOffset = newRemoteClock - newLocalClock;
clockExpirationLocal = newLocalClock + maxClockAge;
localTime = newLocalClock; // to keep clockUpdate() happy
}
else if (origLocalClock != origLocalClock) {
// error; localClock cookie is invalid (parsed as NaN)
clockOffset = null;
clockExpirationLocal = null;
}
else {
// fall back to clocks in cookies
clockOffset = origRemoteClock - origLocalClock;
clockExpirationLocal = origLocalClock + maxClockAge;
localTime = origLocalClock;
// so clockUpdate() will reload if newLocalClock
// is earlier (clock was reset)
}
/* Reload page at server midnight to display the new date,
by expiring the clock then */
var nextDayLocal = (new Date(serverDateObject.getFullYear(),
serverDateObject.getMonth(),
serverDateObject.getDate() + 1)).getTime() - clockOffset;
if (nextDayLocal < clockExpirationLocal) {
clockExpirationLocal = nextDayLocal;
}
}
function clockOnLoad()
{
clockUpdate();
}
function clockOnUnload() {
clockClearTimeout();
}
function clockClearTimeout() {
if (clockTimerID) {
clearTimeout(clockTimerID);
clockTimerID = null;
}
}
function clockToggleSeconds()
{
clockClearTimeout();
if (clockShowsSeconds) {
clockShowsSeconds = false;
clockIncrementMillis = 60000;
}
else {
clockShowsSeconds = true;
clockIncrementMillis = 1000;
}
clockUpdate();
}
function clockTimeString(inHours, inMinutes, inSeconds) {
return inHours
+ (inMinutes < 10 ? ":0" : ":") + inMinutes
+ (inSeconds < 10 ? ":0" : ":") + inSeconds;
}
function clockDisplayTime(inHours, inMinutes, inSeconds) {
clockWriteToDiv("ClockTime", clockTimeString(inHours, inMinutes, inSeconds));
}
function clockWriteToDiv(divName, newValue) // APS 6/29/00
{
var divObject = simpleFindObj(divName);
newValue = '<b>' + newValue + '<' + '/b>';
if (divObject && divObject.innerHTML) {
divObject.innerHTML = newValue;
}
else if (divObject && divObject.document) {
divObject.document.writeln(newValue);
divObject.document.close();
}
// else divObject wasn't found; it's only a clock, so don't bother complaining
}
function clockGetCookieData(label) {
/* find the value of the specified cookie in the document's
semicolon-delimited collection. For IE Win98 compatibility, search
from the end of the string (to find most specific host/path) and
don't require "=" between cookie name & empty cookie values. Returns
null if cookie not found. One remaining problem: Under IE 5 [Win98],
setting a cookie with no equals sign creates a cookie with no name,
just data, which is indistinguishable from a cookie with that name
but no data but can't be overwritten by any cookie with an equals
sign. */
var c = document.cookie;
if (c) {
var labelLen = label.length, cEnd = c.length;
while (cEnd > 0) {
var cStart = c.lastIndexOf(';',cEnd-1) + 1;
/* bug fix to Danny Goodman's code: calculate cEnd, to
prevent walking the string char-by-char & finding cookie
labels that contained the desired label as suffixes */
// skip leading spaces
while (cStart < cEnd && c.charAt(cStart)==" ") cStart++;
if (cStart + labelLen <= cEnd && c.substr(cStart,labelLen) == label) {
if (cStart + labelLen == cEnd) {
return ""; // empty cookie value, no "="
}
else if (c.charAt(cStart+labelLen) == "=") {
// has "=" after label
return unescape(c.substring(cStart + labelLen + 1,cEnd));
}
}
cEnd = cStart - 1; // skip semicolon
}
}
return null;
}
/* Called regularly to update the clock display as well as onLoad (user
may have clicked the Back button to arrive here, so the clock would need
an immediate update) */
function clockUpdate()
{
var lastLocalTime = localTime;
localTime = (new Date()).getTime();
/* Sanity-check the diff. in local time between successive calls;
reload if user has reset system clock */
if (clockOffset == null) {
clockDisplayTime(null, null, null);
}
else if (localTime < lastLocalTime || clockExpirationLocal < localTime) {
/* Clock expired, or time appeared to go backward (user reset
the clock). Reset cookies to prevent infinite reload loop if
server doesn't give a new time. */
document.cookie = 'remoteClock=-';
document.cookie = 'localClock=-';
location.reload(); // will refresh time values in cookies
}
else {
// Compute what time would be on server
var serverTime = new Date(localTime + clockOffset);
clockDisplayTime(serverTime.getHours(), serverTime.getMinutes(),
serverTime.getSeconds());
// Reschedule this func to run on next even clockIncrementMillis boundary
clockTimerID = setTimeout("clockUpdate()",
clockIncrementMillis - (serverTime.getTime() % clockIncrementMillis));
}
}
/*** End of Clock ***/
//-->
window.onload=clockInit(clockLocalStartTime, clockServerStartTime);clockOnLoad();
window.onunload=clockOnUnload();
clockUpdate();
</script>
<table class="table table-striped table-condensed">
<tbody>
<tr>
<td style="width:40%">Server Time</td>
<td style="width:60%">
<div id="ClockTime">
<b><?= clockTimeString($gDate, $gClockShowsSeconds) ?></b>
</div>
</td>
</tr>
<tr>
<td colspan="2" id="ntpstatus">
<?=gettext("Updating...");?>
</td>
</tr>
</tbody>
</table>
<script>
$(window).on("load", function() {
function ntp_getstatus() {
scroll(0,0);
var url = "/widgets/widgets/ntp_status.widget.php";
var pars = 'updateme=yes';
jQuery.ajax(
url,
{
type: 'get',
data: pars,
complete: ntpstatuscallback
});
// Refresh the status every 1 minute
setTimeout(ntp_getstatus, 1*60*1000);
}
function ntpstatuscallback(transport) {
// The server returns formatted html code
var responseStringNtp = transport.responseText;
jQuery('#ntpstatus').prop('innerHTML',responseStringNtp);
}
// Do the first status check 1 second after the dashboard opens
setTimeout(ntp_getstatus, 1000);
});
</script>

View File

@ -1,187 +0,0 @@
<?php
/*
* Copyright (C) 2014-2023 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("guiconfig.inc");
require_once("plugins.inc.d/openvpn.inc");
function openvpn_config()
{
global $config;
$result = [];
foreach (['openvpn-server', 'openvpn-client'] as $section) {
$result[$section] = [];
if (!empty($config['openvpn'][$section])) {
foreach ($config['openvpn'][$section] as $settings) {
if (empty($settings) || isset($settings['disable'])) {
continue;
}
$server = [];
$default_port = ($section == 'openvpn-server') ? 1194 : '';
$server['port'] = !empty($settings['local_port']) ? $settings['local_port'] : $default_port;
$server['mode'] = $settings['mode'];
if (empty($settings['description'])) {
$settings['description'] = ($section == 'openvpn-server') ? 'Server' : 'Client';
}
$server['name'] = "{$settings['description']} {$settings['protocol']}:{$server['port']}";
$server['vpnid'] = $settings['vpnid'];
$result[$section][] = $server;
}
}
}
foreach ((new OPNsense\OpenVPN\OpenVPN())->Instances->Instance->iterateItems() as $key => $node) {
if (!empty((string)$node->enabled)) {
$section = "openvpn-{$node->role}";
$default_port = ($section == 'openvpn-server') ? 1194 : '';
$default_desc = ($section == 'openvpn-server') ? 'Server' : 'Client';
$server = [
'port' => !empty((string)$node->port) ? (string)$node->port : $default_port,
'mode' => (string)$node->role,
'description' => !empty((string)$node->description) ? (string)$node->description : $default_desc,
'name' => "{$node->description} {$node->proto}:{$node->port}",
'vpnid' => $key
];
$result[$section][] = $server;
}
}
return $result;
}
$openvpn_status = json_decode(configd_run('openvpn connections client,server'), true) ?? [];
$openvpn_cfg = openvpn_config();
foreach ($openvpn_cfg as $section => &$ovpncfg) {
foreach ($ovpncfg as &$item) {
$opt = ($section == 'openvpn-server') ? 'server' : 'client';
if (!empty($openvpn_status[$opt][$item['vpnid']])) {
$item = array_merge($openvpn_status[$opt][$item['vpnid']], $item);
}
}
}
?>
<script>
$("#dashboard_container").on("WidgetsReady", function() {
// link kill buttons
$(".act_kill_client").click(function(event){
event.preventDefault();
let params = {server_id: $(this).data("client-port"), session_id: $(this).data("client-ip")};
$.post('/api/openvpn/service/kill_session/', params, function(data, status){
location.reload();
});
});
});
</script>
<?php
foreach ($openvpn_cfg['openvpn-server'] as $server) :?>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th colspan="3">
<?=$server['name'];?> <?=gettext("Client connections");?>
</th>
</tr>
<tr>
<th><?=gettext("Name/Time");?></th>
<th><?=gettext("Real/Virtual IP");?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php
if (!empty($server['client_list'])):
foreach ($server['client_list'] as $conn) :?>
<tr>
<td><?=$conn['common_name'] ?? '';?><br/><?=$conn['connected_since'] ?? '';?></td>
<td><?= join('<br/>', array_filter([$conn['real_address'] ?? '', $conn['virtual_address'] ?? '', $conn['virtual_ipv6_address'] ?? ''])) ?></td>
<td>
<span class="fa fa-times fa-fw act_kill_client" data-client-port="<?=$server['vpnid'];?>"
data-client-ip="<?=$conn['real_address'];?>"
style='cursor:pointer;'
title='Kill client connection from <?=$conn['real_address']; ?>'>
</span>
</td>
</tr>
<?php
endforeach;
elseif (!empty($server['timestamp'])):?>
<tr>
<td><?=date('Y-m-d H:i:s', $server['timestamp']);?></td>
<td><?= join('<br/>', array_filter([$server['real_address'] ?? '', $server['virtual_address'] ?? '', $server['virtual_ipv6_address'] ?? ''])) ?></td>
<td>
<span class='fa fa-exchange fa-fw <?=$server['status'] == "connected" ? "text-success" : "text-danger" ;?>'></span>
</td>
</tr>
<?php
endif;?>
</tbody>
</table>
<br/>
<?php
endforeach; ?>
<?php
if (!empty($openvpn_cfg['openvpn-client'])) {?>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th colspan="3"><?= gettext('Client Instance Statistics') ?></th>
</tr>
<tr>
<th><?= gettext('Name/Time') ?></th>
<th><?= gettext('Remote/Virtual IP') ?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php
foreach ($openvpn_cfg['openvpn-client'] as $client) :?>
<tr>
<td><?=$client['name'];?><br/><?=date('Y-m-d H:i:s', $client['timestamp']);?></td>
<td><?= join('<br/>', array_filter([$client['real_address'] ?? '', $client['virtual_address'] ?? '', $client['virtual_ipv6_address'] ?? ''])) ?></td>
<td>
<span class='fa fa-exchange fa-fw <?=$client['status'] == "connected" ? "text-success" : "text-danger" ;?>'></span>
</td>
</tr>
<?php
endforeach; ?>
</tbody>
</table>
<?php
}
if (empty($openvpn_cfg['openvpn-client']) && empty($openvpn_cfg['openvpn-server'])): ?>
<table class="table table-striped table-condensed">
<tr>
<td><?= gettext('No OpenVPN instance defined or enabled.') ?></td>
</tr>
</table>
<?php endif;

View File

@ -1,100 +0,0 @@
<?php
/*
* Copyright (C) 2014 Deciso B.V.
* Copyright (C) 2009 Scott Ullrich <sullrich@gmail.com>
*
* 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");
if ($_GET['getpic']=="true") {
$pic_type_s = explode(".", $config['widgets']['picturewidget_filename']);
$pic_type = $pic_type_s[1];
if ($config['widgets']['picturewidget']) {
$data = base64_decode($config['widgets']['picturewidget']);
}
header("Content-Disposition: inline; filename=\"{$config['widgets']['picturewidget_filename']}\"");
header("Content-Type: image/{$pic_type}");
header("Content-Length: " . strlen($data));
echo $data;
exit;
}
if ($_POST) {
if (is_uploaded_file($_FILES['pictfile']['tmp_name'])) {
/* read the file contents */
$fd_pic = fopen($_FILES['pictfile']['tmp_name'], "rb");
while (($buf=fread($fd_pic, 8192)) != '') {
// Here, $buf is guaranteed to contain data
$data .= $buf;
}
fclose($fd_pic);
if (!$data) {
die("Could not read temporary file");
} else {
$picname = basename($_FILES['uploadedfile']['name']);
$config['widgets']['picturewidget'] = base64_encode($data);
$config['widgets']['picturewidget_filename'] = $_FILES['pictfile']['name'];
write_config("Picture widget saved via Dashboard.");
header(url_safe('Location: /index.php'));
exit;
}
}
}
?>
<div id="picture-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/picture.widget.php" method="post" name="iforma" enctype="multipart/form-data">
<table class="table table-striped">
<tr>
<td>
<input name="pictfile" type="file" class="btn btn-primary formbtn" id="pictfile" size="20" />
</td>
</tr>
<tr>
<td>
<input id="submit_pictfile_widget" name="submit_pictfile_widget" type="submit" class="btn btn-primary formbtn" value="<?= html_safe(gettext('Upload')) ?>" />
</td>
</tr>
</table>
</form>
</div>
<!-- hide picture if none is defined in the configuration -->
<?php
if ($config['widgets']['picturewidget_filename'] != "") :?>
<div id="picture-widgets" style="padding: 5px">
<a href='/widgets/widgets/picture.widget.php?getpic=true' target='_blank'>
<img style="border:0px solid; width:100%; height:100%" src="/widgets/widgets/picture.widget.php?getpic=true" alt="picture" />
</a>
</div>
<?php
endif ?>
<!-- needed to show the settings widget icon -->
<script>
//<![CDATA[
$("#picture-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,178 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2009 Scott Ullrich <sullrich@gmail.com>
*
* 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("simplepie/autoloader.php");
require_once("simplepie/idn/idna_convert.class.php");
function textLimit($string, $length, $replacer = '...')
{
if (strlen($string) > $length) {
return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;
}
return $string;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
$config['widgets']['rssfeed'] = str_replace("\n", ",", htmlspecialchars($pconfig['rssfeed'], ENT_QUOTES | ENT_HTML401));
$config['widgets']['rssmaxitems'] = str_replace("\n", ",", htmlspecialchars($pconfig['rssmaxitems'], ENT_QUOTES | ENT_HTML401));
$config['widgets']['rsswidgetheight'] = htmlspecialchars($pconfig['rsswidgetheight'], ENT_QUOTES | ENT_HTML401);
$config['widgets']['rsswidgettextlength'] = htmlspecialchars($pconfig['rsswidgettextlength'], ENT_QUOTES | ENT_HTML401);
write_config("Saved RSS Widget feed via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
// Use saved feed and max items
if (!empty($config['widgets']['rssfeed'])) {
$rss_feed_s = explode(",", $config['widgets']['rssfeed']);
$textarea_txt = str_replace(",", "\n", $config['widgets']['rssfeed']);
} else {
// Set a default feed if none exists
$rss_feed_s = 'https://forum.opnsense.org/index.php?board=11.0&action=.xml;limit=20;type=rss2';
$config['widgets']['rssfeed'] = $rss_feed_s;
$textarea_txt = '';
}
if (!empty($config['widgets']['rssmaxitems']) && is_numeric($config['widgets']['rssmaxitems'])) {
$max_items = $config['widgets']['rssmaxitems'];
} else {
$max_items = 10;
}
if (!empty($config['widgets']['rsswidgetheight']) && is_numeric($config['widgets']['rsswidgetheight'])) {
$rsswidgetheight = $config['widgets']['rsswidgetheight'];
} else {
$rsswidgetheight = 300;
}
if (!empty($config['widgets']['rsswidgettextlength']) && is_numeric($config['widgets']['rsswidgettextlength'])) {
$rsswidgettextlength = $config['widgets']['rsswidgettextlength'];
} else {
$rsswidgettextlength = 140; // oh twitter, how do we love thee?
}
?>
<div id="rss-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/rss.widget.php" method="post" name="iformc">
<table class="table table-striped">
<tr>
<td colspan="2">
<textarea name="rssfeed" id="rssfeed" cols="40" rows="3" style="max-width:100%;"><?=$textarea_txt;?></textarea>
</td>
</tr>
<tr>
<td>
<?= gettext('Display number of items:') ?>
</td>
<td>
<select name='rssmaxitems' id='rssmaxitems'>
<option value='<?= $max_items ?>'><?= $max_items ?></option>
<?php
for ($x=100; $x<5100; $x=$x+100) {
echo "<option value='{$x}'>{$x}</option>\n";
}?>
</select>
</td>
</tr>
<tr>
<td>
<?= gettext('Widget height:') ?>
</td>
<td>
<select name='rsswidgetheight' id='rsswidgetheight'>
<option value='<?= $rsswidgetheight ?>'><?= $rsswidgetheight ?>px</option>
<?php
for ($x=100; $x<5100; $x=$x+100) {
echo "<option value='{$x}'>{$x}px</option>\n";
}?>
</select>
</td>
</tr>
<tr>
<td>
<?= gettext('Show how many characters from story:') ?>
</td>
<td>
<select name='rsswidgettextlength' id='rsswidgettextlength'>
<option value='<?= $rsswidgettextlength ?>'><?= $rsswidgettextlength ?></option>
<?php
for ($x=10; $x<5100; $x=$x+10) {
echo "<option value='{$x}'>{$x}</option>\n";
}?>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<input id="submitc" name="submitc" type="submit" class="btn btn-primary formbtn" value="<?= html_safe(gettext('Save')) ?>" />
</td>
</tr>
</table>
</form>
</div>
<div id="rss-widgets" style="padding: 5px; height: <?=$rsswidgetheight?>px; overflow:scroll;">
<?php
@mkdir('/tmp/simplepie');
@mkdir('/tmp/simplepie/cache');
exec("chmod a+rw /tmp/simplepie/.");
exec("chmod a+rw /tmp/simplepie/cache/.");
$feed = new SimplePie();
$feed->set_cache_location("/tmp/simplepie/");
$feed->set_feed_url($rss_feed_s);
$feed->init();
$feed->handle_content_type();
$feed->strip_htmltags();
$counter = 1;
try {
foreach ($feed->get_items() as $item) {
echo "<a target='blank' href='" . $item->get_permalink() . "'>" . $item->get_title() . "</a><br />";
$content = $item->get_content();
$content = strip_tags($content);
echo textLimit($content, $rsswidgettextlength) . "<br />";
echo "Source: <a target='_blank' href='" . $item->get_permalink() . "'>".$feed->get_title()."</a><br />";
$counter++;
if ($counter > $max_items) {
break;
}
echo "<hr/>";
}
} catch (Error $e) {
echo gettext("Unable to fetch rss feed");
}
?>
</div>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#rss-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,153 +0,0 @@
<?php
/*
* Copyright (C) 2014-2023 Deciso B.V.
* Copyright (C) 2007 Sam Wenham
* Copyright (C) 2005-2006 Colin Smith <ethethlay@gmail.com>
* Copyright (C) 2004-2005 Scott Ullrich <sullrich@gmail.com>
* 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");
require_once("interfaces.inc");
if (isset($_POST['servicestatusfilter'])) {
$config['widgets']['servicestatusfilter'] = $_POST['servicestatusfilter'];
write_config("Saved Service Status Filter via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
?>
<script>
$(window).on('load', function () {
function control_services(action, id, title, icon) {
return '<span data-service_action="' + action + '" data-service="' + id + '" ' +
'class="btn btn-xs btn-default srv_status_act2" title="' + title + '">' +
'<i class="fa fa-' + icon + ' fa-fw"></i></span>';
}
function fetch_services() {
ajaxGet('/api/core/service/search', {}, function(data, status) {
if (data['rows'] !== undefined) {
let $table = $('#service_widget_table');
let items = {};
$table.find('tr[data-service-widget-id]').each(function() {
let $item = $(this);
items[$item.attr('data-service-widget-id')] = $item;
});
$.each(data['rows'], function(key, value) {
let $item = items.hasOwnProperty(value.id) ? items[value.id] : null;
if (!$item) {
$item = $('<tr>').attr('data-service-widget-id', value.id);
$item.append($('<td/>'));
$item.append($('<td/>'));
$item.append($('<td style="width: 3em;"/>'));
$item.append($('<td style="width: 5em; white-space: nowrap;"/>'));
$item.hide();
$table.append($item);
items[value.id] = $item;
}
$item.find('td:eq(0)').text(value.name);
$item.find('td:eq(1)').text(value.description);
if (value.running) {
$item.find('td:eq(2)').html('<span class="label label-opnsense label-opnsense-xs label-success pull-right" title="<?= gettext('Running') ?>"><i class="fa fa-play fa-fw"></i></span>');
} else {
$item.find('td:eq(2)').html('<span class="label label-opnsense label-opnsense-xs label-danger pull-right" title="<?= gettext('Stopped') ?>"><i class="fa fa-stop fa-fw"></i></span>');
}
if (value.locked) {
$item.find('td:eq(3)').html(control_services('restart', value.id, "<?= gettext('Restart') ?>", 'repeat'));
} else if (value.running) {
$item.find('td:eq(3)').html(control_services('restart', value.id, "<?= gettext('Restart') ?>", 'repeat') +
control_services('stop', value.id, "<?= gettext('Stop') ?>", 'stop'));
} else {
$item.find('td:eq(3)').html(control_services('start', value.id, "<?= gettext('Start') ?>", 'play'));
}
let hide_items = $("#servicestatusfilter").val().split(',');
if (!hide_items.includes(value.name)) {
$item.show();
} else {
$item.hide();
}
});
$('.srv_status_act2').click(function (event) {
event.preventDefault();
let url = '/api/core/service/' + $(this).data('service_action') + '/' + $(this).data('service');
$("#OPNsenseStdWaitDialog").modal('show');
$.post(url, {}, function (data) {
// refresh page after service action via server
location.reload(true);
});
});
}
});
setTimeout(fetch_services, 5000);
}
fetch_services();
});
</script>
<!-- service options -->
<div id="services_status-settings" style="display:none;">
<form action="/widgets/widgets/services_status.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<thead>
<tr>
<th><?= gettext('Comma-separated list of services to NOT display in the widget') ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="servicestatusfilter" id="servicestatusfilter" value="<?= html_safe($config['widgets']['servicestatusfilter'] ?? '') ?>" /></td>
</tr>
<tr>
<td>
<input id="submitd" name="submitd" type="submit" class="btn btn-primary" value="<?= html_safe(gettext('Save')) ?>" />
</td>
</tr>
</tbody>
</table>
</form>
</div>
<!-- service table -->
<table id="service_widget_table" class="table table-striped table-condensed">
<thead>
<tr>
<th><?= gettext('Service') ?></th>
<th><?= gettext('Description') ?></th>
<th style="width:3em;"></th>
<th style="width:5em;"></th>
</tr>
</thead>
<tbody>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#services_status-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,289 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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");
?>
<script src="<?= cache_safe('/ui/js/moment-with-locales.min.js') ?>"></script>
<script>
var system_information_widget_cpu_data = []; // reference to measures
var system_information_widget_cpu_chart = null; // reference to chart object
var system_information_widget_cpu_chart_data = null; // reference to chart data object
/**
* update cpu chart
*/
function system_information_widget_cpu_update(sender, data)
{
// update cpu usage progress-bar
var cpu_perc = parseInt(data['cpu']['used']);
$("#system_information_widget_cpu .progress-bar").css("width", cpu_perc + "%").attr("aria-valuenow", cpu_perc + "%");
$("#system_information_widget_cpu .cpu_text").html(cpu_perc + " % ");
// push new measurement, keep a maximum of 100 measures in
system_information_widget_cpu_data.push(parseInt(data['cpu']['used']));
if (system_information_widget_cpu_data.length > 100) {
system_information_widget_cpu_data.shift();
} else if (system_information_widget_cpu_data.length == 1) {
system_information_widget_cpu_data.push(parseInt(data['cpu']['used']));
}
let chart_data = [];
let count = 0;
system_information_widget_cpu_data.map(function(item){
chart_data.push([count, item]);
count++;
});
system_information_widget_cpu_chart_data.datum([{'key':'cpu', 'values':chart_data}]).transition().duration(500).call(system_information_widget_cpu_chart);
}
/**
* update widget
*/
function system_information_widget_update(sender, data)
{
// update cpu usage chart
system_information_widget_cpu_update(sender, data);
$("#system_information_widget_firmware").html(data['firmware']);
$("#system_information_widget_cpu_type").html(data['cpu']['model'] + ' ('+data['cpu']['cores']+' cores, '+data['cpu']['cpus']+' threads)');
var uptime_days = parseInt(moment.duration(parseInt(data['uptime']), 'seconds').asDays());
var uptime_str = "";
if (uptime_days > 0) {
uptime_str += uptime_days + " <?=html_safe(gettext('days'));?> ";
}
uptime_str += moment.utc(parseInt(data['uptime'])*1000).format("HH:mm:ss");
$("#system_information_widget_uptime").html(uptime_str);
$("#system_information_widget_datetime").html(data['date_frmt']);
$("#system_information_widget_last_config_change").html(data['config']['last_change_frmt']);
$("#system_information_widget_versions").html(data['versions'].join('<br/>'));
var states_perc = parseInt((parseInt(data['kernel']['pf']['states']) / parseInt(data['kernel']['pf']['maxstates']))*100);
$("#system_information_widget_states .progress-bar").css("width", states_perc + "%").attr("aria-valuenow", states_perc + "%");
var states_text = states_perc + " % " + "( " + data['kernel']['pf']['states'] + "/" + data['kernel']['pf']['maxstates'] + " )";
$("#system_information_widget_states .state_text").html(states_text);
var mbuf_perc = parseInt((parseInt(data['kernel']['mbuf']['total']) / parseInt(data['kernel']['mbuf']['max']))*100);
$("#system_information_widget_mbuf .progress-bar").css("width", mbuf_perc + "%").attr("aria-valuenow", mbuf_perc + "%");
var mbuf_text = mbuf_perc + " % " + "( " + data['kernel']['mbuf']['total'] + "/" + data['kernel']['mbuf']['max'] + " )";
$("#system_information_widget_mbuf .state_text").html(mbuf_text);
$("#system_information_widget_load").html(data['cpu']['load'].join(','));
var mem_perc = parseInt(data['kernel']['memory']['used'] / data['kernel']['memory']['total']*100);
$("#system_information_widget_memory .progress-bar").css("width", mem_perc + "%").attr("aria-valuenow", mem_perc + "%");
var mem_text = mem_perc + " % " + "( " + parseInt(data['kernel']['memory']['used']/1024/1024) + "/";
mem_text += parseInt(data['kernel']['memory']['total']/1024/1024) + " MB )";
if (data['kernel']['memory']['arc_txt'] !== undefined) {
mem_text += " { " + data['kernel']['memory']['arc_txt'] + " }";
}
$("#system_information_widget_memory .state_text").html(mem_text);
// swap usage
let counter = 0;
$("#system_information_widget_swap .swap_devices").html("");
data['disk']['swap'].map(function(swap) {
var html = $("#system_information_widget_swap .swap_template").html();
html = html.replace('swap_id_sequence', 'system_information_widget_swap_'+counter);
$("#system_information_widget_swap .swap_devices").html($("#system_information_widget_swap .swap_devices").html() + html);
var swap_perc = parseInt(swap['used'] * 100 / swap['total']);
$("#system_information_widget_swap_"+counter+' .progress-bar').css("width", swap_perc + "%").attr("aria-valuenow", swap_perc + "%");
var swap_text = swap_perc + " % " + "( " + parseInt(swap['used']/1024) + "/";
swap_text += parseInt(swap['total']/1024) + " MB )";
$("#system_information_widget_swap_"+counter+" .state_text").html(swap_text);
counter += 1;
});
if (counter != 0) {
$("#system_information_widget_swap_info").show();
} else {
$("#system_information_widget_swap_info").hide();
}
// disk usage
counter = 0;
$("#system_information_widget_disk .disk_devices").html("");
data['disk']['devices'].map(function(device) {
var html = $("#system_information_widget_disk .disk_template").html();
html = html.replace('disk_id_sequence', 'system_information_widget_disk_'+counter);
$("#system_information_widget_disk .disk_devices").html($("#system_information_widget_disk .disk_devices").html() + html);
var disk_perc = device['capacity'].replace('%', '');
$("#system_information_widget_disk_"+counter+' .progress-bar').css("width", disk_perc + "%").attr("aria-valuenow", disk_perc + "%");
var disk_text = device['capacity'] + ' ' + device['mountpoint'] + ' ['+device['type']+'] (' + device['used'] +'/' + device['size'] + ')';
$("#system_information_widget_disk_"+counter+" .state_text").html(disk_text);
counter += 1;
});
if (counter != 0) {
$("#system_information_widget_disk_info").show();
} else {
$("#system_information_widget_disk_info").hide();
}
}
/**
* page setup
*/
$(window).on("load", function() {
// draw cpu graph
nv.addGraph(function() {
system_information_widget_cpu_chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.useInteractiveGuideline(false)
.interactive(false)
.showLegend(false)
.showXAxis(false)
.clipEdge(true)
.margin({top:5,right:5,bottom:5,left:25});
system_information_widget_cpu_chart.yAxis.tickFormat(d3.format('.0'));
system_information_widget_cpu_chart.forceY([0, 100]);
system_information_widget_cpu_chart_data = d3.select("#system_information_widget_chart_cpu_usage svg").datum([{'key':'cpu', 'values':[[0, 0]]}]);
system_information_widget_cpu_chart_data.transition().duration(500).call(system_information_widget_cpu_chart);
});
});
</script>
<table class="table table-striped table-condensed" data-plugin="system" data-callback="system_information_widget_update">
<tbody>
<tr>
<td style="width:30%"><?=gettext("Name");?></td>
<td><?=$config['system']['hostname'] . "." . $config['system']['domain']; ?></td>
</tr>
<tr>
<td><?=gettext("Versions");?></td>
<td id="system_information_widget_versions"></td>
</tr>
<tr>
<td><?= gettext('Updates') ?></td>
<td>
<a href='/ui/core/firmware#checkupdate'><span id="system_information_widget_firmware"><?= gettext('Retrieving internal update status...') ?></span></a>
</td>
</tr>
<tr>
<td><?=gettext("CPU type");?></td>
<td id="system_information_widget_cpu_type"></td>
</tr>
<tr>
<td><?=gettext("CPU usage");?></td>
<td>
<div id="system_information_widget_chart_cpu_usage">
<svg style="height:40px;"></svg>
</div>
</td>
</tr>
<tr>
<td><?=gettext("Load average");?></td>
<td id="system_information_widget_load"></td>
</tr>
<tr>
<td><?=gettext("Uptime");?></td>
<td id="system_information_widget_uptime"></td>
</tr>
<tr>
<td><?=gettext("Current date/time");?></td>
<td id="system_information_widget_datetime"></td>
</tr>
<tr>
<td><?=gettext("Last config change");?></td>
<td id="system_information_widget_last_config_change"></td>
</tr>
<tr>
<td><?=gettext("CPU usage");?></td>
<td id="system_information_widget_cpu">
<div class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="cpu_text" style="position:absolute;right:0;left:0;"></span>
</div>
</td>
</tr>
<tr>
<td><?=gettext("State table size");?></td>
<td id="system_information_widget_states">
<div class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="state_text" style="position:absolute;right:0;left:0;"></span>
</div>
</td>
</tr>
<tr>
<td><?=gettext("MBUF usage");?></td>
<td id="system_information_widget_mbuf">
<div class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="state_text" style="position:absolute;right:0;left:0;"></span>
</div>
</td>
</tr>
<tr>
<td><?=gettext("Memory usage");?></td>
<td id="system_information_widget_memory">
<div class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="state_text" style="position:absolute;right:0;left:0;"></span>
</div>
</td>
</tr>
<tr id="system_information_widget_swap_info">
<td><?=gettext("SWAP usage");?></td>
<td id="system_information_widget_swap">
<div style="display:none" class="swap_template">
<!-- template -->
<div id="swap_id_sequence" class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="state_text" style="position:absolute;right:0;left:0;"></span>
</div>
<div style="height:1px;">
</div>
</div>
<div class="swap_devices">
</div>
</td>
</tr>
<tr id="system_information_widget_disk_info">
<td><?=gettext("Disk usage");?></td>
<td id="system_information_widget_disk">
<div style="display:none" class="disk_template">
<!-- template -->
<div id="disk_id_sequence" class="progress" style="text-align:center;">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%; z-index: 0;"></div>
<span class="state_text" style="position:absolute;right:0;left:0;"></span>
</div>
<div style="height:1px;">
</div>
</div>
<div class="disk_devices">
</div>
</td>
</tr>
</tbody>
</table>

View File

@ -1,199 +0,0 @@
<?php
/*
* Copyright (C) 2021 A. Kulikov <kulikov.a@gmail.com>
* Copyright (C) 2015 S. Linke <dev@devsash.de>
* 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");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input_errors = array();
if (is_numeric($_POST['systemlogfiltercount'])) {
$config['widgets']['systemlogfiltercount'] = $_POST['systemlogfiltercount'];
}
if (is_numeric($_POST['systemlogentriesupdateinterval'])) {
$config['widgets']['systemlogupdateinterval'] = $_POST['systemlogentriesupdateinterval'];
}
if (!empty($_POST['systemlogentriesfilter'])) {
if (!preg_match('/^[0-9,a-z,A-Z *\-_.\#]*$/', $_POST['systemlogentriesfilter'])) {
$input_errors[] = gettext("Query filter string is invalid");
}
}
if (!empty($_POST['systemlogseverity'])) {
$config['widgets']['systemlogseverity'] = $_POST['systemlogseverity'];
}
if (count($input_errors) == 0) {
$config['widgets']['systemlogentriesfilter'] = $_POST['systemlogentriesfilter'];
write_config("System Log Widget settings saved");
header(url_safe('Location: /index.php'));
exit;
}
for ($i = 0; $i < count($input_errors); $i++) {
setcookie("inputerrors[$i]", $input_errors[$i], 0, '/');
}
header(url_safe('Location: /index.php'));
exit;
}
$systemlogEntriesToFetch = isset($config['widgets']['systemlogfiltercount']) ? $config['widgets']['systemlogfiltercount'] : 20;
$systemlogupdateinterval = isset($config['widgets']['systemlogupdateinterval']) ? $config['widgets']['systemlogupdateinterval'] : 10;
$systemlogseverity = isset($config['widgets']['systemlogseverity']) ? $config['widgets']['systemlogseverity'] : "Debug";
$systemlogentriesfilter = isset($config['widgets']['systemlogentriesfilter']) ? $config['widgets']['systemlogentriesfilter'] : "";
if (isset($_COOKIE['inputerrors'])) {
foreach ($_COOKIE['inputerrors'] as $i => $value) {
$input_errors[] = $value;
setcookie("inputerrors[$i]", "", time() - 3600);
}
}
$prios = array('Emergency', 'Alert', 'Critical', 'Error', 'Warning', 'Notice', 'Informational', 'Debug');
?>
<div id="system_log-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/system_log.widget.php" method="post" name="iform">
<table class="table table-striped">
<tr>
<td><?= gettext('Number of Log lines to display') ?>:</td>
<td>
<select name="systemlogfiltercount" id="systemlogfiltercount" class="selectpicker_widget" data-live-search="true" data-size="5">
<?php for ($i = 1; $i <= 50; $i++) {?>
<option value="<?= html_safe($i) ?>" <?= $systemlogEntriesToFetch == $i ? 'selected="selected"' : '' ?>><?= html_safe($i) ?></option>
<?php } ?>
</select>
</td>
</tr>
<tr>
<td><?= gettext('Update interval in seconds:') ?></td>
<td>
<select id="systemlogentriesupdateinterval" name="systemlogentriesupdateinterval" class="selectpicker_widget" data-live-search="true" data-size="5">
<?php for ($i = 5; $i <= 30; $i++) {?>
<option value="<?= html_safe($i) ?>" <?= $systemlogupdateinterval == $i ? 'selected="selected"' : '' ?>><?= html_safe($i) ?></option>
<?php } ?>
</select>
</td>
</tr>
<tr>
<td><?= gettext('Minimum severity:') ?></td>
<td>
<select name="systemlogseverity" id="severity_filter" data-title="<?=html_safe(gettext("Severity")); ?>" class="selectpicker_widget" data-width="200px">
<?php foreach ($prios as $prio) {?>
<option value="<?= html_safe($prio) ?>" <?= $systemlogseverity == $prio ? 'selected="selected"' : '' ?>><?= html_safe(gettext($prio)) ?></option>
<?php } ?>
</select>
</td>
</tr>
<tr>
<td><?= gettext('Log query filter:') ?></td>
<td>
<input id="systemlogentriesfilter" name="systemlogentriesfilter" type="text" value="<?=$systemlogentriesfilter?>" placeholder="<?=$systemlogentriesfilter?>" />
</td>
</tr>
<tr>
<td>
<input id="submit_system_log_widget" name="submit_system_log_widget" type="submit" class="btn btn-primary formbtn" style="float: left;" value="<?= html_safe(gettext('Save')) ?>">
</td>
<td></td>
</tr>
</table>
</form>
</div>
<div style="overflow: overlay;">
<?php
if (isset($input_errors) && count($input_errors) > 0) {
print_input_errors($input_errors);
}
?>
</div>
<div id="system_log-widgets" class="content-box table-responsive">
<table id="system_log_table" class="table table-striped">
<tbody></tbody>
</table>
</div>
<script>
function fetch_system_log(rowCount, refresh_interval_ms, requestSeverity) {
//it is more correct to pass the filter value to the function (without searching the value every time). but this method allows to "live" test the filter value before saving
let filterstring = "";
if ($("#systemlogentriesfilter").val()) {
filterstring = $("#systemlogentriesfilter").val();
}
$.ajax({
url: 'api/diagnostics/log/core/system',
data: 'current=1&rowCount=' + rowCount + '&severity=' + requestSeverity +'&searchPhrase=' + filterstring,
type: 'POST'
})
.done(function (data, status) {
$(".system_log_entry").remove();
let entry;
let system_log_tr = "";
if (typeof data.rows !== "undefined") {
if (data.rows.length == 0) {
system_log_tr += '<tr class="system_log_entry"><td style="text-align: center;"><?=html_safe(gettext("No results found!")); ?></td></tr>';
} else {
while ((entry = data.rows.shift())) {
system_log_tr += '<tr class="system_log_entry"><td style="white-space: nowrap;">' + entry['timestamp'] + '<br>[' + entry['severity'] + ']<br>' + entry['process_name'].split('[')[0] + '</td><td>' + entry['line'] + '</td></tr>';
}
}
} else {
system_log_tr += '<tr class="system_log_entry"><td style="text-align: center;"><?=html_safe(gettext("An empty response from the server.")); ?></td></tr>';
}
$("#system_log_table tbody").append(system_log_tr);
setTimeout(fetch_system_log, refresh_interval_ms, rowCount, refresh_interval_ms, requestSeverity);
})
.fail(function (jqXHR, textStatus) {
console.log("Request failed: " + textStatus);
setTimeout(fetch_system_log, refresh_interval_ms, rowCount, refresh_interval_ms, requestSeverity);
})
}
$("#dashboard_container").on("WidgetsReady", function () {
// needed to display the widget settings menu
$("#system_log-configure").removeClass("disabled");
var rowCount = $("#systemlogfiltercount").val();
var refresh_interval_ms = parseInt($("#systemlogentriesupdateinterval").val()) * 1000;
refresh_interval_ms = (isNaN(refresh_interval_ms) || refresh_interval_ms < 5000 || refresh_interval_ms > 60000) ? 10000 : refresh_interval_ms;
let filterstring = "";
severities = $('#severity_filter option').map(function(){
return (this.value ? this.value : null);
}).get();
let selectedSeverity = $('#severity_filter').val();
let requestSeverity = severities.slice(0,severities.indexOf(selectedSeverity) + 1).join(',');
let title = selectedSeverity == "Debug" ? '' : '&nbsp;&nbsp;[' + $('#severity_filter option:selected').text() + ']';
if ($("#systemlogentriesfilter").val()) {
filterstring = $("#systemlogentriesfilter").val();
title += '&nbsp;&nbsp;filtered with "' + filterstring + '"';
}
$('#system_log').find('h3').append(title);
fetch_system_log(rowCount, refresh_interval_ms, requestSeverity);
})
</script>

View File

@ -1,228 +0,0 @@
<?php
/*
* Copyright (C) 2014-2016 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("guiconfig.inc");
config_read_array('widgets', 'thermal_sensors_widget');
function fix_temp_value($value, int $default): int
{
if (is_numeric($value) && (int)$value == $value && $value >= 0 and $value <= 100) {
return (int)$value;
} else {
return $default;
}
}
function fix_checkbox_value($value): bool
{
if ($value !== '') {
return true;
} else {
return false;
}
}
$fields = [
['name' => 'thermal_sensors_widget_zone_warning_threshold', 'default' => 70, 'processFunc' => 'fix_temp_value'],
['name' => 'thermal_sensors_widget_zone_critical_threshold', 'default' => 80, 'processFunc' => 'fix_temp_value'],
['name' => 'thermal_sensors_widget_core_warning_threshold', 'default' => 70, 'processFunc' => 'fix_temp_value'],
['name' => 'thermal_sensors_widget_core_critical_threshold', 'default' => 80, 'processFunc' => 'fix_temp_value'],
['name' => 'thermal_sensors_widget_show_one_core_temp', 'default' => false, 'processFunc' => 'fix_checkbox_value'],
['name' => 'thermal_sensors_widget_show_temp_in_fahrenheit', 'default' => false, 'processFunc' => 'fix_checkbox_value'],
];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = [];
foreach ($fields as $field) {
$pconfig[$field['name']] = !empty($config['widgets']['thermal_sensors_widget'][$field['name']]) ? $config['widgets']['thermal_sensors_widget'][$field['name']] : $field['default'];
}
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
foreach ($fields as $field) {
$newValue = $field['processFunc']($_POST[$field['name']] ?? '', $field['default']);
$config['widgets']['thermal_sensors_widget'][$field['name']] = $newValue;
}
write_config("Thermal sensors widget saved via Dashboard.");
header(url_safe('Location: /index.php'));
exit;
}
?>
<script>
'use strict';
function thermal_sensors_widget_update(sender, data) {
let firstCore = true;
data.map(function (sensor) {
// Skip if the user only wants one core temperature and we have already showed one.
if (!firstCore) {
return;
}
if (sensor['type'] === 'core' && $('#thermal_sensors_widget_show_one_core_temp').attr('checked') === 'checked') {
firstCore = false;
}
const tr_id = "thermal_sensors_widget_" + sensor['device'].replace(/\./g, '_');
let tbody = sender.find('tbody');
if (tbody.find('#' + tr_id).length === 0) {
let tr = $('<tr>');
tr.attr('id', tr_id);
let td = $('<td>');
td.html($('#thermal_sensors_widget_progress_bar').html());
tr.append(td);
tbody.append(tr);
}
// probe warning / danger temp
let danger_temp, warning_temp;
if (sensor['type'] === 'core') {
danger_temp = parseInt($('#thermal_sensors_widget_core_critical_threshold').val());
warning_temp = parseInt($('#thermal_sensors_widget_core_warning_threshold').val());
} else {
danger_temp = parseInt($('#thermal_sensors_widget_zone_critical_threshold').val());
warning_temp = parseInt($('#thermal_sensors_widget_zone_warning_threshold').val());
}
// progress bar style
let progressBar = $('#' + tr_id + ' .progress-bar');
const tempIntValue = parseInt(sensor['temperature']);
if (tempIntValue > danger_temp) {
progressBar.removeClass('progress-bar-success')
.removeClass('progress-bar-warning')
.removeClass('progress-bar-danger')
.addClass('progress-bar-danger');
} else if (tempIntValue > warning_temp) {
progressBar.removeClass('progress-bar-success')
.removeClass('progress-bar-warning')
.removeClass('progress-bar-danger')
.addClass('progress-bar-warning');
} else {
progressBar.removeClass('progress-bar-success')
.removeClass('progress-bar-warning')
.removeClass('progress-bar-danger')
.addClass('progress-bar-success');
}
// update bar
if ($('#thermal_sensors_widget_show_temp_in_fahrenheit').attr('checked') === 'checked') {
progressBar.html(Number.parseFloat(1.8 * sensor['temperature'] + 32).toFixed(1) + ' &deg;F');
} else {
progressBar.html(sensor['temperature'] + ' &deg;C');
}
progressBar.css("width", tempIntValue + "%").attr("aria-valuenow", tempIntValue + "%");
// update label
$('#' + tr_id + ' .info').html(sensor['type_translated'] + ' ' + sensor['device_seq'] + ' <small>(' + sensor['device'] + ')<small>');
});
}
</script>
<div id="thermal_sensors-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/thermal_sensors.widget.php" method="post" id="iform_thermal_sensors_settings" name="iform_thermal_sensors_settings">
<table class="table table-striped">
<thead>
<tr>
<th colspan="2"><?= gettext('Thresholds in °C (1 to 100):') ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?= gettext('Zone Warning:') ?></td>
<td>
<input type="text" id="thermal_sensors_widget_zone_warning_threshold" name="thermal_sensors_widget_zone_warning_threshold" value="<?= $pconfig['thermal_sensors_widget_zone_warning_threshold']; ?>" />
</td>
</tr>
<tr>
<td><?= gettext('Zone Critical:') ?></td>
<td>
<input type="text" id="thermal_sensors_widget_zone_critical_threshold" name="thermal_sensors_widget_zone_critical_threshold" value="<?= $pconfig['thermal_sensors_widget_zone_critical_threshold']; ?>" />
</td>
</tr>
<tr>
<td><?= gettext('Core Warning:') ?></td>
<td>
<input type="text" id="thermal_sensors_widget_core_warning_threshold" name="thermal_sensors_widget_core_warning_threshold" value="<?= $pconfig['thermal_sensors_widget_core_warning_threshold']; ?>" />
</td>
</tr>
<tr>
<td><?= gettext('Core Critical:') ?></td>
<td>
<input type="text" id="thermal_sensors_widget_core_critical_threshold" name="thermal_sensors_widget_core_critical_threshold" value="<?= $pconfig['thermal_sensors_widget_core_critical_threshold']; ?>" />
</td>
</tr>
<tr>
<td></td>
<td>
<input type="checkbox" id="thermal_sensors_widget_show_one_core_temp" name="thermal_sensors_widget_show_one_core_temp" <?=$pconfig['thermal_sensors_widget_show_one_core_temp'] ? 'checked="checked"' : ''; ?>/>
<?= gettext('Only show first found CPU core temperature') ?>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="checkbox" id="thermal_sensors_widget_show_temp_in_fahrenheit" name="thermal_sensors_widget_show_temp_in_fahrenheit" <?=$pconfig['thermal_sensors_widget_show_temp_in_fahrenheit'] ? 'checked="checked"' : ''; ?>/>
<?= gettext('Display temperature in fahrenheit') ?>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" id="thermal_sensors_widget_submit" name="thermal_sensors_widget_submit" class="btn btn-primary formbtn" value="<?= html_safe(gettext('Save')) ?>" />
</td>
</tr>
<tr>
<td colspan="2">
<span>* <?= sprintf(gettext('You can configure a proper Thermal Sensor / Module %shere%s.'),'<a href="system_advanced_misc.php">','</a>') ?></span>
</td>
</tr>
</tbody>
</table>
</form>
</div>
<!-- template progress bar used for all constructed items in thermal_sensors_widget_update() -->
<div style="display:none" id="thermal_sensors_widget_progress_bar">
<div class="progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div>
</div>
<span class="info">
</span>
</div>
<table class="table table-striped table-condensed" data-plugin="temperature" data-callback="thermal_sensors_widget_update">
<tbody>
</tbody>
</table>
<!-- needed to display the widget settings menu -->
<script>
//<![CDATA[
$("#thermal_sensors-configure").removeClass("disabled");
//]]>
</script>

View File

@ -1,272 +0,0 @@
<?php
/*
* Copyright (C) 2014-2021 Deciso B.V.
* Copyright (C) 2007 Scott Dale
* Copyright (C) 2004-2005 T. Lechat <dev@lechat.org>
* Copyright (C) 2004-2005 Manuel Kasper <mk@neon1.net>
* Copyright (C) 2004-2005 Jonathan Watt <jwatt@jwatt.org>
* 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("widgets/include/interface_list.inc");
require_once("interfaces.inc");
$interfaces = get_configured_interface_with_descr();
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = array();
$pconfig['traffic_graphs_interfaces'] = !empty($config['widgets']['traffic_graphs_interfaces']) ?
explode(',', $config['widgets']['traffic_graphs_interfaces']) : ['lan', 'wan'];
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pconfig = $_POST;
if (!empty($pconfig['traffic_graphs_interfaces'])) {
$config['widgets']['traffic_graphs_interfaces'] = implode(',', $pconfig['traffic_graphs_interfaces']);
} elseif (isset($config['widgets']['traffic_graphs_interfaces'])) {
unset($config['widgets']['traffic_graphs_interfaces']);
}
write_config("Saved Widget Interface List via Dashboard");
header(url_safe('Location: /index.php'));
exit;
}
?>
<script src="<?=cache_safe('/ui/js/chart.min.js');?>"></script>
<script src="<?=cache_safe('/ui/js/chartjs-plugin-streaming.min.js');?>"></script>
<script src="<?=cache_safe('/ui/js/chartjs-plugin-colorschemes.js');?>"></script>
<script src="<?=cache_safe('/ui/js/moment-with-locales.min.js');?>"></script>
<script src="<?=cache_safe('/ui/js/chartjs-adapter-moment.js');?>"></script>
<link rel="stylesheet" type="text/css" href="<?=cache_safe(get_themed_filename('/css/chart.css'));?>" rel="stylesheet" />
<script>
/**
* page setup
*/
$("#dashboard_container").on("WidgetsReady", function() {
function set_alpha(color, opacity) {
const op = Math.round(Math.min(Math.max(opacity || 1, 0), 1) * 255);
return color + op.toString(16).toUpperCase();
}
function format_field(value) {
if (!isNaN(value) && value > 0) {
let fileSizeTypes = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];
let ndx = Math.floor(Math.log(value) / Math.log(1000) );
if (ndx > 0) {
return (value / Math.pow(1000, ndx)).toFixed(2) + ' ' + fileSizeTypes[ndx];
} else {
return value.toFixed(2);
}
} else {
return "";
}
}
/**
* create new traffic chart
*/
function traffic_graph(target, init_data) {
// setup legend
let all_datasets = [];
Object.keys(init_data.interfaces).forEach(function(intf) {
all_datasets.push({
label: init_data.interfaces[intf].name,
hidden: true,
borderColor: init_data.interfaces[intf].color,
backgroundColor: init_data.interfaces[intf].color,
pointHoverBackgroundColor: init_data.interfaces[intf].color,
pointHoverBorderColor: init_data.interfaces[intf].color,
pointBackgroundColor: init_data.interfaces[intf].color,
pointBorderColor: init_data.interfaces[intf].color,
intf: intf,
last_time: init_data.time,
last_data: init_data.interfaces[intf][target.data('src_field')],
src_field: target.data('src_field'),
data: []
});
});
// new chart
var ctx = target[0].getContext('2d');
var config = {
type: 'line',
data: {
datasets: all_datasets
},
options: {
maintainAspectRatio: false,
elements: {
line: {
fill: true,
cubicInterpolationMode: 'monotone',
clip: 0
}
},
scales: {
x: {
time: {
tooltipFormat:'HH:mm:ss',
unit: 'second',
minUnit: 'second',
displayFormats: {
second: 'HH:mm:ss',
minute: 'HH:mm:ss'
}
},
type: 'realtime',
realtime: {
duration: 50000,
refresh: 5000,
delay: 5000
},
},
y: {
ticks: {
callback: function (value, index, values) {
return format_field(value);
}
}
}
},
hover: {
mode: 'nearest',
intersect: false
},
plugins: {
tooltip: {
mode: 'nearest',
intersect: false,
callbacks: {
label: function(context) {
return context.dataset.label + ": " + format_field(context.dataset.data[context.dataIndex].y).toString();
}
}
},
legend: {
display: false,
},
title: {
display: false
},
streaming: {
frameRate: 30
},
colorschemes: {
scheme: 'tableau.Classic10'
}
}
}
};
return new Chart(ctx, config);
}
// register traffic update event
ajaxGet('/api/diagnostics/traffic/interface',{}, function(data, status){
$( document ).on( "updateTrafficCharts", {
charts: [
traffic_graph($("#rxChart"), data),
traffic_graph($("#txChart"), data)
]
}, function( event, data) {
let charts = event.data.charts;
for (var i =0 ; i < charts.length; ++i) {
let this_chart = charts[i];
Object.keys(data.interfaces).forEach(function(intf) {
this_chart.config.data.datasets.forEach(function(dataset) {
if (dataset.intf == intf) {
let calc_data = data.interfaces[intf][dataset.src_field];
let elapsed_time = data.time - dataset.last_time;
dataset.hidden = !$("#traffic_graphs_interfaces").val().includes(intf);
dataset.data.push({
x: Date.now(),
y: Math.round(((calc_data - dataset.last_data) / elapsed_time) * 8, 0)
});
dataset.last_time = data.time;
dataset.last_data = calc_data;
return;
}
});
});
this_chart.update();
}
});
/**
* poll for new stats and update selected charts
*/
(function traffic_poller(){
ajaxGet("/api/diagnostics/traffic/interface", {}, function(data, status) {
if (data.interfaces !== undefined) {
$( document ).trigger( "updateTrafficCharts", [ data ] );
}
});
setTimeout(traffic_poller, 5000);
})();
});
// needed to display the widget settings menu
$("#traffic_graphs-configure").removeClass("disabled");
});
</script>
<div id="traffic_graphs-settings" class="widgetconfigdiv" style="display:none;">
<form action="/widgets/widgets/traffic_graphs.widget.php" method="post" name="iformd">
<table class="table table-condensed">
<tr>
<td>
<select id="traffic_graphs_interfaces" name="traffic_graphs_interfaces[]" multiple="multiple" class="selectpicker_widget">
<?php foreach ($interfaces as $iface => $ifacename): ?>
<option value="<?= html_safe($iface) ?>" <?= in_array($iface, $pconfig['traffic_graphs_interfaces']) ? 'selected="selected"' : '' ?>><?= html_safe($ifacename) ?></option>
<?php endforeach ?>
</select>
<button id="submitd" name="submitd" type="submit" class="btn btn-primary" value="yes"><?= gettext('Save') ?></button>
</td>
</tr>
</table>
</form>
</div>
<!-- traffic graph table -->
<table class="table table-condensed">
<tbody>
<tr>
<td><?=gettext("In (bps)");?></td>
</tr>
<tr>
<td>
<div class="chart-container">
<canvas id="rxChart" data-src_field="bytes received"></canvas>
</div>
</td>
</tr>
<tr>
<td><?=gettext("Out (bps)");?></td>
</tr>
<tr>
<td>
<div class="chart-container">
<canvas id="txChart" data-src_field="bytes transmitted"></canvas>
</div>
</td>
</tr>
</tbody>
</table>

View File

@ -1,95 +0,0 @@
<?php
/*
* Copyright (C) 2020-2023 Deciso B.V.
* Copyright (C) 2020 D. Domig
* Copyright (C) 2022 Patrik Kernstock <patrik@kernstock.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.
*/
?>
<table class="table table-striped table-condensed" id="wg-table">
<thead>
<tr>
<th><?= gettext("Instance") ?></th>
<th><?= gettext("Peer") ?></th>
<th><?= gettext("Public Key") ?></th>
<th><?= gettext("Latest Handshake") ?></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot style="display: none;">
<tr>
<td colspan="4"><?= gettext("No WireGuard instance defined or enabled.") ?></td>
</tr>
</tfoot>
</table>
<style>
.psk_td {
max-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
text-decoration: underline;
}
</style>
<script>
$(window).on("load", function() {
function wgUpdateStatus()
{
ajaxGet("/api/wireguard/service/show", {}, function(data, status) {
let $target = $("#wg-table > tbody").empty();
if (data.rows !== undefined && data.rows.length > 0) {
$("#wg-table > tfoot").hide();
for (let i=0; data.rows.length > i; ++i) {
let row = data.rows[i];
let $tr = $("<tr/>");
let ifname = row.ifname ? row.if + ' (' + row.ifname + ') ' : row.if;
$tr.append($("<td>").append(ifname));
$tr.append($("<td>").append(row.name));
$tr.append($("<td class='psk_td'>").append(row['public-key']));
let latest_handhake = '';
if (row['latest-handshake']) {
latest_handhake = moment.unix(row['latest-handshake']).local().format('YYYY-MM-DD HH:mm:ss');
}
$tr.append($("<td>").append(latest_handhake));
$target.append($tr);
}
$(".psk_td").each(function(){
$(this).tooltip({title: $(this).text(), container: 'body', trigger: 'hover'});
});
} else{
$("#wg-table > tfoot").show();
}
setTimeout(wgUpdateStatus, 10000);
});
};
wgUpdateStatus();
});
</script>