Index: trunk/core/kernel/parser/template_parser.php =================================================================== diff -u -r2566 -r2596 --- trunk/core/kernel/parser/template_parser.php (.../template_parser.php) (revision 2566) +++ trunk/core/kernel/parser/template_parser.php (.../template_parser.php) (revision 2596) @@ -1,13 +1,14 @@ Ses =& $this->Application->recallObject('Session'); } - + function AddParam($pattern, $value, $dont_sort=0) { $this->ForSort[] = Array($pattern, $value); if (!$dont_sort) //used when mass-adding params, to escape sorting after every new param $this->SortParams(); //but do sort by default! } - + //We need to sort params by its name length desc, so that params starting with same word get parsed correctly function SortParams() { @@ -51,15 +52,15 @@ $this->Values[] = $pair[1]; } } - + function CmpParams($a, $b) { $a_len = strlen($a[0]); $b_len = strlen($b[0]); if ($a_len == $b_len) return 0; return $a_len > $b_len ? -1 : 1; } - + function SetParams($params) { if (!is_array($params)) $params = Array(); @@ -69,39 +70,39 @@ } $this->SortParams(); //Sort once after adding is done } - + function GetParam($name) { //return isset($this->Params[strtolower($name)]) ? $this->Params[strtolower($name)] : false; return isset($this->Params[$name]) ? $this->Params[$name] : false; } - + function SetParam($name, $value) { $this->Params[strtolower($name)] = $value; } - + function SetBuffer($body) { $this->Buffers[$this->RecursionIndex] = $body; } - + function GetBuffer() { return $this->Buffers[$this->RecursionIndex]; } - + function GetCode() { - return $this->Code[$this->RecursionIndex]; + return $this->Code[$this->RecursionIndex]; } - + function AppendBuffer($append) { $this->Buffers[$this->RecursionIndex] .= $append; $this->AppendCode( $this->ConvertToCode($append) ); } - + function AppendOutput($append, $append_code=false) { if ($this->SkipMode == parse) { @@ -115,14 +116,14 @@ $this->AppendBuffer($append); //append to buffer if we are skipping tags } } - + function ConvertToCode($data) { $code = '$o .= \''. str_replace("'", "\'", $data) .'\';'; $code = explode("\n", $code); return $code; } - + function AppendCode($code) { if (defined('EXPERIMENTAL_PRE_PARSE')) { @@ -139,15 +140,15 @@ } } } - + function AppendCompiledFunction($f_name, $f_body) { $real_name = 'f_'.abs(crc32($this->TemplateName)).'_'.$f_name; if (defined('EXPERIMENTAL_PRE_PARSE')) { // if such function already compiled if ( isset($this->Application->CompiledFunctions[$f_name]) || function_exists($real_name) - ) + ) { if (!isset($this->Application->CompiledFunctions[$f_name])) { $real_name = $real_name.'_'; @@ -156,22 +157,22 @@ $real_name = $this->Application->CompiledFunctions[$f_name].'_'; } } - + $this->CompiledBuffer .= 'if (!function_exists(\''.$real_name.'\')) {'."\n"; - - + + $this->CompiledBuffer .= "\t".'$application->PreParsedBlocks[\''.$f_name.'\'] = \''.$real_name.'\';'; $this->CompiledBuffer .= "\n\t".'function '.$real_name.'($params)'."\n\t{\n"; $this->CompiledBuffer .= $f_body; $this->CompiledBuffer .= "\t}\n\n"; - + $this->CompiledBuffer .= '}'."\n"; - + $this->Application->CompiledFunctions[$f_name] = $real_name; - + } } - + function AppendCompiledCode($code) { if (defined('EXPERIMENTAL_PRE_PARSE')) { @@ -186,7 +187,7 @@ $this->CompiledBuffer .= "\t".'echo $o;'."\n\t".'$o = \'\';'."\n"; } } - + function AppendCompiledHTML($append) { if (defined('EXPERIMENTAL_PRE_PARSE')) { @@ -195,16 +196,16 @@ $this->CompiledBuffer .= '<'.'?php'."\n"; } } - + function ResetCode() { $this->Code[$this->RecursionIndex] = Array(); } - + function FindTag2() { $openings = Array('<%' => '%>', ' Array('>', '/>'), ' '>', '' => ''); - + $tag_open_pos = false; foreach ($openings as $an_opening => $closings) { $pos = strpos($this->Template, $an_opening, $this->Position); @@ -215,16 +216,16 @@ $tag_closings = $closings; } } - + if ($tag_open_pos === false) { //If no tags left - adding all other data $this->AppendOutput(substr($this->Template, $this->Position), true); return false; } - + //Adding all data before tag open $this->AppendOutput(substr($this->Template, $this->Position, $tag_open_pos - $this->Position), true); - - + + if (is_array($tag_closings)) { $tag_close_pos = false; foreach ($tag_closings as $a_closing) { @@ -244,11 +245,11 @@ $tag_close_pos = strpos($this->Template, $closing_tag, $tag_open_pos); } $close_len = strlen($closing_tag); - + //Cutting out the tag itself $tag = substr($this->Template, $tag_open_pos + $open_len, $tag_close_pos - $tag_open_pos - $open_len); - - + + if ($opening_tag == '') { //empty closing means old style in-portal if .... $tag = 'm:endif'; } - + if ($opening_tag == 'Params, 'PrefixSpecial'); - $tag = $prefix.$tag; + $tag = $prefix.$tag; } - + // temporary - for backward compatability with in-portal style if if ($opening_tag == '' && $tag_part != 'm_if' && $tag_part != 'm_DefineElement') { if (strpos($the_tag, ' ') !== false) { @@ -294,25 +295,25 @@ } $tag = 'm:if prefix="'.$prefix.'" function="'.$function.'" '.$params; } - - $this->Position = $tag_close_pos + $close_len; + + $this->Position = $tag_close_pos + $close_len; return $tag; } - + function CurrentLineNumber() { return substr_count(substr($this->Template, 0, $this->Position), "\n")+1; } - + function SkipModeName() { switch ($this->SkipMode) { case skip: return 'skip'; case skip_tags: return 'skip_tags'; - case parse: return 'parse'; + case parse: return 'parse'; } } - + function CheckDir($dir) { if (file_exists($dir)) { @@ -329,48 +330,64 @@ } } } - + function Parse($template, $name='unknown', $pre_parse = 1) { $this->Template = $template; $this->TemplateName = $name; $this->Position = 0; $this->Output = ''; $this->TagHolder = new MyTagHolder(); - + $has_inp_tags = false; - + if ($this->GetParam('from_inportal')) $pre_parse = 0; - + if (defined('EXPERIMENTAL_PRE_PARSE') && $pre_parse) { $template_cache =& $this->Application->recallObject('TemplatesCache'); $fname = $template_cache->GetRealFilename($this->TemplateName).'.php'; - + $fname = str_replace(DOC_ROOT.BASE_PATH, DOC_ROOT.BASE_PATH.'/kernel/cache', $fname); - $this->CheckDir(dirname($fname)); - + + if (!defined('SAFE_MODE') || !SAFE_MODE) { + $this->CheckDir(dirname($fname)); + } + $tname = $template_cache->GetRealFilename($this->TemplateName).'.tpl'; - - if (file_exists($fname) && filemtime($fname) > filemtime($tname)) { - ob_start(); - include($fname); - $output = ob_get_contents(); - ob_end_clean(); - - if ( !$this->GetParam('from_inportal') ) { - if ( strpos($output, 'Application->recallObject('Inp1Parser'); - $output = $inp1_parser->Parse($name, $output); - } + + $output = ''; + $is_cached = false; + ob_start(); + if (defined('SAFE_MODE') && SAFE_MODE) { + $conn =& $this->Application->GetADODBConnection(); + $cached = $conn->GetRow('SELECT * FROM '.TABLE_PREFIX.'Cache WHERE VarName = "'.$fname.'"'); + if ($cached !== false && $cached['Cached'] > filemtime($tname)) { + eval('?'.'>'.$cached['Data'].'<'.'?'); + $is_cached = true; } + } + else { + if (file_exists($fname) && filemtime($fname) > filemtime($tname)) { + include($fname); + $is_cached = true; + } + } + $output = ob_get_contents(); + ob_end_clean(); + + if ( $is_cached && !$this->GetParam('from_inportal') ) { + if ( strpos($output, 'Application->recallObject('Inp1Parser'); + $output = $inp1_parser->Parse($name, $output); + } return $output; } - + $this->CompiledBuffer .= '<'.'?php'."\n"; $this->CompiledBuffer .= 'global $application;'."\n"; $this->CompiledBuffer .= '$o = \'\';'."\n"; } - + if (!getArrayValue($this->Params, 'PrefixSpecial')) { $this->Params['PrefixSpecial'] = '$PrefixSpecial'; } @@ -386,41 +403,47 @@ } // $tag =& new MyTag($tag_data, $this); $tag =& $this->TagHolder->GetTag($tag_data, $this); - + if (!$this->CheckRecursion($tag)) //we do NOT process closing tags { $tag->Process(); } } - + if ( !$this->GetParam('from_inportal') ) { if ( strpos($this->Output, 'Application->recallObject('Inp1Parser'); $this->Output = $inp1_parser->Parse($name, $this->Output); $has_inp_tags = true; } } - - + + if (defined('EXPERIMENTAL_PRE_PARSE') && $pre_parse && !$has_inp_tags) { // $this->CompiledBuffer .= 'echo $o;'."\n"; $this->CompiledBuffer .= '?'.'>'."\n"; - - $compiled = fopen($fname, 'w'); - fwrite($compiled, $this->CompiledBuffer); - fclose($compiled); + + if (defined('SAFE_MODE') && SAFE_MODE) { + if (!isset($conn)) $conn =& $this->Application->GetADODBConnection(); + $conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ('.$conn->qstr($fname).','.$conn->qstr(str_replace('<'.'?php','<'.'?',$this->CompiledBuffer)).','.mktime().')'); + } + else { + $compiled = fopen($fname, 'w'); + fwrite($compiled, $this->CompiledBuffer); + fclose($compiled); + } } - + return $this->Output; } - + function ParseBlock($params, $force_pass_params=0, $as_template=false) { if( $this->Application->isDebugMode() && dbg_ConstOn('DBG_SHOW_TAGS') ) { global $debugger; $debugger->appendHTML('ParseBlock '.$params['name'].' pass_params is '.$params['pass_params'].' force is '.$force_pass_params.' in '.$debugger->getFileLink($debugger->getLocalFile(DOC_ROOT.BASE_PATH.THEMES_PATH.'/'.$this->TemplateName).'.tpl', $this->CurrentLineNumber(), '', true)); - + } /*if ( $this->Application->isDebugMode() && dbg_ConstOn('DBG_PRE_PARSE') ) { global $debugger; @@ -429,35 +452,35 @@ if (defined('EXPERIMENTAL_PRE_PARSE')) { $this->MainParser = false; if (isset($this->Application->PreParsedBlocks[$params['name']]) ) { - + if ($this->ParamsRecursionIndex == 0) { $this->ParamsStack[$this->ParamsRecursionIndex] = $this->Params; } - + if (isset($params['pass_params']) || $force_pass_params) { $pass_params = array_merge($this->ParamsStack[$this->ParamsRecursionIndex], $params); } else { $pass_params = $params; } - + $this->ParamsStack[++$this->ParamsRecursionIndex] = $pass_params; $this->Params = $pass_params; - + $f = $this->Application->PreParsedBlocks[$params['name']]; - + // $this->ParamsRecursionIndex--; - + //$this->SetParams($params); $ret = $f($pass_params); - + unset($this->ParamsStack[$this->ParamsRecursionIndex--]); $this->Params = $this->ParamsStack[$this->ParamsRecursionIndex]; $this->MainParser = true; return $ret; } } - + $BlockParser =& $this->Application->makeClass('TemplateParser'); if (isset($params['pass_params']) || $force_pass_params) { $BlockParser->SetParams(array_merge($this->Params, $params)); @@ -467,32 +490,32 @@ $this->Application->Parser =& $BlockParser; if (!isset($params['name'])) trigger_error('***Error: Block name not passed to ParseBlock', E_USER_ERROR); $templates_cache =& $this->Application->recallObject('TemplatesCache'); - + $template_name = $as_template ? $params['name'] : $templates_cache->GetTemplateFileName($params['name']) . '-block:'.$params['name']; - + $silent = getArrayValue($params, 'from_inportal') && !defined('DBG_TEMPLATE_FAILURE'); - + $o = $BlockParser->Parse( - $templates_cache->GetTemplateBody($params['name'], $silent), + $templates_cache->GetTemplateBody($params['name'], $silent), $template_name ); if (getArrayValue($params, 'BlockNoData') && !$BlockParser->DataExists) { $template_name = $as_template ? $params['BlockNoData'] : $templates_cache->GetTemplateFileName($params['BlockNoData']) . '-block:'.$params['BlockNoData']; $o = $BlockParser->Parse( - $templates_cache->GetTemplateBody($params['BlockNoData'], $silent), + $templates_cache->GetTemplateBody($params['BlockNoData'], $silent), $template_name - ); + ); } $this->Application->Parser =& $this; $this->Application->Parser->DataExists = $this->Application->Parser->DataExists || $BlockParser->DataExists; return $o; } - + function Recurve(&$tag) { $this->Recursion[++$this->RecursionIndex] =& $tag; } - + function CheckRecursion(&$tag) { if ($this->RecursionIndex > 0) { //If we are inside the recursion @@ -503,7 +526,7 @@ } return false; } - + function SetSkipMode($mode) { $this->SkipMode = $mode;