<html>
<head>
	<style rel="stylesheet" type="text/css">
	#alertInfo  {
		display : none;
		font : Fixed;
		font-size : 12px;
		border  : 1px solid #888;
		padding : 3px;
		height  : 150px;
	}

	#alertInfoTable  {
		font : Fixed;
		font-size : 12px;
		width : 100%;
	}

	a  {
		color : #2d2;
	}

	button  {
		background-color : #ddd;
		color : #222;
		font-size : 13px;
		border : 1px dotted #888;
	}

	button:hover  {
		background-color : #7fc;
	}
	</style>

	<script type="text/javascript" src="js/raphael.js"></script>
	<script type="text/javascript" src="js/dracula_graffle.js"></script>
	<script type="text/javascript" src="js/dracula_graph.js"></script>
	<script type="text/javascript">
<!--

redraw = null;
width  = 0;
height = 0;
layouter = null;
renderer = null;
json = [];

inCorrelateFrom = false;
inCorrelateTo   = false;
correlationFrom = -1;
correlationTo   = -1;
correlationFromIndex = -1;
correlationToIndex   = -1;

inUncorrelateFrom = false;
inUncorrelateTo   = false;
uncorrelationFrom = -1;
uncorrelationTo   = -1;
uncorrelationFromIndex = -1;
uncorrelationToIndex   = -1;

function correlate()  {
	var div = document.getElementById ( 'alertInfo' );
	var button = document.getElementById ( 'correlate' );

	if ( inCorrelateFrom || inCorrelateTo )
	{
		inCorrelateFrom = false;
		div.style.backgroundColor = '#FFF';
		div.style.display = 'none';
		button.innerHTML = 'Manually correlate';
	} else {
		inCorrelateFrom = true;
		inCorrelateTo   = false;
		div.innerHTML = '<b>Click on the source alert of the correlation</b>';
		div.style.backgroundColor = '#FF9';
		div.style.display = 'block';
		button.innerHTML = 'Cancel manual correlation';
	}
}

function uncorrelate()  {
	var div = document.getElementById ( 'alertInfo' );
	var button = document.getElementById ( 'uncorrelate' );

	if ( inUncorrelateFrom || inUncorrelateTo )
	{
		inUncorrelateFrom = false;
		div.style.backgroundColor = '#FFF';
		div.style.display = 'none';
		button.innerHTML = 'Remove correlation';
	} else {
		inUncorrelateFrom = true;
		inUncorrelateTo   = false;
		div.innerHTML = '<b>Click on the source alert of the un-correlation</b>';
		div.style.backgroundColor = '#FF9';
		div.style.display = 'block';
		button.innerHTML = 'Cancel un-correlation';
	}
}

window.onload = function()  {
	var req = new XMLHttpRequest();

	if ( navigator.appName.indexOf('Microsoft') != -1 )
	{
		width  = (document.body.offsetWidth > 20) ?
			document.body.offsetWidth - 20 : 20;
		height = (document.body.offsetHeight > 200 ) ?
			document.body.offsetHeight - 200 : 200;
	} else {
		width  = (window.innerWidth > 20) ?
			window.innerWidth - 20 : 20;
		height = (window.innerHeight > 200) ?
			window.innerHeight - 200 : 200;
	}

	req.open ( 'GET', 'http://' + window.location.host + '/correlation_graph.json', true );
	req.onreadystatechange = function()  {
		if ( req.readyState == 4 && req.status == 200 )
		{
			var g = new Graph();
			var connections = [];
			json = JSON.parse ( req.responseText );

			for ( var i=0; i < json.length; i++ )
			{
				g.addNode ( json[i].id, { label: json[i].label });

				if ( json[i].connectedTo )
				{
					for ( var j=0; j < json[i].connectedTo.length; j++ )
					{
						connections.push ({
							"from": json[i].id,
							"to"  : json[i].connectedTo[j].id
						});
					}
				}
			}

			for ( var i=0; i < connections.length; i++ )
			{
				g.addEdge ( connections[i].from, connections[i].to, { directed: true });
			}

			var canvas = document.getElementById ( 'canvas' );
			canvas.style.width = width;
			canvas.style.height = height;

			var layouter = new Graph.Layout.Spring ( g );
			layouter.layout();

			var renderer = new Graph.Renderer.Raphael ( 'canvas', g, width, height );
			renderer.draw();

			redraw = function() {
				layouter.layout();
				renderer.draw();
			};

			for ( var i=0; i < json.length; i++ )
			{
				var node = document.getElementById ( 'alert' + json[i].id );

				if ( node )
				{
					node.onclick = function()  {
						var div = document.getElementById ( 'alertInfo' );

						if ( div )
						{
							var id = this.id.replace ( /^alert/, "" );
							var json_element = null;
							var index = -1;

							for ( var i=0; i < json.length; i++ )
							{
								if ( json[i].id == id )
								{
									json_element = json[i];
									index = i;
									break;
								}
							}

							// Correlation stuff
							if ( inCorrelateFrom )
							{
								inCorrelateFrom = false;
								inCorrelateTo   = true;
								correlationFrom = id;
								correlationFromIndex = index;
								div.innerHTML = "<b>Click on the destination alert of the correlation</b><br>\n" +
									"From: <b>" + json_element.label + "</b>";
								return;
							} else if ( inCorrelateTo ) {
								inCorrelateTo = false;
								correlationTo = id;
								correlationToIndex = index;

								div.style.backgroundColor = '#FFF';
								div.style.display = 'none';

								// Check if this correlation is already there
								for ( var j=0; j < connections.length; j++ )
								{
									if ( connections[j].from == correlationFrom &&
											connections[j].to == correlationTo )
									{
										document.getElementById ( 'correlate' ).innerHTML = "Manually correlate";
										return;
									}
								}

								var from_sid = json[correlationFromIndex].snortSID;
								var from_gid = json[correlationFromIndex].snortGID;
								var from_rev = json[correlationFromIndex].snortREV;
								var to_sid   = json[correlationToIndex].snortSID;
								var to_gid   = json[correlationToIndex].snortGID;
								var to_rev   = json[correlationToIndex].snortREV;

								var corr_req = new XMLHttpRequest();
								corr_req.open ( 'GET', 'http://' + window.location.host +
										'/correlate.cgi?' +
										'action=add' +
										'&from_sid=' + from_sid +
										'&from_gid=' + from_gid +
										'&from_rev=' + from_rev +
										'&to_sid=' + to_sid +
										'&to_gid=' + to_gid +
										'&to_rev=' + to_rev, true );

								corr_req.send ( null );
								document.getElementById ( 'correlate' ).innerHTML = "Manually correlate";

								connections.push ({
									"from": correlationFrom,
									"to"  : correlationTo
								});

								g.addEdge ( correlationFrom, correlationTo, { directed: true });
								redraw();
								return;
							}

							// Un-correlation stuff
							if ( inUncorrelateFrom )
							{
								inUncorrelateFrom = false;
								inUncorrelateTo   = true;
								uncorrelationFrom = id;
								uncorrelationFromIndex = index;
								div.innerHTML = "<b>Click on the destination alert of the un-correlation</b><br>\n" +
									"From: <b>" + json_element.label + "</b>";
								return;
							} else if ( inUncorrelateTo ) {
								inUncorrelateTo = false;
								uncorrelationTo = id;
								uncorrelationToIndex = index;

								div.style.backgroundColor = '#FFF';
								div.style.display = 'none';

								// Check if the alerts are already un-correlated
								var correlated = false;

								for ( var j=0; j < connections.length && !correlated; j++ )
								{
									if ( connections[j].from == uncorrelationFrom &&
											connections[j].to == uncorrelationTo )
									{
										correlated = true;
									}
								}

								if ( !correlated )
								{
									document.getElementById ( 'uncorrelate' ).innerHTML = "Remove correlation";
									return;
								}

								var from_sid = json[uncorrelationFromIndex].snortSID;
								var from_gid = json[uncorrelationFromIndex].snortGID;
								var from_rev = json[uncorrelationFromIndex].snortREV;
								var to_sid   = json[uncorrelationToIndex].snortSID;
								var to_gid   = json[uncorrelationToIndex].snortGID;
								var to_rev   = json[uncorrelationToIndex].snortREV;

								var corr_req = new XMLHttpRequest();
								corr_req.open ( 'GET', 'http://' + window.location.host +
										'/correlate.cgi?' +
										'action=remove' +
										'&from_sid=' + from_sid +
										'&from_gid=' + from_gid +
										'&from_rev=' + from_rev +
										'&to_sid=' + to_sid +
										'&to_gid=' + to_gid +
										'&to_rev=' + to_rev, true );

								corr_req.send ( null );
								document.getElementById ( 'uncorrelate' ).innerHTML = "Remove correlation";

								// Remove the connection from the array
								for ( var j=0; j < connections.length; j++ )
								{
									if ( connections[j].from == uncorrelationFrom &&
											connections[j].to == uncorrelationTo )
									{
										connections.slice ( j, 1 );
										break;
									}
								}

								redraw();
								return;
							}

							var content =
								'<table id="alertInfoTable" cellspacing="5"><tr style="background-color:#99ff99">' +
								'<td><b>Type</b></td><td><b>From</b></td>' +
								'<td><b>To</b></td><td><b>Date</b></td></tr>' +
								'<tr><td>' + json_element.label;

							if ( json_element.packets )
							{
								content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
									json_element.packets.length;

								for ( var j=0; j < json_element.packets.length; j++ )
								{
									json_element.packets[j].match ( /^.*(=*)$/ );
									var pad = RegExp.$1;
									var len = parseInt ( json_element.packets[j].length * 3 / 4 ) - pad.length;

									json_element.date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );

									var month = RegExp.$1;
									var day   = RegExp.$2;
									var hour  = RegExp.$3;
									var min   = RegExp.$4;
									var sec   = RegExp.$5;
									var year  = RegExp.$6;

									switch ( month )
									{
										case 'Jan': month =  1; break;
										case 'Feb': month =  2; break;
										case 'Mar': month =  3; break;
										case 'Apr': month =  4; break;
										case 'May': month =  5; break;
										case 'Jun': month =  6; break;
										case 'Jul': month =  7; break;
										case 'Ago': month =  8; break;
										case 'Sep': month =  9; break;
										case 'Oct': month = 10; break;
										case 'Nov': month = 11; break;
										case 'Dec': month = 12; break;
										default   : month =  1; break;
									}

									var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
									timestamp = timestamp.replace ( /0{3}$/, "" );

									content += '&packet_len' + j + '=' + len +
									'&time' + j + '=' + timestamp +
									'&packet' + j + '=' + escape ( json_element.packets[j] );
								}
									
								content += '">save as pcap file</a>)';
							}
							
							content += '</td><td>' +
								json_element.from + '</td><td>' + json_element.to + '</td>' +
								'<td>' + json_element.date + '</td></tr>';

							if ( json_element.clusteredAlerts )
							{
								for ( var j=0; j < json_element.clusteredAlerts.length; j++ )
								{
									content +=
										'<tr><td>' + json_element.clusteredAlerts[j].label;

									if ( json_element.clusteredAlerts[j].packets )
									{
										content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
												json_element.clusteredAlerts[j].packets.length;
												
										for ( var k=0; k < json_element.clusteredAlerts[j].packets.length; k++ )
										{
											var unescaped = unescape ( json_element.clusteredAlerts[j].packets[k] );
											unescaped.match ( /(=+)/ );
											var pad = RegExp.$1;
											var len = parseInt ( json_element.clusteredAlerts[j].packets[k].length * 3 / 4 ) - pad.length;
											json_element.clusteredAlerts[j].date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );
											var month = RegExp.$1;
											var day   = RegExp.$2;
											var hour  = RegExp.$3;
											var min   = RegExp.$4;
											var sec   = RegExp.$5;
											var year  = RegExp.$6;

											switch ( month )
											{
												case 'Jan': month =  0; break;
												case 'Feb': month =  1; break;
												case 'Mar': month =  2; break;
												case 'Apr': month =  3; break;
												case 'May': month =  4; break;
												case 'Jun': month =  5; break;
												case 'Jul': month =  6; break;
												case 'Ago': month =  7; break;
												case 'Sep': month =  8; break;
												case 'Oct': month =  9; break;
												case 'Nov': month = 10; break;
												case 'Dec': month = 11; break;
												default   : month =  0; break;
											}

											var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
											timestamp = timestamp.replace ( /0{3}$/, "" );

											content += '&packet_len' + k + '=' + len +
												'&time' + k + '=' + timestamp +
												'&packet' + k + '=' + escape ( json_element.clusteredAlerts[j].packets[k] );
										}

										content += '">save as pcap file</a>)';
									}
									
									content += '</td>' +
										'<td>' + json_element.clusteredAlerts[j].from + '</td>' +
										'<td>' + json_element.clusteredAlerts[j].to + '</td>' +
										'<td>' + json_element.clusteredAlerts[j].date + '</td></tr>';
								}
							}

							content += '</table>';
							div.style.display = 'block';
							div.innerHTML = content;
						}
					};
				}
			}
		}
	};

	req.send ( null );
};

-->
    </script>
</head>
<body>
<div id="canvas" style="border: 1px solid #000"></div>
<div style="height : 5px"></div>
<button id="redraw" onClick="redraw();">Redraw</button>
<button id="correlate" onClick="correlate();">Manually correlate</button>
<button id="uncorrelate" onClick="uncorrelate();">Remove correlation</button>
<div id="popupAlert"></div>
<div id="alertInfo"></div>

</body>
</html>