public function load($tpl, $quiet = false) { $tpldir_b4 = $this->cur_tpl_dir; /* Resolve ".", ".." and protect from possible LFI */ $tpl = str_replace("\\", "/", $tpl); if ($tpl[0] != "/") { $tpl = $this->cur_tpl_dir . "/" . $tpl; } $pathex = array_filter(explode("/", $tpl), function ($s) { return $s != "." and !empty($s); }); $pathex = array_merge($pathex); while (($i = array_search("..", $pathex)) !== false) { if ($i == 0) { $pathex = array_slice($pathex, 1); } else { $pathex = array_merge(array_slice($pathex, 0, $i), array_slice($pathex, $i + 2)); } } $tpl = implode("/", $pathex); $this->cur_tpl_dir = dirname($tpl); if ($quiet) { $blocks_back = clone $this->blocks; $blockorder_back = clone $this->blockorder; } $mode = StorageAccess::MODE_TRANSCOMPILED; $content = $this->storage_access->load($tpl, $mode); if ($mode == StorageAccess::MODE_SOURCE) { try { $ast = Parser::parse($content, $tpl); $transc = Transcompiler::transcompile($ast); } catch (ParseCompileError $e) { $e->rewrite($content); throw $e; } $this->storage_access->save($tpl, $transc, StorageAccess::MODE_TRANSCOMPILED); eval("\$content = {$transc};"); } $output = $content($this); $this->cur_tpl_dir = $tpldir_b4; if ($quiet) { $this->blocks = $blocks_back; $this->blockorder = $blockorder_back; } else { return $output; } }
if (!empty($text_and_var_buffer)) { $code .= "\$outputstack[\$outputstack_i] .= " . implode(" . ", $text_and_var_buffer) . ";\n"; } if ($avoid_outputstack) { $tmpvar = self::tempvar("tmp"); $code = "\$outputstack[] = '';\n\$outputstack_i++;" . $code; $code .= "\${$tmpvar} = array_pop(\$outputstack);\n\$outputstack_i--;\n"; return array("\${$tmpvar}", $code); } return $code; } /* * Function: transcompile * Transcompiles an abstract syntax tree to PHP. * You only need this function, if you want to manually transcompile a template. * * Parameters: * $ast - The abstract syntax tree to transcompile. * * Returns: * PHP code. The PHP code is an anonymous function expecting a <STECore> instance as its parameter and returns a string (everything that was not pached into a section). */ public static function transcompile($ast) { /* self::Transcompile and add some boilerplate code. */ $boilerplate = "\$outputstack = array('');\n\$outputstack_i = 0;\n"; return "function(\$ste)\n{\n" . self::indent_code($boilerplate . self::_transcompile($ast) . "return array_pop(\$outputstack);") . "\n}"; } } Transcompiler::init_builtins();