mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-28 15:09:33 +00:00
1679 lines
50 KiB
Lua
1679 lines
50 KiB
Lua
--
|
|
-- (C) 2013-24 - ntop.org
|
|
--
|
|
local dirs = ntop.getDirs()
|
|
local info = ntop.getInfo()
|
|
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
|
|
|
|
require "label_utils"
|
|
|
|
local script_manager = require("script_manager")
|
|
local template_utils = require("template_utils")
|
|
local recording_utils = require("recording_utils")
|
|
local alert_entities = require("alert_entities")
|
|
|
|
local page_utils = {}
|
|
|
|
local is_nedge = ntop.isnEdge()
|
|
|
|
-- #################################
|
|
|
|
local active_section = nil
|
|
local active_entry = nil
|
|
local active_sub_entry = nil
|
|
|
|
local zoneinfo = 'null'
|
|
local temp_zoneinfo = ntop.getInfo().zoneinfo
|
|
local newline = string.find(temp_zoneinfo, "\n")
|
|
|
|
-- WARNING: in FreeBSD, the zoneinfo ends with a newline character, so remove the newline and everything works fine
|
|
if newline then
|
|
temp_zoneinfo = string.sub(temp_zoneinfo, 1, newline - 1)
|
|
end
|
|
|
|
if temp_zoneinfo ~= nil then
|
|
zoneinfo = "( /^[\\x00-\\xFF]*$/.test('" .. temp_zoneinfo .. "') && moment.tz.zone('" .. temp_zoneinfo ..
|
|
"') != null ? '" .. temp_zoneinfo ..
|
|
"' : function() { console.warn('zoneinfo not valid:' + (/^[\\x00-\\xFF]*$/.test('" .. temp_zoneinfo ..
|
|
"') ? '" .. temp_zoneinfo .. "' : 'Invalid string') ); return null; }())"
|
|
end
|
|
|
|
-- #################################
|
|
|
|
page_utils.menu_sections = {
|
|
monitoring = {
|
|
key = "monitoring",
|
|
i18n_title = "monitoring",
|
|
icon = "fas fa-satellite-dish"
|
|
},
|
|
dashboard = {
|
|
key = "dashboard",
|
|
i18n_title = "index_page.dashboard",
|
|
icon = "fas fa-tachometer-alt"
|
|
},
|
|
alerts = {
|
|
key = "alerts",
|
|
i18n_title = "details.alerts",
|
|
icon = "fas fa-exclamation-triangle"
|
|
},
|
|
flows = {
|
|
key = "flows",
|
|
i18n_title = "flows",
|
|
icon = "fas fa-stream"
|
|
},
|
|
hosts = {
|
|
key = "hosts",
|
|
i18n_title = "hosts",
|
|
icon = "fas fa-laptop"
|
|
},
|
|
maps = {
|
|
key = "maps",
|
|
i18n_title = "maps",
|
|
icon = "fas fa-map"
|
|
},
|
|
collection = {
|
|
key = "collection",
|
|
i18n_title = "flow_devices.exporters",
|
|
icon = "fas fa-file-export",
|
|
zmq_only = true --[[ only for non-packet ZMQ interfaces --]]
|
|
},
|
|
if_stats = {
|
|
key = "if_stats",
|
|
i18n_title = "interface",
|
|
icon = "fas fa-ethernet"
|
|
},
|
|
system_stats = {
|
|
key = "system_stats",
|
|
i18n_title = "system",
|
|
icon = "fas fa-desktop"
|
|
},
|
|
admin = {
|
|
key = "admin",
|
|
i18n_title = "settings",
|
|
icon = "fas fa-cog"
|
|
},
|
|
alert_exclusions = {
|
|
key = "alert_exclusions",
|
|
i18n_title = "edit_check.exclusion_list",
|
|
icon = "fas fa-bell-slash"
|
|
},
|
|
dev = {
|
|
key = "dev",
|
|
i18n_title = "developer",
|
|
icon = "fas fa-code"
|
|
},
|
|
about = {
|
|
key = "about",
|
|
i18n_title = "help",
|
|
icon = "fas fa-life-ring"
|
|
},
|
|
chatbot = {
|
|
key = "chatbot",
|
|
i18n_title = "chatbot",
|
|
icon = "fa-solid fa-headset"
|
|
},
|
|
health = {
|
|
key = "health",
|
|
i18n_title = "health",
|
|
icon = "fas fa-laptop-medical"
|
|
},
|
|
pollers = {
|
|
key = "pollers",
|
|
i18n_title = "pollers",
|
|
icon = "fas fa-heartbeat"
|
|
},
|
|
tools = {
|
|
key = "tools",
|
|
i18n_title = "tools",
|
|
icon = "fas fa-cogs"
|
|
},
|
|
pools = {
|
|
key = "pools",
|
|
i18n_title = "pools.pools",
|
|
icon = "fas fa-users"
|
|
},
|
|
notifications = {
|
|
key = "notifications",
|
|
i18n_title = "endpoint_notifications.notifications",
|
|
icon = "fas fa-bell"
|
|
},
|
|
checks = {
|
|
key = "checks",
|
|
i18n_title = "about.checks"
|
|
},
|
|
policies = {
|
|
key = "policies",
|
|
i18n_title = "policies",
|
|
icon = "fa-solid fa-book-open"
|
|
},
|
|
-- nEdge
|
|
views = {
|
|
key = "hosts",
|
|
i18n_title = "views",
|
|
icon = "fas fa-bars"
|
|
}
|
|
}
|
|
|
|
-- #################################
|
|
|
|
-- help_link: this variable contains the contextual link to the documentation
|
|
|
|
page_utils.menu_entries = {
|
|
-- Monitoring
|
|
active_monitoring = {
|
|
key = "active_monitoring",
|
|
i18n_title = "active_monitoring_stats.active_monitoring",
|
|
section = "monitoring"
|
|
},
|
|
vulnerability_scan = {
|
|
key = "vulnerability_scan",
|
|
i18n_title = "scan_hosts",
|
|
section = "monitoring"
|
|
},
|
|
|
|
-- Dashboard
|
|
traffic_dashboard = {
|
|
key = "traffic_dashboard",
|
|
i18n_title = "dashboard.traffic_dashboard",
|
|
section = "dashboard",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/dashboard/dashboard.html"
|
|
},
|
|
network_discovery = {
|
|
key = "network_discovery",
|
|
i18n_title = "discover.network_discovery",
|
|
section = "dashboard"
|
|
},
|
|
traffic_report = {
|
|
key = "traffic_report",
|
|
i18n_title = "report.traffic_report",
|
|
section = "dashboard",
|
|
help_link = "https://www.ntop.org/guides/ntopng/flow_dump/clickhouse/reports.html"
|
|
},
|
|
traffic_analysis = {
|
|
key = "traffic_analysis",
|
|
i18n_title = "db_explorer.traffic_analysis",
|
|
section = "dashboard",
|
|
help_link = "https://www.ntop.org/guides/ntopng/flow_dump/clickhouse/historical_flows.html"
|
|
},
|
|
|
|
-- Alerts
|
|
detected_alerts = {
|
|
key = "detected_alerts",
|
|
i18n_title = "show_alerts.detected_alerts",
|
|
section = "alerts",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/alerts_explorer.html"
|
|
},
|
|
alerts_dashboard = {
|
|
key = "alerts_dashboard",
|
|
i18n_title = "alerts_dashboard.alerts_dashboard",
|
|
section = "alerts"
|
|
},
|
|
flow_alerts_explorer = {
|
|
key = "flow_alerts_explorer",
|
|
i18n_title = "flow_alerts_explorer.label",
|
|
section = "alerts"
|
|
},
|
|
alerts_list = {
|
|
key = "alerts_list",
|
|
i18n_title = "details.alerts_list",
|
|
section = "alerts"
|
|
},
|
|
alerts_analysis = {
|
|
key = "alerts_analysis",
|
|
i18n_title = "details.alerts_analysis",
|
|
section = "alerts"
|
|
},
|
|
|
|
-- Flows
|
|
flows = {
|
|
key = "flows",
|
|
i18n_title = "flows",
|
|
section = "flows",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/flows/flows.html"
|
|
},
|
|
active_flows = {
|
|
key = "active_flows",
|
|
i18n_title = "active_flows",
|
|
section = "flows"
|
|
},
|
|
flow_details = {
|
|
key = "flow_details",
|
|
i18n_title = "flow_details.flow_details",
|
|
section = "flows"
|
|
},
|
|
db_explorer = {
|
|
key = "db_explorer",
|
|
i18n_title = "db_explorer.historical_data_explorer",
|
|
section = "flows",
|
|
help_link = "https://www.ntop.org/guides/ntopng/flow_dump/clickhouse/historical_flows.html"
|
|
},
|
|
server_ports = {
|
|
key = "server_ports",
|
|
i18n_title = "server_ports.server_ports",
|
|
section = "flows",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/flows/server_ports.html"
|
|
},
|
|
|
|
-- Hosts
|
|
hosts = {
|
|
key = "hosts",
|
|
i18n_title = "hosts",
|
|
section = "hosts",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/hosts/hosts.html#id1"
|
|
},
|
|
devices = {
|
|
key = "devices",
|
|
i18n_title = "layer_2",
|
|
section = "hosts"
|
|
},
|
|
assets = {
|
|
key = "assets",
|
|
i18n_title = "assets",
|
|
section = "hosts"
|
|
},
|
|
|
|
-- Chatbot
|
|
chatbot = {
|
|
key = "chatbot",
|
|
i18n_title = "chatbot",
|
|
section = "chatbot"
|
|
},
|
|
|
|
-- Interface
|
|
interface = {
|
|
key = "interface",
|
|
i18n_title = "interface_details",
|
|
section = "if_stats"
|
|
},
|
|
networks = {
|
|
key = "networks",
|
|
i18n_title = "networks",
|
|
section = "if_stats",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/interface/networks.html"
|
|
},
|
|
vlans = {
|
|
key = "vlans",
|
|
i18n_title = "vlan_stats.vlans",
|
|
section = "if_stats"
|
|
},
|
|
host_pools = {
|
|
key = "host_pools",
|
|
i18n_title = "host_pools.host_pools",
|
|
section = "if_stats"
|
|
},
|
|
autonomous_systems = {
|
|
key = "autonomous_systems",
|
|
i18n_title = "as_stats.autonomous_systems",
|
|
section = "if_stats",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/interface/autonomous_systems.html"
|
|
},
|
|
countries = {
|
|
key = "countries",
|
|
i18n_title = "countries",
|
|
section = "if_stats",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/interface/countries.html"
|
|
},
|
|
operating_systems = {
|
|
key = "operating_systems",
|
|
i18n_title = "operating_systems",
|
|
section = "if_stats",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/interface/operating_systems.html"
|
|
},
|
|
http_servers = {
|
|
key = "http_servers",
|
|
i18n_title = "http_servers_stats.local_http_servers",
|
|
section = "if_stats",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/interface/http_servers_local.html"
|
|
},
|
|
containers = {
|
|
key = "containers",
|
|
i18n_title = "containers_stats.containers",
|
|
section = "if_stats"
|
|
},
|
|
pods = {
|
|
key = "pods",
|
|
i18n_title = "containers_stats.pods",
|
|
section = "if_stats"
|
|
},
|
|
|
|
-- Pollers
|
|
snmp = {
|
|
key = "snmp",
|
|
i18n_title = "prefs.snmp",
|
|
section = "pollers"
|
|
},
|
|
snmp_monitoring = {
|
|
key = "snmp_monitoring",
|
|
i18n_title = "prefs.snmp",
|
|
section = "monitoring"
|
|
},
|
|
infrastructure_dashboard = {
|
|
key = "infrastructure_dashboard",
|
|
i18n_title = "infrastructure_dashboard.infrastructure_dashboard",
|
|
section = "pollers"
|
|
},
|
|
|
|
-- Status (Health)
|
|
system_status = {
|
|
key = "system_status",
|
|
i18n_title = "system_status",
|
|
section = "health"
|
|
},
|
|
interfaces_status = {
|
|
key = "interfaces_status",
|
|
i18n_title = "system_interfaces_status",
|
|
section = "health"
|
|
},
|
|
alerts_status = {
|
|
key = "alerts_status",
|
|
i18n_title = "system_alerts_status",
|
|
section = "health"
|
|
},
|
|
influxdb_status = {
|
|
key = "influxdb_status",
|
|
i18n_title = "InfluxDB",
|
|
section = "health"
|
|
},
|
|
redis_status = {
|
|
key = "redis_status",
|
|
i18n_title = "Redis",
|
|
section = "health"
|
|
},
|
|
clickhouse_status = {
|
|
key = "clickhouse",
|
|
i18n_title = "ClickHouse",
|
|
section = "health"
|
|
},
|
|
|
|
-- exporters
|
|
event_exporters = {
|
|
key = "event_exporters",
|
|
i18n_title = "event_exporters.event_exporters",
|
|
section = "collection"
|
|
},
|
|
sflow_exporters = {
|
|
key = "sflow_exporters",
|
|
i18n_title = "flows_page.sflow_devices",
|
|
section = "collection"
|
|
},
|
|
exporters = {
|
|
key = "exporters",
|
|
i18n_title = "flow_devices.flow_exporters",
|
|
section = "collection",
|
|
help_link = "https://www.ntop.org"
|
|
},
|
|
nprobe = {
|
|
key = "nprobe",
|
|
i18n_title = "flow_devices.nprobe_instances",
|
|
section = "collection"
|
|
},
|
|
observation_points = {
|
|
key = "observation_points",
|
|
i18n_title = "flow_devices.observation_points",
|
|
section = "collection",
|
|
help_link = "https://www.ntop.org"
|
|
},
|
|
|
|
-- Map
|
|
analysis_map = {
|
|
key = "analysis_map",
|
|
i18n_title = "analysis",
|
|
section = "maps"
|
|
},
|
|
geo_map = {
|
|
key = "geo_map",
|
|
i18n_title = "geo_map.geo_map",
|
|
section = "maps",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/network_interface/maps/geo_map.html"
|
|
},
|
|
hosts_map = {
|
|
key = "hosts_map",
|
|
i18n_title = "flows_page.hosts",
|
|
section = "maps"
|
|
},
|
|
|
|
-- Settings
|
|
nedge_users = {
|
|
key = "nedge_users",
|
|
i18n_title = "manage_users.manage_users",
|
|
section = "admin",
|
|
help_link = "https://www.ntop.org/guides/nedge/users.html#"
|
|
},
|
|
manage_users = {
|
|
key = "manage_users",
|
|
i18n_title = ternary(is_nedge, "nedge.system_users", "manage_users.manage_users"),
|
|
section = "admin",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/settings/users.html"
|
|
},
|
|
preferences = {
|
|
key = "preferences",
|
|
i18n_title = "prefs.preferences",
|
|
section = "admin",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/settings/preferences.html"
|
|
},
|
|
categories = {
|
|
key = "categories",
|
|
i18n_title = "custom_categories.apps_and_categories",
|
|
section = "admin",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/settings/applications_and_categories.html#custom-applications"
|
|
},
|
|
category_lists = {
|
|
key = "category_lists",
|
|
i18n_title = "category_lists.category_lists",
|
|
section = "admin"
|
|
},
|
|
conf_backup = {
|
|
key = "conf_backup",
|
|
i18n_title = "conf_backup.conf_backup",
|
|
section = "admin"
|
|
},
|
|
conf_restore = {
|
|
key = "conf_restore",
|
|
i18n_title = "conf_backup.conf_restore",
|
|
section = "admin"
|
|
},
|
|
manage_configurations = {
|
|
key = "manage_configurations",
|
|
i18n_title = "manage_configurations.manage_configurations",
|
|
section = "admin"
|
|
},
|
|
|
|
-- Policies
|
|
device_protocols = {
|
|
key = "device_protocols",
|
|
i18n_title = "device_protocols.device_protocols",
|
|
section = "policies"
|
|
},
|
|
access_control_list = {
|
|
key = "access_control_list",
|
|
i18n_title = "access_control_list",
|
|
section = "policies"
|
|
},
|
|
network_config = {
|
|
key = "network_config",
|
|
i18n_title = "checks.network_configuration",
|
|
section = "policies"
|
|
},
|
|
traffic_rules = {
|
|
key = "traffic_rules",
|
|
i18n_title = "if_stats_config.traffic_rules",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/policies/traffic_rules.html"
|
|
},
|
|
profiles = {
|
|
key = "profiles",
|
|
i18n_title = "traffic_profiles.traffic_profiles",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/policies/traffic_profiles.html"
|
|
},
|
|
alert_exclusions = {
|
|
key = "alert_exclusions",
|
|
i18n_title = "edit_check.exclusion_list",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/behavioural_checks_exclusion.html"
|
|
},
|
|
alert_exclusions_hosts = {
|
|
key = "alert_exclusions",
|
|
subkey = "hosts",
|
|
i18n_title = alert_entities.host.i18n_label,
|
|
section = "alert_exclusions",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
alert_exclusions_flows = {
|
|
key = "alert_exclusions",
|
|
subkey = "flows",
|
|
i18n_title = alert_entities.flow.i18n_label,
|
|
section = "alert_exclusions",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
alert_exclusions_domains = {
|
|
key = "alert_exclusions",
|
|
subkey = "domains",
|
|
i18n_title = alert_entities.domain.i18n_label,
|
|
section = "alert_exclusions",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config = {
|
|
key = "scripts_config",
|
|
i18n_title = "about.checks",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_all = {
|
|
key = "scripts_config",
|
|
subkey = "all",
|
|
i18n_title = "all",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_hosts = {
|
|
key = "scripts_config",
|
|
subkey = "hosts",
|
|
i18n_title = alert_entities.host.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_interfaces = {
|
|
key = "scripts_config",
|
|
subkey = "interfaces",
|
|
i18n_title = alert_entities.interface.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_networks = {
|
|
key = "scripts_config",
|
|
subkey = "networks",
|
|
i18n_title = alert_entities.network.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_snmp_devices = {
|
|
key = "scripts_config",
|
|
subkey = "snmp_devices",
|
|
i18n_title = alert_entities.snmp_device.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_flows = {
|
|
key = "scripts_config",
|
|
subkey = "flows",
|
|
i18n_title = alert_entities.flow.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_system = {
|
|
key = "scripts_config",
|
|
subkey = "system",
|
|
i18n_title = alert_entities.system.i18n_label,
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_syslog = {
|
|
key = "scripts_config",
|
|
subkey = "syslog",
|
|
i18n_title = "syslog.syslog",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
scripts_config_active_monitoring = {
|
|
key = "scripts_config",
|
|
subkey = "active_monitoring",
|
|
i18n_title = "active_monitoring",
|
|
section = "policies",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/others/available_alerts.html"
|
|
},
|
|
device_exclusions = {
|
|
key = "device_exclusions",
|
|
i18n_title = "edit_check.device_exclusion",
|
|
section = "policies"
|
|
},
|
|
|
|
-- Notifications
|
|
endpoint_notifications = {
|
|
key = "endpoint_notifications",
|
|
i18n_title = "endpoint_notifications.endpoint_list",
|
|
section = "notifications",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/available_endpoints.html#available-endpoints"
|
|
},
|
|
endpoint_recipients = {
|
|
key = "endpoint_recipients",
|
|
i18n_title = "endpoint_notifications.enpoint_recipients_list",
|
|
section = "notifications",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/available_endpoints.html#available-endpoints"
|
|
},
|
|
|
|
-- Tools
|
|
export_data = {
|
|
key = "export_data",
|
|
i18n_title = "manage_data.export",
|
|
section = "tools"
|
|
},
|
|
|
|
-- Pools
|
|
host_members = {
|
|
key = "host_members",
|
|
i18n_title = "host_pools.host_members",
|
|
section = "pools"
|
|
},
|
|
manage_pools = {
|
|
key = "manage_pools",
|
|
i18n_title = "pools.pools",
|
|
section = "pools"
|
|
},
|
|
|
|
-- Home
|
|
live_capture = {
|
|
key = "live_capture",
|
|
i18n_title = "live_capture.active_live_captures",
|
|
section = "home"
|
|
},
|
|
|
|
-- Developer
|
|
directories = {
|
|
key = "directories",
|
|
i18n_title = "about.directories",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/scripts/distributing_scripts.html"
|
|
},
|
|
checks_dev = {
|
|
key = "checks_dev",
|
|
i18n_title = "about.checks",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/scripts/checks.html"
|
|
},
|
|
analyze_db = {
|
|
key = "analyze_db",
|
|
i18n_title = "about.analyze_db",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/advanced_features/index.html"
|
|
},
|
|
analyze_pcap = {
|
|
key = "analyze_pcap",
|
|
i18n_title = "about.analyze_pcap",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/developer/analyze_pcap_file.html"
|
|
},
|
|
alert_definitions = {
|
|
key = "alert_definitions",
|
|
i18n_title = "about.alert_defines",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/scripts/alert_definitions.html"
|
|
},
|
|
api = {
|
|
key = "api",
|
|
i18n_title = "lua_c_api",
|
|
section = "dev"
|
|
},
|
|
rest_api = {
|
|
key = "rest_api",
|
|
i18n_title = "swagger_api",
|
|
section = "dev"
|
|
},
|
|
manage_data = {
|
|
key = "manage_data",
|
|
i18n_title = "manage_data.manage_data",
|
|
section = "dev",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/developer/manage_data.html"
|
|
},
|
|
|
|
-- Help
|
|
about = {
|
|
key = "about",
|
|
i18n_title = "about.about",
|
|
section = "about",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/help/about.html"
|
|
},
|
|
license = {
|
|
key = "license",
|
|
i18n_title = "license_page.license",
|
|
section = "about"
|
|
},
|
|
limits = {
|
|
key = "limits",
|
|
i18n_title = "limits_page.limits",
|
|
section = "about"
|
|
},
|
|
blog = {
|
|
key = "blog",
|
|
i18n_title = "about.ntop_blog",
|
|
section = "about"
|
|
},
|
|
telegram = {
|
|
key = "telegram",
|
|
i18n_title = "about.telegram",
|
|
section = "about"
|
|
},
|
|
report_issue = {
|
|
key = "report_issue",
|
|
i18n_title = "about.report_issue",
|
|
section = "about"
|
|
},
|
|
manual = {
|
|
key = "manual",
|
|
i18n_title = "about.readme_and_manual",
|
|
section = "about"
|
|
},
|
|
suggest_feature = {
|
|
key = "suggest_feature",
|
|
i18n_title = "about.suggest_feature",
|
|
section = "about"
|
|
},
|
|
|
|
-- Just a divider for horizontal rows in the menu
|
|
divider = {
|
|
key = "divider"
|
|
},
|
|
|
|
-- nEdge
|
|
gateways_users = {
|
|
key = "gateways_users",
|
|
i18n_title = "dashboard.gateways_users",
|
|
section = "dashboard"
|
|
},
|
|
nedge_flows = {
|
|
key = "nedge_flows",
|
|
i18n_title = "flows",
|
|
section = "hosts"
|
|
},
|
|
nedge_interfaces = {
|
|
key = "nedge_interfaces",
|
|
i18n_title = "interfaces",
|
|
section = "dashboard"
|
|
},
|
|
users = {
|
|
key = "users",
|
|
i18n_title = "users.users",
|
|
section = "hosts",
|
|
help_link = "https://www.ntop.org/guides/ntopng/user_interface/shared/settings/preferences.html#user-authentication"
|
|
},
|
|
system_setup = {
|
|
key = "system_setup",
|
|
i18n_title = "nedge.system_setup",
|
|
section = "system_stats",
|
|
help_link = "https://www.ntop.org/guides/nedge/get_started.html"
|
|
},
|
|
dhcp_static_leases = {
|
|
key = "dhcp_static_leases",
|
|
i18n_title = "nedge.static_dhcp_leases",
|
|
section = "system_stats"
|
|
},
|
|
dhcp_active_leases = {
|
|
key = "dhcp_active_leases",
|
|
i18n_title = "nedge.active_dhcp_leases",
|
|
section = "system_stats"
|
|
},
|
|
port_forwarding = {
|
|
key = "port_forwarding",
|
|
i18n_title = "nedge.port_forwarding",
|
|
section = "system_stats"
|
|
},
|
|
rules_config = {
|
|
key = "rules_config",
|
|
i18n_title = "nedge.rules_config_title",
|
|
section = "system_stats"
|
|
},
|
|
forwarders_config = {
|
|
key = "forwarders_config",
|
|
i18n_title = "nedge.repeaters_config_title",
|
|
section = "system_stats"
|
|
}
|
|
}
|
|
|
|
-- Extend the menu entries with the scripts
|
|
local menu, entries_data = script_manager.getMenuEntries()
|
|
page_utils.scripts_menu = menu or {}
|
|
|
|
if entries_data then
|
|
for k, v in pairs(entries_data) do
|
|
page_utils.menu_entries[k] = v
|
|
end
|
|
end
|
|
|
|
-- #################################
|
|
|
|
-- NOTE: this function must be called after page_utils.print_header_and_set_active_menu_entry
|
|
function page_utils.print_page_title(title, mini_title)
|
|
local help_link = page_utils.menu_entries[active_entry].help_link or ""
|
|
print("<header class='mb-3 d-flex align-items-center'>")
|
|
print("<h2 class='d-inline-block'>" .. title .. "</h2>")
|
|
if (not isEmptyString(help_link)) then
|
|
print("<a data-bs-toggle='tooltip' title='" .. i18n("open_documentation") .. "' target='_newtab' href='" ..
|
|
help_link .. "' class='text-muted ms-auto'><i class='fas fa-question-circle'></i></a>")
|
|
end
|
|
|
|
if mini_title and not isEmptyString(mini_title) then
|
|
print("<small style='margin-left: auto;'>" .. mini_title .. "</small>")
|
|
end
|
|
print("</header>")
|
|
|
|
end
|
|
|
|
-- #################################
|
|
|
|
-- NOTE: this function is called by the web pages in order to
|
|
-- set the active entry and section and highlight it into the menu
|
|
function page_utils.print_header_and_set_active_menu_entry(entry, i18n_params, alt_title)
|
|
require "locales_utils"
|
|
entry = entry or page_utils.menu_entries.traffic_dashboard
|
|
|
|
active_section = entry.section
|
|
active_entry = entry.key
|
|
if entry.subkey then
|
|
active_sub_entry = entry.subkey
|
|
end
|
|
|
|
page_utils.print_header(alt_title or i18n(entry.i18n_title, i18n_params) or entry.i18n_title)
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.get_active_section()
|
|
return (active_section)
|
|
end
|
|
|
|
function page_utils.get_active_entry()
|
|
return (active_entry)
|
|
end
|
|
|
|
function page_utils.get_active_sub_entry()
|
|
return (active_sub_entry)
|
|
end
|
|
|
|
-- #################################
|
|
|
|
-- @brief Encode the HTML entities in a string.
|
|
-- Useful when printing dissected data which may result in XSS
|
|
-- e.g., curl -u admin:admin1 "http://devel:3000/</a><script>alert(1);</script><a>"
|
|
-- @param s The string to escape.
|
|
-- @return The string with HTML entities properly escaped
|
|
function page_utils.safe_html(s)
|
|
if not s then
|
|
return ''
|
|
end
|
|
|
|
ret = string.gsub(s, "[}{\">/<'&]", {
|
|
["&"] = "&",
|
|
["<"] = "<",
|
|
[">"] = ">",
|
|
['"'] = """,
|
|
["'"] = "'",
|
|
["/"] = "/"
|
|
})
|
|
|
|
return (ret)
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.is_dark_mode_enabled(theme)
|
|
|
|
local dark_mode
|
|
local theme = theme or ntop.getPref("ntopng.user." .. _SESSION["user"] .. ".theme")
|
|
|
|
if (isEmptyString(theme)) then
|
|
dark_mode = false
|
|
else
|
|
dark_mode = (theme == "dark")
|
|
end
|
|
|
|
return dark_mode
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.print_header(title, addLoginJS)
|
|
local http_prefix = ntop.getHttpPrefix()
|
|
local static_file_epoch = ntop.getStaticFileEpoch() .. ""
|
|
|
|
local dark_mode = page_utils.is_dark_mode_enabled(_POST["toggle_theme"])
|
|
local page_title = i18n("welcome_to", {
|
|
product = info.product
|
|
})
|
|
local favicon_path = nil
|
|
|
|
local admin_lang = ntop.getPref("ntopng.user.admin.language")
|
|
local language = ternary(isEmptyString(admin_lang), "en", admin_lang)
|
|
local locale_path = dirs.installdir .. "/scripts/locales/" .. language .. ".lua"
|
|
local locale_when = ntop.fileLastChange(locale_path)
|
|
|
|
if title ~= nil then
|
|
page_title = info.product .. " - " .. title
|
|
end
|
|
|
|
print [[
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>]]
|
|
print(page_title)
|
|
print [[</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/third-party.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/ntopng.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/white-mode.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">]]
|
|
|
|
if (dark_mode) then
|
|
print [[<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/dark-mode.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">]]
|
|
end
|
|
|
|
if (ntop.isPro() or ntop.isnEdge()) and ntop.exists(dirs.installdir .. "/httpdocs/img/custom_favicon.ico") then
|
|
favicon_path = http_prefix .. "/img/custom_favicon.ico"
|
|
end
|
|
if (favicon_path ~= nil) then
|
|
print [[<link href="]]
|
|
print(favicon_path)
|
|
print [[" rel="icon">]]
|
|
else
|
|
print [[<link href="]]
|
|
print(http_prefix)
|
|
print [[/favicon.ico" rel="icon">]]
|
|
end
|
|
|
|
print [[
|
|
<style>
|
|
.flag {
|
|
width: 16px;
|
|
height: 11px;
|
|
margin-top: -5px;
|
|
background:url(]]
|
|
print(http_prefix)
|
|
print [[/dist/images/flags.png) no-repeat
|
|
}
|
|
</style>
|
|
|
|
]]
|
|
|
|
if addLoginJS then
|
|
print [[<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print [[/dist/login.js?]]
|
|
print(static_file_epoch)
|
|
print [["></script>]]
|
|
end
|
|
|
|
if (ntop.isPro() and ntop.exists(dirs.installdir .. "/httpdocs/css/custom-theme.css")) then
|
|
print [[
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/css/custom-theme.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">
|
|
]]
|
|
end
|
|
|
|
print [[
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print("/lua/locale.lua?" .. locale_when .. "&user_language=" .. language);
|
|
print [["> </script>
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print [[/dist/third-party.js?]]
|
|
print(static_file_epoch)
|
|
print [["></script>
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print [[/dist/ntopng.js?]]
|
|
print(static_file_epoch)
|
|
print [["></script>
|
|
<script>
|
|
const ntop_zoneinfo = ]]
|
|
print(zoneinfo)
|
|
print [[;
|
|
const http_prefix = "]]
|
|
print(ntop.getHttpPrefix())
|
|
print [[";
|
|
</script>
|
|
</head>]]
|
|
print([[
|
|
<body class="body ]] .. (dark_mode and "dark" or "") .. [[">
|
|
]])
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.print_header_minimal(title, addLoginJS)
|
|
local http_prefix = ntop.getHttpPrefix()
|
|
|
|
local page_title = i18n("welcome_to", {
|
|
product = info.product
|
|
})
|
|
if title ~= nil then
|
|
page_title = info.product .. " - " .. title
|
|
end
|
|
|
|
local admin_lang = ntop.getPref("ntopng.user.admin.language")
|
|
local language = ternary(isEmptyString(admin_lang), "en", admin_lang)
|
|
local locale_path = dirs.installdir .. "/scripts/locales/" .. language .. ".lua"
|
|
local locale_when = ntop.fileLastChange(locale_path)
|
|
local static_file_epoch = ntop.getStaticFileEpoch() .. ""
|
|
|
|
print [[
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>]]
|
|
print(page_title)
|
|
print [[</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/third-party.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">
|
|
<link href="]]
|
|
print(http_prefix)
|
|
print [[/dist/ntopng.css?]]
|
|
print(static_file_epoch)
|
|
print [[" rel="stylesheet">
|
|
]]
|
|
|
|
if (ntop.isPro() or ntop.isnEdge()) and ntop.exists(dirs.installdir .. "/httpdocs/img/custom_favicon.ico") then
|
|
favicon_path = http_prefix .. "/img/custom_favicon.ico"
|
|
end
|
|
if (favicon_path ~= nil) then
|
|
print [[<link href="]]
|
|
print(favicon_path)
|
|
print [[" rel="icon">]]
|
|
else
|
|
print [[<link href="]]
|
|
print(http_prefix)
|
|
print [[/favicon.ico" rel="icon">]]
|
|
end
|
|
|
|
print [[
|
|
<style>
|
|
.flag {
|
|
width: 16px;
|
|
height: 11px;
|
|
margin-top: -5px;
|
|
background:url(]]
|
|
print(http_prefix)
|
|
print [[/dist/images/flags.png) no-repeat
|
|
}
|
|
</style>
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print("/lua/locale.lua?" .. locale_when .. "&user_language=" .. language);
|
|
print [["> </script>
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print [[/dist/third-party.js?]]
|
|
print(static_file_epoch)
|
|
print [["></script>
|
|
<script type="application/javascript" src="]]
|
|
print(http_prefix)
|
|
print [[/dist/ntopng.js?]]
|
|
print(static_file_epoch)
|
|
print [["></script>
|
|
<script> const ntop_zoneinfo = ]]
|
|
print(zoneinfo)
|
|
print [[;</script>
|
|
</head>
|
|
<body>
|
|
|
|
]]
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.get_navbar_context(title, base_url, items_table, label_url, back_url)
|
|
local help_link = page_utils.menu_entries[active_entry].help_link or nil
|
|
local icon = page_utils.menu_sections[active_section].icon or ""
|
|
|
|
local navbar = {
|
|
main_icon = icon,
|
|
main_title = title,
|
|
base_url = base_url,
|
|
items_table = items_table,
|
|
label_url = label_url,
|
|
back_url = back_url,
|
|
help_link = help_link
|
|
}
|
|
return navbar
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.get_new_navbar_context(title, base_url, items_table, label_url, back_url)
|
|
local help_link = page_utils.menu_entries[active_entry].help_link or nil
|
|
local icon = page_utils.menu_sections[active_section].icon or ""
|
|
|
|
local navbar = {
|
|
main_title = {
|
|
icon = icon,
|
|
label = title
|
|
},
|
|
base_url = base_url,
|
|
items_table = items_table,
|
|
label_url = label_url,
|
|
back_url = back_url,
|
|
help_link = help_link
|
|
}
|
|
return navbar
|
|
end
|
|
-- #################################
|
|
|
|
function page_utils.print_navbar(title, base_url, items_table, label_url, back_url, end_items)
|
|
local help_link = page_utils.menu_entries[active_entry].help_link or nil
|
|
local icon = page_utils.menu_sections[active_section].icon or ""
|
|
|
|
local context = {
|
|
navbar = {
|
|
title = "<i class='" .. icon .. "'></i>" .. " " .. title,
|
|
base_url = base_url,
|
|
items_table = items_table,
|
|
label_url = label_url,
|
|
back_url = back_url,
|
|
help_link = help_link,
|
|
end_items = end_items
|
|
}
|
|
}
|
|
print(template_utils.gen("pages/components/page-navbar.template", context))
|
|
end
|
|
|
|
-- #################################
|
|
local menubar_structure = {}
|
|
|
|
function page_utils.init_menubar()
|
|
menubar_structure = {}
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.add_menubar_section(section)
|
|
menubar_structure[#menubar_structure + 1] = section
|
|
end
|
|
|
|
-- #################################
|
|
|
|
local function print_submenu(section, container_list_name)
|
|
local active_subpage = page_utils.get_active_entry()
|
|
local active_subsubpage = page_utils.get_active_sub_entry()
|
|
local section_key = section.section.key
|
|
local section_id = section_key .. "-submenu"
|
|
local list_name = section_id .. "-list"
|
|
|
|
print [[<div data-parent='#]]
|
|
print(container_list_name)
|
|
print [[' class='collapse side-collapse' id=']]
|
|
print(section_id)
|
|
print [['>
|
|
<ul class='nav flex-column' id=']]
|
|
print(list_name)
|
|
print [['>
|
|
]]
|
|
|
|
for _, section_entry in ipairs(section.entries) do
|
|
if not section_entry.hidden then
|
|
if section_entry.custom then
|
|
print(section_entry.custom)
|
|
elseif section_entry.entry.key == "divider" then
|
|
print [[
|
|
<li class="dropdown-divider"></li>
|
|
]]
|
|
else
|
|
local external_link = false
|
|
local section_has_submenu = section_entry.entries
|
|
local active = false
|
|
|
|
if section_entry.entry and (section_entry.entry.key == active_subpage and
|
|
(not section_entry.entry.subkey or section_entry.entry.subkey == active_subsubpage)) then
|
|
active = true
|
|
end
|
|
|
|
if section_entry.url:starts("http") then
|
|
-- Absolute (external) url
|
|
|
|
external_link = true
|
|
end
|
|
print [[
|
|
<li class=']]
|
|
if active then
|
|
print("active")
|
|
end
|
|
print [['>
|
|
|
|
<a class="]]
|
|
if section_has_submenu then
|
|
print [[submenu ]]
|
|
end
|
|
if active then
|
|
print [[active ]]
|
|
end
|
|
if external_link == true then
|
|
print [[ntopng-external-link ]]
|
|
end
|
|
print [["]]
|
|
|
|
if section_has_submenu then
|
|
print [[ data-bs-toggle="collapse" ]]
|
|
end
|
|
print [[href="]]
|
|
if section_has_submenu then
|
|
local submenu_section_key = section_entry.section.key
|
|
local submenu_section_id = submenu_section_key .. "-submenu"
|
|
print("#" .. submenu_section_id)
|
|
else
|
|
if external_link then
|
|
print(section_entry.url)
|
|
else
|
|
print(ntop.getHttpPrefix() .. section_entry.url)
|
|
end
|
|
end
|
|
print [["]]
|
|
|
|
if section_entry.entry.is_modal then
|
|
print(' data-bs-toggle="modal"')
|
|
end
|
|
|
|
if external_link then
|
|
-- Open in a new page
|
|
print(' target="_blank"')
|
|
end
|
|
|
|
print [[>]]
|
|
print(i18n(section_entry.entry.i18n_title) or section_entry.entry.i18n_title)
|
|
if section_entry.suffix then
|
|
print(section_entry.suffix)
|
|
end
|
|
if external_link then
|
|
print(" <i class='fas fa-external-link-alt'></i>")
|
|
end
|
|
|
|
print [[</a>]]
|
|
|
|
if section_has_submenu then
|
|
print_submenu(section_entry, list_name)
|
|
end
|
|
|
|
print [[</li>
|
|
]]
|
|
end
|
|
end
|
|
end
|
|
|
|
print [[
|
|
</ul>
|
|
</div>
|
|
]]
|
|
end
|
|
|
|
-- #################################
|
|
|
|
local function print_section(section, list_name)
|
|
local active_page = page_utils.get_active_section()
|
|
local show_section = false
|
|
local section_has_submenu = (section.entries and #section.entries > 0)
|
|
|
|
if (not section.hidden) then
|
|
if not section_has_submenu then
|
|
show_section = true
|
|
else
|
|
-- The section is shown only if at least one of its sub entries
|
|
-- is shown
|
|
for _, section_entry in pairs(section.entries or {}) do
|
|
if not section_entry.hidden then
|
|
show_section = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if show_section then
|
|
local section_key = section.section.key
|
|
local section_id = section_key .. "-submenu"
|
|
|
|
print [[
|
|
<li class="nav-item ]]
|
|
print(active_page == section_key and 'active' or '')
|
|
print [[">
|
|
<a class="]]
|
|
|
|
if section_has_submenu then
|
|
print [[submenu ]]
|
|
end
|
|
|
|
if active_page == section_key then
|
|
print [[active ]]
|
|
end
|
|
|
|
print [[" ]]
|
|
|
|
if section_has_submenu then
|
|
print [[ data-bs-toggle="collapse" ]]
|
|
end
|
|
|
|
print [[href="]]
|
|
|
|
if section.url then
|
|
print(ntop.getHttpPrefix() .. section.url)
|
|
else
|
|
print("#" .. section_id)
|
|
end
|
|
|
|
print [[">
|
|
<span class="]]
|
|
print(section.section.icon)
|
|
print [["></span> ]]
|
|
print(i18n(section.section.i18n_title))
|
|
print [[
|
|
</a>]]
|
|
|
|
if section_has_submenu then
|
|
print_submenu(section, list_name)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- #################################
|
|
|
|
function page_utils.print_menubar()
|
|
local is_system_interface = page_utils.is_system_view()
|
|
local logo_path = nil
|
|
local list_name = "sidebar"
|
|
|
|
if (ntop.isPro() or ntop.isnEdge()) and ntop.exists(dirs.installdir .. "/httpdocs/img/custom_logo.png") then
|
|
logo_path = ntop.getHttpPrefix() .. "/img/custom_logo.png"
|
|
end
|
|
|
|
local navbar_style = _POST["toggle_theme"] or ntop.getPref("ntopng.user." .. _SESSION["user"] .. ".theme")
|
|
|
|
if ((navbar_style == nil) or (navbar_style == "white") or (navbar_style == "")) then
|
|
navbar_style = "default"
|
|
end
|
|
|
|
if (navbar_style == "default") then
|
|
navbar_style = "dark"
|
|
end
|
|
|
|
print('<nav id="n-sidebar" class="bg-' .. navbar_style .. ' py-0 px-2">')
|
|
print([[
|
|
<div class="mobile-menu-button d-flex">
|
|
<form class='w-100' method='post' action="/?">
|
|
<input hidden name='switch_interface' value='1' />
|
|
<input hidden name='csrf' value=']] .. ntop.getRandomCSRFValue() .. [[' />
|
|
]] .. template_utils.gen("pages/components/ifaces-select.template", {
|
|
ifaces = page_utils.get_interface_list(),
|
|
is_sys_iface = is_system_interface
|
|
}) .. [[
|
|
</form>
|
|
<button data-bs-toggle="]] .. list_name .. [[" class='ms-5 my-auto btn btn-close'></button>
|
|
</div>
|
|
<div class="mobile-menu-stats">
|
|
]])
|
|
|
|
-- the network load will not be displayed in system view mode
|
|
if not is_system_interface then
|
|
print([[<div class="network-load mb-2 w-100"></div>]])
|
|
end
|
|
|
|
print([[
|
|
<div class="info-stats w-100">]] .. page_utils.generate_info_stats() .. [[</div>
|
|
</div>
|
|
]])
|
|
print("<h3 class='muted'><a href='" .. ntop.getHttpPrefix() .. "/'>")
|
|
|
|
if (logo_path ~= nil) then
|
|
print("<img class=\"logo-brand\" height=\"52px\" src=\"" .. logo_path .. "\" alt='Custom Logo' />")
|
|
else
|
|
print(addLogoSvg())
|
|
end
|
|
|
|
print([[
|
|
</a>
|
|
</h3>
|
|
|
|
<ul class="nav-side mb-4" id=']] .. list_name .. [['>
|
|
]])
|
|
|
|
for _, section in ipairs(menubar_structure) do
|
|
print_section(section, list_name)
|
|
end
|
|
|
|
print([[
|
|
</ul>
|
|
</nav>
|
|
]])
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function page_utils.get_interface_list()
|
|
local interfaces = {}
|
|
local iface_names = interface.getIfNames()
|
|
local is_system_interface = page_utils.is_system_view()
|
|
|
|
local num_ifaces = 0
|
|
for k, v in pairs(iface_names) do
|
|
num_ifaces = num_ifaces + 1
|
|
end
|
|
|
|
local ifs = interface.getStats()
|
|
local is_pcap_dump = interface.isPcapDumpInterface()
|
|
local is_packet_interface = interface.isPacketInterface()
|
|
local views = {}
|
|
local drops = {}
|
|
local recording = {}
|
|
local packetinterfaces = {}
|
|
local ifnames = {}
|
|
local ifdescr = {}
|
|
local ifHdescr = {}
|
|
local ifCustom = {}
|
|
local dynamic = {}
|
|
|
|
for v, k in pairs(iface_names) do
|
|
interface.select(k)
|
|
local _ifstats = interface.getStats()
|
|
ifnames[_ifstats.id] = k
|
|
ifdescr[_ifstats.id] = _ifstats.description
|
|
-- io.write("["..k.."/"..v.."][".._ifstats.id.."] "..ifnames[_ifstats.id].."=".._ifstats.id.."\n")
|
|
if (_ifstats.isView == true) then
|
|
views[k] = true
|
|
end
|
|
if (interface.isSubInterface()) then
|
|
dynamic[k] = true
|
|
end
|
|
if (recording_utils.isEnabled(_ifstats.id)) then
|
|
recording[k] = true
|
|
end
|
|
if (interface.isPacketInterface()) then
|
|
packetinterfaces[k] = true
|
|
end
|
|
if (_ifstats.stats_since_reset.drops * 100 > _ifstats.stats_since_reset.packets) then
|
|
drops[k] = true
|
|
end
|
|
ifHdescr[_ifstats.id] = getHumanReadableInterfaceName(_ifstats.description .. "")
|
|
ifCustom[_ifstats.id] = _ifstats.customIftype
|
|
end
|
|
|
|
-- First round: only physical interfaces
|
|
-- Second round: only virtual interfaces
|
|
|
|
for round = 1, 2 do
|
|
|
|
for k, _ in pairsByValues(ifHdescr, asc) do
|
|
|
|
if ((round == 1) and (ifCustom[k] ~= nil)) or (((round == 2) and (ifCustom[k] == nil))) then
|
|
goto continue
|
|
end
|
|
|
|
local v = ifnames[k]
|
|
|
|
-- table.clone needed to modify some parameters while keeping the original unchanged
|
|
local page_params = table.clone(_GET)
|
|
page_params.ifid = k
|
|
|
|
local url_query = getPageUrl("", page_params)
|
|
|
|
-- NOTE: the actual interface switching is performed in C in LuaEngine::handle_script_request
|
|
local action_url = ""
|
|
|
|
if (is_system_interface) then
|
|
action_url = ntop.getHttpPrefix() .. '/' .. url_query
|
|
else
|
|
action_url = url_query
|
|
end
|
|
|
|
local descr = getHumanReadableInterfaceName(v .. "")
|
|
|
|
if (string.contains(descr, "{")) then -- Windows
|
|
descr = ifdescr[k]
|
|
else
|
|
|
|
if (descr ~= ifdescr[k]) and (not views[v]) then
|
|
|
|
if (descr == shortenCollapse(ifdescr[k])) then
|
|
descr = ifdescr[k]
|
|
else
|
|
descr = descr .. " (" .. ifdescr[k] .. ")" -- Add description
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
interfaces[#interfaces + 1] = {
|
|
is_virtual = (round == 2), -- Is the interface virtual or physical?
|
|
is_paused = isPausedInterface(v), -- Is the interfaces paused?
|
|
is_selected = (v == ifname) and not is_system_interface, -- Is the in
|
|
is_dynamic = (dynamic[v]),
|
|
is_recording = (recording[v]),
|
|
has_drops = (drops[v]),
|
|
has_views = (views[v]),
|
|
ifid = k,
|
|
action_url = action_url,
|
|
human_name = descr
|
|
}
|
|
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
interface.select(ifs.id .. "")
|
|
|
|
return interfaces
|
|
end
|
|
|
|
function page_utils.generate_info_stats()
|
|
|
|
local _ifstats = interface.getStats()
|
|
|
|
local upload_stats = ""
|
|
local download_stats = ""
|
|
|
|
for _, v in pairs(_ifstats["download_stats"]) do
|
|
download_stats = download_stats .. tostring(-v * 1000 * 8) .. "," -- push the values in bit, they are stored as KB in c++
|
|
end
|
|
|
|
for _, v in pairs(_ifstats["upload_stats"]) do
|
|
upload_stats = upload_stats .. tostring(v * 1000 * 8) .. "," -- push the values in bit, they are stored as KB in c++
|
|
end
|
|
|
|
download_stats = download_stats:sub(1, -2)
|
|
upload_stats = upload_stats:sub(1, -2)
|
|
if (_ifstats.id == -1) then
|
|
return ""
|
|
end
|
|
if _ifstats.has_traffic_directions then
|
|
return ([[
|
|
<a href=']] .. ntop.getHttpPrefix() .. [[/lua/if_stats.lua'>
|
|
<div class='up'>
|
|
<i class="fas fa-arrow-up"></i>
|
|
<span style='display: none;' class="network-load-chart-upload">]] .. upload_stats .. [[</span>
|
|
<span class="text-end chart-upload-text"></span>
|
|
</div>
|
|
<div class='down'>
|
|
<i class="fas fa-arrow-down"></i>
|
|
<span style='display: none;' class="network-load-chart-download">]] .. download_stats .. [[</span>
|
|
<span class="text-end chart-download-text"></span>
|
|
</div>
|
|
</a>
|
|
]])
|
|
else
|
|
return ([[
|
|
<a href=']] .. ntop.getHttpPrefix() .. [[/lua/if_stats.lua'>
|
|
<span style='display: none;' class="network-load-chart-total">0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</span>
|
|
<span class="text-end chart-total-text"></span>
|
|
</a>
|
|
]])
|
|
end
|
|
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function page_utils.is_system_view()
|
|
return interface.getId() == tonumber(getSystemInterfaceId()) and isAdministrator()
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
--- Check if the current page is valid
|
|
--- @return boolean True if the current page is in available_pages, false otherwise
|
|
function page_utils.is_valid_page(selected_page, available_pages)
|
|
|
|
if selected_page == nil then
|
|
traceError(TRACE_WARNING, TRACE_DEBUG, "selected_pages is nil!")
|
|
return false
|
|
end
|
|
if available_pages == nil then
|
|
traceError(TRACE_WARNING, TRACE_DEBUG, "available_pages is nil!")
|
|
return false
|
|
end
|
|
if type(available_pages) ~= 'table' then
|
|
traceError(TRACE_WARNING, TRACE_DEBUG, "available_pages is not a table!")
|
|
return false
|
|
end
|
|
|
|
-- do a linear search
|
|
for _, page in ipairs(available_pages) do
|
|
if (page == selected_page) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
-- @brief Prepares the URL which will be used for the redirect after interface switch
|
|
-- @param ifid The interface identifier of the interface that will be switched
|
|
-- @param if_type The type of the interface that will be switched
|
|
-- @return The URL
|
|
function page_utils.switch_interface_form_action_url(active_ifid, switch_ifid, switch_if_type)
|
|
local action_url = ""
|
|
local page_params = table.clone(_GET)
|
|
|
|
-- Read the currently active page
|
|
local active_page = page_utils.get_active_section()
|
|
|
|
if active_ifid == tonumber(getSystemInterfaceId()) then
|
|
-- If the switch is between the system interface and a non-system interface
|
|
-- the URL is just the home
|
|
action_url = ntop.getHttpPrefix() .. '/'
|
|
elseif page_utils.menu_sections[active_page] and page_utils.menu_sections[active_page]["zmq_only"] and
|
|
switch_if_type ~= "zmq" and switch_if_type ~= "custom" then
|
|
-- If the interface that will be switched is non-ZMQ, and the currently
|
|
-- selected page is for ZMQ-only interfaces, then a redirection to root
|
|
-- is performed, rather than preserving the current page
|
|
action_url = ntop.getHttpPrefix() .. '/'
|
|
end
|
|
|
|
-- Attach the interface id of the interface that will be switched
|
|
page_params.ifid = switch_ifid
|
|
|
|
page_params["observationPointId"] = nil
|
|
|
|
-- Return the url, preserving all existing page parameters (e.g., host=xx)
|
|
local res = getPageUrl(action_url, page_params)
|
|
|
|
return res
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
return page_utils
|
|
|