mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-23 03:27:02 +09:00
Fix develop client behavior, popup isolation and PHP method visibility (#8292)
* fix(core): correct client state and declare public method contracts Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(security): isolate Midwinter external homepage popup Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(client): isolate menu state and simplify validated JavaScript guards Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test(auth): use certificate expiry truth in rendering assertions Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * refactor(js): remove unused local storage while retaining initializer calls Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(js): encode inline translated values through the shared JSON boundary Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * style(js): wrap encoded translation literals without changing messages Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(client): remove unused checkbox reads from graph resizing Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * refactor(client): declare repeated function locals once Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test(ui): run column width regression in browser CI Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This commit is contained in:
1 parent
391c6ead18
commit
08d0f94f24
32 files changed
+834
-329
No files matched your search
@@ -0,0 +1,30 @@
|
||||
name: Develop client security
|
||||
on:
|
||||
pull_request:
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [develop]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
chromium:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
cache-dependency-path: tests/e2e/package-lock.json
|
||||
- name: Install locked browser tooling
|
||||
working-directory: tests/e2e
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm ci --ignore-scripts
|
||||
npx --no-install playwright install --with-deps chromium
|
||||
- name: Verify popup isolation, navigation state and column widths
|
||||
working-directory: tests/e2e
|
||||
run: npx --no-install playwright test tests/develop-client-security.spec.ts tests/develop-menu-state.spec.ts tests/table-column-widths.spec.ts --project=chromium
|
||||
@@ -261,7 +261,7 @@ midwinter.navigationBox.table = {
|
||||
*/
|
||||
init: function($box) {
|
||||
if (!$box || !$box.length) return;
|
||||
const helper = $box.data('helper');
|
||||
$box.data('helper');
|
||||
const ns = midwinter.navigationBox.table;
|
||||
|
||||
// bind toggle checkboxes
|
||||
|
||||
@@ -34,7 +34,7 @@ midwinter.navigationBox.tree = {
|
||||
*/
|
||||
getDefaultConfig: function(overrides = {}) {
|
||||
// derive the type from the object path
|
||||
const type = 'tree';
|
||||
|
||||
const base = 'midwinter.navigationBox';
|
||||
|
||||
const defaults = {
|
||||
|
||||
@@ -16,15 +16,15 @@ $.toastPopup = function(options) {
|
||||
loader: true,
|
||||
}
|
||||
|
||||
if (typeof options == "undefined") {
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
} else if (typeof options == "string" || typeof options == "String") {
|
||||
} else if (typeof options === "string" || options instanceof String) {
|
||||
options = {
|
||||
text: options
|
||||
text: String(options)
|
||||
};
|
||||
}
|
||||
|
||||
toastOptions = $.extend(defaultOptions, options, fixedOptions);
|
||||
const toastOptions = $.extend(defaultOptions, options, fixedOptions);
|
||||
return $.toast(toastOptions);
|
||||
}
|
||||
|
||||
|
||||
+179
-168
@@ -199,7 +199,7 @@ jQuery.ajaxQ = (function () {
|
||||
*/
|
||||
function basename(path, suffix) {
|
||||
var b = path;
|
||||
var lastChar = b.charAt(b.length - 1);
|
||||
b.charAt(b.length - 1);
|
||||
|
||||
// Don't remove trailing slash for now //
|
||||
/*
|
||||
@@ -229,12 +229,12 @@ function basename(path, suffix) {
|
||||
/** getTimestampFromDate - Simple function to convert a MySQL Date
|
||||
* to a timestamp */
|
||||
function getTimestampFromDate(dateStamp) {
|
||||
if (typeof dateStamp != 'undefined') {
|
||||
if (dateStamp !== undefined) {
|
||||
var dateParts = dateStamp.split(' ');
|
||||
var timeParts = dateParts[1].split(':');
|
||||
|
||||
dateParts = dateParts[0].split('-');
|
||||
var date = new Date(dateParts[0], parseInt(dateParts[1], 10) - 1, dateParts[2], timeParts[0], timeParts[1]);
|
||||
var date = new Date(dateParts[0], Number.parseInt(dateParts[1], 10) - 1, dateParts[2], timeParts[0], timeParts[1]);
|
||||
|
||||
return date.getTime() / 1000;
|
||||
}
|
||||
@@ -267,7 +267,7 @@ function getQueryString(name) {
|
||||
*/
|
||||
$.fn.delayKeyup = function (callback, ms) {
|
||||
var timer = 0;
|
||||
if (typeof ms === 'undefined' || ms < 500) {
|
||||
if (ms === undefined || ms < 500) {
|
||||
ms = keyup_delay;
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ $.fn.enableDisableOptions = function (values, optionEnabled, valueCheckFunc) {
|
||||
}
|
||||
|
||||
var selectMenu = $(this).selectmenu('instance');
|
||||
if (typeof selectMenu != 'undefined') {
|
||||
if (selectMenu !== undefined) {
|
||||
$(this).selectmenu('refresh');
|
||||
}
|
||||
|
||||
@@ -448,11 +448,12 @@ $.fn.textWidth = function (text) {
|
||||
* without any wrapping.
|
||||
*/
|
||||
$.fn.textBoxWidth = function () {
|
||||
var text;
|
||||
var org = $(this);
|
||||
if (org.val()) {
|
||||
var text = encodeURIComponent(org.val());
|
||||
text = encodeURIComponent(org.val());
|
||||
} else {
|
||||
var text = encodeURIComponent(org.text());
|
||||
text = encodeURIComponent(org.text());
|
||||
}
|
||||
|
||||
var html = $('<span style="display:none;white-space:nowrap;position:absolute;width:auto;left:-9999px">' + text + '</span>');
|
||||
@@ -842,7 +843,7 @@ function dqUpdateDeps(snmp_query_id) {
|
||||
$('tr[id^="dqline' + snmp_query_id + '_"]').each(function (data) {
|
||||
var id = $(this).attr('id');
|
||||
var pieces = id.split('_');
|
||||
var dq = pieces[0].substr(6);
|
||||
pieces[0].substr(6);
|
||||
var hash = pieces[1];
|
||||
|
||||
if ($.inArray(hash, created_graphs[snmp_query_graph_id]) >= 0) {
|
||||
@@ -1104,12 +1105,13 @@ function applySkin() {
|
||||
$(document).tooltip({
|
||||
items: 'div.cactiTooltipHint, span.cactiTooltipHint, .checkboxSlider',
|
||||
content: function () {
|
||||
var text;
|
||||
var element = $(this);
|
||||
|
||||
if (element.is('div')) {
|
||||
var text = DOMPurify.sanitize($(this).find('span').html());
|
||||
text = DOMPurify.sanitize($(this).find('span').html());
|
||||
} else if (element.is('span') || element.is('a')) {
|
||||
var text = DOMPurify.sanitize($(this).prop('title'));
|
||||
text = DOMPurify.sanitize($(this).prop('title'));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -1171,7 +1173,7 @@ function applySkin() {
|
||||
|
||||
$('#main').css('display', 'table');
|
||||
|
||||
var showPage = $('#main').map(function (i, el) {
|
||||
$('#main').map(function (i, el) {
|
||||
var dfd = $.Deferred();
|
||||
$(el).show(function () {
|
||||
dfd.resolve();
|
||||
@@ -1569,19 +1571,19 @@ function sessionNoticesDisplay() {
|
||||
var title = '';
|
||||
var id = '';
|
||||
|
||||
if (typeof notice.message !== 'undefined') {
|
||||
if (notice.message !== undefined) {
|
||||
message = notice.message;
|
||||
}
|
||||
|
||||
if (typeof notice.title !== 'undefined') {
|
||||
if (notice.title !== undefined) {
|
||||
titLe = notice.tite;
|
||||
}
|
||||
|
||||
if (typeof notice.level !== 'undefined') {
|
||||
if (notice.level !== undefined) {
|
||||
level = notice.level;
|
||||
}
|
||||
|
||||
if (typeof notice.id !== 'undefined') {
|
||||
if (notice.id !== undefined) {
|
||||
id = '-' + notice.id;
|
||||
}
|
||||
|
||||
@@ -1617,6 +1619,7 @@ function sessionNoticesDisplay() {
|
||||
}
|
||||
|
||||
function sessionMessageDisplay() {
|
||||
var sessionMessageButtons;
|
||||
var title = '';
|
||||
var header = '';
|
||||
|
||||
@@ -1628,11 +1631,11 @@ function sessionMessageDisplay() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof sessionMessage.level != 'undefined') {
|
||||
if (sessionMessage.level !== undefined) {
|
||||
if (sessionMessage.level == MESSAGE_LEVEL_ERROR) {
|
||||
title = errorReasonTitle;
|
||||
header = errorOnPage;
|
||||
var sessionMessageButtons = {
|
||||
sessionMessageButtons = {
|
||||
'Ok': {
|
||||
text: sessionMessageOk,
|
||||
id: 'btnSessionMessageOk',
|
||||
@@ -1646,7 +1649,7 @@ function sessionMessageDisplay() {
|
||||
} else if (sessionMessage.level == MESSAGE_LEVEL_MIXED) {
|
||||
title = mixedReasonTitle;
|
||||
header = mixedOnPage;
|
||||
var sessionMessageButtons = {
|
||||
sessionMessageButtons = {
|
||||
'Ok': {
|
||||
text: sessionMessageOk,
|
||||
id: 'btnSessionMessageOk',
|
||||
@@ -1663,7 +1666,7 @@ function sessionMessageDisplay() {
|
||||
} else {
|
||||
title = sessionMessageTitle;
|
||||
header = sessionMessageSave;
|
||||
var sessionMessageButtons = {
|
||||
sessionMessageButtons = {
|
||||
'Pause': {
|
||||
text: sessionMessagePause,
|
||||
id: 'btnSessionMessagePause',
|
||||
@@ -2006,10 +2009,11 @@ function responsiveUI(event) {
|
||||
|
||||
/* change textbox and textarea widths */
|
||||
$('input[type="text"], textarea').each(function () {
|
||||
var offset;
|
||||
if ($(this).attr('type') == 'text') {
|
||||
var offset = 20;
|
||||
offset = 20;
|
||||
} else {
|
||||
var offset = 5;
|
||||
offset = 5;
|
||||
}
|
||||
|
||||
if (mainWidth != 100) {
|
||||
@@ -2039,11 +2043,12 @@ function responsiveUI(event) {
|
||||
}
|
||||
|
||||
function getMainWidth() {
|
||||
var mainWidth;
|
||||
// Subtract 15px for the scroll bar
|
||||
if ($('#navigation').length && $('#navigation').is(':visible')) {
|
||||
var mainWidth = $('body').outerWidth() - $('#navigation').width() - 15;
|
||||
mainWidth = $('body').outerWidth() - $('#navigation').width() - 15;
|
||||
} else {
|
||||
var mainWidth = $('body').outerWidth() - 15;
|
||||
mainWidth = $('body').outerWidth() - 15;
|
||||
}
|
||||
|
||||
return mainWidth;
|
||||
@@ -2060,21 +2065,20 @@ function getCactiHelp(cactiPage) {
|
||||
}
|
||||
|
||||
function responsiveResizeGraphs(initialize) {
|
||||
var graphRow, drillDown;
|
||||
var mainWidth = getMainWidth() - 30;
|
||||
var myColumns = $('#columns').val();
|
||||
var isThumb = $('#thumbnails').is(':checked') || $('#thumbnails').val() == 'true';
|
||||
var isBusiness = $('#business_hours').is(':checked') || $('#business_hours').val() == 'true';
|
||||
|
||||
if ($('.tableRowGraph:first').length) {
|
||||
var graphRow = $('.tableRowGraph:first').width();
|
||||
graphRow = $('.tableRowGraph:first').width();
|
||||
} else {
|
||||
var graphRow = 0;
|
||||
graphRow = 0;
|
||||
}
|
||||
|
||||
if ($('.graphDrillDown:first').length) {
|
||||
var drillDown = $('.graphDrillDown:first').outerWidth() + 15;
|
||||
drillDown = $('.graphDrillDown:first').outerWidth() + 15;
|
||||
} else {
|
||||
var drillDown = 0;
|
||||
drillDown = 0;
|
||||
}
|
||||
|
||||
if (myColumns == null) {
|
||||
@@ -2088,12 +2092,12 @@ function responsiveResizeGraphs(initialize) {
|
||||
}
|
||||
|
||||
// Dont resize if nothing changed
|
||||
if (typeof initialize == 'undefined' && (previousMainWidth == null || (previousMainWidth == mainWidth && previousColumns == myColumns))) {
|
||||
if (initialize === undefined && (previousMainWidth == null || (previousMainWidth == mainWidth && previousColumns == myColumns))) {
|
||||
previousMainWidth = mainWidth;
|
||||
return true;
|
||||
}
|
||||
|
||||
var myWidth = parseInt((graphRow - (drillDown * myColumns)) / myColumns);
|
||||
var myWidth = Number.parseInt((graphRow - (drillDown * myColumns)) / myColumns);
|
||||
|
||||
$('.graphimage').each(function () {
|
||||
var graph_id = $(this).attr('graph_id');
|
||||
@@ -2103,11 +2107,11 @@ function responsiveResizeGraphs(initialize) {
|
||||
graph_id = $(this).attr('id').replace('graph_', '');
|
||||
}
|
||||
|
||||
var rra_id = $(this).attr('rra_id');
|
||||
$(this).attr('rra_id');
|
||||
var type = $(this).attr('graph_type');
|
||||
|
||||
var original_cwidth = $('#wrapper_' + graph_id).attr('graph_width');
|
||||
var original_cheight = $('#wrapper_' + graph_id).attr('graph_height');
|
||||
$('#wrapper_' + graph_id).attr('graph_height');
|
||||
|
||||
/* original image attributes */
|
||||
var image_width = $(this).attr('image_width');
|
||||
@@ -2131,12 +2135,12 @@ function responsiveResizeGraphs(initialize) {
|
||||
ratio = 1;
|
||||
}
|
||||
|
||||
var new_image_width = parseInt(image_width * ratio)
|
||||
var new_image_height = parseInt(image_height * ratio)
|
||||
var new_canvas_width = parseInt(canvas_width * ratio);
|
||||
var new_canvas_height = parseInt(canvas_height * ratio);
|
||||
var new_canvas_graph_top = parseInt(canvas_top * ratio);
|
||||
var new_canvas_graph_left = parseInt(canvas_left * ratio);
|
||||
var new_image_width = Number.parseInt(image_width * ratio)
|
||||
var new_image_height = Number.parseInt(image_height * ratio)
|
||||
var new_canvas_width = Number.parseInt(canvas_width * ratio);
|
||||
var new_canvas_height = Number.parseInt(canvas_height * ratio);
|
||||
var new_canvas_graph_top = Number.parseInt(canvas_top * ratio);
|
||||
var new_canvas_graph_left = Number.parseInt(canvas_left * ratio);
|
||||
|
||||
$(this).attr('graph_width', new_canvas_width);
|
||||
$(this).attr('graph_height', new_canvas_height);
|
||||
@@ -2163,8 +2167,9 @@ function responsiveResizeGraphs(initialize) {
|
||||
}
|
||||
|
||||
function resizeTreePanel() {
|
||||
var navWidth;
|
||||
var docHeight = $(window).outerHeight();
|
||||
var navWidth = $('.cactiTreeNavigationArea').width();
|
||||
navWidth = $('.cactiTreeNavigationArea').width();
|
||||
var searchHeight = $('.cactiTreeSearch').outerHeight();
|
||||
var pageHeadHeight = $('.cactiPageHead').outerHeight();
|
||||
var breadCrHeight = $('.breadCrumbBar').outerHeight();
|
||||
@@ -2214,7 +2219,7 @@ function resizeTreePanel() {
|
||||
$('.cactiTreeNavigationArea').css('overflow-x', '');
|
||||
}
|
||||
|
||||
var navWidth = $('#navigation').width();
|
||||
navWidth = $('#navigation').width();
|
||||
$('#searcher').css('width', getTreeSearchWidth(navWidth));
|
||||
}
|
||||
|
||||
@@ -2279,10 +2284,10 @@ function tuneTable(object, width) {
|
||||
var width = width;
|
||||
var tableWidth = $(object).width();
|
||||
var totalCols = $(object).find('th').length;
|
||||
var reducedWidth = 0;
|
||||
|
||||
var columnsHidden = countHiddenCols(object);
|
||||
var visibleColumns = totalCols - columnsHidden;
|
||||
var id = $(object).attr('id');
|
||||
$(object).attr('id');
|
||||
|
||||
if (rows > 101) return false;
|
||||
|
||||
@@ -2306,7 +2311,7 @@ function tuneTable(object, width) {
|
||||
var debug = false;
|
||||
|
||||
var tableHeaders = $(object).find('th');
|
||||
var tableCheckBox = $(tableHeaders).each(function () {
|
||||
$(tableHeaders).each(function () {
|
||||
if ($(this).index() == tableHeaders.length) {
|
||||
calculatedColumns.addClass('noHide');
|
||||
}
|
||||
@@ -2343,7 +2348,7 @@ function tuneTable(object, width) {
|
||||
// and See which need to be hidden
|
||||
if (!calculatedColumns.includes($(this).index())) {
|
||||
var columnWidth = $.textMetrics(this).width + calculatedPadding;
|
||||
var name = $(this).find('div.sortinfo').attr('sort-column');
|
||||
$(this).find('div.sortinfo').attr('sort-column');
|
||||
|
||||
if (debug) {
|
||||
console.log(
|
||||
@@ -2376,7 +2381,6 @@ function tuneTable(object, width) {
|
||||
tableChanged = false;
|
||||
|
||||
if (allSeenWidth < width) {
|
||||
calculatedColumns = calculatedColumns.sort();
|
||||
|
||||
// Since we can show hidden columns now, let's go
|
||||
// in reverse until we run out of space
|
||||
@@ -2384,7 +2388,7 @@ function tuneTable(object, width) {
|
||||
if (!calculatedColumns.includes($(this).index())) {
|
||||
if ($(this).is(':hidden') && stopExpand == false) {
|
||||
var columnWidth = $.textMetrics(this).width + calculatedPadding;
|
||||
var name = $(this).find('div.sortinfo').attr('sort-column');
|
||||
$(this).find('div.sortinfo').attr('sort-column');
|
||||
|
||||
if (allSeenWidth + columnWidth < tableWidth) {
|
||||
$(this).show();
|
||||
@@ -2424,17 +2428,18 @@ function tuneTable(object, width) {
|
||||
}
|
||||
|
||||
function tuneFilter(object, width) {
|
||||
var timespan, clearWidth;
|
||||
if ($(object).find('#timespan').length && $(object).find('#timespan').is(':visible')) {
|
||||
var timespan = true;
|
||||
timespan = true;
|
||||
|
||||
var timeShiftWidth = $(object).find('.shiftArrow').closest('td').width();
|
||||
var dateWidth = $(object).find('#date1').closest('td').width() + $(object).find('#date1').closest('td').prev('td').width();
|
||||
var clearWidth = $('#tsclear').width();
|
||||
clearWidth = $('#tsclear').width();
|
||||
var refreshWidth = $('#tsrefresh').width();
|
||||
} else {
|
||||
var timespan = false;
|
||||
timespan = false;
|
||||
|
||||
var clearWidth = $(object).find('#clear').width();
|
||||
clearWidth = $(object).find('#clear').width();
|
||||
var saveWidth = $(object).find('#save').width();
|
||||
var exportWidth = $(object).find('#export').width();
|
||||
var importWidth = $(object).find('#import').width();
|
||||
@@ -2573,7 +2578,7 @@ function tuneFilter(object, width) {
|
||||
function handleUserMenu(toggle) {
|
||||
var storage = Storages.sessionStorage;
|
||||
|
||||
var windowWidth = $(window).width();
|
||||
$(window).width();
|
||||
|
||||
/* set the navigation id is not set */
|
||||
if (currentNavId == 'undefined' || currentNavId == null) {
|
||||
@@ -2610,7 +2615,7 @@ function handleUserMenu(toggle) {
|
||||
|
||||
function menuHide(store) {
|
||||
var myClass = '';
|
||||
var curMargin = parseInt($('#navigation_right').css('margin-left'));
|
||||
var curMargin = Number.parseInt($('#navigation_right').css('margin-left'));
|
||||
|
||||
if ($('.cactiTreeNavigationArea').length) {
|
||||
myClass = '.cactiTreeNavigationArea';
|
||||
@@ -2691,7 +2696,7 @@ function loadTopTab(href, id, force) {
|
||||
var storage = Storages.sessionStorage;
|
||||
|
||||
/* used for debugging */
|
||||
var stack = ''; //getStackTrace(); // new Error().stack;
|
||||
//getStackTrace(); // new Error().stack;
|
||||
var url = href;// + (href.indexOf('?') > 0 ? '&' : '?') + 'headercontent=true';
|
||||
|
||||
/* close all toasts */
|
||||
@@ -2788,8 +2793,6 @@ function userMenuNavigationExists(url) {
|
||||
|
||||
return myFound;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function loadPageUsingPost(href, postData, returnLocation) {
|
||||
@@ -2942,7 +2945,7 @@ function loadUrl(options) {
|
||||
/* get rid of old selectmenu's */
|
||||
$('.ui-selectmenu-menu').empty();
|
||||
|
||||
if (typeof options.noState == 'undefined' || options.noState == false) {
|
||||
if (options.noState === undefined || options.noState == false) {
|
||||
/* close all toasts */
|
||||
$.toast().reset('all');
|
||||
}
|
||||
@@ -3008,7 +3011,7 @@ function postUrl(options, data) {
|
||||
statePushed = false;
|
||||
cont = false;
|
||||
|
||||
if (typeof options.noState == 'undefined' || options.noState == false) {
|
||||
if (options.noState === undefined || options.noState == false) {
|
||||
/* close all toasts */
|
||||
$.toast().reset('all');
|
||||
}
|
||||
@@ -3035,7 +3038,7 @@ function findElement(htmlObject, element) {
|
||||
|
||||
if (htmlObject !== null) {
|
||||
wanted = htmlObject.find(element);
|
||||
if (typeof wanted == 'undefined' || wanted.length == 0) {
|
||||
if (wanted === undefined || wanted.length == 0) {
|
||||
wanted = htmlObject.filter(element);
|
||||
}
|
||||
}
|
||||
@@ -3060,7 +3063,7 @@ function sanitizeAjaxOptions(check) {
|
||||
redirect: '',
|
||||
};
|
||||
|
||||
if (typeof check == 'undefined') {
|
||||
if (check === undefined) {
|
||||
check = {};
|
||||
}
|
||||
|
||||
@@ -3071,11 +3074,11 @@ function sanitizeAjaxOptions(check) {
|
||||
options.noState = options.url.indexOf('nostate') > -1;
|
||||
}
|
||||
|
||||
if (typeof check.noState != 'undefined') {
|
||||
if (check.noState !== undefined) {
|
||||
options.noState = check.noState;
|
||||
}
|
||||
|
||||
if (typeof check.scroll != 'undefined') {
|
||||
if (check.scroll !== undefined) {
|
||||
options.scroll = check.scroll;
|
||||
}
|
||||
|
||||
@@ -3143,7 +3146,7 @@ function handleAjaxResponse(html, options) {
|
||||
}
|
||||
|
||||
var matches = null;
|
||||
if (typeof html.match !== 'undefined') {
|
||||
if (html.match !== undefined) {
|
||||
matches = html.match(/<title>(.*?)<\/title>/);
|
||||
}
|
||||
|
||||
@@ -3158,7 +3161,7 @@ function handleAjaxResponse(html, options) {
|
||||
myTitle = htmlTitle;
|
||||
}
|
||||
|
||||
if (typeof htmlContent == 'undefined') {
|
||||
if (htmlContent === undefined) {
|
||||
htmlContent = html;
|
||||
}
|
||||
|
||||
@@ -3172,7 +3175,7 @@ function handleAjaxResponse(html, options) {
|
||||
let confirmation = '#action_confirm';
|
||||
let htmlConfirm = findElement(htmlObject, confirmation).parent().html();
|
||||
|
||||
if (typeof htmlConfirm !== 'undefined' && typeof window['preparePopOver'] === 'function') {
|
||||
if (htmlConfirm !== undefined && typeof window['preparePopOver'] === 'function') {
|
||||
preparePopOver(htmlConfirm);
|
||||
}else {
|
||||
$(elementId).hide().empty().hide();
|
||||
@@ -3217,7 +3220,7 @@ function handleAjaxResponse(html, options) {
|
||||
}
|
||||
|
||||
if (options.funcEnd != '') {
|
||||
if (typeof window[options.funcEnd] === 'undefined') {
|
||||
if (window[options.funcEnd] === undefined) {
|
||||
console.log('WARNING: Missing function "' + options.funcEnd + '".');
|
||||
} else {
|
||||
window[options.funcEnd](options, html);
|
||||
@@ -3236,13 +3239,14 @@ function getPresentHTTPError(data) {
|
||||
}
|
||||
|
||||
function getPresentHTTPErrorOrRedirect(data, url) {
|
||||
if (typeof data.status != 'undefined') {
|
||||
var errorSub, errorText;
|
||||
if (data.status !== undefined) {
|
||||
var errorStr = data.status;
|
||||
var errorSub = data.statusText;
|
||||
var errorText = errorReasonUnexpected;
|
||||
errorSub = data.statusText;
|
||||
errorText = errorReasonUnexpected;
|
||||
var found = false;
|
||||
|
||||
if (typeof data.responseText != 'undefined') {
|
||||
if (data.responseText !== undefined) {
|
||||
var dataText = data.responseText;
|
||||
|
||||
var title_match = dataText.match(/<title>(.*?)<\/title>/);
|
||||
@@ -3250,22 +3254,22 @@ function getPresentHTTPErrorOrRedirect(data, url) {
|
||||
var para_match = dataText.match(/<p>(.*?)<\/p>/);
|
||||
|
||||
if (title_match != null) {
|
||||
var errorSub = title_match[1];
|
||||
errorSub = title_match[1];
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (head_match != null) {
|
||||
var errorSub = head_match[1];
|
||||
errorSub = head_match[1];
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (para_match != null) {
|
||||
var errorText = para_match[1];
|
||||
errorText = para_match[1];
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found && dataText != '') {
|
||||
var errorText = dataText;
|
||||
errorText = dataText;
|
||||
}
|
||||
|
||||
var returnStr = '<div id="httperror" style="display:none">' +
|
||||
@@ -3299,7 +3303,7 @@ function getPresentHTTPErrorOrRedirect(data, url) {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof url != 'undefined') {
|
||||
if (url !== undefined) {
|
||||
if (data.status >= 500) {
|
||||
// Let the HTTP Error stick log an error
|
||||
$.get(urlPath + 'help.php?page=' + encodeURIComponent(url) + '&error=' + data.status);
|
||||
@@ -3313,7 +3317,7 @@ function getPresentHTTPErrorOrRedirect(data, url) {
|
||||
}
|
||||
|
||||
function ajaxAnchors() {
|
||||
var page = basename(location.pathname);
|
||||
basename(location.pathname);
|
||||
|
||||
$(document).rebind('click.cactiPostAction', 'a.cactiPostAction', function (event) {
|
||||
if (!shouldCaptureClick(event)) {
|
||||
@@ -3389,11 +3393,11 @@ function checkFormStatus(href, type, scroll_or_id) {
|
||||
var formID = $(this).attr('id');
|
||||
var submitData = $(this).serializeForm();
|
||||
|
||||
if (typeof formArray != 'undefined' && typeof formArray[formID] != 'undefined') {
|
||||
if (typeof formArray != 'undefined' && formArray[formID] !== undefined) {
|
||||
var formData = formArray[formID];
|
||||
|
||||
$.each(submitData, function (index, value) {
|
||||
if (typeof formData[index] != 'undefined') {
|
||||
if (formData[index] !== undefined) {
|
||||
if (formData[index] != value) {
|
||||
if (index == 'settings_sendmail_path' || index == 'rrd_archive' || index == '__csrf_magicSubmit' || index == '__csrf_magic' || index == 'settings_smtp_password' || index == 'settings_smtp_password_confirm') {
|
||||
// Ignore this entry
|
||||
@@ -3424,11 +3428,12 @@ function setupCollapsible() {
|
||||
var storage = Storages.sessionStorage;
|
||||
|
||||
$('.collapsible').each(function (data) {
|
||||
var state;
|
||||
var id = $(this).attr('id') + '_cs';
|
||||
if (storage.isSet(id)) {
|
||||
var state = storage.get(id);
|
||||
state = storage.get(id);
|
||||
} else {
|
||||
var state = 'show';
|
||||
state = 'show';
|
||||
}
|
||||
|
||||
if (state == 'hide') {
|
||||
@@ -3541,7 +3546,7 @@ function setupSortable() {
|
||||
|
||||
var $target = $(e.target);
|
||||
var sortAdd = '';
|
||||
var href = '';
|
||||
|
||||
|
||||
if (!$target.is('.ui-resizable-handle')) {
|
||||
var page = $(this).find('.sortinfo').attr('sort-page');
|
||||
@@ -3598,10 +3603,11 @@ function setupBreadcrumbs() {
|
||||
function saveTableWidths(initial) {
|
||||
// We will save columns widths persistently
|
||||
var storage = Storages.localStorage;
|
||||
var key;
|
||||
|
||||
|
||||
// Initialize table width on the page
|
||||
$('table.cactiTable').each(function (data) {
|
||||
var sizes, items;
|
||||
var table = $(this);
|
||||
|
||||
// Persist widths under the action-independent data-colsizing key when it
|
||||
@@ -3615,27 +3621,27 @@ function saveTableWidths(initial) {
|
||||
}
|
||||
|
||||
if (storage.isSet(key)) {
|
||||
var sizes = storage.get(key);
|
||||
sizes = storage.get(key);
|
||||
} else {
|
||||
var sizes = new Array();
|
||||
sizes = new Array();
|
||||
}
|
||||
|
||||
var items = sizes ? sizes : new Array();
|
||||
items = sizes ? sizes : new Array();
|
||||
var width = $(document).width();
|
||||
|
||||
// if the table width changes, reset the columns
|
||||
if (key !== undefined && sizes == undefined) {
|
||||
storage.remove(key);
|
||||
|
||||
var sizes = new Array();
|
||||
var items = new Array();
|
||||
sizes = new Array();
|
||||
items = new Array();
|
||||
} else if (key !== undefined && initial) {
|
||||
if (items.length > 0) {
|
||||
if (items[0] + 18 < width) {
|
||||
storage.remove(key);
|
||||
|
||||
var sizes = new Array();
|
||||
var items = new Array();
|
||||
sizes = new Array();
|
||||
items = new Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3912,7 +3918,7 @@ function setSelectMenus() {
|
||||
that._renderItemData( ul, item );
|
||||
});
|
||||
|
||||
if (typeof(attr['data-defaultLabel']) !== 'undefined') {
|
||||
if (attr['data-defaultLabel'] !== undefined) {
|
||||
if(this.menuWrap.find('input').length === 0) {
|
||||
this.menuWrap.prepend('<div class="ui-selectmenu-search"><input type="search" class="ui-state-default ui-corner-all" data-scope="theme" placeholder="' + searchPlaceholder + '"></div>');
|
||||
}
|
||||
@@ -3957,17 +3963,17 @@ function setSelectMenus() {
|
||||
}
|
||||
},
|
||||
_renderButtonItem: function(item) {
|
||||
let that = this;
|
||||
|
||||
let attr = this.element[0].attributes;
|
||||
let showDefaultLabel = select2Setup["displayDefaultLabel"];
|
||||
|
||||
if (typeof(attr['data-defaultLabel']) !== 'undefined') {
|
||||
if (attr['data-defaultLabel'] !== undefined) {
|
||||
let defaultLabel = attr['data-defaultLabel'].value;
|
||||
let filterActive = '';
|
||||
let defaultIndex = 0;
|
||||
let defaultValue = this.element.find("option").eq(0).val();
|
||||
|
||||
if (typeof(attr['data-defaultValue']) !== 'undefined') {
|
||||
if (attr['data-defaultValue'] !== undefined) {
|
||||
let defaultValue = attr['data-defaultValue'].value;
|
||||
}
|
||||
|
||||
@@ -4019,6 +4025,7 @@ function setSelectMenus() {
|
||||
|
||||
$.widget('custom.dropicon', $.ui.selectmenu, {
|
||||
_renderItem: function( ul, item ) {
|
||||
var style;
|
||||
var li = $('<li>');
|
||||
var wrapper = $('<div>', {text: item.label});
|
||||
|
||||
@@ -4027,9 +4034,9 @@ function setSelectMenus() {
|
||||
}
|
||||
|
||||
if (item.element.attr('data-style') != '') {
|
||||
var style = item.element.attr('data-style')+';background:transparent;min-width:20px;';
|
||||
style = item.element.attr('data-style')+';background:transparent;min-width:20px;';
|
||||
} else {
|
||||
var style = 'background:transparent;min-width:20px;';
|
||||
style = 'background:transparent;min-width:20px;';
|
||||
}
|
||||
|
||||
var iclass = item.element.attr('data-class');
|
||||
@@ -4273,10 +4280,10 @@ function setupEllipsis() {
|
||||
/* re-position */
|
||||
var position = $(this).position();
|
||||
|
||||
if (position.left - parseInt(submenu.outerWidth()) < 0) {
|
||||
if (position.left - Number.parseInt(submenu.outerWidth()) < 0) {
|
||||
submenu.css({ 'left': 0 }).slideDown(120);
|
||||
} else {
|
||||
submenu.css({ 'left': position.left - parseInt(submenu.outerWidth()) + parseInt($(this).outerWidth()) }).slideDown(120);
|
||||
submenu.css({ 'left': position.left - Number.parseInt(submenu.outerWidth()) + Number.parseInt($(this).outerWidth()) }).slideDown(120);
|
||||
}
|
||||
} else {
|
||||
submenu.slideUp(120);
|
||||
@@ -4308,6 +4315,7 @@ function setupEllipsis() {
|
||||
function keepWindowSize() {
|
||||
$(window).on('resize', function (event) {
|
||||
waitForFinalEvent(function () {
|
||||
var graphTabWidth, userTabs, items, done;
|
||||
$('.cactiGraphContentArea').show();
|
||||
|
||||
var resizeTime = new Date();
|
||||
@@ -4355,15 +4363,15 @@ function keepWindowSize() {
|
||||
$('.dropdownMenu > ul').hide();
|
||||
|
||||
if ($('#gtabs > .tabs').is(':visible')) {
|
||||
var graphTabWidth = $('#gtabs > .tabs').outerWidth();
|
||||
graphTabWidth = $('#gtabs > .tabs').outerWidth();
|
||||
} else {
|
||||
var graphTabWidth = 0;
|
||||
graphTabWidth = 0;
|
||||
}
|
||||
|
||||
if ($('.usertabs').length) {
|
||||
var userTabs = $('.usertabs').outerWidth();
|
||||
userTabs = $('.usertabs').outerWidth();
|
||||
} else {
|
||||
var userTabs = 0;
|
||||
userTabs = 0;
|
||||
}
|
||||
|
||||
var bodyWidth = $('body').width();
|
||||
@@ -4372,7 +4380,7 @@ function keepWindowSize() {
|
||||
otherWidth += $(this).outerWidth();
|
||||
});
|
||||
|
||||
var ellipsisWidth = $('.maintabs-submenu-ellipsis').outerWidth();
|
||||
$('.maintabs-submenu-ellipsis').outerWidth();
|
||||
var tabHeight = $('#tabs').outerHeight();
|
||||
var mainTabPos = false;
|
||||
|
||||
@@ -4390,8 +4398,8 @@ function keepWindowSize() {
|
||||
|
||||
pageWidth = bodyWidth;
|
||||
|
||||
var items = $($('.maintabs nav ul li a.lefttab').get());
|
||||
var done = false;
|
||||
items = $($('.maintabs nav ul li a.lefttab').get());
|
||||
done = false;
|
||||
items.each(function () {
|
||||
var id = $(this).attr('id');
|
||||
|
||||
@@ -4399,8 +4407,8 @@ function keepWindowSize() {
|
||||
});
|
||||
|
||||
// Hide top menus if you have to
|
||||
var items = $($('.maintabs nav ul li a.lefttab').get().reverse());
|
||||
var done = false;
|
||||
items = $($('.maintabs nav ul li a.lefttab').get().reverse());
|
||||
done = false;
|
||||
items.each(function () {
|
||||
var id = $(this).attr('id');
|
||||
|
||||
@@ -4447,15 +4455,16 @@ function showCurrentTab(id) {
|
||||
}
|
||||
|
||||
function tabsWrapping() {
|
||||
var mainTabHeight, userTabPos, gtabsWidth, utabsWidth;
|
||||
var mainTabPos = $('.maintabs:first').position();
|
||||
var tabHeight = $('#tabs').height();
|
||||
|
||||
if ($('.usertabs').length) {
|
||||
var mainTabHeight = tabHeight;
|
||||
var userTabPos = $('.usertabs').position();
|
||||
mainTabHeight = tabHeight;
|
||||
userTabPos = $('.usertabs').position();
|
||||
} else {
|
||||
var mainTabHeight = $('.maintabs:first nav').height();
|
||||
var userTabPos = mainTabPos;
|
||||
mainTabHeight = $('.maintabs:first nav').height();
|
||||
userTabPos = mainTabPos;
|
||||
}
|
||||
|
||||
var bodyWidth = $('body').width();
|
||||
@@ -4468,15 +4477,15 @@ function tabsWrapping() {
|
||||
var mtabsWidth = $('.maintabs:not(.usertabs)').outerWidth();
|
||||
|
||||
if ($('#gtabs>.tabs').length) {
|
||||
var gtabsWidth = $('#gtabs>.tabs').outerWidth();
|
||||
gtabsWidth = $('#gtabs>.tabs').outerWidth();
|
||||
} else {
|
||||
var gtabsWidth = 0;
|
||||
gtabsWidth = 0;
|
||||
}
|
||||
|
||||
if ($('.usertabs').length) {
|
||||
var utabsWidth = $('.usertabs').outerWidth();
|
||||
utabsWidth = $('.usertabs').outerWidth();
|
||||
} else {
|
||||
var utabsWidth = 0;
|
||||
utabsWidth = 0;
|
||||
}
|
||||
|
||||
if (gtabsWidth + mtabsWidth + utabsWidth + otherWidth + ellipsisWidth > bodyWidth - 20) {
|
||||
@@ -4521,7 +4530,7 @@ function setCactiTabCookie() {
|
||||
}
|
||||
|
||||
function checkForRedirects(data, href) {
|
||||
if (typeof data == 'undefined') {
|
||||
if (data === undefined) {
|
||||
return true;
|
||||
} else if (typeof data == 'object') {
|
||||
return true;
|
||||
@@ -4535,7 +4544,7 @@ function checkForRedirects(data, href) {
|
||||
$.ajaxQ.abortAll();
|
||||
document.location = urlPath + 'permission_denied.php';
|
||||
} else if (data.indexOf('cactiRedirect') >= 0) {
|
||||
if (typeof href == 'undefined' || href == null) {
|
||||
if (href === undefined || href == null) {
|
||||
$.ajaxQ.abortAll();
|
||||
location.reload();
|
||||
} else {
|
||||
@@ -4590,13 +4599,13 @@ function finalizeGraphFilter(options, data) {
|
||||
function applyGraphFilter() {
|
||||
var href = correctUrlParameters(graphPage + '?action=' + pageAction +
|
||||
'&rfilter=' + base64_encode($('#rfilter').val()) +
|
||||
(typeof $('#site_id').val() != 'undefined' ? '&site_id=' + $('#site_id').val() : '') +
|
||||
(typeof $('#location').val() != 'undefined' ? '&location=' + $('#location').val() : '') +
|
||||
(typeof $('#host_id').val() != 'undefined' ? '&host_id=' + $('#host_id').val() : '') +
|
||||
(typeof $('#graph_source').val() != 'undefined' ? '&graph_source=' + $('#graph_source').val() : '') +
|
||||
(typeof $('#graph_order').val() != 'undefined' ? '&graph_order=' + $('#graph_order').val() : '') +
|
||||
(typeof $('#cf').val() != 'undefined' ? '&cf=' + $('#cf').val() : '') +
|
||||
(typeof $('#measure').val() != 'undefined' ? '&measure=' + $('#measure').val() : '') +
|
||||
($('#site_id').val() !== undefined ? '&site_id=' + $('#site_id').val() : '') +
|
||||
($('#location').val() !== undefined ? '&location=' + $('#location').val() : '') +
|
||||
($('#host_id').val() !== undefined ? '&host_id=' + $('#host_id').val() : '') +
|
||||
($('#graph_source').val() !== undefined ? '&graph_source=' + $('#graph_source').val() : '') +
|
||||
($('#graph_order').val() !== undefined ? '&graph_order=' + $('#graph_order').val() : '') +
|
||||
($('#cf').val() !== undefined ? '&cf=' + $('#cf').val() : '') +
|
||||
($('#measure').val() !== undefined ? '&measure=' + $('#measure').val() : '') +
|
||||
'&columns=' + $('#columns').val() +
|
||||
'&graphs=' + $('#graphs').val() +
|
||||
'&graph_template_id=' + $('#graph_template_id').val() +
|
||||
@@ -4618,7 +4627,7 @@ function pushState(myTitle, options) {
|
||||
options = sanitizeAjaxOptions(options);
|
||||
if (!options.noState) {
|
||||
if (statePushed == false) {
|
||||
if (typeof window.history.pushState != 'undefined') {
|
||||
if (window.history.pushState !== undefined) {
|
||||
var myObject = { Page: myTitle, Url: cleanUrlParameters(options.url), Options: Object.assign({}, options) };
|
||||
window.history.pushState(myObject, myObject.Page, myObject.Url);
|
||||
}
|
||||
@@ -4630,11 +4639,11 @@ function pushState(myTitle, options) {
|
||||
function handlePopState(e) {
|
||||
var href = document.location.href;
|
||||
|
||||
if (typeof e !== 'undefined' && e.state != 'undefined' && e.state != null) {
|
||||
if (typeof e.state.Options != 'undefined' && e.state.Options != null) {
|
||||
if (e !== undefined && e.state != 'undefined' && e.state != null) {
|
||||
if (e.state.Options !== undefined && e.state.Options != null) {
|
||||
loadUrl(e.state.Options);
|
||||
return false;
|
||||
} else if (typeof e.state.Url != 'undefined' && e.state.Url != null) {
|
||||
} else if (e.state.Url !== undefined && e.state.Url != null) {
|
||||
loadUrl({ url: href });
|
||||
return false;
|
||||
}
|
||||
@@ -4647,13 +4656,13 @@ function applyGraphTimespan() {
|
||||
($('#rfilter').length ? '&rfilter=' + base64_encode($('#rfilter').val()) : '') +
|
||||
'&predefined_timespan=' + $('#predefined_timespan').val() +
|
||||
'&predefined_timeshift=' + $('#predefined_timeshift').val() +
|
||||
(typeof $('#site_id').val() != 'undefined' ? '&site_id=' + $('#site_id').val() : '') +
|
||||
(typeof $('#location').val() != 'undefined' ? '&location=' + $('#location').val() : '') +
|
||||
(typeof $('#host_id').val() != 'undefined' ? '&host_id=' + $('#host_id').val() : '') +
|
||||
(typeof $('#graph_source').val() != 'undefined' ? '&graph_source=' + $('#graph_source').val() : '') +
|
||||
(typeof $('#graph_order').val() != 'undefined' ? '&graph_order=' + $('#graph_order').val() : '') +
|
||||
(typeof $('#cf').val() != 'undefined' ? '&cf=' + $('#cf').val() : '') +
|
||||
(typeof $('#measure').val() != 'undefined' ? '&measure=' + $('#measure').val() : '') +
|
||||
($('#site_id').val() !== undefined ? '&site_id=' + $('#site_id').val() : '') +
|
||||
($('#location').val() !== undefined ? '&location=' + $('#location').val() : '') +
|
||||
($('#host_id').val() !== undefined ? '&host_id=' + $('#host_id').val() : '') +
|
||||
($('#graph_source').val() !== undefined ? '&graph_source=' + $('#graph_source').val() : '') +
|
||||
($('#graph_order').val() !== undefined ? '&graph_order=' + $('#graph_order').val() : '') +
|
||||
($('#cf').val() !== undefined ? '&cf=' + $('#cf').val() : '') +
|
||||
($('#measure').val() !== undefined ? '&measure=' + $('#measure').val() : '') +
|
||||
'&columns=' + $('#columns').val() +
|
||||
'&graphs=' + $('#graphs').val() +
|
||||
'&graph_template_id=' + $('#graph_template_id').val() +
|
||||
@@ -4795,15 +4804,15 @@ function redrawGraph(graph_id) {
|
||||
'&business_hours=' + (isBusiness ? 'true' : 'false') +
|
||||
|
||||
$.getJSON(href, function(data) {
|
||||
if (typeof data.status == 'undefined') {
|
||||
if (data.status === undefined) {
|
||||
if (myWidth < data.image_width) {
|
||||
ratio = myWidth / data.image_width;
|
||||
data.image_width = parseInt(data.image_width * ratio);
|
||||
data.image_height = parseInt(data.image_height * ratio);
|
||||
data.graph_width = parseInt(data.graph_width * ratio);
|
||||
data.graph_height = parseInt(data.graph_height * ratio);
|
||||
data.graph_top = parseInt(data.graph_top * ratio);
|
||||
data.graph_left = parseInt(data.graph_left * ratio);
|
||||
data.image_width = Number.parseInt(data.image_width * ratio);
|
||||
data.image_height = Number.parseInt(data.image_height * ratio);
|
||||
data.graph_width = Number.parseInt(data.graph_width * ratio);
|
||||
data.graph_height = Number.parseInt(data.graph_height * ratio);
|
||||
data.graph_top = Number.parseInt(data.graph_top * ratio);
|
||||
data.graph_left = Number.parseInt(data.graph_left * ratio);
|
||||
}
|
||||
|
||||
$('#wrapper_' + data.local_graph_id).empty().html(
|
||||
@@ -4916,7 +4925,7 @@ function initGraphDrilldown() {
|
||||
}
|
||||
|
||||
function initializeGraphs(disable_cache) {
|
||||
disable_cache = (typeof disable_cache == 'undefined') ? false : true;
|
||||
disable_cache = (disable_cache === undefined) ? false : true;
|
||||
|
||||
$.ajaxQ.abortAll();
|
||||
|
||||
@@ -5044,12 +5053,12 @@ function initializeGraphs(disable_cache) {
|
||||
if (myWidth < data.image_width) {
|
||||
ratio = myWidth / data.image_width;
|
||||
|
||||
data.image_width = parseInt(data.image_width * ratio);
|
||||
data.image_height = parseInt(data.image_height * ratio);
|
||||
data.graph_width = parseInt(data.graph_width * ratio);
|
||||
data.graph_height = parseInt(data.graph_height * ratio);
|
||||
data.graph_top = parseInt(data.graph_top * ratio);
|
||||
data.graph_left = parseInt(data.graph_left * ratio);
|
||||
data.image_width = Number.parseInt(data.image_width * ratio);
|
||||
data.image_height = Number.parseInt(data.image_height * ratio);
|
||||
data.graph_width = Number.parseInt(data.graph_width * ratio);
|
||||
data.graph_height = Number.parseInt(data.graph_height * ratio);
|
||||
data.graph_top = Number.parseInt(data.graph_top * ratio);
|
||||
data.graph_left = Number.parseInt(data.graph_left * ratio);
|
||||
}
|
||||
|
||||
var wrapper_id = '#wrapper_' + data.local_graph_id;
|
||||
@@ -5417,7 +5426,7 @@ $.widget('custom.dropcolor', {
|
||||
_select: function (event, ui) {
|
||||
var regExp = /\(([^)]+)\)/;
|
||||
var hex = regExp.exec(ui.item.label);
|
||||
var id = $(ui.item.option).attr('value');
|
||||
$(ui.item.option).attr('value');
|
||||
|
||||
if (hex !== null) {
|
||||
color = hex[1];
|
||||
@@ -5512,7 +5521,7 @@ function expandClipboardSection(section) {
|
||||
section.slideDown('fast');
|
||||
}
|
||||
|
||||
var children = section.find('table').each(function (i) {
|
||||
section.find('table').each(function (i) {
|
||||
expandClipboardSection($(this));
|
||||
});
|
||||
}
|
||||
@@ -5821,16 +5830,17 @@ function setSNMP() {
|
||||
}
|
||||
|
||||
function checkSNMPPassphrase(type) {
|
||||
var pass, conf, span;
|
||||
var minChars = 8;
|
||||
|
||||
if (type == 'priv') {
|
||||
var pass = '#snmp_priv_passphrase';
|
||||
var conf = '#snmp_priv_passphrase_confirm';
|
||||
var span = 'priv';
|
||||
pass = '#snmp_priv_passphrase';
|
||||
conf = '#snmp_priv_passphrase_confirm';
|
||||
span = 'priv';
|
||||
} else {
|
||||
var pass = '#snmp_password';
|
||||
var conf = '#snmp_password_confirm';
|
||||
var span = 'auth';
|
||||
pass = '#snmp_password';
|
||||
conf = '#snmp_password_confirm';
|
||||
span = 'auth';
|
||||
}
|
||||
|
||||
if ($(pass).val().length == 0) {
|
||||
@@ -5848,18 +5858,19 @@ function checkSNMPPassphrase(type) {
|
||||
}
|
||||
|
||||
function checkSNMPPassphraseConfirm(type) {
|
||||
var pass, conf, span, spanconf;
|
||||
var minChars = 8;
|
||||
|
||||
if (type == 'priv') {
|
||||
var pass = '#snmp_priv_passphrase';
|
||||
var conf = '#snmp_priv_passphrase_confirm';
|
||||
var span = 'priv';
|
||||
var spanconf = 'privconf';
|
||||
pass = '#snmp_priv_passphrase';
|
||||
conf = '#snmp_priv_passphrase_confirm';
|
||||
span = 'priv';
|
||||
spanconf = 'privconf';
|
||||
} else {
|
||||
var pass = '#snmp_password';
|
||||
var conf = '#snmp_password_confirm';
|
||||
var span = 'auth';
|
||||
var spanconf = 'authconf';
|
||||
pass = '#snmp_password';
|
||||
conf = '#snmp_password_confirm';
|
||||
span = 'auth';
|
||||
spanconf = 'authconf';
|
||||
}
|
||||
|
||||
if ($(conf).val().length < minChars) {
|
||||
@@ -5897,7 +5908,7 @@ const streamAvailabilityToggleOptions = ['0', '1', '2', '3', '4', '5', '6'];
|
||||
const streamSNMPToggleOptions = ['1', '2', '3'];
|
||||
|
||||
function setAvailability() {
|
||||
var hasChanged = false;
|
||||
|
||||
|
||||
if ($('#availability_method').val() != '7') {
|
||||
if ($('#snmp_version').val() == '0') {
|
||||
@@ -6020,7 +6031,7 @@ function formValidate(formId, href) {
|
||||
}
|
||||
|
||||
if (name !== null && name.length > 0) {
|
||||
if (typeof formRules[formId] !== 'undefined') {
|
||||
if (formRules[formId] !== undefined) {
|
||||
formRules[formId][name] = {
|
||||
required: true,
|
||||
email: true,
|
||||
@@ -6080,7 +6091,7 @@ function toggleFields(fields, prefix = '#row_') {
|
||||
Object.keys(fields).forEach(index => {
|
||||
curParent = $(prefix + index).parent().attr('id');
|
||||
|
||||
if (typeof curParent != 'undefined' && curParent != lastParent) {
|
||||
if (curParent !== undefined && curParent != lastParent) {
|
||||
parents.push(curParent);
|
||||
}
|
||||
|
||||
@@ -6092,7 +6103,7 @@ function toggleFields(fields, prefix = '#row_') {
|
||||
$(prefix + index).hide();
|
||||
}
|
||||
|
||||
if (typeof curParent != 'undefined') {
|
||||
if (curParent !== undefined) {
|
||||
lastParent = curParent;
|
||||
}
|
||||
});
|
||||
|
||||
+13
-12
@@ -38,16 +38,17 @@ var url;
|
||||
var local_graph_id = null;
|
||||
|
||||
function realtimeDetectBrowser() {
|
||||
var browser;
|
||||
if (navigator.userAgent.indexOf('MSIE') >= 0) {
|
||||
var browser = 'IE';
|
||||
browser = 'IE';
|
||||
} else if (navigator.userAgent.indexOf('Chrome') >= 0) {
|
||||
var browser = 'Chrome';
|
||||
browser = 'Chrome';
|
||||
} else if (navigator.userAgent.indexOf('Mozilla') >= 0) {
|
||||
var browser = 'FF';
|
||||
browser = 'FF';
|
||||
} else if (navigator.userAgent.indexOf('Opera') >= 0) {
|
||||
var browser = 'Opera';
|
||||
browser = 'Opera';
|
||||
} else {
|
||||
var browser = 'Other';
|
||||
browser = 'Other';
|
||||
}
|
||||
|
||||
return browser;
|
||||
@@ -55,7 +56,7 @@ function realtimeDetectBrowser() {
|
||||
|
||||
function imageOptionsChanged(action) {
|
||||
const graph_start = $('#graph_start').val();
|
||||
var graph_end = 0;
|
||||
|
||||
const ds_step = $('#ds_step').val();
|
||||
var size = $('#size').val();
|
||||
const isThumb = $('#thumbnails').is(':checked');
|
||||
@@ -78,12 +79,12 @@ function imageOptionsChanged(action) {
|
||||
if (action === 'countdown') {
|
||||
url = `graph_realtime.php?action=countdown&top=0&left=0&local_graph_id=${local_graph_id}&ds_step=${ds_step}&count=${count}&size=${size}&graph_nolegend=${isThumb}`;
|
||||
} else if (action === 'initial') {
|
||||
url = `graph_realtime.php?action=initial&top=0&left=0&local_graph_id=${local_graph_id}&graph_start=-${parseInt(graph_start) > 0 ? graph_start:'60'}&ds_step=${ds_step}&count=${count}&size=${size}`;
|
||||
url = `graph_realtime.php?action=initial&top=0&left=0&local_graph_id=${local_graph_id}&graph_start=-${Number.parseInt(graph_start) > 0 ? graph_start:'60'}&ds_step=${ds_step}&count=${count}&size=${size}`;
|
||||
} else {
|
||||
url = `graph_realtime.php?action=${action}&top=0&left=0&local_graph_id=${local_graph_id}&graph_start=-${parseInt(graph_start) > 0 ? graph_start:'60'}&ds_step=${ds_step}&count=${count}&size=${size}&graph_nolegend=${isThumb}`;
|
||||
url = `graph_realtime.php?action=${action}&top=0&left=0&local_graph_id=${local_graph_id}&graph_start=-${Number.parseInt(graph_start) > 0 ? graph_start:'60'}&ds_step=${ds_step}&count=${count}&size=${size}&graph_nolegend=${isThumb}`;
|
||||
}
|
||||
|
||||
Pace.stop;
|
||||
Pace.stop();
|
||||
|
||||
$.getJSON(url)
|
||||
.done(function(data) {
|
||||
@@ -170,7 +171,7 @@ function countRealtimeGraphs() {
|
||||
}
|
||||
|
||||
function stopRealtime() {
|
||||
var graph;
|
||||
|
||||
|
||||
for (key in realtimeArray) {
|
||||
var graph_id = key;
|
||||
@@ -239,7 +240,7 @@ function realtimeGrapher() {
|
||||
}
|
||||
|
||||
const graph_start = $('#graph_start').val();
|
||||
var graph_end = 0;
|
||||
|
||||
const ds_step = $('#ds_step').val();
|
||||
var size = $('#size').val();
|
||||
const isThumb = $('#thumbnails').is(':checked');
|
||||
@@ -276,7 +277,7 @@ function realtimeGrapher() {
|
||||
position = $('body').position();
|
||||
}
|
||||
|
||||
$.get(`${urlPath}graph_realtime.php?action=countdown&top=${parseInt(position.top)}&left=${parseInt(position.left)}${isThumb ? '&graph_nolegend=true':'&graph_nolegend=false'}&graph_end=0&graph_start=-${parseInt(graph_start) > 0 ? graph_start:'60'}&local_graph_id=${local_graph_id}&ds_step=${ds_step}&count=${count}&size=${size}`)
|
||||
$.get(`${urlPath}graph_realtime.php?action=countdown&top=${Number.parseInt(position.top)}&left=${Number.parseInt(position.left)}${isThumb ? '&graph_nolegend=true':'&graph_nolegend=false'}&graph_end=0&graph_start=-${Number.parseInt(graph_start) > 0 ? graph_start:'60'}&local_graph_id=${local_graph_id}&ds_step=${ds_step}&count=${count}&size=${size}`)
|
||||
.done(function(data) {
|
||||
var results = (typeof data === 'string') ? JSON.parse(data) : data;
|
||||
|
||||
|
||||
@@ -134,12 +134,12 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
$('#navigation').hide();
|
||||
$('li.menuitem').each(function() {
|
||||
active = storage.get($(this).attr('id'));
|
||||
const active = storage.get($(this).attr('id'));
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
$(this).next('a').show();
|
||||
@@ -155,7 +155,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')){
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -172,8 +172,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -134,12 +134,12 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
$('#navigation').hide();
|
||||
$('li.menuitem').each(function() {
|
||||
active = storage.get($(this).attr('id'));
|
||||
const active = storage.get($(this).attr('id'));
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
$(this).next('a').show();
|
||||
@@ -155,7 +155,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')){
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -172,8 +172,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -96,18 +96,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -132,7 +128,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -149,8 +145,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -135,18 +135,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -172,7 +168,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -189,8 +185,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -134,12 +134,12 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
$('#navigation').hide();
|
||||
$('li.menuitem').each(function() {
|
||||
active = storage.get($(this).attr('id'));
|
||||
const active = storage.get($(this).attr('id'));
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
$(this).next('a').show();
|
||||
@@ -155,7 +155,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')){
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -172,8 +172,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -456,7 +456,7 @@ function setupTheme() {
|
||||
});
|
||||
} else {
|
||||
$("#navBackdrop").on('click', function() {
|
||||
window.open('https://cacti.net', '_blank');
|
||||
window.open('https://cacti.net', '_blank', 'noopener,noreferrer');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -597,7 +597,7 @@ function toggleCactiNavigationBoxPin(event) {
|
||||
let caller = $(event.currentTarget);
|
||||
let helper = caller.attr('data-helper');
|
||||
let navigationBox = $('[class^="mdw-ConsoleNavigationBox"][data-helper="' + helper + '"]');
|
||||
let compact_nav_icon = $('[class^="compact_nav_icon"][data-helper="' + helper + '"]');
|
||||
$('[class^="compact_nav_icon"][data-helper="' + helper + '"]');
|
||||
|
||||
if(event.data && event.data.dock) {
|
||||
event.data.dock = event.data.dock.replace(/^./, str => str.toUpperCase());
|
||||
@@ -670,7 +670,7 @@ function hideDropDownMenu() {
|
||||
function toggleTableColumn(event) {
|
||||
let storage = Storages.localStorage;
|
||||
let tableHash = event.target.dataset.table;
|
||||
let cIndex = parseInt(event.target.dataset.column);
|
||||
let cIndex = Number.parseInt(event.target.dataset.column);
|
||||
let cClass = 'no-col'+cIndex;
|
||||
let storage_table_headers = storage.get('midWinter_' + tableHash);
|
||||
|
||||
@@ -914,7 +914,7 @@ function changeGuiFontSize(change=true) {
|
||||
setDocumentAttribute('zoom-level', mdw.session.theme.font.zoom);
|
||||
}
|
||||
/* update output field beside input selector */
|
||||
$('#mdw_themeFontSizeValue').val((parseFloat(mdw.session.theme.font.zoom) + 25).toFixed(1) + ' %');
|
||||
$('#mdw_themeFontSizeValue').val((Number.parseFloat(mdw.session.theme.font.zoom) + 25).toFixed(1) + ' %');
|
||||
}
|
||||
|
||||
function toggleGuiAnimations() {
|
||||
@@ -1022,9 +1022,9 @@ function togglePopOver(force) {
|
||||
|
||||
function fullScreen(event) {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen().then( r => fullScreenChangeHandler() );
|
||||
document.documentElement.requestFullscreen().then(() => fullScreenChangeHandler()).catch(() => fullScreenChangeHandler());
|
||||
}else if (document.exitFullscreen) {
|
||||
document.exitFullscreen().then( r => fullScreenChangeHandler() );
|
||||
document.exitFullscreen().then(() => fullScreenChangeHandler()).catch(() => fullScreenChangeHandler());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,7 +1328,7 @@ registry.midwinter = {
|
||||
let midWinter_Color_Mode_Auto = mdw.session.theme.color.auto;
|
||||
let midWinter_Font_Size = mdw.session.theme.font.zoom;
|
||||
let midWinter_Animations = mdw.session.theme.boxes.animated
|
||||
let midWinter_ShownFontSizeValue = parseFloat(midWinter_Font_Size) + 25;
|
||||
let midWinter_ShownFontSizeValue = Number.parseFloat(midWinter_Font_Size) + 25;
|
||||
let midWinter_Auto_Table_Layout = mdw.session.theme.mobile.autoTableLayout;
|
||||
let midWinter_Controls_SubTitle = mdw.session.theme.controls.subTitle;
|
||||
|
||||
|
||||
@@ -88,18 +88,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -125,7 +121,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -142,8 +138,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -153,18 +153,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -190,7 +186,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -207,8 +203,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -135,18 +135,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -172,7 +168,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -189,8 +185,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -134,12 +134,12 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
$('#navigation').hide();
|
||||
$('li.menuitem').each(function() {
|
||||
active = storage.get($(this).attr('id'));
|
||||
const active = storage.get($(this).attr('id'));
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
$(this).next('a').show();
|
||||
@@ -155,7 +155,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')){
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -172,8 +172,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
@@ -28,7 +28,7 @@ function themeReady() {
|
||||
$('#navigation_right').rebind('scroll', function (event) {
|
||||
var scroll_position_x = $('#navigation_right').scrollLeft();
|
||||
var scroll_position_y = $('#navigation_right').scrollTop();
|
||||
$('.bottom_scroll_up').css({'color': ((scroll_position_x == 0 & scroll_position_y == 0) ? '' : '#93CEFF') });
|
||||
$('.bottom_scroll_up').css({'color': ((scroll_position_x === 0 && scroll_position_y === 0) ? '' : '#93CEFF') });
|
||||
});
|
||||
|
||||
// Add nice search filter to filters
|
||||
@@ -158,18 +158,14 @@ function themeReady() {
|
||||
}
|
||||
|
||||
function setMenuVisibility() {
|
||||
storage=Storages.sessionStorage;
|
||||
const storage = Storages.sessionStorage;
|
||||
|
||||
// Initialize the navigation settings
|
||||
// This will setup the initial visibility of the menu
|
||||
$('li.menuitem').each(function() {
|
||||
var id = $(this).attr('id');
|
||||
const id = $(this).attr('id');
|
||||
|
||||
if (storage.isSet(id)) {
|
||||
var active = storage.get(id);
|
||||
} else {
|
||||
var active = null;
|
||||
}
|
||||
const active = storage.isSet(id) ? storage.get(id) : null;
|
||||
|
||||
if (active != null && active == 'active') {
|
||||
$(this).find('ul').attr('aria-hidden', 'false').attr('aria-expanded', 'true').show();
|
||||
@@ -195,7 +191,7 @@ function setMenuVisibility() {
|
||||
$('#nav li:has(ul) a.active').rebind('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
id = $(this).closest('.menuitem').attr('id');
|
||||
const id = $(this).closest('.menuitem').attr('id');
|
||||
|
||||
if ($(this).next().is(':visible')) {
|
||||
$(this).next('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
@@ -212,8 +208,6 @@ function setMenuVisibility() {
|
||||
}
|
||||
|
||||
$('li.menuitem').not('#'+id).each(function() {
|
||||
text = $(this).attr('id');
|
||||
id = $(this).attr('id');
|
||||
|
||||
$(this).find('ul').attr('aria-hidden', 'true').attr('aria-expanded', 'false');
|
||||
$(this).find('ul').slideUp( { duration: 200, easing: 'swing' } );
|
||||
|
||||
+8
-8
@@ -127,7 +127,7 @@ function setButtonData(buttonName, buttonData) {
|
||||
button.button();
|
||||
button.data('buttonData', buttonData);
|
||||
if (buttonData != null) {
|
||||
var buttonCheck = button.data('buttonData');
|
||||
button.data('buttonData');
|
||||
if (buttonData.Enabled) {
|
||||
button.button('enable');
|
||||
} else {
|
||||
@@ -231,7 +231,7 @@ function getDefaultInstallData() {
|
||||
}
|
||||
|
||||
function toggleHeader(key, initial) {
|
||||
if (typeof initial === 'undefined') {
|
||||
if (initial === undefined) {
|
||||
initial = null;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ function toggleHeader(key, initial) {
|
||||
}
|
||||
|
||||
function toggleSection(key, initial) {
|
||||
if (typeof initial === 'undefined') {
|
||||
if (initial === undefined) {
|
||||
initial = null;
|
||||
}
|
||||
|
||||
@@ -559,7 +559,7 @@ function prepareInstallData(installStep, stepOnly) {
|
||||
}
|
||||
|
||||
// No installation step if we have never started.
|
||||
if (typeof installStep === 'undefined' && installData.Step == STEP_NONE) {
|
||||
if (installStep === undefined && installData.Step == STEP_NONE) {
|
||||
newData = [];
|
||||
} else {
|
||||
newData = getDefaultInstallData();
|
||||
@@ -572,12 +572,12 @@ function prepareInstallData(installStep, stepOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof installStep !== 'undefined') {
|
||||
if (installStep !== undefined) {
|
||||
step = installData.Step;
|
||||
if (step == STEP_WELCOME) prepareStepWelcome(newData);
|
||||
|
||||
// Assume we want all data if stepOnly not set
|
||||
if (typeof stepOnly === 'undefined') {
|
||||
if (stepOnly === undefined) {
|
||||
if (step == STEP_INSTALL_TYPE) prepareStepInstallType(newData);
|
||||
else if (step == STEP_BINARY_LOCATIONS) prepareStepBinaryLocations(newData);
|
||||
else if (step == STEP_PROFILE_AND_AUTOMATION) prepareStepProfileAndAutomation(newData);
|
||||
@@ -700,7 +700,7 @@ function performStep(installStep, suppressRefresh, forceReload, csrfRetry) {
|
||||
$('#installContent').html(data.Html);
|
||||
$('#installContent').show();
|
||||
|
||||
if (typeof $('#installData').data('debug') !== 'undefined') {
|
||||
if ($('#installData').data('debug') !== undefined) {
|
||||
debugData = data;
|
||||
debugData.Html = '';
|
||||
debug = $('#installDebug');
|
||||
@@ -822,7 +822,7 @@ function performTestConnection(csrfRetry) {
|
||||
$('#installContent').removeClass('cactiInstallLoaderBlur');
|
||||
|
||||
var isSuccessful = false, statusText = testFailed;
|
||||
if (typeof data.status !== 'undefined') {
|
||||
if (data.status !== undefined) {
|
||||
if (data.status == 'true') {
|
||||
isSuccessful = true;
|
||||
statusText = testSuccessful;
|
||||
|
||||
+4
-2
@@ -3200,7 +3200,8 @@ function html_common_header(string $title, string $selectedTheme = '') : void {
|
||||
var showHideFilter = '<?php print __esc('Click to Show/Hide Filter'); ?>';
|
||||
var spikeKillResults = '<?php print __esc('SpikeKill Results'); ?>';
|
||||
var standardGraphicalUserInterface = '<?php print __esc('Standard Mode'); ?>';
|
||||
var tableConstraints = '<?php print __esc('Allow or limit the table columns to extend beyond the current windows limits.'); ?>';
|
||||
var tableConstraints = <?php print cacti_js_encode(__esc('Allow or limit the table columns to extend beyond the current windows ' .
|
||||
'limits.')); ?>;
|
||||
var testFailed = '<?php print __esc('Connection Failed'); ?>';
|
||||
var testSuccessful = '<?php print __esc('Connection Successful'); ?>';
|
||||
var theme = '<?php print $selectedTheme; ?>';
|
||||
@@ -3245,7 +3246,8 @@ function html_common_header(string $title, string $selectedTheme = '') : void {
|
||||
var zoom_i18n_zoom_out_factor = '<?php print __esc('Zoom Out Factor'); ?>';
|
||||
var zoom_i18n_zoom_out_positioning = '<?php print __esc('Zoom Out Positioning'); ?>';
|
||||
var zoom_outOfRangeTitle='<?php print __esc('Zoom Window Out of Range'); ?>';
|
||||
var zoom_outOfRangeMessage='<?php print __esc('Zoom Dates before January 1, 1993 are not supported in Cacti! Pick a more recent date.'); ?>';
|
||||
var zoom_outOfRangeMessage= <?php print cacti_js_encode(__esc('Zoom Dates before January 1, 1993 are not supported in Cacti! Pick a ' .
|
||||
'more recent date.')); ?>;
|
||||
</script>
|
||||
<?php
|
||||
// Global icons
|
||||
|
||||
+13
-13
@@ -477,7 +477,7 @@ class Ldap {
|
||||
public string $cn_full_name;
|
||||
public string $cn_email;
|
||||
|
||||
function __construct() {
|
||||
public function __construct() {
|
||||
// No DB lookup here: Cacti\Auth\LdapLoginProvider::buildLdap() is the
|
||||
// single source of truth for mapping login_providers.parameters onto
|
||||
// these properties, so this class stays a pure connection/protocol
|
||||
@@ -486,14 +486,14 @@ class Ldap {
|
||||
$this->host = '';
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
public function __destruct() {
|
||||
}
|
||||
|
||||
function ErrorHandler(int $level, string $message, string $file, int $line, array $context = []) : bool {
|
||||
public function ErrorHandler(int $level, string $message, string $file, int $line, array $context = []) : bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
function SetLdapHandler() : void {
|
||||
public function SetLdapHandler() : void {
|
||||
// drop out of cactis error handler
|
||||
restore_error_handler();
|
||||
|
||||
@@ -503,7 +503,7 @@ class Ldap {
|
||||
cacti_session_close();
|
||||
}
|
||||
|
||||
function RestoreCactiHandler() : void {
|
||||
public function RestoreCactiHandler() : void {
|
||||
// drop out of ldaps error handler
|
||||
restore_error_handler();
|
||||
|
||||
@@ -513,13 +513,13 @@ class Ldap {
|
||||
cacti_session_start();
|
||||
}
|
||||
|
||||
function RecordError(array $output, string $section = 'LDAP') : void {
|
||||
public function RecordError(array $output, string $section = 'LDAP') : void {
|
||||
$logDN = empty($output['dn']) ? '' : (', DN: ' . $output['dn']);
|
||||
cacti_log($section . ': ' . $output['error_text'] . $logDN, false, 'AUTH');
|
||||
cacti_log($section . ': ' . $output['stack'], false, 'AUTH', $this->debug);
|
||||
}
|
||||
|
||||
function Connect() : array {
|
||||
public function Connect() : array {
|
||||
$output = [];
|
||||
$ldap_conn = null;
|
||||
|
||||
@@ -698,7 +698,7 @@ class Ldap {
|
||||
}
|
||||
}
|
||||
|
||||
function Authenticate() : array {
|
||||
public function Authenticate() : array {
|
||||
$output = [];
|
||||
|
||||
cacti_log('LDAP: Authentication Start', false, 'AUTH', $this->debug);
|
||||
@@ -838,7 +838,7 @@ class Ldap {
|
||||
return $output;
|
||||
}
|
||||
|
||||
function GetMask() : int {
|
||||
public function GetMask() : int {
|
||||
if (!defined('ENT_HTML401')) {
|
||||
return ENT_COMPAT;
|
||||
} else {
|
||||
@@ -869,7 +869,7 @@ class Ldap {
|
||||
* failure) so the caller can leave assignments untouched
|
||||
* rather than revoking them on a transient outage.
|
||||
*/
|
||||
function ResolveGroupMemberships(string $username, array $groupNames) : ?array {
|
||||
public function ResolveGroupMemberships(string $username, array $groupNames) : ?array {
|
||||
if (!cacti_sizeof($groupNames)) {
|
||||
return [];
|
||||
}
|
||||
@@ -1136,7 +1136,7 @@ class Ldap {
|
||||
return $queries;
|
||||
}
|
||||
|
||||
function Search() : array {
|
||||
public function Search() : array {
|
||||
$output = [];
|
||||
|
||||
// Determine connection method and create LDAP Object
|
||||
@@ -1256,7 +1256,7 @@ class Ldap {
|
||||
return $output;
|
||||
}
|
||||
|
||||
function Getcn() : array {
|
||||
public function Getcn() : array {
|
||||
$output = [];
|
||||
|
||||
// Determine connection method and create LDAP Object
|
||||
@@ -1397,7 +1397,7 @@ class Ldap {
|
||||
return $output;
|
||||
}
|
||||
|
||||
function isUserInLDAPGroup(object $ldapConn, string $ldapbasedn, string $groupDN, string $ldapUser) : bool {
|
||||
public function isUserInLDAPGroup(object $ldapConn, string $ldapbasedn, string $groupDN, string $ldapUser) : bool {
|
||||
$query = cacti_ldap_filter(
|
||||
'(&(distinguishedName=<user>)(memberOf:1.2.840.113556.1.4.1941:=<group>))',
|
||||
['user' => $ldapUser, 'group' => $groupDN]
|
||||
|
||||
+8
-8
@@ -56,13 +56,13 @@ class MibParser extends MibCache {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct() {
|
||||
public function __construct() {
|
||||
set_time_limit(0);
|
||||
ini_set('memory_limit', '-1');
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
function add_mib(string $filename, string $mib_name): void {
|
||||
public function add_mib(string $filename, string $mib_name): void {
|
||||
$mibtext = file_get_contents($filename);
|
||||
|
||||
if ($mibtext === false) {
|
||||
@@ -78,7 +78,7 @@ class MibParser extends MibCache {
|
||||
* @param string $text
|
||||
* @return array
|
||||
*/
|
||||
function get_tokens($text) {
|
||||
public function get_tokens($text) {
|
||||
$in_quote = false;
|
||||
$in_comment = false;
|
||||
$token = '';
|
||||
@@ -197,7 +197,7 @@ class MibParser extends MibCache {
|
||||
* @param array $allowed
|
||||
* @return array
|
||||
*/
|
||||
function parse_simple_token($tokens, &$index, $allowed = null) {
|
||||
public function parse_simple_token($tokens, &$index, $allowed = null) {
|
||||
$index++;
|
||||
|
||||
if (is_array($allowed)) {
|
||||
@@ -222,7 +222,7 @@ class MibParser extends MibCache {
|
||||
* @param integer $index
|
||||
* @return array
|
||||
*/
|
||||
function parse_SYNTAX_token($tokens, &$index) {
|
||||
public function parse_SYNTAX_token($tokens, &$index) {
|
||||
$ret = null;
|
||||
|
||||
switch($tokens[$index + 1]) {
|
||||
@@ -316,7 +316,7 @@ class MibParser extends MibCache {
|
||||
* @param string $end
|
||||
* @return array
|
||||
*/
|
||||
function parse_bracket_token($tokens, &$index, $start, $end) {
|
||||
public function parse_bracket_token($tokens, &$index, $start, $end) {
|
||||
$begin = $index + 1;
|
||||
|
||||
while ($index + 1 < count($tokens) && $tokens[$index] != $end) {
|
||||
@@ -338,7 +338,7 @@ class MibParser extends MibCache {
|
||||
* @param boolean $full
|
||||
* @param mixed $mib_name
|
||||
*/
|
||||
function parse_mib($mibtext, $mib_name, $full = false): void {
|
||||
public function parse_mib($mibtext, $mib_name, $full = false): void {
|
||||
$tokens = MibParser::get_tokens($mibtext);
|
||||
$cnt = count($tokens);
|
||||
$rec = [];
|
||||
@@ -424,7 +424,7 @@ class MibParser extends MibCache {
|
||||
}
|
||||
}
|
||||
|
||||
function generate(): void {
|
||||
public function generate(): void {
|
||||
$this->oids['enterprises'] = ['oid' => '.1.3.6.1.4.1'];
|
||||
|
||||
foreach ($this->parsed as $object) {
|
||||
|
||||
+21
-21
@@ -42,23 +42,23 @@ class Net_Ping {
|
||||
public int $avail_method;
|
||||
public int $ping_type;
|
||||
|
||||
function __construct() {
|
||||
public function __construct() {
|
||||
$this->port = 33439;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
public function __destruct() {
|
||||
}
|
||||
|
||||
function close_socket() : void {
|
||||
public function close_socket() : void {
|
||||
@socket_shutdown($this->socket, 2);
|
||||
socket_close($this->socket);
|
||||
}
|
||||
|
||||
function start_time() : void {
|
||||
public function start_time() : void {
|
||||
$this->timer_start_time = microtime(true);
|
||||
}
|
||||
|
||||
function get_time(int $acc = 2) : mixed {
|
||||
public function get_time(int $acc = 2) : mixed {
|
||||
// format start time
|
||||
$start_time = $this->timer_start_time;
|
||||
// get and format end time
|
||||
@@ -67,7 +67,7 @@ class Net_Ping {
|
||||
return number_format($end_time - $start_time, $acc);
|
||||
}
|
||||
|
||||
function build_udp_packet() : void {
|
||||
public function build_udp_packet() : void {
|
||||
$data = 'cacti-monitoring-system'; // the actual test data
|
||||
|
||||
// now lets build the actual UDP packet
|
||||
@@ -75,19 +75,19 @@ class Net_Ping {
|
||||
$this->request_len = strlen($this->request);
|
||||
}
|
||||
|
||||
function ping_error_handler(int $errno, string $errmsg, string $filename, int $linenum, array $vars = []) : bool {
|
||||
public function ping_error_handler(int $errno, string $errmsg, string $filename, int $linenum, array $vars = []) : bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
function set_ping_error_handler() : void {
|
||||
public function set_ping_error_handler() : void {
|
||||
set_error_handler([$this, 'ping_error_handler']);
|
||||
}
|
||||
|
||||
function restore_cacti_error_handler() : void {
|
||||
public function restore_cacti_error_handler() : void {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
function build_icmp_packet() : void {
|
||||
public function build_icmp_packet() : void {
|
||||
$seq_low = random_int(0,255);
|
||||
$seq_high = random_int(0,255);
|
||||
|
||||
@@ -107,7 +107,7 @@ class Net_Ping {
|
||||
$this->request_len = strlen($this->request);
|
||||
}
|
||||
|
||||
function get_checksum(string $data) : string {
|
||||
public function get_checksum(string $data) : string {
|
||||
if (strlen($data) % 2) {
|
||||
$data .= "\x00";
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class Net_Ping {
|
||||
return pack('n*', ~$sum);
|
||||
}
|
||||
|
||||
function ping_icmp() : bool {
|
||||
public function ping_icmp() : bool {
|
||||
// ping me
|
||||
if ($this->host['hostname']) {
|
||||
// initialize variables
|
||||
@@ -299,7 +299,7 @@ class Net_Ping {
|
||||
}
|
||||
}
|
||||
|
||||
function seteuid() : int {
|
||||
public function seteuid() : int {
|
||||
$cacti_user = '';
|
||||
|
||||
// if we are unix, set the effective userid to root and then create
|
||||
@@ -312,7 +312,7 @@ class Net_Ping {
|
||||
return $cacti_user;
|
||||
}
|
||||
|
||||
function setuid(int $cacti_poller_account) : void {
|
||||
public function setuid(int $cacti_poller_account) : void {
|
||||
// if we are unix, set the effective userid to root and then create
|
||||
if ((CACTI_SERVER_OS == 'unix') &&
|
||||
(function_exists('posix_getuid'))) {
|
||||
@@ -320,7 +320,7 @@ class Net_Ping {
|
||||
}
|
||||
}
|
||||
|
||||
function ping_snmp() : mixed {
|
||||
public function ping_snmp() : mixed {
|
||||
// initialize variables
|
||||
$this->snmp_status = 'down';
|
||||
$this->snmp_response = 'Device did not respond to SNMP';
|
||||
@@ -352,7 +352,7 @@ class Net_Ping {
|
||||
return $result;
|
||||
}
|
||||
|
||||
function get_snmp_result(string $oid) : bool {
|
||||
public function get_snmp_result(string $oid) : bool {
|
||||
$h = $this->host;
|
||||
|
||||
// getnext does not work in php versions less than 5
|
||||
@@ -389,7 +389,7 @@ class Net_Ping {
|
||||
}
|
||||
} // ping_snmp
|
||||
|
||||
function ping_udp() : bool {
|
||||
public function ping_udp() : bool {
|
||||
$this->set_ping_error_handler();
|
||||
|
||||
// hostname must be nonblank
|
||||
@@ -519,7 +519,7 @@ class Net_Ping {
|
||||
}
|
||||
} // end ping_udp
|
||||
|
||||
function ping_tcp() : bool {
|
||||
public function ping_tcp() : bool {
|
||||
$this->set_ping_error_handler();
|
||||
|
||||
// hostname must be nonblank
|
||||
@@ -651,7 +651,7 @@ class Net_Ping {
|
||||
}
|
||||
} // end ping_tcp
|
||||
|
||||
function ping(int $avail_method = AVAIL_SNMP_AND_PING, int $ping_type = PING_ICMP, int $timeout = 500, int $retries = 3) : bool {
|
||||
public function ping(int $avail_method = AVAIL_SNMP_AND_PING, int $ping_type = PING_ICMP, int $timeout = 500, int $retries = 3) : bool {
|
||||
$this->set_ping_error_handler();
|
||||
|
||||
// initialize variables
|
||||
@@ -761,7 +761,7 @@ class Net_Ping {
|
||||
};
|
||||
} // end_ping
|
||||
|
||||
function is_ipaddress(string $ip_address = '') : bool {
|
||||
public function is_ipaddress(string $ip_address = '') : bool {
|
||||
// check for ipv4/v6
|
||||
if (function_exists('filter_var')) {
|
||||
if (filter_var($ip_address, FILTER_VALIDATE_IP) !== false) {
|
||||
@@ -776,7 +776,7 @@ class Net_Ping {
|
||||
}
|
||||
}
|
||||
|
||||
function strip_ip_address(string $ip_address) : string {
|
||||
public function strip_ip_address(string $ip_address) : string {
|
||||
// clean up hostname if specifying snmp_transport
|
||||
if (str_contains($ip_address, 'tcp6:')) {
|
||||
$ip_address = str_replace('tcp6:', '', cacti_strtolower($ip_address));
|
||||
|
||||
+7
-2
@@ -262,8 +262,13 @@ function display_settings() : void {
|
||||
var currentTab = '<?php print $current_tab; ?>';
|
||||
var dataCollectors = '<?php print $data_collectors; ?>';
|
||||
var permsTitle = '<?php print __esc('Changing Permission Model Warning'); ?>';
|
||||
var permsHeader = '<?php print __esc('Changing Permission Model will alter a users effective Graph permissions.'); ?>';
|
||||
var permsMessage = '<?php print __esc('After you change the Graph Permission Model you should audit your Users and User Groups Effective Graph permission to ensure that you still have adequate control of your Graphs. NOTE: If you want to restrict all Graphs at the Device or Graph Template Graph Permission Model, the default Graph Policy should be set to \'Deny\'.'); ?>';
|
||||
var permsHeader = <?php print cacti_js_encode(__esc('Changing Permission Model will alter a users effective Graph ' .
|
||||
'permissions.')); ?>;
|
||||
var permsMessage = <?php print cacti_js_encode(__esc('After you change the Graph Permission Model you should audit your ' .
|
||||
'Users and User Groups Effective Graph permission to ensure that you ' .
|
||||
'still have adequate control of your Graphs. NOTE: If you want to ' .
|
||||
'restrict all Graphs at the Device or Graph Template Graph Permission ' .
|
||||
'Model, the default Graph Policy should be set to \'Deny\'.')); ?>;
|
||||
|
||||
$(function() {
|
||||
$('#filter').keyup(function() {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
+-------------------------------------------------------------------------+
|
||||
| Copyright (C) 2004-2026 The Cacti Group |
|
||||
| Licensed under the GNU General Public License, version 2 or later. |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Cacti: The Complete RRDtool-based Graphing Solution |
|
||||
+-------------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
function cacti_test_public_method_contracts(): array {
|
||||
static $contracts = null;
|
||||
|
||||
if ($contracts !== null) {
|
||||
return $contracts;
|
||||
}
|
||||
|
||||
// Load the production classes in a separate process. Collecting this test
|
||||
// must not alter class/function ownership in other Cacti unit test files.
|
||||
$probe = dirname(__DIR__, 2) . '/fixtures/Core/PublicMethodContractProbe.php';
|
||||
$process = proc_open([PHP_BINARY, $probe], [
|
||||
0 => ['pipe', 'r'],
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
], $pipes);
|
||||
|
||||
if (!is_resource($process)) {
|
||||
throw new RuntimeException('Unable to start the public API probe.');
|
||||
}
|
||||
|
||||
fclose($pipes[0]);
|
||||
$output = stream_get_contents($pipes[1]);
|
||||
$errors = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
if (proc_close($process) !== 0) {
|
||||
throw new RuntimeException($errors);
|
||||
}
|
||||
|
||||
$contracts = json_decode($output, true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
return $contracts;
|
||||
}
|
||||
|
||||
$baseline = json_decode(file_get_contents(
|
||||
dirname(__DIR__, 2) . '/fixtures/Core/public-method-signatures.json'
|
||||
), true, 512, JSON_THROW_ON_ERROR);
|
||||
$cases = [];
|
||||
|
||||
foreach ($baseline as $name => $contract) {
|
||||
$cases[$name] = [$name, $contract];
|
||||
}
|
||||
|
||||
test('the public method retains its complete Cacti develop call contract', function (string $name, array $expected) {
|
||||
$actual = cacti_test_public_method_contracts();
|
||||
expect($actual)->toHaveCount(46);
|
||||
expect($actual[$name])->toBe($expected);
|
||||
})->with($cases);
|
||||
@@ -127,7 +127,9 @@ test('form_cert_box() shows the expiration date of a pasted valid certificate',
|
||||
form_cert_box('idp_x509cert', $pem, '', 6, 60);
|
||||
$html = ob_get_clean();
|
||||
|
||||
$expected = date('Y-m-d', strtotime('+30 days'));
|
||||
$certificate = openssl_x509_parse($pem);
|
||||
expect($certificate)->not->toBeFalse();
|
||||
$expected = date('Y-m-d', $certificate['validTo_time_t']);
|
||||
|
||||
expect($html)->toContain('<textarea');
|
||||
expect($html)->toContain('Good Till: ' . $expected);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
// Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later.
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/Helpers/CactiStubs.php';
|
||||
require_once CACTI_PATH_INCLUDE . '/global.php';
|
||||
|
||||
test('inline translated values use the shared JSON boundary and preserve HTML escaping', function (string $path, string $variable, string $catalogMessage) {
|
||||
$source = file_get_contents(CACTI_PATH_BASE . '/' . $path);
|
||||
$pattern = '/\bvar\s+' . preg_quote($variable, '/') . '\s*=\s*[\'\"]?<\?php\s+print\s+(.*?)\?>/s';
|
||||
expect(preg_match($pattern, $source, $match))->toBe(1);
|
||||
$parser = (new \PhpParser\ParserFactory())->createForNewestSupportedVersion();
|
||||
$statements = $parser->parse('<?php print ' . trim($match[1]));
|
||||
$expression = $statements[0]->expr;
|
||||
expect($expression)->toBeInstanceOf(\PhpParser\Node\Expr\Print_::class);
|
||||
$encodedCall = $expression->expr;
|
||||
expect($encodedCall)->toBeInstanceOf(\PhpParser\Node\Expr\FuncCall::class);
|
||||
expect($encodedCall->name->toString())->toBe('cacti_js_encode');
|
||||
$translatedCall = $encodedCall->args[0]->value;
|
||||
expect($translatedCall)->toBeInstanceOf(\PhpParser\Node\Expr\FuncCall::class);
|
||||
expect($translatedCall->name->toString())->toBe('__esc');
|
||||
|
||||
// Supply adversarial catalog text to the actual production expression;
|
||||
// neither the translation helper nor the JSON encoder is replaced.
|
||||
$translatedCall->args[0]->value = new \PhpParser\Node\Expr\Variable('catalogMessage');
|
||||
$printer = new \PhpParser\PrettyPrinter\Standard();
|
||||
$encoded = eval('return ' . $printer->prettyPrintExpr($encodedCall) . ';');
|
||||
expect(json_decode($encoded, true, 512, JSON_THROW_ON_ERROR))->toBe(__esc($catalogMessage));
|
||||
expect($encoded)->not->toContain('</script>');
|
||||
expect($encoded)->not->toContain("\u{2028}");
|
||||
expect($encoded)->not->toContain("\u{2029}");
|
||||
})->with([
|
||||
['settings.php', 'permsHeader'],
|
||||
['settings.php', 'permsMessage'],
|
||||
['lib/html.php', 'tableConstraints'],
|
||||
['lib/html.php', 'zoom_outOfRangeMessage'],
|
||||
])->with([
|
||||
'quotes and backslashes' => ["single' double\" backslash\\"],
|
||||
'script closing text' => ['</script><script>window.untrusted=true</script>'],
|
||||
'line terminators' => ["first\nsecond\u{2028}third\u{2029}fourth"],
|
||||
'HTML entities' => ['" ' <b>caption</b>'],
|
||||
]);
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later. */
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
test('Midwinter homepage popup cannot access its opener', async ({ page, context }) => {
|
||||
const source = readFileSync(resolve(__dirname, '../../../include/themes/midwinter/main.js'), 'utf8');
|
||||
const sink = source.indexOf("window.open('https://cacti.net'");
|
||||
expect(sink).toBeGreaterThan(0);
|
||||
const start = source.lastIndexOf('function()', sink);
|
||||
const end = source.indexOf('});', sink);
|
||||
expect(start).toBeGreaterThan(0);
|
||||
expect(end).toBeGreaterThan(sink);
|
||||
const handler = source.slice(start, end + 1);
|
||||
await context.route('https://cacti.net/**', route => route.fulfill({
|
||||
contentType: 'text/html', body: '<!DOCTYPE html><title>Fixture homepage</title>',
|
||||
}));
|
||||
await page.setContent('<!DOCTYPE html><button id="homepage">Homepage</button>');
|
||||
// Execute the repository-owned callback with a real click; no fixture
|
||||
// implementation of window.open or opener isolation is substituted.
|
||||
await page.addScriptTag({ content: `document.querySelector('#homepage').addEventListener('click', ${handler});` });
|
||||
const popupPromise = context.waitForEvent('page');
|
||||
await page.locator('#homepage').click();
|
||||
const popup = await popupPromise;
|
||||
await popup.waitForLoadState();
|
||||
expect(await popup.evaluate(() => window.opener)).toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later. */
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const root = resolve(__dirname, '../../..');
|
||||
const layout = readFileSync(resolve(root, 'include/layout.js'), 'utf8');
|
||||
const start = layout.indexOf('$.fn.rebind = function');
|
||||
const body = layout.indexOf('{', start);
|
||||
let depth = 0;
|
||||
let end = body;
|
||||
for (; end < layout.length; end++) {
|
||||
if (layout[end] === '{') depth++;
|
||||
if (layout[end] === '}' && --depth === 0) break;
|
||||
}
|
||||
const rebind = layout.slice(start, end + 1) + ';';
|
||||
|
||||
for (const theme of ['cacti', 'carrot', 'dark', 'deepness', 'hollyberry', 'modern', 'paper-plane', 'paw', 'raspberry', 'sunrise']) {
|
||||
for (const stored of [false, true]) {
|
||||
test(`${theme} navigation keeps menu state local with ${stored ? 'persisted' : 'empty'} storage`, async ({ page }) => {
|
||||
await page.route('http://cacti.test/**', route => route.fulfill({
|
||||
contentType: 'text/html',
|
||||
body: '<!DOCTYPE html><div id="navigation"><div id="nav"><ul>' +
|
||||
'<li class="menuitem" id="menu-a"><a class="active" href="#a">A</a><ul><li><a class="selected">Selected</a></li></ul></li>' +
|
||||
'<li class="menuitem" id="menu-b"><a class="active" href="#b">B</a><ul><li><a>Other</a></li></ul></li>' +
|
||||
'</ul></div></div>',
|
||||
}));
|
||||
await page.goto('http://cacti.test/');
|
||||
await page.addScriptTag({ path: resolve(root, 'include/js/jquery.js') });
|
||||
await page.addScriptTag({ path: resolve(root, 'include/js/js.storage.js') });
|
||||
await page.addScriptTag({ content: rebind });
|
||||
const source = readFileSync(resolve(root, `include/themes/${theme}/main.js`), 'utf8');
|
||||
const menu = source.indexOf('function setMenuVisibility() {');
|
||||
expect(menu).toBeGreaterThan(0);
|
||||
await page.addScriptTag({ content: source.slice(menu) });
|
||||
await page.evaluate(stored => {
|
||||
const host = window as any;
|
||||
host.jQuery.fx.off = true;
|
||||
for (const name of ['id', 'active', 'text', 'storage']) host[name] = `host-${name}`;
|
||||
if (stored) {
|
||||
host.Storages.sessionStorage.set('menu-a', 'active');
|
||||
host.Storages.sessionStorage.set('menu-b', 'collapsed');
|
||||
}
|
||||
host.setMenuVisibility();
|
||||
host.setMenuVisibility();
|
||||
}, stored);
|
||||
const menuB = page.locator('#menu-b > ul');
|
||||
await expect(menuB).toBeHidden();
|
||||
await page.locator('#menu-b > a').click();
|
||||
await expect(menuB).toBeVisible();
|
||||
await expect(menuB).toHaveAttribute('aria-expanded', 'true');
|
||||
await expect(menuB).toHaveAttribute('aria-hidden', 'false');
|
||||
await expect(page.locator('#menu-a > ul')).toBeHidden();
|
||||
expect(await page.evaluate(() => {
|
||||
const storage = (window as any).Storages.sessionStorage;
|
||||
return [storage.get('menu-a'), storage.get('menu-b')];
|
||||
})).toEqual(['collapsed', 'active']);
|
||||
await page.locator('#menu-b > a').click();
|
||||
await expect(menuB).toBeHidden();
|
||||
await expect(menuB).toHaveAttribute('aria-expanded', 'false');
|
||||
await expect(menuB).toHaveAttribute('aria-hidden', 'true');
|
||||
expect(await page.evaluate(() => (window as any).Storages.sessionStorage.get('menu-b'))).toBe('collapsed');
|
||||
expect(await page.evaluate(() => ['id', 'active', 'text', 'storage'].map(name => (window as any)[name])))
|
||||
.toEqual(['host-id', 'host-active', 'host-text', 'host-storage']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later. */
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
test('column widths follow the table attribute across action changes and retain the ID fallback', async ({ page }) => {
|
||||
const root = resolve(__dirname, '../../..');
|
||||
const source = readFileSync(resolve(root, 'include/layout.js'), 'utf8');
|
||||
const start = source.indexOf('function saveTableWidths(initial)');
|
||||
const end = source.indexOf('\n}\n', start);
|
||||
expect(start).toBeGreaterThan(0);
|
||||
expect(end).toBeGreaterThan(start);
|
||||
await page.route('http://cacti.test/column-widths', route => route.fulfill({
|
||||
contentType: 'text/html',
|
||||
body: '<!DOCTYPE html><table id="hosts_view" class="cactiTable" data-colsizing="hosts"><tr><th class="ui-resizable">Name</th><th class="ui-resizable">Count</th></tr></table>',
|
||||
}));
|
||||
await page.goto('http://cacti.test/column-widths');
|
||||
await page.addScriptTag({ path: resolve(root, 'include/js/jquery.js') });
|
||||
await page.addScriptTag({ path: resolve(root, 'include/js/js.storage.js') });
|
||||
await page.addScriptTag({ content: source.slice(start, end + 2) });
|
||||
await page.evaluate(() => {
|
||||
const browser = window as any;
|
||||
browser.Storages.localStorage.set('hosts', [browser.$(document).width(), 210, 180]);
|
||||
browser.saveTableWidths(true);
|
||||
});
|
||||
expect(await page.locator('th').first().evaluate(element => element.getAttribute('resizeWidth'))).toBe('210');
|
||||
await page.evaluate(() => {
|
||||
const browser = window as any;
|
||||
document.querySelector('table')!.id = 'hosts_edit_report';
|
||||
browser.$('th').css('width', 50);
|
||||
browser.saveTableWidths(true);
|
||||
});
|
||||
expect(await page.locator('th').first().evaluate(element => element.getAttribute('resizeWidth'))).toBe('210');
|
||||
await page.evaluate(() => {
|
||||
const browser = window as any;
|
||||
const table = document.querySelector('table')!;
|
||||
table.removeAttribute('data-colsizing');
|
||||
browser.Storages.localStorage.set(table.id, [browser.$(document).width(), 260, 190]);
|
||||
browser.saveTableWidths(true);
|
||||
});
|
||||
expect(await page.locator('th').first().evaluate(element => element.getAttribute('resizeWidth'))).toBe('260');
|
||||
await page.evaluate(() => {
|
||||
const browser = window as any;
|
||||
document.querySelector('table')!.setAttribute('data-colsizing', '');
|
||||
browser.saveTableWidths(true);
|
||||
});
|
||||
expect(await page.locator('th').first().evaluate(element => element.getAttribute('resizeWidth'))).toBe('260');
|
||||
expect(await page.evaluate(() => Object.hasOwn(window, 'sizes') || Object.hasOwn(window, 'items'))).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
+-------------------------------------------------------------------------+
|
||||
| Copyright (C) 2004-2026 The Cacti Group |
|
||||
| Licensed under the GNU General Public License, version 2 or later. |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Cacti: The Complete RRDtool-based Graphing Solution |
|
||||
+-------------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/lib/ping.php';
|
||||
require_once dirname(__DIR__, 3) . '/lib/ldap.php';
|
||||
require_once dirname(__DIR__, 3) . '/lib/mib_cache.php';
|
||||
require_once dirname(__DIR__, 3) . '/lib/mib_parser.php';
|
||||
|
||||
$contracts = [];
|
||||
|
||||
foreach (['Net_Ping', 'Ldap', 'MibParser'] as $class) {
|
||||
foreach ((new ReflectionClass($class))->getMethods() as $method) {
|
||||
if ($method->getDeclaringClass()->getName() !== $class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameters = [];
|
||||
|
||||
foreach ($method->getParameters() as $parameter) {
|
||||
$parameters[] = [
|
||||
'name' => $parameter->getName(),
|
||||
'reference' => $parameter->isPassedByReference(),
|
||||
'variadic' => $parameter->isVariadic(),
|
||||
'type' => $parameter->hasType() ? (string) $parameter->getType() : null,
|
||||
'optional' => $parameter->isOptional(),
|
||||
'default' => !$parameter->isDefaultValueAvailable() ? null :
|
||||
($parameter->isDefaultValueConstant() ?
|
||||
['constant' => $parameter->getDefaultValueConstantName()] :
|
||||
['value' => $parameter->getDefaultValue()]),
|
||||
];
|
||||
}
|
||||
|
||||
$contracts[$class . '::' . $method->getName()] = [
|
||||
'public' => $method->isPublic(),
|
||||
'static' => $method->isStatic(),
|
||||
'parameters' => $parameters,
|
||||
'return' => $method->hasReturnType() ? (string) $method->getReturnType() : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
print json_encode($contracts, JSON_THROW_ON_ERROR);
|
||||
@@ -0,0 +1 @@
|
||||
{"Net_Ping::__construct":{"public":true,"static":false,"parameters":[],"return":null},"Net_Ping::__destruct":{"public":true,"static":false,"parameters":[],"return":null},"Net_Ping::close_socket":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::start_time":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::get_time":{"public":true,"static":false,"parameters":[{"name":"acc","reference":false,"variadic":false,"type":"int","optional":true,"default":{"value":2}}],"return":"mixed"},"Net_Ping::build_udp_packet":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::ping_error_handler":{"public":true,"static":false,"parameters":[{"name":"errno","reference":false,"variadic":false,"type":"int","optional":false,"default":null},{"name":"errmsg","reference":false,"variadic":false,"type":"string","optional":false,"default":null},{"name":"filename","reference":false,"variadic":false,"type":"string","optional":false,"default":null},{"name":"linenum","reference":false,"variadic":false,"type":"int","optional":false,"default":null},{"name":"vars","reference":false,"variadic":false,"type":"array","optional":true,"default":{"value":[]}}],"return":"bool"},"Net_Ping::set_ping_error_handler":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::restore_cacti_error_handler":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::build_icmp_packet":{"public":true,"static":false,"parameters":[],"return":"void"},"Net_Ping::get_checksum":{"public":true,"static":false,"parameters":[{"name":"data","reference":false,"variadic":false,"type":"string","optional":false,"default":null}],"return":"string"},"Net_Ping::ping_icmp":{"public":true,"static":false,"parameters":[],"return":"bool"},"Net_Ping::seteuid":{"public":true,"static":false,"parameters":[],"return":"int"},"Net_Ping::setuid":{"public":true,"static":false,"parameters":[{"name":"cacti_poller_account","reference":false,"variadic":false,"type":"int","optional":false,"default":null}],"return":"void"},"Net_Ping::ping_snmp":{"public":true,"static":false,"parameters":[],"return":"mixed"},"Net_Ping::get_snmp_result":{"public":true,"static":false,"parameters":[{"name":"oid","reference":false,"variadic":false,"type":"string","optional":false,"default":null}],"return":"bool"},"Net_Ping::ping_udp":{"public":true,"static":false,"parameters":[],"return":"bool"},"Net_Ping::ping_tcp":{"public":true,"static":false,"parameters":[],"return":"bool"},"Net_Ping::ping":{"public":true,"static":false,"parameters":[{"name":"avail_method","reference":false,"variadic":false,"type":"int","optional":true,"default":{"constant":"AVAIL_SNMP_AND_PING"}},{"name":"ping_type","reference":false,"variadic":false,"type":"int","optional":true,"default":{"constant":"PING_ICMP"}},{"name":"timeout","reference":false,"variadic":false,"type":"int","optional":true,"default":{"value":500}},{"name":"retries","reference":false,"variadic":false,"type":"int","optional":true,"default":{"value":3}}],"return":"bool"},"Net_Ping::is_ipaddress":{"public":true,"static":false,"parameters":[{"name":"ip_address","reference":false,"variadic":false,"type":"string","optional":true,"default":{"value":""}}],"return":"bool"},"Net_Ping::strip_ip_address":{"public":true,"static":false,"parameters":[{"name":"ip_address","reference":false,"variadic":false,"type":"string","optional":false,"default":null}],"return":"string"},"Ldap::__construct":{"public":true,"static":false,"parameters":[],"return":null},"Ldap::__destruct":{"public":true,"static":false,"parameters":[],"return":null},"Ldap::ErrorHandler":{"public":true,"static":false,"parameters":[{"name":"level","reference":false,"variadic":false,"type":"int","optional":false,"default":null},{"name":"message","reference":false,"variadic":false,"type":"string","optional":false,"default":null},{"name":"file","reference":false,"variadic":false,"type":"string","optional":false,"default":null},{"name":"line","reference":false,"variadic":false,"type":"int","optional":false,"default":null},{"name":"context","reference":false,"variadic":false,"type":"array","optional":true,"default":{"value":[]}}],"return":"bool"},"Ldap::SetLdapHandler":{"public":true,"static":false,"parameters":[],"return":"void"},"Ldap::RestoreCactiHandler":{"public":true,"static":false,"parameters":[],"return":"void"},"Ldap::RecordError":{"public":true,"static":false,"parameters":[{"name":"output","reference":false,"variadic":false,"type":"array","optional":false,"default":null},{"name":"section","reference":false,"variadic":false,"type":"string","optional":true,"default":{"value":"LDAP"}}],"return":"void"},"Ldap::Connect":{"public":true,"static":false,"parameters":[],"return":"array"},"Ldap::Authenticate":{"public":true,"static":false,"parameters":[],"return":"array"},"Ldap::GetMask":{"public":true,"static":false,"parameters":[],"return":"int"},"Ldap::ResolveGroupMemberships":{"public":true,"static":false,"parameters":[{"name":"username"Line truncated
|
||||
@@ -0,0 +1,205 @@
|
||||
/* Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later. */
|
||||
'use strict';
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
const vm = require('node:vm');
|
||||
const root = path.resolve(__dirname, '../..');
|
||||
|
||||
function source(file) {
|
||||
return fs.readFileSync(path.join(root, file), 'utf8');
|
||||
}
|
||||
|
||||
function functionAt(text, start) {
|
||||
assert.ok(start >= 0);
|
||||
const body = text.indexOf('{', start);
|
||||
let depth = 0;
|
||||
for (let offset = body; offset < text.length; offset++) {
|
||||
if (text[offset] === '{') depth++;
|
||||
if (text[offset] === '}' && --depth === 0) return text.slice(start, offset + 1);
|
||||
}
|
||||
throw new Error('Unclosed production function');
|
||||
}
|
||||
|
||||
function load(file, names, globals) {
|
||||
const text = source(file);
|
||||
const context = vm.createContext(globals);
|
||||
for (const name of names) {
|
||||
vm.runInContext(functionAt(text, text.indexOf(`function ${name}(`)), context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
test('fullscreen controls reconcile state after successful and rejected requests', async () => {
|
||||
for (const fullscreen of [false, true]) {
|
||||
for (const rejected of [false, true]) {
|
||||
let entries = 0;
|
||||
let exits = 0;
|
||||
let updates = 0;
|
||||
const result = () => rejected ? Promise.reject(new Error('Browser denied request')) : Promise.resolve();
|
||||
const context = load('include/themes/midwinter/main.js', ['fullScreen'], {
|
||||
document: {
|
||||
fullscreenElement: fullscreen,
|
||||
documentElement: { requestFullscreen: () => { entries++; return result(); } },
|
||||
exitFullscreen: () => { exits++; return result(); },
|
||||
},
|
||||
fullScreenChangeHandler: () => { updates++; },
|
||||
});
|
||||
context.fullScreen({});
|
||||
await new Promise(resolve => setImmediate(resolve));
|
||||
assert.equal(entries, fullscreen ? 0 : 1);
|
||||
assert.equal(exits, fullscreen ? 1 : 0);
|
||||
assert.equal(updates, 1);
|
||||
}
|
||||
}
|
||||
const context = load('include/themes/midwinter/main.js', ['fullScreen'], {
|
||||
document: { fullscreenElement: true },
|
||||
});
|
||||
assert.doesNotThrow(() => context.fullScreen({}));
|
||||
});
|
||||
|
||||
test('toast accepts primitive and boxed strings without leaking global state', () => {
|
||||
const text = source('include/js/ui-notices.js');
|
||||
const start = text.indexOf('function(options)');
|
||||
let rendered;
|
||||
const jquery = {
|
||||
extend: (...options) => Object.assign({}, ...options),
|
||||
toast: options => { rendered = options; return options; },
|
||||
};
|
||||
const toast = vm.runInNewContext(`(${functionAt(text, start)})`, { $: jquery, String });
|
||||
for (const value of ['plain', new String('boxed'), { text: 'configured' }, undefined]) {
|
||||
toast(value);
|
||||
assert.equal(typeof rendered.text, 'string');
|
||||
assert.equal(rendered.text, value === undefined ? 'No text was set, please check the usage of showToast' : typeof value === 'object' && !(value instanceof String) ? value.text : String(value));
|
||||
}
|
||||
});
|
||||
|
||||
test('realtime requests stop Pace for countdown, initial load and refresh', () => {
|
||||
for (const action of ['countdown', 'initial', 'refresh']) {
|
||||
let stops = 0;
|
||||
let requested;
|
||||
const jquery = selector => ({
|
||||
val: () => ({ '#graph_start': '60', '#ds_step': '5', '#size': '50', '#local_graph_id': '42' })[selector],
|
||||
is: () => false, width: () => 600, height: () => 400,
|
||||
});
|
||||
jquery.getJSON = url => { requested = url; return { done: () => ({ fail: () => {} }) }; };
|
||||
const context = load('include/realtime.js', ['imageOptionsChanged'], {
|
||||
$: jquery, window: {}, Pace: { stop: () => { stops++; } },
|
||||
count: 0, rtWidth: 0, rtHeight: 0, local_graph_id: null,
|
||||
});
|
||||
context.imageOptionsChanged(action);
|
||||
assert.equal(stops, 1);
|
||||
assert.match(requested, new RegExp(`action=${action}&`));
|
||||
assert.match(requested, /local_graph_id=42&/);
|
||||
}
|
||||
});
|
||||
|
||||
test('Sunrise scroll indicator covers horizontal and vertical scrolling', () => {
|
||||
const text = source('include/themes/sunrise/main.js');
|
||||
const marker = ".rebind('scroll', ";
|
||||
const start = text.indexOf(marker) + marker.length;
|
||||
for (const x of [0, 10]) {
|
||||
for (const y of [0, 10]) {
|
||||
let color;
|
||||
const callback = vm.runInNewContext(`(${functionAt(text, start)})`, {
|
||||
$: selector => selector === '#navigation_right'
|
||||
? { scrollLeft: () => x, scrollTop: () => y }
|
||||
: { css: styles => { color = styles.color; } },
|
||||
});
|
||||
callback({});
|
||||
assert.equal(color, x === 0 && y === 0 ? '' : '#93CEFF');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('navigation membership handles the console, matching and absent links', () => {
|
||||
const jquery = () => ({ find: () => ({ each: callback => {
|
||||
for (const href of ['host.php', 'graphs.php']) callback.call({ href });
|
||||
} }) });
|
||||
const context = load('include/layout.js', ['userMenuNavigationExists'], {
|
||||
$: value => typeof value === 'object' ? { attr: () => value.href } : jquery(),
|
||||
basename: value => value.split('/').pop(),
|
||||
});
|
||||
for (const [url, expected] of [['index.php', true], ['/cacti/index.php', true], ['graphs.php', true], ['missing.php', false]]) {
|
||||
assert.equal(context.userMenuNavigationExists(url), expected);
|
||||
}
|
||||
});
|
||||
|
||||
test('wide tables restore hidden cells even when their column indexes exceed nine', () => {
|
||||
const headers = Array.from({ length: 12 }, (_, index) => ({
|
||||
index, visible: [0, 1, 10, 11].includes(index),
|
||||
locked: [0, 10].includes(index), checkbox: index === 11,
|
||||
}));
|
||||
const cells = headers.map((header) => ({ index: header.index, visible: header.visible }));
|
||||
const table = { table: true };
|
||||
function collection(nodes) {
|
||||
return {
|
||||
length: nodes.length,
|
||||
get: () => nodes,
|
||||
each: (callback) => {
|
||||
nodes.forEach((node, index) => callback.call(node, index, node));
|
||||
return collection(nodes);
|
||||
},
|
||||
find: (selector) => collection(selector === 'th' ? headers : selector === 'td' ? cells : selector === 'tr' ? [{}, {}] : []),
|
||||
width: () => 300,
|
||||
attr: () => 'table-fixture',
|
||||
index: () => nodes[0].index,
|
||||
css: (property) => property === 'display' ? (nodes[0].visible ? 'table-cell' : 'none') : undefined,
|
||||
hasClass: (name) => name === 'noHide' ? nodes[0].locked : name === 'tableSubHeaderCheckbox' && nodes[0].checkbox,
|
||||
is: (selector) => selector === ':visible' ? nodes[0].visible : !nodes[0].visible,
|
||||
show: () => { nodes.forEach((node) => { node.visible = true; }); },
|
||||
hide: () => { nodes.forEach((node) => { node.visible = false; }); },
|
||||
};
|
||||
}
|
||||
const jquery = (value) => value && typeof value.each === 'function' ? value : collection(Array.isArray(value) ? value : [value]);
|
||||
jquery.textMetrics = () => ({ width: 5 });
|
||||
const context = load('include/layout.js', ['countHiddenCols', 'tuneTable'], { $: jquery, hScroll: false });
|
||||
context.tuneTable(table, 500);
|
||||
assert.equal(headers.every((header) => header.visible), true);
|
||||
assert.equal(cells.every((cell) => cell.visible), true);
|
||||
});
|
||||
|
||||
test('realtime shutdown restores snapshots populated by the layout click handler', () => {
|
||||
const initial = '<img id="graph_42" alt="Traffic graph">';
|
||||
let content = initial;
|
||||
let filters = 0;
|
||||
const link = {};
|
||||
function jquery(selector) {
|
||||
const chain = {
|
||||
attr: () => 'graph_42_realtime',
|
||||
html: (value) => {
|
||||
if (selector === '#wrapper_42') {
|
||||
if (value === undefined) return content;
|
||||
content = value;
|
||||
}
|
||||
return chain;
|
||||
},
|
||||
trigger: () => chain, empty: () => chain, find: () => chain,
|
||||
tooltip: () => chain, children: () => chain, on: () => chain,
|
||||
zoom: () => chain, remove: () => chain, css: () => chain,
|
||||
};
|
||||
return chain;
|
||||
}
|
||||
const context = load('include/realtime.js', ['stopRealtime'], {
|
||||
$: jquery, realtimeArray: [], keepRealtime: [], timeOffset: 0,
|
||||
realtimeClickOn: 'Start', realtimeClickOff: 'Stop', urlPath: '',
|
||||
setFilters: () => { filters++; }, tuneFilter: () => {}, realtimeGrapher: () => {}, shouldCaptureClick: () => true,
|
||||
});
|
||||
const layout = functionAt(source('include/layout.js'), source('include/layout.js').indexOf('function initializeGraphs('));
|
||||
const marker = "$(this).rebind('click', function (event) {";
|
||||
const scope = layout.indexOf("$('a[id$=\"_realtime\"]')");
|
||||
assert.notEqual(scope, -1);
|
||||
const start = layout.indexOf(marker, scope) + marker.indexOf('function (event)');
|
||||
assert.ok(start > 0);
|
||||
const click = vm.runInContext(`(${functionAt(layout, start)})`, context);
|
||||
click.call(link, { preventDefault: () => {}, stopPropagation: () => {} });
|
||||
assert.equal(context.realtimeArray[42], true);
|
||||
assert.equal(context.keepRealtime[42], initial);
|
||||
content = 'realtime frame';
|
||||
context.stopRealtime();
|
||||
assert.equal(content, initial);
|
||||
assert.equal(context.realtimeArray[42], false);
|
||||
assert.equal(filters, 2);
|
||||
});
|
||||
Reference in new issue
Block a user