mirror of
https://github.com/lucaspalomodevelop/opnsense-core.git
synced 2026-03-13 08:09:42 +00:00
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:
parent
f587c307e3
commit
cff24b7a8a
36
plist
36
plist
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"/>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)]);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 ?>;">
|
||||
<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;
|
||||
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$carp_status_title = gettext('CARP');
|
||||
$carp_status_title_link = 'ui/diagnostics/interface/vip';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$cpu_usage_title = gettext('CPU usage');
|
||||
$cpu_usage_title_link = 'ui/diagnostics/systemhealth';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$gateways_title = gettext('Gateways');
|
||||
$gateways_title_link = 'ui/routing/configuration';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$interface_list_title = gettext('Interfaces');
|
||||
$interface_list_title_link = 'interfaces_assign.php';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$interface_statistics_title = gettext('Interface Statistics');
|
||||
$interface_statistics_title_link = 'ui/interfaces/overview';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$ipsec_title = gettext('IPsec');
|
||||
$ipsec_title_link = 'ui/ipsec/sessions';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$log_title = gettext('Firewall Log');
|
||||
$log_title_link = 'ui/diagnostics/firewall/log';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$monit_title = gettext('Monit');
|
||||
$monit_title_link = 'ui/monit/status';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$ntp_status_title = gettext('Network Time');
|
||||
$ntp_status_title_link = 'status_ntpd.php';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$openvpn_title = gettext('OpenVPN');
|
||||
$openvpn_title_link = 'ui/openvpn/status';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$services_status_title = gettext('Services');
|
||||
$services_status_title_link = 'ui/core/service';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$system_log_title = gettext('System Log');
|
||||
$system_log_title_link = 'ui/diagnostics/log/core/system';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$thermal_sensors_title = gettext('Thermal Sensors');
|
||||
$thermal_sensors_title_link = 'system_advanced_misc.php';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$traffic_graphs_title = gettext('Traffic Graph');
|
||||
$traffic_graphs_title_link = 'ui/diagnostics/traffic';
|
||||
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$wireguard_title = gettext('WireGuard');
|
||||
$wireguard_title_link = 'ui/wireguard/general';
|
||||
@ -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'])):?>
|
||||
|
||||
<?=htmlspecialchars($status_i18n);?>
|
||||
<?=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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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> </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;">~</td>
|
||||
<?php endwhile ?>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
|
||||
<!-- needed to display the widget settings menu -->
|
||||
<script>
|
||||
//<![CDATA[
|
||||
$("#interface_statistics-configure").removeClass("disabled");
|
||||
//]]>
|
||||
</script>
|
||||
@ -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> <?=gettext("Overview");?> </strong>
|
||||
</div>
|
||||
<div data-for="ipsec-tunnel" class="ipsec-tab table-cell" style="cursor: pointer; display:table-cell">
|
||||
<strong> <?=gettext("Tunnels");?> </strong>
|
||||
</div>
|
||||
<div data-for="ipsec-mobile" class="ipsec-tab table-cell" style="cursor: pointer; display:table-cell">
|
||||
<strong> <?=gettext("Mobile");?> </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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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;
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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" ? '' : ' [' + $('#severity_filter option:selected').text() + ']';
|
||||
if ($("#systemlogentriesfilter").val()) {
|
||||
filterstring = $("#systemlogentriesfilter").val();
|
||||
title += ' filtered with "' + filterstring + '"';
|
||||
}
|
||||
$('#system_log').find('h3').append(title);
|
||||
fetch_system_log(rowCount, refresh_interval_ms, requestSeverity);
|
||||
})
|
||||
|
||||
</script>
|
||||
@ -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) + ' °F');
|
||||
} else {
|
||||
progressBar.html(sensor['temperature'] + ' °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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
Loading…
x
Reference in New Issue
Block a user