#!/usr/bin/php -q
<?php
//	License for all code of this FreePBX module can be found in the license file inside the module directory
//	Copyright 2006-2014 Schmooze Com Inc.
//

if (version_compare(PHP_VERSION, '5.3.0', '<')) {
	echo "FreePBX Requires PHP Version 5.3.0 or Higher, you have: ".PHP_VERSION."\n";
	die();
}

date_default_timezone_set('America/Los_Angeles');
require_once ("libfreepbx.install.php");
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/php-upgrade.functions.php');
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/sql.functions.php');
require_once(dirname(__FILE__) . '/amp_conf/htdocs/admin/libraries/utility.functions.php');

# constants
define("AMP_CONF", "/etc/amportal.conf");
define("ASTERISK_CONF", "/etc/asterisk/asterisk.conf");
define("UPGRADE_DIR", dirname(__FILE__)."/upgrades");
define("MODULE_DIR", dirname(__FILE__)."/amp_conf/htdocs/admin/modules/");

# semi constants
$webroot	= "/var/www/html";
$ampsbin_dir = "/usr/local/sbin";	// default if not set
$ampbin_dir = "/var/lib/asterisk/bin";
$asterisk_user	= "asteriskuser";
$asterisk_pass	= "amp109";

/********************************************************************************************************************/

function showHelp() {
	out("Optional parameters:",false);
	out("  --help, -h, -?           Show this help",false);
	out("  --dbhost <ip address>    Use a remote database server",false);
	out("  --dbname databasename    Use database name specified, instead of 'asterisk'",false);
	out("  --username <user>        Use <user> to connect to db and write config",false);
	out("  --password <pass>        Use <pass> to connect to db and write config",false);
	out("  --freepbxip <ip>         FreePBX web interface is accessed from <ip>",false);
	out("  --webroot <path>         Web root where FreePBX will be installed",false);
	out("  --cgibin <path>          Path where cgi-bin's lives",false);
	out("  --bin <path>             Path of asterisk binaries",false);
	out("  --sbin <path>            Path of system admin binaries",false);
	out("  --asteriskuser <user>    Asterisk Manager username",false);
	out("  --asteriskpass <pass>    Asterisk Manager password",false);
	out("  --asteriskip <ip>        Asterisk Manager IP address",false);
	out("  --debug                  Enable debug output",false);
	out("  --dry-run                Don't actually do anything",false);
	out("  --force-version <ver>    Force upgrade from version <ver>",false);
	out("  --skip-module-install    Don't run install scripts for packaged modules, the files are still loaded.",false);
	out("                           In a development environment you may not want the install scripts run.",false);
	out("  --no-files               Just run updates without installing files",false);
	out("  --force-overwrite        Don't ask if it is ok to overwrite modified files, assume yes for all.",false);
	out("  --install-moh            Install default music-on-hold files (normally doesn't, unless ",false);
	out("                           it's a new installation)",false);
	out("  --dev-links              Make links to files in the source directory instead of copying",false);
	out("                           (intended for developers only)",false);
	out("  --update-links           Update dev links without running through the whole install process (Bail before modules)", false);
	out("  --engine <name>          Use the specified PBX Engine ('asterisk')",false);
	out("  --uid <user>             Set ownership of files to user",false);
	out("  --gid <group>            Set ownership of files to group",false);
	out("  --scripted               Scripted install. Do not ask any questions.",false);
	out("                           (Intended for unattended installers only)",false);
	out("  --set-freepbx-settings   Force set the internal FreePBX DB Settings with install time parameters",false);
	out("  --installdb              Set up the FreePBX database",false);
	out("  --cleaninstall           Like 'make clean' will clean up any previous settings or previous setup while installing a-new",false);
	out("  --uninstall              Completely Uninstall FreePBX",false);
}

function install_parse_amportal_conf($filename) {
	$file = file($filename);
	foreach ($file as $line) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$line,$matches)) {

			// TODO: force booleans into 0/1 this should be ok given the limited number of configuration values
			//
			switch (trim(strtolower($matches[2]))) {
				case 'false':
				case 'no':
				case 'off':
				case '0':
					$conf[$matches[1]] = '0';
				case 'true':
				case 'yes':
				case 'on':
				case '1':
					$conf[$matches[1]] = '1';
				default:
					$conf[$matches[1]] = $matches[2];
				break;
			}
		}
	}

	// use same defaults as function.inc.php
	if ( !isset($conf["AMPDBENGINE"]) || ($conf["AMPDBENGINE"] == "")) {
		$conf["AMPDBENGINE"] = "mysql";
	}

	if ( !isset($conf["AMPDBNAME"]) || ($conf["AMPDBNAME"] == "")) {
		$conf["AMPDBNAME"] = "asterisk";
	}

	if ( !isset($conf["AMPENGINE"]) || ($conf["AMPENGINE"] == "")) {
		$conf["AMPENGINE"] = "asterisk";
	}
	out("parsed amp_conf variables from $filename:");
	foreach ($conf as $keyword => $value) {
		out("amp_conf [$keyword] => [$value]");
	}

	return $conf;
}

function install_parse_asterisk_conf($filename) {
	$file = file($filename);
	foreach ($file as $line) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s* (?:=>|=) \s*(.*)\s*([;#].*)?/",$line,$matches)) {
			$conf[ $matches[1] ] = $matches[2];
		}
	}
	// Now set defaults if not set (although asterisk should fail if not set but at least
	// it will get the setup somewhat right
	//
	if (!isset($asterisk_conf['astetcdir']))    { $asterisk_conf['astetcdir']    = "/etc/asterisk"; }
	if (!isset($asterisk_conf['astmoddir']))    { $asterisk_conf['astmoddir']    = "/usr/lib/asterisk/modules"; }
	if (!isset($asterisk_conf['astvarlibdir'])) { $asterisk_conf['astvarlibdir'] = "/var/lib/asterisk"; }
	if (!isset($asterisk_conf['astagidir']))    { $asterisk_conf['astagidir']    = "/var/lib/asterisk/agi-bin"; }
	if (!isset($asterisk_conf['astspooldir']))  { $asterisk_conf['astspooldir']  = "/var/spool/asterisk"; }
	if (!isset($asterisk_conf['astrundir']))    { $asterisk_conf['astrundir']    = "/var/run/asterisk"; }
	if (!isset($asterisk_conf['astlogdir']))    { $asterisk_conf['astlogdir']    = "/var/log/asterisk"; }

	return $conf;
}

function write_amportal_conf($filename, $conf) {
	$file = file($filename);
	// parse through the file
	foreach (array_keys($file) as $key) {
		if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$file[$key],$matches)) {
			// this is an option=value line
			if (isset($conf[ $matches[1] ])) {
				// rewrite the line, if we have this in $conf
				$file[$key] = $matches[1]."=".$conf[ $matches[1] ]."\n";
				// unset it so we know what's new
				unset($conf[ $matches[1] ]);
			}
		}
	}

	// add new entries
	foreach ($conf as $key=>$val) {
		$file[] = $key."=".$val."\n";
	}

	// write the file
	if (!$fd = fopen($filename, "w")) {
		fatal("Could not open ".$filename." for writing");
	}
	fwrite($fd, implode("",$file));
	fclose($fd);
}

function ask_overwrite($file1, $file2) {
	global $check_md5s;
	do {
		out($file2." has been changed from the original version.");
		outn("Overwrite (y=yes/a=all/n=no/d=diff/s=shell/x=exit)? ");
		$key = fgets(STDIN,1024);
		switch (strtolower($key[0])) {
			case "y": return true;
			case "a": $check_md5s=false; return true;
			case "n": return false;
			case "d":
				out("");
				// w = ignore whitespace, u = unified
				passthru("diff -wu ".escapeshellarg($file2)." ".escapeshellarg($file1));
			break;
			case "s":
				if (function_exists("pcntl_fork")) {
					out("");
					$shell = (isset($_ENV["SHELL"]) ? $_ENV["SHELL"] : "/bin/bash");
					out("Dropping to shell. Type 'exit' to return");
					out("-> Original file:  ".$file2);
					out("-> New file:       ".$file1);

					$pid = pcntl_fork();
					if ($pid == -1) {
						out("[ERROR] cannot fork");
					} else if ($pid) {
						// parent
						pcntl_waitpid($pid, $status);
						// we wait till the child exits/dies/whatever
					} else {
						pcntl_exec($shell, array(), $_ENV);
					}

					out("Returned from shell");
				} else {
					out("[ERROR] PHP not built with process control (--enable-pcntl) support: cannot spawn shell");
				}

			break;
			case "x":
				out("-> Original file:  ".$file2);
				out("-> New file:       ".$file1);
				out("Exiting install program.");
				exit(1);
			break;
		}
		out("");
	} while(1);
}

/** Write AMP-generated configuration files
*/
function generate_configs() {
	global $amp_conf;
	global $dryrun;
	global $debug;
	global $runas_uid;

	out("Generating Configurations.conf, (if Asterisk is not running, you will get an error)");
	out("In case of error, start Asterisk and hit the red bar in the GUI to generate the Configurations.conf files");
	if (!$dryrun) {
		// added --run-install to make it work like it has been working since retrieve_conf changed to not run module install scripts by default

		//
		// TODO: Should check if Asterisk is running and/or try to start it.
		//
		passthru("sudo -u $runas_uid ".trim($amp_conf["AMPBIN"])."/retrieve_conf --run-install --skip-registry-checks ".($debug ? ' --debug' : ''));
	}
}


/** Collect AMP settings */
function collect_settings($filename, $dbhost = '', $dbuser = '', $dbpass = '', $dbname = 'asterisk') {
	global $webroot;
	global $ampsbin_dir;
	global $ampbin_dir;
	global $asterisk_user;
	global $asterisk_pass;
	global $scripted;
	global $freepbxip;
	global $asteriskip;
	global $runas_uid;
	global $runas_gid;
	global $asterisk_user;
	global $asterisk_pass;

	out("Creating new $filename");

	if ($scripted == true) {
		# Scripted install. Everything should have been set for us, don't ask questions.
		out("Scripted install. Accepting command line params.");
		$amp_conf["AMPDBUSER"] = $dbuser;
		$amp_conf["AMPDBPASS"] = $dbpass;
		$amp_conf["AMPDBHOST"] = $dbhost;
		$amp_conf["AMPDBNAME"] = $dbname;
		$amp_conf["AMPMGRUSER"] = $asterisk_user;
		$amp_conf["AMPMGRPASS"] = $asterisk_pass;
		$amp_conf["AMPWEBROOT"] = $webroot;
		$amp_conf["AMPWEBADDRESS"] = $freepbxip;
		$amp_conf["ASTMANAGERHOST"] = $asteriskip;
		$amp_conf["AMPEXTENSIONS"] = "extensions";
		$amp_conf["AMPBIN"] = $ampbin_dir;
		$amp_conf["AMPSBIN"] = "$ampsbin_dir";
		$amp_conf["AMPASTERISKWEBUSER"] = $runas_uid;
		$amp_conf["AMPASTERISKWEBGROUP"] = $runas_gid;
		$amp_conf["AMPASTERISKUSER"] = $runas_uid;
		$amp_conf["AMPASTERISKGROUP"] = $runas_gid;
		$amp_conf["AMPDEVUSER"] = $runas_uid;
		$amp_conf["AMPDEVGROUP"] = $runas_gid;
		write_amportal_conf($filename, $amp_conf);
		outn(AMP_CONF." written");
		return;
	}

	outn("Enter your USERNAME to connect to the '$dbname' database:\n [".($dbuser ? $dbuser : $asterisk_user) . "] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPDBUSER"] = ($dbuser ? $dbuser : $asterisk_user);
	} else {
		$amp_conf["AMPDBUSER"] = $key;
	}

	outn("Enter your PASSWORD to connect to the '$dbname' database:\n [".($dbpass ? $dbpass : $asterisk_pass)."] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPDBPASS"] = ($dbpass ? $dbpass : $asterisk_pass);
	} else {
		$amp_conf["AMPDBPASS"] = $key;
	}

	outn("Enter the hostname of the '$dbname' database:\n [".($dbhost ? $dbhost : "localhost")."] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPDBHOST"] = ($dbhost ? $dbhost : "localhost");
	} else {
		$amp_conf["AMPDBHOST"] = $key;
	}

	outn("Enter a USERNAME to connect to the Asterisk Manager interface:\n [admin] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPMGRUSER"] = "admin";
	} else {
		$amp_conf["AMPMGRUSER"] = $key;
	}

	$rs = substr(md5(rand()), 0, 5);
	outn("Enter a PASSWORD to connect to the Asterisk Manager interface:\n [amp111] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPMGRPASS"] = "amp111";
	} else {
		$amp_conf["AMPMGRPASS"] = $key;
	}

	do {
		out("Enter the path to use for your AMP web root:\n [$webroot] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key)) {
			$amp_conf["AMPWEBROOT"] = "$webroot";
			if (amp_mkdir($amp_conf["AMPWEBROOT"],"0755",true)){
				out("Created ".$amp_conf["AMPWEBROOT"]);
				break;
			} else {
				fatal("Cannot create ".$amp_conf["AMPWEBROOT"]."!");
			}
		} else {
			$amp_conf["AMPWEBROOT"] = rtrim($key,'/');

			//regression follows us all around freepbx #6159
			$webroot = $amp_conf["AMPWEBROOT"];

			if (is_dir($amp_conf["AMPWEBROOT"])) {
				break;
			} else if (amp_mkdir($amp_conf["AMPWEBROOT"],"0755",true)){
				out("Created ".$amp_conf["AMPWEBROOT"]);
				break;
			} else {
				fatal("Cannot create ".$amp_conf["AMPWEBROOT"]."!");
			}
		}
	} while(1);


	outn("Enter the IP ADDRESS or hostname used to access the AMP web-admin:\n [$freepbxip] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPWEBADDRESS"] = $freepbxip;
	} else {
		$amp_conf["AMPWEBADDRESS"] = $key;
	}

	outn("Use simple Extensions [extensions] admin or separate Devices and Users [deviceanduser]?\n [extensions] ");
	$key = trim(fgets(STDIN,1024));
	if (preg_match('/^$/',$key)) {
		$amp_conf["AMPEXTENSIONS"] = "extensions";
	} else {
		$amp_conf["AMPEXTENSIONS"] = $key;
	}

	do {
		out("Enter directory in which to store AMP executable scripts:\n [$ampbin_dir] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key)) {
			$amp_conf["AMPBIN"] = $ampbin_dir;
		} else {
			$amp_conf["AMPBIN"] = rtrim($key,'/');
		}

		if (is_dir($amp_conf["AMPBIN"])) {
			break;
		} else if (amp_mkdir($amp_conf["AMPBIN"],"0755",true)){
			out("Created ".$amp_conf["AMPBIN"]);
			break;
		} else {
			fatal("Cannot create ".$amp_conf["AMPBIN"]."!");
		}
	} while(1);

	do {
		out("Enter directory in which to store super-user scripts:\n [$ampsbin_dir] ");
		$key = trim(fgets(STDIN,1024));
		if (preg_match('/^$/',$key)) {
			$amp_conf["AMPSBIN"] = "$ampsbin_dir";
		} else {
			$amp_conf["AMPSBIN"] = rtrim($key,'/');
		}

		if (is_dir($amp_conf["AMPSBIN"])) {
			break;
		} else if (amp_mkdir($amp_conf["AMPSBIN"],"0755",true)){
			out("Created ".$amp_conf["AMPSBIN"]);
			break;
		} else {
			fatal("Cannot create ".$amp_conf["AMPSBIN"]."!");
		}
	} while(1);

	// write amportal.conf
	write_amportal_conf($filename, $amp_conf);
	outn(AMP_CONF." written");
}

/** Set base of packaged modules to the versions packaged in the tarball since they are
*  getting overwritten with the tarball from anything that may have been updated online.
*
*/
function set_base_version() {
	global $dryrun;

	// read modules list from MODULE_DIR
	//
	$included_modules = array();
	$dir = opendir(MODULE_DIR);
	while ($file = readdir($dir)) {
		if ($file[0] != "." && $file[0] != "_" && is_dir(MODULE_DIR."/".$file)) {
			$included_modules[] = $file;
		}
	}
	closedir($dir);

	foreach ($included_modules as $up_module) {
		outn("Checking $up_module.. ");
		if (!$dryrun) {
			out(set_module_version($up_module));
		} else {
			out("Dry Run Not Updated");
		}
	}
}

/** Install all modules packaged with the install. We use the force flag because the
*  the assumption is that the dependencies are met and the package is able to have
*  the modules installed.
*/
function install_modules() {
	global $dryrun;
	global $amp_conf;

	// read modules list from MODULE_DIR
	//
	$included_modules = array();
	$dir = opendir(MODULE_DIR);
	while ($file = readdir($dir)) {
		if ($file[0] != "." && $file[0] != "_" && is_dir(MODULE_DIR."/".$file)) {
			$included_modules[] = $file;
		}
	}
	closedir($dir);

	$output = array();
	$keep_checking = true;
	$num_modules = false;
	while ($keep_checking && count($included_modules)) {
		if ($num_modules === count($included_modules)) {
			$keep_checking = false;
		} else {
			$num_modules = count($included_modules);
		}
		foreach ($included_modules as $id => $up_module) {
			outn("Checking $up_module.. ");
			if (!$dryrun) {
				// if $keep_checking then check dependencies first and skip if not met
				// otherwise we will install anyhow even if some dependencies are not met
				// since it is included. (TODO: should we not?)
				//
				if ($keep_checking) {
					exec($amp_conf['AMPBIN']."/module_admin --no-warnings checkdepends $up_module",$output,$retval);
					unset($output);
					if ($retval) {
						out("dependencies pending");
						continue;
					}
				}
				// Framework modules cannot be enabled, only installed.
				//
				switch ($up_module) {
					case 'framework':
					case 'fw_ari':
						system($amp_conf['AMPBIN']."/module_admin --no-warnings -f install $up_module");
						out("installed");
					break;
					default:
						system($amp_conf['AMPBIN']."/module_admin --no-warnings -f install $up_module");
						system($amp_conf['AMPBIN']."/module_admin --no-warnings -f enable $up_module");
						out("installed");
				}
				unset($included_modules[$id]);
			} else {
				out("Dry Run Not Installed");
			}
		}
	}
}

/** Set the module version number to the packaged version and enable
*  module must require not install.php or install.sql script
*  this is primarily to package core and framework with FreePBX tarballs
*
*/
function set_module_version($module) {
	global $db;

	$module_dir = MODULE_DIR;
	$file_path = $module_dir.$module."/module.xml";
	if (file_exists($file_path)) {
		// TODO: this is bad, there are other version tags (depends on) but this
		//       is equivalnet to what publish.pl does, so it expects this to be
		//       at the top.
		//
		$module_xml = file_get_contents($file_path);
		if (preg_match('/<version>(.+)<\/version>/', $module_xml, $matches)) {
			$version = $matches[1];
		} else {
			fatal("ERROR: $file_path found but no version information");
		}
	} else {
		return  "not packaged, no updating needed";
	}

	// If we didn't return above, then we found the package as part of the install
	// tarball and want to update the version info since this might be overwriting
	// an existing install that has a newer version.
	//
	$sql = "SELECT version FROM modules WHERE modulename = '$module'";
	$result = $db->getCol($sql);
	if(DB::IsError($result)) {
		fatal("error accessing version table: ".$result->getMessage());
	}
	$sql = "";
	if (count($result) == 0) {
		// insert but disable as we have to first run install scripts which come later
		$sql = "INSERT INTO modules (modulename, version, enabled) VALUES ('$module', '$version', 0)";
	} else if ($result[0] != $version) {
		if (version_compare_freepbx($version, $result[0], "gt")) {
			// if new version is greater than old, then we disable the module and it will get enabled next when installed
			//
			$sql = "UPDATE modules SET version = '$version', enabled = 0 WHERE modulename = '$module'";
		} else {
			// if new version is equal to or less than old, then we leave it in the enable/disable state it was in but just
			// reset the version number.
			//
			$sql = "UPDATE modules SET version = '$version' WHERE modulename = '$module'";
		}
	}
	if ($sql) {
		debug($sql);
		$result = $db->query($sql);
		if(DB::IsError($result)) {
			fatal("error writing to version table: ".$result->getMessage());
		}
		return "updated to $version";
	} else {
		return "already at $version";
	}
}

function installampimport_mysql_dump($file,$db=NULL) {
	if(!isset($db)) {
		global $db;
	}

	$dir = dirname(__FILE__);
	if(file_exists($dir.'/SQL/'.$file)) {
		// Temporary variable, used to store current query
		$templine = '';
		// Read in entire file
		$lines = file($dir.'/SQL/'.$file);
		// Loop through each line
		foreach ($lines as $line) {
			// Skip it if it's a comment
			if (substr($line, 0, 2) == '--' || $line == '') {
				continue;
			}

			// Add this line to the current segment
			$templine .= $line;
			// If it has a semicolon at the end, it's the end of the query
			if (substr(trim($line), -1, 1) == ';') {
				// Perform the query
				$result = $db->query($templine);
				if(DB::IsError($result)) {
					fatal("Error performing query: ". $templine . " Message:".$result->getMessage());
				}
				// Reset temp variable to empty
				$templine = '';
			}
		}
	}
}

/********************************************************************************************************************/

//
// TODO: will this work, basically using bootstrap once installed if using to upgrade, etc?
/*
$bootstrap_settings['skip_astman']) = true;
$bootstrap_settings['freepbx_auth'] = false;
$restrict_mods = true;
if (@include_once(getenv('FREEPBX_CONF') ? getenv('FREEPBX_CONF') : '/etc/freepbx.conf')) {
out(_("FreePBX already installed, bootstrapping"));
} else if (@include_once('/etc/asterisk/freepbx.conf')) {
out(_("FreePBX already installed, bootstrapping"));
} else {
// all the initialization here instead
}
*/

// **** Make sure we have STDIN etc

// from  ben-php dot net at efros dot com   at  php.net/install.unix.commandline
if (version_compare(phpversion(),'4.3.0','<') || !defined("STDIN")) {
	define('STDIN',fopen("php://stdin","r"));
	define('STDOUT',fopen("php://stdout","r"));
	define('STDERR',fopen("php://stderr","r"));
	register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );
}

// **** Make sure we have PEAR's DB.php, and include it

outn("Checking for PEAR DB..");
if (! @ include('DB.php')) {
	out("FAILED");
	fatal("PEAR must be installed (requires DB.php). Include path: ".ini_get("include_path"));
}
out("OK");

// **** Make sure we have PEAR's GetOpts.php, and include it

outn("Checking for PEAR Console::Getopt..");
if (! @ include("Console/Getopt.php")) {
	out("FAILED");
	fatal("PEAR must be installed (requires Console/Getopt.php). Include path: ".ini_get("include_path"));
}
out("OK");

// **** Parse out command-line options
$shortopts = "h?u:p:";
$longopts = array(
	"asteriskip=",
	"asteriskpass=",
	"asteriskuser=",
	"bin=",
	"cgibin=",
	"cleaninstall",
	"dbhost=",
	"dbname=",
	"debug",
	"dev-links",
	"dry-run",
	"engine=",
	"fopwebroot=",
	"force-overwrite",
	"force-version=",
	"freepbxip=",
	"gid=",
	"help",
	"install-moh",
	"installdb",
	"make-links-devel",
	"no-files",
	"password=",
	"sbin=",
	"scripted",
	"set-freepbx-settings",
	"skip-module-install",
	"uid=",
	"uninstall",
	"update-links",
	"username=",
	"webroot=",
);

$args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
if (is_object($args)) {
	// assume it's PEAR_ERROR
	out($args->message);
	exit(255);
}

$debug = false;
$dryrun = false;
$install_files = true;
$override_astvers = false;
$scripted = false;

$install_moh = false;
$make_links = false;
$update_links = false;
$module_install = true;
$set_freepbx_settings = false;

$installamp_clean = false;
$uninstallamp = false;
$installdb = false;

//initialize variables to avoid php notices
$dbhost = null;
$dbname = 'asterisk';
$new_username = null;
$new_password = null;

$runas_uid = "asterisk";
$runas_gid = "asterisk";
$freepbxip = "192.168.1.1";
$asteriskip = "localhost";

foreach ($args[0] as $arg) {
	switch ($arg[0]) {
		case "--help": case "h": case "?":
			showHelp();
			exit(10);
		break;
		case "--dry-run":
			out("Dry-run only, nothing will be changed");
			$dryrun = true;
		break;
		case "--debug":
			$debug = true;
			debug("Debug mode enabled");
		break;
		case "--username": case "u":
			out("Using username: ".$arg[1]);
			$new_username = $arg[1];
		break;
		case "--password": case "p":
			out("Using password: ".str_repeat("*",strlen($arg[1])));
			$new_password = $arg[1];
		break;
		case "--force-version":
			$version = $arg[1];
			out("Forcing upgrade from version ".$version);
		break;
		case "--dbhost":
			$dbhost = $arg[1];
			out("Using remote database server at ".$dbhost);
		break;
		case "--dbname":
			$dbname = $arg[1];
			out("Using database ".$dbname);
		break;
		case "--no-files":
			$install_files = false;
			out("Running upgrade only, without installing files.");
		break;
		case "--force-overwrite":
			$check_md5s = false;
			out("Overwriting all files including modified ones.");
		break;
		case "--engine":
			if ($arg[1] != 'asterisk') {
				fatal('Currently only "asterisk" is supported as a PBX engine');
			}
			$pbx_engine = $arg[1];
		break;
		case "--install-moh":
			$install_moh = true;
		break;
		case "--set-freepbx-settings":
			$set_freepbx_settings = true;
		break;
		case "--fopwebroot":
		case "--install-fop":
			out("install-fop: depricated setting, does nothing.");
		break;
		case "--update-links":
			$update_links = true;
			//Note: there is NO break here on purpose!
		case "--make-links-devel":
		case "--dev-links":
			$make_links = true;
		break;
		case "--skip-module-install":
			$module_install = false;
		break;
		case "--webroot":
			$webroot = $arg[1];
			out("Using Webroot at ".$webroot);
		break;
		case "--cgibin":
			$cgibin = $arg[1];
			out("Using CGI-BIN at ".$cgibin);
		break;
		case "--bin":
			$ampbin_dir = $arg[1];
			out("Using bin at ".$ampbin_dir);
		break;
		case "--sbin":
			$ampsbin_dir = $arg[1];
			out("Using sbin at ".$ampsbin_dir);
		break;
		case "--asteriskuser":
			$asterisk_user = $arg[1];
			out("Using Asterisk user ".$asterisk_user);
		break;
		case "--asteriskpass":
			$asterisk_pass = $arg[1];
			out("Using asteriskpass ".str_repeat("*",strlen($arg[1])));
		break;
		case "--uid":
			$runas_uid = $arg[1];
			out("Setting ownership (user) to ".$runas_uid);
		break;
		case "--gid":
			$runas_gid = $arg[1];
			out("Setting ownership (group) to ".$runas_gid);
		break;
		case "--scripted":
			$scripted = true;
			out("Unattended installation. No questions will be asked");
		break;
		case "--freepbxip":
			$freepbxip = $arg[1];
			out("Setting IP address of web interface to $freepbxip");
		break;
		case "--asteriskip":
			$asteriskip = $arg[1];
			out("Setting IP address of asterisk to $asteriskip");
		break;
		case "--cleaninstall":
			$installamp_clean = true;
		break;
		case "--uninstall":
			$uninstallamp = true;
		break;
		case "--installdb":
			$installdb = true;
		break;
	}
}

if($installamp_clean || $uninstallamp) {
	global $webroot;
	global $asterisk_user;
	global $asterisk_pass;

	$oldampconf = array();
	if(file_exists('/etc/amportal.conf')) {
		$amportalconf = file_get_contents('/etc/amportal.conf');
		if(preg_match('/AMPWEBROOT=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPWEBROOT'] = $matches[1];
		}
		if(preg_match('/AMPDBENGINE=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPDBENGINE'] = $matches[1];
		}
		if(preg_match('/AMPDBUSER=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPDBUSER'] = $matches[1];
		}
		if(preg_match('/AMPDBPASS=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPDBPASS'] = $matches[1];
		}
		if(preg_match('/AMPDBNAME=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPDBNAME'] = $matches[1];
		}
		if(preg_match('/AMPDBHOST=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPDBHOST'] = $matches[1];
		}
		if(preg_match('/AMPBIN=(.*)/',$amportalconf,$matches)) {
			$oldampconf['AMPBIN'] = $matches[1];
		}
		outn("Remove /etc/amportal.conf?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Removing /etc/amportal.conf.....");
				unlink('/etc/amportal.conf');
				out("Done!");
			break;
		}
	}

	if(file_exists('/etc/freepbx.conf')) {
		outn("Remove /etc/freepbx.conf?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Removing /etc/freepbx.conf.....");
				unlink('/etc/freepbx.conf');
				out("Done!");
			break;
		}
	}

	if(file_exists('/usr/local/sbin/amportal')) {
		outn("Remove /usr/local/sbin/amportal?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Removing /usr/local/sbin/amportal.....");
				unlink('/usr/local/sbin/amportal');
				out("Done!");
			break;
		}
	}

	if(!empty($oldampconf['AMPBIN']) && file_exists($oldampconf['AMPBIN'])) {
		outn("Remove All FreePBX Tools in ".$oldampconf['AMPBIN']."?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		$files = array("archive_recordings","freepbx_engine", "gen_amp_conf.php", "libfreepbx.confgen.php", "retrieve_conf", "freepbx-cron-scheduler.php", "freepbx_setting", "generate_hints.php", "module_admin", "retrieve_parse_amportal_conf.pl");
		foreach (glob($oldampconf['AMPBIN']."/*") as $filename) {
			if(is_link($filename)) {
				if(preg_match('/'.preg_quote($oldampconf['AMPWEBROOT'],'/').'/i',readlink($filename))) {
					$files[] = basename($filename);
				}
			}
		}
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				foreach($files as $file) {
					if(file_exists($oldampconf['AMPBIN'].'/'.$file)) {
						outn("Removing ".$oldampconf['AMPBIN']."/".$file.".....");
						unlink($oldampconf['AMPBIN'].'/'.$file);
						out("Done!");
					}
				}
			break;
		}
	}

	if(!empty($oldampconf) && isset($oldampconf['AMPWEBROOT']) && file_exists($oldampconf['AMPWEBROOT'])) {
		outn("Remove ".$oldampconf['AMPWEBROOT']."?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Removing ".$oldampconf['AMPWEBROOT']."......");
				exec('rm -Rf '.$oldampconf['AMPWEBROOT']);
				out("Done!");
			break;
		}
	}

	if(!$uninstallamp && !empty($oldampconf) && $oldampconf['AMPDBENGINE'] == 'mysql') {
		outn("Reinitalize & Reinstall Freepbx's Asterisk Database?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Erasing FreePBX Asterisk Database...");
				$datasource = 'mysql://'.$oldampconf["AMPDBUSER"].':'.$oldampconf["AMPDBPASS"].'@'.$oldampconf["AMPDBHOST"].'/'.$oldampconf["AMPDBNAME"];
				$cleandb = DB::connect($datasource); // attempt connection

				if(DB::IsError($cleandb)) {
					out("FAILED");
					fatal("Try not selecting 'y' on Reinitalize & Reinstall Freepbx's Asterisk Database");
				} else {
					$sql = "SHOW TABLES FROM ".$oldampconf['AMPDBNAME'];
					$tables = $cleandb->getAll($sql);
					foreach($tables as $list) {
						$sql = "DROP TABLE ".$oldampconf['AMPDBNAME'].".".$list[0];
						$cleandb->query($sql);
					}
					out("Done");
					outn("Reinstalling FreePBX Asterisk DB Structure...");
					installampimport_mysql_dump('newinstall.sql',$cleandb);
					out("Done");
				}
			break;
		}

		outn("Reinitalize & Reinstall Freepbx's CDR Database?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Erasing FreePBX CDR Database...");
				//for asterisk CDR
				$datasource = 'mysql://'.$oldampconf["AMPDBUSER"].':'.$oldampconf["AMPDBPASS"].'@'.$oldampconf["AMPDBHOST"].'/asteriskcdrdb';
				$cdrdb = DB::connect($datasource); // attempt connection
				if(DB::IsError($cdrdb)) {
					out("FAILED TO REMOVE CDR");
				} else {
					$sql = "SHOW TABLES FROM asteriskcdrdb";
					$tables = $cleandb->getAll($sql);
					foreach($tables as $list) {
						$sql = "DROP TABLE asteriskcdrdb.".$list[0];
						$cleandb->query($sql);
					}
					out("Done");
					outn("Reinstalling FreePBX CDR DB Structure...");
					installampimport_mysql_dump('cdr_mysql_table.sql', $cdrdb);
					out("Done!");
				}
			break;
		}
	}

	if($uninstallamp && (!empty($oldampconf) || !empty($new_username))) {
		$u_username = !empty($oldampconf["AMPDBUSER"]) ? $oldampconf["AMPDBUSER"] : $new_username;
		$u_password = !empty($oldampconf["AMPDBPASS"]) ? $oldampconf["AMPDBPASS"] : (!empty($new_password) ? $new_password : '');
		$u_host = !empty($oldampconf["AMPDBHOST"]) ? $oldampconf["AMPDBHOST"] : (!empty($dbhost) ? $dbhost : 'localhost');
		$u_database = !empty($oldampconf["AMPDBNAME"]) ? $oldampconf["AMPDBNAME"] : (!empty($dbname) ? $dbname : 'asterisk');

		outn("Uninstall Freepbx's Asterisk Database?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Erasing FreePBX Asterisk Database...");
				$datasource = 'mysql://'.$u_username.':'.$u_password.'@'.$u_host.'/'.$u_database;
				$cleandb = DB::connect($datasource); // attempt connection

				if(DB::IsError($cleandb)) {
					out("FAILED");
					fatal("Could Not Connect to Database (Probably already deleted)");
				} else {
					$sql = "SHOW TABLES FROM ".$u_database;
					$tables = $cleandb->getAll($sql);
					foreach($tables as $list) {
						$sql = "DROP TABLE ".$u_database.".".$list[0];
						$cleandb->query($sql);
					}
					out("Done");
				}
			break;
		}

		outn("Uninstall Freepbx's CDR Database?:\n [y] ");
		$key = trim(fgets(STDIN,1024));
		switch($key) {
			case "n":
			case "no":
			break;
			case "y":
			case "yes":
			default:
				outn("Erasing FreePBX CDR Database...");
				$datasource = 'mysql://'.$u_username.':'.$u_password.'@'.$u_host.'/asteriskcdrdb';
				$cleandb = DB::connect($datasource); // attempt connection

				if(DB::IsError($cleandb)) {
					out("FAILED");
					//fatal("Could Not Connect to Database (Probably already deleted)");
				} else {
					$sql = "SHOW TABLES FROM asteriskcdrdb";
					$tables = $cleandb->getAll($sql);
					foreach($tables as $list) {
						$sql = "DROP TABLE asteriskcdrdb.".$list[0];
						$cleandb->query($sql);
					}
					out("Done");
				}
			break;
		}
	}
	if($uninstallamp) {
		die("Successfully Uninstalled FreePBX\n");
	}
}

// **** Look for user = root

// TODO: if we bootstrap, do this first before even trying. Also, is there a problem boostraping as user root???
//
outn("Checking user..");
$euid = (posix_getpwuid(posix_geteuid()));
$current_user = $euid['name'];
if ($current_user != "root"){
	out("FAILED");
	fatal($argv[0]." must be run as root");
}
out("OK");


// TODO: if we bootstrap, do this first before even trying.
//
outn("Checking if Asterisk is running..");
exec("pidof asterisk", $pid_val, $ret);
if ($ret) {
	out("FAILED");
	fatal($argv[0]."\n\tAsterisk must be running. If this is a first time install, you should start\n\tAsterisk by typing './start_asterisk start'\n\tFor upgrading, you should run 'amportal start'");
}
out("running with PID: ".$pid_val[0]."..OK");

// **** Check for amportal.conf, create if necessary

// TODO: Check if freepbx_settings has been setup, if so then we don't even want to mess with ampportal.conf, that
//       should only be first time install.
//
outn("Checking for ".AMP_CONF."..");
if (!file_exists(AMP_CONF)) {
	out(AMP_CONF." does not exist, copying default");
	copy("amportal.conf", AMP_CONF);

	// this file contains password and should not be a+r
	// this addresses http://freepbx.org/trac/ticket/1878
	chown(AMP_CONF, $runas_uid);
	chgrp(AMP_CONF, $runas_gid);
	chmod(AMP_CONF, 0640);

	collect_settings(AMP_CONF, $dbhost, $new_username, $new_password, $dbname);

	out("Assuming new install, --install-moh added to command line");
	$install_moh = true;
}
out("OK");

// **** read amportal.conf

// TODO: see comments above, have we already boostraped, if so, skip this?
//
outn("Reading ".AMP_CONF."..");
$amp_conf = install_parse_amportal_conf(AMP_CONF);
if (count($amp_conf) == 0) {
	fatal("FAILED");
}
out("OK");

// TODO: if we boostrapped I think we can count on ALL of these being set but maybe it's
//       fine to do a sanity check?
//
// Ensure our "critical" variables are set.  We absolutely need these to copy in files.

if (!array_key_exists("AMPWEBROOT",$amp_conf)) {
	out("Adding AMPWEBROOT option to amportal.conf - using AMP default");
	$amp_conf["AMPWEBROOT"] = "/var/www/html";
}
if (!array_key_exists("AMPBIN",$amp_conf)) {
	out("Adding AMPBIN option to amportal.conf - using AMP default");
	$amp_conf["AMPBIN"] = "/var/lib/asterisk/bin";
}
if (!array_key_exists("AMPSBIN",$amp_conf)) {
	out("Adding AMPSBIN option to amportal.conf - using AMP default");
	$amp_conf["AMPSBIN"] = "/usr/sbin";
}
if (!array_key_exists("AMPDBENGINE",$amp_conf)) {
	out("Adding AMPDBENGINE option to amportal.conf - using AMP default");
	$amp_conf["AMPDBENGINE"] = "mysql";
}
if (!array_key_exists("AMPDBNAME",$amp_conf)) {
	out("Adding AMPDBNAME option to amportal.conf - using AMP default");
	$amp_conf["AMPDBNAME"] = "asterisk";
}

// TODO: if we boostrapped do we ignore these? (Can they even be set?)
//
if (isset($new_username)) {
	$amp_conf["AMPDBUSER"] = $new_username;
}
if (isset($new_password)) {
	$amp_conf["AMPDBPASS"] = $new_password;
}
if (isset($dbhost)) {
	$amp_conf["AMPDBHOST"] = $dbhost;
}
if (isset($dbname)) {
	$amp_conf["AMPDBNAME"] = $dbname;
}
// If they pre-set this in their amportal.conf or this is an upgrade, we should honor it as well
//
// TODO: if we boostrap, then this value could be normalized (1/0 I think?)
//
// write amportal.conf
// TODO: if we boostrapped we don't want to write amportal.conf, or do we? e.g. if we are running out of the file vs. the
//       database then we probably want to write, though there should be a freepbx_conf class to use that does that and knows
//       how to make that decsion as well as what to write?
//
if(empty($amp_conf["AMPDBUSER"]) || empty($amp_conf["AMPDBPASS"]) || empty($amp_conf["AMPDBHOST"]) || empty($amp_conf["AMPDBNAME"])) {
	die("Database settings were blank. Try again\n");
}

write_amportal_conf(AMP_CONF, $amp_conf);

// **** Check for amportal.conf, create if necessary

outn("Checking for ".ASTERISK_CONF."..");
if (!file_exists(ASTERISK_CONF)) {
	out(ASTERISK_CONF." does not exist, copying default");
	copy("asterisk.conf", ASTERISK_CONF);

	if(file_exists("/usr/lib64/asterisk/modules")) {
		out("Detected lib64 based system, adjusting asterisk.conf");
		$contents = file_get_contents(ASTERISK_CONF);
		$contents = str_replace("/usr/lib/asterisk/modules","/usr/lib64/asterisk/modules",$contents);
		file_put_contents(ASTERISK_CONF,$contents);
	}
}
out("OK");

// **** read asterisk.conf

// TODO: if we boostrapped don't do this
//
outn("Reading ".ASTERISK_CONF."..");
$asterisk_conf = install_parse_asterisk_conf(ASTERISK_CONF);
if (count($asterisk_conf) == 0) {
	fatal("FAILED. Have you installed Asterisk?");
}
out("OK");

/* TODO: if we boostrapped this should have been done but doesn't hurt?
*/
if (isset($asterisk_conf['astetcdir'])) { $amp_conf['ASTETCDIR'] = $asterisk_conf['astetcdir']; }
if (isset($asterisk_conf['astmoddir'])) { $amp_conf['ASTMODDIR'] = $asterisk_conf['astmoddir']; }
if (isset($asterisk_conf['astvarlibdir'])) { $amp_conf['ASTVARLIBDIR'] = $asterisk_conf['astvarlibdir']; }
if (isset($asterisk_conf['astagidir'])) { $amp_conf['ASTAGIDIR'] = $asterisk_conf['astagidir']; }
if (isset($asterisk_conf['astspooldir'])) { $amp_conf['ASTSPOOLDIR'] = $asterisk_conf['astspooldir']; }
if (isset($asterisk_conf['astrundir'])) { $amp_conf['ASTRUNDIR'] = $asterisk_conf['astrundir']; }
if (isset($asterisk_conf['astlogdir'])) { $amp_conf['ASTLOGDIR'] = $asterisk_conf['astlogdir']; }

if (!isset($pbx_engine)) { $pbx_engine='asterisk'; }
out("Using $pbx_engine as PBX Engine");
$amp_conf["AMPENGINE"]=$pbx_engine;

// TODO: I guess we have new variables set, of course see note above if we boostrapped. Probably
//       this one stays?
//
write_amportal_conf(AMP_CONF, $amp_conf);


// **** Write asterisk version to ASTETCDIR/version

// TODO: does anything use this? What's the point? (other than we need the version for below)
//
$tmpoutput = '';
$tmpout = exec("asterisk -V", $tmpoutput, $exitcode);
if ($exitcode != 0) {
	fatal("Error executing asterisk: be sure Asterisk is installed and in the path");
}
if (!$fd = fopen($amp_conf['ASTETCDIR'].'/version','w')) {
	fatal('Cannot open '.$amp_conf['ASTETCDIR'].'/version for writing');
}
fwrite($fd, $tmpout);
fclose($fd);
// change to read-only
chmod($amp_conf['ASTETCDIR'].'/version',0444);


// normally this would be the contents of ASTETCDIR/version, but this is for simplicity, as we just read it above
$verinfo = $tmpout;

// **** Check asterisk version
//  Set the 'engine' to be 'asterisk14' if using asterisk 1.4, otherwise
//  'asterisk'
outn("Checking for Asterisk version..");
if ((preg_match('/^Asterisk (\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) || 
	(preg_match('/^Asterisk SVN-(\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) ||
	(preg_match('/^Asterisk GIT-(\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches))) {
	if ((version_compare($matches[1], "1.8") < 0)) {
		fatal("Asterisk 1.6, 1.8, 10, 11 or 12 is required for this version of FreePBX. Detected version is: ".$matches[1]);
	}
	if (version_compare($matches[1], "14", "ge")) {
		fatal("Asterisk 1.8, 10, 11, 12 or 13 is required for this version of FreePBX. Detected version is: ".$matches[1]);
	}
	out("{$matches[1]}");
	$asterisk_version = $matches[1];

} elseif (preg_match('/^Asterisk ([ABC]\.\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) {
	if (substr($matches[1], 0, 1) == "A") {
		fatal("Asterisk Business Edition B or C is required for this version of FreePBX. Detected version is: ".$matches[1]);
	}
	out("{$matches[1]}");
	$asterisk_version = '1.4'; //Not really, but this makes sure that proper execution occurs later on reload commands, etc.

} elseif ($asterisk_version = preg_match('/^Asterisk SVN.+/', $verinfo) ||
		$asterisk_version = preg_match('/^Asterisk GIT.+/', $verinfo)) {
	out("FAIL");
	out("*** WARNING ***");
	out("You are not using a released version of Asterisk. We are unable to verify");
	out("that your Asterisk version is compatible with FreePBX. Whilst this probably");
	out("won't cause any problems, YOU NEED TO BE CERTAIN that it is compatible");
	out("with at least the released Asterisk version 1.8" );
} else {
	fatal("Could not determine asterisk version (got: \"".$verinfo."\" please report this)");
}

// **** Make sure selinux isn't enabled

outn("Checking for selinux..");
$tmpoutput = array();
$tmpout = exec("getenforce 2>/dev/null", $tmpoutput, $sereturn);
if (isset($tmpoutput[0]) && strtolower($tmpoutput[0]) === "enabled") {
	// this method seems better because disabled and permissive are the same
	// if a user installs and realizes selinux is running the other method
	// requires a reboot to get selinuxenabled to work after editing the  selinux config
	// this will allow you to use setenforce 0 which turns selinux into permissive mode which
	// doesnt enforce, it just warns.
	fatal("selinux is ENABLED. This is not supported. Please disable selinux before using FreePBX");
}
out("OK");

// **** Connect to database

// TODO: if we bootstrapped, we are already connected and this can all be skipped
//
outn("Connecting to database..");

$db_engine = $amp_conf["AMPDBENGINE"];
if ($db_engine != "sqlite3") {
	$db_user = $amp_conf["AMPDBUSER"];
	$db_pass = $amp_conf["AMPDBPASS"];
	$db_host = $amp_conf["AMPDBHOST"];
}
$db_name = $amp_conf["AMPDBNAME"];

// we still support older configurations,  and fall back
// into mysql when no other engine is defined
if ($db_engine == "") {
	$db_engine = "mysql";
}

switch ($db_engine) {
	case "pgsql":
	case "mysql":
		// datasource in in this style: dbengine://username:password@host/database
		if (!function_exists($db_engine.'_connect')) {
			out("FAILED");
			fatal($db_engine." PHP libraries not installed");
		}

		$datasource = $db_engine.'://'.$db_user.':'.$db_pass.'@'.$db_host.'/'.$db_name;
		$db = DB::connect($datasource); // attempt connection
	break;

	case "sqlite":
		die_freepbx("SQLite2 support is deprecated. Please use sqlite3 only.");
	break;

	case "sqlite3":
		if (!isset($amp_conf["AMPDBFILE"])) {
			die("You must setup properly AMPDBFILE in /etc/amportal.conf");
		}

		if (isset($amp_conf["AMPDBFILE"]) == "") {
			die("AMPDBFILE in /etc/amportal.conf cannot be blank");
		}

		/* on centos this extension is not loaded by default */
		if (! extension_loaded('sqlite3.so')  && ! extension_loaded('SQLITE3'))
			dl('sqlite3.so');

		if (! @require_once('DB/sqlite3.php') ) {
			out("FAILED");
			fatal( "Your PHP installation has no PEAR/SQLite3 support. Please install php-sqlite3 and php-pear.");
		}

		$datasource = "sqlite3:///" . $amp_conf["AMPDBFILE"] . "?mode=0666";
		$db = DB::connect($datasource);
	break;

	default:
		die( "Unknown SQL engine: [$db_engine]");
}

if(DB::IsError($db)) {
	out("FAILED");
	debug($db->userinfo);
	out("Try running ".$argv[0]." --username=user --password=pass  (using your own user and pass)");
	fatal("Cannot connect to database");

}
out("OK");

if($installdb) {
	outn("Checking state of FreePBX DB...");
	$sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '".$amp_conf["AMPDBNAME"]."'";
	if(!$db->getOne($sql)) {
		outn("FreePBX DB is empty, inserting standard rows...");
		installampimport_mysql_dump('newinstall.sql');
		out("Done!");
	} else {
		out("FreePBX DB is already populated skipping");
	}

	//for asterisk CDR
	outn("Checking state of FreePBX CDRDB...");
	$datasource = 'mysql://'.$amp_conf["AMPDBUSER"].':'.$amp_conf["AMPDBPASS"].'@'.$amp_conf["AMPDBHOST"].'/asteriskcdrdb';
	$cdrdb = DB::connect($datasource); // attempt connection
	if(DB::IsError($cdrdb)) {
		out("FAILED TO INSTALL CDR");
	} else {
		$sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'asteriskcdrdb'";
		if(!$cdrdb->getOne($sql)) {
			outn("FreePBX DB is empty, inserting standard rows...");
			installampimport_mysql_dump('cdr_mysql_table.sql', $cdrdb);
			out("Done!");
		} else {
			out("FreePBX CDR DB is already populated skipping");
		}
	}
}

// **** Read DB for version info

if (!isset($version)) {
	outn("Checking current version of FreePBX..");
	$version = install_getversion();
	if (!$version) {
		out("no version information");
		out("Assuming new installation");
	} else {
		out($version);
	}
}

// Check if freepbx_settings is there and has been initialized
// if it has anything less than about 5 settings in it (and that
// is probably quite low) then something is wrong so assume it
// is not there.
//
$sql = "SELECT count(*) FROM freepbx_settings";
$num_settings = $db->getOne($sql);
$force_amportal_conf = DB::IsError($num_settings) || $num_settings < 5;

// **** Copy files

$asteriskuser = isset($amp_conf['AMPASTERISKUSER']) && $amp_conf['AMPASTERISKUSER'] ? $amp_conf['AMPASTERISKUSER'] : 'asterisk';
$installfw = false;
if ($install_files) {
	outn("Installing new FreePBX files..");
	$check_md5s=true;
	$md5sums = read_md5_file(UPGRADE_DIR."/".$version.".md5");
	if(!file_exists(MODULE_DIR)) {
		mkdir(MODULE_DIR);
	}
	list($num_files, $num_copied) = recursive_copy("amp_conf", "", $md5sums);
	if($make_links) {
		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework')) {
			mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/framework');
			chown($amp_conf['AMPWEBROOT'].'/admin/modules/framework',$asteriskuser);
		}
		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml')) {
			symlink(dirname(__FILE__).'/module.xml',$amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml');
			chown($amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml',$asteriskuser);
		}
		$installfw = true;
	} else {
		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework')) {
			mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/framework');
			chown($amp_conf['AMPWEBROOT'].'/admin/modules/framework',$asteriskuser);
        }
        if(!file_exists(dirname(__FILE__).'/amp_conf/htdocs/admin/modules/_cache')) {
            mkdir(dirname(__FILE__).'/amp_conf/htdocs/admin/modules/_cache',0777,true);
            chown(dirname(__FILE__).'/amp_conf/htdocs/admin/modules',$asteriskuser);
            if(!file_exists(dirname(__FILE__).'/amp_conf/htdocs/admin/modules')) {
                die("We were not able to create the local modules directory, which is important\n");
            }
        }
    	if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/_cache')) {
    		mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/_cache',0777,true);
    		chown($amp_conf['AMPWEBROOT'].'/admin/modules',$asteriskuser);
    		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules')) {
    			die("We were not able to create the web modules directory, which is important\n");
    		}
        }
		if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml')) {
			copy(dirname(__FILE__).'/module.xml',$amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml');
			chown($amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml',$asteriskuser);
		}
		$installfw = true;
	}
	if (!is_file("/etc/asterisk/voicemail.conf")) copy("/etc/asterisk/voicemail.conf.template","/etc/asterisk/voicemail.conf");
	if (!is_dir("/var/spool/asterisk/voicemail/device")) amp_mkdir("/var/spool/asterisk/voicemail/device", "0755", true);
	$copy_lang = ($make_links) ? "linked" : "copied";
	out("OK (".$num_copied." files ".$copy_lang.", ".($num_files-$num_copied)." skipped)");

	// link the packed js library for ARI, if there the error will indicate that
	$libfreepbx = $amp_conf['AMPWEBROOT'].'/admin/common/libfreepbx.javascripts.js';
	$dest_libfreepbx = $amp_conf['AMPWEBROOT'].'/recordings/theme/js/libfreepbx.javascripts.js';
	if (!file_exists($amp_conf['AMPWEBROOT'].'/recordings/theme/js')) {
		mkdir($amp_conf['AMPWEBROOT'].'/recordings/theme/js',0755, true);
	}
	if (file_exists($libfreepbx) && !file_exists($dest_libfreepbx)) {
		outn(_("linking libfreepbx.javascripts.js to theme/js.."));
		if (link($libfreepbx, $dest_libfreepbx)) {
			out(_("ok"));
		} else {
			out(_("possible error - check warning message"));
		}
	}
}

if (!$dryrun) {
	$asteriskuser = isset($amp_conf['AMPASTERISKUSER']) && $amp_conf['AMPASTERISKUSER'] ? $amp_conf['AMPASTERISKUSER'] : 'asterisk';

	if (file_exists($amp_conf["AMPSBIN"]."/amportal")) {
		exec("chmod 755 ".$amp_conf["AMPSBIN"]."/amportal");
		outn("amportal..");
	} else {
		outn("no amportal..");
	}
	if (file_exists($amp_conf["AMPSBIN"]."/fpbx")) {
		exec("chmod 755 ".$amp_conf["AMPSBIN"]."/fpbx");
		outn("fpbx..");
	} else {
		outn("no fpbx..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/freepbx_engine")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/freepbx_engine");
		outn("freepbx_engine..");
	} else {
		outn("no freepbx_engine..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/freepbx_setting")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/freepbx_setting");
		outn("freepbx_setting..");
	} else {
		outn("no freepbx_setting..");
	}
	if (file_exists($amp_conf["AMPBIN"]."/gen_amp_conf.php")) {
		exec("chmod 755 ".$amp_conf["AMPBIN"]."/gen_amp_conf.php");
		outn("gen_amp_conf.php..");
	} else {
		outn("no gen_amp_conf..");
	}
	out("done");

	// Ensure UIDs are set correctly before any chowns happen
	// Note - freepbx_engine must be used the first time to ensure that freepbx.conf exists.
	exec($amp_conf["AMPBIN"]."/freepbx_engine admin freepbx_setting AMPASTERISKWEBGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting AMPASTERISKWEBUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting AMPASTERISKGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting AMPASTERISKUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting AMPDEVGROUP $runas_gid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting AMPDEVUSER $runas_uid");
	exec($amp_conf["AMPBIN"]."/freepbx_setting ASTMANAGERHOST $asteriskip");
	// edit conf file passwords and then
	// reload manager in asterisk if it is running:
	//
	if (file_exists(dirname(__FILE__)."/apply_conf.sh")) {
		out("apply username/password changes to conf files:");
		debug("Running ".dirname(__FILE__)."/apply_conf.sh");
		$apply_conf_out = array();
		if ($force_amportal_conf) {
			out("running apply_conf.sh from " . AMP_CONF);
			putenv('FORCE_AMPORTAL_CONF=1');
			exec(dirname(__FILE__)."/apply_conf.sh ".AMP_CONF, $apply_conf_out);
			putenv('FORCE_AMPORTAL_CONF=');
		} else {
			out("running apply_conf.sh from freepbx_settings");
			exec(dirname(__FILE__)."/apply_conf.sh", $apply_conf_out);
		}
		foreach ($apply_conf_out as $line) {
			out("\t".$line);
		}
		unset($apply_conf_out);
		out("done with apply_conf.sh");
	}

	/* As of Asterisk 1.4.16 or there about, a missing #include file will make the reload fail. So
	we need to make sure that we have such for everything that is in our configs. We will simply
	look for the #include statements and touch the files vs. trying to inventory everything we may
	need and then forgetting something.
	*/

	outn("creating missing #include files..");
	$include_err = false;
	exec("grep '#include' ".$amp_conf['ASTETCDIR']."/*.conf | sed 's/;.*//; s/#include//'",$output,$retcode);
	if ($retcode != 0) {
		out("Error code $retcode: trying to search for missing #include files");
		$include_err = true;
	}

	foreach($output as $file) {
		if (trim($file) == '') {
			continue;
		}
		$parse1 = explode(':',$file);
		$parse2 = explode(';',$parse1[1]);
		$rawfile = trim($parse2[0]);
		if ($rawfile == '') {
			continue;
		}

		$target = ($rawfile[0] == '/') ? $rawfile : $amp_conf['ASTETCDIR']."/$rawfile";

		if (!file_exists($target)) {
			exec("sudo -u $asteriskuser touch $target", $output, $retcode);
			if ($retcode != 0) {
				out("Error code $retcode: trying to create empty file $target");
				$include_err = true;
			}
		}
	}
	if (! $include_err) {
		out("OK");
	}
	// reload manager in asterisk if it was running:
	// note: I removed the check for Asterisk 1.2, theres just no point
	system("asterisk -rx 'module reload manager'");
}

// **** Create spool directories for monitor and fax
if (!is_dir($amp_conf["ASTSPOOLDIR"]."/monitor"))
	amp_mkdir($amp_conf["ASTSPOOLDIR"]."/monitor","0766",true);
if (!is_dir($amp_conf["ASTSPOOLDIR"]."/fax"))
	amp_mkdir($amp_conf["ASTSPOOLDIR"]."/fax","0766",true);

//Check to make sure database is installed
$sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '".$amp_conf["AMPDBNAME"]."'";
if(!$db->getOne($sql)) {
	fatal('The '. $amp_conf["AMPDBNAME"] . ' ' . $amp_conf["AMPDBENGINE"] . ' database appears empty, try running with the "--cleaninstall --installdb" commands or install the database manually');
}
// **** Set permissions all files

// tell amportal/freepbx_engine to use amportal.conf and not bootstrap
// if freepbx_settings has not been setup yet or you will get an error.
//
if ($install_files) {
	outn("Setting permissions on files..");
	if (!$dryrun) {
		if ($force_amportal_conf) {
			putenv('FORCE_AMPORTAL_CONF=1');
		}
		exec($amp_conf["AMPSBIN"]."/amportal chown");
		if ($force_amportal_conf) {
			putenv('FORCE_AMPORTAL_CONF=');
		}
	}
	out("OK");
}

outn("Loading Bootstrap..");
if (!class_exists('FreePBX')) {
	include_once ($amp_conf['AMPWEBROOT'].'/admin/libraries/BMO/FreePBX.class.php');
}
if (!class_exists('notfications')) {
	include_once ($amp_conf['AMPWEBROOT'].'/admin/libraries/notifications.class.php');
}
if (!class_exists('module_functions')) {
	include_once ($amp_conf['AMPWEBROOT'].'/admin/libraries/modulefunctions.class.php');
}
if (!class_exists('modulelist')) {
	include_once ($amp_conf['AMPWEBROOT'].'/admin/libraries/modulelist.class.php');
}
out("OK");

// Run through all the upgrade scripts starting at the specified version
//
upgrade_all($version);
if(!file_exists(dirname(__FILE__).'/module.xml')) {
	die('Cant Find Framework XML');
}
$fwxml = simplexml_load_file(dirname(__FILE__).'/module.xml');
//setversion to whatever is in framework.xml forever for here on out.
$fwver = (string)$fwxml->version;
if(!empty($fwver)) {
	if(!function_exists('setversion')) {
		die('Cant find function setversion');
	}
	setversion($fwver);
	if(install_getversion() != $fwver) {
		die('Internal Error. Function install_getversion did not match the Framework version, even after it was suppose to be applied');
	}
} else {
	die('Version from Framework was empty, cant continue');
}

// Save $amp_conf variables so we can set the configured values
if (($set_freepbx_settings && $force_amportal_conf) || (!file_exists('/etc/redhat-release')))  {
	$amp_conf_file = $amp_conf;
}

freepbx_settings_init(true);
out("..OK");

// TODO: if file is $force_amportal_conf let's go set any settings in freepbx_settings,
//       question is, should we do this further up???
//
if (($set_freepbx_settings && $force_amportal_conf) || (!file_exists('/etc/redhat-release'))) {
	out("Setting freepbx settings form " . AMP_CONF);
	$freepbx_conf =& freepbx_conf::create();
	//find and set webroot first as everything else relies on it
	foreach ($amp_conf_file as $keyword => $value) {
		if ($freepbx_conf->conf_setting_exists($keyword)) {
			$freepbx_conf->set_conf_values(array($keyword => $value),true,true);
			out("freepbx setting [$keyword] set to [$value]");
		} else {
			out("freepbx setting [$keyword] DOES NOT EXIST, can't set to [$value]");
		}
	}
} else {
	//We are here mainly because of bug #6159
	//Meaning they are installing this on CentOS manually so the above checks fail
	global $webroot;
	if(isset($webroot) && !empty($webroot) && ($webroot != $amp_conf['AMPWEBROOT'])) {
		$freepbx_conf =& freepbx_conf::create();
		outn("Noticed Irregular AMPWEBROOT setting....");
		if ($freepbx_conf->conf_setting_exists('AMPWEBROOT')) {
			$freepbx_conf->set_conf_values(array('AMPWEBROOT' => $webroot),true,true);
		}
		$amportalconf = file_get_contents('/etc/amportal.conf');
		$amportalconf = preg_replace('/AMPWEBROOT=.*/', 'AMPWEBROOT='.$webroot, $amportalconf);
		file_put_contents('/etc/amportal.conf',$amportalconf);
		out("Fixed");
	}
}

// **** Generate AMP configs
out("Generating AMP configs..");
generate_configs();
out("Generating AMP configs..OK");

$version = install_getversion();

// Now force an install for all modules that are packaged with the tarball
// directory.
//
if ($module_install && !$update_links) {
	install_modules();
	if($installfw) {
		system($amp_conf['AMPBIN']."/module_admin --no-warnings -f install framework");
	}
} else {
	out("bypassing packaged module installation because --skip-module-install or --update-links flag");
}

//Start trusting the key
FreePBX::GPG()->trustFreePBX();
if($update_links) {
	//copy framework into installed folder if it doesnt already exist
	if(!file_exists($amp_conf['AMPWEBROOT'].'/admin/modules/framework')) {
		mkdir($amp_conf['AMPWEBROOT'].'/admin/modules/framework');
	}
	copy(__DIR__.'/module.xml',$amp_conf['AMPWEBROOT'].'/admin/modules/framework/module.xml');
}

// **** Set reload flag for AMP admin
needreload();

if ($amp_conf["AMPWEBADDRESS"]) {
	out("Please update your modules and reload Asterisk by visiting http://".$amp_conf["AMPWEBADDRESS"]."/admin",false);
} else {
	out("Please update your modules and reload Asterisk by browsing to your server.",false);
}

out("",false);
out("*************************************************************************",false);
out("* Note: It's possible that if you click the red 'Update Now' bar BEFORE *",false);
out("* updating your modules, your machine will start dropping calls. Ensure *",false);
out("* that all modules are up to date BEFORE YOU CLICK THE RED BAR. As long *",false);
out("* as this is observed, your machine will be fully functional whilst the *",false);
out("* upgrade is in progress.                                               *",false);
out("*************************************************************************",false);
out("****************************************",false);
out("* At This Time Please Restart Asterisk *",false);
out("****************************************",false);
// vim: set ts=4 sw=4 ai : //
// Ensure you 'set modeline' in your ~/.vimrc to activate this //
