<?php
	ini_set('display_errors',true);
	error_reporting(E_ALL);
	
	//var_dump($_SERVER);
	$amp_conf = parse_amportal_conf("/etc/amportal.conf");
		
	$amp_conf_defaults = array(
		'AMPDBENGINE'    => array('std' , 'mysql'),
		'AMPDBNAME'      => array('std' , 'asterisk'),
		'AMPENGINE'      => array('std' , 'asterisk'),
		'ASTMANAGERPORT' => array('std' , '5038'),
		'ASTMANAGERHOST' => array('std' , 'localhost'),
		'AMPDBHOST'      => array('std' , 'localhost'),
		'AMPDBUSER'      => array('std' , 'asteriskuser'),
		'AMPDBPASS'      => array('std' , 'amp109'),
		'AMPMGRUSER'     => array('std' , 'admin'),
		'AMPMGRPASS'     => array('std' , 'amp111'),
		'FOPPASSWORD'    => array('std' , 'passw0rd'),
		'FOPSORT'        => array('std' , 'extension'),
		'AMPSYSLOGLEVEL '=> array('std' , 'LOG_ERR'),
		'ARI_ADMIN_PASSWORD' => array('std' , 'ari_password'),

		'ASTETCDIR'      => array('dir' , '/etc/asterisk'),
		'ASTMODDIR'      => array('dir' , '/usr/lib/asterisk/modules'),
		'ASTVARLIBDIR'   => array('dir' , '/var/lib/asterisk'),
		'ASTAGIDIR'      => array('dir' , '/var/lib/asterisk/agi-bin'),
		'ASTSPOOLDIR'    => array('dir' , '/var/spool/asterisk/'),
		'ASTRUNDIR'      => array('dir' , '/var/run/asterisk'),
		'ASTLOGDIR'      => array('dir' , '/var/log/asterisk'),
		'AMPBIN'         => array('dir' , '/var/lib/asterisk/bin'),
		'AMPSBIN'        => array('dir' , '/usr/sbin'),
		'AMPWEBROOT'     => array('dir' , '/var/www/html'),
		'FOPWEBROOT'     => array('dir' , '/var/www/html/panel'),
		'MOHDIR'         => array('dir' , '/mohmp3'),
		'FPBXDBUGFILE'	 => array('dir' , '/tmp/freepbx_debug.log'),

		'USECATEGORIES'  => array('bool' , true),
		'ENABLECW'       => array('bool' , true),
		'CWINUSEBUSY'    => array('bool' , true),
		'FOPRUN'         => array('bool' , true),
		'AMPBADNUMBER'   => array('bool' , true),
		'DEVEL'          => array('bool' , false),
		'DEVELRELOAD'    => array('bool' , false),
		'CUSTOMASERROR'  => array('bool' , true),
		'DYNAMICHINTS'   => array('bool' , false),
		'BADDESTABORT'   => array('bool' , false),
		'SERVERINTITLE'  => array('bool' , false),
		'XTNCONFLICTABORT' => array('bool' , false),
		'USEDEVSTATE'    => array('bool' , false),
		'MODULEADMINWGET'=> array('bool' , false),
		'AMPDISABLELOG'  => array('bool' , true),
		'AMPENABLEDEVELDEBUG'=> array('bool' , false),
		'AMPMPG123'       => array('bool' , true),
		'FOPDISABLE'      => array('bool' , false),
		'ZAP2DAHDICOMPAT' => array('bool' , false),
		'USEQUEUESTATE'   => array('bool' , false),
		'CHECKREFERER'    => array('bool' , true),
		'USEDIALONE'      => array('bool' , false),
		'RELOADCONFIRM'   => array('bool' , true),
		'DISABLECUSTOMCONTEXTS'   => array('bool' , false),
	);
	
	include_once('admin/components.class.php');
	include_once('admin/common/db_connect.php');
	//include_once('admin/functions.inc.php');
	include_once("libs/misc.lib.php");
	require_once("/var/www/html/admin/extensions.class.php");
	
	global $amp_conf_defaults;
	
	if(!function_exists('parse_amportal_conf')){
		function parse_amportal_conf($filename) {
			if( !file_exists($filename) ){
				return false;
			}
			
			$file = file($filename);
			foreach($file as $line){
				if(preg_match("/^\s*([a-zA-Z0-9_]+)=([a-zA-Z0-9 .&-@=_!<>\"\']+)\s*$/",$line,$matches)){
					$conf[ $matches[1] ] = $matches[2];
				}
			}
			return $conf;
		}
	}
	
	/*
	include_once("libs/misc.lib.php");
	include_once "configs/default.conf.php";
	include_once "libs/paloSantoNavigation.class.php"; 
	include_once "libs/paloSantoDB.class.php";
	include_once "libs/paloSantoMenu.class.php";
	include_once("libs/paloSantoACL.class.php");// Don activate unless you know what you are doing. Too risky!

	$developerMode=false;

	session_name("elastixSession");
	session_start();

	load_language();
	$lang = get_language();
	if(file_exists("langmenus/$lang.lang")){
		include_once "langmenus/$lang.lang";
		global $arrLangMenu;
		global $arrLang;
		$arrLang = array_merge($arrLang,$arrLangMenu);
	}

	$pACL = new paloACL($arrConf['elastix_dsn']['acl']);

	require_once("libs/smarty/libs/Smarty.class.php");
	$smarty = new Smarty();
	$smarty->template_dir = "themes/" . $arrConf['mainTheme'];
	$smarty->compile_dir =  "var/templates_c/";
	$smarty->config_dir =   "configs/";
	$smarty->cache_dir =    "var/cache/";

	if (isset($_SESSION['elastix_user']) && 
		isset($_SESSION['elastix_pass']) && 
		$pACL->authenticateUser($_SESSION['elastix_user'], $_SESSION['elastix_pass']) 
		or $developerMode==true) {
		
		$pMenu = new paloMenu($arrConf['elastix_dsn']['menu']);

		$idUser = $pACL->getIdUser($_SESSION['elastix_user']);

		$arrMenuFiltered = $developerMode 
			? $pMenu->cargar_menu()
			: $pMenu->filterAuthorizedMenus($idUser);


		foreach($arrMenuFiltered as $idMenu=>$arrMenuItem) {
			$arrMenuFiltered[$idMenu]['Name'] = _tr($arrMenuItem['Name']);
		}
		$oPn = new paloSantoNavigation($arrConf, $arrMenuFiltered, $smarty);
	   
		if (isset($_POST['menu'])) $menu = $_POST['menu'];
		elseif (isset($_GET['menu'])) $menu=$_GET['menu'];
		elseif(empty($menu) and !empty($_SESSION['menu'])) $menu=$_SESSION['menu'];
		else $menu='';

		if (count($arrMenuFiltered)>0)
			$oPn->showMenu($menu);

		$menuBookmark = $oPn->getFirstChildOfMainMenuByBookmark($_SESSION['menu']);
		if(getParameter("action") == "addBookmark" || getParameter("action") == "deleteBookmark"){
			include_once "libs/paloSantoJSON.class.php";
			$jsonObject = new PaloSantoJSON();
			$id_menu = getParameter("id_menu");
			$output = "";
			if(isset($id_menu) && $id_menu !=""){
				$output  = putMenuAsBookmark($id_menu);
				$output["data"]["menu_url"] = $oPn->getFirstChildOfMainMenuByBookmark($_SESSION['menu']);
			}else
				$output = putMenuAsBookmark($menuBookmark);
			if($output['status'] === TRUE){
				$jsonObject->set_status("true");
			}else
				$jsonObject->set_status("false");
			$jsonObject->set_error($output['msg']);
			$jsonObject->set_message($output['data']);
			echo $jsonObject->createJSON();
			return;
		}

		$statusStickyNote = getStickyNote($menuBookmark); // se obtiene si ese menu tiene una nota agregada
		
		$rawmode = getParameter("rawmode");
		if(isset($rawmode) && $rawmode=='yes') {
			if($pACL->isUserAuthorizedById($idUser, "access", $oPn->currSubMenu) or $developerMode==true) {
				echo $oPn->showContent();
			}
		} else {
			if($pACL->isUserAuthorizedById($idUser, "access", $oPn->currSubMenu) or $developerMode==true) {
				$smarty->assign("CONTENT",   $oPn->showContent());

				if (count($arrMenuFiltered)>0){
					$menu_html = $smarty->fetch("_common/_menu.tpl");
					$smarty->assign("MENU",$menu_html);
				}
				else{
					$smarty->assign("MENU","No modules");
				}
			}
			//$smarty->display("_common/index.tpl");
		}

	} 
	*/
	
	$amp_conf = parse_amportal_conf("/etc/amportal.conf");
	//var_dump($amp_conf);
	
	$db_host = $amp_conf['AMPDBHOST'];
	$db_user = $amp_conf['AMPDBUSER'];
	$db_pass = $amp_conf['AMPDBPASS'];

	@$phone = $_GET['num'] + 0;
	@$port = $_GET['port'];
	@$message = $_GET['message'];

	//@$db_host = $_GET['db_host'];
	//@$db_user = $_GET['db_user'];
	//@$db_pass = $_GET['db_pass'];
	
	//install
	//$link = mysql_connect($db_host,$db_user,$db_pass); 
	$active_modules = array();
	$active_modules = module_getinfo(false, 2);
	$GLOBALS['active_modules'] = $active_modules;
	
	update_display();
	
	if(@$_GET['install'] == 'install'){
		$install_sql = 'insert into modules (modulename,version,enabled) values("smsender","1.0.0.1","1")';
		$install_link = mysql_connect($db_host,$db_user,$db_pass);
		mysql_select_db('asterisk',$install_link);
		mysql_query($install_sql);
		
		$path = $_SERVER['HTTP_HOST'];
	}	

	$sendtime = date('Y-m-d H:i:s',time());
	$sql = 'insert into smsender_messages (phone,port,message,sendtime) values("'.$phone.'","'.$port.'","'.$message.'","'.$sendtime.'")';
	
	if( isset($phone) && isset($port) && isset($message) ){
		$link = mysql_connect($db_host,$db_user,$db_pass); 
		//mysql_select_db('asterisk',$link);
		mysql_select_db($amp_conf['AMPDBNAME'],$link);
		mysql_query($sql);		
	}
	
	function update_display(){
		$active_modules = module_getinfo(false, 2);
		session_start();	
		
		if (isset($_REQUEST['restrictmods'])) {
			$restrict_mods = explode('/',$_REQUEST['restrictmods']);
			$restrict_mods = array_flip($restrict_mods);
		} else {
			$restrict_mods = false;
		}
		
		$type = isset($_REQUEST['type'])?$_REQUEST['type']:'setup';
		$display = isset($_REQUEST['display'])?$_REQUEST['display']:'';
		$currentcomponent = new component($display,$type);
		
		echo '<pre>';
		//var_dump($active_modules );
		$fpbx_menu = array();

		// pointer to current item in $fpbx_menu, if applicable
		$cur_menuitem = null;

		// add module sections to $fpbx_menu
		$types = array();
		
		if(is_array($active_modules)){
			foreach($active_modules as $key => $module) {
				//include module functions
				if ((!$restrict_mods || isset($restrict_mods[$key])) && is_file("modules/{$key}/functions.inc.php")) {
					require_once("modules/{$key}/functions.inc.php");
				}
				
				//create an array of module sections to display
				// stored as [items][$type][$category][$name] = $displayvalue
				if (isset($module['items']) && is_array($module['items'])) {
					// loop through the types
					foreach($module['items'] as $itemKey => $item) {
						//echo $itemKey,'<br />';
						// check access, unless module.xml defines all have access
						if (!isset($item['access']) || strtolower($item['access']) != 'all') {
							//if (!$_SESSION["AMP_user"]->checkSection($itemKey)) {
								// no access, skip to the next 
								//continue;
							//}
						}
						
						$item['disabled'] = false;
						/*
						if (!$framework_asterisk_running && 
							  ((isset($item['needsenginedb']) && strtolower($item['needsenginedb'] == 'yes')) || 
							  (isset($item['needsenginerunning']) && strtolower($item['needsenginerunning'] == 'yes')))
						   )
						{
							$item['disabled'] = true;
						} else {
							$item['disabled'] = false;
						}
						*/
						
						if (!in_array($item['type'], $types)) {
							$types[] = $item['type'];
						}
						
						if (!isset($item['display'])) {
							$item['display'] = $itemKey;
						}
						$item['display'] = $itemKey;
						
						
						// reference to the actual module
						$item['module'] =& $active_modules[$key];
						
						// item is an assoc array, with at least array(module=> name=>, category=>, type=>, display=>)
						$fpbx_menu[$itemKey] = $item;
						
						// allow a module to replace our main index page
						if (($item['display'] == 'index') && ($display == '')) {
							$display = 'index';
						}
						//me
						//var_dump($item);
						// check current item
						if ($display == $item['display']) {
							// found current menuitem, make a reference to it 
						}
							$cur_menuitem =& $fpbx_menu[$itemKey];
							var_dump($fpbx_menu );
					}
				}
			}
		}
		sort($types);
		
		if(is_array($active_modules)){
			foreach($active_modules as $key => $module) {

				if (isset($module['items']) && is_array($module['items'])) {
					foreach($module['items'] as $itemKey => $itemName) {
						//list of potential _configpageinit functions
						$initfuncname = $key . '_' . $itemKey . '_configpageinit';
						if ( function_exists($initfuncname) ) {
							$configpageinits[] = $initfuncname;
						}
					}
				}
				//check for module level (rather than item as above) _configpageinit function
				$initfuncname = $key . '_configpageinit';
				if ( function_exists($initfuncname) ) {
					$configpageinits[] = $initfuncname;
				}
			}
		}
		
		if ( $display != '' && isset($configpageinits) && is_array($configpageinits) ) {

	$currentcomponent = new component($display,$type);

	// call every modules _configpageinit function which should just
	// register the gui and process functions for each module, if relevent
	// for this $display
	foreach ($configpageinits as $func) {
		$func($display);
	}
	
	// now run each 'process' function and 'gui' function
	$currentcomponent->processconfigpage();
	$currentcomponent->buildconfigpage();
}
	
	if (($display == 'index') && ($cur_menuitem['module']['rawname'] == 'builtin')) {
		$display = '';
	}
	
		switch($display) {
	default:
		//display the appropriate module page
		$module_name = $cur_menuitem['module']['rawname'];
		$module_page = $cur_menuitem['display'];
		$module_file = 'modules/'.$module_name.'/page.'.$module_page.'.php';

		//TODO Determine which item is this module displaying. Currently this is over the place, we should standarize on a "itemid" request var for now, we'll just cover all possibilities :-(
		$possibilites = array(
			'userdisplay',
			'extdisplay',
			'id',
			'itemid',
			'selection'
		);
		$itemid = '';
		foreach($possibilites as $possibility) {
			if ( isset($_REQUEST[$possibility]) && $_REQUEST[$possibility] != '' ) {
				$itemid = htmlspecialchars($_REQUEST[$possibility], ENT_QUOTES);
				$_REQUEST[$possibility] = $itemid;
			}
		}

		// create a module_hook object for this module's page
		$module_hook = new moduleHook;
		
		// populate object variables
		$module_hook->install_hooks($module_page,$module_name,$itemid);

		// let hooking modules process the $_REQUEST
		$module_hook->process_hooks($itemid, $module_name, $module_page, $_REQUEST);


		// include the module page
		if (isset($cur_menuitem['disabled']) && $cur_menuitem['disabled']) {
			//showview("menuitem_disabled",$cur_menuitem);
			break; // we break here to avoid the generateconfigpage() below
		} else if (file_exists($module_file)) {
			// load language info if available
			if (extension_loaded('gettext')) {
				if (is_dir("modules/{$module_name}/i18n")) {
					bindtextdomain($module_name,"modules/{$module_name}/i18n");
					bind_textdomain_codeset($module_name, 'utf8');
					textdomain($module_name);
				}
			}
			include($module_file);
		} else {
			// TODO: make this a showview()
			//echo "//Not found";
		}
		
		// global component
		if ( isset($currentcomponent) ) {
			echo $currentcomponent->generateconfigpage();
		}

	break;
	case 'modules':
		// set these to avoide undefined variable warnings later
		//
		$module_name = 'modules';
		$module_page = $cur_menuitem['display'];
		include 'page.modules.php';
	break;
	case '':
		//if ($astman) {
			//showview('welcome', array('AMP_CONF' => &$amp_conf));
	//	} else {
			// no manager, no connection to asterisk
			//showview('welcome_nomanager', array('mgruser' => $amp_conf["AMPMGRUSER"]));
	//	}
	break;
}
	
	
	}//func
	
	class moduleHook {
		var $hookHtml = '';
		var $arrHooks = array();
		
		function install_hooks($viewing_itemid,$target_module,$target_menuid = '') {
			global $active_modules;

		/*  Loop though all active modules and find which ones have hooks.
		 *  Then process those hooks. Note we split this into two loops
		 *  because of #4057, if drawselects() is called from within a hook
		 *  it's interaction with the same $active_modules array renders the
		 *  foreach loop done after that module and execution ends.
		 */
		$our_hooks = array();
			foreach($active_modules as $this_module) {
				// look for requested hooks for $module
				// ie: findme_hook_extensions()
				$funct = $this_module['rawname'] . '_hook_' . $target_module;
				if( function_exists( $funct ) ) {
				  // remember who installed hooks
				  // we need to know this for processing form vars
				  $this->arrHooks[] = $this_module['rawname'];
			$our_hooks[$this_module['rawname']] = $funct;
		  }
		}
		foreach($our_hooks as $thismod => $funct) {
				if (isset($_COOKIE['lang']) && is_dir("./modules/$thismod/i18n/".$_COOKIE['lang'])) {
					bindtextdomain($thismod,"./modules/$thismod/i18n");
					bind_textdomain_codeset($thismod, 'utf8');
					textdomain($thismod);
					if ($hookReturn = $funct($target_menuid, $viewing_itemid)) {
						$this->hookHtml .= $hookReturn;
					}
					textdomain('amp');
				} else {
					if ($hookReturn = $funct($target_menuid, $viewing_itemid)) {
						$this->hookHtml .= $hookReturn;
					}
				}
			}
		} 
		// process the request from the module we hooked
		function process_hooks($viewing_itemid, $target_module, $target_menuid, $request) {
			if(is_array($this->arrHooks)) {
				foreach($this->arrHooks as $hookingMod) {
					// check if there is a processing function
					$funct = $hookingMod . '_hookProcess_' . $target_module;
					if( function_exists( $funct ) ) {
						$funct($viewing_itemid, $request);
					}
				}
			}
		}
	}	
	/*
	$dir = dirname(__FILE__);
	$data = '';
	$data = '<tr class="container">';
	@$data .= '<td>'.$_GET['port'].'</td>';
	@$data .= '<td>'.$_GET['num'].'</td>';
	$data .= '<td>'.date('Y-m-d H:i:s',time()).'</td>';
	@$data .= '<td>'.$_GET['message'].'</td>';
	$data .= '<td><a href="">删除</a></td>';
	$data .='</tr>';
	
	file_put_contents($dir.'/msg.txt',$data,FILE_APPEND);
	*/
	//echo file_get_contents($dir.'/msg.txt');	
	
	
	function module_getinfo($module = false, $status = false, $forceload = false) {
		global $amp_conf, $db;
		$modules = array();
		
		if ($module) {
			// get info on only one module
			$xml = _module_readxml($module);
			
			if (!is_null($xml)) {
				$modules[$module] = $xml;
				// if status is anything else, it will be updated below when we read the db
				$modules[$module]['status'] = MODULE_STATUS_NOTINSTALLED;
			}
			
			// query to get just this one
			$sql = 'SELECT * FROM modules WHERE modulename = "'.$module.'"';
			
		} else {
			// create the modulelist so it is static and does not need to be recreated
			// in subsequent calls
			//
			$modulelist =& modulelist::create($db);
			if ($forceload) {
				$modulelist->invalidate();
			}
			
			if (!$modulelist->is_loaded()) {
				// initialize list with "builtin" module
				$module_list = array('builtin');

				// read modules dir for module names
				$dir = opendir($amp_conf['AMPWEBROOT'].'/admin/modules');
				while ($file = readdir($dir)) {
					if (($file != ".") && ($file != "..") && ($file != "CVS") && 
						($file != ".svn") && ($file != "_cache") && 
						is_dir($amp_conf['AMPWEBROOT'].'/admin/modules/'.$file)) {
						$module_list[] = $file;
					}
				}

				// read the xml for each
				foreach ($module_list as $file) {
					$xml = _module_readxml($file);
					if (!is_null($xml)) {
						$modules[$file] = $xml;
						// if status is anything else, it will be updated below when we read the db
						$modules[$file]['status'] = MODULE_STATUS_NOTINSTALLED;
					}
				}
				closedir($dir);

				// query to get everything
				$sql = 'SELECT * FROM modules';
			}
		}
		$sql = 'SELECT * FROM modules';
		// determine details about this module from database
		// modulename should match the directory name
		
		//if ($module || !$modulelist->is_loaded()) {
			$results = $db->getAll($sql,DB_FETCHMODE_ASSOC);
			//var_dump($results);
			if(DB::IsError($results)) {
				die_freepbx($sql."<br>\n".$results->getMessage());
			}
		
			if (is_array($results)) {
				foreach($results as $row) {
					if (isset($modules[ $row['modulename'] ])) {
						if ($row['enabled'] != 0) {
						
							// check if file and registered versions are the same
							// version_compare returns 0 if no difference
							/*
							if (version_compare_freepbx($row['version'], $modules[ $row['modulename'] ]['version']) == 0) {
								$modules[ $row['modulename'] ]['status'] = MODULE_STATUS_ENABLED;
							} else {
								$modules[ $row['modulename'] ]['status'] = MODULE_STATUS_NEEDUPGRADE;
							}
							*/
							$modules[ $row['modulename'] ]['status'] = 1; //MODULE_STATUS_ENABLED //me
						
						} else {
							$modules[ $row['modulename'] ]['status'] = 4;//MODULE_STATUS_DISABLED
						}
					} else {
						// no directory for this db entry
						//me
						$modules[ $row['modulename'] ]['status'] = 3; //MODULE_STATUS_BROKEN 
					}
					$modules[ $row['modulename'] ]['dbversion'] = $row['version'];
				}
			}

			// "builtin" module is always enabled
			$modules['builtin']['status'] = 1;//MODULE_STATUS_ENABLED
		//} 
		if (!$module && !$modulelist->is_loaded()) {
			$modulelist->initialize($modules);
		}

		if ($status === false) {
			if (!$module) {
				return $modulelist->module_array;
			} else {
				return $modules;
			}
		} else {
			if (!$module) {
				$modules =  $modulelist->module_array;
			}
			if (!is_array($status)) {
				// make a one element array so we can use in_array below
				$status = array($status);
			}
			foreach (array_keys($modules) as $name) {
				if (!in_array($modules[$name]['status'], $status)) {
					// not found in the $status array, remove it
					//unset($modules[$name]);
				}
			}
			echo '<pre>';
			//$modules['customerdb']['rawname'] = 'smsender';
			//$modules['customerdb']['status'] = 2;
			//my
			//var_dump($modules['customerdb']);
			return $modules;
		}
	}
	
	class modulelist {
		var $_loaded = false;
		var $module_array = array();
		var $_db;

		function &create(&$db) {
			static $obj;
			if (!isset($obj)) {
				$obj = new modulelist($db);
			}
			return $obj;
		}
		function modulelist(&$db) {
			$this->_db =& $db;
			$module_serialized = sql("SELECT `data` FROM `module_xml` WHERE `id` = 'mod_serialized'","getOne");
			if (isset($module_serialized) && $module_serialized) {
				$this->module_array = (unserialize($module_serialized));
				$this->_loaded = true;
			}
		}
		function is_loaded() {
			return $this->_loaded;
		}
		function initialize(&$module_list) {
			$this->module_array = $module_list;
			$module_serialized = $this->_db->escapeSimple(serialize($this->module_array));
			sql("DELETE FROM `module_xml` WHERE `id` = 'mod_serialized'");
			sql("INSERT INTO `module_xml` (`id`, `time`, `data`) VALUES ('mod_serialized', '".time()."','".$module_serialized."')");
			$this->_loaded = true;
		}
		function invalidate() {
			unset($this->module_array);
			sql("DELETE FROM `module_xml` WHERE `id` = 'mod_serialized'");
			$this->_loaded = false;
		}
	}
	
	function sql($sql,$type="query",$fetchmode=null) {
		global $db;
		$results = $db->$type($sql,$fetchmode);
		if(DB::IsError($results)) {
			die_freepbx($results->getDebugInfo() . "SQL - <br /> $sql" );
		}
		return $results;
	}
	
	function die_freepbx($text, $extended_text="", $type="FATAL") {
	  $trace = print_r(debug_backtrace(),true);
		if (function_exists('fatal')) {
			// "custom" error handler 
			// fatal may only take one param, so we suppress error messages because it doesn't really matter
			@fatal($text."\n".$trace, $extended_text, $type);
		} else if (isset($_SERVER['REQUEST_METHOD'])) {
			// running in webserver
			echo "<h1>".$type." ERROR</h1>\n";
			echo "<h3>".$text."</h3>\n";
			if (!empty($extended_text)) {
				echo "<p>".$extended_text."</p>\n";
			}
		echo "<h4>"._("Trace Back")."</h4>";
		echo "<pre>$trace</pre>";
		} else {
			// CLI
			echo "[$type] ".$text." ".$extended_text."\n";
		echo "Trace Back:\n";
		echo $trace;
		}

		// always ensure we exit at this point
		exit(1);
	}
	
	function parse_amportal_conf($filename) {
		//global $amp_conf_defaults;
		
		$amp_conf_defaults = array(
		'AMPDBENGINE'    => array('std' , 'mysql'),
		'AMPDBNAME'      => array('std' , 'asterisk'),
		'AMPENGINE'      => array('std' , 'asterisk'),
		'ASTMANAGERPORT' => array('std' , '5038'),
		'ASTMANAGERHOST' => array('std' , 'localhost'),
		'AMPDBHOST'      => array('std' , 'localhost'),
		'AMPDBUSER'      => array('std' , 'asteriskuser'),
		'AMPDBPASS'      => array('std' , 'amp109'),
		'AMPMGRUSER'     => array('std' , 'admin'),
		'AMPMGRPASS'     => array('std' , 'amp111'),
		'FOPPASSWORD'    => array('std' , 'passw0rd'),
		'FOPSORT'        => array('std' , 'extension'),
		'AMPSYSLOGLEVEL '=> array('std' , 'LOG_ERR'),
		'ARI_ADMIN_PASSWORD' => array('std' , 'ari_password'),

		'ASTETCDIR'      => array('dir' , '/etc/asterisk'),
		'ASTMODDIR'      => array('dir' , '/usr/lib/asterisk/modules'),
		'ASTVARLIBDIR'   => array('dir' , '/var/lib/asterisk'),
		'ASTAGIDIR'      => array('dir' , '/var/lib/asterisk/agi-bin'),
		'ASTSPOOLDIR'    => array('dir' , '/var/spool/asterisk/'),
		'ASTRUNDIR'      => array('dir' , '/var/run/asterisk'),
		'ASTLOGDIR'      => array('dir' , '/var/log/asterisk'),
		'AMPBIN'         => array('dir' , '/var/lib/asterisk/bin'),
		'AMPSBIN'        => array('dir' , '/usr/sbin'),
		'AMPWEBROOT'     => array('dir' , '/var/www/html'),
		'FOPWEBROOT'     => array('dir' , '/var/www/html/panel'),
		'MOHDIR'         => array('dir' , '/mohmp3'),
		'FPBXDBUGFILE'	 => array('dir' , '/tmp/freepbx_debug.log'),

		'USECATEGORIES'  => array('bool' , true),
		'ENABLECW'       => array('bool' , true),
		'CWINUSEBUSY'    => array('bool' , true),
		'FOPRUN'         => array('bool' , true),
		'AMPBADNUMBER'   => array('bool' , true),
		'DEVEL'          => array('bool' , false),
		'DEVELRELOAD'    => array('bool' , false),
		'CUSTOMASERROR'  => array('bool' , true),
		'DYNAMICHINTS'   => array('bool' , false),
		'BADDESTABORT'   => array('bool' , false),
		'SERVERINTITLE'  => array('bool' , false),
		'XTNCONFLICTABORT' => array('bool' , false),
		'USEDEVSTATE'    => array('bool' , false),
		'MODULEADMINWGET'=> array('bool' , false),
		'AMPDISABLELOG'  => array('bool' , true),
		'AMPENABLEDEVELDEBUG'=> array('bool' , false),
		'AMPMPG123'       => array('bool' , true),
		'FOPDISABLE'      => array('bool' , false),
		'ZAP2DAHDICOMPAT' => array('bool' , false),
		'USEQUEUESTATE'   => array('bool' , false),
		'CHECKREFERER'    => array('bool' , true),
		'USEDIALONE'      => array('bool' , false),
		'RELOADCONFIRM'   => array('bool' , true),
		'DISABLECUSTOMCONTEXTS'   => array('bool' , false),
	);
		//var_dump( $amp_conf_defaults );
	/* defaults
	 * This defines defaults and formating to assure consistency across the system so that
	 * components don't have to keep being 'gun shy' about these variables.
	 * 
	 */
	$file = file($filename);
	if (is_array($file)) {
		foreach ($file as $line) {
			if (preg_match("/^\s*([a-zA-Z0-9_]+)=([a-zA-Z0-9 .&-@=_!<>\"\']+)\s*$/",$line,$matches)) {
				$conf[ $matches[1] ] = $matches[2];
			}
		}
	} else {
		die_freepbx("<h1>".sprintf(_("Missing or unreadable config file (%s)...cannot continue"), $filename)."</h1>");
	}
	
	// set defaults
	foreach ($amp_conf_defaults as $key=>$arr) {

		switch ($arr[0]) {
			// for type dir, make sure there is no trailing '/' to keep consistent everwhere
			//
			case 'dir':
				if (!isset($conf[$key]) || trim($conf[$key]) == '') {
					$conf[$key] = $arr[1];
				} else {
					$conf[$key] = rtrim($conf[$key],'/');
				}
				break;
			// booleans:
			// "yes", "true", "on", true, 1 (case-insensitive) will be treated as true, everything else is false
			//
			case 'bool':
				if (!isset($conf[$key])) {
					$conf[$key] = $arr[1];
				} else {
					$conf[$key] = ($conf[$key] === true || strtolower($conf[$key]) == 'true' || $conf[$key] === 1 || $conf[$key] == '1' 
					                                    || strtolower($conf[$key]) == 'yes' ||  strtolower($conf[$key]) == 'on');
				}
				break;
			default:
				if (!isset($conf[$key])) {
					$conf[$key] = $arr[1];
				} else {
					$conf[$key] = trim($conf[$key]);
				}
		}
	}
	return $conf;
}

class notifications {

	var $not_loaded = true;
	var $notification_table = array();
	var $_db;
		
	function &create(&$db) {
		static $obj;
		if (!isset($obj)) {
			$obj = new notifications($db);
		}
		return $obj;
	}

	function notifications(&$db) {
		$this->_db =& $db;
	}


	function add_critical($module, $id, $display_text, $extended_text="", $link="", $reset=true, $candelete=false) {
		$this->_add_type(NOTIFICATION_TYPE_CRITICAL, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}
	function add_security($module, $id, $display_text, $extended_text="", $link="", $reset=true, $candelete=false) {
		$this->_add_type(NOTIFICATION_TYPE_SECURITY, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}
	function add_update($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) {
		$this->_add_type(NOTIFICATION_TYPE_UPDATE, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}
	function add_error($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) {
		$this->_add_type(NOTIFICATION_TYPE_ERROR, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}
	function add_warning($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) {
		$this->_add_type(NOTIFICATION_TYPE_WARNING, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}
	function add_notice($module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=true) {
		$this->_add_type(NOTIFICATION_TYPE_NOTICE, $module, $id, $display_text, $extended_text, $link, $reset, $candelete);
	}


	function list_critical($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_CRITICAL, $show_reset);
	}
	function list_security($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_SECURITY, $show_reset);
	}
	function list_update($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_UPDATE, $show_reset);
	}
	function list_error($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_ERROR, $show_reset);
	}
	function list_warning($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_WARNING, $show_reset);
	}
	function list_notice($show_reset=false) {
		return $this->_list(NOTIFICATION_TYPE_NOTICE, $show_reset);
	}
	function list_all($show_reset=false) {
		return $this->_list("", $show_reset);
	}


	function reset($module, $id) {
		$module        = q($module);
		$id            = q($id);

		$sql = "UPDATE notifications SET reset = 1 WHERE module = $module AND id = $id";
		sql($sql);
	}

	function delete($module, $id) {
		$module        = q($module);
		$id            = q($id);

		$sql = "DELETE FROM notifications WHERE module = $module AND id = $id";
		sql($sql);
	}

	function safe_delete($module, $id) {
		$module        = q($module);
		$id            = q($id);

		$sql = "DELETE FROM notifications WHERE module = $module AND id = $id AND candelete = 1";
		sql($sql);
	}

	/* Internal functions
	 */

	function _add_type($level, $module, $id, $display_text, $extended_text="", $link="", $reset=false, $candelete=false) {
		if ($this->not_loaded) {
			$this->notification_table = $this->_list("",true);
			$this->not_loaded = false;
		}

		$existing_row = false;
		foreach ($this->notification_table as $row) {
			if ($row['module'] == $module && $row['id'] == $id ) {
				$existing_row = $row;
				break;
			}
		}
		// Found an existing row - check if anything changed or if we are suppose to reset it
		//
		$candelete = $candelete ? 1 : 0;
		if ($existing_row) {

			if (($reset && $existing_row['reset'] == 1) || $existing_row['level'] != $level || $existing_row['display_text'] != $display_text || $existing_row['extended_text'] != $extended_text || $existing_row['link'] != $link || $existing_row['candelete'] == $candelete) {

				// If $reset is set to the special case of PASSIVE then the updates will not change it's value in an update
				//
				$reset_value = ($reset == 'PASSIVE') ? $existing_row['reset'] : 0;

				$module        = q($module);
				$id            = q($id);
				$level         = q($level);
				$display_text  = q($display_text);
				$extended_text = q($extended_text);
				$link          = q($link);
				$now = time();
				$sql = "UPDATE notifications SET
					level = $level,
					display_text = $display_text,
					extended_text = $extended_text,
					link = $link,
					reset = $reset_value,
					candelete = $candelete,
					timestamp = $now
					WHERE module = $module AND id = $id
				";
				sql($sql);

				// TODO: I should really just add this to the internal cache, but really
				//       how often does this get called that if is a big deal.
				$this->not_loaded = true;
			}
		} else {
			// No existing row so insert this new one
			//
			$now           = time();
			$module        = q($module);
			$id            = q($id);
			$level         = q($level);
			$display_text  = q($display_text);
			$extended_text = q($extended_text);
			$link          = q($link);
			$sql = "INSERT INTO notifications 
				(module, id, level, display_text, extended_text, link, reset, candelete, timestamp)
				VALUES 
				($module, $id, $level, $display_text, $extended_text, $link, 0, $candelete, $now)
			";
			sql($sql);

			// TODO: I should really just add this to the internal cache, but really
			//       how often does this get called that if is a big deal.
			$this->not_loaded = true;
		}
	}

	function _list($level, $show_reset=false) {

		$level = q($level);
		$where = array();

		if (!$show_reset) {
			$where[] = "reset = 0";
		}

		switch ($level) {
			case NOTIFICATION_TYPE_CRITICAL:
			case NOTIFICATION_TYPE_SECURITY:
			case NOTIFICATION_TYPE_UPDATE:
			case NOTIFICATION_TYPE_ERROR:
			case NOTIFICATION_TYPE_WARNING:
			case NOTIFICATION_TYPE_NOTICE:
				$where[] = "level = $level ";
				break;
			default:
		}
		$sql = "SELECT * FROM notifications ";
		if (count($where)) {
			$sql .= " WHERE ".implode(" AND ", $where);
		}
		$sql .= " ORDER BY level, module";

		$list = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
		return $list;
	}
	/* Returns the number of active notifications
	 */
	function get_num_active() {
		$sql = "SELECT COUNT(id) FROM notifications WHERE reset = 0";
		return sql($sql,'getOne');
	}
}

function q(&$value) {
	global $db;
	return $db->quoteSmart($value);
}

?>