Location: PHPKode > projects > Contrack Order Management > contrack/patUser-2.2.3/include/patConfiguration.php
<?PHP
/**
*	patConfiguration
*	Class to read XML config files
*
*	@access		public
*	@version	1.4
*	@author		Stephan Schmidt <hide@address.com>
*	@package	patConfiguration
*/
	class	patConfiguration
{
/**
*	table used for translation of xml special chars
*	@var	array	$xmlSpecialchars
*/
	var	$xmlSpecialchars	=	array(
										"&"		=>	"&amp;",
										"'"		=>	"&apos;",
										"\""	=>	"&quot;",
										"<"		=>	"&lt;",
										">"		=>	"&gt;"
									);
/**
*	current path as array
*	@var	array	$path
*/
	var	$path		=	array();

/**
*	array that stores configuration
*	@var	array	$conf
*/
	var	$conf		=	array();

/**
*	array that stores configuration from the current file
*	@var	array	$currentConf
*/
	var	$currentConf=	array();

/**
*	array that stores extensions
*	@var	array	$extensions
*/
	var	$extensions	=	array();

/**
*	stack of the namespaces
*	@var	array	$nsStack
*/
	var	$nsStack	=	array();

/**
*	stack of values
*	@var	array	$valStack
*/
	var	$valStack	=	array();

/**
*	current depth of the stored values, i.e. array depth
*	@var	int	$valDepth
*/
	var	$valDepth	=	1;

/**
*	current CDATA found
*	@var	string	$data
*/
	var	$data		=	"";
	
/**
*	directory where include files are located
*	@var	string	$includeDir
*/
	var	$includeDir		=	"";
	
/**
*	directory where cache files are located
*	@var	string	$cacheDir
*/
	var	$cacheDir		=	"cache";
	
/**
*	list of all files that were needed
*	@var	array	$externalFiles
*/
	var	$externalFiles		=	array();
	
/**
*	all open files
*	@var	array	$xmlFiles
*/
	var	$xmlFiles			=	array();
	
/**
*	list of tags and the default types
*	@var	array	$defaultTypes
*/
	var	$defaultTypes		=	array();

/**
*	set default types for tags
*
*	@access	public
*	@param	array	$defaultTypes
*/
	function	setDefaultTypes( $types )
	{
		$this->defaultTypes		=	$types;
	}
	
/**
*	set the directory, where all xml config files are stored
*
*	@access	public
*	@param	string	$configDir	name of the directory
*/
	function	setConfigDir( $configDir )
	{
		$this->configDir	=	$configDir;
	}
	
/**
*	set the directory, where all extensions are stored
*
*	@access	public
*	@param	string	$includeDir	name of the directory
*/
	function	setIncludeDir( $includeDir )
	{
		$this->includeDir	=	$includeDir;
	}

/**
*	set the directory, where all cache files are stored
*
*	@access	public
*	@param	string	$cacheDir	name of the directory
*/
	function	setCacheDir( $cacheDir )
	{
		$this->cacheDir	=	$cacheDir;
	}
	
/**
*	load a configuration from a cache
*	if cache is not valid, it will be updated automatically
*
*	@access	public
*	@param	string	$file	name of config file
*	@param	string	$mode	mode of the parsing ( "w" = overwrite old config, "a" = append to config )
*/	
	function	loadCachedConfig( $file, $mode = "w" )
	{
		$this->currentConf		=	array();
		$this->externalFiles	=	array();

		//	clear old values
		if( $mode == "w" )
			$this->conf		=	array();

		//	get full path
		$file	=	( $this->configDir!="" ) ? $this->configDir."/".$file : $file; 

		if( $result	=	$this->loadFromCache( $file ) )
		{
			$this->conf		=	array_merge( $this->conf, $result );
		}
		else
		{
			$this->parseXMLFile( $file );
			$this->writeCache( $file, $this->currentConf, $this->externalFiles );
		}
		return	true;
	}

/**
*	parse a configuration file
*
*	@access	public
*	@param	string	$file	name of the configuration file
*	@param	string	$mode	mode of the parsing ( "w" = overwrite old config, "a" = append to config )
*/	
	function	parseConfigFile( $file, $mode = "w" )
	{
		$this->path				=	array();
		$this->externalFiles	=	array();
		$this->currentConf		=	array();

		if( $mode == "w" )
			$this->conf		=	array();

		$file			=	( $this->configDir!="" ) ? $this->configDir."/".$file : $file; 

		$this->parseXMLFile( $file );

		return	true;
	}

/**
*	load cache
*
*	@access	private
*	@param	string	$file	filename
*	@return	mixed	$result	config on success, false otherwise
*/
	function	loadFromCache( $file )
	{
		$cacheFile	=	$this->cacheDir . "/" . md5( $file ) . ".cache";

		if( !file_exists( $cacheFile ) )
			return	false;

		$cacheTime		=	filemtime( $cacheFile );

		if( filemtime( $file ) > $cacheTime )
			return	false;

		if( !$fp = @fopen( $cacheFile, "r" ) )
			return	false;
			
		$result		=	false;
		flock( $fp, LOCK_SH );
		while( !feof( $fp ) )
		{
			$line	=	trim( fgets( $fp, 4096 ) );
			list( $action, $param )	=	explode( "=", $line, 2 );

			switch( $action )
			{
				case	"checkFile":
					if( filemtime( $param ) > $cacheTime )
					{
						flock( $fp, LOCK_UN );
						fclose( $fp );
						return	false;
					}
					break;
				case	"startCache":
					$result		=	unserialize( fread( $fp, filesize( $cacheFile ) ) );
					break 2;
				default:
					flock( $fp, LOCK_UN );
					fclose( $fp );
					return	false;
					break;
			}
		}
		
		flock( $fp, LOCK_UN );
		fclose( $fp );
		return	$result;
	}
	
/**
*	write cache
*
*	@access	private
*	@param	string	$file	filename
*	@param	array	$config	configuration
*	@param	array	$externalFiles	list of files used
*/
	function	writeCache( $file, $config, $externalFiles )
	{
		$cacheData	=	serialize( $config );
		$cacheFile	=	$this->cacheDir . "/" . md5( $file ) . ".cache";
		
		$fp			=	@fopen( $cacheFile, "w" );
		if( !$fp )
			return	false;
		flock( $fp, LOCK_EX );

		$cntFiles	=	count( $externalFiles );
		for( $i = 0; $i < $cntFiles; $i++ )
			fputs( $fp, "checkFile=".$externalFiles[$i]."\n" );

		fputs( $fp, "startCache=yes"."\n" );
		fwrite( $fp, $cacheData );
		flock( $fp, LOCK_UN );
		fclose( $fp );
		return	true;
	}
	
/**
*	write a configfile
*	format may be php or xml
*
*	@access	public
*	@param	string	$filename	name of the configfile
*	@param	string	$format		format of the config file (xml or php)
*	@param	array	$options	available options for php: varname => anyString ; available options for xml: mode => pretty
*/
	function	writeConfigFile( $filename, $format = "xml", $options = array() )
	{
		switch( $format )
		{
			case	"php":
				$content	=	$this->buildPHPConfigFile( $options );
				break;
			default:
				$content	=	$this->buildXMLConfigFile( $options );
				break;
		}
		if( $content )
		{
			$file	=	( $this->configDir!="" ) ? $this->configDir."/".$filename : $filename; 
			$fp		=	fopen( $file, "w" );
			if( $fp )
			{
				flock( $fp, LOCK_EX );
				fputs( $fp, $content );
				flock( $fp, LOCK_UN );
				fclose( $fp );
			}
		}
	}

/**
*	create an xml representation of the current config
*
*	@access	private
*	@return	string	$xml	xml representation
*/
	function	buildXMLConfigFile( $options )
	{
		$this->openTags		=	array();

		$config				=	$this->conf;
		ksort( $config );
		reset( $config );
		
		if( $options["mode"] == "pretty" )
			$options["nl"]		=	"\n";
		else
			$options["nl"]		=	"";

		$options["depth"]		=	0;
		
		$xml		=	"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
		$xml		.=	"<configuration>".$options["nl"];
		$options["depth"]++;
		
		while( list( $key, $value ) = each( $config ) )
		{
			$path	=	explode( ".", $key );

			switch( count( $path ) )
			{
				case	0:
					$this->niceDie( "buildXMLConfigFile", "configValue without name found!" );
					break;
				default:
					$openNew		=	array();

					$tag			=	array_pop( $path );

					$start			=	max( count( $path ), count( $this->openTags ) );
					
					for( $i=( $start-1 ); $i>=0; $i-- )
					{
						if( $path[$i] != $this->openTags[$i] )
						{
							if( $this->openTags[$i] )
							{
								array_pop( $this->openTags );
								$options["depth"]--;
								if( $options["mode"] == "pretty" )
									$xml	.=	str_repeat( "\t", $options["depth"] );
								$xml	.=	"</path>".$options["nl"];
							}
							if( $path[$i] )
								array_push( $openNew, $path[$i] );
						}
					}
							
					while( $path = array_pop( $openNew ) )
					{
						array_push( $this->openTags, $path );
						$xml	.=	str_repeat( "\t", $options["depth"] );
						$xml	.=	"<path name=\"".$path."\">".$options["nl"];
						$options["depth"]++;
					}

					$xml	.=	$this->createTag( $tag, $value, $options );
					
					break;
			}
		}

		//	close all open tags
		while( $open = array_pop( $this->openTags ) )
		{
			$options["depth"]--;
			$xml	.=	str_repeat( "\t", $options["depth"] );
			$xml	.=	"</path>".$options["nl"];
		}
		$xml		.=	"</configuration>";

		return	$xml;
	}

/**
*	create configValue tag
*
*	@access	private
*	@param	string	$name 	name attribute of the tag
*	@param	mixed	$value 	value of the tag
*	@return	string	$tag	xml representation of the tag
*/
	function	createTag( $name, $value, $options )
	{
		if( $name )
			$atts["name"]	=	$name;

		if( is_bool( $value ) )
		{
			$atts["type"]	=	"bool";
			$value			=	$value ? "true" : "false";
		}
		elseif( is_float( $value ) )
			$atts["type"]	=	"float";
		elseif( is_int( $value ) )
			$atts["type"]	=	"int";
		elseif( is_array( $value ) )
			$atts["type"]	=	"array";
		elseif( is_string( $value ) )
			$atts["type"]	=	"string";

		$tag	=	"";
		if( $options["mode"] == "pretty" )
			$tag	.=	str_repeat( "\t", $options["depth"] );
		$tag	.=	"<configValue";

		if( is_array( $atts ) )
		{
			reset( $atts );
			while( list( $att, $val ) = each( $atts ) )
				$tag	.=	" ".$att."=\"".$val."\"";
		}
		
		if( !$value )
		{
			$tag	.=	"/>".$options["nl"];
		}
		else
		{
			$tag	.=	">";

			if( is_array( $value ) )
			{
				$options["depth"]++;

				reset( $value );
				$tag	.=	$options["nl"];
				while( list( $key, $val ) = each( $value ) )
				{
					if( is_int( $key ) )
						unset( $key );
					$tag	.=	$this->createTag( $key, $val, $options );
				}

				$options["depth"]--;
				if( $options["mode"] == "pretty" )
					$tag	.=	str_repeat( "\t", $options["depth"] );
			}
			else
				$tag	.=	$this->replaceXMLSpecialchars( $value );

			$tag	.=	"</configValue>".$options["nl"];
		}
		return	$tag;
	}

/**
*	create a php representation of the current config
*
*	@access	private
*	@return	string	$php	php representation
*/
	function	buildPHPConfigFile( $options )
	{
		$varname			=	isset( $options["varname"] ) ? $options["varname"] : "config";

		$config				=	$this->conf;
		ksort( $config );
		reset( $config );

		$php		=	"<?PHP\n// Configuration generated by patConfiguration\n\n";
		$php		.=	"\$".$varname." = array();\n";
		
		while( list( $key, $value ) = each( $config ) )
		{
			$php	.=	$this->getPHPConfigLine( "\$".$varname."[\"".$key."\"]", $value );
		}

		$php		.=	"?>";
		return	$php;
	}

/**
*	build one line in the php config file
*
*	@access	private
*	@param	string	$prefix		variable name and array index
*	@param	mixed	$value		value of the config option
*	@return	string	$line		on line of php code
*/
	function	getPHPConfigLine( $prefix, $value )
	{
		if( is_bool( $value ) )
			$value			=	$value ? "true" : "false";
		elseif( is_string( $value ) )
			$value			=	"\"".addslashes( $value )."\"";

		if( is_array( $value ) )
		{
			$line		=	$prefix." = array();\n";;
			reset( $value );
			while( list( $key, $val ) = each( $value ) )
			{
				if( !is_int( $key ) )
					$key	=	"\"".$key."\"";
				$line	.=	$this->getPHPConfigLine( $prefix."[".$key."]", $val );
			}
			return	$line;
		}
		else
			return	$prefix." = ".$value.";\n";
	}
	
/**
*	add an extension
*
*	@access	public
*	@param	object patConfigExtension	&$ext	extension that should be added
*	@param	string						$ns		namespace for this extension (if differs from default ns)
*/	
	function	addExtension( &$ext, $ns = "" )
	{
		if( $ns == "" )
			$ns	=	$ext->getDefaultNS();

		$ext->setConfigReference( $this );
			
		$this->extensions[$ns]	=	&$ext;
	}

/**
*	handle start element
*	if the start element contains a namespace calls the eppropriate handler
*	
*	@param	int		$parser		resource id of the current parser
*	@param	string	$name		name of the element
*	@param	array	$attributes	array containg all attributes of the element
*/
	function	startElement( $parser, $name, $attributes )
	{
		//	separate namespace and local name
		$tag	=	explode( ":", $name );

		//	check if namespace exists and an extension for the ns exists
		if( count( $tag ) == 2 && isset( $this->extensions[$tag[0]] ) )
		{
			array_push( $this->nsStack, $tag[0] );
			$this->extensions[$tag[0]]->startElement( $parser, $tag[1], $attributes );
		}
		//	No namespace => handle internally
		else
		{
			array_push( $this->nsStack, false );
			switch( strtolower( $name ) )
			{
				//	configuration
				case	"configuration":
					break;

				//	define
				case	"define":
					if( !isset( $attributes["type"] ) )
						$attributes["type"]		=	"string";

					//	define a new tag
					if( isset( $attributes["tag"] ) )
					{
						$tag	=	$attributes["tag"];
						if( !isset( $attributes["name"] ) )
						{
							$tagName		=	$attributes["tag"];
							$nameAttribute	=	NULL;
						}
						else
						{
							switch( $attributes["name"] )
							{
								case	"_none":
									$tagName	=	NULL;
									$nameAttribute	=	NULL;
									break;
								case	"_attribute":
									$tagName		=	"_attribute";
									$nameAttribute	=	$attributes["attribute"];
									break;
								default:
									$tagName		=	$attributes["name"];
									$nameAttribute	=	NULL;
									break;
							}
						}

						$this->defaultTypes[$tag]	=	array(
																"type"	=>	$attributes["type"],
																"name"	=>	$tagName
															);
						if( $nameAttribute )
							$this->defaultTypes[$tag]["nameAttribute"]	=	$nameAttribute;

						$this->lastDefindedTag	=	$tag;
					}
					elseif( isset( $attributes["attribute"] ) )
					{
						$tag	=	$this->lastDefindedTag;
						if( !isset( $this->defaultTypes[$tag]["attributes"] ) || !is_array( $this->defaultTypes[$tag]["attributes"] ) )
							$this->defaultTypes[$tag]["attributes"]	=	array();
						
						$this->defaultTypes[$tag]["attributes"][$attributes["attribute"]]	=	$attributes["type"];
					}
					break;

				case	"getconfigvalue":
					$this->appendData( $this->getConfigValue( $attributes["path"] ) );
					break;
					
				//	extension
				case	"extension":
					if( isset( $attributes["file"] ) )
					{
						$fpath	=	( $this->includeDir ) ? $this->includeDir."/".$attributes["file"] : $attributes["file"];
						include_once( $fpath );
					}
					if( isset( $attributes["name"] ) )
					{
						if( class_exists( $attributes["name"] ) )
						{
							//	create new extension
							$ext	=	new	$attributes["name"];
	
							//	get namespace
							if( isset( $attributes["ns"] ) )
								$ns	=	$attributes["ns"];
							else
								$ns	=	$ext->getDefaultNS();
					
							//	add extension
							$ext->setConfigReference( $this );
							$this->extensions[$ns]	=	$ext;
						}
					}
					break;

				case	"xinc":
					//	include a single file
					if( isset( $attributes["href"] ) )
					{
						$file		=	$this->getFullPath( $attributes["href"] );
						
						##
						array_push( $this->externalFiles, $file );
						$this->parseXMLFile( $file );
					}
					//	include a directory
					elseif( isset( $attributes["dir"] ) )
					{
						if( !isset( $attributes["extension"] ) )
							$attributes["extension"]	=	"xml";

						$dir		=	$this->getFullPath( $attributes["dir"] );
						$files		=	$this->getFilesInDir( $dir, $attributes["extension"] );
						reset( $files );
						foreach( $files as $file )
						{
							array_push( $this->externalFiles, $file );
							$this->parseXMLFile( $file );
						}
					}
					
					break;

				//	path
				case	"path":
					$this->addToPath( $attributes["name"] );
					break;

				//	Config Value Tag found
				case	"configvalue":

					//	store name and type of value
					$val	=	@array(	"type"		=>	$attributes["type"],
										"name"		=>	$attributes["name"] );
										
					$this->valDepth	=	array_push( $this->valStack, $val );
					break;

				//	any other tag found
				//	=> use as path
				default:
					if( isset( $this->defaultTypes[$name] ) )
					{
						$type		=	$this->defaultTypes[$name]["type"];

						$tagName	=	$this->defaultTypes[$name]["name"];
						if( $tagName == "_attribute" )
						{
							$tagName	=	$attributes[$this->defaultTypes[$name]["nameAttribute"]];
						}
						
						//	store name and type of value
						$val	=	array(	"type"		=>	$type,
											"name"		=>	$tagName );
											
						if( isset( $this->defaultTypes[$name]["attributes"] ) && is_array( $this->defaultTypes[$name]["attributes"] ) )
						{
							$value	=	array();
							foreach( $this->defaultTypes[$name]["attributes"] as $name => $type )
							{
								if( isset( $attributes[$name] ) )
									$value[$name]	=	$this->convertValue( $attributes[$name], $type );
							}
							$val["value"]	=	$value;
						}

						$this->valDepth	=	array_push( $this->valStack, $val );
					}
					else
					{
						$this->addToPath( $name );
					}
					break;
			}
		}
	}

	
/**
*	handle end element
*	if the end element contains a namespace calls the eppropriate handler
*	
*	@param	int		$parser		resource id of the current parser
*	@param	string	$name		name of the element
*/
	function	endElement( $parser, $name )
	{
		//	remove namespace from stack
		array_pop( $this->nsStack );

		//	separate namespace and local name
		$tag	=	explode( ":", $name );

		//	check if namespace exists and an extension for the ns exists
		if( count( $tag ) == 2 && isset( $this->extensions[$tag[0]] ) )
		{
			$this->extensions[$tag[0]]->endElement( $parser, $tag[1] );
		}
		//	No namespace => handle internally
		else
		{
			switch( strtolower( $name ) )
			{
				//	configuration / extension
				case	"configuration":
				case	"getconfigvalue":
				case	"extension":
					break;

				case	"define":
					break;

				//	path
				case	"path":
					$this->removeLastFromPath();
					break;

				//	config value
				case	"configvalue":

					//	get last name and type
					$val	=	array_pop( $this->valStack );
									
					//	decrement depth, as one tag was removed from
					//	stack
					$this->valDepth--;

					//	if no value was found (e.g. other tags inside)
					//	use CDATA that was found between the tags
					if( !isset( $val["value"] ) )
						$val["value"]	=	$this->getData();
						
					$this->setTypeValue( $val["value"], $val["type"], $val["name"] );
					
					break;

				//	Any other tag
				default:
					if( isset( $this->defaultTypes[$name] ) )
					{
						//	get last name and type
						$val	=	array_pop( $this->valStack );
										
						//	decrement depth, as one tag was removed from
						//	stack
						$this->valDepth--;
	
						//	if no value was found (e.g. other tags inside)
						//	use CDATA that was found between the tags
						if( !isset( $val["value"] ) )
							$val["value"]	=	$this->getData();
							
						$this->setTypeValue( $val["value"], $val["type"], $val["name"] );
					}
					else
					{
						//	if data was found => store it
						if( $data = $this->getData() )
							$this->setTypeValue( $data );

						//	shorten path
						$this->removeLastFromPath();
					}
					break;		
			}
		}
	}
	
/**
*	handle character data
*	if the character data was found between tags using namespaces, the appropriate namesapce handler will be called
*	
*	@param	int		$parser		resource id of the current parser
*	@param	string	$data		character data, that was found		
*/
	function	characterData( $parser, $data )
	{
		if( trim( $data ) )
			$this->data	.=	$data;
	}

/**
*	add element to path
*
*	@access	private
*	@param	string	$key	element that should be appended to path
*/
	function	addToPath( $key )
	{
		array_push( $this->path, $key );
	}
	
/**
*	remove last element from path
*
*	@access	private
*/
	function	removeLastFromPath()
	{
		array_pop( $this->path );
	}

/**
*	set value for the current path
*
*	@access	private
*	@param	mixed	$value	value that should be set
*/
	function	setValue( $value )
	{
		$string	=	implode( ".", $this->path );
		$this->conf[$string]			=	$value;

		$this->currentConf[$string]		=	$value;
	}

/**
*	returns the current data between the open tags
*	data can be anything, from strings, to arrays or objects
*
*	@access	private
*	@return	mixed	$value	data between text
*/

	function	getData()
	{
		$data		=	$this->data;
		//	delete the data before returning it
		$this->data	=	NULL;
		return	$data;
	}

/**
*	append Data to the current data
*
*	@param	mixed	$data	data to be appended
*/
	function	appendData( $data ) 
	{
		if( is_string( $this->data ) )
		{
			//	append string
			if( is_string( $data ) )
				$this->data		.=		$data;
			else
				$this->data		=		array( $this->data, $data );
		}
		elseif( is_array( $this->data ) )
		{
			//	append string
			if( is_array( $data ) )
				$this->data	=	array_merge( $this->data, $data );
			else
				$this->data[]		=		$data;
		}
		else
			$this->data				=		$data;	
	}
	
/**
*	convert a value to a certain type ans set it for the current path
*
*	@access	private
*	@param	mixed	$value	value that should be set
*	@param	string	$type	type of the value (string, bool, integer, double)
*/
	function	setTypeValue( $value, $type = "leave", $name = "" )
	{
		//	convert value
		$value	=	$this->convertValue( $value, $type );

		//	check, if there are parent values
		//	insert current value into parent array
		if( count( $this->valStack ) > 0 )
		{
			if( $name )
				$this->valStack[($this->valDepth-1)]["value"][$name]	=	$value;
			else
				$this->valStack[($this->valDepth-1)]["value"][]			=	$value;
		}

		//	No valuestack
		else
		{
			if( $this->nsStack[( count( $this->nsStack )-1 )] )
				$this->appendData( $value );
			else
			{
				if( $name )
					$this->addToPath( $name );
	
				$this->setValue( $value );
	
				if( $name )
					$this->removeLastFromPath();

				//	clear all found CDATA
				$this->data	=	"";
			}
		}
	}

/**
*	convert a string variable to any type
*
*	@access	private
*	@param	string	$value	value that should be converted
*	@param	string	$type	type of the value (string, bool, integer, double)
*	@return	mixed	$value
*/	
	function	convertValue( $value, $type = "string" )
	{
		switch( $type )
		{
			//	string
			case	"string":
				settype( $value, "string" );
				break;

			//	boolean
			case	"boolean":
			case	"bool":
				if( $value == "true" || $value == "yes" || $value == "on" )
					$value	=	true;
				else
					$value	=	false;
				break;

			//	integer
			case	"integer":
			case	"int":
				settype( $value, "integer" );
				break;

			//	double
			case	"float":
			case	"double":
				settype( $value, "double" );
				break;

			//	array
			case	"array":
				if( !is_array( $value ) )
				{
					if( trim( $value ) )
						$value	=	array( $value );
					else
						$value	=	array();
				}
				break;
		}
		return	$value;
	}
	
/**
*	returns a configuration value
*	if no path is given, all config values will be returnded in an array
*
*	@access	public
*	@param	string	$path	path, where the value is stored
*	@return	mixed	$value	value
*/
	function	getConfigValue( $path = "" )
	{
		if( $path == "" )
			return	$this->conf;

		if( strstr( $path, "*" ) )
		{
			$path		=	str_replace( ".", "\.", $path )."$";
			$path		=	"^".str_replace( "*", ".*", $path )."$";
			$values		=	array();
			reset( $this->conf );
			while( list( $key, $value ) = each( $this->conf ) )
			{
				if( eregi( $path, $key ) )
					$values[$key]	=	$value;
			}
			return	$values;
		}

		//	check wether a value of an array was requested
		if( $index	= strrchr( $path, "[" ) )
		{
			$path		=	substr( $path, 0, strrpos( $path, "[" ) );
			$index		=	substr( $index, 1, ( strlen( $index ) - 2 ) );
			$tmp		=	$this->getConfigValue( $path );
			
			return	$tmp[$index];
		}
		
		if( isset( $this->conf[$path] ) )
			return	$this->conf[$path];
		
		return	false;
	}
	
/**
*	set a config value
*	*
*	@access	public
*	@param	string	$path	path, where the value will be stored
*	@param	mixed	$value	value to store
*/
	function	setConfigValue( $path, $value, $type = "leave" )
	{
		$this->conf[$path]			=	$this->convertValue( $value, $type );
		$this->currentConf[$path]	=	$this->convertValue( $value, $type );
	}
	
/**
*	sets several config values
*
*	@access	public
*	@param	array	$values		assoc array containg paths and values
*/
	function	setConfigValues( $values )
	{
		if( !is_array( $values ) )
			return	false;
		reset( $values );
		while( list( $path, $value ) = each( $values ) )
			$this->setConfigValue( $path, $value );
	}
	
/**
*	clears a config value
*	if no path is given, the complete config will be cleared
*
*	@access	public
*	@param	string	$path	path, where the value is stored
*/
	function	clearConfigValue( $path = "" )
	{
		if( $path == "" )
		{
			$this->conf		=	array();
			return	true;
		}
		
		if( strstr( $path, "*" ) )
		{
			$path		=	str_replace( ".", "\.", $path )."$";
			$path		=	"^".str_replace( "*", ".*", $path )."$";
			$values		=	array();
			reset( $this->conf );
			while( list( $key, $value ) = each( $this->conf ) )
			{
				if( eregi( $path, $key ) )
					unset( $this->conf[$key] );
			}
			return	true;
		}

		if( !isset( $this->conf[$path] ) )
			return	false;
			
		unset( $this->conf[$path] );
		return	true;
	}


/*
*	parse an external entity
*
*	@param	int		$parser				resource id of the current parser
*	@param	string	$openEntityNames	space-separated list of the names of the entities that are open for the parse of this entity (including the name of the referenced entity)
*	@param	string	$base				currently empty string
*	@param	string	$systemId			system identifier as specified in the entity declaration
*	@param	string	$publicId			publicId, is the public identifier as specified in the entity declaration, or an empty string if none was specified; the whitespace in the public identifier will have been normalized as required by the XML spec
*/

	function	externalEntity( $parser, $openEntityNames, $base, $systemId, $publicId )
	{
		if( $systemId )
		{
			$file	=	( $this->configDir!="" ) ? $this->configDir."/".$systemId : $systemId; 
			array_push( $this->externalFiles, $file );
			$this->parseXMLFile( $file );
		}
		return	true;
	}

/**
*	calculates the full path of a file that should be included
*
*	@access	private
*	@param	string	$path
*	@return	string	$fullPath
*/
	function	getFullPath( $path )
	{
		if( strncmp( $path, "/", 1 ) != 0 )
		{
			if( !empty( $this->xmlFiles ) )
			{
				$currentFile	=	$this->xmlFiles[( count( $this->xmlFiles ) - 1 )];
				$fullPath		=	dirname( $currentFile ) . "/" . $path;
			}
		}
		//	absolute path
		else
		{
			$path		=	substr( $path, 1 );

			if( !empty( $this->configDir ) )
				$fullPath	=	$this->configDir."/". $path;
			else
				$fullPath	=	$path;
		}
		
		$realPath	=	realpath( $fullPath );
		if( empty( $realPath ) )
			$this->niceDie( "getFullPath", "Could not resolve full path for path: '".$path."' - please check the path syntax." );
		
		return	$realPath;
	}

/**
*	get all files in a directory
*
*	@access	private
*	@param	string	$dir
*	@param	string	$ext	file extension
*/
	function	getFilesInDir( $dir, $ext )
	{
		$files	=	array();
		if( !$dh = dir( $dir ) )
			return	$files;
			
		while( $entry = $dh->read() )
		{
			if( $entry == "." || $entry == ".." )
				continue;
			if( is_dir( $dir . "/" . $entry ) )
				continue;
			if( strtolower( strrchr( $entry, "." ) ) != ".".$ext )
				continue;
			array_push( $files, $dir. "/" . $entry );
		}

		return	$files;
	}
	
/**
*	parse an external xml file
*
*	@param	string	$file	filename, without dirname
*/

	function	parseXMLFile( $file )
	{
		$parser	= $this->createParser();
		
		if( !( $fp = @fopen( $file, "r" ) ) )
			$this->niceDie( "parseXMLFile", "Could not open XML file '".$file."'." );
			
		array_push( $this->xmlFiles, $file );

		flock( $fp, LOCK_SH );

		while( $data = fread( $fp, 4096 ) )
		{
		    if ( !xml_parse( $parser, $data, feof( $fp ) ) )
			{
				$message	=	sprintf(	"XML error: %s at line %d in file $file",
											xml_error_string( xml_get_error_code( $parser ) ),
											xml_get_current_line_number( $parser ) );
				$this->niceDie( "parseXMLFile", $message );
    		}
		}

		array_pop( $this->xmlFiles );
		
		flock( $fp, LOCK_UN );
		xml_parser_free( $parser );
	}
	
/**
*	create a parser
*
*	@return	object	$parser
*/

	function	createParser()
	{
		//	init XML Parser
		$parser	=	xml_parser_create();
		xml_set_object( $parser, $this );
		xml_set_element_handler( $parser, "startElement", "endElement" );
		xml_set_character_data_handler( $parser, "characterData" );
		xml_set_external_entity_ref_handler( $parser, "externalEntity" );

		xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );

		return	$parser;
	}
	
	
/**
*	replace XML special chars
*
*	@param	string	$string		string, where special chars should be replaced
*	@param	array	$table		table used for replacing
*	@return	string	$string		string with replaced chars
*/

	function	replaceXMLSpecialchars( $string, $table = array() )
	{
		if( empty( $table ) )
			$table	=	&$this->xmlSpecialchars;

		$string		=	strtr( $string, $table );

		return	$string;
	}

/**
*	generates a "nice" variant of die() with a few more interesting infos
*
*	@param	string	$method		method in which the error occurred
*	@param	string	$message	the error message to display
*/
	function	niceDie( $method, $message )
	{
		echo '<html><head><style>.text{font-family:verdana;color:#000000;font-size:12px;letter-spacing:-1px;}</style></head><body class="text">';
		echo '<b class="text">patConfiguration Error:</b><p>';
		echo '<table cellpadding="1" cellspacing="0" border="0">';
		echo '	<tr>';
		echo '		<td class="text"><b>Function</b></td>';
		echo '		<td class="text">&nbsp;:&nbsp;</td>';
		echo '		<td class="text">'.$method.'</td>';
		echo '	</tr>';
		echo '	<tr valign="top">';
		echo '		<td class="text"><b>Error</b></td>';
		echo '		<td class="text">&nbsp;:&nbsp;</td>';
		echo '		<td class="text">'.$message.'</td>';
		echo '	</tr>';
		echo '</table>';
		echo '</div></body></html>';
		exit;
	}
	
}
?>
Return current item: Contrack Order Management