class_template.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: class_template.php 36284 2016-12-12 00:47:50Z nemohou $
  7. */
  8. if(!defined('IN_DISCUZ')) {
  9. exit('Access Denied');
  10. }
  11. class template {
  12. var $subtemplates = array();
  13. var $csscurmodules = '';
  14. var $replacecode = array('search' => array(), 'replace' => array());
  15. var $blocks = array();
  16. var $language = array();
  17. var $file = '';
  18. function parse_template($tplfile, $templateid, $tpldir, $file, $cachefile) {
  19. $basefile = basename(DISCUZ_ROOT.$tplfile, '.htm');
  20. $file == 'common/header' && defined('CURMODULE') && CURMODULE && $file = 'common/header_'.CURMODULE;
  21. $this->file = $file;
  22. if($fp = @fopen(DISCUZ_ROOT.$tplfile, 'r')) {
  23. $template = @fread($fp, filesize(DISCUZ_ROOT.$tplfile));
  24. fclose($fp);
  25. } elseif($fp = @fopen($filename = substr(DISCUZ_ROOT.$tplfile, 0, -4).'.php', 'r')) {
  26. $template = $this->getphptemplate(@fread($fp, filesize($filename)));
  27. fclose($fp);
  28. } else {
  29. $tpl = $tpldir.'/'.$file.'.htm';
  30. $tplfile = $tplfile != $tpl ? $tpl.', '.$tplfile : $tplfile;
  31. $this->error('template_notfound', $tplfile);
  32. }
  33. $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]+\])*)";
  34. $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";
  35. $headerexists = preg_match("/{(sub)?template\s+[\w:\/]+?header\}/", $template);
  36. $this->subtemplates = array();
  37. for($i = 1; $i <= 3; $i++) {
  38. if(strexists($template, '{subtemplate')) {
  39. $template = preg_replace_callback("/[\n\r\t]*(\<\!\-\-)?\{subtemplate\s+([a-z0-9_:\/]+)\}(\-\-\>)?[\n\r\t]*/is", array($this, 'parse_template_callback_loadsubtemplate_2'), $template);
  40. }
  41. }
  42. $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
  43. $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
  44. $template = preg_replace_callback("/\{lang\s+(.+?)\}/is", array($this, 'parse_template_callback_languagevar_1'), $template);
  45. $template = preg_replace_callback("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/i", array($this, 'parse_template_callback_blocktags_1'), $template);
  46. $template = preg_replace_callback("/[\n\r\t]*\{blockdata\/(\d+?)\}[\n\r\t]*/i", array($this, 'parse_template_callback_blockdatatags_1'), $template);
  47. $template = preg_replace_callback("/[\n\r\t]*\{ad\/(.+?)\}[\n\r\t]*/i", array($this, 'parse_template_callback_adtags_1'), $template);
  48. $template = preg_replace_callback("/[\n\r\t]*\{ad\s+([a-zA-Z0-9_\[\]]+)\/(.+?)\}[\n\r\t]*/i", array($this, 'parse_template_callback_adtags_21'), $template);
  49. $template = preg_replace_callback("/[\n\r\t]*\{date\((.+?)\)\}[\n\r\t]*/i", array($this, 'parse_template_callback_datetags_1'), $template);
  50. $template = preg_replace_callback("/[\n\r\t]*\{avatar\((.+?)\)\}[\n\r\t]*/i", array($this, 'parse_template_callback_avatartags_1'), $template);
  51. $template = preg_replace_callback("/[\n\r\t]*\{eval\}\s*(\<\!\-\-)*(.+?)(\-\-\>)*\s*\{\/eval\}[\n\r\t]*/is", array($this, 'parse_template_callback_evaltags_2'), $template);
  52. $template = preg_replace_callback("/[\n\r\t]*\{eval\s+(.+?)\s*\}[\n\r\t]*/is", array($this, 'parse_template_callback_evaltags_1'), $template);
  53. $template = preg_replace_callback("/[\n\r\t]*\{csstemplate\}[\n\r\t]*/is", array($this, 'parse_template_callback_loadcsstemplate'), $template);
  54. $template = str_replace("{LF}", "<?=\"\\n\"?>", $template);
  55. $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\-\>\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
  56. $template = preg_replace_callback("/\{hook\/(\w+?)(\s+(.+?))?\}/i", array($this, 'parse_template_callback_hooktags_13'), $template);
  57. $template = preg_replace_callback("/$var_regexp/s", array($this, 'parse_template_callback_addquote_1'), $template);
  58. $template = preg_replace_callback("/\<\?\=\<\?\=$var_regexp\?\>\?\>/s", array($this, 'parse_template_callback_addquote_1'), $template);
  59. $headeradd = $headerexists ? "hookscriptoutput('$basefile');" : '';
  60. if(!empty($this->subtemplates)) {
  61. $headeradd .= "\n0\n";
  62. foreach($this->subtemplates as $fname) {
  63. $headeradd .= "|| checktplrefresh('$tplfile', '$fname', ".time().", '$templateid', '$cachefile', '$tpldir', '$file')\n";
  64. }
  65. $headeradd .= ';';
  66. }
  67. if(!empty($this->blocks)) {
  68. $headeradd .= "\n";
  69. $headeradd .= "block_get('".implode(',', $this->blocks)."');";
  70. }
  71. $template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); {$headeradd}?>\n$template";
  72. $template = preg_replace_callback("/[\n\r\t]*\{template\s+([a-z0-9_:\/]+)\}[\n\r\t]*/is", array($this, 'parse_template_callback_stripvtags_template1'), $template);
  73. $template = preg_replace_callback("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", array($this, 'parse_template_callback_stripvtags_template1'), $template);
  74. $template = preg_replace_callback("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/is", array($this, 'parse_template_callback_stripvtags_echo1'), $template);
  75. $template = preg_replace_callback("/([\n\r\t]*)\{if\s+(.+?)\}([\n\r\t]*)/is", array($this, 'parse_template_callback_stripvtags_if123'), $template);
  76. $template = preg_replace_callback("/([\n\r\t]*)\{elseif\s+(.+?)\}([\n\r\t]*)/is", array($this, 'parse_template_callback_stripvtags_elseif123'), $template);
  77. $template = preg_replace("/\{else\}/i", "<? } else { ?>", $template);
  78. $template = preg_replace("/\{\/if\}/i", "<? } ?>", $template);
  79. $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", array($this, 'parse_template_callback_stripvtags_loop12'), $template);
  80. $template = preg_replace_callback("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*/is", array($this, 'parse_template_callback_stripvtags_loop123'), $template);
  81. $template = preg_replace("/\{\/loop\}/i", "<? } ?>", $template);
  82. $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
  83. if(!empty($this->replacecode)) {
  84. $template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
  85. }
  86. $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
  87. if(!@$fp = fopen(DISCUZ_ROOT.$cachefile, 'w')) {
  88. $this->error('directory_notfound', dirname(DISCUZ_ROOT.$cachefile));
  89. }
  90. $template = preg_replace_callback("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/", array($this, 'parse_template_callback_transamp_0'), $template);
  91. $template = preg_replace_callback("/\<script[^\>]*?src=\"(.+?)\"(.*?)\>\s*\<\/script\>/is", array($this, 'parse_template_callback_stripscriptamp_12'), $template);
  92. $template = preg_replace_callback("/[\n\r\t]*\{block\s+([a-zA-Z0-9_\[\]]+)\}(.+?)\{\/block\}/is", array($this, 'parse_template_callback_stripblock_12'), $template);
  93. $template = preg_replace("/\<\?(\s{1})/is", "<?php\\1", $template);
  94. $template = preg_replace("/\<\?\=(.+?)\?\>/is", "<?php echo \\1;?>", $template);
  95. flock($fp, 2);
  96. fwrite($fp, $template);
  97. fclose($fp);
  98. }
  99. function parse_template_callback_loadsubtemplate_2($matches) {
  100. return $this->loadsubtemplate($matches[2]);
  101. }
  102. function parse_template_callback_languagevar_1($matches) {
  103. return $this->languagevar($matches[1]);
  104. }
  105. function parse_template_callback_blocktags_1($matches) {
  106. return $this->blocktags($matches[1]);
  107. }
  108. function parse_template_callback_blockdatatags_1($matches) {
  109. return $this->blockdatatags($matches[1]);
  110. }
  111. function parse_template_callback_adtags_1($matches) {
  112. return $this->adtags($matches[1]);
  113. }
  114. function parse_template_callback_adtags_21($matches) {
  115. return $this->adtags($matches[2], $matches[1]);
  116. }
  117. function parse_template_callback_datetags_1($matches) {
  118. return $this->datetags($matches[1]);
  119. }
  120. function parse_template_callback_avatartags_1($matches) {
  121. return $this->avatartags($matches[1]);
  122. }
  123. function parse_template_callback_evaltags_2($matches) {
  124. return $this->evaltags($matches[2]);
  125. }
  126. function parse_template_callback_evaltags_1($matches) {
  127. return $this->evaltags($matches[1]);
  128. }
  129. function parse_template_callback_loadcsstemplate($matches) {
  130. return $this->loadcsstemplate();
  131. }
  132. function parse_template_callback_hooktags_13($matches) {
  133. return $this->hooktags($matches[1], $matches[3]);
  134. }
  135. function parse_template_callback_addquote_1($matches) {
  136. return $this->addquote('<?='.$matches[1].'?>');
  137. }
  138. function parse_template_callback_stripvtags_template1($matches) {
  139. return $this->stripvtags('<? include template(\''.$matches[1].'\'); ?>');
  140. }
  141. function parse_template_callback_stripvtags_echo1($matches) {
  142. return $this->stripvtags('<? echo '.$matches[1].'; ?>');
  143. }
  144. function parse_template_callback_stripvtags_if123($matches) {
  145. return $this->stripvtags($matches[1].'<? if('.$matches[2].') { ?>'.$matches[3]);
  146. }
  147. function parse_template_callback_stripvtags_elseif123($matches) {
  148. return $this->stripvtags($matches[1].'<? } elseif('.$matches[2].') { ?>'.$matches[3]);
  149. }
  150. function parse_template_callback_stripvtags_loop12($matches) {
  151. return $this->stripvtags('<? if(is_array('.$matches[1].')) foreach('.$matches[1].' as '.$matches[2].') { ?>');
  152. }
  153. function parse_template_callback_stripvtags_loop123($matches) {
  154. return $this->stripvtags('<? if(is_array('.$matches[1].')) foreach('.$matches[1].' as '.$matches[2].' => '.$matches[3].') { ?>');
  155. }
  156. function parse_template_callback_transamp_0($matches) {
  157. return $this->transamp($matches[0]);
  158. }
  159. function parse_template_callback_stripscriptamp_12($matches) {
  160. return $this->stripscriptamp($matches[1], $matches[2]);
  161. }
  162. function parse_template_callback_stripblock_12($matches) {
  163. return $this->stripblock($matches[1], $matches[2]);
  164. }
  165. function languagevar($var) {
  166. $vars = explode(':', $var);
  167. $isplugin = count($vars) == 2;
  168. if(!$isplugin) {
  169. !isset($this->language['inner']) && $this->language['inner'] = array();
  170. $langvar = &$this->language['inner'];
  171. } else {
  172. !isset($this->language['plugin'][$vars[0]]) && $this->language['plugin'][$vars[0]] = array();
  173. $langvar = &$this->language['plugin'][$vars[0]];
  174. $var = &$vars[1];
  175. }
  176. if(!isset($langvar[$var])) {
  177. $this->language['inner'] = lang('template');
  178. if(!$isplugin) {
  179. if(defined('IN_MOBILE')) {
  180. $mobiletpl = getglobal('mobiletpl');
  181. list($path) = explode('/', str_replace($mobiletpl[IN_MOBILE].'/', '', $this->file));
  182. } else {
  183. list($path) = explode('/', $this->file);
  184. }
  185. foreach(lang($path.'/template') as $k => $v) {
  186. $this->language['inner'][$k] = $v;
  187. }
  188. if(defined('IN_MOBILE')) {
  189. foreach(lang('mobile/template') as $k => $v) {
  190. $this->language['inner'][$k] = $v;
  191. }
  192. }
  193. } else {
  194. global $_G;
  195. if(empty($_G['config']['plugindeveloper'])) {
  196. loadcache('pluginlanguage_template');
  197. } elseif(!isset($_G['cache']['pluginlanguage_template'][$vars[0]]) && preg_match("/^[a-z]+[a-z0-9_]*$/i", $vars[0])) {
  198. if(@include(DISCUZ_ROOT.'./data/plugindata/'.$vars[0].'.lang.php')) {
  199. $_G['cache']['pluginlanguage_template'][$vars[0]] = $templatelang[$vars[0]];
  200. } else {
  201. loadcache('pluginlanguage_template');
  202. }
  203. }
  204. $this->language['plugin'][$vars[0]] = $_G['cache']['pluginlanguage_template'][$vars[0]];
  205. }
  206. }
  207. if(isset($langvar[$var])) {
  208. return $langvar[$var];
  209. } else {
  210. return '!'.$var.'!';
  211. }
  212. }
  213. function blocktags($parameter) {
  214. $bid = intval(trim($parameter));
  215. $this->blocks[] = $bid;
  216. $i = count($this->replacecode['search']);
  217. $this->replacecode['search'][$i] = $search = "<!--BLOCK_TAG_$i-->";
  218. $this->replacecode['replace'][$i] = "<?php block_display('$bid');?>";
  219. return $search;
  220. }
  221. function blockdatatags($parameter) {
  222. $bid = intval(trim($parameter));
  223. $this->blocks[] = $bid;
  224. $i = count($this->replacecode['search']);
  225. $this->replacecode['search'][$i] = $search = "<!--BLOCKDATA_TAG_$i-->";
  226. $this->replacecode['replace'][$i] = "";
  227. return $search;
  228. }
  229. function adtags($parameter, $varname = '') {
  230. $parameter = stripslashes($parameter);
  231. $i = count($this->replacecode['search']);
  232. $this->replacecode['search'][$i] = $search = "<!--AD_TAG_$i-->";
  233. $this->replacecode['replace'][$i] = "<?php ".(!$varname ? 'echo ' : '$'.$varname.'=')."adshow(\"$parameter\");?>";
  234. return $search;
  235. }
  236. function datetags($parameter) {
  237. $parameter = stripslashes($parameter);
  238. $i = count($this->replacecode['search']);
  239. $this->replacecode['search'][$i] = $search = "<!--DATE_TAG_$i-->";
  240. $this->replacecode['replace'][$i] = "<?php echo dgmdate($parameter);?>";
  241. return $search;
  242. }
  243. function avatartags($parameter) {
  244. $parameter = stripslashes($parameter);
  245. $i = count($this->replacecode['search']);
  246. $this->replacecode['search'][$i] = $search = "<!--AVATAR_TAG_$i-->";
  247. $this->replacecode['replace'][$i] = "<?php echo avatar($parameter);?>";
  248. return $search;
  249. }
  250. function evaltags($php) {
  251. $i = count($this->replacecode['search']);
  252. $this->replacecode['search'][$i] = $search = "<!--EVAL_TAG_$i-->";
  253. $this->replacecode['replace'][$i] = "<? $php?>";
  254. return $search;
  255. }
  256. function hooktags($hookid, $key = '') {
  257. global $_G;
  258. $i = count($this->replacecode['search']);
  259. $this->replacecode['search'][$i] = $search = "<!--HOOK_TAG_$i-->";
  260. $dev = '';
  261. if(isset($_G['config']['plugindeveloper']) && $_G['config']['plugindeveloper'] == 2) {
  262. $dev = "echo '<hook>[".($key ? 'array' : 'string')." $hookid".($key ? '/\'.'.$key.'.\'' : '')."]</hook>';";
  263. }
  264. $key = $key != '' ? "[$key]" : '';
  265. $this->replacecode['replace'][$i] = "<?php {$dev}if(!empty(\$_G['setting']['pluginhooks']['$hookid']$key)) echo \$_G['setting']['pluginhooks']['$hookid']$key;?>";
  266. return $search;
  267. }
  268. function stripphpcode($type, $code) {
  269. $this->phpcode[$type][] = $code;
  270. return '{phpcode:'.$type.'/'.(count($this->phpcode[$type]) - 1).'}';
  271. }
  272. function loadsubtemplate($file) {
  273. $tplfile = template($file, 0, '', 1);
  274. $filename = DISCUZ_ROOT.$tplfile;
  275. if(($content = @implode('', file($filename))) || ($content = $this->getphptemplate(@implode('', file(substr($filename, 0, -4).'.php'))))) {
  276. $this->subtemplates[] = $tplfile;
  277. return $content;
  278. } else {
  279. return '<!-- '.$file.' -->';
  280. }
  281. }
  282. function getphptemplate($content) {
  283. $pos = strpos($content, "\n");
  284. return $pos !== false ? substr($content, $pos + 1) : $content;
  285. }
  286. function loadcsstemplate() {
  287. global $_G;
  288. $scripts = array(STYLEID.'_common');
  289. $content = $this->csscurmodules = '';
  290. $content = @implode('', file(DISCUZ_ROOT.'./data/cache/style_'.STYLEID.'_module.css'));
  291. $content = preg_replace_callback("/\[(.+?)\](.*?)\[end\]/is", array($this, 'loadcsstemplate_callback_cssvtags_12'), $content);
  292. if($this->csscurmodules) {
  293. $this->csscurmodules = preg_replace(array('/\s*([,;:\{\}])\s*/', '/[\t\n\r]/', '/\/\*.+?\*\//'), array('\\1', '',''), $this->csscurmodules);
  294. if(@$fp = fopen(DISCUZ_ROOT.'./data/cache/style_'.STYLEID.'_'.$_G['basescript'].'_'.CURMODULE.'.css', 'w')) {
  295. fwrite($fp, $this->csscurmodules);
  296. fclose($fp);
  297. } else {
  298. exit('Can not write to cache files, please check directory ./data/ and ./data/cache/ .');
  299. }
  300. $scripts[] = STYLEID.'_'.$_G['basescript'].'_'.CURMODULE;
  301. }
  302. $scriptcss = '';
  303. foreach($scripts as $css) {
  304. $scriptcss .= '<link rel="stylesheet" type="text/css" href="'.$_G['setting']['csspath'].$css.'.css?{VERHASH}" />';
  305. }
  306. $scriptcss .= '{if $_G[uid] && isset($_G[cookie][extstyle]) && strpos($_G[cookie][extstyle], TPLDIR) !== false}<link rel="stylesheet" id="css_extstyle" type="text/css" href="$_G[cookie][extstyle]/style.css" />{elseif $_G[style][defaultextstyle]}<link rel="stylesheet" id="css_extstyle" type="text/css" href="$_G[style][defaultextstyle]/style.css" />{/if}';
  307. return $scriptcss;
  308. }
  309. function loadcsstemplate_callback_cssvtags_12($matches) {
  310. return $this->cssvtags($matches[1], $matches[2]);
  311. }
  312. function cssvtags($param, $content) {
  313. global $_G;
  314. $modules = explode(',', $param);
  315. foreach($modules as $module) {
  316. $module .= '::'; //fix notice
  317. list($b, $m) = explode('::', $module);
  318. if($b && $b == $_G['basescript'] && (!$m || $m == CURMODULE)) {
  319. $this->csscurmodules .= $content;
  320. return;
  321. }
  322. }
  323. return;
  324. }
  325. function transamp($str) {
  326. $str = str_replace('&', '&amp;', $str);
  327. $str = str_replace('&amp;amp;', '&amp;', $str);
  328. return $str;
  329. }
  330. function addquote($var) {
  331. return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
  332. }
  333. function stripvtags($expr, $statement = '') {
  334. $expr = str_replace('\\\"', '\"', preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
  335. $statement = str_replace('\\\"', '\"', $statement);
  336. return $expr.$statement;
  337. }
  338. function stripscriptamp($s, $extra) {
  339. $s = str_replace('&amp;', '&', $s);
  340. return "<script src=\"$s\" type=\"text/javascript\"$extra></script>";
  341. }
  342. function stripblock($var, $s) {
  343. $s = preg_replace("/<\?=\\\$(.+?)\?>/", "{\$\\1}", $s);
  344. preg_match_all("/<\?=(.+?)\?>/", $s, $constary);
  345. $constadd = '';
  346. $constary[1] = array_unique($constary[1]);
  347. foreach($constary[1] as $const) {
  348. $constadd .= '$__'.$const.' = '.$const.';';
  349. }
  350. $s = preg_replace("/<\?=(.+?)\?>/", "{\$__\\1}", $s);
  351. $s = str_replace('?>', "\n\$$var .= <<<EOF\n", $s);
  352. $s = str_replace('<?', "\nEOF;\n", $s);
  353. $s = str_replace("\nphp ", "\n", $s);
  354. return "<?\n$constadd\$$var = <<<EOF\n".$s."\nEOF;\n?>";
  355. }
  356. function error($message, $tplname) {
  357. discuz_error::template_error($message, $tplname);
  358. }
  359. }
  360. ?>