国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

4 місяці тому
1 рік тому
2 роки тому
2 роки тому
2 роки тому
1 рік тому
8 місяці тому
1 рік тому
8 місяці тому
3 роки тому
8 місяці тому
8 місяці тому
3 роки тому
3 роки тому
2 роки тому
5 місяці тому
3 роки тому
3 роки тому
5 місяці тому
5 місяці тому
3 роки тому
3 роки тому
2 роки тому
8 місяці тому
2 роки тому
5 місяці тому
8 місяці тому
3 роки тому
8 місяці тому
1 рік тому
1 рік тому
8 місяці тому
1 рік тому
8 місяці тому
8 місяці тому
5 місяці тому
1 рік тому
5 місяці тому
8 місяці тому
4 місяці тому
8 місяці тому
5 місяці тому
4 місяці тому
3 роки тому
8 місяці тому
4 місяці тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
2 роки тому
1 рік тому
3 роки тому
2 роки тому
1 рік тому
3 роки тому
8 місяці тому
8 місяці тому
2 роки тому
8 місяці тому
2 роки тому
8 місяці тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. /**
  4. * 主题模板
  5. *
  6. * @version $id:dedetag.class.php 10:33 2010年7月6日 tianya $
  7. * @package DedeBIZ.Libraries
  8. * @copyright Copyright (c) 2022 DedeBIZ.COM
  9. * @license GNU GPL v2 (https://www.dedebiz.com/license)
  10. * @link https://www.dedebiz.com
  11. */
  12. class DedeTag
  13. {
  14. var $IsReplace = FALSE; //标记是否已被替代,供解析器使用
  15. var $TagName = ''; //标记名称
  16. var $InnerText = ''; //标记之间的文本
  17. var $StartPos = 0; //标记起始位置
  18. var $EndPos = 0; //标记结束位置
  19. var $CAttribute = null; //标记属性描述,即是class DedeAttribute
  20. var $TagValue = ''; //标记的值
  21. var $TagID = 0;
  22. /**
  23. * 获取标记的名称和值
  24. *
  25. * @access public
  26. * @return string
  27. */
  28. function GetName()
  29. {
  30. return strtolower($this->TagName);
  31. }
  32. /**
  33. * 获取值
  34. *
  35. * @access public
  36. * @return string
  37. */
  38. function GetValue()
  39. {
  40. return $this->TagValue;
  41. }
  42. //下面两个成员函数仅是为了兼容旧版
  43. function GetTagName()
  44. {
  45. return strtolower($this->TagName);
  46. }
  47. function GetTagValue()
  48. {
  49. return $this->TagValue;
  50. }
  51. //获取标记的指定属性
  52. function IsAttribute($str)
  53. {
  54. return $this->CAttribute->IsAttribute($str);
  55. }
  56. function GetAttribute($str)
  57. {
  58. return $this->CAttribute->GetAtt($str);
  59. }
  60. function GetAtt($str)
  61. {
  62. return $this->CAttribute->GetAtt($str);
  63. }
  64. function GetInnerText()
  65. {
  66. return $this->InnerText;
  67. }
  68. }
  69. /**
  70. * DedeTagParse模板类
  71. * function c____DedeTagParse();
  72. *
  73. * @package DedeTagParse
  74. * @subpackage DedeBIZ.Libraries
  75. * @link https://www.dedebiz.com
  76. */
  77. class DedeTagParse
  78. {
  79. var $NameSpace = 'dede'; //标记的名字空间
  80. var $TagStartWord = '{'; //标记起始
  81. var $TagEndWord = '}'; //标记结束
  82. var $TagMaxLen = 64; //标记名称的最大值
  83. var $CharToLow = TRUE; //TRUE表示对属性和标记名称不区分大小写
  84. var $IsCache = FALSE; //是否使用缓冲
  85. var $TempMkTime = 0;
  86. var $CacheFile = '';
  87. var $SourceString = ''; //模板字符串
  88. var $CTags = array(); //标记集合
  89. var $Count = -1; //$Tags标记个数
  90. var $refObj = ''; //引用当前模板类的对象
  91. var $taghashfile = '';
  92. function __construct()
  93. {
  94. if (!isset($GLOBALS['cfg_tplcache'])) {
  95. $GLOBALS['cfg_tplcache'] = 'N';
  96. }
  97. if ($GLOBALS['cfg_tplcache'] == 'Y') {
  98. $this->IsCache = TRUE;
  99. } else {
  100. $this->IsCache = FALSE;
  101. }
  102. if (DEDE_ENVIRONMENT == 'development') {
  103. $this->IsCache = FALSE;
  104. }
  105. $this->NameSpace = 'dede';
  106. $this->TagStartWord = '{';
  107. $this->TagEndWord = '}';
  108. $this->TagMaxLen = 64;
  109. $this->CharToLow = TRUE;
  110. $this->SourceString = '';
  111. $this->CTags = array();
  112. $this->Count = -1;
  113. $this->TempMkTime = 0;
  114. $this->CacheFile = '';
  115. }
  116. function DedeTagParse()
  117. {
  118. $this->__construct();
  119. }
  120. /**
  121. * 设置标记的命名空间,默认为dede
  122. *
  123. * @access public
  124. * @param string $str 字符串
  125. * @param string $s 开始标记
  126. * @param string $e 结束标记
  127. * @return void
  128. */
  129. function SetNameSpace($str, $s = "{", $e = "}")
  130. {
  131. $this->NameSpace = strtolower($str);
  132. $this->TagStartWord = $s;
  133. $this->TagEndWord = $e;
  134. }
  135. /**
  136. * 重置成员变量或Clear
  137. *
  138. * @access public
  139. * @return void
  140. */
  141. function SetDefault()
  142. {
  143. $this->SourceString = '';
  144. $this->CTags = array();
  145. $this->Count = -1;
  146. }
  147. /**
  148. * 强制引用
  149. *
  150. * @access public
  151. * @param object $refObj 隶属对象
  152. * @return void
  153. */
  154. function SetRefObj(&$refObj)
  155. {
  156. $this->refObj = $refObj;
  157. }
  158. function GetCount()
  159. {
  160. return $this->Count + 1;
  161. }
  162. function Clear()
  163. {
  164. $this->SetDefault();
  165. }
  166. /**
  167. * CheckDisabledFunctions COMMENT : CheckDisabledFunctions检查是否存在禁止的函数
  168. *
  169. * @access public
  170. * @param string
  171. * @return bool
  172. */
  173. function CheckDisabledFunctions($str, &$errmsg = '')
  174. {
  175. global $cfg_disable_funs;
  176. $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';
  177. //模板引擎添加disable_functions
  178. if (defined('DEDEDISFUN')) {
  179. $tokens = token_get_all_nl('<?php'.$str."\n\r?>");
  180. $disabled_functions = explode(',', $cfg_disable_funs);
  181. foreach ($tokens as $token) {
  182. if (is_array($token)) {
  183. if ($token[0] = '306' && in_array($token[1], $disabled_functions)) {
  184. $errmsg = 'DedeBIZ Error:function disabled "'.$token[1].'" <a href="https://www.dedebiz.com/help" target="_blank">more</a>';
  185. return FALSE;
  186. }
  187. }
  188. }
  189. }
  190. return TRUE;
  191. }
  192. /**
  193. * 检测模板缓存
  194. *
  195. * @access public
  196. * @param string $filename 文件名称
  197. * @return string
  198. */
  199. function LoadCache($filename)
  200. {
  201. global $cfg_tplcache, $cfg_tplcache_dir;
  202. if (!$this->IsCache) {
  203. return FALSE;
  204. }
  205. $cdir = dirname($filename);
  206. $cachedir = DEDEROOT.$cfg_tplcache_dir;
  207. $ckfile = str_replace($cdir, '', $filename).substr(md5($filename), 0, 16).'.inc';
  208. $ckfullfile = $cachedir.'/'.$ckfile;
  209. $ckfullfile_t = $cachedir.'/'.$ckfile.'.txt';
  210. $this->CacheFile = $ckfullfile;
  211. $this->TempMkTime = filemtime($filename);
  212. if (!file_exists($ckfullfile) || !file_exists($ckfullfile_t)) {
  213. return FALSE;
  214. }
  215. //检测模板最后更新时间
  216. $fp = fopen($ckfullfile_t, 'r');
  217. $time_info = trim(fgets($fp, 64));
  218. fclose($fp);
  219. if ($time_info != $this->TempMkTime) {
  220. return FALSE;
  221. }
  222. //引入缓冲数组
  223. include($this->CacheFile);
  224. $errmsg = '';
  225. //把缓冲数组文档读入类
  226. if (isset($z) && is_array($z)) {
  227. foreach ($z as $k => $v) {
  228. $this->Count++;
  229. $ctag = new DedeTAg();
  230. $ctag->CAttribute = new DedeAttribute();
  231. $ctag->IsReplace = FALSE;
  232. $ctag->TagName = $v[0];
  233. $ctag->InnerText = $v[1];
  234. $ctag->StartPos = $v[2];
  235. $ctag->EndPos = $v[3];
  236. $ctag->TagValue = '';
  237. $ctag->TagID = $k;
  238. if (isset($v[4]) && is_array($v[4])) {
  239. $i = 0;
  240. $ctag->CAttribute->Items = array();
  241. foreach ($v[4] as $k => $v) {
  242. $ctag->CAttribute->Count++;
  243. $ctag->CAttribute->Items[$k] = $v;
  244. }
  245. }
  246. $this->CTags[$this->Count] = $ctag;
  247. }
  248. } else {
  249. //模板没有缓冲数组
  250. $this->CTags = '';
  251. $this->Count = -1;
  252. }
  253. return TRUE;
  254. }
  255. /**
  256. * 写入缓存
  257. *
  258. * @access public
  259. * @param string
  260. * @return void
  261. */
  262. function SaveCache()
  263. {
  264. if (!empty($this->CacheFile)) {
  265. $fp = fopen($this->CacheFile.'.txt', "w");
  266. fwrite($fp, $this->TempMkTime."\n");
  267. fclose($fp);
  268. $fp = fopen($this->CacheFile, "w");
  269. flock($fp, 3);
  270. fwrite($fp, '<'.'?php'."\r\n");
  271. $errmsg = '';
  272. if (is_array($this->CTags)) {
  273. foreach ($this->CTags as $tid => $ctag) {
  274. $arrayValue = 'Array("'.$ctag->TagName.'",';
  275. if (!$this->CheckDisabledFunctions($ctag->InnerText, $errmsg)) {
  276. fclose($fp);
  277. @unlink($this->taghashfile);
  278. @unlink($this->CacheFile);
  279. @unlink($this->CacheFile.'.txt');
  280. die($errmsg);
  281. }
  282. $arrayValue .= '"'.str_replace('$', '\$', str_replace("\r", "\\r", str_replace("\n", "\\n", str_replace('"', '\"', str_replace("\\", "\\\\", $ctag->InnerText))))).'"';
  283. $arrayValue .= ",{$ctag->StartPos},{$ctag->EndPos});";
  284. fwrite($fp, "\$z[$tid]={$arrayValue}\n");
  285. if (is_array($ctag->CAttribute->Items)) {
  286. fwrite($fp, "\$z[$tid][4]=array();\n");
  287. foreach ($ctag->CAttribute->Items as $k => $v) {
  288. $v = str_replace("\\", "\\\\", $v);
  289. $v = str_replace('"', "\\".'"', $v);
  290. $v = str_replace('$', '\$', $v);
  291. $k = trim(str_replace("'", "", $k));
  292. if ($k == "") {
  293. continue;
  294. }
  295. if ($k != 'tagname') {
  296. fwrite($fp, "\$z[$tid][4]['$k']=\"$v\";\n");
  297. }
  298. }
  299. }
  300. }
  301. }
  302. fwrite($fp, "\n".'?'.'>');
  303. fclose($fp);
  304. }
  305. }
  306. /**
  307. * 载入模板文件
  308. *
  309. * @access public
  310. * @param string $filename 文件名称
  311. * @return void
  312. */
  313. function LoadTemplate($filename)
  314. {
  315. $this->SetDefault();
  316. if (!file_exists($filename)) {
  317. $this->SourceString = " $filename Not Found! ";
  318. $this->ParseTemplet();
  319. } else {
  320. $fp = @fopen($filename, "r");
  321. while ($line = fgets($fp, 1024)) {
  322. $this->SourceString .= $line;
  323. }
  324. fclose($fp);
  325. if ($this->LoadCache($filename)) {
  326. return;
  327. } else {
  328. $this->ParseTemplet();
  329. }
  330. }
  331. }
  332. //仅用于兼容旧版本
  333. function LoadTemplet($filename)
  334. {
  335. $this->LoadTemplate($filename);
  336. }
  337. //仅用于兼容旧版本
  338. function LoadFile($filename)
  339. {
  340. $this->LoadTemplate($filename);
  341. }
  342. /**
  343. * 载入模板字符串
  344. *
  345. * @access public
  346. * @param string $str 字符串
  347. * @return void
  348. */
  349. function LoadSource($str)
  350. {
  351. //优化模板字符串存取读取方式
  352. $this->taghashfile = $filename = DEDEDATA.'/tplcache/'.md5($str).'.inc';
  353. if (!is_file($filename)) {
  354. file_put_contents($filename, $str);
  355. }
  356. $this->LoadTemplate($filename);
  357. }
  358. function LoadString($str)
  359. {
  360. $this->LoadSource($str);
  361. }
  362. /**
  363. * 获得指定名称的Tag的id,如果有多个同名的Tag,则取没有被取代为文档的第一个Tag
  364. *
  365. * @access public
  366. * @param string $str 字符串
  367. * @return int
  368. */
  369. function GetTagID($str)
  370. {
  371. if ($this->Count == -1) {
  372. return -1;
  373. }
  374. if ($this->CharToLow) {
  375. $str = strtolower($str);
  376. }
  377. foreach ($this->CTags as $id => $CTag) {
  378. if ($CTag->TagName == $str && !$CTag->IsReplace) {
  379. return $id;
  380. }
  381. }
  382. return -1;
  383. }
  384. /**
  385. * 获得指定名称的CTag数据类,如果有多个同名的Tag,则取没有被分配文档的第一个Tag
  386. *
  387. * @access public
  388. * @param string $str 字符串
  389. * @return mixed
  390. */
  391. function GetTag($str)
  392. {
  393. if ($this->Count == -1) {
  394. return '';
  395. }
  396. if ($this->CharToLow) {
  397. $str = strtolower($str);
  398. }
  399. foreach ($this->CTags as $id => $CTag) {
  400. if ($CTag->TagName == $str && !$CTag->IsReplace) {
  401. return $CTag;
  402. }
  403. }
  404. return '';
  405. }
  406. /**
  407. * 通过名称获取标记
  408. *
  409. * @access public
  410. * @param string $str 字符串
  411. * @return string
  412. */
  413. function GetTagByName($str)
  414. {
  415. return $this->GetTag($str);
  416. }
  417. /**
  418. * 获得指定id的CTag数据类
  419. *
  420. * @access public
  421. * @param string 标签id
  422. * @return string
  423. */
  424. function GetTagByID($id)
  425. {
  426. if (isset($this->CTags[$id])) {
  427. return $this->CTags[$id];
  428. } else {
  429. return '';
  430. }
  431. }
  432. /**
  433. * 给_vars数组传递一个元素
  434. *
  435. * @access public
  436. * @param string $vname 标签名
  437. * @param string $vvalue 标签值
  438. * @return void
  439. */
  440. function AssignVar($vname, $vvalue)
  441. {
  442. if (!isset($_sys_globals['define'])) {
  443. $_sys_globals['define'] = 'yes';
  444. }
  445. $_sys_globals[$vname] = $vvalue;
  446. }
  447. /**
  448. * 分配指定id的标记的值
  449. *
  450. * @access public
  451. * @param string $i 标签id
  452. * @param string $str 字符串
  453. * @param string $runfunc 运行函数
  454. * @return void
  455. */
  456. function Assign($i, $str, $runfunc = TRUE)
  457. {
  458. if (isset($this->CTags[$i])) {
  459. $this->CTags[$i]->IsReplace = TRUE;
  460. $this->CTags[$i]->TagValue = $str;
  461. if ($this->CTags[$i]->GetAtt('function') != '' && $runfunc) {
  462. $this->CTags[$i]->TagValue = $this->EvalFunc($str, $this->CTags[$i]->GetAtt('function'), $this->CTags[$i]);
  463. }
  464. }
  465. }
  466. /**
  467. * 分配指定名称的标记的值,如果标记包含属性,请不要用此函数
  468. *
  469. * @access public
  470. * @param string $tagname 标签名称
  471. * @param string $str 字符串
  472. * @return void
  473. */
  474. function AssignName($tagname, $str)
  475. {
  476. foreach ($this->CTags as $id => $CTag) {
  477. if ($CTag->TagName == $tagname) {
  478. $this->Assign($id, $str);
  479. }
  480. }
  481. }
  482. /**
  483. * 处理特殊标记
  484. *
  485. * @access public
  486. * @return void
  487. */
  488. function AssignSysTag()
  489. {
  490. global $_sys_globals;
  491. for ($i = 0; $i <= $this->Count; $i++) {
  492. $CTag = $this->CTags[$i];
  493. $str = '';
  494. //获取一个外部变量
  495. if ($CTag->TagName == 'global') {
  496. $str = $this->GetGlobals($CTag->GetAtt('name'));
  497. if ($this->CTags[$i]->GetAtt('function') != '') {
  498. //$str = $this->EvalFunc( $this->CTags[$i]->TagValue, $this->CTags[$i]->GetAtt('function'),$this->CTags[$i] );
  499. $str = $this->EvalFunc($str, $this->CTags[$i]->GetAtt('function'), $this->CTags[$i]);
  500. }
  501. $this->CTags[$i]->IsReplace = TRUE;
  502. $this->CTags[$i]->TagValue = $str;
  503. }
  504. //引入静态文件
  505. else if ($CTag->TagName == 'include') {
  506. $filename = ($CTag->GetAtt('file') == '' ? $CTag->GetAtt('filename') : $CTag->GetAtt('file'));
  507. $str = $this->IncludeFile($filename, $CTag->GetAtt('ismake'));
  508. $this->CTags[$i]->IsReplace = TRUE;
  509. $this->CTags[$i]->TagValue = $str;
  510. }
  511. //循环一个普通数组
  512. else if ($CTag->TagName == 'foreach') {
  513. $arr = $this->CTags[$i]->GetAtt('array');
  514. if (isset($GLOBALS[$arr])) {
  515. foreach ($GLOBALS[$arr] as $k => $v) {
  516. $istr = '';
  517. $istr .= preg_replace("/\[field:key([\r\n\t\f ]+)\/\]/is", $k, $this->CTags[$i]->InnerText);
  518. $str .= preg_replace("/\[field:value([\r\n\t\f ]+)\/\]/is", $v, $istr);
  519. }
  520. }
  521. $this->CTags[$i]->IsReplace = TRUE;
  522. $this->CTags[$i]->TagValue = $str;
  523. }
  524. //设置获取变量值
  525. else if ($CTag->TagName == 'var') {
  526. $vname = $this->CTags[$i]->GetAtt('name');
  527. if ($vname == '') {
  528. $str = '';
  529. } else if ($this->CTags[$i]->GetAtt('value') != '') {
  530. $_vars[$vname] = $this->CTags[$i]->GetAtt('value');
  531. } else {
  532. $str = (isset($_vars[$vname]) ? $_vars[$vname] : '');
  533. }
  534. $this->CTags[$i]->IsReplace = TRUE;
  535. $this->CTags[$i]->TagValue = $str;
  536. }
  537. //运行PHP接口
  538. if ($CTag->GetAtt('runphp') == 'yes') {
  539. $this->RunPHP($CTag, $i);
  540. }
  541. if (is_array($this->CTags[$i]->TagValue)) {
  542. $this->CTags[$i]->TagValue = 'array';
  543. }
  544. }
  545. }
  546. //运行PHP代码
  547. function RunPHP(&$refObj, $i)
  548. {
  549. $DedeMeValue = $phpcode = '';
  550. if ($refObj->GetAtt('source') == 'value') {
  551. $phpcode = $this->CTags[$i]->TagValue;
  552. } else {
  553. $DedeMeValue = $this->CTags[$i]->TagValue;
  554. $phpcode = $refObj->GetInnerText();
  555. }
  556. $phpcode = preg_replace("/'@me'|\"@me\"|@me/i", '$DedeMeValue', $phpcode);
  557. try {
  558. @eval($phpcode);
  559. $this->CTags[$i]->TagValue = $DedeMeValue;
  560. $this->CTags[$i]->IsReplace = TRUE;
  561. } catch (Exception $e) {
  562. //or die("<xmp>$phpcode</xmp>");
  563. }
  564. $this->CTags[$i]->TagValue = $DedeMeValue;
  565. $this->CTags[$i]->IsReplace = TRUE;
  566. }
  567. /**
  568. * 把分析模板输出到一个字符串中,不替换没被处理的值
  569. *
  570. * @access public
  571. * @return string
  572. */
  573. function GetResultNP()
  574. {
  575. $ResultString = '';
  576. if ($this->Count == -1) {
  577. return $this->SourceString;
  578. }
  579. $this->AssignSysTag();
  580. $nextTagEnd = 0;
  581. $strok = '';
  582. for ($i = 0; $i <= $this->Count; $i++) {
  583. if ($this->CTags[$i]->GetValue() != "") {
  584. if ($this->CTags[$i]->GetValue() == '#@Delete@#') {
  585. $this->CTags[$i]->TagValue = '';
  586. }
  587. $ResultString .= substr($this->SourceString, $nextTagEnd, $this->CTags[$i]->StartPos - $nextTagEnd);
  588. $ResultString .= $this->CTags[$i]->GetValue();
  589. $nextTagEnd = $this->CTags[$i]->EndPos;
  590. }
  591. }
  592. $slen = strlen($this->SourceString);
  593. if ($slen > $nextTagEnd) {
  594. $ResultString .= substr($this->SourceString, $nextTagEnd, $slen - $nextTagEnd);
  595. }
  596. return $ResultString;
  597. }
  598. /**
  599. * 把分析模板输出到一个字符串中并返回
  600. *
  601. * @access public
  602. * @return string
  603. */
  604. function GetResult()
  605. {
  606. $ResultString = '';
  607. if ($this->Count == -1) {
  608. return $this->SourceString;
  609. }
  610. $this->AssignSysTag();
  611. $nextTagEnd = 0;
  612. $strok = '';
  613. for ($i = 0; $i <= $this->Count; $i++) {
  614. $ResultString .= substr($this->SourceString, $nextTagEnd, $this->CTags[$i]->StartPos - $nextTagEnd);
  615. $ResultString .= $this->CTags[$i]->GetValue();
  616. $nextTagEnd = $this->CTags[$i]->EndPos;
  617. }
  618. $slen = strlen($this->SourceString);
  619. if ($slen > $nextTagEnd) {
  620. $ResultString .= substr($this->SourceString, $nextTagEnd, $slen - $nextTagEnd);
  621. }
  622. return $ResultString;
  623. }
  624. /**
  625. * 直接解析模板
  626. *
  627. * @access public
  628. * @return void
  629. */
  630. function Display()
  631. {
  632. echo $this->GetResult();
  633. }
  634. /**
  635. * 解析模板为文件
  636. *
  637. * @access public
  638. * @param string $filename 要保存到的文件
  639. * @return void
  640. */
  641. function SaveTo($filename)
  642. {
  643. $fp = @fopen($filename, "w") or die("请检查栏目生成目录是否填写正确,目录文件是否存在");
  644. fwrite($fp, $this->GetResult());
  645. fclose($fp);
  646. }
  647. /**
  648. * 解析模板
  649. *
  650. * @access public
  651. * @return void
  652. */
  653. function ParseTemplet()
  654. {
  655. $TagStartWord = $this->TagStartWord;
  656. $TagEndWord = $this->TagEndWord;
  657. $sPos = 0;
  658. $ePos = 0;
  659. $FullTagStartWord = $TagStartWord.$this->NameSpace.":";
  660. $sTagEndWord = $TagStartWord."/".$this->NameSpace.":";
  661. $eTagEndWord = "/".$TagEndWord;
  662. $tsLen = strlen($FullTagStartWord);
  663. $sourceLen = strlen($this->SourceString);
  664. if ($sourceLen <= ($tsLen + 3)) {
  665. return;
  666. }
  667. $cAtt = new DedeAttributeParse();
  668. $cAtt->charToLow = $this->CharToLow;
  669. //遍历模板字符串,请取标记及其属性信息
  670. for ($i = 0; $i < $sourceLen; $i++) {
  671. $tTagName = '';
  672. //如果不进行此判断,无法识别相连的两个标记
  673. if ($i - 1 >= 0) {
  674. $ss = $i - 1;
  675. } else {
  676. $ss = 0;
  677. }
  678. $sPos = strpos($this->SourceString, $FullTagStartWord, $ss);
  679. $isTag = $sPos;
  680. if ($i == 0) {
  681. $headerTag = substr($this->SourceString, 0, strlen($FullTagStartWord));
  682. if ($headerTag == $FullTagStartWord) {
  683. $isTag = TRUE;
  684. $sPos = 0;
  685. }
  686. }
  687. if ($isTag === FALSE) {
  688. break;
  689. }
  690. //判断是否已经到倒数第三个字符可能性几率极小,取消此逻辑
  691. for ($j = ($sPos + $tsLen); $j < ($sPos + $tsLen + $this->TagMaxLen); $j++) {
  692. if ($j > ($sourceLen - 1)) {
  693. break;
  694. } else if (preg_match("/[\/ \t\r\n]/", $this->SourceString[$j]) || $this->SourceString[$j] == $this->TagEndWord) {
  695. break;
  696. } else {
  697. $tTagName .= $this->SourceString[$j];
  698. }
  699. }
  700. if ($tTagName != '') {
  701. $i = $sPos + $tsLen;
  702. $endPos = -1;
  703. $fullTagEndWordThis = $sTagEndWord.$tTagName.$TagEndWord;
  704. $e1 = strpos($this->SourceString, $eTagEndWord, $i);
  705. $e2 = strpos($this->SourceString, $FullTagStartWord, $i);
  706. $e3 = strpos($this->SourceString, $fullTagEndWordThis, $i);
  707. $e4 = strpos($this->SourceString, $TagStartWord, $i);
  708. $e1 = trim($e1);
  709. $e2 = trim($e2);
  710. $e3 = trim($e3);
  711. $e1 = ($e1 == '' ? '-1' : $e1);
  712. $e2 = ($e2 == '' ? '-1' : $e2);
  713. $e3 = ($e3 == '' ? '-1' : $e3);
  714. if ($e3 == -1) {
  715. $endPos = $e1;
  716. $elen = $endPos + strlen($eTagEndWord);
  717. } else if ($e1 == -1) {
  718. $endPos = $e3;
  719. $elen = $endPos + strlen($fullTagEndWordThis);
  720. } else {
  721. if ($e1 < $e2 && $e1 < $e3) {
  722. if ($e4 < $e1) {
  723. $endPos = $e3;
  724. $elen = $endPos + strlen($fullTagEndWordThis);
  725. } else {
  726. $endPos = $e1;
  727. $elen = $endPos + strlen($eTagEndWord);
  728. }
  729. } else {
  730. $endPos = $e3;
  731. $elen = $endPos + strlen($fullTagEndWordThis);
  732. }
  733. }
  734. if ($endPos == -1) {
  735. echo "Tag Character postion $sPos, '$tTagName' Error<br>\r\n";
  736. break;
  737. }
  738. $i = $elen;
  739. $ePos = $endPos;
  740. //分析所找到的标记位置等信息
  741. $attStr = '';
  742. $innerText = '';
  743. $startInner = 0;
  744. for ($j = ($sPos + $tsLen); $j < $ePos; $j++) {
  745. if ($startInner == 0 && ($this->SourceString[$j] == $TagEndWord && $this->SourceString[$j - 1] != "\\")) {
  746. $startInner = 1;
  747. continue;
  748. }
  749. if ($startInner == 0) {
  750. $attStr .= $this->SourceString[$j];
  751. } else {
  752. $innerText .= $this->SourceString[$j];
  753. }
  754. }
  755. //echo "<xmp>$attStr</xmp>\r\n";
  756. $cAtt->SetSource($attStr);
  757. if ($cAtt->cAttributes->GetTagName() != '') {
  758. $this->Count++;
  759. $CDTag = new DedeTag();
  760. $CDTag->TagName = $cAtt->cAttributes->GetTagName();
  761. $CDTag->StartPos = $sPos;
  762. $CDTag->EndPos = $i;
  763. $CDTag->CAttribute = $cAtt->cAttributes;
  764. $CDTag->IsReplace = FALSE;
  765. $CDTag->TagID = $this->Count;
  766. $CDTag->InnerText = $innerText;
  767. $this->CTags[$this->Count] = $CDTag;
  768. }
  769. } else {
  770. $i = $sPos + $tsLen;
  771. break;
  772. }
  773. }
  774. // exit;
  775. if ($this->IsCache) {
  776. $this->SaveCache();
  777. }
  778. }
  779. /**
  780. * 处理某字段的函数
  781. *
  782. * @access public
  783. * @param string $fieldvalue 字段值
  784. * @param string $functionname 函数名称
  785. * @param object $refObj 隶属对象
  786. * @return string
  787. */
  788. function EvalFunc($fieldvalue, $functionname, &$refObj)
  789. {
  790. $DedeFieldValue = $fieldvalue;
  791. $functionname = str_replace("{\"", "[\"", $functionname);
  792. $functionname = str_replace("\"}", "\"]", $functionname);
  793. $functionname = preg_replace("/'@me'|\"@me\"|@me/i", '$DedeFieldValue', $functionname);
  794. $functionname = "\$DedeFieldValue = ".$functionname;
  795. try {
  796. @eval($functionname.";");
  797. if (empty($DedeFieldValue)) {
  798. return '';
  799. } else {
  800. return $DedeFieldValue;
  801. }
  802. } catch (Throwable $e) {
  803. //or die("<xmp>$functionname</xmp>");
  804. echo DedeAlert('模板存在无法解析的标签,请检查模板标签后更新网站,错误提示:'.$e->getMessage(),ALERT_WARNING);
  805. return '';
  806. }
  807. }
  808. /**
  809. * 获得一个外部变量
  810. *
  811. * @access public
  812. * @param string $varname 变量名称
  813. * @return string
  814. */
  815. function GetGlobals($varname)
  816. {
  817. $varname = trim($varname);
  818. //禁止在模板文件读取数据库密码
  819. if ($varname == "dbuserpwd" || $varname == "cfg_dbpwd") {
  820. return "";
  821. }
  822. //正常情况
  823. if (isset($GLOBALS[$varname])) {
  824. return $GLOBALS[$varname];
  825. } else {
  826. return "";
  827. }
  828. }
  829. /**
  830. * 引入文件
  831. *
  832. * @access public
  833. * @param string $filename 文件名
  834. * @param string $ismake 是否需要编译
  835. * @return string
  836. */
  837. function IncludeFile($filename, $ismake = 'no')
  838. {
  839. global $cfg_df_style;
  840. $restr = '';
  841. if ($filename == '') {
  842. return '';
  843. }
  844. if (file_exists(DEDEROOT."/theme/".$filename)) {
  845. $okfile = DEDEROOT."/theme/".$filename;
  846. } else if (file_exists(DEDEROOT.'/theme/'.$cfg_df_style.'/'.$filename)) {
  847. $okfile = DEDEROOT.'/theme/'.$cfg_df_style.'/'.$filename;
  848. } else {
  849. return "主题模板不存在:$filename";
  850. }
  851. //编译
  852. if ($ismake != "no") {
  853. require_once(DEDEINC."/channelunit.func.php");
  854. $dtp = new DedeTagParse();
  855. $dtp->LoadTemplet($okfile);
  856. MakeOneTag($dtp, $this->refObj);
  857. $restr = $dtp->GetResult();
  858. } else {
  859. $fp = @fopen($okfile, "r");
  860. while ($line = fgets($fp, 1024)) $restr .= $line;
  861. fclose($fp);
  862. }
  863. return $restr;
  864. }
  865. }
  866. //属性数据描述
  867. class DedeAttribute
  868. {
  869. var $Count = -1;
  870. var $Items = array(); //属性元素的集合
  871. //获得某个属性
  872. function GetAtt($str)
  873. {
  874. if ($str == "") {
  875. return "";
  876. }
  877. if (isset($this->Items[$str])) {
  878. return $this->Items[$str];
  879. } else {
  880. return "";
  881. }
  882. }
  883. //同上
  884. function GetAttribute($str)
  885. {
  886. return $this->GetAtt($str);
  887. }
  888. //判断属性是否存在
  889. function IsAttribute($str)
  890. {
  891. if (isset($this->Items[$str])) return TRUE;
  892. else return FALSE;
  893. }
  894. //获得标记名称
  895. function GetTagName()
  896. {
  897. return $this->GetAtt("tagname");
  898. }
  899. //获得属性个数
  900. function GetCount()
  901. {
  902. return $this->Count + 1;
  903. }
  904. }
  905. //属性解析器
  906. class DedeAttributeParse
  907. {
  908. var $sourceString = '';
  909. var $sourceMaxSize = 1024;
  910. var $cAttributes = null;
  911. var $charToLow = TRUE;
  912. function SetSource($str = '')
  913. {
  914. $this->cAttributes = new DedeAttribute();
  915. $strLen = 0;
  916. $this->sourceString = trim(preg_replace("/[ \r\n\t]{1,}/", " ", $str));
  917. //为了在function内能使用数组,这里允许对[ ]进行转义使用
  918. $this->sourceString = str_replace('\]', ']', $this->sourceString);
  919. $this->sourceString = str_replace('[', '[', $this->sourceString);
  920. $strLen = strlen($this->sourceString);
  921. if ($strLen > 0 && $strLen <= $this->sourceMaxSize) {
  922. $this->ParseAttribute();
  923. }
  924. }
  925. //解析属性
  926. function ParseAttribute()
  927. {
  928. $d = '';
  929. $tmpatt = '';
  930. $tmpvalue = '';
  931. $startdd = -1;
  932. $ddtag = '';
  933. $hasAttribute = FALSE;
  934. $strLen = strlen($this->sourceString);
  935. $this->cAttributes->Items = array();
  936. //获得Tag的名称,解析到cAtt->GetAtt('tagname')中
  937. for ($i = 0; $i < $strLen; $i++) {
  938. if ($this->sourceString[$i] == ' ') {
  939. $this->cAttributes->Count++;
  940. $tmpvalues = explode('.', $tmpvalue);
  941. $this->cAttributes->Items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  942. if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
  943. $this->cAttributes->Items['name'] = $tmpvalues[1];
  944. }
  945. $tmpvalue = '';
  946. $hasAttribute = TRUE;
  947. break;
  948. } else {
  949. $tmpvalue .= $this->sourceString[$i];
  950. }
  951. }
  952. //不存在属性列表的情况
  953. if (!$hasAttribute) {
  954. $this->cAttributes->Count++;
  955. $tmpvalues = explode('.', $tmpvalue);
  956. $this->cAttributes->Items['tagname'] = ($this->charToLow ? strtolower($tmpvalues[0]) : $tmpvalues[0]);
  957. if (isset($tmpvalues[1]) && $tmpvalues[1] != '') {
  958. $this->cAttributes->Items['name'] = $tmpvalues[1];
  959. }
  960. return;
  961. }
  962. $tmpvalue = '';
  963. //如果字符串含有属性值,遍历源字符串并获得各属性
  964. for ($i; $i < $strLen; $i++) {
  965. $d = $this->sourceString[$i];
  966. //查找属性名称
  967. if ($startdd == -1) {
  968. if ($d != '=') {
  969. $tmpatt .= $d;
  970. } else {
  971. if ($this->charToLow) {
  972. $tmpatt = strtolower(trim($tmpatt));
  973. } else {
  974. $tmpatt = trim($tmpatt);
  975. }
  976. $startdd = 0;
  977. }
  978. }
  979. //查找属性限定标志
  980. else if ($startdd == 0) {
  981. switch ($d) {
  982. case ' ':
  983. break;
  984. case '"':
  985. $ddtag = '"';
  986. $startdd = 1;
  987. break;
  988. case '\'':
  989. $ddtag = '\'';
  990. $startdd = 1;
  991. break;
  992. default:
  993. $tmpvalue .= $d;
  994. $ddtag = ' ';
  995. $startdd = 1;
  996. break;
  997. }
  998. } else if ($startdd == 1) {
  999. if ($d == $ddtag && (isset($this->sourceString[$i - 1]) && $this->sourceString[$i - 1] != "\\")) {
  1000. $this->cAttributes->Count++;
  1001. $this->cAttributes->Items[$tmpatt] = trim($tmpvalue);
  1002. $tmpatt = '';
  1003. $tmpvalue = '';
  1004. $startdd = -1;
  1005. } else {
  1006. $tmpvalue .= $d;
  1007. }
  1008. }
  1009. }
  1010. //最后一个属性给值
  1011. if ($tmpatt != '') {
  1012. $this->cAttributes->Count++;
  1013. $this->cAttributes->Items[$tmpatt] = trim($tmpvalue);
  1014. }
  1015. }
  1016. }
  1017. ?>