diff --git a/attic/scripts/lua/http_status_code.lua b/attic/scripts/lua/http_status_code.lua new file mode 100644 index 0000000000..4f2b763ace --- /dev/null +++ b/attic/scripts/lua/http_status_code.lua @@ -0,0 +1,57 @@ +-- +-- (C) 2020 - ntop.org +-- + +-- This page shows the HTTP errors that a user can get +-- example: 404, 403, ... + +dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require("lua_utils") +local page_utils = require("page_utils") +local message = _GET["message"] or "forbidden" +local referal_url = _GET["referer"] or '/' +local error_message = _GET["error_message"] or "" + +if(_GET["message"] == "not_found") then + status_code = 404 +elseif(_GET["message"] == "internal_error") then + status_code = 500 +else + status_code = 403 -- forbidden +end + +sendHTTPContentTypeHeader('text/html', nil, nil, nil, status_code) +page_utils.print_header() + + +referal_url = string.sub(referal_url, string.find(referal_url, "/"), string.len(referal_url)) +message = "http_status_code."..message + +dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") + +print([[ +
+
+

+ ]].. i18n("error_page.presence").. [[ +

+ ]]) + +print(i18n(message)) + + print('

'..error_message) +print([[

+ + + ]].. i18n("error_page.go_back").. [[ + +
+
+ +
+
+]]) + +dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") diff --git a/attic/scripts/lua/ntopng_logout.lua b/attic/scripts/lua/ntopng_logout.lua new file mode 100644 index 0000000000..1969767a5b --- /dev/null +++ b/attic/scripts/lua/ntopng_logout.lua @@ -0,0 +1,24 @@ +-- +-- (C) 2013-26 - ntop.org +-- + +dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "lua_utils" +local debug = false + +sendHTTPHeaderLogout('text/html') + +ntop.delCache("ntopng.cache.sessions.".._SESSION["session"]) +if (debug) then io.write("Deleting ".."ntopng.cache.sessions.".._SESSION["session"].."\n") end + +print [[ + + + + ]] print(i18n("login.logging_out")) print[[ + + + +]] diff --git a/httpdocs/dist b/httpdocs/dist index fe596484d9..2d237d6b65 160000 --- a/httpdocs/dist +++ b/httpdocs/dist @@ -1 +1 @@ -Subproject commit fe596484d9dafb467ceb3e5c427873084ca9fb86 +Subproject commit 2d237d6b65859adab137b09f565a1a8dd29df512 diff --git a/httpdocs/tables_config/flows_list.json b/httpdocs/tables_config/flows_list.json index 87004da3b8..7b9b98ed3e 100644 --- a/httpdocs/tables_config/flows_list.json +++ b/httpdocs/tables_config/flows_list.json @@ -189,7 +189,7 @@ ] }, { - "title_i18n": "db_search.flowfilters.flow_risk", + "title_i18n": "flow_alerts_filter", "data_field": "risk", "sortable": false, "min-width" : "140px", diff --git a/include/Paginator.h b/include/Paginator.h index 4498254bcd..7d1b682e9c 100644 --- a/include/Paginator.h +++ b/include/Paginator.h @@ -50,7 +50,6 @@ class Paginator { int32_t iface_index_filter; u_int16_t pool_filter, alert_type_filter; AlertLevelGroup alert_type_severity_filter; - int32_t risk_filter; u_int8_t *mac_filter, icmp_type, icmp_code, dscp_filter; DetailsLevel details_level; bool details_level_set; @@ -298,14 +297,6 @@ class Paginator { return false; } - inline bool riskFilter(int32_t* f) const { - if (risk_filter >= 0) { - (*f) = risk_filter; - return true; - } - return false; - } - inline bool macFilter(u_int8_t** f) const { if (mac_filter) { (*f) = mac_filter; diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index a1156e1cdc..85935ae97b 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -10,6 +10,7 @@ local lang = { ["acknowledged_all"] = "All", ["acknowledged_only"] = "Acknowledged Only", ["action"] = "Action", + ["flow_alerts_filter"] = "Flow Alerts", ["ask_google_ai" ] = "Ask Google AI", ["timestamp"] = "Timestamp", ["triggered_by"] = "Triggered By", @@ -7465,6 +7466,10 @@ local lang = { ["model_price_deleted"] = "Model price deleted successfully", ["confirm_delete_price_body"] = "Are you sure you want to delete the price entry for model '{model}'?", ["chatid_copied_to_clipboard"] = "Chat URL copied to clipboard", + ["debug_dump_title"] = "Chat Debug Dump Exported", + ["debug_dump_body"] = "Download a JSON dump of this conversation for troubleshooting purposes.", + ["debug_dump_download"] = "Download JSON", + ["debug_dump_email"] = "Please send this dump to {email} so our support team can investigate the issue.", ["1h"] = "1h", ["6h"] = "6h", ["24h"] = "24h", diff --git a/scripts/lua/http_status_code.lua b/scripts/lua/http_status_code.lua index 4f2b763ace..41a579f2ca 100644 --- a/scripts/lua/http_status_code.lua +++ b/scripts/lua/http_status_code.lua @@ -1,5 +1,5 @@ -- --- (C) 2020 - ntop.org +-- (C) 2026 - ntop.org -- -- This page shows the HTTP errors that a user can get @@ -9,14 +9,18 @@ dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path require("lua_utils") -local page_utils = require("page_utils") -local message = _GET["message"] or "forbidden" -local referal_url = _GET["referer"] or '/' -local error_message = _GET["error_message"] or "" +local page_utils = require("page_utils") +local json = require "dkjson" +local template_utils = require "template_utils" -if(_GET["message"] == "not_found") then +local message = _GET["message"] or "forbidden" +local referal_url = _GET["referer"] or '/' +local error_message = _GET["error_message"] or "" + +local status_code +if(message == "not_found") then status_code = 404 -elseif(_GET["message"] == "internal_error") then +elseif(message == "internal_error") then status_code = 500 else status_code = 403 -- forbidden @@ -25,33 +29,19 @@ end sendHTTPContentTypeHeader('text/html', nil, nil, nil, status_code) page_utils.print_header() - referal_url = string.sub(referal_url, string.find(referal_url, "/"), string.len(referal_url)) -message = "http_status_code."..message dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") -print([[ -
-
-

- ]].. i18n("error_page.presence").. [[ -

- ]]) +local context = { + message_key = "http_status_code."..message, + error_message = error_message, + referal_url = referal_url, +} -print(i18n(message)) - - print('

'..error_message) -print([[

- - - ]].. i18n("error_page.go_back").. [[ - -
-
- -
-
-]]) +template_utils.render("pages/vue_page.template", { + vue_page_name = "PageHttpStatusCode", + page_context = json.encode(context) +}) dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") diff --git a/scripts/lua/modules/flow_utils.lua b/scripts/lua/modules/flow_utils.lua index 5d5b1fd36b..2d0e87b8dc 100644 --- a/scripts/lua/modules/flow_utils.lua +++ b/scripts/lua/modules/flow_utils.lua @@ -179,7 +179,6 @@ function getFlowsFilter() local src_asn = _GET["src_asn"] local dst_asn = _GET["dst_asn"] local host_pool = _GET["host_pool_id"] - local risk = _GET["risk"] local flow_status = _GET["flow_status"] local flow_status_severity = _GET["flow_status_severity"] local status = _GET["status"] @@ -428,10 +427,6 @@ function getFlowsFilter() pageinfo["poolFilter"] = tonumber(host_pool) end - if not isEmptyString(risk) then - pageinfo["riskFilter"] = tonumber(risk) - end - if not isEmptyString(client) then pageinfo["client"] = client end diff --git a/scripts/lua/ntopng_logout.lua b/scripts/lua/ntopng_logout.lua index 2e332470bf..0866abb1e4 100644 --- a/scripts/lua/ntopng_logout.lua +++ b/scripts/lua/ntopng_logout.lua @@ -1,25 +1,31 @@ -- --- (C) 2013-26 - ntop.org +-- (C) 2026 - ntop.org -- dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path require "lua_utils" -local debug = false +local page_utils = require "page_utils" +local json = require "dkjson" +local template_utils = require "template_utils" sendHTTPHeaderLogout('text/html') ntop.delCache("ntopng.cache.sessions.".._SESSION["session"]) -if (debug) then io.write("Deleting ".."ntopng.cache.sessions.".._SESSION["session"].."\n") end + +page_utils.print_header_minimal(i18n("login.logging_out")) + +local context = { + redirect_url = ntop.getHttpPrefix() .. "/", +} + +template_utils.render("pages/vue_page.template", { + vue_page_name = "PageLogout", + page_context = json.encode(context) +}) print [[ - - - - ]] print(i18n("login.logging_out")) print[[ - ]] - diff --git a/scripts/lua/rest/v2/get/flow/flow_filters.lua b/scripts/lua/rest/v2/get/flow/flow_filters.lua index 2212389b5d..2160fbe310 100644 --- a/scripts/lua/rest/v2/get/flow/flow_filters.lua +++ b/scripts/lua/rest/v2/get/flow/flow_filters.lua @@ -285,21 +285,6 @@ if table.len(flowstats["transit_asn"]) > 0 then } end -local severity_stats = flowstats["alert_levels"] -for s, severity_details in pairsByField(alert_consts.severity_groups, "severity_group_id", asc) do - if severity_stats[s] and severity_stats[s] > 0 then - status_filters[#status_filters + 1] = { - group = i18n("severity"), - key = "status", - value = s, - label = (i18n(severity_details.i18n_title) or s) - .. " (" - .. format_utils.formatValue(severity_stats[s]) - .. ")", - } - end -end - for _, entry in pairs({ "connecting", "closed", "established", "reset" }) do status_filters[#status_filters + 1] = { key = "status", @@ -309,6 +294,36 @@ for _, entry in pairs({ "connecting", "closed", "established", "reset" }) do } end +rsp[#rsp + 1] = { + action = "status", + label = i18n("status"), + name = "status", + value = status_filters, +} + +-- Flow alerts filters (severity + alert type breakdown) +local alerts_filters = { { + key = "status", + value = "", + label = i18n("all"), +} } + +local severity_stats = flowstats["alert_levels"] +for s, severity_details in pairsByField(alert_consts.severity_groups, "severity_group_id", asc) do + if severity_stats[s] and severity_stats[s] > 0 then + alerts_filters[#alerts_filters + 1] = { + group = i18n("severity"), + key = "status", + value = s, + label = (i18n(severity_details.i18n_title) or s) + .. " (" + .. format_utils.formatValue(severity_stats[s]) + .. ")", + count = severity_stats[s], + } + end +end + tmp_list = {} for status_key, status in pairs(flowstats["status"]) do if status.count > 0 then @@ -318,52 +333,21 @@ for status_key, status in pairs(flowstats["status"]) do key = "status", value = status_key, label = name .. " (" .. format_utils.formatValue(status.count) .. ")", + count = status.count, } end end for _, value in pairsByKeys(tmp_list, asc) do - status_filters[#status_filters + 1] = value + alerts_filters[#alerts_filters + 1] = value end -rsp[#rsp + 1] = { - action = "status", - label = i18n("status"), - name = "status", - value = status_filters, -} - --- Risk filters -if flowstats["risk"] and table.len(flowstats["risk"]) > 0 then - local risk_filters = { { - key = "risk", - value = "", - label = i18n("all"), - } } - - tmp_list = {} - for risk_id, risk_details in pairs(flowstats["risk"]) do - if risk_id ~= 0 then - local name = risk_details.name or tostring(risk_id) - tmp_list[name] = { - key = "risk", - value = risk_id, - label = name .. " (" .. format_utils.formatValue(risk_details.count) .. ")", - count = risk_details.count, - risk_name = name, - } - end - end - - for _, value in pairsByKeys(tmp_list, asc) do - risk_filters[#risk_filters + 1] = value - end - +if #alerts_filters > 1 then rsp[#rsp + 1] = { - action = "risk", - label = i18n("db_search.flowfilters.flow_risk"), - name = "risk", - value = risk_filters, + action = "flow_alerts", + label = i18n("flow_alerts_filter"), + name = "flow_alerts", + value = alerts_filters, } end diff --git a/scripts/lua/rest/v2/get/flow/geomap.lua b/scripts/lua/rest/v2/get/flow/geomap.lua index bd4fa0baab..40796b9bba 100644 --- a/scripts/lua/rest/v2/get/flow/geomap.lua +++ b/scripts/lua/rest/v2/get/flow/geomap.lua @@ -37,10 +37,7 @@ end local flows_filter = getFlowsFilter() flows_filter = as_utils.formatFilters(flows_filter, true) --- Need client/server geo-coordinates and country (for the flag in the --- tooltip), capped tightly since this powers a map view, not a paginated --- table. -flows_filter.detailsLevel = "max" +-- Capped tightly since this powers a map view, not a paginated table. flows_filter.maxHits = 512 flows_filter.perPage = 512 flows_filter.toSkip = 0 @@ -52,18 +49,36 @@ local nodes = {} local nodes_seen = {} local edges = {} -local function add_node(ip, lat, lng, country, protocol) - if isEmptyString(ip) or (lat == 0 and lng == 0) then +local geoloc_cache = {} + +local function get_geoloc(ip) + if geoloc_cache[ip] ~= nil then + return geoloc_cache[ip] + end + + local info = interface.getHostInfo(ip) + local geoloc = false + if info and info.latitude and info.longitude and info.latitude ~= 0 and info.longitude ~= 0 then + geoloc = { lat = info.latitude, lng = info.longitude, country = info.country } + end + + geoloc_cache[ip] = geoloc + return geoloc +end + +local function add_node(ip, protocol) + local geoloc = get_geoloc(ip) + if isEmptyString(ip) or not geoloc then return end if not nodes_seen[ip] then nodes_seen[ip] = { - lat = lat, - lng = lng, + lat = geoloc.lat, + lng = geoloc.lng, label = ip, ip = ip, status = "Online", - country = country, + country = geoloc.country, protocols = {}, connectionCount = 0 } @@ -79,17 +94,17 @@ if flows_stats and flows_stats.flows then for _, value in ipairs(flows_stats.flows) do local cli_ip = value["cli.ip"] local srv_ip = value["srv.ip"] - local cli_lat, cli_lng = value["cli.latitude"], value["cli.longitude"] - local srv_lat, srv_lng = value["srv.latitude"], value["srv.longitude"] local protocol = value["proto.ndpi"] - add_node(cli_ip, cli_lat, cli_lng, value["cli.country"], protocol) - add_node(srv_ip, srv_lat, srv_lng, value["srv.country"], protocol) + add_node(cli_ip, protocol) + add_node(srv_ip, protocol) - if cli_lat and cli_lat ~= 0 and srv_lat and srv_lat ~= 0 then + local cli_geoloc = get_geoloc(cli_ip) + local srv_geoloc = get_geoloc(srv_ip) + if cli_geoloc and srv_geoloc then edges[#edges + 1] = { - sourcePosition = { cli_lng, cli_lat }, - targetPosition = { srv_lng, srv_lat }, + sourcePosition = { cli_geoloc.lng, cli_geoloc.lat }, + targetPosition = { srv_geoloc.lng, srv_geoloc.lat }, sourceSiteId = cli_ip, targetSiteId = srv_ip, protocol = protocol, diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 64be299f0c..387dcd4a0a 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -5538,7 +5538,6 @@ static bool flow_matches(Flow* f, struct flowHostRetriever* retriever) { IpAddress* cli_ip = (IpAddress*)f->get_srv_ip_addr(); IpAddress* srv_ip = (IpAddress*)f->get_cli_ip_addr(); u_int16_t alert_type_filter, site_id; - int32_t risk_filter = -1; u_int8_t ip_version; u_int8_t l4_protocol; u_int8_t* mac_filter; @@ -5951,16 +5950,6 @@ static bool flow_matches(Flow* f, struct flowHostRetriever* retriever) { !f->getAlertsBitmap().isSetBit(alert_type_filter)) return (false); - /* Flow risk filter: 0 means "no risk" (i.e. flow not flagged by nDPI), - * not an actual risk bit. */ - if (retriever->pag && retriever->pag->riskFilter(&risk_filter)) { - if (risk_filter == 0) { - if (f->hasRisks()) return (false); - } else if (!f->hasRisk((ndpi_risk_enum)risk_filter)) { - return (false); - } - } - /* Flow Status severity filter */ if (retriever->pag && retriever->pag->flowStatusFilter(&flow_status_severity_filter)) { diff --git a/src/Paginator.cpp b/src/Paginator.cpp index b3836a8141..929fc13e24 100644 --- a/src/Paginator.cpp +++ b/src/Paginator.cpp @@ -70,7 +70,6 @@ Paginator::Paginator() { mac_filter = NULL; alert_type_filter = ((u_int16_t)-1); alert_type_severity_filter = alert_level_group_none; - risk_filter = -1; iface_index_filter = -1; memset(&deviceIP, 0, sizeof(deviceIP)); inIndex = outIndex = ifaceIndex = (u_int32_t)-1; @@ -267,8 +266,6 @@ void Paginator::readOptions(lua_State* L, int index) { iface_index_filter = lua_tointeger(L, -1); else if (!strcmp(key, "statusFilter")) alert_type_filter = lua_tointeger(L, -1); - else if (!strcmp(key, "riskFilter")) - risk_filter = lua_tointeger(L, -1); else if (!strcmp(key, "statusSeverityFilter")) alert_type_severity_filter = (AlertLevelGroup)lua_tointeger(L, -1); else if (!strcmp(key, "interfaceRole"))