国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1551 lines
47KB

  1. <?php if(!defined('DEDEINC')) exit("Request Error!");
  2. /**
  3. * 模板引擎文件
  4. *
  5. * @version $Id: dedetemplate.class.php 3 15:44 2010年7月6日Z tianya $
  6. * @package DedeCMS.Libraries
  7. * @copyright Copyright (c) 2007 - 2018, DesDev, Inc.
  8. * @copyright Copyright (c) 2020, DedeBIZ.COM
  9. * @license https://www.dedebiz.com/license/v6
  10. * @link https://www.dedebiz.com
  11. */
  12. /**
  13. * 这个函数用于定义任意名称的块使用的接口
  14. * 返回值应是一个二维数组
  15. * 块调用对应的文件为 include/taglib/plus_blockname.php
  16. * ----------------------------------------------------------------
  17. * 由于标记一般存在默认属性,在编写块函数时,应该在块函数中进行给属性赋省缺值处理,如:
  18. * $attlist = "titlelen=30,catalogid=0,modelid=0,flag=,addon=,row=8,ids=,orderby=id,orderway=desc,limit=,subday=0";
  19. * 给属性赋省缺值
  20. * FillAtts($atts,$attlist);
  21. * 处理属性中使用的系统变量 var、global、field 类型(不支持多维数组)
  22. * FillFields($atts,$fields,$refObj);
  23. *
  24. * @access public
  25. * @param array $atts 属性
  26. * @param object $refObj 所属对象
  27. * @param array $fields 字段
  28. * @return string
  29. */
  30. function MakePublicTag($atts=array(),$refObj='',$fields=array())
  31. {
  32. $atts['tagname'] = preg_replace("/[0-9]{1,}$/", "", $atts['tagname']);
  33. $plusfile = DEDEINC.'/tpllib/plus_'.$atts['tagname'].'.php';
  34. if(!file_exists($plusfile))
  35. {
  36. if(isset($atts['rstype']) && $atts['rstype']=='string')
  37. {
  38. return '';
  39. }
  40. else
  41. {
  42. return array();
  43. }
  44. }
  45. else
  46. {
  47. include_once($plusfile);
  48. $func = 'plus_'.$atts['tagname'];
  49. return $func($atts, $refObj, $fields);
  50. }
  51. }
  52. /**
  53. * 设定属性的默认值
  54. *
  55. * @access public
  56. * @param array $atts 属性
  57. * @param array $attlist 属性列表
  58. * @return void
  59. */
  60. function FillAtts(&$atts, $attlist)
  61. {
  62. $attlists = explode(',', $attlist);
  63. foreach($attlists as $att)
  64. {
  65. list($k, $v)=explode('=', $att);
  66. if(!isset($atts[$k]))
  67. {
  68. $atts[$k] = $v;
  69. }
  70. }
  71. }
  72. /**
  73. * 把上级的fields传递给atts
  74. *
  75. * @access public
  76. * @param array $atts 属性
  77. * @param object $refObj 所属对象
  78. * @param array $fields 字段
  79. * @return string
  80. */
  81. function FillFields(&$atts, &$refObj, &$fields)
  82. {
  83. global $_vars;
  84. foreach($atts as $k=>$v)
  85. {
  86. if(preg_match('/^field\./i',$v))
  87. {
  88. $key = preg_replace('/^field\./i', '', $v);
  89. if( isset($fields[$key]) )
  90. {
  91. $atts[$k] = $fields[$key];
  92. }
  93. }
  94. else if(preg_match('/^var\./i', $v))
  95. {
  96. $key = preg_replace('/^var\./i', '', $v);
  97. if( isset($_vars[$key]) )
  98. {
  99. $atts[$k] = $_vars[$key];
  100. }
  101. }
  102. else if(preg_match('/^global\./i', $v))
  103. {
  104. $key = preg_replace('/^global\./i', '', $v);
  105. if( isset($GLOBALS[$key]) )
  106. {
  107. $atts[$k] = $GLOBALS[$key];
  108. }
  109. }
  110. }
  111. }
  112. /**
  113. * class Tag 标记的数据结构描述
  114. * function C__Tag();
  115. *
  116. * @package Tag
  117. * @subpackage DedeCMS.Libraries
  118. * @link http://www.dedecms.com
  119. */
  120. class Tag
  121. {
  122. var $isCompiler=FALSE; //标记是否已被替代,供解析器使用
  123. var $tagName=""; //标记名称
  124. var $innerText=""; //标记之间的文本
  125. var $startPos=0; //标记起始位置
  126. var $endPos=0; //标记结束位置
  127. var $cAtt=""; //标记属性描述,即是class TagAttribute
  128. var $tagValue=""; //标记的值
  129. var $tagID = 0;
  130. /**
  131. * 获取标记的名称和值
  132. *
  133. * @access public
  134. * @return string
  135. */
  136. function GetName()
  137. {
  138. return strtolower($this->tagName);
  139. }
  140. function GetValue()
  141. {
  142. return $this->tagValue;
  143. }
  144. function IsAtt($str)
  145. {
  146. return $this->cAtt->IsAttribute($str);
  147. }
  148. function GetAtt($str)
  149. {
  150. return $this->cAtt->GetAtt($str);
  151. }
  152. /**
  153. * 获取底层模板
  154. *
  155. * @return string
  156. */
  157. function GetinnerText()
  158. {
  159. return $this->innerText;
  160. }
  161. }
  162. /**
  163. * 模板解析器
  164. * function C__DedeTemplate
  165. *
  166. * @package DedeTemplate
  167. * @subpackage DedeCMS.Libraries
  168. * @link http://www.dedecms.com
  169. */
  170. class DedeTemplate
  171. {
  172. var $tagMaxLen = 64;
  173. var $charToLow = TRUE;
  174. var $isCache = TRUE;
  175. var $isParse = FALSE;
  176. var $isCompiler = TRUE;
  177. var $templateDir = '';
  178. var $tempMkTime = 0;
  179. var $cacheFile = '';
  180. var $configFile = '';
  181. var $buildFile = '';
  182. var $refDir = '';
  183. var $cacheDir = '';
  184. var $templateFile = '';
  185. var $sourceString = '';
  186. var $cTags = array();
  187. //var $definedVars = array();
  188. var $count = -1;
  189. var $loopNum = 0;
  190. var $refObj = '';
  191. var $makeLoop = 0;
  192. var $tagStartWord = '{dede:';
  193. var $fullTagEndWord = '{/dede:';
  194. var $sTagEndWord = '/}';
  195. var $tagEndWord = '}';
  196. var $tpCfgs = array();
  197. /**
  198. * 析构函数
  199. *
  200. * @access public
  201. * @param string $templatedir 模板目录
  202. * @param string $refDir 所属目录
  203. * @return void
  204. */
  205. function __construct($templatedir='',$refDir='')
  206. {
  207. //$definedVars[] = 'var';
  208. //缓存目录
  209. if($templatedir=='')
  210. {
  211. $this->templateDir = DEDEROOT.'/templates';
  212. }
  213. else
  214. {
  215. $this->templateDir = $templatedir;
  216. }
  217. //模板include目录
  218. if($refDir=='')
  219. {
  220. if(isset($GLOBALS['cfg_df_style']))
  221. {
  222. $this->refDir = $this->templateDir.'/'.$GLOBALS['cfg_df_style'].'/';
  223. }
  224. else
  225. {
  226. $this->refDir = $this->templateDir;
  227. }
  228. }
  229. $this->cacheDir = DEDEROOT.$GLOBALS['cfg_tplcache_dir'];
  230. }
  231. //构造函数,兼容PHP4
  232. function DedeTemplate($templatedir='',$refDir='')
  233. {
  234. $this->__construct($templatedir,$refDir);
  235. }
  236. /**
  237. * 设定本类自身实例的类引用和使用本类的类实例(如果在类中使用本模板引擎,后一参数一般为$this)
  238. *
  239. * @access public
  240. * @param object $refObj 实例对象
  241. * @return string
  242. */
  243. function SetObject(&$refObj)
  244. {
  245. $this->refObj = $refObj;
  246. }
  247. /**
  248. * 设定Var的键值对
  249. *
  250. * @access public
  251. * @param string $k 键
  252. * @param string $v 值
  253. * @return string
  254. */
  255. function SetVar($k, $v)
  256. {
  257. $GLOBALS['_vars'][$k] = $v;
  258. }
  259. /**
  260. * 设定Var的键值对
  261. *
  262. * @access public
  263. * @param string $k 键
  264. * @param string $v 值
  265. * @return string
  266. */
  267. function Assign($k, $v)
  268. {
  269. $GLOBALS['_vars'][$k] = $v;
  270. }
  271. /**
  272. * 设定数组
  273. *
  274. * @access public
  275. * @param string $k 键
  276. * @param string $v 值
  277. * @return string
  278. */
  279. function SetArray($k, $v)
  280. {
  281. $GLOBALS[$k] = $v;
  282. }
  283. /**
  284. * 设置标记风格
  285. *
  286. * @access public
  287. * @param string $ts 标签开始标记
  288. * @param string $ftend 标签结束标记
  289. * @param string $stend 标签尾部结束标记
  290. * @param string $tend 结束标记
  291. * @return void
  292. */
  293. function SetTagStyle($ts='{dede:',$ftend='{/dede:',$stend='/}',$tend='}')
  294. {
  295. $this->tagStartWord = $ts;
  296. $this->fullTagEndWord = $ftend;
  297. $this->sTagEndWord = $stend;
  298. $this->tagEndWord = $tend;
  299. }
  300. /**
  301. * 获得模板设定的config值
  302. *
  303. * @access public
  304. * @param string $k 键名
  305. * @return string
  306. */
  307. function GetConfig($k)
  308. {
  309. return (isset($this->tpCfgs[$k]) ? $this->tpCfgs[$k] : '');
  310. }
  311. /**
  312. * 设定模板文件
  313. *
  314. * @access public
  315. * @param string $tmpfile 模板文件
  316. * @return void
  317. */
  318. function LoadTemplate($tmpfile)
  319. {
  320. if(!file_exists($tmpfile))
  321. {
  322. echo " Template Not Found! ";
  323. exit();
  324. }
  325. $tmpfile = preg_replace("/[\\/]{1,}/", "/", $tmpfile);
  326. $tmpfiles = explode('/',$tmpfile);
  327. $tmpfileOnlyName = preg_replace("/(.*)\//", "", $tmpfile);
  328. $this->templateFile = $tmpfile;
  329. $this->refDir = '';
  330. for($i=0; $i < count($tmpfiles)-1; $i++)
  331. {
  332. $this->refDir .= $tmpfiles[$i].'/';
  333. }
  334. if(!is_dir($this->cacheDir))
  335. {
  336. $this->cacheDir = $this->refDir;
  337. }
  338. if($this->cacheDir!='')
  339. {
  340. $this->cacheDir = $this->cacheDir.'/';
  341. }
  342. if(isset($GLOBALS['_DEBUG_CACHE']))
  343. {
  344. $this->cacheDir = $this->refDir;
  345. }
  346. $this->cacheFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'.inc', $tmpfileOnlyName);
  347. $this->configFile = $this->cacheDir.preg_replace("/\.(wml|html|htm|php)$/", "_".$this->GetEncodeStr($tmpfile).'_config.inc', $tmpfileOnlyName);
  348. //不开启缓存、当缓存文件不存在、及模板为更新的文件的时候才载入模板并进行解析
  349. if($this->isCache==FALSE || !file_exists($this->cacheFile)
  350. || filemtime($this->templateFile) > filemtime($this->cacheFile))
  351. {
  352. $t1 = ExecTime(); //debug
  353. $fp = fopen($this->templateFile,'r');
  354. $this->sourceString = fread($fp,filesize($this->templateFile));
  355. fclose($fp);
  356. $this->ParseTemplate();
  357. //模板解析时间
  358. //echo ExecTime() - $t1;
  359. }
  360. else
  361. {
  362. //如果存在config文件,则载入此文件,该文件用于保存 $this->tpCfgs的内容,以供扩展用途
  363. //模板中用{tag:config name='' value=''/}来设定该值
  364. if(file_exists($this->configFile))
  365. {
  366. include($this->configFile);
  367. }
  368. }
  369. }
  370. /**
  371. * 载入模板字符串
  372. *
  373. * @access public
  374. * @param string $str 模板字符串
  375. * @return void
  376. */
  377. function LoadString($str='')
  378. {
  379. $this->sourceString = $str;
  380. $hashcode = md5($this->sourceString);
  381. $this->cacheFile = $this->cacheDir."/string_".$hashcode.".inc";
  382. $this->configFile = $this->cacheDir."/string_".$hashcode."_config.inc";
  383. $this->ParseTemplate();
  384. }
  385. /**
  386. * 调用此函数include一个编译后的PHP文件,通常是在最后一个步骤才调用本文件
  387. *
  388. * @access public
  389. * @return string
  390. */
  391. function CacheFile()
  392. {
  393. global $gtmpfile;
  394. $this->WriteCache();
  395. return $this->cacheFile;
  396. }
  397. /**
  398. * 显示内容,由于函数中会重新解压一次$GLOBALS变量,所以在动态页中,应该尽量少用本方法,
  399. * 取代之是直接在程序中 include $tpl->CacheFile(),不过include $tpl->CacheFile()这种方式不能在类或函数内使用
  400. *
  401. * @access public
  402. * @param string
  403. * @return void
  404. */
  405. function Display()
  406. {
  407. global $gtmpfile;
  408. extract($GLOBALS, EXTR_SKIP);
  409. $this->WriteCache();
  410. include $this->cacheFile;
  411. }
  412. /**
  413. * 保存运行后的程序为文件
  414. *
  415. * @access public
  416. * @param string $savefile 保存到的文件目录
  417. * @return void
  418. */
  419. function SaveTo($savefile)
  420. {
  421. extract($GLOBALS, EXTR_SKIP);
  422. $this->WriteCache();
  423. ob_start();
  424. include $this->cacheFile;
  425. $okstr = ob_get_contents();
  426. ob_end_clean();
  427. $fp = @fopen($savefile,"w") or die(" Tag Engine Create File FALSE! ");
  428. fwrite($fp,$okstr);
  429. fclose($fp);
  430. }
  431. // ------------------------------------------------------------------------
  432. /**
  433. * CheckDisabledFunctions
  434. *
  435. * COMMENT : CheckDisabledFunctions : 检查是否存在禁止的函数
  436. *
  437. * @access public
  438. * @param string
  439. * @return bool
  440. */
  441. function CheckDisabledFunctions($str,&$errmsg='')
  442. {
  443. global $cfg_disable_funs;
  444. $cfg_disable_funs = isset($cfg_disable_funs)? $cfg_disable_funs : 'phpinfo,eval,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite';
  445. // 模板引擎增加disable_functions
  446. if (!defined('DEDEDISFUN')) {
  447. $tokens = token_get_all_nl($str);
  448. $disabled_functions = explode(',', $cfg_disable_funs);
  449. foreach ($tokens as $token)
  450. {
  451. if (is_array($token))
  452. {
  453. if ($token[0] = '306' && in_array($token[1], $disabled_functions))
  454. {
  455. $errmsg = 'DedeCMS Error:function disabled "'.$token[1].'" <a href="http://help.dedecms.com/install-use/apply/2013/0711/2324.html" target="_blank">more...</a>';
  456. return FALSE;
  457. }
  458. }
  459. }
  460. }
  461. return TRUE;
  462. }
  463. /**
  464. * 解析模板并写缓存文件
  465. *
  466. * @access public
  467. * @param string $ctype 缓存类型
  468. * @return void
  469. */
  470. function WriteCache($ctype='all')
  471. {
  472. if(!file_exists($this->cacheFile) || $this->isCache==FALSE
  473. || ( file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)) ) )
  474. {
  475. if(!$this->isParse)
  476. {
  477. $this->ParseTemplate();
  478. }
  479. $fp = fopen($this->cacheFile,'w') or dir("Write Cache File Error! ");
  480. flock($fp,3);
  481. $result = trim($this->GetResult());
  482. $errmsg = '';
  483. //var_dump($result);exit();
  484. if (!$this->CheckDisabledFunctions($result, $errmsg))
  485. {
  486. fclose($fp);
  487. @unlink($this->cacheFile);
  488. die($errmsg);
  489. }
  490. fwrite($fp,$result);
  491. fclose($fp);
  492. if(count($this->tpCfgs) > 0)
  493. {
  494. $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
  495. flock($fp,3);
  496. fwrite($fp,'<'.'?php'."\r\n");
  497. foreach($this->tpCfgs as $k=>$v)
  498. {
  499. $v = str_replace("\"","\\\"",$v);
  500. $v = str_replace("\$","\\\$",$v);
  501. fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
  502. }
  503. fwrite($fp,'?'.'>');
  504. fclose($fp);
  505. }
  506. }
  507. /*
  508. if(!file_exists($this->cacheFile) || $this->isCache==FALSE
  509. || ( file_exists($this->templateFile) && (filemtime($this->templateFile) > filemtime($this->cacheFile)) ) )
  510. {
  511. if($ctype!='config')
  512. {
  513. if(!$this->isParse)
  514. {
  515. $this->ParseTemplate();
  516. }
  517. $fp = fopen($this->cacheFile,'w') or dir("Write Cache File Error! ");
  518. flock($fp,3);
  519. fwrite($fp,trim($this->GetResult()));
  520. fclose($fp);
  521. }
  522. else
  523. {
  524. if(count($this->tpCfgs) > 0)
  525. {
  526. $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
  527. flock($fp,3);
  528. fwrite($fp,'<'.'?php'."\r\n");
  529. foreach($this->tpCfgs as $k=>$v)
  530. {
  531. $v = str_replace("\"","\\\"",$v);
  532. $v = str_replace("\$","\\\$",$v);
  533. fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
  534. }
  535. fwrite($fp,'?'.'>');
  536. fclose($fp);
  537. }
  538. }
  539. }
  540. else
  541. {
  542. if($ctype=='config' && count($this->tpCfgs) > 0 )
  543. {
  544. $fp = fopen($this->configFile,'w') or dir("Write Config File Error! ");
  545. flock($fp,3);
  546. fwrite($fp,'<'.'?php'."\r\n");
  547. foreach($this->tpCfgs as $k=>$v)
  548. {
  549. $v = str_replace("\"","\\\"",$v);
  550. $v = str_replace("\$","\\\$",$v);
  551. fwrite($fp,"\$this->tpCfgs['$k']=\"$v\";\r\n");
  552. }
  553. fwrite($fp,'?'.'>');
  554. fclose($fp);
  555. }
  556. }
  557. */
  558. }
  559. /**
  560. * 获得模板文件名的md5字符串
  561. *
  562. * @access public
  563. * @param string $tmpfile 模板文件
  564. * @return string
  565. */
  566. function GetEncodeStr($tmpfile)
  567. {
  568. //$tmpfiles = explode('/',$tmpfile);
  569. $encodeStr = substr(md5($tmpfile),0,24);
  570. return $encodeStr;
  571. }
  572. /**
  573. * 解析模板
  574. *
  575. * @access public
  576. * @return void
  577. */
  578. function ParseTemplate()
  579. {
  580. if($this->makeLoop > 5)
  581. {
  582. return ;
  583. }
  584. $this->count = -1;
  585. $this->cTags = array();
  586. $this->isParse = TRUE;
  587. $sPos = 0;
  588. $ePos = 0;
  589. $tagStartWord = $this->tagStartWord;
  590. $fullTagEndWord = $this->fullTagEndWord;
  591. $sTagEndWord = $this->sTagEndWord;
  592. $tagEndWord = $this->tagEndWord;
  593. $startWordLen = strlen($tagStartWord);
  594. $sourceLen = strlen($this->sourceString);
  595. if( $sourceLen <= ($startWordLen + 3) )
  596. {
  597. return;
  598. }
  599. $cAtt = new TagAttributeParse();
  600. $cAtt->CharToLow = TRUE;
  601. //遍历模板字符串,请取标记及其属性信息
  602. $t = 0;
  603. $preTag = '';
  604. $tswLen = strlen($tagStartWord);
  605. @$cAtt->cAttributes->items = array();
  606. for($i=0; $i<$sourceLen; $i++)
  607. {
  608. $ttagName = '';
  609. //如果不进行此判断,将无法识别相连的两个标记
  610. if($i-1>=0)
  611. {
  612. $ss = $i-1;
  613. }
  614. else
  615. {
  616. $ss = 0;
  617. }
  618. $tagPos = strpos($this->sourceString,$tagStartWord,$ss);
  619. //判断后面是否还有模板标记
  620. if($tagPos==0 && ($sourceLen-$i < $tswLen
  621. || substr($this->sourceString,$i,$tswLen)!=$tagStartWord ))
  622. {
  623. $tagPos = -1;
  624. break;
  625. }
  626. //获取TAG基本信息
  627. for($j = $tagPos+$startWordLen; $j < $tagPos+$startWordLen+$this->tagMaxLen; $j++)
  628. {
  629. if(preg_match("/[ >\/\r\n\t\}\.]/", $this->sourceString[$j]))
  630. {
  631. break;
  632. }
  633. else
  634. {
  635. $ttagName .= $this->sourceString[$j];
  636. }
  637. }
  638. if($ttagName!='')
  639. {
  640. $i = $tagPos + $startWordLen;
  641. $endPos = -1;
  642. //判断 '/}' '{tag:下一标记开始' '{/tag:标记结束' 谁最靠近
  643. $fullTagEndWordThis = $fullTagEndWord.$ttagName.$tagEndWord;
  644. $e1 = strpos($this->sourceString, $sTagEndWord, $i);
  645. $e2 = strpos($this->sourceString, $tagStartWord, $i);
  646. $e3 = strpos($this->sourceString, $fullTagEndWordThis, $i);
  647. $e1 = trim($e1); $e2 = trim($e2); $e3 = trim($e3);
  648. $e1 = ($e1=='' ? '-1' : $e1);
  649. $e2 = ($e2=='' ? '-1' : $e2);
  650. $e3 = ($e3=='' ? '-1' : $e3);
  651. if($e3==-1)
  652. {
  653. //不存在'{/tag:标记'
  654. $endPos = $e1;
  655. $elen = $endPos + strlen($sTagEndWord);
  656. }
  657. else if($e1==-1)
  658. {
  659. //不存在 '/}'
  660. $endPos = $e3;
  661. $elen = $endPos + strlen($fullTagEndWordThis);
  662. }
  663. //同时存在 '/}' 和 '{/tag:标记'
  664. else
  665. {
  666. //如果 '/}' 比 '{tag:'、'{/tag:标记' 都要靠近,则认为结束标志是 '/}',否则结束标志为 '{/tag:标记'
  667. if($e1 < $e2 && $e1 < $e3 )
  668. {
  669. $endPos = $e1;
  670. $elen = $endPos + strlen($sTagEndWord);
  671. }
  672. else
  673. {
  674. $endPos = $e3;
  675. $elen = $endPos + strlen($fullTagEndWordThis);
  676. }
  677. }
  678. //如果找不到结束标记,则认为这个标记存在错误
  679. if($endPos==-1)
  680. {
  681. echo "Tpl Character postion $tagPos, '$ttagName' Error!<br />\r\n";
  682. break;
  683. }
  684. $i = $elen;
  685. //分析所找到的标记位置等信息
  686. $attStr = '';
  687. $innerText = '';
  688. $startInner = 0;
  689. for($j = $tagPos+$startWordLen; $j < $endPos; $j++)
  690. {
  691. if($startInner==0)
  692. {
  693. if($this->sourceString[$j]==$tagEndWord)
  694. {
  695. $startInner=1; continue;
  696. }
  697. else
  698. {
  699. $attStr .= $this->sourceString[$j];
  700. }
  701. }
  702. else
  703. {
  704. $innerText .= $this->sourceString[$j];
  705. }
  706. }
  707. $ttagName = strtolower($ttagName);
  708. //if、php标记,把整个属性串视为属性
  709. if(preg_match("/^if[0-9]{0,}$/", $ttagName))
  710. {
  711. $cAtt->cAttributes = new TagAttribute();
  712. $cAtt->cAttributes->count = 2;
  713. $cAtt->cAttributes->items['tagname'] = $ttagName;
  714. $cAtt->cAttributes->items['condition'] = preg_replace("/^if[0-9]{0,}[\r\n\t ]/", "", $attStr);
  715. $innerText = preg_replace("/\{else\}/i", '<'."?php\r\n}\r\nelse{\r\n".'?'.'>', $innerText);
  716. }
  717. else if($ttagName=='php')
  718. {
  719. $cAtt->cAttributes = new TagAttribute();
  720. $cAtt->cAttributes->count = 2;
  721. $cAtt->cAttributes->items['tagname'] = $ttagName;
  722. $cAtt->cAttributes->items['code'] = '<'."?php\r\n".trim(preg_replace("/^php[0-9]{0,}[\r\n\t ]/",
  723. "",$attStr))."\r\n?".'>';
  724. }
  725. else
  726. {
  727. //普通标记,解释属性
  728. $cAtt->SetSource($attStr);
  729. }
  730. $this->count++;
  731. $cTag = new Tag();
  732. $cTag->tagName = $ttagName;
  733. $cTag->startPos = $tagPos;
  734. $cTag->endPos = $i;
  735. $cTag->cAtt = $cAtt->cAttributes;
  736. $cTag->isCompiler = FALSE;
  737. $cTag->tagID = $this->count;
  738. $cTag->innerText = $innerText;
  739. $this->cTags[$this->count] = $cTag;
  740. }
  741. else
  742. {
  743. $i = $tagPos+$startWordLen;
  744. break;
  745. }
  746. }//结束遍历模板字符串
  747. if( $this->count > -1 && $this->isCompiler )
  748. {
  749. $this->CompilerAll();
  750. }
  751. }
  752. /**
  753. * 把模板标记转换为PHP代码
  754. *
  755. * @access public
  756. * @return void
  757. */
  758. function CompilerAll()
  759. {
  760. $this->loopNum++;
  761. if($this->loopNum > 10)
  762. {
  763. return; //限制最大递归深度为 10 以防止因标记出错等可能性导致死循环
  764. }
  765. $ResultString = '';
  766. $nextTagEnd = 0;
  767. for($i=0; isset($this->cTags[$i]); $i++)
  768. {
  769. $ResultString .= substr($this->sourceString, $nextTagEnd, $this->cTags[$i]->startPos - $nextTagEnd);
  770. $ResultString .= $this->CompilerOneTag($this->cTags[$i]);
  771. $nextTagEnd = $this->cTags[$i]->endPos;
  772. }
  773. $slen = strlen($this->sourceString);
  774. if($slen > $nextTagEnd)
  775. {
  776. $ResultString .= substr($this->sourceString,$nextTagEnd,$slen-$nextTagEnd);
  777. }
  778. $this->sourceString = $ResultString;
  779. $this->ParseTemplate();
  780. }
  781. /**
  782. * 获得最终结果
  783. *
  784. * @access public
  785. * @return string
  786. */
  787. function GetResult()
  788. {
  789. if(!$this->isParse)
  790. {
  791. $this->ParseTemplate();
  792. }
  793. $addset = '';
  794. $addset .= '<'.'?php'."\r\n".'if(!isset($GLOBALS[\'_vars\'])) $GLOBALS[\'_vars\'] = array(); '."\r\n".'$fields = array();'."\r\n".'?'.'>';
  795. return preg_replace("/\?".">[ \r\n\t]{0,}<"."\?php/", "", $addset.$this->sourceString);
  796. }
  797. /**
  798. * 编译单个标记
  799. *
  800. * @access public
  801. * @param string $cTag 标签
  802. * @return string
  803. */
  804. function CompilerOneTag(&$cTag)
  805. {
  806. $cTag->isCompiler = TRUE;
  807. $tagname = $cTag->tagName;
  808. $varname = $cTag->GetAtt('name');
  809. $rsvalue = "";
  810. //用于在模板中设置一个变量以提供作扩展用途
  811. //此变量直接提交到 this->tpCfgs 中,并会生成与模板对应的缓存文件 ***_config.php 文件
  812. if( $tagname == 'config' )
  813. {
  814. $this->tpCfgs[$varname] = $cTag->GetAtt('value');
  815. }
  816. else if( $tagname == 'global' )
  817. {
  818. $cTag->tagValue = $this->CompilerArrayVar('global',$varname);
  819. if( $cTag->GetAtt('function') != '' )
  820. {
  821. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  822. }
  823. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  824. }
  825. else if( $tagname == 'cfg' )
  826. {
  827. $cTag->tagValue = '$GLOBALS[\'cfg_'.$varname.'\']'; //处理函数
  828. if( $cTag->GetAtt('function')!='' )
  829. {
  830. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  831. }
  832. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  833. }
  834. else if( $tagname == 'name' )
  835. {
  836. $cTag->tagValue = '$'.$varname; //处理函数
  837. if( $cTag->GetAtt('function')!='' )
  838. {
  839. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  840. }
  841. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  842. }
  843. else if( $tagname == 'object' )
  844. {
  845. list($_obs,$_em) = explode('->',$varname);
  846. $cTag->tagValue = "\$GLOBALS['{$_obs}']->{$_em}"; //处理函数
  847. if( $cTag->GetAtt('function')!='' )
  848. {
  849. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  850. }
  851. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  852. }
  853. else if($tagname == 'var')
  854. {
  855. $cTag->tagValue = $this->CompilerArrayVar('var', $varname);
  856. if( $cTag->GetAtt('function')!='' )
  857. {
  858. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  859. }
  860. // 增加默认空值处理
  861. if ($cTag->GetAtt('default')!='')
  862. {
  863. $cTag->tagValue = '<'.'?php echo empty('.$cTag->tagValue.')? \''.addslashes($cTag->GetAtt('default')).'\':'.$cTag->tagValue.'; ?'.'>';
  864. } else {
  865. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  866. }
  867. }
  868. else if($tagname == 'field')
  869. {
  870. $cTag->tagValue = '$fields[\''.$varname.'\']';
  871. if( $cTag->GetAtt('function')!='' )
  872. {
  873. $cTag->tagValue = $this->CompilerFunction($cTag->GetAtt('function'), $cTag->tagValue);
  874. }
  875. $cTag->tagValue = '<'.'?php echo '.$cTag->tagValue.'; ?'.'>';
  876. }
  877. else if( preg_match("/^key[0-9]{0,}/", $tagname) || preg_match("/^value[0-9]{0,}/", $tagname))
  878. {
  879. if( preg_match("/^value[0-9]{0,}/", $tagname) && $varname!='' )
  880. {
  881. $cTag->tagValue = '<'.'?php echo '.$this->CompilerArrayVar($tagname,$varname).'; ?'.'>';
  882. }
  883. else
  884. {
  885. $cTag->tagValue = '<'.'?php echo $'.$tagname.'; ?'.'>';
  886. }
  887. }
  888. else if( preg_match("/^if[0-9]{0,}$/", $tagname) )
  889. {
  890. $cTag->tagValue = $this->CompilerIf($cTag);
  891. }
  892. else if( $tagname=='echo' )
  893. {
  894. if(trim($cTag->GetInnerText())=='') $cTag->tagValue = $cTag->GetAtt('code');
  895. else
  896. {
  897. $cTag->tagValue = '<'."?php echo $".trim($cTag->GetInnerText())." ;?".'>';
  898. }
  899. }
  900. else if( $tagname=='php' )
  901. {
  902. if(trim($cTag->GetInnerText())=='') $cTag->tagValue = $cTag->GetAtt('code');
  903. else
  904. {
  905. $cTag->tagValue = '<'."?php\r\n".trim($cTag->GetInnerText())."\r\n?".'>';
  906. }
  907. }
  908. //遍历数组
  909. else if( preg_match("/^array[0-9]{0,}/",$tagname) )
  910. {
  911. $kk = '$key';
  912. $vv = '$value';
  913. if($cTag->GetAtt('key')!='')
  914. {
  915. $kk = '$key'.$cTag->GetAtt('key');
  916. }
  917. if($cTag->GetAtt('value')!='')
  918. {
  919. $vv = '$value'.$cTag->GetAtt('value');
  920. }
  921. $addvar = '';
  922. if(!preg_match("/\(/",$varname))
  923. {
  924. $varname = '$GLOBALS[\''.$varname.'\']';
  925. }
  926. else
  927. {
  928. $addvar = "\r\n".'$myarrs = $pageClass->'.$varname.";\r\n";
  929. $varname = ' $myarrs ';
  930. }
  931. $rsvalue = '<'.'?php '.$addvar.' foreach('.$varname.' as '.$kk.'=>'.$vv.'){ ?'.">";
  932. $rsvalue .= $cTag->GetInnerText();
  933. $rsvalue .= '<'.'?php } ?'.">\r\n";
  934. $cTag->tagValue = $rsvalue;
  935. }
  936. //include 文件
  937. else if($tagname == 'include')
  938. {
  939. $filename = $cTag->GetAtt('file');
  940. if($filename=='')
  941. {
  942. $filename = $cTag->GetAtt('filename');
  943. }
  944. $cTag->tagValue = $this->CompilerInclude($filename, FALSE);
  945. if($cTag->tagValue==0) $cTag->tagValue = '';
  946. $cTag->tagValue = '<'.'?php include $this->CompilerInclude("'.$filename.'");'."\r\n".' ?'.'>';
  947. }
  948. else if( $tagname=='label' )
  949. {
  950. $bindFunc = $cTag->GetAtt('bind');
  951. $rsvalue = 'echo '.$bindFunc.";\r\n";
  952. $rsvalue = '<'.'?php '.$rsvalue.' ?'.">\r\n";
  953. $cTag->tagValue = $rsvalue;
  954. }
  955. else if( $tagname=='datalist' )
  956. {
  957. //生成属性数组
  958. foreach($cTag->cAtt->items as $k=>$v)
  959. {
  960. $v = $this->TrimAtts($v);
  961. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
  962. }
  963. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  964. $rsvalue .= '$blockValue = $this->refObj->GetArcList($atts,$this->refObj,$fields); '."\r\n";
  965. $rsvalue .= 'if(is_array($blockValue)){'."\r\n";
  966. $rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
  967. $rsvalue .= $cTag->GetInnerText();
  968. $rsvalue .= '<'.'?php'."\r\n}\r\n}".'?'.'>';
  969. $cTag->tagValue = $rsvalue;
  970. }
  971. else if( $tagname=='pagelist' )
  972. {
  973. //生成属性数组
  974. foreach($cTag->cAtt->items as $k=>$v)
  975. {
  976. $v = $this->TrimAtts($v);
  977. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
  978. }
  979. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  980. $rsvalue .= ' echo $this->refObj->GetPageList($atts,$this->refObj,$fields); '."\r\n".'?'.">\r\n";
  981. $cTag->tagValue = $rsvalue;
  982. }
  983. else
  984. {
  985. $bindFunc = $cTag->GetAtt('bind');
  986. $bindType = $cTag->GetAtt('bindtype');
  987. $rstype = ($cTag->GetAtt('resulttype')=='' ? $cTag->GetAtt('rstype') : $cTag->GetAtt('resulttype') );
  988. $rstype = strtolower($rstype);
  989. //生成属性数组
  990. foreach($cTag->cAtt->items as $k=>$v)
  991. {
  992. if(preg_match("/(bind|bindtype)/i",$k))
  993. {
  994. continue;
  995. }
  996. $v = $this->TrimAtts($v);
  997. $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n";
  998. }
  999. $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue;
  1000. //绑定到默认函数还是指定函数(datasource属性指定)
  1001. if($bindFunc=='')
  1002. {
  1003. $rsvalue .= '$blockValue = MakePublicTag($atts,$this->refObj,$fields); '."\r\n";
  1004. }
  1005. else
  1006. {
  1007. //自定义绑定函数如果不指定 bindtype,则指向$this->refObj->绑定函数名,即是默认指向被引用的类对象
  1008. if($bindType=='') $rsvalue .= '$blockValue = $this->refObj->'.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
  1009. else $rsvalue .= '$blockValue = '.$bindFunc.'($atts,$this->refObj,$fields); '."\r\n";
  1010. }
  1011. //返回结果类型:默认为 array 是一个二维数组,string 是字符串
  1012. if($rstype=='string')
  1013. {
  1014. $rsvalue .= 'echo $blockValue;'."\r\n".'?'.">";
  1015. }
  1016. else
  1017. {
  1018. $rsvalue .= 'if(is_array($blockValue) && count($blockValue) > 0){'."\r\n";
  1019. $rsvalue .= 'foreach( $blockValue as $key=>$fields )'."\r\n{\r\n".'?'.">";
  1020. $rsvalue .= $cTag->GetInnerText();
  1021. $rsvalue .= '<'.'?php'."\r\n}\r\n}\r\n".'?'.'>';
  1022. }
  1023. $cTag->tagValue = $rsvalue;
  1024. }
  1025. return $cTag->tagValue;
  1026. }
  1027. /**
  1028. * 编译可能为数组的变量
  1029. *
  1030. * @access public
  1031. * @param string $vartype 变量类型
  1032. * @param string $varname 变量名称
  1033. * @return string
  1034. */
  1035. function CompilerArrayVar($vartype, $varname)
  1036. {
  1037. $okvalue = '';
  1038. if(!preg_match("/\[/", $varname))
  1039. {
  1040. if(preg_match("/^value/",$vartype))
  1041. {
  1042. $varname = $vartype.'.'.$varname;
  1043. }
  1044. $varnames = explode('.',$varname);
  1045. if(isset($varnames[1]))
  1046. {
  1047. $varname = $varnames[0];
  1048. for($i=1; isset($varnames[$i]); $i++)
  1049. {
  1050. $varname .= "['".$varnames[$i]."']";
  1051. }
  1052. }
  1053. }
  1054. if(preg_match("/\[/", $varname))
  1055. {
  1056. $varnames = explode('[', $varname);
  1057. $arrend = '';
  1058. for($i=1;isset($varnames[$i]);$i++)
  1059. {
  1060. $arrend .= '['.$varnames[$i];
  1061. }
  1062. if(!preg_match("/[\"']/", $arrend)) {
  1063. $arrend = str_replace('[', '', $arrend);
  1064. $arrend = str_replace(']', '', $arrend);
  1065. $arrend = "['{$arrend}']";
  1066. }
  1067. if($vartype=='var')
  1068. {
  1069. $okvalue = '$GLOBALS[\'_vars\'][\''.$varnames[0].'\']'.$arrend;
  1070. }
  1071. else if( preg_match("/^value/", $vartype) )
  1072. {
  1073. $okvalue = '$'.$varnames[0].$arrend;
  1074. }
  1075. else if($vartype=='field')
  1076. {
  1077. $okvalue = '$fields[\''.$varnames[0].'\']'.$arrend;
  1078. }
  1079. else
  1080. {
  1081. $okvalue = '$GLOBALS[\''.$varnames[0].'\']'.$arrend;
  1082. }
  1083. }
  1084. else
  1085. {
  1086. if($vartype=='var')
  1087. {
  1088. $okvalue = '$GLOBALS[\'_vars\'][\''.$varname.'\']';
  1089. }
  1090. else if( preg_match("/^value/",$vartype) )
  1091. {
  1092. $okvalue = '$'.$vartype;
  1093. }
  1094. else if($vartype=='field')
  1095. {
  1096. $okvalue = '$'.str_replace($varname);
  1097. }
  1098. else
  1099. {
  1100. $okvalue = '$GLOBALS[\''.$varname.'\']';
  1101. }
  1102. }
  1103. return $okvalue;
  1104. }
  1105. /**
  1106. * 编译if标记
  1107. *
  1108. * @access public
  1109. * @param string $cTag 标签
  1110. * @return string
  1111. */
  1112. function CompilerIf($cTag)
  1113. {
  1114. $condition = trim($cTag->GetAtt('condition'));
  1115. if($condition =='')
  1116. {
  1117. $cTag->tagValue=''; return '';
  1118. }
  1119. if (version_compare(PHP_VERSION, '5.5.0', '>='))
  1120. {
  1121. $condition = preg_replace_callback("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/is", "private_rt", $condition);
  1122. } else {
  1123. $condition = preg_replace("/((var\.|field\.|cfg\.|global\.|key[0-9]{0,}\.|value[0-9]{0,}\.)[\._a-z0-9]+)/ies", "private_rt('\\1')", $condition);
  1124. } $rsvalue = '<'.'?php if('.$condition.'){ ?'.'>';
  1125. $rsvalue .= $cTag->GetInnerText();
  1126. $rsvalue .= '<'.'?php } ?'.'>';
  1127. return $rsvalue;
  1128. }
  1129. /**
  1130. * 处理block区块传递的atts属性的值
  1131. *
  1132. * @access public
  1133. * @param string $v 值
  1134. * @return string
  1135. */
  1136. function TrimAtts($v)
  1137. {
  1138. $v = str_replace('<'.'?','&lt;?',$v);
  1139. $v = str_replace('?'.'>','?&gt;',$v);
  1140. return $v;
  1141. }
  1142. /**
  1143. * 函数 function 语法处理
  1144. *
  1145. * @access public
  1146. * @param string $funcstr 函数字符串
  1147. * @param string $nvalue 函数值
  1148. * @return string
  1149. */
  1150. function CompilerFunction($funcstr, $nvalue)
  1151. {
  1152. $funcstr = str_replace('@quote', '"', $funcstr);
  1153. $funcstr = str_replace('@me', $nvalue, $funcstr);
  1154. return $funcstr;
  1155. }
  1156. /**
  1157. * 引入文件 include 语法处理
  1158. *
  1159. * @access public
  1160. * @param string $filename 文件名
  1161. * @param string $isload 是否载入
  1162. * @return string
  1163. */
  1164. function CompilerInclude($filename, $isload=TRUE)
  1165. {
  1166. $okfile = '';
  1167. if( @file_exists($filename) )
  1168. {
  1169. $okfile = $filename;
  1170. }
  1171. else if( @file_exists($this->refDir.$filename) )
  1172. {
  1173. $okfile = $this->refDir.$filename;
  1174. }
  1175. else if( @file_exists($this->refDir."../".$filename) )
  1176. {
  1177. $okfile = $this->refDir."../".$filename;
  1178. }
  1179. if($okfile=='') return 0;
  1180. if( !$isload ) return 1;
  1181. $itpl = new DedeTemplate($this->templateDir);
  1182. $itpl->isCache = $this->isCache;
  1183. $itpl->SetObject($this->refObj);
  1184. $itpl->LoadTemplate($okfile);
  1185. return $itpl->CacheFile();
  1186. }
  1187. }
  1188. /**
  1189. * class TagAttribute Tag属性集合
  1190. * function C__TagAttribute();
  1191. * 属性的数据描述
  1192. *
  1193. * @package TagAttribute
  1194. * @subpackage DedeCMS.Libraries
  1195. * @link http://www.dedecms.com
  1196. */
  1197. class TagAttribute
  1198. {
  1199. var $count = -1;
  1200. var $items = array(); //属性元素的集合
  1201. /**
  1202. * 获得某个属性
  1203. *
  1204. * @access public
  1205. * @param string $str 预处理字符串
  1206. * @return string
  1207. */
  1208. function GetAtt($str)
  1209. {
  1210. if($str=="")
  1211. {
  1212. return "";
  1213. }
  1214. if(isset($this->items[$str]))
  1215. {
  1216. return $this->items[$str];
  1217. }
  1218. else
  1219. {
  1220. return "";
  1221. }
  1222. }
  1223. /**
  1224. * 同上
  1225. *
  1226. * @access public
  1227. * @param string $str 预处理字符串
  1228. * @return string
  1229. */
  1230. function GetAttribute($str)
  1231. {
  1232. return $this->GetAtt($str);
  1233. }
  1234. /**
  1235. * 判断属性是否存在
  1236. *
  1237. * @access public
  1238. * @param string $str 预处理字符串
  1239. * @return bool
  1240. */
  1241. function IsAttribute($str)
  1242. {
  1243. if(isset($this->items[$str])) return TRUE;
  1244. else return FALSE;
  1245. }
  1246. /**
  1247. * 获得标记名称
  1248. *
  1249. * @access public
  1250. * @return string
  1251. */
  1252. function GettagName()
  1253. {
  1254. return $this->GetAtt("tagname");
  1255. }
  1256. /**
  1257. * 获得属性个数
  1258. *
  1259. * @access public
  1260. * @return int
  1261. */
  1262. function Getcount()
  1263. {
  1264. return $this->count+1;
  1265. }
  1266. }//End Class
  1267. /**
  1268. * 属性解析器
  1269. * function C__TagAttributeParse();
  1270. *
  1271. * @package TagAttribute
  1272. * @subpackage DedeCMS.Libraries
  1273. * @link http://www.dedecms.com
  1274. */
  1275. class TagAttributeParse
  1276. {
  1277. var $sourceString = "";
  1278. var $sourceMaxSize = 1024;
  1279. var $cAttributes = array();
  1280. var $charToLow = TRUE;
  1281. function SetSource($str="")
  1282. {
  1283. $this->cAttributes = new TagAttribute();
  1284. $strLen = 0;
  1285. $this->sourceString = trim(preg_replace("/[ \r\n\t\f]{1,}/"," ",$str));
  1286. $strLen = strlen($this->sourceString);
  1287. if($strLen>0 && $strLen <= $this->sourceMaxSize)
  1288. {
  1289. $this->ParseAttribute();
  1290. }
  1291. }
  1292. /**
  1293. * 解析属性
  1294. *
  1295. * @access public
  1296. * @return void
  1297. */
  1298. function ParseAttribute()
  1299. {
  1300. $d = '';
  1301. $tmpatt = '';
  1302. $tmpvalue = '';
  1303. $startdd = -1;
  1304. $ddtag = '';
  1305. $hasAttribute=FALSE;
  1306. $strLen = strlen($this->sourceString);
  1307. $this->cAttributes->items = array();
  1308. // 获得Tag的名称,解析到 cAtt->GetAtt('tagname') 中
  1309. for($i=0; $i<$strLen; $i++)
  1310. {
  1311. if($this->sourceString[$i]==' ')
  1312. {
  1313. $this->cAttributes->count++;
  1314. $tmpvalues = explode('.', $tmpvalue);
  1315. $this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  1316. if( isset($tmpvalues[2]) )
  1317. {
  1318. $okname = $tmpvalues[1];
  1319. for($j=2;isset($tmpvalues[$j]);$j++)
  1320. {
  1321. $okname .= "['".$tmpvalues[$j]."']";
  1322. }
  1323. $this->cAttributes->items['name'] = $okname;
  1324. }
  1325. else if(isset($tmpvalues[1]) && $tmpvalues[1]!='')
  1326. {
  1327. $this->cAttributes->items['name'] = $tmpvalues[1];
  1328. }
  1329. $tmpvalue = '';
  1330. $hasAttribute = TRUE;
  1331. break;
  1332. }
  1333. else
  1334. {
  1335. $tmpvalue .= $this->sourceString[$i];
  1336. }
  1337. }
  1338. //不存在属性列表的情况
  1339. if(!$hasAttribute)
  1340. {
  1341. $this->cAttributes->count++;
  1342. $tmpvalues = explode('.', $tmpvalue);
  1343. $this->cAttributes->items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  1344. if( isset($tmpvalues[2]) )
  1345. {
  1346. $okname = $tmpvalues[1];
  1347. for($i=2;isset($tmpvalues[$i]);$i++)
  1348. {
  1349. $okname .= "['".$tmpvalues[$i]."']";
  1350. }
  1351. $this->cAttributes->items['name'] = $okname;
  1352. }
  1353. else if(isset($tmpvalues[1]) && $tmpvalues[1]!='')
  1354. {
  1355. $this->cAttributes->items['name'] = $tmpvalues[1];
  1356. }
  1357. return ;
  1358. }
  1359. $tmpvalue = '';
  1360. //如果字符串含有属性值,遍历源字符串,并获得各属性
  1361. for($i; $i<$strLen; $i++)
  1362. {
  1363. $d = $this->sourceString[$i];
  1364. //查找属性名称
  1365. if($startdd==-1)
  1366. {
  1367. if($d != '=')
  1368. {
  1369. $tmpatt .= $d;
  1370. }
  1371. else
  1372. {
  1373. if($this->charToLow)
  1374. {
  1375. $tmpatt = strtolower(trim($tmpatt));
  1376. }
  1377. else
  1378. {
  1379. $tmpatt = trim($tmpatt);
  1380. }
  1381. $startdd=0;
  1382. }
  1383. }
  1384. //查找属性的限定标志
  1385. else if($startdd==0)
  1386. {
  1387. switch($d)
  1388. {
  1389. case ' ':
  1390. break;
  1391. case '\'':
  1392. $ddtag = '\'';
  1393. $startdd = 1;
  1394. break;
  1395. case '"':
  1396. $ddtag = '"';
  1397. $startdd = 1;
  1398. break;
  1399. default:
  1400. $tmpvalue .= $d;
  1401. $ddtag = ' ';
  1402. $startdd = 1;
  1403. break;
  1404. }
  1405. }
  1406. else if($startdd==1)
  1407. {
  1408. if($d==$ddtag && ( isset($this->sourceString[$i-1]) && $this->sourceString[$i-1]!="\\") )
  1409. {
  1410. $this->cAttributes->count++;
  1411. $this->cAttributes->items[$tmpatt] = trim($tmpvalue);
  1412. $tmpatt = '';
  1413. $tmpvalue = '';
  1414. $startdd = -1;
  1415. }
  1416. else
  1417. {
  1418. $tmpvalue .= $d;
  1419. }
  1420. }
  1421. }//for
  1422. //最后一个属性的给值
  1423. if($tmpatt != '')
  1424. {
  1425. $this->cAttributes->count++;
  1426. $this->cAttributes->items[$tmpatt] = trim($tmpvalue);
  1427. }//print_r($this->cAttributes->items);
  1428. }// end func
  1429. }//End Class
  1430. /**
  1431. * 私有标签编译,主要用于if标签内的字符串解析
  1432. *
  1433. * @access public
  1434. * @param string $str 需要编译的字符串
  1435. * @return string
  1436. */
  1437. function private_rt($str)
  1438. {
  1439. if (is_array($str)) {
  1440. $arr = explode('.', $str[0]);
  1441. } else {
  1442. $arr = explode('.', $str);
  1443. }
  1444. $rs = '$GLOBALS[\'';
  1445. if($arr[0] == 'cfg')
  1446. {
  1447. return $rs.'cfg_'.$arr[1]."']";
  1448. }
  1449. elseif($arr[0] == 'var')
  1450. {
  1451. $arr[0] = '_vars';
  1452. $rs .= implode('\'][\'', $arr);
  1453. $rs .= "']";
  1454. return $rs;
  1455. }
  1456. elseif($arr[0] == 'global')
  1457. {
  1458. unset($arr[0]);
  1459. $rs .= implode('\'][\'', $arr);
  1460. $rs .= "']";
  1461. return $rs;
  1462. }
  1463. else
  1464. {
  1465. if($arr[0] == 'field') $arr[0] = 'fields';
  1466. $rs = '$'.$arr[0]."['";
  1467. unset($arr[0]);
  1468. $rs .= implode('\'][\'', $arr);
  1469. $rs .= "']";
  1470. return $rs;
  1471. }
  1472. }