<?php

//
// Common functions
//

function nfsen_run ( $args ) {

	global $BINDIR;

	$run = "$BINDIR/nfsen -q $args";
	$fh = popen("$run 2>&1", 'r');
	$result = array();
	$status = '';
	while ( $line = rtrim(fgets($fh, 1024)) ) {
		if ( preg_match("/^OK|ERR/", $line ) ) {
			$status = $line;
			if ( preg_match("/^ERR/", $line ) )
				$_SESSION['error'] = $line;
		} else 
			$result[] = $line;
	}
	pclose($fh);

	$_SESSION['nfsen_status'] = $status;
	$_SESSION['nfsen_return'] = $result;
	return preg_match("/^OK/", $status) ? true : false;

} // End of nfsen_run

function nfdump_run ( $args ) {

	global $PREFIX;

	$run = "$PREFIX/nfdump $args";
	$fh = popen("$run 2>&1", 'r');
	$result = array();
	$status = '';
	while ( $line = rtrim(fgets($fh, 1024)) ) {
		$result[] = $line;
	}
	pclose($fh);

	$_SESSION['nfdump_return'] = $result;

} // End of nfdump_run

function UNIX2ISO ($time) {

	$tmp = localtime($time);
	$tstring  = $tmp[5] + 1900;
	$tmp[4]  += 1;
	$tstring .= $tmp[4] < 10 ? "0" . $tmp[4] : $tmp[4];
	$tstring .= $tmp[3] < 10 ? "0" . $tmp[3] : $tmp[3];
	$tstring .= $tmp[2] < 10 ? "0" . $tmp[2] : $tmp[2];
	$tstring .= $tmp[1] < 10 ? "0" . $tmp[1] : $tmp[1];

	return $tstring;

} // End of UNIX2ISO

function ISO2UNIX ($time) {

	// 2004 02 13 12 45 /
	preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/", $time, $matches);
	$unixtime = mktime ( $matches[4], $matches[5], 0, $matches[2], $matches[3], $matches[1]);

	return $unixtime;

} // End of ISO2UNIX

function DISPLAY2UNIX($str) {

	$_tmp = preg_replace("/-/", "", $str);

	$_len = strlen($_tmp);
	if ( $_len < 12 || $_len > 12 )
		return -1;

	if ( preg_match("/[^\d]+/", $_tmp ))
		return -1;

	if ( is_numeric($_tmp) && $_tmp > 197001010000 && $_tmp < 203801191414 ) {
		$_tmp = ISO2UNIX($_tmp);
	} else
		$_tmp = -1;

	return $_tmp;

} // End of DISPLAY2UNIX

function UNIX2DISPLAY($time) {
	// converts any UNIX time in display readable format:
	// 2004-02-13-12-45
	
	$iso = UNIX2ISO($time);

	return preg_replace("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/", "$1-$2-$3-$4-$5", $iso);

} // End of UNIX2DISPLAY

function ScaleValue ( $value, $rateval ) {

	if ( $rateval != 1 ) {
		$value = $value / $rateval;
		$rate_label = '/s';	// make bits
	} else {
		$rate_label = '';
	}

	$_1KB = 1024.0;
	$_1MB = 1024.0 * $_1KB;
	$_1GB = 1024.0 * $_1MB;
	$_1TB = 1024.0 * $_1GB;

	$scaled = 0;
	if ( $value >= $_1TB ) {
		$scaled = $value / $_1TB;
		$unit = "T";
	} elseif ( $value >= $_1GB ) {
		$scaled = $value / $_1GB;
		$unit = "G";
	} elseif ( $value >= $_1MB ) {
		$scaled = $value / $_1MB;
		$unit = "M";
	} elseif ( $value >= $_1KB ) {
		$scaled = $value / $_1KB;
		$unit = "K";
	} else {
		$scaled = $value;
		$unit = " ";
	}
	if ( $scaled > 0 )
		$str = sprintf("%5.1f %s%s", $scaled, $unit, $rate_label);
	else
		$str = "$value ${unit}${rate_label}";

	return preg_replace("/^\s+/", "", $str);
	

} // End of ScaleValue

function ScaleBytes ( $value, $rateval ) {

	if ( $rateval != 1 ) {
		$value = $value / $rateval * 8;
		$rate_label = '/s';	// make bits
		$Bit_Byte   = 'b';
	} else {
		$rate_label = '';
		$Bit_Byte   = 'B';
	}

	$_1KB = 1024.0;
	$_1MB = 1024.0 * $_1KB;
	$_1GB = 1024.0 * $_1MB;
	$_1TB = 1024.0 * $_1GB;

	$scaled = 0;
	if ( $value >= $_1TB ) {
		$scaled = $value / $_1TB;
		$unit = "T";
	} elseif ( $value >= $_1GB ) {
		$scaled = $value / $_1GB;
		$unit = "G";
	} elseif ( $value >= $_1MB ) {
		$scaled = $value / $_1MB;
		$unit = "M";
	} elseif ( $value >= $_1KB ) {
		$scaled = $value / $_1KB;
		$unit = "K";
	} else {
		$scaled = $value;
		$unit = " ";
	}
	if ( $scaled > 0 )
		$str = sprintf("%5.1f %s%s%s", $scaled, $unit, $Bit_Byte, $rate_label);
	else
		$str = "$value ${unit}${Bit_Byte}${rate_label}";

	return preg_replace("/^\s+/", "", $str);
	
} // End of ScaleBytes

//
// Plugin related functions
//

function Plugin_Error( $plugin_id ) {
	
	print "<h3>Plugin Error! Can't run plugin</h3>\n";

} // End of Plugin_Error

function GetPlugins () {

	if ( array_key_exists('PluginList', $_SESSION ) ) {
		if ( array_key_exists('PluginListUpdate', $_SESSION ) && 
		( time() - $_SESSION['PluginListUpdate'] < 600 ) ) {
			return $_SESSION['PluginList'];
		}
	}

	$plugins = nfsen_run("-P");
	if ( $plugins ) {
		$plugins   = $_SESSION['nfsen_return'];
	} else {
		$plugins = array();
	}
	$_SESSION['PluginList'] = $plugins;
	$_SESSION['PluginListUpdate'] = time();

	return $plugins;

} // End of GetPlugins

//
// Profile related functions
//

function GetProfiles () {

	if ( array_key_exists('ProfileList', $_SESSION ) ) {
		if ( array_key_exists('ProfileListUpdate', $_SESSION ) && 
		( time() - $_SESSION['ProfileListUpdate'] < 600 ) ) {
			return $_SESSION['ProfileList'];
		}
	}

	$profiles = nfsen_run("-A");
	if ( $profiles ) {
		$profiles   = $_SESSION['nfsen_return'];
		$profiles[] = "New Profile ...";
	} else {
		$profiles = array();
		$profiles[] = "&lt;No profiles available&gt;";
	}
	$_SESSION['ProfileList'] = $profiles;
	$_SESSION['ProfileListUpdate'] = time();

	return $profiles;

} // End of GetProfiles

function ReadProfile ($profile) {
	global $PROFILESTATDIR;

/*
	* this code below can be used to read the profile using nfsen_run
	* As open the profile.dat file and read the profile info directly seems more 
	* efficient, this code remains commented and is not used today
	*
	$args = "-l $profile";
	if ( nfsen_run($args);) 
		return false;

	foreach ( $SESSION['nfsen_return'] as $line ) {
		// Skip rubish lines
		if ( !preg_match("/|/", $line) ) {
			continue;
		}

		list ($key, $value) = explode("|", $line);
		if ( $key == 'description' ) {
			// replace escape chars in description and remove '#' tag on each line
			$value = preg_replace("/\\\\012/", "\n", $value);
			$value = preg_replace("/\\\\047/",  "'", $value);
			$value = preg_replace("/\\\\174/",  "|", $value);
			$value = preg_replace("/\\\\134/", "\\", $value);
			$value = preg_replace("/^# /", "", $value);
			$value = preg_replace("/\n# /", "\n", $value);
			$profileinfo['comment'] = explode("\n", $value);
		} else 
			$profileinfo[$key] = $value;
	}
	return $profileinfo;
*/

	$fh = @fopen("$PROFILESTATDIR/$profile/profile.dat", "r");
	if ( !$fh ) {
		return array();
	}

	$comment = array();
	while ( $line = rtrim(fgets($fh, 1024)) ) {

		// grab comment
		if ( preg_match("/^#/", $line) ) {
			$comment[] = preg_replace("/^#\s{0,1}/", "", $line);
			continue;
		}

		// Skip empty lines
		if ( !preg_match("/=/", $line) ) {
			continue;
		}

		// Read profile info
		$line = preg_replace("/\s*=\s*/", '=', $line);
		list ($key, $value) = explode("=", $line);
		$profileinfo[$key] = $value;
	}
	fclose($fh);
	$profileinfo['comment'] = $comment;

	return $profileinfo;

} // End of ReadProfile

function ShowMessages () {

	if ( array_key_exists('warning', $_SESSION ) ) {
		print "<h3 class='warnstring'>WARNING: " . $_SESSION['warning'] . "!</h3>\n";
		unset($_SESSION['warning']);
	}

	if ( array_key_exists('error', $_SESSION ) ) {
		print "<h3 class='errstring'>ERROR: " . $_SESSION['error'] . "!</h3>\n";
		unset($_SESSION['error']);
	}

} // End of ShowMessages

function ReadStat($source) {

	global $PROFILEDATADIR;

	// indices into array
	// 0  Time: 1075888800
	// 1  Ident: swiix1
	// 2  Flows: 2010696
	// 3  Flows_tcp: 2010696
	// 4  Flows_udp: 0
	// 5  Flows_icmp: 0
	// 6  Flows_other: 0
	// 7  Packets: 32534108
	// 8  Packets_tcp: 32534108
	// 9  Packets_udp: 0
	// 10 Packets_icmp: 0
	// 11 Packets_other: 0
	// 12 Bytes: 19871469109
	// 13 Bytes_tcp: 19871469109
	// 14 Bytes_udp: 0
	// 15 Bytes_icmp: 0
	// 16 Bytes_other: 0
	// 17 First: 1075887894
	// 18 Last: 1075889096


	$profile = $_SESSION['profile'];
	if ( $_SESSION['tleft'] != $_SESSION['tright'] ) {
		$t = $_SESSION['tleft'];
		$tslot1 = UNIX2ISO($t);
		$t = $_SESSION['tright'];
		$tslot2 = UNIX2ISO($t);
		$datafile = "-R $PROFILEDATADIR/$profile/$source/nfcapd.$tslot1:nfcapd.$tslot2";
	} else {
		$t=$_SESSION['tleft'];
		$tslot = UNIX2ISO($t);
		$datafile = "-r $PROFILEDATADIR/$profile/$source/nfcapd.$tslot";
	}

	$ret = nfdump_run("$datafile -I");
	$statinfo = $_SESSION['nfdump_return'];

	// old style nfdump files
	if ( count ($statinfo) > 19 ) {
		array_unshift($statinfo, $t);
	}
	$SumStat = array();
	foreach ( $statinfo as $line ) {
		list ($dummy, $value) = explode(": ", $line);
		$SumStat[] = $value;
	}

	return $SumStat;

} // End of ReadStat 

function FindMaxValue() {

	global $PROFILEDATADIR;

	$profile = $_SESSION['profile'];
	$max_value = 0;
	$max_timeslot = 0;

	$index = 2;
	if ( $_SESSION['type'] == 'flows' ) 
		$index = 2;
	if ( $_SESSION['type'] == 'packets' ) 
		$index = 7;
	if ( $_SESSION['type'] == 'traffic' ) 
		$index = 12;

	$index_offset = 0;
	if ( $_SESSION['proto'] == 'TCP' )
		$index_offset = 1;
	if ( $_SESSION['proto'] == 'UDP' )
		$index_offset = 2;
	if ( $_SESSION['proto'] == 'ICMP' )
		$index_offset = 3;
	if ( $_SESSION['proto'] == 'other' )
		$index_offset = 4;

	$index = $index + $index_offset;
	$_tmparray = explode(':', $_SESSION['graph_sources']);

	for ( $t=$_SESSION['tleft'] - 3600; $t <= $_SESSION['tleft'] + 3600; $t += 300 ) {
		$tslot = UNIX2ISO($t);

		$sum = 0;
		foreach ( $_tmparray as $source ) {
			$statfile = "$PROFILEDATADIR/$profile/$source/nfcapd.$tslot";
			$ret = nfdump_run("-r $statfile -I");
			$tmp = $_SESSION['nfdump_return'];
		
			// old style nfdump files
			if ( count ($tmp) > 19 ) {
				array_unshift($tmp, $t);
			}
			$statinfo = array();
			foreach ( $tmp as $line ) {
				list ($dummy, $value) = explode(": ", $line);
				$statinfo[] = $value;
			}

			if ( $_SESSION['linegraph'] ) {
				if ( $statinfo[$index] > $sum ) 
					$sum = $statinfo[$index];
			} else {
				$sum += $statinfo[$index];
			}
		}
		if ( $sum > $max_value ) {
			$max_value = $sum;
			$max_timeslot = $t;
		}
	}

	return $max_timeslot;

} // End of FindMaxValue

function DefaultFilters () {

	global $VARDIR;

	$FilterDir = "$VARDIR/filters";
	$dh = opendir($FilterDir);

	if ( !$dh ) {
		// No filter dir. return silently => no default filters
		return;
	}
	
	$filters = array();
	while (($entry = readdir($dh)) !== false) {
		if ( is_file("$FilterDir/$entry") ) {
			$filters[] = $entry;
		}
	}
	closedir($dh);
	$_SESSION['defaultfilters'] = $filters;

} // End of DefaultFilters

/*
 * Parse the expire input string and set new_expire as the number of hours
 * for this profiles new expire value.
 * valid form:
 *	<num>				number of hours
 * 	<num> h|hour|hours	number of hours
 *	<num> d|day|days	number of days
 *	<num> d|day|days <num> h|hour|hours	combination days and hours
 * returns the number of hours of new expire or -1 if string unparsable
 */
function ParseExpire ($str) {

	$new_expire = 0;
	$valid		= 0;	// we found a valid string

	$str = preg_replace( array( '/^\s+/s', '/\s+$/s'), array( '', ''), $str);
	// a single number: add 'h'
	if ( is_numeric($str) ) {
		$str = (int)$str;
		$str .= "h";
	}

	// normalize the input string. Replace 'never' with 0h
	$str  = preg_replace("/never/i", "0h", $str);

	// normalize the input string. Replace all day, days with 'd'
	$str  = preg_replace("/days/i", "d", $str);
	$str  = preg_replace("/day/i", "d", $str);

	// normalize the input string. Replace all hour, hours with 'h'
	$str  = preg_replace("/hours/i", "h", $str);
	$str  = preg_replace("/hour/i", "h", $str);

	// now parse the string
	preg_match("/(\d+\.{0,1}\d*)\s*d/", $str, $matches);
	if ( count($matches) == 2 ) { 	// at least 2 entries are required
		$new_expire = (int)($matches[1] * 24);
		$valid = 1;
	}
	preg_match("/(\d+)\s*h/", $str, $matches);
	if ( count($matches) == 2 ) {	// at least 2 entries are required
		$new_expire += $matches[1];
		$valid = 1;
	}
	
	return $valid ? $new_expire : -1;

} // End of ParseExpire

/*
 * parse new max size.
 * valid form:
 *	<num>	defaults to num MB
 * 	<num><scale>	<scale> : K[B], M[B], G[B], and T[B]
 * returns the number of bytes of new max size or -1 if string unparsable
 */
function ParseMaxSize ($str) {

	$valid		 = 0;	// we found a valid string

	$str = preg_replace( array( '/^\s+/s', '/\s+$/s'), array( '', ''), $str);
	if ( $str == 'unlimited' ) 
		$str = "0";

	// a single number: add 'M'
	if ( is_numeric($str) ) {
		$str = (int)$str;
		$str .= "M";
	}

	// normalize the input string. Strip 'B'
	$str  = preg_replace("/B/", "", $str);

	preg_match("/(\d+\.{0,1}\d*)\s*([K|M|G|T])/", $str, $matches);
	if ( count($matches) == 3 ) {	// at least 3 entries are required
		if ( is_numeric($matches[1]) ) {
			$valid = 1;
		}
	}

	$str = preg_replace("/\s+/", '', $str);
	
	return $valid ? $str : '';

} // End of ParseMaxSize

?>
