<?php
/*
 *
 *  Copyright (c) 2004, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *   * Neither the name of SWITCH nor the names of its contributors may be
 *     used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 * 
 *  $Author: peter $
 *
 *  $Id: nfsen.php 57 2006-07-27 11:36:40Z peter $
 *
 *  $LastChangedRevision: 57 $
 *
 */

include ("conf.php");
include ("nfsenutil.php");
include ("navigator.php");

$DisplayOrder = array ( 'any', 'TCP', 'UDP', 'ICMP', 'other' );
$TypeOrder	  = array ( 'flows', 'packets', 'traffic');

// All available options 
$ListNOption  = array ( 10, 20, 50, 100, 500, 1000);
$TopNOption   = array ( 10, 20, 50, 100, 200, 500);

$IPStatOption = array ( 'Any IP Address', 'SRC IP Address', 'DST IP Address', 
						'Any Port', 'SRC Port', 'DST Port',  
						'Any AS',  'SRC AS',   'DST AS',
						'Any interface', 'In interface', 'Out interface');
$IPStatArg	  = array ( '-s ip',   '-s srcip',   '-s dstip', 
						'-s port', '-s srcport', '-s dstport', 
						'-s as',   '-s srcas',   '-s dstas',
						'-s if',   '-s inif',    '-s outif');

$IPStatOrder  = array ( 'flows', 'packets', 'bytes', 'pps', 'bps', 'bpp' );
$LimitScale	  = array ( '-', 'K', 'M', 'G', 'T' );

$OutputFormatOption = array ( 'line', 'long', 'extended');
$OutputFormatArg 	= array ( '-o line', '-o long', '-o extended');

/* 
 * scale factor: Number of 5min slices per pixel
 * graph with 576 pixel
 * 0.25 * 576 * 300 = 43200 => 12 hours
 * 0.5  * 576 * 300 = 86400 => 1 day
 * $scale * 172800 = time range of graph
 */
$WinSizeScale  = array ( 0.25,		  0.5,	   1,		 2,		   3.5,		 7,	      14);
// labels of the scale selector
$WinSizeLabels = array ( '12 Hours', '1 day', '2 days', '4 days', '1 week', '2 weeks', '1 month' );

$self = $_SERVER['PHP_SELF'];
session_start();
unset($_SESSION['nfsend']);

//
// Function definitions
//

function SendHeader () {

	global $self;
	$str = $_SESSION['tab'] == 4 ? strftime("%b %d %Y - %H:%M", $_SESSION['tleft']) : 'Overview';
	header("Content-type: text/html; charset=utf-8");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
	<title>NFSEN - Profile <?echo $_SESSION['profile'] . " $str";?></title>
	<meta HTTP-EQUIV="Cache-Control" content="no-cache">
<?php
	if ( $_SESSION['tab'] != 4 && $_SESSION['refresh'] > 0 ) {
		print "<meta HTTP-EQUIV='Refresh' CONTENT='" . $_SESSION['refresh'] . "; URL=$self?bookmark=" . $_SESSION['bookmark'] . "'>\n";
	}
?>
	<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<?php	include ("css.html");
	if ( $_SESSION['tab'] == 5 )
		include ("css-admin.html");
?>

</head>

<body>
<?php
	navigator();

} // End of SendHeader

function TimeSlotUpdate () {

	global $WinSizeScale;
	global $RRDoffset;

	/* 
	 * make sure tend exists.
	 * tend is initialized when entering tab 4 the first time, either from tabs 1, 2 or 3
	 * or from a bookmark. Otherwise tend needs to exists from other tab 4 runs.
	 * tend is the reference point in the graph.
	 */
	if ( !isset($_SESSION['tend']) ) 
		$_SESSION['tend'] = $_SESSION['profileinfo']['tend'];

	// make sure the tend mark is with the profile data
	if ( ($_SESSION['tend'] > $_SESSION['profileinfo']['tend']) ||
		 ($_SESSION['tend'] < $_SESSION['profileinfo']['tstart']) ) 
		$_SESSION['tend'] = $_SESSION['profileinfo']['tend'];

	/* 
	 * scale factor of the graph. The unit is number of 5min slots/px
	 * WinSizeScale defines all available scales. 
	 * The default for the graphs is 1 day => scale = 0.5
	 */
	$scale  = $WinSizeScale[$_SESSION['wsize']];

	/*
	 * start of the graph
	 */
	$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;	// see scale factor

	/*
	 * Mark update: The tleft/tright markers are set by the following user inputs:
	 * - click into the graph
	 * - adjust graph by the button controls '>' ">>" etc.
	 * - enter the tleft marker into text field
	 */

	// remember current timespan
	$span = $_SESSION['tright'] - $_SESSION['tleft'];	

	// process clicks into the graph

	if ( isset($_GET['coord']) ) {
		$coord	  = $_GET['coord'];
		list ($x, $y ) = split ( ',', $coord ) ;
		list ($trash, $x ) = split ( '\?', $x ) ;
		#
		# x may be any value between $RRDoffset and $RRDoffset + 576. This is any valid timeslot within the graph
		if ( is_numeric($x) && ( $x >= $RRDoffset && $x <= ($RRDoffset+576) ) ) {	
			$x = (int)$x;
			// for debugging
			$_SESSION['x'] = $x;
			$offset = (int)(( $x - $RRDoffset ) * $scale ) * 300;		// offset in UNIX sec from tstart
			if ( array_key_exists('rightmark', $_SESSION ) && ($_SESSION['rightmark'] == 1) ) {
				# mouse click to set right mark
				$_SESSION['tright'] = $_SESSION['tstart'] + $offset;
				$_SESSION['rightmark'] = 0;
				unset($_SESSION['rightmark']);
			} else {
				# mouse click to set left mark
				$_SESSION['tleft']  = $_SESSION['tstart'] + $offset;
				$_SESSION['tright']	= $_SESSION['tleft'] + $span;
			}

			if ( $_SESSION['tright'] < $_SESSION['tleft'] ) {
				$_tmp = $_SESSION['tright'];
				$_SESSION['tright'] = $_SESSION['tleft'];
				$_SESSION['tleft']  = $_tmp;
			}

			// adjust tleft if beyond end of profile
			if ($_SESSION['tleft'] < $_SESSION['profileinfo']['tstart'] ) {
				$_SESSION['tleft']  = $_SESSION['profileinfo']['tstart'];
				$_SESSION['tright'] = $_SESSION['tleft'] + $span;	
				SetMessage('warning', "Mark outside available timeframe");
			}
			// adjust tright if beyond end of profile
			if ($_SESSION['tright'] > $_SESSION['profileinfo']['tend'] ) {
				$_SESSION['tright'] = $_SESSION['profileinfo']['tend'];
				SetMessage('warning', "Mark outside available timeframe");
			}
		} else {
				$_left  = UNIX2DISPLAY($_SESSION['profileinfo']['tstart']);
				$_right = UNIX2DISPLAY($_SESSION['profileinfo']['tend']);
				SetMessage('warning', "Please select a timeslot between '$_left' and '$_right'");
		}
	}

	// process adjust buttons
	if ( isset($_POST['adjust']) ) {
		$_tmp = $_POST['adjust'];
		switch($_tmp) {
			case ">":
				if ( ($_SESSION['tright'] + 300 ) <= $_SESSION['profileinfo']['tend']) {
					$_SESSION['tleft']  += 300;	// increase one 5 min slice
					$_SESSION['tright'] += 300;	// increase one 5 min slice
				} else {
					SetMessage('error', "Mark outside available timeframe");
				}
				break;
			case "<":
				if ( ($_SESSION['tleft'] - 300 ) >= $_SESSION['profileinfo']['tstart']) {
					$_SESSION['tleft']  -= 300;	// decrease one 5 min slice
					$_SESSION['tright'] -= 300;	// decrease one 5 min slice
				} else {
					SetMessage('error', "Mark outside available timeframe");
				}
				break;
			case "<<":
				// shift tleft left by a full windowsize;
				if ( ($_SESSION['tleft'] - $scale * 172800) >= $_SESSION['profileinfo']['tstart'] ) {
					// if tleft is within profile, then tend is also within profile
					$_SESSION['tleft']	-= $scale * 172800;
					$_SESSION['tright']	-= $scale * 172800;
					$_SESSION['tstart'] -= $scale * 172800;
					$_SESSION['tend']	-= $scale * 172800;
				} else {
					SetMessage('error', "Mark outside available timeframe");
				}
				break;
			case ">>":
				// shift tleft right by a full windowsize;
				if ( ($_SESSION['tright'] + $scale * 172800) <= $_SESSION['profileinfo']['tend'] ) {
					// tright is still within profile boundaries
					$_SESSION['tleft']	+= $scale * 172800;
					$_SESSION['tright']	+= $scale * 172800;
					$_SESSION['tstart'] += $scale * 172800;
					$_SESSION['tend']	+= $scale * 172800;
				} else {
					SetMessage('error', "Mark outside available timeframe");
				}
				break;
			case ">|":
					// move to end of profile
					$_SESSION['tend']	= $_SESSION['profileinfo']['tend'];
					$_tmp = $_SESSION['profileinfo']['tend'] - $_SESSION['tright'];
					$_SESSION['tright']	= $_SESSION['profileinfo']['tend'];
					$_SESSION['tleft']	= $_SESSION['tleft'] + $_tmp;
					$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;	// see scale
				break;
			case "|":
				// center tleft, if possible, otherwise move as much as we can
				$_tmp = ($scale * 172800 - ( $_SESSION['tright'] - $_SESSION['tleft']) ) >>1;
				// shift only multiple of 5min units
				$_tmp -= $_tmp % 300;
				if (( $_SESSION['tright'] + $_tmp ) > $_SESSION['profileinfo']['tend'] ) {
					$_SESSION['tend'] = $_SESSION['profileinfo']['tend'];
				} else {
					$_SESSION['tend'] = $_SESSION['tright'] + $_tmp;
				}
				$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;
				break;
			case "^":
				$max_timeslot = FindMaxValue();
				if ( $max_timeslot ) {
					$_SESSION['tleft']  = $max_timeslot;
					$_SESSION['tright'] = $max_timeslot;
				} else {
					SetMessage('error', "Could not find max time slot");
				}
				break;
			case "Reset Timeslot":
				// clear right mark
				$_SESSION['tright']	= $_SESSION['tleft'];
				break;
		}
	}

	// process data input field
	if ( isset($_POST['tleft']) ) {
		$_tmp = DISPLAY2UNIX($_POST['tleft']);
		if ( $_tmp > 0 ) {
			// make sure we fall at the beginning of a 5min slot
			$_SESSION['tleft'] = $_tmp - ($_tmp % 300);

			// if tleft is outside the profile, set tleft to end of profile
			if ( ($_SESSION['tleft'] < $_SESSION['profileinfo']['tstart'])  || 
				 ($_SESSION['tleft'] > $_SESSION['profileinfo']['tend'])) {
				$_SESSION['tleft'] = $_SESSION['profileinfo']['tend'];
				SetMessage('error', "Mark outside available timeframe");
			}

			// set the right mark with old timespam
			$_SESSION['tright'] = $_SESSION['tleft'] + $span;
			if ( $_SESSION['tright'] > $_SESSION['profileinfo']['tend'] ) {
				$_SESSION['tright']  = $_SESSION['profileinfo']['tend'];
				SetMessage('warning', "Time span truncated");
			}

			// now adjust tstart and tend
			$_SESSION['tend'] = $_SESSION['tleft'] + $scale * 86400;
			if ( $_SESSION['tend'] > $_SESSION['profileinfo']['tend'] )
				$_SESSION['tend']	= $_SESSION['profileinfo']['tend'];
			$_SESSION['tstart']	= $_SESSION['tend'] - $scale * 172800;

			// center the graph
			$_tmp = ($scale * 172800 - ( $_SESSION['tright'] - $_SESSION['tleft']) ) >>1;
			// shift only multiple of 5min units
			$_tmp -= $_tmp % 300;
			if (( $_SESSION['tright'] + $_tmp ) > $_SESSION['profileinfo']['tend'] ) {
				$_SESSION['tend'] = $_SESSION['profileinfo']['tend'];
			} else {
				$_SESSION['tend'] = $_SESSION['tright'] + $_tmp;
			}
			$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;
		}
	}

	if ( isset($_POST['tright']) ) {
		$_tmp = DISPLAY2UNIX($_POST['tright']);
		if ( $_tmp > 0 ) {
			// make sure we fall at the beginning of a 5min slot
			$_SESSION['tright'] = $_tmp - ( $_tmp % 300);

			// if tright is outside the profile, reset tright to tleft + 300
			if ( ($_SESSION['tright'] < $_SESSION['profileinfo']['tstart'])  || 
				 ($_SESSION['tright'] > $_SESSION['profileinfo']['tend'])) {
				$_SESSION['tright']	= $_SESSION['tleft'] + $span;
				SetMessage('error', "Mark outside available timeframe");
			}

			// check if timespan is larger, than we can display with current wsize
			if ( ( $_SESSION['tright'] - $_SESSION['tleft'] ) > ($scale * 172800) ) {
				$_SESSION['tright']	= $_SESSION['tleft'] + $span;
				SetMessage('warning', "Out of range for right mark");
			}

			// center the graph
			$_tmp = ($scale * 172800 - ( $_SESSION['tright'] - $_SESSION['tleft']) ) >>1;
			// shift only multiple of 5min units
			$_tmp -= $_tmp % 300;
			if (( $_SESSION['tright'] + $_tmp ) > $_SESSION['profileinfo']['tend'] ) {
				$_SESSION['tend'] = $_SESSION['profileinfo']['tend'];
			} else {
				$_SESSION['tend'] = $_SESSION['tright'] + $_tmp;
			}
			$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;
		}
	}

	// make sure right > left
	if ( $_SESSION['tright'] < $_SESSION['tleft'] ) {
		$_tmp = $_SESSION['tright'];
		$_SESSION['tright'] = $_SESSION['tleft'];
		$_SESSION['tleft']  = $_tmp;
	}

	/*
	* Follow me:
	* If the tleft is within 10% of the left or right margin
	* adjust the graph and move the tleft into the middle of
	* the graph
	*/
	$margin = 8640 * $scale;	// 10% of graph
	$offset = ($scale * 172800 - ( $_SESSION['tright'] - $_SESSION['tleft']) ) >>1;
	// shift only multiple of 5min units
	$offset -= $offset % 300;
	if ((($_SESSION['tright'] > ($_SESSION['tend'] - $margin)) ||
		 ($_SESSION['tleft'] < ($_SESSION['tstart'] + $margin))) && 
		(($_SESSION['tright'] + $offset) < $_SESSION['profileinfo']['tend']) ) {
		$_SESSION['tend'] = $_SESSION['tright'] + $offset;
		$_SESSION['tstart'] = $_SESSION['tend'] - $scale * 172800;
	} 

} // End of TimeSlotUpdate


function ParseInput () {

	global $PROFILESTATDIR;
	global $VARDIR;
	global $DisplayOrder;
	global $TypeOrder;
	global $ListNOption;
	global $TopNOption;
	global $IPStatOption;
	global $IPStatOrder;
	global $WinSizeScale;
	global $LimitScale;
	global $OutputFormatOption;

	// these session vars are packed into the bookmark
	$BookmarkVars =  array ( 'tab', 'plugin_tab', 'profile', 'sourcelist', 'proto', 'type', 
							 'wsize', 'tend', 'tleft', 'tright', 'logscale', 'ratesclae', 'linegraph');

	/* 
	 * user input may come from forms or links ( POST or GET data ) due to normal
	 * form processing. If a bookmark is specified in the URL, this overwrites other
	 * input data. To simplify data input checks, an intermediate daary $_input is used
	 */

	if ( !isset($_SESSION['channels'])  ) {
		$_SESSION['channels'] = array();
	}
	$channels = $_SESSION['channels'];

	if ( isset($_GET['bookmark']) ) {
		// process bookmarkstring
		$_vars = explode( '|', base64_decode(urldecode($_GET['bookmark']) ));
		if ( count($BookmarkVars) == count($_vars) ) {
			for ( $i=0; $i<count($BookmarkVars); $i++ ) {
				if ( $_vars[$i] != '-' ) 
					$_input[$BookmarkVars[$i]] = $_vars[$i];
			}
		} else {
			SetMessage('warning', "Bookmark error");
		}
	} else {
		// process GET and POST vars
		if ( isset($_GET['tab']) ) 
			$_input['tab'] = $_GET['tab'];

		if ( isset($_GET['plugin_tab']) ) 
			$_input['plugin_tab'] = $_GET['plugin_tab'];

		if ( isset($_POST['profile']) )
			$_input['profile'] = $_POST['profile'];

		if ( isset($_GET['proto']) )
			$_input['proto'] = $_GET['proto'];

		if ( isset($_GET['type']) )
			$_input['type'] = $_GET['type'];

		if ( isset($_POST['wsize']) )
			$_input['wsize'] = $_POST['wsize'];

		if ( isset($_POST['mselect']) ) {
			$_tmp = $_POST['mselect'];
			if ( $_tmp == 1 )
				$_SESSION['rightmark'] = 1;
			else {
				$_SESSION['rightmark'] = 0;
				unset($_SESSION['rightmark']);
			}
		}

		if ( isset($_POST['ratescale']) )
			$_input['ratescale'] = $_POST['ratescale'];

		if ( isset($_POST['logscale']) )
			$_input['logscale'] = $_POST['logscale'];

		if ( isset($_POST['linegraph']) )
			$_input['linegraph'] = $_POST['linegraph'];

		// process sources. 'sourcetrigger' is a hidden field, always present to
		// trigger this block
		if ( isset($_POST['srctrigger']) ) {
			$_src = array();
			if ( isset($_POST['MultipleSources']) ) {
				$_selected = $_POST['MultipleSources'] == 'All' ? 1 : 0;
				for ($i=0; $i<count($channels); $i++) {
					$_src[$i] = $_selected;
				}
			} else {
				for ($i=0; $i<count($channels); $i++) {
					$_src[$i] = array_key_exists($channels[$i], $_POST) ? 1 : 0;
				}
			}
			$_input['sourcelist'] = implode(':', $_src);
		}
	}

	// Make sure tab exists
	if ( !isset($_SESSION['tab']) )
		$_SESSION['tab'] = 0;

	if ( !isset($_SESSION['plugin_tab']) )
		$_SESSION['plugin_tab'] = 0;

	/* 
	 * Merge the $_input vars into the current session
	 */

	// process tab - tab is required
	if ( isset($_input['tab']) ) {
		$_tab = $_input['tab'];
		if ( ! is_numeric($_tab) && ( ($_tab > count($TabList)) || ($_tab < 0) ) ) {
			$_tab = 0;
		}
		$_tab = (int)$_tab;
		// if we change directly from 'home' to 'details', remember to init the 
		// SESSION details 
		if ( ($_SESSION['tab'] == 0 || $_SESSION['tab'] == 5 || $_SESSION['tab'] == 6 ) && $_tab == 4 ) {
			$_SESSION['init'] = 'flows';
		}
		// when entering tab 5, from any other tab, make sure we have an up to date
		// ProfileList, as profiles may have been manipulated from the cmd line.
		if ( $_SESSION['tab'] != 5 && $_tab == 5 ) {
			unset($_SESSION['ProfileList']);
			unset($_SESSION['PluginList']);
			GetProfiles();
			GetPlugins();
			DefaultFilters();
		}
		$_SESSION['tab'] = $_tab;
	}

	// process plugin tab
	if ( isset($_input['plugin_tab']) ) {
		$plugins  = GetPlugins ();
		$_tab = $_input['plugin_tab'];
		if ( ! is_numeric($_tab) && ( ($_tab > count($plugins)) || ($_tab < 0) ) ) {
			$_tab = 0;
		}
		$_SESSION['plugin_tab'] = $_tab;
	}

	// process type
	if ( isset($_input['type']) ) {
		foreach ( $TypeOrder as $type ) {
			if ( $_input['type'] == $type ) {
				$_SESSION['type'] = $_input['type'];
			}
		}
	} 

	// Make sure profile is set
	if ( !isset($_SESSION['profile']) )
		$_SESSION['profile'] = 'live';
	
	$datfile = "$PROFILESTATDIR/" . $_SESSION['profile'] . "/profile.dat";
	if ( !file_exists($datfile) ) {
		SetMessage('error', "Selected profile " . $_SESSION['profile'] . " does not exist. Switch to profile 'live'");
		$_SESSION['profile'] = 'live';
		// Force rebuild of profilelist
		unset($_SESSION['ProfileList']);
	}

	// process profile - profile is required
	if ( isset($_input['profile']) ) {
		$_profile = $_input['profile'];
		// force tab 5 to create a new profile
		if ( $_profile == "New Profile ..." ) {
			$_SESSION['tab']   = 5;
			$_SESSION['admin'] = 'new';
		} elseif ( !strpos($_profile, '/') && file_exists("$PROFILESTATDIR/$_profile/profile.dat") ) {
			// if we changed profile, init this profile
			if ( $_SESSION['profile'] != $_profile ) {
				$_SESSION['init'] = array_key_exists('type', $_SESSION ) ? $_SESSION['type'] : 'flows';
			}
			$_SESSION['profile'] = $_profile;
		}
	}

	// process proto
	if ( isset($_input['proto']) ) {
		foreach ( $DisplayOrder as $proto ) {
			if ( $_input['proto'] == $proto ) {
				$_SESSION['proto'] = $_input['proto'];
			}
		}
	}

	// process src - sourcelist
	if ( isset($_input['sourcelist']) ) {
		$_src = explode(':', $_input['sourcelist']);
		$_SESSION['src'] = array();
		for ( $i=0; $i < count($channels); $i++ ) {
			if ( is_numeric($_src[$i]) && ( $_src[$i] == 0  || $_src[$i] == 1 ) ) {
				$_SESSION['src'][$i] = $_src[$i];
			} else
				$_SESSION['src'][$i] = 1;
		}
		$_SESSION['sourcelist'] = implode(':', $_SESSION['src']);	// for the bookmark only
	}

	// process tend
	if ( isset($_input['tend']) )
		$_SESSION['tend'] = $_input['tend'];

	// process tleft
	if ( isset($_input['tleft']) )
		$_SESSION['tleft'] = $_input['tleft'];

	// process tright
	if ( isset($_input['tright']) )
		$_SESSION['tright'] = $_input['tright'];

	// process wsize
	if ( isset($_input['wsize']) ) {
		if ( is_numeric($_input['wsize']) && ($_input['wsize'] < count($WinSizeScale)) &&
		($_input['wsize'] >= 0) )
			$_SESSION['wsize'] = $_input['wsize'];
	}

	// process ratescale
	if ( isset($_input['ratescale']) ) {
		if ( is_numeric($_input['ratescale']) && ($_input['ratescale'] > 0) )
			$_SESSION['ratescale'] = 1;
		else
			$_SESSION['ratescale'] = 0;
	}

	// process logscale
	if ( isset($_input['logscale']) ) {
		if ( is_numeric($_input['logscale']) && ($_input['logscale'] > 0) )
			$_SESSION['logscale'] = 1;
		else
			$_SESSION['logscale'] = 0;
	}

	// process linegraph
	if ( isset($_input['linegraph']) ) {
		if ( is_numeric($_input['linegraph']) && ($_input['linegraph'] > 0) )
			$_SESSION['linegraph'] = 1;
		else
			$_SESSION['linegraph'] = 0;
	}

	$profileinfo = ReadProfile($_SESSION['profile']);
	if ( $profileinfo == FALSE ) {
		SetMessage('warning', "Reset to profile live");
	}

	$_SESSION['profileinfo'] = $profileinfo;
	$channels = explode(':', $profileinfo['sourcelist']);
	$_SESSION['channels'] = $channels;

	$disable_refresh = $_SESSION['tab'] == 6 || (array_key_exists('admin', $_SESSION) && $_SESSION['admin']);
	if ( !$disable_refresh && $profileinfo['type'] == 0 || $profileinfo['type'] == 2 )
		$_SESSION['refresh'] = 300;
	else 
		$_SESSION['refresh'] = 0;
		

	// Unless a bookmark was specified
	// if we enter tab 4 ( detailed view ) initilize some values to defaults
	// init contains the type, we want to start with.
	if ( array_key_exists('init', $_SESSION) && !isset($_GET['bookmark']) ) {
		$_SESSION['type']	   = $_SESSION['init'];
		$_SESSION['proto']	   = 'any';
		$_SESSION['wsize']	   = 1;		// index 1 into WinSizeLabels is 1 day - the default
		$_SESSION['ratescale'] = 1;
		$_SESSION['logscale']  = 0;
		$_SESSION['linegraph'] = 0;
		$_SESSION['tend']	   = $_SESSION['profileinfo']['tend'];
		if (($_SESSION['tend'] - 43200) < $_SESSION['profileinfo']['tstart'] )
			// the middle of the graph is outside the profile, so set the mark 
			// to the beginning of the profile
			$_SESSION['tleft']  = $_SESSION['profileinfo']['tstart'];	
		else
			// set the tleft to the middle of the graph
			$_SESSION['tleft']  = $_SESSION['tend'] - 43200;
		$_SESSION['tright'] = $_SESSION['tleft'];
		$_SESSION['src']	= array();

		#
		$_tmparray = explode(':', $_SESSION['profileinfo']['sourcelist']);
		foreach ( $_tmparray as $source ) {
			$_profilesources[$source] = 1;
		}
		for ( $i=0; $i<count($channels); $i++ ) {
			$_SESSION['src'][] = array_key_exists($channels[$i], $_profilesources ) ? 1 : 0;
		}

		$_SESSION['sourcelist'] = implode(':', $_SESSION['src']);	// for the bookmark only
		if ( !array_key_exists('defaultfilters', $_SESSION ) )
			DefaultFilters();
		$_SESSION['p_defaultfilter'] = -1;
		// clear init tag
		unset($_SESSION['init']);
	}

	// only relevant in detailed tab
	if ( $_SESSION['tab'] == 4 ) 
		TimeSlotUpdate();

	// only relevant in admin tab
	if ( $_SESSION['tab'] == 5 ) {
		// Edit expire value?
		if ( array_key_exists('edit_expire_x', $_POST ))
			$_SESSION['edit_expire'] = 1;
		// Edit max size value?
		if ( array_key_exists('edit_maxsize_x', $_POST ))
			$_SESSION['edit_maxsize'] = 1;
		// when the user enters the <enter> button instead of clicking
		// the enter button provided, most browsers take the first element
		// in the form, and pretend, that this was selected. This may produce 
		// incorrect results, therefore I introduced a webbug button 'EnterKey'
		// which results in the same action
		if ( array_key_exists('EnterKey_x', $_POST ) ||
			array_key_exists('edit', $_POST ) ) {
			$_SESSION['admin'] = 'change';
			$_tmp = ParseMaxSize($_POST['profile_maxsize']);
			if ( strlen($_tmp) > 0 )
				$_SESSION['new_maxsize'] = $_tmp;
			else
				SetMessage('warning', "Invalid value for maxsize");
			$_tmp = ParseExpire($_POST['profile_expire']);
			if ( $_tmp >= 0 )
				$_SESSION['new_expire'] = $_tmp;
			else
				SetMessage('warning', "Invalid value for expire");
		}
		// Delete this profile ?
		if ( array_key_exists('deleteprofile_x', $_POST ) ||
			 array_key_exists('confirmdelete', $_POST ))
			$_SESSION['admin'] = 'delete';
		// Cancel create oder delete profile
		if ( array_key_exists('cancel', $_POST ) || 
			 array_key_exists('new_cancel', $_POST )) {
			unset($_SESSION['delete_profile']);
			unset($_SESSION['delete_requested']);
			unset($_SESSION['new_profile']);
		}
		// create a new profile ?
		if ( array_key_exists('new_create', $_POST ) ||
			 array_key_exists('new_create_x', $_POST )) {
			$_SESSION['admin'] = 'new';
			$errstr = '';	// preset error string
			$_profile = $_POST['new_profilename'];
			$_found = 0;
			foreach ( $_SESSION['ProfileList'] as $p ) 
				if ( $p == $_profile )
					$_found = 1;
			if ( $_found ) 
				$errstr .= "<br>Profile '$_profile' already exists";
			else {
				if ( preg_match("/[^A-Za-z0-9\-+_]+/", $_profile ))
					$errstr .= "<br>Profile name '$_profile' contains illegal characters";
				elseif ( mkdir("/tmp/$_profile", 0700)) {
					rmdir("/tmp/$_profile");
					$_SESSION['new_profile']['profilename'] = $_profile;
				} else {
					$errstr .= "<br>Profile name '$_profile': Can't create test directory";
				}
			}

			// Profile start time
			$_tmp = $_POST['new_tstart'];
			if ( strlen($_tmp) > 0 ) {
				$_tmp = DISPLAY2UNIX($_tmp);
				if ( $_tmp > 0 )
					$_SESSION['new_profile']['tstart'] = $_POST['new_tstart'];
				else
					$errstr .= "<br>Start time '" . $_POST['new_tstart'] . "': Invalid";
			}

			// Profile end time
			$_tmp = $_POST['new_tend'];
			if ( strlen($_tmp) > 0 ) {
				$_tmp = DISPLAY2UNIX($_tmp);
				if ( $_tmp > 0 )
					$_SESSION['new_profile']['tend'] = $_POST['new_tend'];
				else
					$errstr .= "<br>End time '" . $_POST['new_tend'] . "': Invalid";
			}
	
			if ( strlen($_SESSION['new_profile']['tend']) && strlen($_SESSION['new_profile']['tstart']) &&
					( $_SESSION['new_profile']['tend'] < $_SESSION['new_profile']['tstart'] ) )
				$errstr .= "<br>End time '" . $_SESSION['new_profile']['tend'] . "' earlier then Start time '" .
							$_SESSION['new_profile']['tstart'] . "'";

			// netflow sources
			if ( array_key_exists('new_sources', $_POST ) ) {
				$_tmp = array();
				foreach ( $_POST['new_sources'] as $source ) {
					if ( is_numeric($source) && $source < count($channels) ) {
						$source = (int)$source;
						$_tmp[] = $source;
					}
				}
				$_SESSION['new_profile']['sources'] = $_tmp;
				
			} else {
				$errstr .= "<br>Sources: Need at least 1 source";
			}

			// filter
			$filter = array_key_exists('new_filter', $_POST ) ? $_POST['new_filter'] : '';
			if ( strlen($filter) > 0 ) {
				$filter = preg_replace("/\r/", ' ', $filter);
				$filter = preg_replace("/\n/", ' ', $filter);
				$filter = escapeshellarg($filter);
				$ret = nfsend_query("nfdump args=-Z $filter", 0);
				if ( is_array($ret) ) {

					$cmdout = array_shift($ret);

					if ( strlen($cmdout) > 0 ) {
							$errstr .= "<br>Filter syntax: $cmdout";
					}
					$_SESSION['new_profile']['filter'] = $_POST['new_filter'];	// redisplay the filter
				}
			} else {
				$errstr .= "<br>Missing profile filter";
			}


			// max profile size
			$_tmp = array_key_exists('new_maxsize', $_POST ) ? $_POST['new_maxsize'] : '0';
			if ( strlen($_tmp) > 0 ) {
				$str = ParseMaxSize($_tmp);
				if ( strlen($str) > 0 )
					$_SESSION['new_profile']['maxsize'] = $str;
				else
					$errstr .= "<br>Max Size: '$_tmp' invalid";
			}

			// expire time
			$_tmp = array_key_exists('new_expire', $_POST ) ? $_POST['new_expire'] : '0';
			if ( strlen($_tmp) > 0 ) {
				$str = ParseExpire($_tmp);
				if ( $str >= 0 )
					$_SESSION['new_profile']['expire'] = $str;
				else
					$errstr .= "<br>Expire time: '$_tmp' invalid";
			}

			// description
			$_SESSION['new_profile']['description'] = $_POST['new_description'];
			if ( strlen($errstr) )
				SetMessage('error', $errstr);
			else
				$_SESSION['admin'] = 'execnew';


		}
		// refresh time if profile building in progress
		if ( !array_key_exists('admin', $_SESSION ) &&
			preg_match("/built/", $_SESSION['profileinfo']['status']) ) {
			$_SESSION['refresh'] = 5;
		}
	} else {	// tab != 5
		// unset in any other case these session vars
		if ( array_key_exists('delete_profile', $_SESSION ))
			unset($_SESSION['delete_profile']);
		if ( array_key_exists('delete_requested', $_SESSION ))
			unset($_SESSION['delete_requested']);
		if ( array_key_exists('new_profile', $_SESSION ))
			unset($_SESSION['new_profile']);
	}

	// process the input data from the netflow processing form
	if ( array_key_exists('dostat', $_POST) || array_key_exists('dolist', $_POST) ) {
		// Assume all arguments are valid. If not, it will be reset to 0
		$argsOK = 1;

		// process sourcelist
		if ( !array_key_exists('srcselector', $_POST )) {
			SetMessage('error', "Select at least one source for netflow processing");
			$argsOK = 0;
		} else {
			$_src = array();
			for ($i=0; $i<count($channels); $i++ ) 
				$_src[$i] = 0;
			for ($i=0; $i<count($_POST['srcselector']); $i++ ) {
				$_tmp = $_POST['srcselector'][$i];
				if ( is_numeric($_tmp) && ($_tmp >= 0) && ($_tmp < count($channels) ) )
					$_tmp = (int)$_tmp;
					$_src[$_tmp] = 1;
			}
			$_SESSION['p_sources'] = $_src;
		}

		// process default filter
		if ( array_key_exists('defaultfilter', $_POST ) && 
			 array_key_exists('defaultfilters', $_SESSION ) ) {
			$_tmp = $_POST['defaultfilter'];
			if ( $_tmp >= -1 && $_tmp < count($_SESSION['defaultfilters']) ) {
				$_SESSION['p_defaultfilter'] = $_tmp;
			}
		}

		// check the syntax of the filter
		if ( array_key_exists('filter', $_POST )) {
			$filter = preg_replace("/\r/", '', $_POST['filter']);
			if ( array_key_exists('p_defaultfilter', $_SESSION) && 
				 array_key_exists('defaultfilters', $_SESSION ) && $_SESSION['p_defaultfilter'] >= 0 ) {
				$_tmp = $_SESSION['p_defaultfilter'];
				$defaultfilter =  file_get_contents("$VARDIR/filters/" . $_SESSION['defaultfilters'][$_tmp]);
				if ( strlen($filter) > 0 ) {
					if ( strlen($defaultfilter) > 0 )
						$filter = "( $filter ) and ( $defaultfilter )";
				} else 
					$filter = $defaultfilter;
			}
			$filter = escapeshellarg($filter);
			$filter = preg_replace("/\r/", ' ', $filter);
			$filter = preg_replace("/\n/", ' ', $filter);

			$ret = nfsend_query("nfdump args=-Z $filter", 0);
			if ( is_array($ret) ) {
				$cmdout = array_shift($ret);

				if ( strlen($cmdout) > 0 ) {
						SetMessage('error', "Filter syntax: $cmdout");
						$argsOK = 0;
				}
				$_SESSION['p_filter'] = $_POST['filter'];	// redisplay the filter
				$_SESSION['combinedfilter'] = $filter;
			}
		}

		// get number of flows to list
		if ( array_key_exists('listN', $_POST )) {
			$_tmp = $_POST['listN'];
			if ( $_tmp >=0 && $_tmp < count($ListNOption) ) {
				$_SESSION['p_listN'] = $_tmp;
			}
		}
		// get the top N value
		if ( array_key_exists('topN', $_POST )) {
			$_tmp = $_POST['topN'];
			if ( $_tmp >=0 && $_tmp < count($TopNOption) ) {
				$_SESSION['p_topN'] = $_tmp;
			}
		}
		// get the type of stat
		if ( array_key_exists('stattype', $_POST )) {
			$_tmp = $_POST['stattype'];
			if ( $_tmp >=0 && $_tmp < count($IPStatOption) ) {
				$_SESSION['p_stattype'] = $_tmp;
			}
		}
	
		// get the flow order
		if ( array_key_exists('floworder', $_POST )) {
			$_tmp = $_POST['floworder'];
			if ( $_tmp >=0 && $_tmp < count($IPStatOrder) ) {
				$_SESSION['p_floworder'] = $_tmp;
			}
		}

		// get the stat order
		if ( array_key_exists('statorder', $_POST )) {
			$_tmp = $_POST['statorder'];
			if ( $_tmp >=0 && $_tmp < count($IPStatOrder) ) {
				$_SESSION['p_statorder'] = $_tmp;
			}
		}
	
		// checkboxes
		$_SESSION['p_aggregate']   = array_key_exists('aggregate', $_POST ) ? 1 : 0;
		$_SESSION['p_timesorted']  = array_key_exists('timesorted', $_POST ) ? 1 : 0;
		$_SESSION['p_longoutput1'] = array_key_exists('longoutput1', $_POST ) ? 1 : 0;
		$_SESSION['p_IPv6_long1']  = array_key_exists('IPv6_long1', $_POST ) ? 1 : 0;
		$_SESSION['p_IPv6_long2']  = array_key_exists('IPv6_long2', $_POST ) ? 1 : 0;
		$_SESSION['p_flowstat']    = array_key_exists('flowstat', $_POST ) ? 1 : 0;
		$_SESSION['p_ipstat']      = array_key_exists('ipstat', $_POST ) ? 1 : 0;
		$_SESSION['p_limitoutput'] = array_key_exists('limitoutput', $_POST ) ? 1 : 0;

		if ( array_key_exists('dostat', $_POST) && ($_SESSION['p_flowstat'] + $_SESSION['p_ipstat'] == 0) ) {
			SetMessage('error', "Need at least one stat type: Packets/Bytes and/or IP stat");
			$argsOK = 0;
		}
		if ( array_key_exists('limitwhat', $_POST )) {
			$_tmp = $_POST['limitwhat'];
			if ( is_numeric($_tmp) && ( $_tmp == 0 || $_tmp == 1 ) )
				$_SESSION['p_limitwhat'] = $_tmp;
		}
		if ( array_key_exists('limithow', $_POST )) {
			$_tmp = $_POST['limithow'];
			if ( is_numeric($_tmp) && ( $_tmp == 0 || $_tmp == 1 ) )
				$_SESSION['p_limithow'] = $_tmp;
		}
		if ( array_key_exists('limitsize', $_POST )) {
			$_tmp = $_POST['limitsize'];
			if ( is_numeric($_tmp) && ($_tmp >= 0) )
				$_SESSION['p_limitsize'] = $_tmp; 
		}
		if ( array_key_exists('limitscale', $_POST )) {
			$_tmp = $_POST['limitscale'];
			if ( is_numeric($_tmp) && $_tmp >= 0 && $_tmp < count($LimitScale) )
				$_SESSION['p_limitscale'] = $_tmp; 
		}
		if ( array_key_exists('output_format1', $_POST )) {
			$_tmp = $_POST['output_format1'];
			if ( is_numeric($_tmp) && $_tmp >= 0 && $_tmp < count($OutputFormatOption) )
				$_SESSION['p_output_format1'] = $_tmp; 
		}
		if ( array_key_exists('output_format2', $_POST )) {
			$_tmp = $_POST['output_format2'];
			if ( is_numeric($_tmp) && $_tmp >= 0 && $_tmp < count($OutputFormatOption) )
				$_SESSION['p_output_format2'] = $_tmp; 
		}
		
		// set the flag to trigger processing
		if ( $argsOK ) 
			$_SESSION['process'] = 1;
	}

	// Generate bookmark
	$vars = array();
	foreach ( $BookmarkVars as $var ) {
		$vars[] = array_key_exists($var, $_SESSION) ? $_SESSION[$var] : '-';
	}

	$_SESSION['bookmark'] = urlencode(base64_encode(implode('|', $vars)));

} // End of ParseInput

////////////////////
// Main starts here
////////////////////

$globals = nfsend_query('globals', 0);
if ( !is_array($globals) ) {
	SetMessage('error', "Can not initialize globals");
	exit;
}
foreach ( $globals as $global ) {
	eval($global);
}

ParseInput();
nfsend_query("du", 0);

if ( $_SESSION['tab'] == 6 ) {
 	$plugins  = GetPlugins ();
	if ( count($plugins) > 0 ) {
		$plugin_name = $plugins[ $_SESSION['plugin_tab'] ];
		$include_file = "$FRONTEND_PLUGINDIR/$plugin_name" . ".php";
		include($include_file);
		$plugin_parse_input = $plugin_name . "_ParseInput";
		$plugin_run 	    = $plugin_name . "_Run";
		$errstr = '';
		if ( !function_exists($plugin_parse_input) ) {
			$errstr = $plugin_parse_input;
		}
		if ( !function_exists($plugin_run) ) {
			$errstr = "$errstr $plugin_run";
		}
		if ( $errstr != '' ) {
			SetMessage('error', "Missing plugin function $errstr");
			$plugin_run 	    = "Plugin_Error";
		} else {
			// Give the plugin a chance to Parse the plugin specific vars
			// The plugin may call SetMessage('error', ... SetMessage('warning', 
			call_user_func($plugin_parse_input, $_SESSION['plugin_tab'], $_SESSION['profile'] );
		}
	}
}

SendHeader();
ShowMessages();
	
// print "<pre>";
// print_r($_SESSION);
// print_r($_POST);
// print "</pre>";

switch ($_SESSION['tab']) {
	case "0":
		require ("overview.php");
		DisplayOverview($_SESSION['profile']);
		break;
	case "1":
		require ("overview.php");
		DisplayGraphs("flows", $_SESSION['profile']);
		break;
	case "2":
		require ("overview.php");
		DisplayGraphs("packets", $_SESSION['profile']);
		break;
	case "3":
		require ("overview.php");
		DisplayGraphs("traffic", $_SESSION['profile']);
		break;
	case "4":
		require ("details.php");
		DisplayDetails();
		break;
	case "5":
		require("profileadmin.php");
		DisplayAdminPage();
		break;
	case "6":
		//	Run the plugin
		if ( count($plugins) > 0 )
			call_user_func($plugin_run, $_SESSION['plugin_tab'], $_SESSION['profile'] );
		// otherwise do nothing
		break;
	default:
}

nfsend_disconnect();


?>
</body>
