///////////////////////////////////////////////////////////////////////////////
/*
intruspect.js
COPYRIGHT
---------
Copyright (C) 2017 Mark G.Daniel
This program, comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under the
conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version.
http://www.gnu.org/licenses/gpl.txt
VERSION
-------
30-JAN-2017 MGD initial
*/
///////////////////////////////////////////////////////////////////////////////
// versions of INTRUSPECT.EXE this JavaScript is compatible with
var intrsp_AcmeVersions = ['1.0.0','1.1.0'];
var intrsp_ExeVersions = ['1.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;
///////////////////////////////////////////////////////////////////////////////
////////////////////////////
// general infrastructure //
////////////////////////////
///////////////////////////////////////////////////////////////////////////////
var intrsp_MSIEversion = 0;
if (navigator.appName == 'Microsoft Internet Explorer')
{
var ua = navigator.userAgent;
var re = new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})');
if (re.exec(ua) != null) intrsp_MSIEversion = parseFloat(RegExp.$1);
}
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;
// default geolocation service (reference to a function)
var intrsp_GeolocateService = null;
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 configGeolocateService (func) { intrsp_GeolocateService = func; }
function configGeolocateFreeGeoIp (host) { geoLocateFreeGeoIp = host; }
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 != '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('display.js');
acmeLoadFile('geolocate.js');
acmeLoadFile('geolocateplus.js');
acmeLoadFile('intruspect.css');
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);
}
///////////////////////////////////////////////////////////////////////////////