<?php
/**
 * 文件名：template.han.php
 * 版本号：1.0
 * 最后修改时间：20010年05月18日
 * 作者：狐狸<foxis@qq.com>
 * 功能描述：一个模板模板操作类
 */

function addquote($var) {
	return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
}

function stripvtags($expr, $statement) {
		$expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
	$statement = str_replace("\\\"", "\"", $statement);
	return $expr.$statement;
}

class TemplateHandler 
{
	var $TemplateRootPath="./templates/";	var $TemplatePath="";					var $TemplateDir="default";				var $CompiledFolder="compiled_tpl/";	var $CompiledPath="";					var $TemplateFile="";					var $CompiledFile="";					var $TemplateString="";				var $TemplateExtension='.html'; 	var $CompiledExtension='.php'; 	var $LinkFileType='css|js|jpeg|jpg|png|bmp|gif|swf'; 
	
	function TemplateHandler(&$config) 
	{
		$this->TemplateRootPath=isset($config['template_root_path'])?$config['template_root_path']:"./templates/";
		$this->TemplateDir=$config['template_path'];
		$this->TemplatePath=$this->TemplateRootPath.$this->TemplateDir.'/';
		if(!isset($config['compiled_root_path']) or $config['compiled_root_path']=='') 
		{
			$this->CompiledPath=$this->TemplatePath.$this->CompiledFolder;
		}
		else 
		{
			$this->CompiledPath=$config['compiled_root_path'].'/'.$this->TemplateDir.'/';
		}
			}

	
	function Template($filename) 
	{
		$this->TemplateFile=$this->TemplatePath.$filename.$this->TemplateExtension;
		$this->CompiledFile=$this->CompiledPath.$filename.$this->CompiledExtension;
		if(!is_file($this->TemplateFile))
		{
			$tpl_path= strpos($this->TemplateDir,'/') ? dirname($this->TemplatePath) . '/' : dirname($this->TemplatePath).'/default/';
			$this->TemplateFile=$tpl_path.$filename.$this->TemplateExtension;
			$this->CompiledFile=$this->CompiledPath.$filename.$this->CompiledExtension;
			if(!is_file($this->TemplateFile))
			die("模板文件'".$this->TemplateFile."'不存在，请检查目录");
		}
		if(@filemtime($this->TemplateFile) > @filemtime($this->CompiledFile))
		{
			if($this->Load())
			{
				$this->Compile();
				$this->Write();
			}
			else 
			{
				Return false;
			}
			
		}
		Return $this->CompiledFile;
	}

	
	function EvalTemplate($filename) 
	{
		$this->TemplateFile=$this->TemplatePath.$filename.$this->TemplateExtension;
		$this->Load();
		$contents=str_replace('"','\"',$this->TemplateString);
		Return "return \"{$contents}\";";
	}
	
	
	function Load() 
	{
		$fp=fopen($this->TemplateFile,'rb');
		if($fp) 
		{
			$this->TemplateString=fread($fp,filesize($this->TemplateFile));
		}
		fclose($fp);
		Return true;
	}

	
	function Compile() 
	{
		global $rewriteHandler;
		$var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(-\>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)?(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
		$const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";

		$nest = 5;
		
		$template=$this->TemplateString;
		
				$rndvar = 'AF' . random(rand(4,12));
		$append="<SCRIPT LANGUAGE=\"JavaScript\">
		var {$rndvar}=document.getElementsByName('FOR'+'MHA'+'SH');
		for(var i=0;i<{$rndvar}.length;i++){$rndvar}[i].value='{FORMHASH}';
		</SCRIPT>";
		if(preg_match("/(\<form.*? method=[\"\']?post[\"\']?[^\>]*\>)/i",$template))
		{
			$template.=$append;
		}
		$template = preg_replace("/(\<form.*? method=[\"\']?post[\"\']?)([^\>]*\>)/i","\\1 \\2\n<input type=\"hidden\" name=\"FORMHASH\" value=\"".substr(md5($rndvar),0,16)."\"/>",$template);
		
				$template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);

		$template = str_replace("{LF}", "<?=\"\\n\"?>", $template);

		$template = preg_replace("/\{$var_regexp\}/s", "<?=\\1?>", $template);

		$template = preg_replace("/$var_regexp/es", "addquote('<?=\\1?>')", $template);
		$template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "addquote('<?=\\1?>')", $template);

		$template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_\/]+)\}[\n\r\t]*/is", "\n<? include \$this->TemplateHandler->template('\\1'); ?>\n", $template);
		$template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", "\n<? include \$this->TemplateHandler->template(\\1); ?>\n", $template);
		$template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? \\1 ?>\n','')", $template);

		$template = preg_replace("/[\n\r\t]*\{conf\s+(.+?)\}[\n\r\t]*/ies", "addquote('<?=\$this->Config[\\1]?>')", $template);
		
		$template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('<? echo \\1; ?>','')", $template);
		$template = preg_replace("/[\n\r\t]*\{elseif\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('<? } elseif(\\1) { ?>','')", $template);
		$template = preg_replace("/[\n\r\t]*\{else\}[\n\r\t]*/is", "\n<? } else { ?>", $template);

		for($i = 0; $i < $nest; $i++) {
			$template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/ies", "stripvtags('\n<? if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\n\\3\n<? } } ?>\n')", $template);
			$template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*(.+?)[\n\r\t]*\{\/loop\}[\n\r\t]*/ies", "stripvtags('\n<? if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\n\\4\n<? } } ?>\n')", $template);
			$template = preg_replace("/[\n\r\t]*\{if\s+(.+?)\}[\n\r]*(.+?)[\n\r]*\{\/if\}[\n\r\t]*/ies", "stripvtags('\n<? if(\\1) { ?>','\n\\2\n<? } ?>\n')", $template);
			$template = preg_replace("/[\n\r\t]*\{while\s+(.+?)\}[\n\r]*(.+?)[\n\r]*\{\/while\}[\n\r\t]*/ies", "stripvtags('\n<? while(\\1) { ?>','\n\\2\n<? } ?>\n')", $template);
		}
		$template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
		$template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
		if(false === DEBUG) {
			$template = preg_replace("/<\!\-\-.*?\-\->/s"," ",$template);
			$template = preg_replace("/\>[\r\n\t\s]+?\</s","> <",$template);
			$template = preg_replace("/[\r\n][\r\n\t\s]+/s","\n",$template);
		}
		$template = trim($template);
		$this->TemplateString=$template;

		if(!empty($this->LinkFileType)) 
		{
			$this->ModifyLinks();
		}
		if($rewriteHandler)
		{
			$this->TemplateString=$rewriteHandler->output($this->TemplateString,true);
		}
	}
	
	function write() 
	{
		$save_dir=dirname($this->CompiledFile);
		if(!is_dir($save_dir))$this->MakeDir($save_dir, 0777);
        $fp = fopen($this->CompiledFile, 'wb');
        if(!$fp)die('模板无法写入,请检查目录是否有可写');
        $length=fwrite($fp, $this->TemplateString);
        fclose($fp);
		Return $length;
	}

    
    function MakeDir($dir_name, $mode = 0777)
    {
        $dir_name = str_replace("\\", "/", $dir_name);
        $dir_name = preg_replace("#(/"."/+)#", "/", $dir_name);
        if (is_dir($dir_name) !== false)Return true;
        $dir_name = explode("/", $dir_name);
		$dirs='';
        foreach($dir_name as $dir)
        {
            if (trim($dir) != '')
            {
                $dirs .= $dir . "/";
                if (is_dir($dirs)==false && @mkdir($dirs, $mode) === false)
                {
                    Return false;
                } else {
                	;
                }
            } 
        } 
        Return true;
    }
	
	function ModifyLinksbak()
	{
		preg_match_all("/src=[\"\'\s]?(.*?)[\"\'\s]|url[\(\"\']{1,3}(.*?)[\s\"\'\)]|background=[\"\']?(.*?)[\"\'\s]|href=[\"\'\s]?(.*?)[\"\'](.*?)\>/si", $this->TemplateString, $match);
		
		$old = @array_values(array_merge(@array_unique($match[1]), $match[2], @array_unique($match[3]), $match[4]));
		$old = array_unique($old);
		$old=preg_grep("~.*?\.(".$this->LinkFileType.")$~i",$old);
		foreach($old as $link)
		{
			if(trim($link) != "" and !strpos($link, ':/'.'/'))
			{
				if(strpos($link,'../')===0) 
				{
					$this->TemplateString=str_replace($link, dirname($this->TemplatePath) . '/' . ltrim($link, './'), $this->TemplateString);	
				}
				else
				{
				$this->TemplateString = str_replace($link, rtrim($this->TemplatePath,'\/') . '/' . ltrim($link, './'), $this->TemplateString);
				}
			}
		}
		return $this->TemplateString;
	}
		function ModifyLinks()
	{
		preg_match_all("/src=[\"\'\s]?(.*?)[\"\'\s]|url[\(\"\']{1,3}(.*?)[\s\"\'\)]|background=[\"\']?(.*?)[\"\'\s]|href=[\"\'\s]?(.*?)[\"\'](.*?)\>/si", $this->TemplateString, $match);
		
		$old = @array_values(array_merge(@array_unique($match[1]), $match[2], @array_unique($match[3]), $match[4]));
		$old = array_unique($old);
		$old=preg_grep("~.*?\.(".$this->LinkFileType.")$~i",$old);
		foreach($old as $link)
		{
			if(trim($link) != "" and false===strpos($link, ':/'.'/'))
			{
				$private_file=str_replace('templates/default/','templates/'.$this->TemplateDir.'/',$link);
				if (!is_file($private_file) && false===strpos($private_file,'templates')) {
					$private_file = 'templates/' . $this->TemplateDir . '/' . $private_file;
				}
				if('default'!=$this->TemplateDir && !is_file($private_file)) {
					$private_file = str_replace('templates/'.$this->TemplateDir.'/','templates/default/',$private_file);
				}
				if(is_file($private_file)==false) {
					continue;
				}

				$this->TemplateString = str_replace($link,$private_file, $this->TemplateString);
			}
		}
		return $this->TemplateString;
	}

	
	function RepairBracket($var) 
	{
		Return preg_replace("~\[([a-z0-9_\x7f-\xff]*?[a-z_\x7f-\xff]+[a-z0-9_\x7f-\xff]*?)\]~i","[\"\\1\"]",$var);
	}


}



?>