///////////////////////////////////////////////////////////////////////////////
/*
intruspect.js
COPYRIGHT
---------
Copyright (C) 2017-2025 Mark G.Daniel
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
VERSION
-------
20-JAN-2025 MGD integrated GeoLocation
30-JAN-2017 MGD initial
*/
///////////////////////////////////////////////////////////////////////////////
// versions of INTRUSPECT.EXE this JavaScript is compatible with
var intrsp_AcmeVersions = ['1.1.0'];
var intrsp_ExeVersions = ['2.0.0'];
var intrsp_ColorConnected = 'black'
var intrsp_ColorDisconnected = 'red'
var intrsp_ThousandComma = ',';
var intrsp_ResourcePath = '/intruspect/-/';
var intrsp_LoadedFrom = location.protocol + location.host;
var intrsp_AcmeIncompatible = 'JavaScript and Acme module incompatible!\n' +
'The multiple sites have cannot interwork.'
var intrsp_ExeIncompatible = 'JavaScript and executable are incompatible!\n' +
'Reload and/or clear browser cache.';
var intrsp_Running = true;
var intrsp_StaticData;
var intrsp_GeoLocateData;
///////////////////////////////////////////////////////////////////////////////
////////////////////////////
// general infrastructure //
////////////////////////////
///////////////////////////////////////////////////////////////////////////////
String.prototype.htmlEscape = function()
{
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
};
return this.replace(/[&<>]/g, function(tag) {
return tagsToReplace[tag] || tag;
});
};
///////////////////////////////////////////////////////////////////////////////
/*
Quick and dirty query string parser. Usage:
var thisParam = intrspFromQuery().this_param;
var thatParam = intrspFromQuery().that_param;
*/
var intrsp_FromQueryParams;
function intrspFromQuery ()
{
if (intrsp_FromQueryParams) return intrsp_FromQueryParams;
var qs = location.search;
qs = qs.substring(qs.indexOf('?')+1).split('&');
var pair;
var params = {};
for (var i = qs.length - 1; i >= 0; i--)
{
pair = qs[i].split('=');
if (pair.length != 2) continue;
params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return (intrsp_FromQueryParams = params);
}
///////////////////////////////////////////////////////////////////////////////
/*
Dynamically modify a stylesheet.
*/
function intrspCSS (selector, property, value)
{
for (var idx = 0; idx < document.styleSheets.length; idx++)
{
var sheet = document.styleSheets[idx];
try {
var rule = selector + '{' + property + ':' + value + ';}';
sheet.insertRule(rule,sheet.cssRules.length);
}
catch(err) {
try {
sheet.addRule(selector,property+':'+value);
}
catch(err) {}
}
}
}
///////////////////////////////////////////////////////////////////////////////
////////////
// CONFIG //
////////////
///////////////////////////////////////////////////////////////////////////////
// period to highlight a deleted intrusion record
var intrsp_DeletedSecs = 30;
// period to highlight an entry with changed count
var intrsp_DeltaSecs = 30;
// the period to highlight just before history deletion
var intrsp_FadingSecs = 15;
// period to keep entries displayed after expiry
var intrsp_HistorySecs = 120;
// period to highlight new entries
var intrsp_NoticedSecs = 30;
function configHistorySecs (secs) { intrsp_HistorySecs = secs; }
function configDeletedSecs (secs) { intrsp_DeletedSecs = secs; }
function configDeltaSecs (secs) { intrsp_DeltaSecs = secs; }
function configFadingSecs (secs) { intrsp_FadingSecs = secs; }
function configForceXHR (tf) { acmeIpcForceXHR(tf); }
function configNoticedSecs (secs) { intrsp_NoticedSecs = secs; }
// these are just stubs and the value is actually processed by INTRUSPECT.C
function configRecordsMax () { }
function configUpdateSecs () { }
///////////////////////////////////////////////////////////////////////////////
/////////
// IPC //
/////////
///////////////////////////////////////////////////////////////////////////////
var intrsp_StreamingData = false;
function intrspStreamData (start)
{
// close any existing connections
intrsp_StreamingData = false;
acmeIpcClose();
if (!start) return;
if (acmeIpcOpen()) intrsp_StreamingData = true;
}
///////////////////////////////////////////////////////////////////////////////
/*
Receive JSON data from the executable.
*/
function intrspReceiveData (data)
{
try {
data = JSON.parse(data);
} catch (err) {
console.log(err,data);
}
if (data.$data == 'alert')
intrspAlert(data.time,data.message);
else
if (data.$data == 'intrusion')
{
intrsp_IntrusionData = data;
}
else
if (data.$data == 'static')
{
intrsp_StaticData = data;
// and add the node to the window title
var json = '{"$AddToTitle":true,"node":"' +
intrsp_StaticData.nodeName + '"}';
window.parent.postMessage(json,'*');
}
else
if (data.$data == 'geolocate')
{
intrsp_GeoLocateData = data;
}
else
if (data.$data != 'runtime')
{
intrspAlert('DATA ERROR: '+data.$data);
console.log(data);
}
if (intrsp_UpdateDisplay) intrspDisplaySummary();
if (intrsp_InsightDisplay) intrspDisplayInsight(data);
}
///////////////////////////////////////////////////////////////////////////////
/*
Append this message to the alert section in the node summary area.
*/
function intrspAlert (time,msg)
{
// fixe ON for INTRUspect
intrsp_AlertsDisplay = true;
if (typeof msg == 'undefined')
{
msg = time;
time = intrsp_IntrusionData['vmsTime'];
}
var alert = $byId('alert');
var closedAlert = $byId('closedAlert');
if (typeof msg == 'string')
{
if (intrsp_AlertsDisplay)
{
if (msg.substr(0,1) == '#') msg = msg.substr(1);
if (msg.substr(0,1) == '!')
var html = '' + time +
' ' + msg.substr(1) + '';
else
var html = '' + time +
' ' + msg + '';
if (alert.innerHTML) alert.innerHTML += '
';
alert.innerHTML += html;
closedAlert.innerHTML = html;
alert.onclick = intrspAlert;
}
}
else
alert.innerHTML = closedAlert.innerHTML = '';
acmeAdjustSize();
}
///////////////////////////////////////////////////////////////////////////////
////////////////
// data store //
////////////////
///////////////////////////////////////////////////////////////////////////////
var intrsp_IntrusionData;
var intrsp_StoreSeconds = 0;
var intrsp_StoreTimeStamp = 0;
///////////////////////////////////////////////////////////////////////////////
///////////
// print //
///////////
///////////////////////////////////////////////////////////////////////////////
var intrsp_PrintClickTimer = null;
var intrsp_PrintInProgress = false;
var intrsp_PrintTimeout = 5; // seconds
var intrsp_PrintUpdate;
function intrspPrintClick ()
{
if (intrsp_PrintInProgress)
intrspAfterPrint();
else
{
intrspBeforePrint();
setTimeout('window.print()',100);
}
return true;
}
function intrspBeforePrint ()
{
if (intrsp_PrintInProgress) return;
intrsp_PrintInProgress = true;
intrsp_PrintUpdate = intrsp_UpdateDisplay;
intrspUpdateClick(false);
clearTimeout(intrsp_PrintClickTimer);
intrsp_PrintClickTimer = null;
intrsp_PrintClickTimer = setTimeout('intrspPrintClick()',intrsp_PrintTimeout*1000);
};
function intrspAfterPrint()
{
if (!intrsp_PrintInProgress) return;
intrsp_PrintInProgress = false;
clearTimeout(intrsp_PrintClickTimer);
intrsp_PrintClickTimer = null;
if (intrsp_PrintUpdate) intrspUpdateClick(true);
};
// NOTE: this is in-line code
var intrsp_MatchMedia;
if (window.matchMedia)
{
intrsp_MatchMedia = window.matchMedia('print');
intrsp_MatchMedia.addListener(function(mql) {
if (mql.matches)
intrspBeforePrint();
else
intrspAfterPrint();
});
}
// a la MSIE
window.onbeforeprint = intrspBeforePrint;
window.onafterprint = intrspAfterPrint;
///////////////////////////////////////////////////////////////////////////////
////////////////
// build page //
////////////////
///////////////////////////////////////////////////////////////////////////////
/*
*/
var intrsp_OnOpenTimer = null;
function intrspOnOpen ()
{
if ($WebSocket)
{
$byId('sumNodeName').style.color = intrsp_ColorConnected;
$byId('monitorClosed').style.color = intrsp_ColorConnected;
// inform the process of the current interests
var params = intrspTheseData();
acmeIpcSend(params);
}
else
{
var disc = "$byId('sumNodeName').style.color = \
$byId('monitorClosed').style.color = intrsp_ColorConnected;";
intrsp_OnOpenTimer = setTimeout(disc,2000);
clearTimeout(intrsp_OnCloseTimer);
intrsp_OnCloseTimer = null;
}
}
///////////////////////////////////////////////////////////////////////////////
/*
*/
var intrsp_OnCloseTimer = null;
function intrspOnClose ()
{
if ($WebSocket)
{
$byId('sumNodeName').style.color = intrsp_ColorDisconnected;
$byId('monitorClosed').style.color = intrsp_ColorDisconnected;
}
else
{
// delay a little for re-request
var disc = "$byId('sumNodeName').style.color = \
$byId('monitorClosed').style.color = intrsp_ColorDisconnected;";
intrsp_OnCloseTimer = setTimeout(disc,2000);
clearTimeout(intrsp_OnOpenTimer);
intrsp_OnOpenTimer = null;
}
}
///////////////////////////////////////////////////////////////////////////////
/*
Primary function called by acme.js when primary JavaScript file loaded.
*/
function $intruspect ()
{
acmeIpcOnOpen(intrspOnOpen);
acmeIpcOnClose(intrspOnClose);
acmeIpcOnMessage(intrspReceiveData);
acmeLoadFile('intruspect.css');
acmeLoadFile('utf8.js');
acmeLoadFile('display.js');
acmeLoadFile('build.js','intrspBuildPage()');
}
if (intrsp_AcmeVersions.indexOf($AcmeVersion) == -1)
{
alert(intrsp_AcmeIncompatible);
throw new Error(intrsp_AcmeIncompatible);
}
if (intrsp_ExeVersions.indexOf($ExeVersion) == -1)
{
alert(intrsp_ExeIncompatible);
throw new Error(intrsp_ExeIncompatible);
}
///////////////////////////////////////////////////////////////////////////////