Location: PHPKode > projects > Template Parser Engine > tags.php
<?
/*
tags.php Durchsucht Templates nach bekannten zusatzbefehlen und führt diese aus
Copyright (C) 2004 Thomas Meinusch

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc.,\ 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*/

#################################################################

// mime-type
if (!function_exists ("mime_content_type")) {
	function mime_content_type ($file) {
		return exec ("file -bi ".escapeshellcmd($file));
	}
}	

// find Tag like <name ...> 
function findTag($name, $area){
	$pos=strpos($area,"<".$name.">");
	if (!$pos){
		$pos=strpos($area,"<".$name." ");
  }
  return $pos;
}

// destroy Tag <!-- TagName (user_var) -->
function destroyTag($tag, $area, $var=""){
	global $DEBUG;
	
	if($DEBUG){
		if($var=="") $var=$tag->Text;
		return str_replace($tag->CONTENT, "<!-- ".$tag->NAME.": $var -->", $area);
	}else{
		return str_replace($tag->CONTENT, "", $area);
	}
}

// <sql for="NAME" order="ORDER" orderdefault="ORDER" start="limit_start" limit="limit">SQL-COMMAND</sql>
// <sqlheader for="NAME">
// <sqlarea name="NAME" start="start" step="step">HTMLTAGS + [#DBFIELDS]</sqlarea>
function SQLTags($area){
	global $PATH;
	global $DB;
	global $handle;
	global $ERROR;
	$limit="";
	if(!is_object($DB)){
		$DB=setDB();
	}

	// SQL-Befehl
	$tag=new Tag("sql",$area);
	$tagname=$tag->TagPara["for"];
	$area=destroyTag($tag, $area);

	// source oder im Template?
	if($tag->TagPara["dir"] && $tag->TagPara["src"]){
		$orgdir=$dir;
		$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
		$dir=$orgdir;
		
//		$sql= "source ".getPath($tag->TagPara["dir"])."/".$tag->TagPara["src"];
		
//		$temp=preg_replace('/[\r\n\t]/i','',$temp); 
		foreach(explode(';',$template->CONTENT) as $sql){ 
			if(trim($sql)) $res=$DB->unbuffered_query($sql);
		}
		return array("area" => $area, "name" => $tag->TagPara["name"], "start" => 0, "rows" => 0, "allrows" => 0, "primary" => $DB->insert_id());
	}else{
		$sql=$tag->Text;
		if($tag->TagPara["order"]){
			$sql.=" ORDER BY ".$tag->TagPara["order"];
		}else if($tag->TagPara["orderdefault"]){
			$sql.=" ORDER BY ".$tag->TagPara["orderdefault"];
		}
		if($tag->TagPara["limit"] || $tag->TagPara["start"]){
			$limit=" limit ";
			if($tag->TagPara["start"]<0) $tag->TagPara["start"]=0;
			if($tag->TagPara["start"]) $limit.=$tag->TagPara["start"].", ";
			$limit.=$tag->TagPara["limit"];
		}
	}

	if($tag->TagPara["type"]=="unbuffered" ){
		$res=$DB->unbuffered_query($sql.$limit);
		return array("area" => $area, "name" => $tag->TagPara["name"], "start" => 0, "rows" => 0, "allrows" => 0, "primary" => $DB->insert_id());
	}else{
		$res=$DB->query($sql.$limit);
	}

	if($DB->message){
		$ERROR[]=$DB->message;
		$DB->message="";
	}
	
	if($res){
		$dbfld=$DB->getFields($sql, false);	
		$allrows=$DB->num_rows();

		// Falls ausserhalb der Liste, dann zeige die letzten Datensätze an!
		if($allrows>0 && $allrows<$tag->TagPara["start"]){
			$tag->TagPara["start"]=max(0,$allrows-$tag->TagPara["limit"]);
			$limit=" limit ";
			$limit.=$tag->TagPara["start"].", ";
			$limit.=$tag->TagPara["limit"];
		
			$res=$DB->query($sql.$limit);
			$dbfld=$DB->getFields($sql, false);
		}
	}else{
		echo "Fehler in SQL:<br />\n$sql.$limit<br />\n";
//		echo $DB->message."<br>\n";
	}

	// SQL auf ganzes Template auswirken lassen
	if(!$tag->TagPara["for"]){
		if(is_array($dbfld)){
			if($row = $DB->fetch_array($res)){

/*				
				// SQL-Header
				if($htag=new Tag("sqlheader",$area)){
					$temp="";
					foreach($dbfld as $f){
						$temp.=str_replace("[%".$htag->TagPara["name"]."_name]", $f->name, $htag->Text);
					}
					$contents=str_replace($htag->CONTENT, $temp, $area);
				}
*/

				foreach($dbfld as $f){
					$area=str_replace("[#".$f->name."]", $row[$f->name], $area);
					$area=str_replace("[#".$f->name."_len]", $f->length, $area);
					$area=str_replace("[#".$f->name."_type]", $f->type, $area);
				}
			}else{
				foreach($dbfld as $f){
					switch($f->type){
						case "int" :
							$area=str_replace("[#".$f->name."]", 0, $area);
							break;
						default:
							$area=str_replace("[#".$f->name."]", "", $area);
					}
					$area=str_replace("[#".$f->name."_len]", $f->length, $area);
					$area=str_replace("[#".$f->name."_type]", $f->type, $area);
				}
			}
		}	
		return array("area" => $area, "name" => $tagname, "start" => $tag->TagPara["start"], "rows" => 1, "allrows" => $allrows);
	}
	
	// SQLLIST-Verarbeiten
	$cnt=0;
	if($tag=new Tag("sqllist",$area, $tag->TagPara["for"])){
		$col=$tag->Text;
		while ($row = $DB->fetch_array($res)){
			if(is_array($dbfld)){
				foreach($dbfld as $f){
					$itag=new Tag($f->name,$col);
					$temp=str_replace("[#".$f->name."]", $row[$f->name], $itag->Text).$itag->CONTENT;
					$col=str_replace($itag->CONTENT,$temp,$col);
				}
			}
			$cnt++;
		}
		if(is_array($dbfld)){
			foreach($dbfld as $f){
//				$col=str_replace(";[#".$f->name."]", "", $col);
//				$itag=new Tag($f->name,$col);
//				$col=str_replace($itag->CONTENT,"",$col);
			}
		}
		$area=str_replace($tag->CONTENT, $col, $area);
		return array("area" => $area, "name" => $tagname, "start" => 0, "rows" => $cnt, "allrows" => $allrows); 
	}

	
	// SQLAREA-Verarbeiten
	$cnt=0;
//	do{
//		while($tag=new Tag("sqlarea",$area, $tagname) && $tag->TagPara["name"]==$tagname){
	$tag=new Tag("sqlarea",$area, $tagname);
	if(!$tag->CONTENT) $tag=new Tag("sqlarea",$area);
	if($tag->CONTENT!=""){
		do{
			$tabr="";

			/*
			preg_match ("/(<sqlarea\ [^>]*name=\"".$tag->TagPara["for"]."\"[^>]*>)/i", $area, $matches);
			if(strlen($matches[0])){
				$tag=new Tag("sqlarea",substr($area,strpos($area,$matches[0])));
			}else{
				$tag=new Tag("sqlarea",$area);
			}
			*/

			$beg=1;
			$step=1;
			if($tag->TagPara["start"]) $beg=(int) $tag->TagPara["start"];
			if($tag->TagPara["step"]) $step=(int) $tag->TagPara["step"];
			if($cnt) $DB->data_seek($res,0); // ersten Datensatz anpeilen
		//	if($tag->TagPara["name"]=="h") echo $tag->CONTENT."<br>\n\n";
			$cnt=0;
		//	if($tag->TagPara["name"]=="h") echo "$tagname = $sql<br>\n\n";
		//	echo "TAG: ".$tag->TagPara["name"]." = $tagname<br>\n\n";
		//	echo $tag->CONTENT."<br>\n\n";
			while ($row = $DB->fetch_array($res)){
				$col=$tag->Text;
				if ($col=="") $col=$area;
		//		if($tag->TagPara["name"]=="h") print_r($dbfld);
				if(is_array($dbfld)){
					foreach($dbfld as $f){
						$col=str_replace("[#".$f->name."]", $row[$f->name], $col);
						$col=str_replace("[#".$f->name."_len]", $f->length, $col);
						$col=str_replace("[#".$f->name."_type]", $f->type, $col);
					}
					$col=str_replace("[%".$tag->TagPara["name"]."]", $beg, $col);
					$beg+=$step;
				}
		//		if($tag->TagPara["name"]=="h") echo $tag->Text." ----> $col<br>\n\n";

				$cnt++;
				$col=str_replace("[%$tagname]", $cnt, $col);
				
				// Falls kein SQLAREA - abbrechen
				if (!$tag->Text) return array("area" => $col, "name" => $tagname, "rows" => $cnt, "allrows" => $allrows); 
				$tabr.=$col;
			}

		//	if($tag->TagPara["name"]=="h") echo "$tabr<br>\n\n";
			if($tabr=="") $tabr=$tag->TagPara["text"];
			$area=str_replace($tag->CONTENT, $tabr, $area);


			$tag=new Tag("sqlarea",$area, $tagname);
		}while($tagname!="" && $tag->TagPara["name"] && $tag->TagPara["name"]==$tagname);
	//	}//while($tag->CONTENT && $tag->TagPara["name"]==$tagname);
	}

	$DB->free_result($res);
	return array("area" => $area, "name" => $tagname, "rows" => $cnt, "allrows" => $allrows);
}

// Daten Konvertierung
function code($contents, $dectype="", $para="", $width=0, $wrap=0, $break="\n"){
	$x=$contents;
	foreach(explode(";", $dectype) as $type){
		switch($type){
			case "quote": // Stellt den Zeichen ' " \ ein Backslash voran
				$x=AddSlashes($x);
				break;
			case "dequote": // Die Backslashes der Zeichenkette werden vor ' " \ entfernt. 
				$x=StripSlashes($x);
				break;
			case "quotec": // Stellt den Zeichen aus \hlkey{info} ein Backslash voran
				$x=AddCSlashes($x, $para);
				break;
			case "dequotec": // Die Backslashes der Zeichenkette werden vor den Zeichen aus \hlkey{info} entfernt
				$x=StripCSlashes($x, $para);
				break;
			case "quotemeta": // Vor alle Sonderzeichen wie . \ + * ? [ ^ ] ( $ ) wird ein Backslash gesetzt
				$x=quotemeta($x);
				break;
			case "nl2br": // Wandelt Zeilenumbrüche in HTML-Tag <br> gewandelt.
				$x=nl2br($x);
				break;

			case "umlaut2uemlaut": // Wandelt alle Umlaute in ae,oe,ue,ss.
				$x=str_replace("ä","ae",$x);
				$x=str_replace("ö","oe",$x);
				$x=str_replace("ü","ue",$x);
				$x=str_replace("Ä","AE",$x);
				$x=str_replace("Ö","OE",$x);
				$x=str_replace("Ü","UE",$x);
				$x=str_replace("ß","SS",$x);
				break;
			case "upper": // Wandelt alle Buchstaben zu Großbuchstaben.
				$x=strtoupper($x);
				break;
			case "lower": // Wandelt alle Buchstaben zu Großbuchstaben.
				$x=strtolower($x);
				break;
			
			case "html2tex": // Wandelt HTML-Sonderzeichen Umlaute in tex-Format
				$x=code($x, "html2txt", $para, $width, $wrap, $break);
				$x=code($x, "txt2tex", $para, $width, $wrap, $break);
				break;
				
			case "txt2tex": // Wandelt Sonderzeichen in tex-Format
				$x=str_replace("&", "\\&", $x);
				$x=str_replace("%", "\\%", $x);
				break;

			case "html2txt": // HTML-spezifische Sonderzeichen (Umlaute) werden in 8-Bit ASCII entschlüsselt
				$x=html_entity_decode($x);
				break;
			case "umlaut2html": // Wandelt NUR Umlaute und Währung in die entsprechenden HTML-Schreibweise um.
				$arr_text=array("ä","ö","ü","ß");
				$arr_html=array("&auml;","&ouml;","&uuml;", "&szlig;");
				for($i=0;$i<sizeof($arr_text);$i++){
					$x=str_replace($arr_text[$i], $arr_html[$i], $x);
				}
				$x=str_replace("¤", "&euro;", $x);
				break;
			case "txt2html": // Wandelt HTML-spezifische Angaben und Sonderzeichen (Umlaute, Währung) in die entsprechenden HTML-Schreibweise um.
				$x=str_replace("¤", "&euro;", $x);
				$x=nl2br(htmlentities($x));
				break;
			case "txt2htmltags": // Wandelt nur HTML-Tags um, damit diese am Bildschirm Sichtbar sind.
				$x=htmlspecialchars($x, $para);
				break;
			case "txt2mail": // 8-Bit Ascii Text wird in E-Mailformat (quoted printable) gewandelt
				$x=txt2mail($x);
				break;
			case "mail2txt": // Sonderzeichen im E-Mailformat (quoted printable) werden in 8-Bit Ascii gewandelt.
				$x=quoted_printable_decode($x);
				break;

			case "bin2hex": // Binäre Daten werden in hexidezimale Entsprechungen gewandelt
				$x=bin2hex($x);
				break;
			case "hex2dec": // Dezimalzahlen nach Hexadezimal wandeln 255 -> FF,
				$x=dechex($x);
				break;
			case "hex2dec": // Hexadezimal ins dezimal wandeln FF -> 255,
				$x=hexdec($x);
				break;
			case "md5": // Zeichenkette wird in einen MD5-Code gewandelt.
				$x=md5($x);
				break;
			case "crc32": // Berechnet die Polynomische Prüfsumme eines Strings mit der Länge von 32 Bit
				$x=crc32($x);
				break;
			case "base64encode": // Wandelt Daten in Base64 z.B. für Mailanhänge um. 
				$x=base64_encode($x);
				break;
			case "base64decode": // Entschlüsselt das Base64 Format 
				$x=base64_decode($x);
				break;
			case "crypt": // Ein String wird nach der kryptischen Routine DES (Zwei-Zeichen-Schlüssel) verschlüsselt
				$x=crypt($x, $para);
				break;
			case "rot13": // Das rot13-Verfahren Addiert zu jedem ASCIIwert eines Zeichen eine 13, der &Uumlauf beginnt wieder bei a bzw. A
				$x=str_rot13($x);
				break;
				
			case "urlencode":
				$x=urlencode($x);
				break;
			case "urldecode":
				$x=urldecode($x);
				break;
			case "utf8encode":
				$x=utf8_encode($x);
				break;
			case "utf8decode":
				$x=utf8_decode($x);
				break;
		}
	}
	if($width>0) $x=wrap($x, $width, $wrap, $break);
	return $x;
}

// Wandelt alle Text-Zeichen in ASCII-7 Code um
function txt2mail($contents, $space=""){
	global $CharList, $HexList;

	if(!is_array($CharList) || !is_array($HexList)){
		$CharList=array();
		$HexList=array();
		for ($i=0; $i<127; $i++) {
			$CharList[$i] = "/".chr($i+128)."/";
			$HexList[$i] = "=".strtoupper(bin2hex(chr($i+128)));
		}
	}
	
	$mail = str_replace("=", "=3D", $contents);
	if($space) str_replace(" ", $space);
	$mail = preg_replace($CharList, $HexList, $mail);
	return $mail;
}

// Umbruch
// 0 - genau die angegebene Länge, 1 - kein Wortumbruch, sonst Wortumbruch
function wrap($contents, $width=0, $wrap=0, $break="\n"){
	if($width>0){
		if(!isset($wrap) || $wrap==0){
			$x=chunk_split($contents, $width);
		}else{
			$x=wordwrap($contents, $width, $break, $wrap-1);
		}
	}
	return $x;
}

function xml2array($area){
	$root=array();
	$sub=array();
	while($tag=new Tag($area)){
		$sub = xml2array($tag->Text);
		if(isset($root[$tag->NAME])){
			if(isset($root[$tag->NAME][0])){
				// anhängen
				$root[$tag->NAME][] = $sub;
			}else{

				$temp=$root[$tag->NAME];
				unset($root[$tag->NAME]);
				$root[$tag->NAME][] = $temp;
				$root[$tag->NAME][] = $sub;
			}
		}else{
			// Einfach
			if($sub) $root[$tag->NAME]=$sub;
		}
		$area=destroyTag($tag, $area);
	}
	if(count($root)>0) return $root;
	return $area;
}


//////////////////////////////////////////////////////////////////////////

function Template2Source($contents, $mkrek=4){
	global $dir, $thisfolder,$thisfile, $filename;
	global $PATH, $config, $DPAGE, $DEBUG; 
	global $ERROR, $ERRNO;
	global $logingroup;

	/**
	Dateien einlesen
	<include dir="TYPE" src="filename" />
	<include dir="TYPE" src="[$info_src]" name="info" />
	<include dir="TYPE" src="filename" codetype="quote" />
	<include dir="TYPE" src="filename" codetype="base64;rot13" width="76" />
	<include dir="TYPE" src="filename" codetype="bin2hex" width="20" />
	<include name="info" type="hidden" dir="TYPE" src="filename" />
	<include dir="TYPE" src="filename" Vorname="Thomas" />
	*/
	
	while($tag=new Tag("include",$contents, false)){
		// wenn Bedingung gegeben und nicht erfüllt
		// dann keine Verarbeitung
		if(isset($tag->TagPara["eval"])){
			$erg=stdVars($tag->TagPara["eval"]);
			eval("\$erg=$erg;");
			if($erg==false){
				$contents=destroyTag($tag, $contents);
				continue;
			}
		}
		
		if(isset($tag->TagPara["name"])){
			$temp=$tag->TagPara["name"];
// wegen Sicherheit darf dir nicht geändert werden!	
//			$tag->TagPara["dir"]=str_replace("[$".$temp."_dir]", $_REQUEST[$temp."_dir"], $tag->TagPara["dir"]);
			$tag->TagPara["src"]=str_replace("[$".$temp."_src]", $_REQUEST[$temp."_src"], $tag->TagPara["src"]);
		}
		$tag->TagPara["dir"]=str_replace("[$"."dir]", $_REQUEST["dir"], $tag->TagPara["dir"]);
		$orgdir=$dir;
		$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
		$temp=$template->CONTENT;
		$dir=$orgdir;
		
		if(isset($tag->TagPara["codetype"])){
			$temp=code($tag->TagPara["codetype"], $tag->TagPara["para"],
				$tag->TagPara["width"], $tag->TagPara["wrap"], $tag->TagPara["break"]);
		}
		if(isset($tag->TagPara["name"])){
			$contents=str_replace("[%".$tag->TagPara["name"]."]",$temp,$contents);
		}
		if($tag->TagPara["type"]=='hidden') $temp="";


		// alle nicht definierten Parameter durch keys ersetzen
		foreach(array_keys($tag->TagPara) as $key){
			switch($key){
				case "dir":
				case "src":
				case "name":
				case "type":
				case "codetype":
				case "width":
					break; // keine Verarbeitung
				default:
					$temp=str_replace('[%'.$key.']',$tag->TagPara[$key],$temp);
			}
		}
		$contents=str_replace($tag->CONTENT,$temp,$contents);

	}
	
	// Template-info
	if($tag=new Tag("body", $contents)){
		$temp= new Template("inc/license.html");
//		$contents=str_replace($tag->Footer,"\n<!--".str_rot13("VGhvbWFzIE1laW51c2No").md5($temp->CONTENT)."-->\n".$tag->Footer, $contents);
		$contents=str_replace($tag->Footer,str_rot13("\n<!-- TRARENGRQ OL GCR 1.4.2 jjj.zrvafbsg.qr !\n     CYRNFR ARIRE PUNATR GUVF YVAR !\n     OVGGR QVRFR MRVYR AVRZNYF AQREA -->\n").$tag->Footer, $contents);


		if($DEBUG){
			if(file_exists($PATH[$dir]["debug"])) $DPAGE=$PATH[$dir]["debug"];
			$temp= new Template($DPAGE);
			$contents=str_replace($tag->Footer,$temp->CONTENT.$tag->Footer, $contents);
		}
	}

	/**
	Nur wenn Zugriff gestattet ist, wird template verarbeitet!
	<lock accept="GRUPPE" src="filename" />
	<lock accept="GRUPPE1;GRUPPE2" dir="all" src="filename" />
	<lock accept="GRUPPE" Abteilung="Verkauf" src="filename" /> 
	*/
	if($tag=new Tag("lock", $contents)){
		$try=4;
		$blnLog=false;
//		do{
//			if(isset($tag->TagPara["accept"])){
				foreach (explode(";", $tag->TagPara["accept"]) as $grp){
					if($grp==$logingroup){
						$blnLog=true;
						// jetzt alle Parameter untersuchen
						if(is_array($_SESSION[$config]["LOGINDATA"])){
							foreach(array_keys($tag->TagPara) as $key){
								switch($key){
									case "accept":
										break;
									case "src":
									case "dir":
										$tag->TagPara[$key]=str_replace("[$".$key."]", $_REQUEST[$key], $tag->TagPara[$key]);
										break;
									default:
										if($tag->TagPara[$key]!=$_SESSION[$config]["LOGINDATA"][$key]) $blnLog=false;
								}
							}
						}
						if($blnLog==true) break;
					}
//				}
				if($blnLog==true) break;
				
				// nicht gefunden
				$ERROR[]="Zugriff auf Datei $filename nicht gestattet";
				$filename=$tag->TagPara["src"];
				if(!isset($tag->TagPara["dir"])) $tag->TagPara["dir"]=$dir;
				$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
				if($mkrek){
					$contents=Template2Source($template->CONTENT, $mkrek--);
				}else{
					return $template->getError();
				}
				if($template->fileOK){
					$tag=new Tag("lock", $contents);
				}else{
					$contents=$template->getError();
					break;
				}
			}
//		}while($try-- && (strlen($tag->TagPara["src"])!=0 && $blnLog==false));

		$contents=str_replace($tag->CONTENT, "", $contents);
	}
	
	/**
	Erstellt das COPY-Steuerbefehl
	<copy type="" name="" select="" where="">
		<table name="">
	</copy>	
	*/
	while($tag=new Tag("copy",$contents)){
		$temp="";
		while($itag=new Tag("table",$tag->Text)){
			if($temp) $temp.",";
			$temp.=$itag->TagPara["name"];
			$tag->Text=str_replace($itag->CONTENT,"",$tag->Text);
		}
		$temp=$tag->TagPara["name"]."=".$temp."|".$tag->TagPara["select"]."|".$tag->TagPara["where"];
		
		$temp='<input type="hidden" name="COPY" value="'.$temp.'" />';
		
		// name Tag ersetzen
		if(isset($tag->TagPara["name"])){
			$contents=str_replace("[%".$tag->TagPara["name"]."]", $temp, $contents);
		}

		// Ersetzen
		if($tag->TagPara["type"]=="hidden") $temp="";
		$contents=str_replace($tag->CONTENT, $temp, $contents);
	}
	
	/**
	Erstellt das LOGIN-Steuerbefehl
	<login type="" name="" dir="" src="">
		<table name="" select="" update="" where="" check="">
		<table name="" select="" update="" where="">
	</login>
	*/
	while($tag=new Tag("login",$contents)){
		$temp="";
		while($itag=new Tag("table",$tag->Text)){
			if($temp) $temp.";";
			$temp.=$itag->TagPara["name"]."|".$itag->TagPara["select"]."|".$itag->TagPara["update"]."|".$itag->TagPara["check"];
			$tag->Text=str_replace($itag->CONTENT,"",$tag->Text);
		}
		
		$temp='<input type="hidden" name="LOGIN" value="'.$temp.'" />';
		
		// name Tag ersetzen
		if(isset($tag->TagPara["name"])){
			$contents=str_replace("[%".$tag->TagPara["name"]."]", $temp, $contents);
		}

		// Ersetzen
		if($tag->TagPara["type"]=="hidden") $temp="";
		$contents=str_replace($tag->CONTENT, $temp, $contents);
	}

	/**
	Benutzt definierte Variablen und ersetzt die definierten Values durch hier in values definierte Werte
	<function for="BLAU" />
	<function for="BLAU|ROT" value="#BLUE|#RED" dir="def" src="info.html" />
	*/
	while($tag=new Tag("function",$contents)){
		$temp="";
		if(isset($tag->TagPara["dir"]) && isset($tag->TagPara["src"])){
			$orgdir=$dir;
			$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
			$temp=$template->CONTENT;
			$dir=$orgdir;
			$var=explode("|",$tag->TagPara["for"]);
			$val=explode("|",$tag->TagPara["value"]);
		}else{
			$itag=new Tag("define",$contents,$tag->TagPara["for"]);
			$temp=$itag->Text;
			$var=explode("|",$itag->TagPara["value"]);
			$val=explode("|",$tag->TagPara["value"]);
		}
		$p=0;
		foreach($var as $x){
			$temp=str_replace("[%".$x."]",$val[$p], $temp);
			$p++;
		}
		$contents=str_replace($tag->CONTENT,$temp,$contents);
	}
	
	/**
	Definiert eine Variable
	<define name="BLAU">#000FF</define>
	<define name="color" value="color|info"><font color="[%color]">[%info]</font></define>
	<define name="color" value="color|info" dir="def" src="info.html" />
	*/
	while($tag=new Tag("define",$contents)){
		if(isset($tag->TagPara["dir"]) && isset($tag->TagPara["src"])){
			$orgdir=$dir;
			$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
			$temp=$template->CONTENT;
			$dir=$orgdir;
		}else{
			$temp=$tag->Text;
		}
		$contents=str_replace("[%".$tag->TagPara["name"]."]",$temp,$contents);
		$contents=destroyTag($tag, $contents);
		unset($temp);
	}
	
	/**
	Komentar
	<rem>Das wird nur bei DEBUG angezeigt!!!</rem>
	<rem debug="3">Das wird nur bei DEBUG=3 angezeigt!!!</rem>
	*/
	while($tag=new Tag("rem",$contents, false)){
		$temp="";
		
		if($DEBUG){
			if(!isset($tag->TagPara["debug"]) || $tag->TagPara["debug"]==$DEBUG){
				$temp=$tag->Text;
			}
		}
		$contents=str_replace($tag->CONTENT,$temp,$contents);
	}
	
	// Standard Felder ersetzen	
	$contents=stdVars($contents);
	
	// Fehler und Hinweise ausgeben.
//	$error="";
//	foreach($ERRNO as $e) $error.= $e;
//	$contents=str_replace("[ERRNO]",$error,$contents);

	/**
	Schleife
	<loop name="NAME" start="" step="" size="" value="x,y">TEXT</loop>
	<loop name="NAME" src="array">[%NAME_path] [%NAME_filename] [%NAME_enctype] [%NAME_basename] [%NAME_filetype]</loop>
	<loop name="NAME" dir="" format="x*.txt" type="dir|src">[%NAME_src] [%NAME_dir]</loop>
	<loop name="NAME" dir="" type="src" src="array">[%NAME_src] [%NAME_dir]</loop>
	<loop name="NAME" for="array">TEXT</loop>
	<loop name="NAME" for="GET">$NAME</loop>
	<loop name="NAME" value="x1|x2,y1|y2" break="," wrap="|">TEXT</loop>
	<loop type="inner" size="2"><loop type="outer" size="2"><loop size="2">X</loop>Y</loop>Z</loop>
	*/
	while ($tag=new Tag("loop", $contents) ){
		if($tag->TagPara["type"]=="inner"){
//			$itag=new Tag("loop",$tag->Text."</loop>");
//			if($itag) $tag=$itag;
			$tag=new Tag("loop", $contents, false);
		}	
		$tabr="";
		
		// start-step-size
		$beg=(int) $tag->TagPara["start"];
		$step=(int) $tag->TagPara["step"];
		if($step==0) $step=1;
		$cnt=(int) $tag->TagPara["size"];
		
		// Inhalt eines Verzeichnisses
		
		// Dateien src
		$files=$_REQUEST[$tag->TagPara["src"]];
		if($cnt==0) $cnt=count($files);
		
		// Dateien und Ordner eines Ordners
//		if($cnt==0 && $tag->TagPara["dir"]){
		if(($cnt==0 && $tag->TagPara["src"]) ||$tag->TagPara["dir"]){
			// nur subfolder zulassen (nicht aufwärts!!!
			$x=realpath(getPath($tag->TagPara["dir"]));
			$temp=$x;
			if($temp==""){
				$ERROR[]="Verzeichnis ".$tag->TagPara["dir"]." nicht gefunden";
			}
			if($x== substr(realpath("$x/".$tag->TagPara["archive"]), 0,strlen($x))){
				$x=realpath("$x/".$tag->TagPara["archive"]);
			}else{
				$tag->TagPara["archive"]="";
			}

			// Variable NAME_archive anpassen
			$_REQUEST[$tag->TagPara["name"]."_archive"]=str_replace($temp,".",$x);
			// Verzeichnis durchlaufen
			$folder = opendir($x);
			$verz_folders=array();
			$verz_files=array();
			while($folder && $file = readdir($folder)){
				// Verz oder file
				if(is_dir("$x/$file")){
					if($file!=".." || $x!=$temp){
						$verz_folders[]=$file;
					}
				}else{
					// sollen Dateien gefiltert werden?
					if(is_array($files)){
						if(in_array($file, $files)) $verz_files[]=$file;
					}else{
						$verz_files[]=$file;
					}
				}
			}
//			$verz=preg_grep("/P.*/", $verz);
			if($tag->TagPara["type"]=="dir"){
				$cnt=count($verz_folders);
			}else{
				$cnt=count($verz_files);
			}
		}
		
		// for
		$cntf=0;
		$for=explode(";",$tag->TagPara["for"]);
		foreach($for as $f){
			$cntf=max($cntf,count($_REQUEST[$f]));
		}
		if($cnt==0) $cnt=$cntf;
		
//2DIMENSIONEN//		if(is_array($for) && !is_string($for)) $cnt=count($for[key($for)]);
		
		// values
		if($tag->TagPara["value"]=="GET"){
			$tag->TagPara["value"]="";
			foreach(array_keys($_GET) as $key){
				if($key!="dir" && $key!="src"){
					if($tag->TagPara["value"]!="") $tag->TagPara["value"].=",";
					$tag->TagPara["value"].=$key."|".$_GET[$key];
				}
			}
		}
		
		if(isset($tag->TagPara["value"]) && trim($tag->TagPara["value"])!=""){
			$break=$tag->TagPara["break"];
			$wrap=$tag->TagPara["wrap"];
			if($break==NULL) $break=",";
			if($wrap==NULL) $wrap="|";
			$val=explode($break, $tag->TagPara["value"]);
			if(count($val)==1) $v=$val[0];
			if($cnt==0) $cnt=count($val);
		}
		// Laufe von beg cnt mal in step Schritten
		for ($i=$beg, $pos=0;$pos<$cnt;$pos++,$i+=$step){
			$temp=str_replace("[%".$tag->TagPara["name"]."]", $i, $tag->Text);
			if(count($val)!=1){
				$v="";
				if($pos<count($val)) $v=$val[$pos];
			}
			$temp=str_replace("[%".$tag->TagPara["name"]."_value]", $v,$temp);

			// value="x1|x2,y1|y2
			$vcnt=0;
			if($wrap){
				foreach(explode($wrap, $v) as $x){
					$vcnt++;
					$temp=str_replace("[%".$tag->TagPara["name"]."_value".$vcnt."]", $x,$temp);
				}
					$temp=str_replace("[%".$tag->TagPara["name"]."_value_cnt]", $vcnt,$temp);
			}

			$x="";
			
			// src - files
			if($pos<count($files)){
				$x=$files[$pos];
//					echo "$x - [%".$tag->TagPara["src"]."_filetype]<br>";
				if(file_exists($x)){
					$temp=str_replace("[%".$tag->TagPara["src"]."_path]", $x, $temp);
					$temp=str_replace("[%".$tag->TagPara["src"]."_filename]", basename($x), $temp);
					$temp=str_replace("[%".$tag->TagPara["src"]."_filetype]", mime_content_type($x), $temp);
					if(substr(mime_content_type($x),0,4)=="text"){
						$temp=str_replace("[%".$tag->TagPara["src"]."_enctype]", "quoted-printable", $temp);
					}else{
						$temp=str_replace("[%".$tag->TagPara["src"]."_enctype]", "base64", $temp);
					}	
//					$temp=str_replace("[%".$tag->TagPara["src"]."_filebasename]", "pic$i", $temp);
//					$contents=str_replace($itag->CONTENT, "cid:pic$i", $contents);
				}
			}
			$x="";
			
			// dir
			if(is_array($verz_folders)){
//				echo "X:".$tag->TagPara["dir"]."=".$verz_files[$pos]."<br>";
				$temp=str_replace("[%".$tag->TagPara["name"]."_dir]", $verz_folders[$pos], $temp);
				$temp=str_replace("[%".$tag->TagPara["name"]."_src]", $verz_files[$pos], $temp);
			}
			$x="";
			
			// for
			foreach($for as $f){
				// 1-dim oder 2-dim Array
				if(is_array($x=$_REQUEST[$f])){
					if(is_string(key($x))){ 
						foreach(array_keys($x) as $key){
							$temp=str_replace("[%".$f."_".$key."]",$x[$key][$pos], $temp);
						}
					}else{
						if($pos<count($x)){
							$temp=str_replace("[%".$f."]", $x[$pos], $temp);
						}
					}
				}else{
					// nur Text
					$temp=str_replace("[%".$f."]", $x, $temp);
				}
			}
			
			$tabr.=$temp;
		}
		//	echo "i: $i, $cnt, $step<br>";
		//echo "<textarea>".$tag->Text."</textarea>\n";
		//echo "<textarea>".$temp."</textarea>";
		//echo "<textarea>".$tabr."</textarea><br>\n";
		$contents=str_replace($tag->CONTENT, $tabr, $contents);
		$contents=str_replace("[%".$tag->TagPara["name"]."_rows]", $pos, $contents);
	}

	/**
	Gehe alle SQL-Felder durch
	<sql for="NAME" order="ORDER" start="limit_start" limit="limit">SQL-BEFEHL</sql>
	<sql dir="sql" src="file.sql"></sql>
	<sql type="unbuffered">SQL-Befehl</sql>
	<sqlarea name="NAME" start="100" step="10">DGFelder</sqlarea>
	*/
	while(strpos($contents,"<sql ")!==false ){
		$temp=SQLTags($contents);
		$contents=$temp["area"];
//		$contents=str_replace("[%".$temp["name"]."_start]", $temp["start"], $contents);
		$contents=str_replace("[%".$temp["name"]."_allrows]", $temp["allrows"], $contents);
		$contents=str_replace("[%".$temp["name"]."_rows]", $temp["rows"], $contents);
		$contents=str_replace("[%".$temp["name"]."_primary]", $temp["primary"], $contents);
	}

	/**
	Convertiere SQL-Select-Befehl in XML-Datei
	<sql2xml target="DIR" src="file.xml" accesskey="w+"><tab>SQL-Befehl</tag></sql2xml>
	*/
	if($tag=new Tag("sql2xml", $contents)){
		global $DB;
		if(!is_object($DB)){
			$DB=setDB();
		}
	}
	while($tag=new Tag("sql2xml", $contents)){
		include_once("XmlWriter.class.php");

		$xml = new XmlWriter();
		while($xmltag=new Tag($tag->Text)){
			$xml->push($xmltag->NAME);
			$xml=$DB->query2xml($xml,$xmltag->Text);
			$xml->pop();
			$tag->Text=destroyTag($xmltag, $tag->Text);
		}

		$xmlstring=$xml->getXml();

		$mode="w+";
		if($tag->TagPara["accesskey"]) $mode=$tag->TagPara["accesskey"];
		$fpath=getPath($tag->TagPara["target"])."/".$tag->TagPara["src"];
		save_file($fpath, $xmlstring, $mode);

		$contents=destroyTag($tag, $contents);
	}

	while($tag=new Tag("xml", $contents)){
		// lese XML-Datenbank
		$xmldbfile= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]);
		$xmldb=xml2array($xmldbfile->CONTENT);
		$xmlcontent="";

		// Gespeicherte Bereiche durchgehen
		foreach(array_keys($xmldb) as $tagname){
			// Bereich aus Template-TAG auselsen 
			while($rowtag=new Tag($tagname,$tag->Text)){
				// Ale Datensätze der jeweiligen Bereiche durchgehen
				foreach($xmldb[$rowtag->NAME]['row'] as $row){
					if(!is_array($row)) $row=$xmldb[$rowtag->NAME]['row'];
					$temp=$rowtag->Text;
					// Alle Variablen einsetzen.
					foreach(array_keys($row) as $key){
						$temp=str_replace("[#".$key."]",$row[$key], $temp);
					}
					//sql
					switch($rowtag->TagPara['type']){
						case 'insert':
							$dbinfo=$DB->createInsertSQL($rowtag->TagPara['table'], $row, true);
							$DBfld= $DB->insertData($dbinfo["sql"]);
							if(is_array($DBfld)) $DBfld=$DBfld[count($DBfld)-1];
							$_REQUEST[$dbinfo["primary_key"]]=$DBfld;
							break;
					}

					$xmlcontent.=$temp;
					if($row==$xmldb[$rowtag->NAME]['row']) break;
				}
				$tag->Text=destroyTag($rowtag,$tag->Text);
			}
		}
		$contents=str_replace($tag->CONTENT,$xmlcontent, $contents);
	}


	/**
	Datum anzeigen
	<date format="%d.%m.%Y - %T" /> heute
	<date format="%L.%m.%Y - %T" /> letzter Tag in diesem Monat
	<date day="+10" format="%A, %d.%m.%Y" /> in 10 Tagen
	<date day="15" man="+1" format="d.m.Y - H.i.s" /> 15 nächsten Monats
	<date type="hidden" format="d.m.Y - H.i.s" src="2005-01-18 17:45:37" name="heute" />
	*/
	$dateformat=array(
		"database" => "%Y-%m-%d %H:%M:%S",
		"german" => "%d.%m.%Y - %H.%M.%S",
		"gerlong" => "%d. %B %Y"
	);
	$dateconv=array(
		'Y' => array('key' => 'year', 'len' =>'4'),
		'y' => array('key' => 'year', 'len' =>'2'),
		'm' => array('key' => 'mon', 'len' =>'2'),
		'd' => array('key' => 'day', 'len' =>'2'),
		'H' => array('key' => 'hours', 'len' =>'2'),
		'M' => array('key' => 'minutes', 'len' =>'2'),
		'S' => array('key' => 'seconds', 'len' =>'2')
	);

	while($tag=new Tag("date", $contents)){
		// format speichern
		$dateinfo=$format=array();
		foreach(array('format','src-format') as $key){
			if(in_array($tag->TagPara[$key], array_keys($dateformat))){
				$format[$key]=$dateformat[$tag->TagPara[$key]];
			}else{
				if(!$tag->TagPara[$key]){
					$format[$key]=$dateformat["database"];
				}else{
					$format[$key]=$tag->TagPara[$key];
				}
			}
		}
		// heutiges oder anderes Datum?
		$temp=$tag->TagPara["src"];
		if($tag->TagPara["src"]){
			// dateinfo aufbauen
			if($format['src-format']){
				$pos=0;$len=0;
				for($i=0;$i<strlen($format['src-format']);$i++){
					if(array_key_exists($key=substr($format['src-format'],$i,1), $dateconv)){
						$dateinfo[$dateconv[$key]['key']]=substr($temp,$pos,$dateconv[$key]['len']);
						$pos+=$dateconv[$key]['len'];
					}else{
						if($key=="%"){
							$len=0;
						}else{
							$pos++;
							$len=1;
						}
					}
				}
			}
		}else{
			$dateinfo=getdate();
			$dateinfo['day']=$dateinfo['mday'];
		}

		foreach(array ('day','mon','year','hours','minutes','seconds') as $key){
			$v=substr($tag->TagPara[$key],0,1);
			if($v=="+" || $v=="-"){
				$dateinfo[$key]+=$tag->TagPara[$key];
			}else if($tag->TagPara[$key]){
				$dateinfo[$key]=$tag->TagPara[$key];
			}
		}
		$temp=mktime($dateinfo['hours'], $dateinfo['minutes'], $dateinfo['seconds'], 
			$dateinfo['mon'], $dateinfo['day'], $dateinfo['year']);
		$format["format"]=str_replace('%L', strftime(date('t',$temp)),$format["format"]);
		$temp=strftime($format["format"], $temp);

		// Tag direkt ersetzen
		if(!isset($tag->TagPara["type"]) || $tag->TagPara["type"]!="hidden"){
			$contents=str_replace($tag->CONTENT, $temp, $contents);
		}else{
			$contents=destroyTag($tag, $contents);
		}
		
		// Variablen anzeigen
		if(isset($tag->TagPara["name"])){
			$contents=str_replace("[%".$tag->TagPara["name"]."]", $temp, $contents);
		}
	}
	
	/**
	Daten wandeln, ver- und entschlüsseln
	<encode codetype="base64" width="76" dir="pics" src="[@picname]">
	<encode codetype="base64" width="76" wrap="0">Das ist verschlüsselt!</encode>
	codetype: file4mail | ...
	*/
	while($tag=new Tag("encode", $contents)){
		if($tag->TagPara["src"]){
			$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"], false);
			$temp=$template->CONTENT;
		}else{
			$temp=$tag->Text;
		}
		
		if($tag->TagPara["codetype"]=="file4mail"){
			if(substr(mime_content_type(getPath($tag->TagPara["dir"])."/".$tag->TagPara["src"]),0,4)=="text"){
				$tag->TagPara["codetype"]="txt2mail";
			}else{
				$tag->TagPara["codetype"]="base64encode";
			}
		}
		$temp=code($temp, $tag->TagPara["codetype"], $tag->TagPara["para"],
		$tag->TagPara["width"], $tag->TagPara["wrap"], $tag->TagPara["break"]);
		$contents=str_replace($tag->CONTENT, $temp, $contents);
	}

	/**
	Sonderzeichen quoten
	<quote>Text mit Sonderzeichen</quote>
	*/
	while($tag=new Tag("quote",$contents)){
#		$temp=$tag->Text;
#		$temp=AddSlashes($temp);
		$contents=str_replace($tag->CONTENT,AddSlashes($tag->Text),$contents);
	}

	/**
	String bearbeiten
	<strings start="1" size="2" value="Text">
	start < 0 heißt von rechts
	*/
	while($tag=new Tag("strings",$contents)){
		$temp=$tag->TagPara["value"];
		if(isset($tag->TagPara["start"])) $tag->TagPara["start"]=0;
		$x=$tag->TagPara["start"];
		if($x<0) $x+=strlen($temp);
		$cnt=$tag->TagPara["size"];
		
		$contents=str_replace($tag->CONTENT,substr($temp, $x,$cnt),$contents);
	}
	
	/**
	Zeilenumbruch
	<wrap type="0" width="10" break="\n">Ein ganz langer Text, der Zerlegt wird</wrap>
	*/
	while($tag=new Tag("wrap",$contents)){
		$temp=wrap($tag->Text, $tag->TagPara["width"], $tag->TagPara["wrap"], $tag->TagPara["break"]);
		$contents=str_replace($tag->CONTENT, $temp ,$contents);
	}

require_once("wiki.php");
	while($tag=new Tag("wiki",$contents)){
		$contents=str_replace($tag->CONTENT, wiki($tag->Text), $contents);
	}

	/**
	Berechnet einen mathematischen Ausdruck
	<calc eval="7+3">
	<calc type="hidden" name="NAME" format="%5.2f" eval="7+3">
	<calc for="[$array]">
	*/
	while($tag=new Tag("calc",$contents)){
		$erg=0;
		if(isset($tag->TagPara["for"])){
			$for=$_REQUEST[$tag->TagPara["for"]];
			foreach ($for as $x){
				$erg+=$x;
			}
			$tag->TagPara["eval"]=$erg;
		}else{
			// 2007.05.03 TM: wie sollen die Kommas behandelt werden: max(7,3) aber x=3.5
			$erg=$tag->TagPara["eval"];
			$erg=str_replace(",",".",$erg); // x=3.5
			$erg=str_replace(";",",",$erg); // max(7;2)
			eval("\$erg=$erg;");
		}	
		if($tag->TagPara["format"]!=""){
			$erg=sprintf($tag->TagPara["format"], $erg);
		}
		// replace
		if($tag->TagPara["search"] && $tag->TagPara["replace"]){
			$erg=str_replace($tag->TagPara["search"],$tag->TagPara["replace"],$erg);
		}
		if(!isset($tag->TagPara["type"]) || $tag->TagPara["type"]!="hidden"){
			$contents=str_replace($tag->CONTENT, $erg, $contents);
		}else{
			$contents=destroyTag($tag, $contents);
		}
		
		if(isset($tag->TagPara["name"])){
			$contents=str_replace("[%".$tag->TagPara["name"]."]", $erg, $contents);
		}
	}
	
	/**
	repeat-Schleife
	<repeat size="anz" wrap="zeichenfolge">text</repeat>
	<repeat size="3" wrap=", ">text</repeat>
	*/
	while ($tag=new Tag("repeat",$contents)){
		$cnt=0;
		$temp="";
		$x=$tag->TagPara["wrap"];
		while($cnt<$tag->TagPara["size"]){
			if($cnt) $temp.=$x;
			$temp.=$tag->Text;
			$cnt++;
		}
		$contents=str_replace($tag->CONTENT, $temp, $contents);
	}
	
	/**
	if-Abfrage
	<if eval="x==y">...<else>...</else></if>
	*/
	while ($tag=new Tag("if",$contents)){
		$itag=new Tag("else", $tag->Text);
		$iftemp=$tag->TagPara["eval"];
		if($iftemp) eval("\$iftemp=$iftemp;");
		if ($iftemp){
			$tag->Text=str_replace($itag->CONTENT,"", $tag->Text);
			$contents=str_replace($tag->CONTENT, $tag->Text, $contents);
		}else{
			$contents=str_replace($tag->CONTENT, $itag->Text, $contents);
		}
//		if (strpos($tag->CONTENT," ")) echo "<textarea>".$tag->CONTENT."</textarea>\n";
	}
	
	/**
	SWITCH-Abfrage
	<switch eval="x">
		<case value="y_1">...</case>
		...
		<case value="y_n">...</case>
		<default>...</default>
	</switch>
	*/
	$temp=" ";
	while ($tag=new Tag("switch",$contents)){
		$bool=false;
		$temp=$tag->Text;
		if($tag->TagPara["eval"]){
			$erg=$tag->TagPara["eval"];
			eval("\$erg=$erg;");
		}else{
			$erg=$tag->TagPara["value"];
		}
		while($itag=new Tag("case",$temp, false)){
			if($itag->TagPara["value"]==$erg){
				$temp=$itag->Text;
				$bool=true;
			}else{
				$temp=str_replace($itag->Header, "", $temp);
			}
		}
		if(!$bool){
			$temp="";
			if($itag=new Tag("default",$tag->Text)) $temp=$itag->Text;
		}	
		$contents=str_replace($tag->CONTENT,$temp, $contents);
	}
	
	/**
	CHOSE-Abfrage
	<chose name="id" start="10" step="5" for="3" type="bool|num" value="x[%id]|">
		<case value="1" />
		<case value="2" />
		<case value="3" />
	</chose>
	*/

	while ($tag=new Tag("chose",$contents)){
		$temp=$tag->Text;
		$x=explode("|",$tag->TagPara["value"]);
		$start=1;
		if($tag->TagPara["start"]) $start=$tag->TagPara["start"];
		$step=1;
		if($tag->TagPara["step"]) $step=$tag->TagPara["step"];
		while($itag=new Tag("case",$temp, false)){
			$erg=$x[0];
			if($tag->TagPara["type"]=='bool' && $tag->TagPara["for"]==$itag->TagPara["value"]){
				$erg=$x[1];
			}
			if($tag->TagPara["type"]=='num'){
				$erg=$x[$tag->TagPara["for"]];
			}
			$temp=str_replace($itag->CONTENT, str_replace("[%".$tag->TagPara["name"]."]", $start, $erg), $temp);
			$start+=$step;
		}
		$contents=str_replace($tag->CONTENT,$temp,$contents);
	}
	/**
	Reguläre Ausdrücke
	<expression name ="NAME" search="EXPRESSION" replace="REPLACE">TEXT</expression>
	<expression name="NAME" search="EXPRESSION" replace="REPLACE|REPLACE">TEXT</expression>
	search="/.*\ \([0-9]\)\([a-z])/" replace="Zahl|Buchstabe"
	*/
	if(findTag("expression",$contents)){
		preg_match_all ("/search=\"([^\"]*)\"/i", $contents, $matches);
		foreach(array_unique($matches[1]) as $match){
			$contents=str_replace($match,base64_encode($match), $contents);
		}
	}
	
	while ($tag=new Tag("expression",$contents)){
		$contents=str_replace($tag->CONTENT,
		preg_replace(base64_decode($tag->TagPara["search"]),$tag->TagPara["replace"],$tag->Text),
		$contents);
	}
	
	/**
	Ausführen von SHELL-Komandos
	<shell type="hidden">BEFEHLE</shell>
	type hidden | visible
	*/
	while($tag=new Tag("shell",$contents)){
		$temp="";
		
		if($tag->Text){
			#$temp = exec(trim($tag->Text));
			$temp=trim($tag->Text);
			$temp = shell_exec($temp);
			if ($tag->TagPara["type"]=="hidden") $temp="";
		}	
		$contents=str_replace($tag->CONTENT, $temp, $contents);
	}

	/**
	Liefert eine Request-Variable zurück,
	sollte der Name nicht geliefert worden sein,
	kann unter default ein Wert spezifiziert werden
	<get value="VARNAME" default="Wert">
	<get type="hidden" value="VARNAME" default="Wert">
	<get dir="Pfad" value="Wert">
	<get value="Wert" codetype="urlencode">
	<get start="3" default="1234567890" />
	<get start="3" length="5" default="1234567890" />
	<get start="-5" length="-3" default="1234567890" />
	LEFT: <get start="3" size="20" fill="x" align="left" length="-3" default="1234567890" />
	RIGHT: <get start="3" size="20" fill="x" align="right" length="-3" default="1234567890" />
	CENTER: <get start="3" size="20" fill="x" align="center" length="-3" default="1234567890" />
	<get search="NAME" replace="Thomas" default="Hallo NAME" />
	<get codetype="upper" default="Hallo Thomas" />
	<get codetype="lower" default="Hallo Thomas" />
	*/

	$padAlign=array(
		'left' => STR_PAD_RIGHT,
		'right' => STR_PAD_LEFT,
		'center' => STR_PAD_BOTH
	);
	while ($tag=new Tag("get",$contents)){
		$temp=$_REQUEST[$tag->TagPara["value"]];
		if($temp=='') $temp=$tag->TagPara["default"];
		

		// Pfad
		if(isset($tag->TagPara["dir"])){
			$x=realpath(getPath($tag->TagPara["dir"]));
			if($x== substr(realpath("$x/".$temp), 0,strlen($x))){
				$temp=realpath("$x/".$temp);
			}
			/*
			if(file_exists("$x/".$temp)){
				$temp=realpath("$x/".$temp);
			}else{
				$temp=realpath("$x");
			}
			*/
			$temp=str_replace($x,".",$temp);
		}
		
		// Ver-/Entschlüsseln
		if(isset($tag->TagPara["codetype"])){
		 	$temp=code($temp, $tag->TagPara["codetype"]);
		}

		// start-end
		if($tag->TagPara["start"] || $tag->TagPara["length"]){
			if($tag->TagPara["length"]){
				$temp=substr($temp,$tag->TagPara["start"],$tag->TagPara["length"]);
			}else{
				$temp=substr($temp,$tag->TagPara["start"]);
			}
		}

		// replace
		if($tag->TagPara["search"] && $tag->TagPara["replace"]){
			$temp=str_replace($tag->TagPara["search"],$tag->TagPara["replace"],$temp);
		}

		// pad
		if($tag->TagPara["size"] && strlen($temp)>$tag->TagPara["size"]){
			if($tag->TagPara["align"]=="right"){
				$temp=substr($temp,-$tag->TagPara["size"]);
			}else{
				$temp=substr($temp,0,$tag->TagPara["size"]);
			}
		}
		if($tag->TagPara["size"] && strlen($tag->TagPara["fill"])){
			$temp=str_pad($temp,$tag->TagPara["size"], $tag->TagPara["fill"]."", $padAlign[$tag->TagPara["align"]]);
		}

		// [%value] Variablen ersetzen
		$contents=str_replace("[%".$tag->TagPara["value"]."]", $temp, $contents);

		// Tag ersetzen
		if($tag->TagPara["type"]=="hidden") $temp="";
		$contents=str_replace($tag->CONTENT, $temp, $contents);
		
	}

######################################################################

	/**
	Bilderkonvertierung
	<pic method="maximize" width="50" height="scale" dir="pics" src="2069Cp.jpg" target="pics" href="tm.jpg" quality="75%">
	method="maximize|max|exact"
	*/
	while($tag=new Tag("pic", $contents)){
		if(file_exists($tag->TagPara["src"]) && !is_dir($tag->TagPara["src"])){
			$picsize=getimagesize($tag->TagPara["src"]);
			if($tag->TagPara["width"]=="scale") $tag->TagPara["width"]=round($picsize[0]*($tag->TagPara["height"]/$picsize[1]));
			if($tag->TagPara["height"]=="scale") $tag->TagPara["height"]=round($picsize[1]*($tag->TagPara["width"]/$picsize[0]));
			$nx=$tag->TagPara["width"];
			$ny=$tag->TagPara["height"];
			
			if($nx+$ny==""){
				$contents=destroyTag($tag, $contents, "Bildkonvertierung fehlgeschlagen");
			}else{
				switch($tag->TagPara["method"]){
					case "maximize":
						$ny=round($nx*($picsize[1]/$picsize[0]));
						if($ny>$tag->TagPara["height"]){
							$ny=$tag->TagPara["height"];
							$nx=round($ny*($picsize[0]/$picsize[1]));
						}
						break;
					case "max":
						$nx=$picsize[0];
						$ny=$picsize[1];
						if($nx>$tag->TagPara["width"]){
							$nx=$tag->TagPara["width"];
							$ny=round($nx*($picsize[1]/$picsize[0]));
						}
						if($ny>$tag->TagPara["height"]){
							$ny=$tag->TagPara["height"];
							$nx=round($ny*($picsize[0]/$picsize[1]));
						}	
						break;
					default:
				}
				$sid=imageCreateFromJPEG($tag->TagPara["src"]);
				$did=imagecreatetruecolor($nx, $ny);
			
				$pic=imagecopyresampled($did, $sid,0,0,0,0,$nx,$ny, $picsize[0], $picsize[1]);
				imagejpeg($did, $tag->TagPara["target"], $tag->TagPara["quality"]);
			}
		}
		$contents=destroyTag($tag, $contents);
	}

	/**
	Template in PDF konvertieren
	<pdf color="" background-color="" title="" face="Arial|..." style="BIU" size="9"
			target="ablage" lowsrc="test.html" type="hidden|view">
		<font face="Arial" size="10" />
		<th width hight color boreder border-color>Value</th>
		<td>Value</td>
		<br size="5" />
		<pos left="" right="" top="" bottom="" />
		<font face="Arial|..." style="BIU" size="9" />
		<p height="20" href="">Text</p>
	</pdf>
	*/
	while($tag=new Tag("pdf", $contents)){
		require_once('pdf.php');
		$temp=$temp2="";
		if($tag->TagPara["lowsrc"]){
			$temp=getPath($tag->TagPara["target"], true)."/".$tag->TagPara["lowsrc"];
		}
		if($tag->TagPara["face"]){
			$temp2='<font face="'.$tag->TagPara["face"];
			if($tag->TagPara["style"]) $temp2.=' style="'.$tag->TagPara["style"];
			if($tag->TagPara["size"]) $temp2.='" size="'.$tag->TagPara["size"];
			$temp2.='" />';
		}
		tpe2pdf($temp2.$tag->Text, $tag->TagPara);
		$contents=destroyTag($tag, $contents);
	}

	/**
	Emailversand
	<mail title="Betreff" from="hide@address.com" to="hide@address.com" src="mail.eml" dir="mail">
		<textmail>file.txt</textmail><htmlmail>file.html</htmlmail>
	</mail>
	*/
	while ($tag=new Tag("mail",$contents)){
		$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"], true);
		$message=$template->CONTENT;
		$contents=destroyTag($tag, $contents);
		if($message=="") continue;
		
		// Inhalt verarbeiten
		$to=html_entity_decode((trim($tag->TagPara["to"])));
		$subject=html_entity_decode((trim($tag->TagPara["title"])));
		if(!isset($tag->TagPara["replay"])){
			$tag->TagPara["replay"]=$tag->TagPara["from"];
		}
		
		// Wortweise trennen
		foreach(array_unique(explode(" ", $subject)) as $temp){
			preg_match('/[äöüß]/i',$temp, $matches);
			if(count($matches)>0){
				$subject=str_replace($temp,"=?iso-8859-15?b?".base64_encode($temp)."=?=", $subject);
			}	
		}
		
		// Buchstabenweise
		$x=false;
		foreach(array_unique(explode(" ", $to)) as $temp){
			preg_match('/[äöüß]/i',$temp, $matches);
			if(count($matches)>0){
				$x=true;
				foreach(array_unique($matches) as $match)
				$to=str_replace($match,txt2mail($match),$to);
			}	
		}
		if($x) $to="=?iso-8859-15?q?".$to."?=";
		
		if(isset($tag->TagPara["from"])) $_REQUEST["mailfrom"]=$tag->TagPara["from"];
		if(isset($tag->TagPara["replay"])) $_REQUEST["mailreplay"]=$tag->TagPara["replay"];
		if(isset($tag->TagPara["to"])) $_REQUEST["mailto"]=$tag->TagPara["to"];
		if(isset($tag->TagPara["cc"])) $_REQUEST["mailto"]=$tag->TagPara["to"];
		if(isset($tag->TagPara["bcc"])) $_REQUEST["mailbcc"]=$tag->TagPara["bcc"];
		if(isset($tag->TagPara["priority"])) $_REQUEST["priority"]=$tag->TagPara["priority"];
		
		// Inline-Tags finden
		preg_match_all ('/<([a-z0-9_]*)>([^<]*)<\/([a-z0-9_]*)>/i',$tag->Text, $matches);
		for($i=0;$i<count($matches[1]);$i++){
			$message=str_replace("[%".$matches[1][$i]."]", $matches[2][$i],$message);
		}

		// include Subfiles
		while($itag=new Tag("include",$message)){
			$template= new Template($PATH, $itag->TagPara["dir"], $itag->TagPara["src"], false);
			$temp=$template->CONTENT;
			$message=str_replace($itag->CONTENT,$temp,$message);
		}

		$message=stdVars($message);
		// Dateinemen finden
		preg_match_all ("/(\[:+[a-z]*+\]|\w)+\/([^\"\s]+|\"[^\"]*\")/i", $message, $lines);
		$_REQUEST["mailfile"]=array();
		$anz=0;
		foreach(array_unique($lines[0]) as $mfile){
			if(file_exists($mfile)){
				$anz++;
				$message=str_replace($mfile, "cid:pic$anz", $message);
				$_REQUEST["mailfile"][]=$mfile;
			}
		}
		
		// Anhänge verarbeiten
		if(isset($tag->TagPara["attachment"])){
			$_REQUEST["attachment"]=array();
			foreach(explode(";", $tag->TagPara["attachment"]) as $mfile){
				if(file_exists($mfile)) $_REQUEST["attachment"][]=$mfile;
			}
		}
		
		$htag=new Tag("body",$message);
		$html=txt2mail($htag->CONTENT);
		$message=str_replace($htag->CONTENT, $html, $message); 
		$message=Template2Source($message);
#		mail($to, "=?iso-8859-15?b?".base64_encode(html_entity_decode(trim($subject)))."=?=", "", $message);
	}

	/**
	Datei erstellen
	<write type="hidden" target="folder" href="dateiname" mode="w+">Inhalt wird gespeichert</write>
	*/
	while($tag=new Tag("write", $contents)){
		$temp=$tag->Text;
		$mode="w+";
		if($tag->TagPara["accesskey"]) $mode=$tag->TagPara["accesskey"];
		if($tag->TagPara["codetype"]=='xls'){ // && $tag->TagPara['action']=='post'){
			require_once 'toexcel.php';
			Source2Excel($tag->TagPara["href"], $temp, true);
		}else{
			if($PATH[$tag->TagPara["target"]]["write"]=="yes"){
				$x=getPath($tag->TagPara["target"])."/".$tag->TagPara["href"];
//				save_file(getPath($tag->TagPara["target"])."/".$tag->TagPara["href"], $temp, $mode);
				save_file($x, $temp, $mode);
			}

			$here=realpath(".");
			chdir(dirname($x));
			$x=basename($x);
			switch($tag->TagPara["codetype"]){
				case "pdf":
					exec ("pdflatex $x; pdflatex $x");
					break;
				case "rtf":
					exec ("latex2rtf $x");
					break;
//				case 'xls':
//					require_once 'toexcel.php';
//					Source2Excel($tag->TagPara["href"], $temp, true);
			}
			chdir($here);

			switch($tag->TagPara["type"]){
				case "hidden":
				case "xls":
					$contents=destroyTag($tag, $contents);
					break;
				default:
					$contents=str_replace($tag->CONTENT,$temp,$contents);
			}
		}
		// falls XLS!!
		$contents=destroyTag($tag, $contents);
		
	}
	
	/**
	File System Objekt
	<fso name="NAME" dir="" format="x*.txt" type="dir|src">[%NAME_src] [%NAME_dir]</fso>
	<fso name="NAME" dir="" type="src" src="array">[%NAME_src] [%NAME_dir]</fso>
	*/
	while ($tag=new Tag("fso", $contents) ){
		// Dateien und Ordner eines Ordners
		if(!isset($tag->TagPara["dir"])){
			destroyTag($tag, $contents);
			continue;
		}
			// nur subfolder zulassen (nicht aufwärts!!!
			$x=realpath(getPath($tag->TagPara["dir"]));
			$temp=$x;
			if($temp==""){
				$ERROR[]="Verzeichnis ".$tag->TagPara["dir"]." nicht gefunden";
			}
			if($x== substr(realpath("$x/".$tag->TagPara["archive"]), 0,strlen($x))){
				$x=realpath("$x/".$tag->TagPara["archive"]);
			}else{
				$tag->TagPara["archive"]="";
			}
			// Variable NAME_archive anpassen
			$_REQUEST[$tag->TagPara["name"]."_archive"]=str_replace($temp,".",$x);
			
			// Verzeichnis durchlaufen
			$folder = opendir($x);
			$verz_folders=array();
			$verz_files=array();
			while($temp && $folder && $file = readdir($folder)){
				// Verz oder file
				if(is_dir("$x/$file")){
					if($file!=".." || $x!=$temp){
						$verz_folders[]=$file;
					}
				}else{
					// sollen Dateien gefiltert werden?
					if(is_array($files)){
						if(in_array($file, $files)) $verz_files[]=$file;
					}else{
						$verz_files[]=$file;
					}
				}
			}
			if($tag->TagPara["type"]=="dir"){
				$cnt=count($verz_folders);
			}else{
				$cnt=count($verz_files);
			}
			$temp="";
			$x="";
			for ($pos=0;$pos<$cnt;$pos++){
				$temp=$tag->Text;
				if(is_array($verz_folders)){
					$temp=str_replace("[%".$tag->TagPara["name"]."_dir]", $verz_folders[$pos], $temp);
					$temp=str_replace("[%".$tag->TagPara["name"]."_src]", $verz_files[$pos], $temp);
					$x.=$temp;
				}
			}
			$contents=str_replace($tag->CONTENT, $x, $contents);
			$x="";
	}

	/**
	Template statisch exportieren
	<export dir="html" src="template.html" target="static" lowsrc="test.html" info="infotext" alt="..." title="...">
		<var>Value</var>
	</export>
	*/
	while($tag=new Tag("export", $contents)){
#		$page=getContent(getPath($tag->TagPara["dir"]), $tag->TagPara["src"]);
		$template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"], false);
		$page=$template->CONTENT;
		if($page){
			preg_match_all ('/<([a-z0-9_]*)>([^<]*)<\/([a-z0-9_]*)>/i',$tag->Text, $matches);
			for($i=0;$i<count($matches[1]);$i++){
				$page=str_replace("[$".$matches[1][$i]."]", $matches[2][$i],$page);
			}
//			if($PATH[$tag->TagPara["dir"]]["write"]==true){
				save_file($tag->TagPara["target"]/$tag->TagPara["lowsrc"], Template2Source($page));
//			}
		}
		$temp= str_replace("<export ", "<a ",$tag->Header);
		$temp= str_replace(" src=\"".$tag->TagPara["src"]."\"", "", $temp);
		$temp= str_replace(" info=\"".$tag->TagPara["info"]."\"", "", $temp);
		$contents=str_replace($tag->CONTENT, $temp.$tag->TagPara["info"]."</a>", $contents);
	}

	unset($tag);
	unset($itag);
	unset($htag);
	return $contents;
}

/**
Datei upload per ftp
<ftp dir="" src="" target="" method="FTP_ASCII">
while($tag=new Tag("ftp", $contents)){
	if($template= new Template($PATH, $tag->TagPara["dir"], $tag->TagPara["src"]){
	
	// speichern
	$zieldatei = "test.htm";
	$lokale_datei = "test.htm";
	$connection_id = ftp_connect($proxyhost);
	$login_result = ftp_login($connection_id, "$benutzername", "$passwort");
	$upload = ftp_put ($connection_id, "$zieldatei", "$lokale_datei", FTP_ASCII);
	ftp_quit($connection_id);

	// laden + speicher lokal
	$local_file_size = filesize($local_file_path);
	$get_result = ftp_get($connection_id, $local_file_path, $remote_file_path, FTP_BINARY, $local_file_size);
}

fopen("http://www.myserver.de/myphp.php", "r");
*/
?>
Return current item: Template Parser Engine