EVOLUTION-MANAGER
Edit File: prefs_utils.lua
-- -- (C) 2014-24 - ntop.org -- -- This file contains the description of all functions -- used to trigger host alerts local verbose = false local prefs = ntop.getPrefs() local info = ntop.getInfo() local menu_subpages = require "prefs_menu" local have_nedge = ntop.isnEdge() local skip_redis = false -- ############################################ -- -- A menu is a list of menu entries -- A menu entry is composed by the following fields: -- - id: the subpage id -- - label: a label to be shown into the menu -- - entries: a list subpages (see belo) -- -- The following optional fields can be specified -- -- - advanced: if true, it should be only shown when advanced settings are enabled -- - pro_only: if true, it should be only shown in ntopng pro version -- - enterprise_only: if true, it should be only shown in ntopng enterprise version -- - disabled: if true, the entry is hidden -- -- A subpage is composed by the following fields: -- - title: the subpage title -- - description: the subpage description -- - hidden: (optional) if true, this subpage is hidden -- -- ############################################ DNS_PRESETS = { {id="comodo_secure", label="Comodo Secure DNS", url="https://www.comodo.com/secure-dns/", primary_dns="8.26.56.26", secondary_dns="8.20.247.20"}, {id="dyn_internet_guide", label="Dyn Internet Guide", url="http://dyn.com/labs/dyn-internet-guide/", primary_dns="216.146.35.35", secondary_dns="216.146.36.36"}, --{id="fool_dns", label="FoolDNS", url="http://www.fooldns.com/fooldns-community/english-version/", primary_dns="87.118.111.215", secondary_dns="213.187.11.62"}, --{id="greenteam_internet", label="GreenTeam Internet", url="http://members.greentm.co.uk/", primary_dns="81.218.119.11", secondary_dns="209.88.198.133"}, {id="opendns", label="OpenDNS", url="https://www.opendns.com/", primary_dns="208.67.222.222", secondary_dns="208.67.220.220"}, {id="opendns_familyshield", label="OpenDNS - FamilyShield", url="https://www.opendns.com/setupguide/?url=familyshield", primary_dns="208.67.222.123", secondary_dns="208.67.220.123", child_safe=true}, {id="quad9_security", label="Quad 9: Security", url="https://quad9.net", primary_dns="9.9.9.9", secondary_dns=""}, {id="google", label="Google DNS", url="https://developers.google.com/speed/public-dns", primary_dns="8.8.8.8", secondary_dns="8.8.4.4"}, {id="cloudflare", label="Cloudflare DNS", url="https://www.cloudflare.com/learning/dns/what-is-1.1.1.1", primary_dns="1.1.1.1", secondary_dns="1.0.0.1"}, {id="cleanbrowsing_security", label="CleanBrowsing - Security", url="https://cleanbrowsing.org", primary_dns="185.228.168.9", secondary_dns="185.228.169.9"}, {id="cleanbrwosing_adult", label="CleanBrowsing - Adult Filter", url="https://cleanbrowsing.org", primary_dns="185.228.168.168", secondary_dns="185.228.169.168", child_safe=true}, } function isSubpageAvailable(subpage, show_advanced_prefs) if show_advanced_prefs == nil then local show_advanced_prefs_key = "ntopng.prefs.show_advanced_prefs" show_advanced_prefs = toboolean(ntop.getPref(show_advanced_prefs_key)) end if (subpage.hidden) or ((subpage.advanced) and (not show_advanced_prefs)) or ((subpage.pro_only) and (not ntop.isPro())) or (subpage.enterprise_l_only and (not info["version.enterprise_l_edition"]) and (not info["version.nedge_enterprise_edition"])) or ((subpage.enterprise_only) and (not info["version.enterprise_edition"]) and (not have_nedge)) or (subpage.nedge_hidden) and (have_nedge) then return false end return true end function prefsGetActiveSubpage(show_advanced_prefs, tab) local subpage_active = nil for _, subpage in ipairs(menu_subpages) do if not isSubpageAvailable(subpage, show_advanced_prefs) then subpage.hidden = true if subpage.id == tab then -- will set to default tab = nil end elseif subpage.id == tab then subpage_active = subpage end end -- default subpage if isEmptyString(tab) then -- Pick the first available subpage for _, subpage in ipairs(menu_subpages) do if isSubpageAvailable(subpage, show_advanced_prefs) then subpage_active = subpage tab = subpage.id break end end end return subpage_active, tab end function printMenuSubpages(tab) for _, subpage in ipairs(menu_subpages) do if not subpage.hidden then local url = ternary(subpage.disabled, "#", ntop.getHttpPrefix() .. [[/lua/admin/prefs.lua?tab=]] .. (subpage.id)) print[[<a href="]] print(url) print[[" class="list-group-item list-group-item-action]] if(tab == subpage.id) then print(" active") elseif subpage.disabled then print(" disabled") end print[[">]] print(subpage.label) print[[</a>]] end end end -- ############################################ --- Notify ntopng upon preference changes function notifyNtopng(key, value) if key == nil then return end -- notify runtime ntopng configuration changes if string.starts(key, 'toggle_logging_level') then if verbose then io.write('notifying ntopng upon logging level pref change\n') end ntop.setLoggingLevel(value) end end -- ############################################ local options_script_loaded = false local options_ctr = 0 function prefsResolutionButtons(fmt, value, fixed_id, format_spec, max_val) local ctrl_id if fixed_id ~= nil then ctrl_id = fixed_id else ctrl_id = "options_group_" .. options_ctr options_ctr = options_ctr + 1 end local res = makeResolutionButtons(format_spec or FMT_TO_DATA_TIME, ctrl_id, fmt, value, {classes={"float-right"}}, max_val) res.value = truncate(res.value or 1) print(res.html) print("<script>") if not options_script_loaded then print(res.init) options_script_loaded = true end print(res.js) print("</script>") return res.value end -- ############################################ -- Runtime preference function prefsInputFieldPrefs(label, comment, prekey, key, default_value, _input_type, showEnabled, disableAutocomplete, allowURLs, extra) extra = extra or {} if(string.ends(prekey, ".")) then k = prekey..key else k = prekey.."."..key end skip_redis = extra.skip_redis or false if not skip_redis then if(_POST[key] ~= nil) then v_s = _POST[key] v = tonumber(v_s) v_cache = ntop.getPref(k) value = v_cache if ((v_cache == nil) or (v_s ~= v_cache)) then if(v ~= nil and (v > 0) and (v <= 86400)) then ntop.setPref(k, tostring(v)) value = v elseif (v_s ~= nil) then if(allowURLs or (extra.pattern == getURLPattern())) then v_s = string.gsub(v_s, "ldaps:__", "ldaps://") v_s = string.gsub(v_s, "ldap:__", "ldap://") v_s = string.gsub(v_s, "http:__", "http://") v_s = string.gsub(v_s, "https:__", "https://") v_s = string.gsub(v_s, "smtp:__", "smtp://") v_s = string.gsub(v_s, "smtps:__", "smtps://") end ntop.setPref(k, v_s) value = v_s end -- least but not last we asynchronously notify the runtime ntopng instance for changes notifyNtopng(key) end else local v_s = nil if not isEmptyString(prekey) then v_s = ntop.getPref(k) end value = v_s if((v_s==nil) or (v_s=="") or (v_s=="nil")) then value = default_value if not isEmptyString(prekey) and (ntop.getPref(k) ~= tostring(default_value)) then ntop.setPref(k, tostring(default_value)) notifyNtopng(key) end end end else value = default_value end -- skip_redis if ((showEnabled == nil) or (showEnabled == true)) then showEnabled = "table-row" else showEnabled = "none" end local attributes = {} if extra.min ~= nil then if extra.tformat ~= nil then attributes["data-min"] = extra.min else attributes["min"] = extra.min end end if extra.max ~= nil then if extra.tformat ~= nil then attributes["data-max"] = extra.max else attributes["max"] = extra.max end end if extra.minlength ~= nil then if extra.tformat ~= nil then attributes["data-minlength"] = extra.minlength else attributes["minlength"] = extra.minlength end end if extra.maxlength ~= nil then if extra.tformat ~= nil then attributes["data-maxlength"] = extra.maxlength else attributes["maxlength"] = extra.maxlength end end if extra.step ~= nil then if extra.tformat ~= nil then attributes["data-step"] = extra.step else attributes["step"] = extra.step end end if extra.disabled == true then attributes["disabled"] = "disabled" end if extra.required == true then attributes["required"] = "" end if extra.pattern ~= nil then attributes["pattern"] = extra.pattern end if (_input_type == "number") then attributes["required"] = "required" elseif (_input_type == "password") then -- disable chrome autocomplete attributes["autocomplete"] = "new-password" end local input_type = "text" if _input_type ~= nil then input_type = _input_type end print('<tr id="'..key..'" style="display: '..showEnabled..';"><td width=50%><strong>'..(label or "")..'</strong>') if(comment ~= nil) then print('<p><small>'..comment..'</small></td>') end local style = {} style["text-align"] = "right" style["margin-bottom"] = "0.5em" print [[ <td align=right> <table class="table table-borderless form-group mb-3" style="margin-bottom: 0; min-width:22em;"> <tr> <td width="100%;"></td> <td style="vertical-align:top;">]] if extra.tformat ~= nil then value = prefsResolutionButtons(extra.tformat, value, nil, extra.format_spec, extra.max) end if extra.width == nil then if _input_type == "number" then style["width"] = "8em" elseif (extra["inputBoxWidth"] ~= nil) then style["width"] = extra["inputBoxWidth"] -- use em i.e. 20em else style["width"] = "20em" end style["margin-left"] = "auto" else style["width"] = "15em" end style["margin-left"] = "auto" style["display"] = "inline" style = table.merge(style, extra.style) attributes = table.merge(attributes, extra.attributes) print[[ </td> <td style="vertical-align:top; padding-left: 2em; white-space: nowrap;"> <input id="id_input_]] print(key) print[[" type="]] print(input_type) print [[" class="form-control" ]] print(table.tconcat(attributes, "=", " ", nil, '"')) print[[ name="]] print(key) print [[" style="]] print(table.tconcat(style, ":", "; ", ";")) print[[" value="]] print(value..'"') if disableAutocomplete then print(" autocomplete=\"off\"") end print [[/>]] print(extra.append or "") print[[ <span id="input_error_]] print(key) print[[" class="text-danger" hidden>!</span> <script> $("#]] print("id_input_" .. key) print[[").on( "focusout", function(tmp) { const min_value = Number(this.getAttribute('min')); const max_value = Number(this.getAttribute('max')); const value = Number(this.value); /* Incorrect value, text danger class! */ if(value < min_value || (max_value != 0 && value > max_value)) { this.classList.add('text-danger'); this.classList.add('ntopng-input-error'); $("#]] print("input_error_" .. key) print[[").removeAttr('hidden'); } else { this.classList.remove('text-danger'); this.classList.remove('ntopng-input-error'); $("#]] print("input_error_" .. key) print[[").attr('hidden', true); } }); $("#]] print("id_input_" .. key) print[[").on( "focusin", function(tmp) { this.classList.remove('text-danger'); this.classList.remove('ntopng-input-error'); $("#]] print("input_error_" .. key) print[[").attr('hidden', true); }); </script> </td> </tr> <tr> <td colspan="3" style="padding:0;"> <div class="help-block with-errors text-end" style="height:1em;"></div> </td> </tr> </table> </td></tr> ]] end -- ############################################ function prefsDropdownFieldPrefs(label, comment, key, values, default_value, showEnabled, extra) extra = extra or {} if extra.save_pref and table.len(_POST) > 0 and isEmptyString(_POST[key]) == false and isEmptyString(extra.pref_key) == false then ntop.setPref(extra.pref_key, _POST[key]) default_value = _POST[key] end if ((showEnabled == nil) or (showEnabled == true)) then showEnabled = "table-row" else showEnabled = "none" end local attributes = {} if extra.disabled == true then attributes["disabled"] = "disabled" end if extra.required == true then attributes["required"] = "" end local input_type = "text" print('<tr id="'..key..'" style="display: '..showEnabled..';"><td width=50%><strong>'..label..'</strong><p><small>'..comment..'</small></td>') local style = {} style["text-align"] = "right" style["margin-bottom"] = "0.5em" print [[ <td align=right> <table class="form-group mb-3" style="margin-bottom: 0; min-width:22em;"> <tr> <td width="100%;"></td>]] if extra.width == nil then style["width"] = "20em" style["margin-left"] = "auto" else style["width"] = "15em" end style["margin-left"] = "auto" style = table.merge(style, extra.style) attributes = table.merge(attributes, extra.attributes) print[[ <td style="vertical-align:top; padding-left: 2em;"> <select id="id_input_]] print(key) print [[" class="form-select" ]] print(table.tconcat(attributes, "=", " ", nil, '"')) print[[ name="]] print(key) print [[" style="]] print(table.tconcat(style, ":", "; ", ";")) print[[" value="]] print((value or '')..'"') print[[>]] if extra.keys == nil then for _, optname in pairs(values) do print("<option " .. ternary(optname == default_value, "selected", "") .. ">"..optname.."</option>") end else for idx, _ in pairs(values) do local key = extra.keys[idx] local val = values[idx] print("<option value=".. key .." " .. ternary(key == default_value, "selected", "") .. ">"..val.."</option>") end end print[[ </select> </td> </tr> <tr> <td colspan="3" style="padding:0;"> <div class="help-block with-errors text-end" style="height:1em;"></div> </td> </tr> </table> </td></tr> ]] end -- ############################################ function prefsInformativeField(label, comment, showEnabled, extra) local extra = extra or {} extra["style"] = extra["style"] or {} extra["style"]["display"] = "none" prefsInputFieldPrefs(label, comment, "", "", "", nil, showEnabled, nil, nil, extra) end function toggleTableButton(label, comment, on_label, on_value, on_color , off_label, off_value, off_color, submit_field, redis_key, disabled) if(_POST[submit_field] ~= nil) then ntop.setPref(redis_key, _POST[submit_field]) value = _POST[submit_field] notifyNtopng(submit_field) else value = ntop.getPref(redis_key) end if (disabled == true) then disabled = 'disabled = ""' else disabled = "" end -- Read it anyway to if(value == off_value) then rev_value = on_value on_active = "btn-secondary" off_active = "btn-"..off_color.." active" else rev_value = off_value on_active = "btn-"..on_color.." active" off_active = "btn-secondary" end if(label ~= "") then print('<tr><td width=50%><strong>'..label..'</strong><p><small>'..comment..'</small></td><td align=right>\n') end print('<form method="post">\n<div class="btn-group btn-toggle">') print('<button type="submit" '..disabled..' class="btn btn-sm '..on_active..'">'..on_label..'</button>') print('<button '..disabled..' class="btn btn-sm '..off_active..'">'..off_label..'</button></div>\n') print('<input id="csrf" name="csrf" type="hidden" value="'..ntop.getRandomCSRFValue()..'" />\n') print('<input type=hidden name='..submit_field..' value='..rev_value..' />\n') print('</form>\n') if(label ~= "") then print('</td></tr>') end return(value) end local function printNestedToSwitchLogic(nested_to_switch, submit_field) if((type(nested_to_switch) ~= "table") or (table.empty(nested_to_switch))) then return end for _, item in ipairs(nested_to_switch) do print[[ if(($("#]] print(submit_field) print[[").val() == "]] print(item.pref_enabled_value or "1") print[[") && ($("#]] print(item.parent) print[[").val() == "]] print(item.parent_enabled_value) print[[")) $("#]] print(item.input) print[[").css("display", "table-row"); else $("#]] print(item.input) print[[").css("display", "none"); ]] end end local function toggleTableButtonPrefs(label, comment, on_label, on_value, on_color , off_label, off_value, off_color, submit_field, redis_key, default_value, disabled, elementToSwitch, hideOn, showElement, nested_to_switch, local_store) local value if not skip_redis and not local_store then value = ntop.getPref(redis_key) if(_POST[submit_field] ~= nil) then if ( (value == nil) or (value ~= _POST[submit_field])) then ntop.setPref(redis_key, _POST[submit_field]) value = _POST[submit_field] notifyNtopng(submit_field) end else if ((value == nil) or (value == "")) then if (default_value ~= nil) then value = default_value else value = off_value end ntop.setPref(redis_key, value) notifyNtopng(submit_field) end end else value = default_value end if (disabled == true) then disabled = 'disabled = ""' else disabled = "" end -- Read it anyway to if(value ~= off_value) then value = on_value end local objRow = "" if ((showElement ~= nil) and (showElement == false)) then objRow = " style=\"display:none\"" else objRow = " style=\"display:table-row\"" end if(label ~= "") then print('<tr id="row_'..submit_field..'"'..objRow..'><td width=50%><strong>'..label..'</strong><p><small>'..comment..'</small></td><td align=right>\n') end print([[ <div class="form-switch"> <input ]].. (value == off_value and '' or 'checked') ..[[ type="checkbox" class="form-check-input" id="check-]].. submit_field ..[["> <label class="form-check-label" for="check-]].. submit_field ..[["></label> <input hidden id="input-]].. submit_field ..[[" name="]].. submit_field ..[[" value="]].. value ..[["> ]]) print([[</div>]]) if(label ~= "") then print('</td></tr>') end print('<script type="text/javascript">') print([[ $("#check-]].. submit_field.. [[").change(function(e) { const value = $(this).is(":checked"); if (value) { ]]..submit_field..[[_functionOn(); } else { ]]..submit_field..[[_functionOff(); } }); ]]) print[[function ]] print(submit_field) print [[_functionOn(){]] print([[$(`#input-]].. submit_field ..[[`).val("]].. on_value ..[[");]]) if elementToSwitch ~= nil then for element = 1, #elementToSwitch do if ((hideOn == nil) or (hideOn == false)) then print('$("#'..elementToSwitch[element]..'").css("display","table-row");') else print('$("#'..elementToSwitch[element]..'").css("display","none");') end end end printNestedToSwitchLogic(nested_to_switch, "input-" .. submit_field) print[[ } ]] print[[ function ]] print(submit_field) print [[_functionOff(){]] print([[$(`#input-]].. submit_field ..[[`).val("]].. off_value ..[["); ]]) if elementToSwitch ~= nil then for element = 1, #elementToSwitch do if ((hideOn == nil) or (hideOn == false)) then print('$("#'..elementToSwitch[element]..'").css("display","none");') else print('$("#'..elementToSwitch[element]..'").css("display","table-row");') end end end printNestedToSwitchLogic(nested_to_switch, "input-" .. submit_field) print [[ }]] print('</script>\n') return(value) end local function get_pref_redis_key(options) local prefix = options.redis_prefix or "ntopng.prefs." return prefix .. ternary(options.pref ~= nil, options.pref, options.field) end function prefsToggleButton(subpage_active, params) local defaults = { to_switch = {}, -- a list of elements to be switched on or off on_text = "On", -- The text when the button is on on_value = "1", -- The value when the button is on on_class = "success", -- The css class when the button is on off_text = "Off", -- The text when the button is off off_value = "0", -- The value when the button is off off_class = "danger", -- The css class when the button is off reverse_switch = false, -- If true, elements are hidden when the item is enabled nested_to_switch = {}, -- Similar to "to_switch" but for nested items local_store = false, -- If true, do not store the field in redis } local options = table.merge(defaults, params) local redis_key = get_pref_redis_key(options) -- used for debugging purpose: -- if (subpage_active.entries[options.field] ~= nil) then -- traceError(TRACE_ERROR, TRACE_CONSOLE, "Missing entry '" .. options.field .. "' inside entries field") -- end return toggleTableButtonPrefs(params.title or subpage_active.entries[options.field].title, (params.description or subpage_active.entries[options.field].description) .. (params.content or subpage_active.entries[options.field].content or ""), options.on_text, options.on_value, options.on_class, options.off_text, options.off_value, options.off_class, options.field, redis_key, options.default, options.disabled, options.to_switch, options.reverse_switch, not options.hidden, options.nested_to_switch, options.local_store) end function multipleTableButtonPrefs(label, comment, array_labels, array_values, default_value, selected_color, submit_field, redis_key, disabled, elementToSwitch, showElementArray, nested_to_switch, showElement, initialValue, toggleElementArray) local value local disabled_attr if not skip_redis then if(_POST[submit_field] ~= nil) then local old_v = ntop.getPref(redis_key) value = _POST[submit_field] if old_v ~= _POST[submit_field] then ntop.setPref(redis_key, _POST[submit_field]) notifyNtopng(submit_field) end else value = initialValue or ntop.getPref(redis_key) if(value == "") then if(default_value ~= nil) then ntop.setPref(redis_key, default_value) value = default_value end end end else value = default_value end if (disabled == true) then disabled = "disabled" disabled_attr = ' disabled="disabled"' else disabled = "" disabled_attr = "" end local objRow = "" if ((showElement ~= nil) and (showElement == false)) then objRow = " style=\"display:none\"" else objRow = " style=\"display:table-row\"" end if(value ~= nil) then if(label ~= "") then print('<tr id="row_'..submit_field..'"'..objRow..'><td width=50%><strong>'..label..'</strong><p><small>'..comment..'</small></td><td align=right>\n') end print('<div class="btn-group" role="group">') for nameCount = 1, #array_labels do local type_button = "btn-secondary" if(value == array_values[nameCount]) then local color if type(selected_color) == "table" then color = selected_color[nameCount] else color = selected_color end type_button = "btn-"..color.." active" end print('<input type="radio" name="'..submit_field..'" id="id_'..submit_field..'_'..array_values[nameCount]..'" value="'..array_values[nameCount]..'" class="btn-check btn-primary" '.. disabled_attr ..'>\n') print('<label class="btn btn-sm '..type_button..'" for="id_'..submit_field..'_'..array_values[nameCount]..'">' .. array_labels[nameCount] .. '</label>\n') end print('</div>\n') print('<script>\n') -- showElementArray can be either: -- 1. a simple table (e.g. {true, false}): it affects all the elements in elementToSwitch -- 2. a nested table (e.g. {{true, false}, {false, false}}): each element in the table -- affects the corresponding element in the elementToSwitch (e.g. {true, false} affects -- elementToSwitch[1], whereas {false, false} affects elementToSwitch[2]) if(showElementArray and (type(showElementArray[1]) ~= "table")) then -- This is simple table (case 1.) above, convert it to case 2 to handle -- both cases consinstenly below. showElementArray = {showElementArray, } end for nameCount = 1, #array_labels do print('$(`label[for="id_'..submit_field..'_'..array_values[nameCount]..'"]`).click(function() {\n') print(' var field = $(\'#id-toggle-'..submit_field..'\');\n') print(' var oldval = field.val(); ') print(' field.val("'..array_values[nameCount]..'").trigger("change");\n') for indexLabel = 1, #array_labels do local color if type(selected_color) == "table" then color = selected_color[indexLabel] else color = selected_color end print[[ let class_]] print(array_values[indexLabel]) print[[ = $(`label[for="id_]] print(submit_field..'_') print(array_values[indexLabel]) print [["]`); class_]] print(array_values[indexLabel]) print[[.removeAttr("class");]] if(array_values[indexLabel] == array_values[nameCount]) then print[[class_]] print(array_values[indexLabel]) print[[.attr("class", "btn btn-sm btn-]]print(color) print[[ active");]] else print[[class_]] print(array_values[indexLabel]) print[[.attr("class", "btn btn-sm btn-secondary");]] end end -- Show/Hide all the elementToSwitch items at once if (showElementArray ~= nil) then for indexSwitch = 1, #showElementArray[1] do if (indexSwitch == nameCount) then if elementToSwitch ~= nil then for element = 1, #elementToSwitch do -- Try to get the element-specific configuration if available, -- otherwise fallback to the default configuration (at index 1) local to_apply = showElementArray[element] or showElementArray[1] if (to_apply[indexSwitch] == true) then -- NOTE: this is executed into the js change callback print('$("#'..elementToSwitch[element]..'").css("display","table-row");\n') else -- NOTE: this is executed into the js change callback print('$("#'..elementToSwitch[element]..'").css("display","none");\n') end end end end end -- Show/Hide all the elementToSwitch selectively elseif (toggleElementArray ~= nil) then for indexSwitch = 1, #toggleElementArray do if (indexSwitch == nameCount) then if elementToSwitch ~= nil then for element = 1, #elementToSwitch do if (toggleElementArray[indexSwitch][element] == true) then -- NOTE: this is executed into the js change callback print('$("#'..elementToSwitch[element]..'").css("display","table-row");\n') else -- NOTE: this is executed into the js change callback print('$("#'..elementToSwitch[element]..'").css("display","none");\n') end end end end end end printNestedToSwitchLogic(nested_to_switch, "id-toggle-" .. submit_field) print('});\n') end print('</script>\n') if(label ~= "") then print('</td></tr>') end end return(value) end function loggingSelector(label, comment, submit_field, redis_key) prefs = ntop.getPrefs() if prefs.has_cmdl_trace_lvl then return end if(_POST[submit_field] ~= nil) then ntop.setCache(redis_key, _POST[submit_field]) value = _POST[submit_field] notifyNtopng(submit_field, _POST[submit_field]) else value = ntop.getCache(redis_key) end if value == "" or value == nil then value = "normal" end local logging_values = {"trace", "debug", "info", "normal", "warning", "error"} local color_map = {"secondary", "success", "info", "primary", "warning", "danger"} local logging_keys = {} local color = "secondary" for i,v in ipairs(logging_values) do logging_keys[i] = firstToUpper(v) end multipleTableButtonPrefs("Log level", "Choose the runtime logging level.", logging_keys, logging_values, value, color_map, submit_field, redis_key) return(value) end function printPageSection(section_name) print('<thead class="table-primary"><tr><th colspan=2 class="info">'..section_name..'</th></tr></thead>') end function printSaveButton(some_content) print('<tr><td colspan=2 style="text-align:right;">' .. (some_content or "") .. '<button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></td></tr>') end function prefsSkipRedis(skip) skip_redis = skip end function isNetBoxEnabled() if not ntop.isEnterpriseXL() then return false end return (ntop.getPref("ntopng.prefs.toggle_netbox") == "1") end function isNtopngAssetsInventoryEnabled() if not ntop.isEnterpriseXL() then return false end return (ntop.getPref("ntopng.prefs.toggle_ntopng_assets_inventory") == "1") end function getNetBoxURL() if not ntop.isEnterpriseXL() or not ntop.getPref("ntopng.prefs.toggle_netbox") == "1" then return "" end return ntop.getPref("ntopng.prefs.netbox_activation_url") end function getNetBoxDefaultSite() if not ntop.isEnterpriseXL() or not ntop.getPref("ntopng.prefs.toggle_netbox") == "1" then return "" end return ntop.getPref("ntopng.prefs.netbox_default_site") end function getNetBoxToken() if not ntop.isEnterpriseXL() or not ntop.getPref("ntopng.prefs.toggle_netbox") == "1" then return "" end return ntop.getPref("ntopng.prefs.netbox_personal_access_token") end