<?
/*
TODO: 
 - Audit collapse animation is jerky and lame
 - Suppress errors in cron script and schedule
 - Cron script shouldn't wallop json files while it's running
 - Update styles and icons in UI when files are (un)ignored
 - Add option to show all ignores/acks
 - Add option to clear all ignores/acks
 - Adding directory aknowlegement could be useful for plugin 
   updates and new sites.
*/
require_once('template.php');

$errors  = array();
$sites   = array();
$slugs   = array();
$audits  = array();
$ignores = array();

$changed_files   = array();
$unacked_files   = array();
$unacked_scripts = array();
$unacked_sites   = array();

$audit_dir = 'json';

$warn_age = 1 * 24 * 60 * 60; # 1 day, 24 hours, or seconds

# need to keep this in sync with vhost-audit.pl
$scripts = array('/.php$/', '/.htaccess$/', '/.js$/');


$sites_file = 'sites.txt';
if ( ($sites = @file($sites_file, FILE_IGNORE_NEW_LINES)) !== FALSE ) {
	$site_count = count($sites);
	sort($sites);
}
else {
	$errors[] = 'Could not open sites file, ' . $sites_file;
}

foreach ($sites as $site) {
	$parts = explode('/', $site);
	$hostname = $parts[count($parts) -2];
	$slugs[$site] = preg_replace('/\./', '_', $hostname);
	$audit_file = $audit_dir . '/' . $hostname . '.json';
	$ignore_file = $audit_dir . '/' . $hostname . '-ignore.json';
	
	# pull in a site's ignore file
	if ( file_exists($ignore_file) ) {
		if ( ($ignore_json = @file_get_contents($ignore_file)) !== FALSE ) {
			$ignore_json = utf8_encode($ignore_json);
			$ignore = @json_decode($ignore_json, true);
			if ($ignore === null) {
				$ignore = array();
			}
			$ignores[$site] = $ignore;
		}
		else {
			$errors[] = 'Could not open ignore file, ' . $ignore_file;
		}
	}

	# pull in a site's audit file
	if ( file_exists($audit_file) ) {
		if ( ($audit_json = @file_get_contents($audit_file)) !== FALSE ) {
			$audit_json = utf8_encode($audit_json);
			$audit = @json_decode($audit_json, true);
			if ($audit === null) {
				$audit = array('data' => array());
			}
			ksort($audit['data']);
			foreach ( array_keys($audit['data']) as $date) {
				if ( is_array($audit['data'][$date]['files']) ) {
					ksort($audit['data'][$date]['files']);
				}
				else {
					$audit['data'][$date]['files'] = array();
				}
				
				foreach ( $audit['data'][$date]['files'] as $file => $action ) {
					$dir = dirname($file);
					if (substr($dir, -1) !== '/') {
						$dir .= '/';
					}
					$audit['data'][$date]['files'][$file] 
						= array('action' => $action);
					if ( isset($ignores[$site][$file]) ) {
						if ( $ignores[$site][$file]['action'] == 'acknowledge' ) {
							if ( $ignores[$site][$file]['date'] > $date ) {
								$audit['data'][$date]['files'][$file]['status'] 
									= 'acknowledge';
							}
						}
						elseif ( $ignores[$site][$file]['action'] == 'ignore_file' ) {
							$audit['data'][$date]['files'][$file]['status'] 
								= 'ignore_file';
						}
					}
					elseif ( isset($ignores[$site][$dir]['action']) ) {
						$audit['data'][$date]['files'][$file]['status'] 
							= 'ignore_dir';
					}
					else {
						$unacked_files[] = $site . $file;
						
						$is_script = false;
						foreach ($scripts AS $script) {
							if ( preg_match($script, $file) ) {
								$is_script = true;
								break;
							}
						}
						if ( $is_script ) {
							$unacked_scripts[] = $site . $file;
							$unacked_sites[$site] = true;
						}
					}
					
				}
			}
			$lastrun = $audit['lastrun'];

			$audits[$site] = $audit;
		}
		else {
			$errors[] = 'Could not open audit file, ' . $audit_file;
		}
	}
	else {
		$errors[] = "Audit file ($audit_file) not found";
	}
	
	$tot_changes += $audit['changes'];
	$tot_scripts += $audit['scripts'];
}

#print_r($unacked_scripts);exit;
$tot_unacked_changes = count($unacked_files);
$tot_unacked_scripts = count($unacked_scripts);
$unacked_sites = array_keys($unacked_sites);

#echo('<pre>Audits: ');
#print_r($audits);
#echo('Ignores: ');
#print_r($ignores);
#echo('</pre>');
#exit;

if ( $_SERVER['HTTP_ACCEPT'] == 'application/json' || $_SERVER['CONTENT_TYPE'] == 'application/json') {
	if ( $tot_unacked_scripts == 0 ) {
		$message = 'OK';
	}
	else {
		$message = 'Unacknowledged script changes in: ' . join(', ', $unacked_sites);
	}
	
	header('Content-type: application/json');
	$response = array(
		'sites'            => $site_count, 
		'changes'          => $tot_changes, 
		'scripts'          => $tot_scripts, 
		'unacked_changes'  => $tot_unacked_changes, 
		'unacked_scripts'  => $tot_unacked_scripts, 
		'unacked_sites'    => $unacked_sites, 
		'message'          => $message
	);
	echo(json_encode($response, JSON_PRETTY_PRINT));
	exit;
}
else {
	$T = new Template('templates/index.php');
	$T->set('errors', $errors);
	$T->set('message', $message);
	$T->set('sites', $sites);
	$T->set('site_count', $site_count);
	$T->set('slugs', $slugs);
	$T->set('ignores', $ignores);
	$T->set('audits', $audits);
	$T->set('warn_age', $warn_age);
	$T->set('scripts', $scripts);
	$T->set('tot_changes', $tot_changes);
	$T->set('tot_scripts', $tot_scripts);
	$T->set('tot_unacked_changes', $tot_unacked_changes);
	$T->set('tot_unacked_scripts', $tot_unacked_scripts);
	$T->set('unacked_sites', $unacked_sites);
	echo($T->fetch());
	exit;
}

?>
