<?php
// +---------------------------------------------------------------------------------------+
// | TenderSystem                                                                          |
// +---------------------------------------------------------------------------------------+
// | The contents of this file are subject to the TenderSystem Public License Version 1.1  |
// | ("License"); you may not use this file except in compliance with the License. You may |
// | obtain a copy of the License at http://www.tendersystem.com/tpl/                      |
// |                                                                                       |
// | Software distributed under the License is distributed on an "AS IS" basis, WITHOUT    |
// | WARRANTY OF ANY KIND, either express or implied. See the License for the specific     |
// | language governing rights and limitations under the License.                          |
// |                                                                                       |
// | All copies of the Covered Code must include the "Powered by TenderSystem" logo and    |
// | ValueCard copyright notice on every user interface screen and in every outgoing       |
// | email in the same form as they appear in the distribution.                            |
// |                                                                                       |
// | The Original Code is: TenderSystem                                                    |
// | The Initial Developer of the Original Code is ValueCard (Pty) Limited.                |
// | Portions created by ValueCard are Copyright (C) 2002 ValueCard (Pty) Limited.         |
// | All Rights Reserved.                                                                  |
// | Contributor(s): __________________.                                                   |
// +---------------------------------------------------------------------------------------+

/**
* Generic functions
* @package TenderSystem
* @subpackage generic
* @copyright Copyright &copy; 2002, ValueCard (Pty) Ltd
* @license http://www.tendersystem.com/tpl/ TenderSystem Public License
* @version 
*/

// Security - ensure that file never called directly
if (eregi("generic.php",$_SERVER['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

// set that no errors are echo'd as that messes up xml
ini_set("display_errors", "0");

// load required files
require(getcwd().'/modules/settings/config.inc.php');

/**
 * Start the session
*/
if (!isset($_SESSION)) {
	session_start();
}
// no cache
header('Cache-Control: no-cache');
header('Pragma: no-cache');
// IE bug fix
header('P3P: CP="CAO PSA OUR"');

/**
 * set xslt session if not present
 * @note: Must be at the top of generic
 */
if (!isset($_SESSION['ts_xslt'])) {
	// determine to do client or server side xslt parsing
	if ($cfg['xslt'] == 'browser') {
		// determine wether or not client browser is xslt enabled
		$xslt_enabled = determine_browser($_SERVER['HTTP_USER_AGENT']);
		if ($xslt_enabled) {
			$_SESSION['ts_xslt'] = 'yes';
		} else {
			$_SESSION['ts_xslt'] = 'no';
		}
	} elseif ($cfg['xslt'] == 'client') {
		// config set to always do client side xslt processing
		$_SESSION['ts_xslt'] = 'yes';
	} elseif ($cfg['xslt'] == 'sablotron' || $cfg['xslt'] == 'libxslt') {
		// config set to always do server side xslt processing
		$_SESSION['ts_xslt'] = 'no';
	}
	// determine if browser can accept gzip encoded pages
	if ($_SESSION['ts_xslt'] == 'yes' && strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip')) {
		$_SESSION['ts_gzip'] = TRUE;
	} else {
		$_SESSION['ts_gzip'] = FALSE;
	}
}

/**
* Timing function
* @return integer time
*/
// if timing is set
if ($cfg['timer'] == "TRUE") {
	// function to start the timer
	function start_timer() {
		$start_time = explode(' ',microtime());
		$start_time = $start_time[1] + $start_time[0];
		return $start_time;
	}
	// function to end the time
	function end_timer($start_time) {
		// calculate the execution time
		if ($start_time) {
			$end_time = explode(' ', microtime());
			$end_time = $end_time[1] + $end_time[0];
			// calculate total execution
			$time = number_format($end_time - $start_time,4);
			// return ending time
			return $time;
		}
	}
	// start the timer
	$cfg['start_time'] = start_timer();
}

/**
 * API INTERFACE
*/
// send message to application server
function send_message($params,$cfg) {
	if (isset($_SESSION['ts_id'])) {
		$params['session'] = $_SESSION['ts_id'];
	}
	if (isset($_SERVER['REMOTE_ADDR'])) {
		$params['ip'] = $_SERVER['REMOTE_ADDR'];
	}
	if ($cfg['api']['debug']) {
		// set debug
		$params['debug'] = "true";
	}
	// determine if message must be sent via api or included
	if ($cfg['api']['connection'] == "curl") {
		// set GUI username and password
		if ($cfg['gui']['username'] && $cfg['gui']['password']) {
			$params['gui_username'] = $cfg['gui']['username'];
			$params['gui_password'] = $cfg['gui']['password'];
		}
		// set the paramater string
		$params_string['all'] = base64_encode(serialize($params));
		$params_string['crc32'] = crc32($params_string['all'] );
	  	// Send http POST - more secure than GET as headers are not encrypted
		// and no limit on information that can be transferred
	  	$ch = curl_init($cfg['api']['server']);
		if ($ch) {
			// do not display header in code output
			curl_setopt($ch, CURLOPT_HEADER, 0);
			// set so to POST
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
			// security to ensure that not diverted to another server
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
			// cache variables and do not print out
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			if($cfg['api']['dontverify']) {
				// do not verify peer
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
				// do not verify host
				curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
			}
			// store the response as variable
			$xml = curl_exec($ch);
			$curl_error = curl_error($ch);
			// close the connection
			curl_close($ch);
		} else {
			// e7 - TenderSystem API connection could not be established. Method used: Curl
			xml_generator('generic','error',"e7","",$cfg);
		}
	} else {
		// directly include the required module
		include(getcwd().'/application/include.php');
	}
	// set the header information
	if (isset($cfg['outputformat'])) {
		if ($cfg['outputformat'] == "CSV") {
			header("Content-type: csv");
			header("Content-Disposition: attachment; filename=\"".$cfg['areas']['filename']."\"");
			echo $xml;
			die();
		}
	}
	// no api response
	if (!$xml || !strpos($xml,"<response>")) {
		// generate and display the xml
		if ($cfg['api_request']) {
			return FALSE;	
		} else {
			// e8 - No api response
			if($curl_error) {
				$e['error_text'] = $curl_error;
			}
			xml_generator('generic','error',"e8",$e,$cfg);
		}
	}
	$xml = trim($xml);
	// determine if session created successfully
	$_SESSION['ts_expire'] = time() + event_parser('<expire>','</expire>',$xml);
	// if successfully logged in set the session paramaters
	if (isset($cfg['logging_in'])) {
		// determine if session created successfully
		$session = event_parser('<session>','</session>',$xml);
		if ($session) {
			// set the session paramaters
			$_SESSION['ts_id'] = $session;
			$_SESSION['ts_name'] = event_parser('<name>','</name>',$xml);
			$_SESSION['ts_surname'] = event_parser('<surname>','</surname>',$xml);
			$_SESSION['ts_classification'] = event_parser('<classification>','</classification>',$xml);
			$_SESSION['ts_permission'] = event_parser('<permission>','</permission>',$xml);
			$_SESSION['ts_theme'] = event_parser('<theme>','</theme>',$xml);
			$_SESSION['ts_lang'] = event_parser('<language>','</language>',$xml);
			// set the username session
			$_SESSION['ts_username'] = $params['username'];
		}
	} else {
		// determine if the session must be destroyed
		$session_expire = event_parser('<sessionexpire>','</sessionexpire>',$xml);
		if ($session_expire == 'true') {
			// destroy the session
			$_SESSION['ts_id'] = $_SESSION['ts_name'] = $_SESSION['ts_surname'] = $_SESSION['ts_classification'] = $_SESSION['ts_permission'] =
			$_SESSION['ts_theme'] = $_SESSION['ts_lang'] = "";
		}
	}
	// determine if xml must be displayed
	if ($cfg['api_request']) {
		// reset request
		$cfg['api_request'] = FALSE;
		// return the xml
		return $xml;
	} else {
		// display the api response
		display_response($xml,$cfg);
	}
}

/**
 * DISPLAY RESPONSE FUNCTION
*/
function display_response($xml,$cfg) {
	if($cfg['input']['type']) {
		$xml.= "\r\n";
		$xml.= "<constraints>\r\n";
		$xml.= "<phonemin>";
		$xml.= $cfg['input']['phone']['min'];
		$xml.= "</phonemin>\r\n";
		$xml.= "<phonemax>";
		$xml.= $cfg['input']['phone']['max'];
		$xml.= "</phonemax>\r\n";
		$xml.= "</constraints>\r\n";
	}
	// insert the footer if required
	if (!$cfg['hide_footer']) {
		$xml.= "\r\n";
		$xml.= "<footer>\r\n";
		$xml.= "<version>";
		$xml.= $cfg['version'];
		$xml.= "</version>\r\n";
		if ($cfg['start_time']) {
			$xml.= "<query>";
			$xml.= end_timer($cfg['start_time']);
			$xml.= "</query>\r\n";
		}
		if ($cfg['disclaimer']) {
			$xml.= "<disclaimer>".$cfg['disclaimer']."</disclaimer>\r\n";
		}
		if ($cfg['privacy']) {
			$xml.= "<privacy>".$cfg['privacy']."</privacy>\r\n";
		}
		$xml.= "</footer>\r\n";
	}
	// close response
	$xml.= "</response>\r\n";
	// display based on client or server side xslt
	if ((($cfg['xslt'] == "client" || $_SESSION['ts_xslt'] == "yes") && $cfg['force_xslt'] != "server")
		|| !has_xslt()) {
		// set the header
		header("Content-type: text/xml");
		// display
		echo $xml;
	} else {
		// get the xsl stylesheet file name from the xml
		$start_pos = strpos($xml,'href="');
		$end_pos = strpos($xml,'.xsl"');
		// determine if start_pos and end_pos present
		if ($start_pos === FALSE || $end_pos === FALSE) {
			echo "XSL stylesheet not present in the XML document.<br/>";
		} else {
			// strip anythings outside the fields
			$start_pos += 7;
			$end_pos += 4;
			$lenght = $end_pos - $start_pos;
			$xsl = substr($xml,$start_pos,$lenght);
			$filebase = getcwd();
			$xsl = $filebase.$xsl;
		}
		convert_xslt($xml,$xsl,$cfg);
	}
	// ensure that no other scripts are executed
	die();
}

function has_xslt() {
	return function_exists('xslt_create') || class_exists('XSLTProcessor');
}

function convert_xslt($xml,$xsl_file,$cfg) {
	$result = FALSE;
	// transform with sablotron
	if(function_exists('xslt_create') && ($cfg['xslt'] == "sablotron" || !class_exists('XSLTProcessor'))) {
		// set the xml as a paramater
		$arguments = array(
		     '/_xml' => $xml
		);
		// transform xml with xsl
		$transform = xslt_create();
		xslt_set_encoding($transform, 'UTF-8');
		$result = xslt_process($transform,'arg:/_xml',$xsl_file,NULL,$arguments);
		if ($result) {
			// strip any line breaks and white spaces
			if ($cfg['display']['strip']) {
				// remove new lines \\n, tabs and \\r
				$result = preg_replace("/(\\t|\\r|\\n)/","",$result);
				// strip extra white spaces
				$result = preg_replace('/\s\s+/', ' ', $result);
			}
			if ($cfg['display']['gzip']) {
				// see if browser encoding activated
				if ($_SESSION['ts_gzip']) {
					// compress the output with maximum compression
					$result = gzencode($result,9);
					// send http header
					header('Content-Encoding: gzip');
				}
			}
			// return
			echo $result;
		} else {
			// error
			trigger_error('Error transforming xml ('.$xsl_file.') : '.xslt_error($transform),E_USER_WARNING);
			// set the header information
			header("Content-type: text/xml");
			// display
			echo $xml;
		}
		xslt_free($transform);
	}
	// transform with libxslt 
	elseif(class_exists('XSLTProcessor') && ($cfg['xslt'] == "libxslt" || !function_exists('xslt_create'))) {
		$xsl = new XSLTProcessor();
		$xsl->importStyleSheet(DOMDocument::load($xsl_file));
		$result = $xsl->transformToXML(DOMDocument::loadXML($xml));
		if ($result) {
			// strip any line breaks and white spaces
			if ($cfg['display']['strip']) {
				// remove new lines \\n, tabs and \\r
				$result = preg_replace("/(\\t|\\r|\\n)/","",$result);
				// strip extra white spaces
				$result = preg_replace('/\s\s+/', ' ', $result);
			}
			if ($cfg['display']['gzip']) {
				// see if browser encoding activated
				if ($_SESSION['ts_gzip']) {
					// compress the output with maximum compression
					$result = gzencode($result,9);
					// send http header
					header('Content-Encoding: gzip');
				}
			}
			// return
			echo $result;
		} else {
			// error
			trigger_error('Error transforming xml with libxslt ('.$xsl_file.')',E_USER_WARNING);
			// set the header information
			header("Content-type: text/xml");
			// display
			echo $xml;
		}
	} else { // nothing to transform with
		echo $xml;
	}
}

/**
* XML Parser - lightweight event based xml parser
* 				Can not differnetiate between a child and parent element
* 				Might change to expat when it becomes more prolific
*/
function event_parser($start_element,$end_element,$xml) {
	// determine the start and end position
	$start_pos = strpos($xml,$start_element);
	$end_pos = strpos($xml,$end_element,$start_pos);
	// determine if start_pos and end_pos present
	if ($start_pos === FALSE || $end_pos === FALSE) {
		return FALSE;
	} else {
		// get the required field
		$start_pos += strlen($start_element);
		$lenght = $end_pos - $start_pos;
		$response = substr($xml,$start_pos,$lenght);
		$response = trim($response);
		return $response;
	}
}

/**
* XML Generator
* @return string xml
*/
function xml_generator($module,$function,$error,$paramater,$cfg) {
	$paramater['localprecurrency'] = $cfg['local']['precurrency'];
	$paramater['localpostcurrency'] = $cfg['local']['postcurrency'];
	// assume normal xsl
	$href="modules/".$module."/templates/".$function;
	// create the default xml file
	$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n";
	$xml.= "<?xml-stylesheet type=\"text/xsl\" href=\"./".$href.".xsl\" ?>\r\n\r\n";
	$xml.= "<response>\r\n";
	$xml.= " <user>\r\n";
	// name
	if (isset($_SESSION['ts_name'])) {
		$xml.= "  <name>".$_SESSION['ts_name']."</name>\r\n";
	}
	// surname
	if (isset($_SESSION['ts_surname'])) {
		$xml.= "  <surname>".$_SESSION['ts_surname']."</surname>\r\n";
	}
	// theme
	$aval_themes = get_themes();
	if (isset($_SESSION['ts_theme']) && in_array($_SESSION['ts_theme'],$aval_themes)) {
		$xml.= "  <theme>".$_SESSION['ts_theme']."</theme>\r\n";
	} else {
		$xml.= "  <theme>".$cfg['theme']."</theme>\r\n";
	}
	// lang
	$aval_lang = get_languages();
	if (isset($_SESSION['ts_lang']) && in_array($_SESSION['ts_lang'],$aval_lang)) {
		$xml.= "  <language>".$_SESSION['ts_lang']."</language>\r\n";
		$language = $_SESSION['ts_lang'];
	} else {
		$xml.= "  <language>".$cfg['language']."</language>\r\n";
		$language = $cfg['language'];
	}
	// type
	if (isset($_SESSION['ts_classification'])) {
		$xml.= "  <classification>".$_SESSION['ts_classification']."</classification>\r\n";
	}
	// permission
	if (isset($_SESSION['ts_permission'])) {
		$xml.= "  <permission>".$_SESSION['ts_permission']."</permission>\r\n";
	}
	if (isset($_SESSION['ts_expire'])) {
		$expire = intval($_SESSION['ts_expire'] - time());
		if($expire > 0) {
			$xml.= "  <expire>".$expire."</expire>\r\n";
		}
	}
	// display error codes
	if ($cfg['error']['codes']) {
		$xml.= "  <errorcodes/>\r\n";
	}
	$xml.= " </user>\r\n";
	// if username or password is not present
	if ($error) {
		include(getcwd()."/application/include/modules/generic/language/".$language."/error.php");
		// filter out generic errors
		if (is_array($error)) {
			foreach($error as $value) {
				if(!$lang[$value]) {
					$xml.= " <error>".$value."</error>\r\n";
				} else {
					if($cfg['error']['codes']) {
						$xml.= " <error_text>".$value.":".$lang[$value]."</error_text>\r\n";
					} else {
						$xml.= " <error_text>".$lang[$value]."</error_text>\r\n";
					}
				}
			}
		} else {
			if(!$lang[$error]) {
				$xml.= " <error>".$error."</error>\r\n";
			} else {
				$xml.= " <error_text>".$error.":".$lang[$error]."</error_text>\r\n";
			}
		}
	}
	// insert array
	if (is_array($paramater)) {
		// set the xml
		$xml.= xml_loop($paramater);
	}
	// display
	display_response($xml,$cfg);
}

/**
* XML LOOP FUNCTION
* - required in xml_generator to set xml array
*/
function xml_loop($param) {
	$search = array('<','>');
	$replace = array('&lt;','&gt;');
	// set the array keys
	$array_keys = array_keys($param);
	// loop through every paramater
	foreach ($array_keys as $value) {
		// determine if it is an array
		if (is_array($param[$value])) {
			// determine the loop increment
			$size = sizeof($param[$value]);
			// loop through every response
			foreach ($param[$value] as $key1 => $value1) {
				// open the xml tag
				$response.= "<".$value.">";
				if (is_array($param[$value][$key1])) {
					// set a spacer
					$response.= "\r\n";
					// re loop through function
					$response.= xml_loop($param[$value][$key1]);
				} else {
					// populate
					$response.= str_replace($search,$replace,$param[$value][$key1]);
				}
				// close the xml tag
				$response.= "</".$value.">\r\n";
			}
		} else {
			// open the xml tag
			if(isset($response)) {
				$response.= "<".$value.">";
			} else {
				$response = "<".$value.">";
			}
			// populate
			$response.= str_replace($search,$replace,$param[$value]);
			// close the xml tag
			$response.= "</".$value.">\r\n";
		}
	}
	// response
	return $response;
}

/**
* SANITISE FUNCTION
* - ensure no html and javascript tags in form input
* @return mixed sanitised code
*/
function sanitise($str) {
	// Notice: \ removed from magic quote insert
	$unacceptable_array = array('<','>','&','\n','\'','\"','\\');
	$replace_array = array('&lt;','&gt;','&amp;','',' inch','&apos;','');
	// determine if it is an array
	if (is_array($str)) {
		// convert via the process_array function
		$response = process_array($str,$unacceptable_array,$replace_array);
	} else {
		// urldecode string
		$str = urldecode($str);
		// remove strings that are dangerous
		$response = trim(str_replace($unacceptable_array,$replace_array,$str));
	}
	return $response;
}

/**
* used in sanitise to loop through an array
* @return mixed sanitised code
*/
function process_array($str,$unacceptable_array,$replace_array) {
	// loop through every paramater and return a string containing the array
	foreach ($str as $key => $value) {
		// determine if the value is an array
		if (is_array($value)) {
			$response[$key] = process_array($str[$key],$unacceptable_array,$replace_array);
		} else {
			$response[$key] = trim(str_replace($unacceptable_array,$replace_array,$value));
		}
	}
	// return the string
	return $response;
}

/**
* determine if browser is XSLT capable
* @return boolean
*/
function determine_browser($browser) {
	// set xslt capable browsers
	$browser_array = array(
		"msie" 		=> "5",
		"firefox" 	=> "8",
		"netscape"	=> "9",
		"galeon"	=> "8"
	);
	// set browser to lower
	$browser = strtolower($browser);
	// determine if used
	foreach ($browser_array as $client => $size) {
		// present
		$position = strpos($browser,$client);
		if  ($position) {
			// get version
			$version = substr($browser, $position + $size,6);
			$version = preg_replace('/[^0-9,.]/','',$version);
			$capable = explode(".",$version);
			// determine xslt
			if ($client == "msie" || $client == "netscape") {
				// exploder and netscape since 6
				if ($capable[0] > 5) {
					return TRUE;
				}
			} elseif ($client == "firefox") {
				// firefox since 1 -> actually only became workable since 1.0.2
				if ($capable[0] > 0) {
					if ($capable[0] == "1" && $capable[1] == "0" && $capable[2] < 2) {
						return FALSE;
					} else {
						//return TRUE;
						return TRUE;
					}
				}
			}  elseif ($client == "galeon") {
				// works on 1.3.20 but will assume it works for 1.3 and higher
				if ($capable[0] > 0) {
					if ($capable[0] == "1" && $capable[1] == "3") {
						return FALSE;
					} else {
						//return TRUE;
						return TRUE;
					}
				}
			}
		}
	}
}

/**
* upload file to server
*/
function upload_file($file,$application,$cfg) {
	// determine if upload is active
	if ($cfg['upload']['active']) {
		// set the upload path
		$upload_path = $cfg['upload']['path'];
		if(file_exists($upload_path) && is_dir($upload_path)) {
			if(is_writable($upload_path)) {
				// new file name
				$filename = $application."_".time()."_".$file['name'];
				// upload destination
				$upload_dest = $upload_path."/".$filename;
				// check file size
				if ($file['size'] <= $cfg['upload']['filesize'] * 1000) {
					// set file information
					$file_type = substr(strrchr($file['name'], "."), 1);
					// determine if file type is allowable
					$allowed = $cfg['upload']['filetype'][$file_type];
					// importing / export
					if ($allowed || $cfg['upload']['any']) {
						// upload file
						if (copy($file['tmp_name'],$upload_dest)) {
							// set the file location
							return $upload_dest; 
						} else {
							// Could not copy file to Gui Upload Directory
							$fileinfo['error'] = "1013";
						}
					} else {
						// Error File type is not of allowable upload type
						$fileinfo['error'] = "1012";
					}
				} else {
					// error file size exceeds maximum allowable size
					$fileinfo['error'] = "1011";
				}
			} else {
				// Gui Upload Directory is not writable
				$fileinfo['error'] = "1010";
			}
		} else {
			// Upload directory does not exist or is not a valid directory
			$fileinfo['error'] = "1009";	
		}
	} else {
		// Gui Upload Inactive
		$fileinfo['error'] = "1008";
	}
	return $fileinfo;
}


/**
* parse excel spreadsheet
*/
function read_excel($upload_dest,$cfg) {
	// include required file
	require_once(getcwd().'/modules/external/class/spreadsheet/reader.php');
	// initialise the excel reader
	$new_excel = new Spreadsheet_Excel_Reader();
	// Set output Encoding
	$new_excel->setOutputEncoding('UTF-8');
	// read the first worksheet
	$new_excel->read($upload_dest);
	// loop through 1st worksheet starting at row 2 and place values in array
	for ($i = 2; $i <= $new_excel->sheets[0]['numRows']; $i++) {
		// limited to 5 colums
		for ($j = 1; $j <= $new_excel->sheets[0]['numCols']; $j++) {
			// insert in array
			$upload_array[$i-2][$j-1] = sanitise($new_excel->sheets[0]['cells'][$i][$j]);
		}
	}
	// return the product array
	return $upload_array;
}

/**
* read the settings file
* @return array
*/
function read_settings($file,$display_type,$valid_settings,$params,$errors,$cfg) {
	// read file into array
	$file_array = file($file);
	// check if file open okay
	if (!$file_array) {
		// Cannot open file
		// 1055 - Cannot open gui settings file
		xml_generator("generic","error","1055",$params,$cfg);
	} else {
		// initial values for all the_settings
		foreach($valid_settings as $key => $value) {
			$params['settings'][0][$key] = FALSE;
		}
		// go through the file
		foreach($file_array as $line) {
			$is_setting = strpos($line,"=");
			if($is_setting) {
				// for double quotes
				$start = strpos($line,'"',$is_setting);
				$end = strpos($line,'"',$start+1);
				// if not double quotes
				if(!$start) {
					// for single quotes
					$start = strpos($line,"'",$is_setting);
					$end = strpos($line,"'",$start+1); 
				}
				// if not single quotes
				if(!$start) {
					$start = $is_setting;
					$end = strpos($line,";",$start+1);
				}
				// get each setting using valid_settings
				foreach($valid_settings as $key => $value) {
					// get the setting
					if(strpos($line,"cfg".$value)){
						$params['settings'][0][$key] = trim(substr($line,$start + 1,$end - $start - 1));
						break;
					} 
				}
			}
		}
		if($display_type) {
			// response
			xml_generator("settings",$display_type,$errors,$params,$cfg);
		} else {
			return $params['settings'];
		}
	}
}

/**
* write a new settings file
* @return array
*/
function write_settings($file,$newguisettings,$guisettings) {
	// read file into array
	$file_array = file($file);
	// check if file open okay
	if (!$file_array) {
		// Cannot open File
		trigger_error(sprintf('Cannot open file : %s', $file), E_USER_WARNING);
		return FALSE;
	} else {
		// go through all lines
		foreach($file_array as $num => $line) {
			// replace needed location section
			foreach($newguisettings as $key => $value) {
				// if a setting match 
				if(strpos($line,$guisettings[$key]) !== FALSE) {
					// replace setting
					$file_array[$num] = "\$cfg".$guisettings[$key]." = ";
					// if a boolean type
					if(trim($value) == "TRUE" || trim($value) == "FALSE") {
						// leave out inverted commas
						$file_array[$num].= $value.";\n";
					} else {
						// else insert inverted commas
						$file_array[$num].= "'".str_replace("'","\\'",$value)."';\n"; 
					}
				}
			}
		}
		// on some platforms (happens on FREBSD 4) a wierd error happens when trying to write to
		// a file that was opened for reading instead, to writing to a different file is done and
		// then renamed
		if($cfg['settings']['rename']) {
			$real_file = $file;
			$file.=".tmp";	
		}
		// open file for writing
		$fp = fopen($file,"w+"); 
		// check if file open okay
		if (!$fp) {
			// Could not open file
			trigger_error(sprintf('Cannot open file for writing : %s', $file), E_USER_WARNING);
			return FALSE;
		} else {	
			// write new data back into file
			foreach($file_array as $line) {
				if(!fwrite($fp,$line,strlen($line))) {
					// Could not write to file 
					trigger_error(sprintf('Could not write to file : %s', $file), E_USER_WARNING);
					return FALSE;
				}
			}
			// close file
			fclose($fp);
		}
		// rename file
		if($cfg['settings']['rename']) {
			if(!rename($file,$real_file)) {
				// Could not write to file 
				trigger_error(sprintf('Could not rename file : %s', $file), E_USER_WARNING);
				return FALSE;
			}
		}
		return TRUE;
	}
}


/**
* return all files present in a directory recursively
* @return array
*/
function examinedir($dir = './',$include_dir=FALSE) {
	if(!file_exists($dir)) {
		return FALSE;
	}
	// open the directory
	$dir_open = opendir($dir); 
	if (!$dir_open) {
		return FALSE;
	}
	// loop through directory
	$file = array();
	while (($dir_content = readdir($dir_open)) !== false) {
		$full_path = $dir."/".$dir_content;
		if(is_dir($full_path) && $dir_content != "CVS" && $dir_content != ".svn" && $dir_content != "." && $dir_content != "..") {
			if($include_dir) {
				$file[] = $full_path;
			}
			$dir_files = examinedir($dir."/".$dir_content,$include_dir);
			if(is_array($dir_files) && $dir_files) { 
				$file = array_merge($file,$dir_files);
			} 
		} elseif(is_file($full_path)) {
			$file[] = $full_path;
		}
	}
   return $file;
}

/**
* return all directories in the folder
* @return array
*/
function list_directories($dir = './',$include_dir=TRUE) {
	if(!file_exists($dir)) {
		return FALSE;
	}
	// open the directory
	$dir_open = opendir($dir); 
	if (!$dir_open) {
		return FALSE;
	}
	// loop through directory
	$file = array();
	while (($dir_content = readdir($dir_open)) !== false) {
		$path = $dir."/".$dir_content;
		if(is_dir($path) && $dir_content!="." && $dir_content!=".." && $dir_content!="CVS" && $dir_content!=".svn") {
			if($include_dir) {
				$file[] = $path;
			} else {
				$file[] = $dir_content;
			}
		}
	}
   return $file;
}

/**
* return all files in the folder
* @return array
*/
function list_files($dir = './',$include_dir=TRUE) {
	if(!file_exists($dir)) {
		return FALSE;
	}
	// open the directory
	$dir_open = opendir($dir); 
	if (!$dir_open) {
		return FALSE;
	}
	// loop through directory
	$file = array();
	while (($dir_content = readdir($dir_open)) !== false) {
		$path = $dir."/".$dir_content;
		if(is_file($path) && $dir_content!="." && $dir_content!=".." && $dir_content!="CVS" && $dir_content!=".svn") {
			if($include_dir) {
				$file[] = $path;
			} else {
				$file[] = $dir_content;
			}
		}
	}
   return $file;
}

/**
* return all files in a folder
* @return array
*/
function get_themes() {
	return list_directories("theme",FALSE);
}

/**
* return all files in a folder
* @return array
*/
function get_languages() {
	return list_directories("modules/generic/language",FALSE);
}

/**
 * remove () -- Vigorously erase files and directories.
 *
 * @param $fileglob mixed If string, must be a file name (foo.txt) or directory name.
 *                        If array, must be an array of file names and/or directories.
 * 
 * @return boolean TRUE on success and FALSE on failure
 */
function remove($fileglob) {
	if(is_dir($fileglob)) {
		// open the directory
		$dir_open = opendir($fileglob); 
		if (!$dir_open) {
			// Cannot remove File
			trigger_error(sprintf('Cannot open folder : %s', $fileglob), E_USER_WARNING);
			return FALSE;
		}
		// go through each file
		while (($dir_content = readdir($dir_open)) !== false) {
			$full_path = $fileglob."/".$dir_content;
			if(is_dir($full_path)) {
				if(basename($full_path) != "." && basename($full_path) !== "..") {
					// directory
					if(!remove($full_path)) {
						// Cannot remove File
						trigger_error(sprintf('Cannot remove folder : %s', $full_path), E_USER_WARNING);
						return FALSE;
					}
				}
			} elseif(is_file($full_path)) {
				// file
				if(!unlink($full_path)) {
					// Cannot remove File
					trigger_error(sprintf('Cannot remove file : %s', $full_path), E_USER_WARNING);
					return FALSE;
				}
			}
		}
		// remove the directory
		return rmdir($fileglob);
	} elseif(is_file($fileglob)) {
		// remove file
		return unlink($fileglob);
	} elseif(is_array($fileglob)) {
		//  through each one
		foreach($fileglob as $value) {
			if(!remove($value)) {
				return FALSE;	
			}	
		}
		return TRUE;
	}
	// if not file,directory or array
	return FALSE;
}

/**
* 
*/
define('REQUEST_ANY',1); // any kind of value
define('REQUEST_CHAR',2); // must be a char
define('REQUEST_DATE',3); // must be a date
define('REQUEST_NUMBER',4); // request a number
define('REQUEST_MONEY',5); // request a money value
define('REQUEST_URL',6); // request a url
define('REQUEST_BOOL',7); // request TRUE or FALSE
define('REQUEST_PHONE',8); // request a phone number
define('REQUEST_EMAIL',9); // request a email address
define('REQUEST_THEME',10); // request a theme
define('REQUEST_LANG',11); // request a language
define('REQUEST_PERCENTAGE',12); // request a percentage
define('REQUEST_LUHN',13); // request a luhn number
define('REQUEST_USERNAME',14); // request a user name
define('REQUEST_PASSWORD',15); // request a password
/* reformat types */
define('FORMAT_NONE',1); // no reformat
define('FORMAT_MONEY',2); // to money
define('FORMAT_UCWORDS',3); // Uppercase the first character of each word in a string and lowercase the rest
define('FORMAT_USERNAME',4); // lowercase place strip unwanted characters
define('FORMAT_PHONE',5); // strip spaces and brackets
define('FORMAT_PASSWORD',6); // lower case password
define('FORMAT_LOWER',7); // lower case word
/* where types are stored */
define('MISSING_VALUE',0);
define('REQUEST_TYPE',1);
define('REFORMAT_TYPE',2);
define('ERROR_TYPE',3);
define('RESULT_KEY',4);

/**
* validate html form input
*/
function get_request(&$request,&$info,&$error,&$cfg) {
	// info must be an array
	if(!is_array($info)) {
		$info = array();
	}
	$error = array();
	// loop through all request
	foreach($request as $key => $value) {
		if(isset($_REQUEST[$key])) {
			$request_value = sanitise($_REQUEST[$key]);
		} else {
			$request_value = "";
		}
		// check if missing and missing error
		if($request_value === "") {
			if(isset($value[MISSING_VALUE]) && $value[MISSING_VALUE]) {
				$error[] = $value[MISSING_VALUE];
			} 
			continue;
		}
		if($cfg['input']['type'] && isset($value[REQUEST_TYPE])) {
			// check the request type
			switch($value[REQUEST_TYPE]) {
				// can't be empty string
				case REQUEST_ANY:
					// ignore	
				break;
				// request a single char
				case REQUEST_CHAR:
					if(strlen($request_value) !== 1) {
						$error[] = $value[ERROR_TYPE]; 	
					}
				break;
				// request a date
				case REQUEST_DATE:
					if(preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2}\$/",$request_value) !== 1) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a url
				case REQUEST_URL:
					if(preg_match("/^http:\/\/[^\/]+/i",$request_value) !== 1) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a Boolean
				case REQUEST_BOOL:
					if($request_value === "TRUE" || $request_value === "FALSE") {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request money type
				case REQUEST_MONEY:
					if($cfg['local']['precurrency']) {
						$request_value = str_replace($cfg['local']['precurrency'],"",$request_value);
					}
					if($cfg['local']['postcurrency']) {	
					$request_value = str_replace($cfg['local']['postcurrency'],"",$request_value);
					}
				// request a number
				case REQUEST_NUMBER:
					if(!is_numeric($request_value)) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a number
				case REQUEST_PHONE:
					if(preg_match("/^([0-9][ ]*){".$cfg['input']['phone']['min'].",".$cfg['input']['phone']['max']."}$/",$request_value) !== 1) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a email address
				case REQUEST_EMAIL:
					if(!is_valid_email_address($request_value)) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a theme
				case REQUEST_THEME:
					if(!is_dir("theme/".$request_value)) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a language
				case REQUEST_LANG:
					if(!is_dir("modules/generic/language/".$request_value)) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a language
				case REQUEST_PERCENTAGE:
					if($request_value < 0 || $request_value > 100) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
				// request a LUHN Check
				case REQUEST_LUHN:
					if($cfg['luhncheck']) {
					   $number = $request_value;
					   $l = strlen($number);
					   for ($i=0; $i<$l; $i++) {
					       $q = substr($number,$l-$i-1,1)*($i%2+1);
					       $r += ($q%10)+(int)($q/10);
					   }
					   $result = !($r%10);
					   if(!$result) {
							$error[] = $value[ERROR_TYPE];
					   }
					}
				break;
				// request a user name
				case REQUEST_USERNAME:
					
				// password
				case REQUEST_PASSWORD:
					if (strlen($request_value) < 5) {
						$error[] = $value[ERROR_TYPE];
					}
				break;
			}
		}
		// check if the input is allowed to be reformated
		if($cfg['input']['format'] && isset($value[REFORMAT_TYPE])) {
			// check refomat type
			switch($value[REFORMAT_TYPE]) {
				// no reformating
				case FORMAT_NONE:
					// do nothing
				break;
				// format for username
				case FORMAT_USERNAME:
					$request_value= str_replace(array(" ",".",",",";","]","[","&","<",">"),"",strtolower($request_value));
					// do nothing
				break;
				// format lower
				case FORMAT_LOWER:
				// format for password
				case FORMAT_PASSWORD:
					$request_value= str_replace(array(" ",".",",",";","]","[","&","<",">"),"",strtolower($request_value));
					// do nothing
				break;
				// reformat to money form
				case FORMAT_MONEY:
					if(is_numeric($request_value)) {
						$request_value = sprintf("%.2f",$request_value);
					}
				break;
				// 
				case FORMAT_UCWORDS:
					$request_value = ucwords(strtolower($request_value));
				break;
				case FORMAT_PHONE:
					$request_value = str_replace(array(" ","(",")","-"),"",$request_value);
				break;
			}
		}
		// insert into info
		if(isset($value[RESULT_KEY]) && $value[RESULT_KEY] !== "") {
			$info[$value[RESULT_KEY]] = $request_value;
		} else {
			$info[$key] = $request_value;
		}
	}
	if($error) {
		return FALSE;
	} else {
		return TRUE;
	}
}

/**
* Determine if it is a valid email address
* @return boolean
*/
function is_valid_email_address($email){
	if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,6})$", $email)) {
		// invalid email address
		return FALSE;
	} else {
		// valid email address
		return TRUE;
	} 
}

// find link items
function link_find($menu,$module,$language,$cfg) {
	// set the complete file path
	$file_path = getcwd()."/modules";
	// open the directory
	$dir = opendir($file_path);
	// if folder accessible
	if ($dir) {
		// loop through all the files (modules)
		while(($file=readdir($dir)) !== FALSE) {
			// determine if hidden file not included
			if($file{0} != "." && $file != "CVS" && is_dir($file_path."/".$file) && file_exists($file_path."/".$file."/link.php")) {
				// set files in an array
				$files[] = $file_path."/".$file."/link.php";
			}
		}
		// close the directory
		closedir($dir);
	} else {
		return FALSE;
	}
	$menu_item = array();
	foreach($files as $value) {
		// set menu item
		include($value);
	}
	return $menu_item;
}

// update config
function insert_old_config($old_config,$new_config) {
	if(!file_exists($old_config) || !file_exists($new_config)) {
		return TRUE;
	}
	$cfg = array();
	$valid_settings = array();
	$settings = array();
	// include old config
	require($old_config);
	// create arrays to write settings
	foreach($cfg as $key => $value) {
		if(is_array($value)) {
			// two dimensional
			foreach($value as $key1 => $value1) {
				if(is_array($value1)) {
					// three dimensional
					foreach($value1 as $key2 => $value2) {
						if(is_array($value2)) {
							// four dimensional
							foreach($value2 as $key3 => $value3) {
								if(is_array($value3)) {
									// five dimensional
									foreach($value3 as $key4 => $value4) {
										if($value4 === FALSE) {
											$value4 = "FALSE";
										} elseif($value4 === TRUE) {
											$value4 = "TRUE";
										}
										$settings[$key.$key1.$key2.$key3.$key4] = $value4;
										$valid_settings[$key.$key1.$key2.$key3.$key4] = "['".$key."']['".$key1."']['".$key2."']['".$key3."']['".$key4."']";
									}
								} else {
									if($value3 === FALSE) {
										$value3 = "FALSE";
									} elseif($value3 === TRUE) {
										$value3 = "TRUE";
									}
									$settings[$key.$key1.$key2.$key3] = $value3;
									$valid_settings[$key.$key1.$key2.$key3] = "['".$key."']['".$key1."']['".$key2."']['".$key3."']";
								}
							}
						} else {
							if($value2 === FALSE) {
								$value2 = "FALSE";
							} elseif($value2 === TRUE) {
								$value2 = "TRUE";
							}
							$settings[$key.$key1.$key2] = $value2;
							$valid_settings[$key.$key1.$key2] = "['".$key."']['".$key1."']['".$key2."']";
						}
					}
				} else {
					if($value1 === FALSE) {
						$value1 = "FALSE";
					} elseif($value1 === TRUE) {
						$value1 = "TRUE";
					}
					$settings[$key.$key1] = $value1;
					$valid_settings[$key.$key1] = "['".$key."']['".$key1."']";
				}
			}
		} else {
			if($key != "version") {
				if($key == 'xslt' && $value == 'server') {
					$settings[$key] = 'browser';
				} elseif($key == "url") {
					if ($_SERVER['HTTPS'] == 'on' ){
					   $location = "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
					} else {
					   $location = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
					}
					$settings[$key] = str_replace(array("main.php","install.php"),"",$location);
				} elseif($value === FALSE) {
					$settings[$key] = "FALSE";
				} elseif($value === TRUE) {
					$settings[$key] = "TRUE";
				} else {
					$settings[$key] = $value;
				}
				$valid_settings[$key] = "['".$key."']";
			}
		}
	}
	// write settings to file
	write_settings($new_config,$settings,$valid_settings);
}

function clear_menu_cache($cfg) {
	if(file_exists(getcwd()."/modules/menu/cache")) {
		$cache_dir = getcwd()."/modules/menu/cache";
		$params['files'] = list_files($cache_dir);
		foreach($params['files'] as $value) {
			unlink($value);
		}
		return $params['files'];
	}
}

function get_xml_info($file) {
	$xml_content = file_get_contents($file);
	return get_xml_info_content($xml_content);
}

function get_xml_info_content($xml_content) {
	// create parser
	$xml_parser = xml_parser_create();
	// parse xml into $xml_array
	$good_parse = xml_parse_into_struct($xml_parser,$xml_content,$info['xml_array'],$info['xml_index']);
	// free parser
	xml_parser_free($xml_parser);
	if(!$good_parse) {
		return FALSE;
	}
	// return
	return $info;
}

function urlencode_array($array) {
   $first = TRUE;
   foreach ($array as $key => $value) {
   		if($first) {
       		$result = "$key=".urlencode($value);
       		$first = FALSE;
   		} else {
   			$result.= "&$key=".urlencode($value);
   		}
   }
   return $result;
}

function get_web_contents($url,$post_fields=FALSE,$with_header=FALSE,$follow=FALSE,$use_curl=TRUE) {
	// check for curl
	if(function_exists('curl_init') && $use_curl) {
		// Send http POST - more secure than GET as headers are not encrypted
		// and no limit on information that can be transferred
		$ch = curl_init($url);
		// Create the basic header
		if ($ch) {
			// IMITATE CLASSIC BROWSER'S BEHAVIOUR : HANDLE COOKIES
			curl_setopt ($ch, CURLOPT_COOKIEJAR, 'modules/generic/cookie.txt');
			// do not display header in code output
			if($with_header) {
				curl_setopt($ch, CURLOPT_HEADER, 1);
			}
			if($post_fields !== FALSE) {
				// set so to POST
				curl_setopt($ch, CURLOPT_POST, 1);
				curl_setopt($ch, CURLOPT_POSTFIELDS,$post_fields);
			}
			if($follow) {
				// diverted to another server
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
			} else {
				// not diverted to another server
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
			}
			// cache variables and do not print out
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			// store the response as variable
			$result['web_contents'] = curl_exec($ch);
			$result['curl_info'] = curl_getinfo($ch);
			// close the connection
			curl_close($ch);
		}
	} else {
		if($use_curl) {
			trigger_error('Curl not enabled', E_USER_WARNING);
		}
		if($post_fields !== FALSE) {
			$url.= "?".$post_fields;
		}
		$result['web_contents'] = file_get_contents($url);
	}
	// response
	return $result;
}

/**
* upload file to server
*/
function file_upload($file,$application,$cfg,$module="generic",$function="error",$parameters="") {
	// determine if upload is active
	if ($cfg['upload']['active']) {
		// set date for file name
		$now = mktime (date("H"), date("i"), date("s"), date("m"), date("d"), date("Y")); 
		// convert unix timestamp to datetime
		$datetime = date("YmdHis", $now);
		// set the upload path
		$upload_path = $cfg['upload']['path'];
		if(!file_exists($upload_path)) {
			// upload load path missing
			$error[] = "310";
			// display error
			xml_generator($module,$function,$error,$parameters,$cfg);
		}
		// determine if dynamic path
		if (substr($upload_path,0,1) == ".") {
			// set complete path
			$upload_path = getcwd().substr($upload_path,1);
		}
		// change file name
		$filename = $application."_".$_SESSION['ts_id']."_".$datetime."_".$file['name'];
		// upload destination
		$upload_dest = $upload_path.$filename;
		// file size
		$filesize = $file['size'];
		$allowable_filesize = $cfg['upload']['filesize'] * 1000;
		if ($filesize > $allowable_filesize) {
			// error file size exceeds maximum allowable size
			$error[] = "281";
			// display error
			xml_generator($module,$function,$error,$parameters,$cfg);
			return FALSE;
		}
		
		// set file information
		$file_type = substr(strrchr($file['name'], "."), 1);
		// determine if file type is allowable
		$allowed = $cfg['upload']['filetype'][$file_type];
		// importing / export
		if (!$allowed && !$cfg['upload']['any']) {
			// invalid filetype
			$error[] = "282";
			// display error
			xml_generator($module,$function,$error,$parameters,$cfg);
			return FALSE;
		}
		// upload file
		if (!copy($file['tmp_name'],$upload_dest)) { 
			// file could not be uploaded
			$error[] = "283";
			// display error
			xml_generator($module,$function,$error,$parameters,$cfg);
			// response
			return FALSE;
		}
		// set the file location
		return $upload_dest;
	} else {
		// upload inactive
		$error[] = "284";
		$error[] = "1";
		// display error
		xml_generator($module,$function,$error,$parameters,$cfg);
		return FALSE;
	}
}
?>