| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- <?php
- /**
- * [Discuz!] (C)2001-2099 Discuz! Team
- * This is NOT a freeware, use is subject to license terms
- * https://license.discuz.vip
- */
- if (!defined('IN_DISCUZ')) {
- exit('Access Denied');
- }
- class template {
- var $subtemplates = [];
- var $csscurmodules = '';
- var $replacecode = ['search' => [], 'replace' => []];
- var $blocks = [];
- var $language = [];
- var $file = '';
- var $filetype = 'htm';
- var $debug = 0;
- var $cellFuncs = [];
- function parse_template($tplfile, $templateid = 1, $tpldir = '', $file = '', $cachefile = '', $postparse = null) {
- $f = $tplfile;
- $basefile = basename($f, '.' . $this->filetype);
- $file == 'common/header' && defined('CURMODULE') && CURMODULE && $file = 'common/header_' . CURMODULE;
- $this->file = $file;
- if (tplfile::file_exists($tplfile)) {
- $template = tplfile::file_get_contents($tplfile);
- } elseif (tplfile::file_exists($filename = substr($tplfile, 0, -(strlen($this->filetype) + 1)) . '.php')) {
- $template = tplfile::file_get_contents($filename);
- $template = tplfile::getphptemplate($template);
- } else {
- $tpl = $tpldir . '/' . $file . '.' . $this->filetype;
- $tplfile = $tplfile != $tpl ? $tpl . ', ' . $tplfile : $tplfile;
- $this->error('template_notfound', $tplfile);
- }
- if ($this->debug) {
- $template = $this->insertdebugmsg($template, $tplfile);
- }
- $var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\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]*)";
- $headerexists = preg_match('/{(sub)?template\s+[\w:\/]+?header\}/', $template);
- $this->subtemplates = [];
- for ($i = 1; $i <= 3; $i++) {
- if (strexists($template, '{subtemplate')) {
- $template = preg_replace_callback("/[\n\r\t]*(\<\!\-\-)?\{subtemplate\s+([a-z0-9_:\/]+)\}(\-\-\>)?[\n\r\t]*/is", [$this, 'parse_template_callback_loadsubtemplate_2'], $template);
- }
- }
- $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
- $template = preg_replace('/\/\*\*\{(.+?)\}\*\//s', "{\\1}", $template);
- $template = preg_replace('/\<\!\-\-\{(.+?)\}\-\-\>/s', "{\\1}", $template);
- $template = preg_replace_callback("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/i", [$this, 'parse_template_callback_blocktags_1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{blockdata\/(\d+?)\}[\n\r\t]*/i", [$this, 'parse_template_callback_blockdatatags_1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{ad\/(.+?)\}[\n\r\t]*/i", [$this, 'parse_template_callback_adtags_1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{ad\s+([a-zA-Z0-9_\[\]]+)\/(.+?)\}[\n\r\t]*/i", [$this, 'parse_template_callback_adtags_21'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{date\((.+?)\)\}[\n\r\t]*/i", [$this, 'parse_template_callback_datetags_1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{avatar\((.+?)\)\}[\n\r\t]*/i", [$this, 'parse_template_callback_avatartags_1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{eval\}\s*(\<\!\-\-)*(.+?)(\-\-\>)*\s*\{\/eval\}[\n\r\t]*/is", [$this, 'parse_template_callback_evaltags_2'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{eval\s+(.+?)\s*\}[\n\r\t]*/is", [$this, 'parse_template_callback_evaltags_1'], $template);
- $template = str_replace('{LF}', "<?=\"\\n\"?>", $template);
- $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)\s(or|\?\?)\s([a-zA-Z0-9\']+)\}/s", "{echo \\1 ?? \\3}", $template);
- $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
- $template = preg_replace_callback('/\{hook\/(\w+?)(\s+(.+?))?\}/i', [$this, 'parse_template_callback_hooktags_13'], $template);
- $template = preg_replace_callback("/$var_regexp/s", [$this, 'parse_template_callback_addquote_1'], $template);
- $template = preg_replace_callback("/\<\?\=\<\?\=$var_regexp\?\>\?\>/s", [$this, 'parse_template_callback_addquote_1'], $template);
- $headeradd = $headerexists ? "hookscriptoutput('$basefile');" : '';
- if (!empty($this->subtemplates)) {
- $headeradd .= "\n0\n";
- foreach ($this->subtemplates as $fname) {
- $headeradd .= "|| checktplrefresh('$tplfile', '$fname', " . time() . ", '$templateid', '$cachefile', '$tpldir', '$file')\n";
- }
- $headeradd .= ';';
- }
- if (!empty($this->blocks)) {
- $headeradd .= "\n";
- $headeradd .= "block_get('" . implode(',', $this->blocks) . "');";
- }
- if (!empty($this->cellFuncs)) {
- $headeradd .= "\n";
- $headeradd .= implode('', $this->cellFuncs) . ';';
- }
- if ($headerexists) {
- $headeradd .= "if(defined('IN_RESTFUL')) {\$GLOBALS['_L'] = get_defined_vars();exit;}";
- }
- if ($cachefile) {
- $template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); {$headeradd}?>\n$template";
- }
- $template = preg_replace_callback("/[\n\r\t]*\{template\s+([a-z0-9_:\/]+)\}[\n\r\t]*/is", [$this, 'parse_template_callback_stripvtags_template1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", [$this, 'parse_template_callback_stripvtags_template1'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/is", [$this, 'parse_template_callback_stripvtags_echo1'], $template);
- $template = preg_replace_callback("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r\t]*)/is", [$this, 'parse_template_callback_stripvtags_if123'], $template);
- $template = preg_replace_callback("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/is", [$this, 'parse_template_callback_stripvtags_elseif123'], $template);
- $template = preg_replace('/\{else\}/i', '<? } else { ?>', $template);
- $template = preg_replace('/\{\/if\}/i', '<? } ?>', $template);
- $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", [$this, 'parse_template_callback_stripvtags_loop12'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", [$this, 'parse_template_callback_stripvtags_loop123'], $template);
- $template = preg_replace('/\{\/loop\}/i', '<? } ?>', $template);
- $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
- if (!empty($this->replacecode)) {
- $template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
- }
- $template = preg_replace("/ \?\>[\n\r]*\<\? /s", ' ', $template);
- if ($cachefile && !@$fp = fopen(DISCUZ_DATA . $cachefile, 'c')) {
- $this->error('directory_notfound', dirname(DISCUZ_DATA . $cachefile));
- }
- $template = preg_replace_callback("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/", [$this, 'parse_template_callback_transamp_0'], $template);
- $template = preg_replace_callback("/\<script[^\>]*?src=\"(.+?)\"(.*?)\>\s*\<\/script\>/is", [$this, 'parse_template_callback_stripscriptamp_12'], $template);
- $template = preg_replace_callback("/[\n\r\t]*\{block\s+([a-zA-Z0-9_\[\]']+)\}(.+?)\{\/block\}/is", [$this, 'parse_template_callback_stripblock_12'], $template);
- $template = preg_replace('/\<\?(\s{1})/is', "<?php\\1", $template);
- $template = preg_replace('/\<\?\=(.+?)\?\>/is', "<?php echo \\1;?>", $template);
- if ($this->debug) {
- $template = preg_replace_callback("/\<script[\s\w=\/\"]*?\>.+?\<\/script\>/is", [$this, 'parse_template_callback_scriptdebugconvert_0'], $template);
- }
- if (is_callable($postparse)) {
- $template = $postparse($template);
- }
- if (!($cachefile && $fp && flock($fp, LOCK_EX) && ftruncate($fp, 0) && fwrite($fp, $template) && fflush($fp) && flock($fp, LOCK_UN) && fclose($fp))) {
- return $template;
- }
- }
- function parse_template_callback_loadsubtemplate_2($matches) {
- return $this->loadsubtemplate($matches[2]);
- }
- function parse_template_callback_blocktags_1($matches) {
- return $this->blocktags($matches[1]);
- }
- function parse_template_callback_blockdatatags_1($matches) {
- return $this->blockdatatags($matches[1]);
- }
- function parse_template_callback_adtags_1($matches) {
- return $this->adtags($matches[1]);
- }
- function parse_template_callback_adtags_21($matches) {
- return $this->adtags($matches[2], $matches[1]);
- }
- function parse_template_callback_datetags_1($matches) {
- return $this->datetags($matches[1]);
- }
- function parse_template_callback_avatartags_1($matches) {
- return $this->avatartags($matches[1]);
- }
- function parse_template_callback_evaltags_2($matches) {
- return $this->evaltags($matches[2]);
- }
- function parse_template_callback_evaltags_1($matches) {
- return $this->evaltags($matches[1]);
- }
- function parse_template_callback_hooktags_13($matches) {
- return $this->hooktags($matches[1], $matches[3] ?? '');
- }
- function parse_template_callback_addquote_1($matches) {
- return $this->addquote('<?=' . $matches[1] . '?>');
- }
- function parse_template_callback_stripvtags_template1($matches) {
- return $this->stripvtags('<? include template(\'' . $matches[1] . '\'); ?>');
- }
- function parse_template_callback_stripvtags_echo1($matches) {
- return $this->stripvtags('<? echo ' . $this->echopolyfill($matches[1]) . '; ?>');
- }
- function parse_template_callback_stripvtags_if123($matches) {
- return $this->stripvtags($matches[1] . '<? if(' . $matches[2] . ') { ?>' . $matches[3]);
- }
- function parse_template_callback_stripvtags_elseif123($matches) {
- return $this->stripvtags($matches[1] . '<? } elseif(' . $matches[2] . ') { ?>' . $matches[3]);
- }
- function parse_template_callback_stripvtags_loop12($matches) {
- return $this->stripvtags($this->looptags($matches[1], $matches[2]));
- }
- function parse_template_callback_stripvtags_loop123($matches) {
- return $this->stripvtags($this->looptags($matches[1], $matches[2], $matches[3]));
- }
- function parse_template_callback_transamp_0($matches) {
- return $this->transamp($matches[0]);
- }
- function parse_template_callback_stripscriptamp_12($matches) {
- return $this->stripscriptamp($matches[1], $matches[2]);
- }
- function parse_template_callback_stripblock_12($matches) {
- return $this->stripblock($matches[1], $matches[2]);
- }
- function parse_template_callback_scriptdebugconvert_0($matches) {
- return $this->scriptdebugconvert($matches[0]);
- }
- function blocktags($parameter) {
- $bid = intval(trim($parameter));
- $this->blocks[] = $bid;
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--BLOCK_TAG_$i-->";
- $this->replacecode['replace'][$i] = "<?php block_display('$bid');?>";
- return $search;
- }
- function blockdatatags($parameter) {
- $bid = intval(trim($parameter));
- $this->blocks[] = $bid;
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--BLOCKDATA_TAG_$i-->";
- $this->replacecode['replace'][$i] = '';
- return $search;
- }
- function adtags($parameter, $varname = '') {
- $parameter = stripslashes($parameter);
- $parameter = preg_replace("/(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)/s", "{\\1}", $this->addquote($parameter));
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--AD_TAG_$i-->";
- $this->replacecode['replace'][$i] = '<?php ' . (!$varname ? 'echo ' : '$' . $varname . '=') . "adshow(\"$parameter\");?>";
- return $search;
- }
- function datetags($parameter) {
- $parameter = stripslashes($parameter);
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--DATE_TAG_$i-->";
- $this->replacecode['replace'][$i] = "<?php echo dgmdate($parameter);?>";
- return $search;
- }
- function avatartags($parameter) {
- $parameter = stripslashes($parameter);
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--AVATAR_TAG_$i-->";
- $this->replacecode['replace'][$i] = "<?php echo avatar($parameter);?>";
- return $search;
- }
- function evaltags($php) {
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--EVAL_TAG_$i-->";
- $this->replacecode['replace'][$i] = $this->debug ? '<? ' . preg_replace(['/^L\d+[\w\.\/]*\-\-\>/', '/\<\!\-\-L\d+[\w\.\/]*\-\-\>/', '/\<\!\-\-L\d+[\w\.\/]*$/', '/^\s*\<\!\-\-/', '/\-\-\>\s*$/'], '', $php) . '?>' : "<? $php?>";
- return $search;
- }
- function hooktags($hookid, $key = '') {
- global $_G;
- $i = count($this->replacecode['search']);
- $this->replacecode['search'][$i] = $search = "<!--HOOK_TAG_$i-->";
- $dev = '';
- if (isset($_G['config']['plugindeveloper']) && $_G['config']['plugindeveloper'] == 2) {
- $dev = "echo '<hook>[" . ($key ? 'array' : 'string') . " $hookid" . ($key ? '/\'.' . $key . '.\'' : '') . "]</hook>';";
- }
- $key = $key != '' ? "[$key]" : '';
- $this->replacecode['replace'][$i] = "<?php {$dev}if(!empty(\$_G['setting']['pluginhooks']['$hookid']$key)) echo \$_G['setting']['pluginhooks']['$hookid']$key;?>";
- return $search;
- }
- function stripphpcode($type, $code) {
- $this->phpcode[$type][] = $code;
- return '{phpcode:' . $type . '/' . (count($this->phpcode[$type]) - 1) . '}';
- }
- function loadsubtemplate($file) {
- $tplfile = template($file, 0, '', 1);
- $filename = $tplfile;
- if ((tplfile::file_exists($filename) && is_readable($filename) && ($content = tplfile::file_get_contents($filename))) ||
- (tplfile::file_exists(substr($filename, 0, -4) . '.php') && is_readable(substr($filename, 0, -4) . '.php') && ($content = tplfile::getphptemplate(tplfile::file_get_contents(substr($filename, 0, -4) . '.php'))))) {
- $this->subtemplates[] = $tplfile;
- return $this->debug ? $this->insertdebugmsg($content, $tplfile) : $content;
- } else {
- return '<!-- ' . $file . ' -->';
- }
- }
- function looptags($param1, $param2, $param3 = '') {
- if (preg_match("/^\<\?\=\\\$.+?\?\>$/s", $param1)) {
- $exprtemp = $param1;
- $return = '<? if(isset(' . $param1 . ') && is_array(' . $param1 . ')) ';
- } else {
- $exprtemp = '$l_' . random(8);
- $return = '<? ' . $exprtemp . ' = ' . $param1 . ';if(is_array(' . $exprtemp . ')) ';
- }
- if ($param3) {
- $return .= 'foreach(' . $exprtemp . ' as ' . $param2 . ' => ' . $param3 . ') { ?>';
- } else {
- $return .= 'foreach(' . $exprtemp . ' as ' . $param2 . ') { ?>';
- }
- return $return;
- }
- function echopolyfill($str) {
- $str = str_replace(' or ', ' ?? ', $str);
- if (str_contains($str, ' ?? ') && version_compare(PHP_VERSION, '7.0', '<')) {
- $str = preg_replace('/^(.+)\s\?\?\s(.+)$/', "isset(\\1) ? (\\1) : (\\2)", $str);
- }
- return $str;
- }
- function transamp($str) {
- $str = str_replace('&', '&', $str);
- $str = str_replace('&amp;', '&', $str);
- return $str;
- }
- function addquote($var) {
- return str_replace("\\\"", "\"", preg_replace_callback("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", [$this, 'addquote_exec'], $var));
- }
- function addquote_exec($matches) {
- return is_numeric($matches[1]) ? '[' . $matches[1] . ']' : "['" . $matches[1] . "']";
- }
- function stripvtags($expr, $statement = '') {
- $expr = str_replace('\\\"', '\"', preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
- if ($this->debug) {
- $expr = preg_replace('/\<\!\-\-L\d+[\w\.\/]*\-\-\>/', '', $expr);
- }
- $statement = str_replace('\\\"', '\"', $statement);
- return $expr . $statement;
- }
- function stripscriptamp($s, $extra) {
- $s = str_replace('&', '&', $s);
- return "<script src=\"$s\" type=\"text/javascript\"$extra></script>";
- }
- function stripblock($var, $s) {
- $var = $this->addquote($var);
- $s = preg_replace("/<\?=\\\$(.+?)\?>/", "{\$\\1}", $s);
- preg_match_all('/<\?=(.+?)\?>/', $s, $constary);
- $constadd = '';
- $constary[1] = array_unique($constary[1]);
- foreach ($constary[1] as $const) {
- $constadd .= '$__' . $const . ' = ' . $const . ';';
- }
- $s = preg_replace('/<\?=(.+?)\?>/', "{\$__\\1}", $s);
- $s = str_replace('?>', "\n\$$var .= <<<EOF\n", $s);
- $s = str_replace('<?', "\nEOF;\n", $s);
- $s = str_replace("\nphp ", "\n", $s);
- return "<?\n$constadd\$$var = <<<EOF\n" . $s . "\nEOF;\n?>";
- }
- function scriptdebugconvert($str) {
- return preg_replace('/\<\!\-\-L(\d+[\w\.\/]*)\-\-\>/', '/**L\1*/', $str);
- }
- function insertdebugmsg($str, $filename) {
- $startmsg = '<!-- BEGIN ' . $filename . ' -->';
- $endmsg = '<!-- END ' . $filename . ' -->';
- $count = 2;
- $debuglevel = $this->debug;
- $str = preg_replace_callback('/\n(\t*)/', function ($matches) use (&$count, $filename, $debuglevel) {
- if ($debuglevel > 1) {
- return "\n" . $matches[1] . '<!--L' . $count++ . $filename . '-->';
- } else {
- return "\n" . $matches[1] . '<!--L' . $count++ . '-->';
- }
- }, $str);
- return $startmsg . $str . $endmsg;
- }
- function error($message, $tplname) {
- discuz_error::template_error($message, $tplname);
- }
- }
|