PageRenderTime 69ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/includes/template/tbs_class_php5.php

http://xinix.googlecode.com/
PHP | 3721 lines | 3167 code | 366 blank | 188 comment | 874 complexity | eba4b2239dbf0ef28ef418b688b83691 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. ********************************************************
  4. TinyButStrong - Template Engine for Pro and Beginners
  5. ------------------------
  6. Version : 3.5.3 for PHP 5
  7. Date : 2010-04-12
  8. Web site : http://www.tinybutstrong.com
  9. Author : http://www.tinybutstrong.com/onlyyou.html
  10. ********************************************************
  11. This library is free software.
  12. You can redistribute and modify it even for commercial usage,
  13. but you must accept and respect the LPGL License version 3.
  14. */
  15. // Check PHP version
  16. if (version_compare(PHP_VERSION,'5.0')<0) echo '<br><b>TinyButStrong Error</b> (PHP Version Check) : Your PHP version is '.PHP_VERSION.' while TinyButStrong needs PHP version 5.0 or higher. You should try with TinyButStrong Edition for PHP 4.';
  17. // Render flags
  18. define('TBS_NOTHING', 0);
  19. define('TBS_OUTPUT', 1);
  20. define('TBS_EXIT', 2);
  21. // Plug-ins actions
  22. define('TBS_INSTALL', -1);
  23. define('TBS_ISINSTALLED', -3);
  24. // *********************************************
  25. class clsTbsLocator {
  26. public $PosBeg = false;
  27. public $PosEnd = false;
  28. public $Enlarged = false;
  29. public $FullName = false;
  30. public $SubName = '';
  31. public $SubOk = false;
  32. public $SubLst = array();
  33. public $SubNbr = 0;
  34. public $PrmLst = array();
  35. public $PrmIfNbr = false;
  36. public $MagnetId = false;
  37. public $BlockFound = false;
  38. public $FirstMerge = true;
  39. public $ConvProtect = true;
  40. public $ConvStr = true;
  41. public $ConvMode = 1; // Normal
  42. public $ConvBr = true;
  43. }
  44. // *********************************************
  45. class clsTbsDataSource {
  46. public $Type = false;
  47. public $SubType = 0;
  48. public $SrcId = false;
  49. public $Query = '';
  50. public $RecSet = false;
  51. public $RecKey = '';
  52. public $RecNum = 0;
  53. public $RecNumInit = 0;
  54. public $RecSaving = false;
  55. public $RecSaved = false;
  56. public $RecBuffer = false;
  57. public $CurrRec = false;
  58. public $TBS = false;
  59. public $OnDataOk = false;
  60. public $OnDataPrm = false;
  61. public $OnDataPrmDone = array();
  62. public $OnDataPi = false;
  63. public function DataAlert($Msg) {
  64. return $this->TBS->meth_Misc_Alert('when merging block '.$this->TBS->_ChrOpen.$this->TBS->_CurrBlock.$this->TBS->_ChrClose,$Msg);
  65. }
  66. public function DataPrepare(&$SrcId,&$TBS) {
  67. $this->SrcId = &$SrcId;
  68. $this->TBS = &$TBS;
  69. $FctInfo = false;
  70. $FctObj = false;
  71. if (is_array($SrcId)) {
  72. $this->Type = 0;
  73. } elseif (is_resource($SrcId)) {
  74. $Key = get_resource_type($SrcId);
  75. switch ($Key) {
  76. case 'mysql link' : $this->Type = 6; break;
  77. case 'mysql link persistent' : $this->Type = 6; break;
  78. case 'mysql result' : $this->Type = 6; $this->SubType = 1; break;
  79. case 'pgsql link' : $this->Type = 7; break;
  80. case 'pgsql link persistent' : $this->Type = 7; break;
  81. case 'pgsql result' : $this->Type = 7; $this->SubType = 1; break;
  82. case 'sqlite database' : $this->Type = 8; break;
  83. case 'sqlite database (persistent)' : $this->Type = 8; break;
  84. case 'sqlite result' : $this->Type = 8; $this->SubType = 1; break;
  85. default :
  86. $FctInfo = $Key;
  87. $FctCat = 'r';
  88. }
  89. } elseif (is_string($SrcId)) {
  90. switch (strtolower($SrcId)) {
  91. case 'array' : $this->Type = 0; $this->SubType = 1; break;
  92. case 'clear' : $this->Type = 0; $this->SubType = 3; break;
  93. case 'mysql' : $this->Type = 6; $this->SubType = 2; break;
  94. case 'text' : $this->Type = 2; break;
  95. case 'num' : $this->Type = 1; break;
  96. default :
  97. $FctInfo = $SrcId;
  98. $FctCat = 'k';
  99. }
  100. } elseif ($SrcId instanceof Iterator) {
  101. $this->Type = 9; $this->SubType = 1;
  102. } elseif ($SrcId instanceof ArrayObject) {
  103. $this->Type = 9; $this->SubType = 2;
  104. } elseif ($SrcId instanceof IteratorAggregate) {
  105. $this->Type = 9; $this->SubType = 3;
  106. } elseif (is_object($SrcId)) {
  107. $FctInfo = get_class($SrcId);
  108. $FctCat = 'o';
  109. $FctObj = &$SrcId;
  110. $this->SrcId = &$SrcId;
  111. } elseif ($SrcId===false) {
  112. $this->DataAlert('the specified source is set to FALSE. Maybe your connection has failed.');
  113. } else {
  114. $this->DataAlert('unsupported variable type : \''.gettype($SrcId).'\'.');
  115. }
  116. if ($FctInfo!==false) {
  117. $ErrMsg = false;
  118. if ($TBS->meth_Misc_UserFctCheck($FctInfo,$FctCat,$FctObj,$ErrMsg)) {
  119. $this->Type = $FctInfo['type'];
  120. if ($this->Type!==5) {
  121. if ($this->Type===4) {
  122. $this->FctPrm = array(false,0);
  123. $this->SrcId = &$FctInfo['open'][0];
  124. }
  125. $this->FctOpen = &$FctInfo['open'];
  126. $this->FctFetch = &$FctInfo['fetch'];
  127. $this->FctClose = &$FctInfo['close'];
  128. }
  129. } else {
  130. $this->Type = $this->DataAlert($ErrMsg);
  131. }
  132. }
  133. return ($this->Type!==false);
  134. }
  135. public function DataOpen(&$Query) {
  136. // Init values
  137. unset($this->CurrRec); $this->CurrRec = true;
  138. if ($this->RecSaved) {
  139. $this->FirstRec = true;
  140. unset($this->RecKey); $this->RecKey = '';
  141. $this->RecNum = $this->RecNumInit;
  142. if ($this->OnDataOk) $this->OnDataArgs[1] = &$this->CurrRec;
  143. return true;
  144. }
  145. unset($this->RecSet); $this->RecSet = false;
  146. $this->RecNumInit = 0;
  147. $this->RecNum = 0;
  148. if (isset($this->TBS->_piOnData)) {
  149. $this->OnDataPi = true;
  150. $this->OnDataPiRef = &$this->TBS->_piOnData;
  151. $this->OnDataOk = true;
  152. }
  153. if ($this->OnDataOk) {
  154. $this->OnDataArgs = array();
  155. $this->OnDataArgs[0] = &$this->TBS->_CurrBlock;
  156. $this->OnDataArgs[1] = &$this->CurrRec;
  157. $this->OnDataArgs[2] = &$this->RecNum;
  158. $this->OnDataArgs[3] = &$this->TBS;
  159. }
  160. switch ($this->Type) {
  161. case 0: // Array
  162. if (($this->SubType===1) and (is_string($Query))) $this->SubType = 2;
  163. if ($this->SubType===0) {
  164. $this->RecSet = &$this->SrcId;
  165. } elseif ($this->SubType===1) {
  166. if (is_array($Query)) {
  167. $this->RecSet = &$Query;
  168. } else {
  169. $this->DataAlert('type \''.gettype($Query).'\' not supported for the Query Parameter going with \'array\' Source Type.');
  170. }
  171. } elseif ($this->SubType===2) {
  172. // TBS query string for array and objects, syntax: "var[item1][item2]->item3[item4]..."
  173. $x = trim($Query);
  174. $z = chr(0);
  175. $x = str_replace(array(']->','][','->','['),$z,$x);
  176. if (substr($x,strlen($x)-1,1)===']') $x = substr($x,0,strlen($x)-1);
  177. $ItemLst = explode($z,$x);
  178. $ItemNbr = count($ItemLst);
  179. $Item0 = &$ItemLst[0];
  180. // Check first item
  181. if ($Item0[0]==='~') {
  182. $Item0 = substr($Item0,1);
  183. if ($this->TBS->ObjectRef!==false) {
  184. $Var = &$this->TBS->ObjectRef;
  185. $i = 0;
  186. } else {
  187. $i = $this->DataAlert('invalid query \''.$Query.'\' because property ObjectRef is not set.');
  188. }
  189. } else {
  190. if (isset($GLOBALS[$Item0])) {
  191. $Var = &$GLOBALS[$Item0];
  192. $i = 1;
  193. } else {
  194. $i = $this->DataAlert('invalid query \''.$Query.'\' because global variable \''.$Item0.'\' is not found.');
  195. }
  196. }
  197. // Check sub-items
  198. $Empty = false;
  199. while (($i!==false) and ($i<$ItemNbr) and ($Empty===false)) {
  200. $x = $ItemLst[$i];
  201. if (is_array($Var)) {
  202. if (isset($Var[$x])) {
  203. $Var = &$Var[$x];
  204. } else {
  205. $Empty = true;
  206. }
  207. } elseif (is_object($Var)) {
  208. $ArgLst = $this->TBS->f_Misc_CheckArgLst($x);
  209. if (method_exists($Var,$x)) {
  210. $f = array(&$Var,$x); unset($Var);
  211. $Var = call_user_func_array($f,$ArgLst);
  212. } elseif (property_exists(get_class($Var),$x)) {
  213. if (isset($Var->$x)) $Var = &$Var->$x;
  214. } elseif (isset($Var->$x)) {
  215. $Var = $Var->$x; // useful for overloaded property
  216. } else {
  217. $Empty = true;
  218. }
  219. } else {
  220. $i = $this->DataAlert('invalid query \''.$Query.'\' because item \''.$ItemLst[$i].'\' is neither an Array nor an Object. Its type is \''.gettype($Var).'\'.');
  221. }
  222. if ($i!==false) $i++;
  223. }
  224. // Assign data
  225. if ($i!==false) {
  226. if ($Empty) {
  227. $this->RecSet = array();
  228. } else {
  229. $this->RecSet = &$Var;
  230. }
  231. }
  232. } elseif ($this->SubType===3) { // Clear
  233. $this->RecSet = array();
  234. }
  235. // First record
  236. if ($this->RecSet!==false) {
  237. $this->RecNbr = $this->RecNumInit + count($this->RecSet);
  238. $this->FirstRec = true;
  239. $this->RecSaved = true;
  240. $this->RecSaving = false;
  241. }
  242. break;
  243. case 6: // MySQL
  244. switch ($this->SubType) {
  245. case 0: $this->RecSet = @mysql_query($Query,$this->SrcId); break;
  246. case 1: $this->RecSet = $this->SrcId; break;
  247. case 2: $this->RecSet = @mysql_query($Query); break;
  248. }
  249. if ($this->RecSet===false) $this->DataAlert('MySql error message when opening the query: '.mysql_error());
  250. break;
  251. case 1: // Num
  252. $this->RecSet = true;
  253. $this->NumMin = 1;
  254. $this->NumMax = 1;
  255. $this->NumStep = 1;
  256. if (is_array($Query)) {
  257. if (isset($Query['min'])) $this->NumMin = $Query['min'];
  258. if (isset($Query['step'])) $this->NumStep = $Query['step'];
  259. if (isset($Query['max'])) {
  260. $this->NumMax = $Query['max'];
  261. } else {
  262. $this->RecSet = $this->DataAlert('the \'num\' source is an array that has no value for the \'max\' key.');
  263. }
  264. if ($this->NumStep==0) $this->RecSet = $this->DataAlert('the \'num\' source is an array that has a step value set to zero.');
  265. } else {
  266. $this->NumMax = ceil($Query);
  267. }
  268. if ($this->RecSet) {
  269. if ($this->NumStep>0) {
  270. $this->NumVal = $this->NumMin;
  271. } else {
  272. $this->NumVal = $this->NumMax;
  273. }
  274. }
  275. break;
  276. case 2: // Text
  277. if (is_string($Query)) {
  278. $this->RecSet = &$Query;
  279. } else {
  280. $this->RecSet = ''.$Query;
  281. }
  282. break;
  283. case 3: // Custom function
  284. $FctOpen = $this->FctOpen;
  285. $this->RecSet = $FctOpen($this->SrcId,$Query);
  286. if ($this->RecSet===false) $this->DataAlert('function '.$FctOpen.'() has failed to open query {'.$Query.'}');
  287. break;
  288. case 4: // Custom method from ObjectRef
  289. $this->RecSet = call_user_func_array($this->FctOpen,array(&$this->SrcId,&$Query));
  290. if ($this->RecSet===false) $this->DataAlert('method '.get_class($this->FctOpen[0]).'::'.$this->FctOpen[1].'() has failed to open query {'.$Query.'}');
  291. break;
  292. case 5: // Custom method of object
  293. $this->RecSet = $this->SrcId->tbsdb_open($this->SrcId,$Query);
  294. if ($this->RecSet===false) $this->DataAlert('method '.get_class($this->SrcId).'::tbsdb_open() has failed to open query {'.$Query.'}');
  295. break;
  296. case 7: // PostgreSQL
  297. switch ($this->SubType) {
  298. case 0: $this->RecSet = @pg_query($this->SrcId,$Query); break;
  299. case 1: $this->RecSet = $this->SrcId; break;
  300. }
  301. if ($this->RecSet===false) $this->DataAlert('PostgreSQL error message when opening the query: '.pg_last_error($this->SrcId));
  302. break;
  303. case 8: // SQLite
  304. switch ($this->SubType) {
  305. case 0: $this->RecSet = @sqlite_query($this->SrcId,$Query); break;
  306. case 1: $this->RecSet = $this->SrcId; break;
  307. }
  308. if ($this->RecSet===false) $this->DataAlert('SQLite error message when opening the query:'.sqlite_error_string(sqlite_last_error($this->SrcId)));
  309. break;
  310. case 9: // Iterator
  311. if ($this->SubType==1) {
  312. $this->RecSet = $this->SrcId;
  313. } else { // 2 or 3
  314. $this->RecSet = $this->SrcId->getIterator();
  315. }
  316. $this->RecSet->rewind();
  317. break;
  318. }
  319. if (($this->Type===0) or ($this->Type===9)) {
  320. unset($this->RecKey); $this->RecKey = '';
  321. } else {
  322. if ($this->RecSaving) {
  323. unset($this->RecBuffer); $this->RecBuffer = array();
  324. }
  325. $this->RecKey = &$this->RecNum; // Not array: RecKey = RecNum
  326. }
  327. return ($this->RecSet!==false);
  328. }
  329. public function DataFetch() {
  330. if ($this->RecSaved) {
  331. if ($this->RecNum<$this->RecNbr) {
  332. if ($this->FirstRec) {
  333. if ($this->SubType===2) { // From string
  334. reset($this->RecSet);
  335. $this->RecKey = key($this->RecSet);
  336. $this->CurrRec = &$this->RecSet[$this->RecKey];
  337. } else {
  338. $this->CurrRec = reset($this->RecSet);
  339. $this->RecKey = key($this->RecSet);
  340. }
  341. $this->FirstRec = false;
  342. } else {
  343. if ($this->SubType===2) { // From string
  344. next($this->RecSet);
  345. $this->RecKey = key($this->RecSet);
  346. $this->CurrRec = &$this->RecSet[$this->RecKey];
  347. } else {
  348. $this->CurrRec = next($this->RecSet);
  349. $this->RecKey = key($this->RecSet);
  350. }
  351. }
  352. if ((!is_array($this->CurrRec)) and (!is_object($this->CurrRec))) $this->CurrRec = array('key'=>$this->RecKey, 'val'=>$this->CurrRec);
  353. $this->RecNum++;
  354. if ($this->OnDataOk) {
  355. if ($this->OnDataPrm) call_user_func_array($this->OnDataPrmRef,$this->OnDataArgs);
  356. if ($this->OnDataPi) $this->TBS->meth_PlugIn_RunAll($this->OnDataPiRef,$this->OnDataArgs);
  357. if ($this->SubType!==2) $this->RecSet[$this->RecKey] = $this->CurrRec; // save modifications because array reading is done without reference :(
  358. }
  359. } else {
  360. unset($this->CurrRec); $this->CurrRec = false;
  361. }
  362. return;
  363. }
  364. switch ($this->Type) {
  365. case 6: // MySQL
  366. $this->CurrRec = mysql_fetch_assoc($this->RecSet);
  367. break;
  368. case 1: // Num
  369. if (($this->NumVal>=$this->NumMin) and ($this->NumVal<=$this->NumMax)) {
  370. $this->CurrRec = array('val'=>$this->NumVal);
  371. $this->NumVal += $this->NumStep;
  372. } else {
  373. $this->CurrRec = false;
  374. }
  375. break;
  376. case 2: // Text
  377. if ($this->RecNum===0) {
  378. if ($this->RecSet==='') {
  379. $this->CurrRec = false;
  380. } else {
  381. $this->CurrRec = &$this->RecSet;
  382. }
  383. } else {
  384. $this->CurrRec = false;
  385. }
  386. break;
  387. case 3: // Custom function
  388. $FctFetch = $this->FctFetch;
  389. $this->CurrRec = $FctFetch($this->RecSet,$this->RecNum+1);
  390. break;
  391. case 4: // Custom method from ObjectRef
  392. $this->FctPrm[0] = &$this->RecSet; $this->FctPrm[1] = $this->RecNum+1;
  393. $this->CurrRec = call_user_func_array($this->FctFetch,$this->FctPrm);
  394. break;
  395. case 5: // Custom method of object
  396. $this->CurrRec = $this->SrcId->tbsdb_fetch($this->RecSet,$this->RecNum+1);
  397. break;
  398. case 7: // PostgreSQL
  399. $this->CurrRec = pg_fetch_assoc($this->RecSet);
  400. break;
  401. case 8: // SQLite
  402. $this->CurrRec = sqlite_fetch_array($this->RecSet,SQLITE_ASSOC);
  403. break;
  404. case 9: // Iterator
  405. if ($this->RecSet->valid()) {
  406. $this->CurrRec = $this->RecSet->current();
  407. $this->RecKey = $this->RecSet->key();
  408. $this->RecSet->next();
  409. } else {
  410. $this->CurrRec = false;
  411. }
  412. break;
  413. }
  414. // Set the row count
  415. if ($this->CurrRec!==false) {
  416. $this->RecNum++;
  417. if ($this->OnDataOk) {
  418. $this->OnDataArgs[1] = &$this->CurrRec; // Reference has changed if ($this->SubType===2)
  419. if ($this->OnDataPrm) call_user_func_array($this->OnDataPrmRef,$this->OnDataArgs);
  420. if ($this->OnDataPi) $this->TBS->meth_PlugIn_RunAll($this->OnDataPiRef,$this->OnDataArgs);
  421. }
  422. if ($this->RecSaving) $this->RecBuffer[$this->RecKey] = $this->CurrRec;
  423. }
  424. }
  425. public function DataClose() {
  426. $this->OnDataOk = false;
  427. $this->OnDataPrm = false;
  428. $this->OnDataPi = false;
  429. if ($this->RecSaved) return;
  430. switch ($this->Type) {
  431. case 6: mysql_free_result($this->RecSet); break;
  432. case 3: $FctClose=$this->FctClose; $FctClose($this->RecSet); break;
  433. case 4: call_user_func_array($this->FctClose,array(&$this->RecSet)); break;
  434. case 5: $this->SrcId->tbsdb_close($this->RecSet); break;
  435. case 7: pg_free_result($this->RecSet); break;
  436. }
  437. if ($this->RecSaving) {
  438. $this->RecSet = &$this->RecBuffer;
  439. $this->RecNbr = $this->RecNumInit + count($this->RecSet);
  440. $this->RecSaving = false;
  441. $this->RecSaved = true;
  442. }
  443. }
  444. }
  445. // *********************************************
  446. class clsTinyButStrong {
  447. // Public properties
  448. public $Source = '';
  449. public $Render = 3;
  450. public $TplVars = array();
  451. public $ObjectRef = false;
  452. public $NoErr = false;
  453. public $Assigned = array();
  454. // Undocumented (can change at any version)
  455. public $Version = '3.5.3';
  456. public $Charset = '';
  457. public $TurboBlock = true;
  458. public $VarPrefix = '';
  459. public $Protect = true;
  460. public $ErrCount = 0;
  461. public $ErrMsg = '';
  462. public $AttDelim = false;
  463. public $MethodsAllowed = false;
  464. // Private
  465. public $_ErrMsgName = '';
  466. public $_LastFile = '';
  467. public $_CharsetFct = false;
  468. public $_Mode = 0;
  469. public $_CurrBlock = '';
  470. public $_ChrOpen = '[';
  471. public $_ChrClose = ']';
  472. public $_ChrVal = '[val]';
  473. public $_ChrProtect = '&#91;';
  474. public $_PlugIns = array();
  475. public $_PlugIns_Ok = false;
  476. public $_piOnFrm_Ok = false;
  477. function clsTinyButStrong($Chrs='',$VarPrefix='') {
  478. if ($Chrs!=='') {
  479. $Ok = false;
  480. $Len = strlen($Chrs);
  481. if ($Len===2) { // For compatibility
  482. $this->_ChrOpen = $Chrs[0];
  483. $this->_ChrClose = $Chrs[1];
  484. $Ok = true;
  485. } else {
  486. $Pos = strpos($Chrs,',');
  487. if (($Pos!==false) and ($Pos>0) and ($Pos<$Len-1)) {
  488. $this->_ChrOpen = substr($Chrs,0,$Pos);
  489. $this->_ChrClose = substr($Chrs,$Pos+1);
  490. $Ok = true;
  491. }
  492. }
  493. if ($Ok) {
  494. $this->_ChrVal = $this->_ChrOpen.'val'.$this->_ChrClose;
  495. $this->_ChrProtect = '&#'.ord($this->_ChrOpen[0]).';'.substr($this->_ChrOpen,1);
  496. } else {
  497. $this->meth_Misc_Alert('with clsTinyButStrong() function','value \''.$Chrs.'\' is a bad tag delimitor definition.');
  498. }
  499. }
  500. $this->VarPrefix = $VarPrefix;
  501. // Links to global variables
  502. global $_TBS_FormatLst, $_TBS_UserFctLst, $_TBS_AutoInstallPlugIns;
  503. if (!isset($_TBS_FormatLst)) $_TBS_FormatLst = array();
  504. if (!isset($_TBS_UserFctLst)) $_TBS_UserFctLst = array();
  505. $this->_FormatLst = &$_TBS_FormatLst;
  506. $this->_UserFctLst = &$_TBS_UserFctLst;
  507. // Auto-installing plug-ins
  508. if (isset($_TBS_AutoInstallPlugIns)) foreach ($_TBS_AutoInstallPlugIns as $pi) $this->PlugIn(TBS_INSTALL,$pi);
  509. }
  510. // Public methods
  511. public function LoadTemplate($File,$Charset='') {
  512. if ($File==='') {
  513. $this->meth_Misc_Charset($Charset);
  514. return true;
  515. }
  516. $Ok = true;
  517. if ($this->_PlugIns_Ok) {
  518. if (isset($this->_piBeforeLoadTemplate) or isset($this->_piAfterLoadTemplate)) {
  519. // Plug-ins
  520. $ArgLst = func_get_args();
  521. $ArgLst[0] = &$File;
  522. $ArgLst[1] = &$Charset;
  523. if (isset($this->_piBeforeLoadTemplate)) $Ok = $this->meth_PlugIn_RunAll($this->_piBeforeLoadTemplate,$ArgLst);
  524. }
  525. }
  526. // Load the file
  527. if ($Ok!==false) {
  528. if (!is_null($File)) {
  529. $x = '';
  530. if (!$this->f_Misc_GetFile($x,$File,$this->_LastFile)) return $this->meth_Misc_Alert('with LoadTemplate() method','file \''.$File.'\' is not found or not readable.');
  531. if ($Charset==='+') {
  532. $this->Source .= $x;
  533. } else {
  534. $this->Source = $x;
  535. }
  536. }
  537. if ($this->_Mode==0) {
  538. if (!is_null($File)) $this->_LastFile = $File;
  539. if ($Charset!=='+') $this->TplVars = array();
  540. $this->meth_Misc_Charset($Charset);
  541. }
  542. // Automatic fields and blocks
  543. $this->meth_Merge_AutoOn($this->Source,'onload',true,true);
  544. }
  545. // Plug-ins
  546. if ($this->_PlugIns_Ok and isset($ArgLst) and isset($this->_piAfterLoadTemplate)) $Ok = $this->meth_PlugIn_RunAll($this->_piAfterLoadTemplate,$ArgLst);
  547. return $Ok;
  548. }
  549. public function GetBlockSource($BlockName,$List=false,$KeepDefTags=true,$ReplaceWith=false) {
  550. $RetVal = array();
  551. $Nbr = 0;
  552. $Pos = 0;
  553. $FieldOutside = false;
  554. $P1 = false;
  555. $Mode = ($KeepDefTags) ? 3 : 2;
  556. $PosBeg1 = 0;
  557. while ($Loc = $this->meth_Locator_FindBlockNext($this->Source,$BlockName,$Pos,'.',$Mode,$P1,$FieldOutside)) {
  558. $Nbr++;
  559. if ($Nbr==1) $PosBeg1 = $Loc->PosBeg;
  560. if ($List) $RetVal[$Nbr] = $Loc->BlockSrc;
  561. $Pos = $Loc->PosEnd;
  562. $P1 = false;
  563. }
  564. if ($Nbr==0) return false;
  565. if (!$List) $RetVal = substr($this->Source,$PosBeg1,$Pos-$PosBeg1+1);
  566. if ($ReplaceWith!==false) $this->Source = substr($this->Source,0,$PosBeg1).$ReplaceWith.substr($this->Source,$Pos+1);
  567. return $RetVal;
  568. }
  569. public function MergeBlock($BlockLst,$SrcId='assigned',$Query='') {
  570. if ($SrcId==='assigned') {
  571. $Arg = array($BlockLst,&$SrcId,&$Query);
  572. if (!$this->meth_Misc_Assign($BlockLst, $Arg, 'MergeBlock')) return 0;
  573. $BlockLst = $Arg[0]; $SrcId = &$Arg[1]; $Query = &$Arg[2];
  574. }
  575. if (is_string($BlockLst)) $BlockLst = explode(',',$BlockLst);
  576. if ($SrcId==='cond') {
  577. $Nbr = 0;
  578. foreach ($BlockLst as $Block) {
  579. $Block = trim($Block);
  580. if ($Block!=='') $Nbr += $this->meth_Merge_AutoOn($this->Source,$Block,true,true);
  581. }
  582. return $Nbr;
  583. } else {
  584. return $this->meth_Merge_Block($this->Source,$BlockLst,$SrcId,$Query,false,0);
  585. }
  586. }
  587. public function MergeField($NameLst,$Value='assigned',$IsUserFct=false,$DefaultPrm=false) {
  588. $FctCheck = $IsUserFct;
  589. if ($PlugIn = isset($this->_piOnMergeField)) $ArgPi = array('','',&$Value,0,&$this->Source,0,0);
  590. $SubStart = 0;
  591. $Ok = true;
  592. $Prm = is_array($DefaultPrm);
  593. if ( ($Value==='assigned') and ($NameLst!=='var') and ($NameLst!=='onshow') and ($NameLst!=='onload') ) {
  594. $Arg = array($NameLst,&$Value,&$IsUserFct,&$DefaultPrm);
  595. if (!$this->meth_Misc_Assign($NameLst, $Arg, 'MergeField')) return false;
  596. $NameLst = $Arg[0]; $Value = &$Arg[1]; $IsUserFct = &$Arg[2]; $DefaultPrm = &$Arg[3];
  597. }
  598. $NameLst = explode(',',$NameLst);
  599. foreach ($NameLst as $Name) {
  600. $Name = trim($Name);
  601. $Cont = false;
  602. switch ($Name) {
  603. case '': $Cont=true;break;
  604. case 'onload': $this->meth_Merge_AutoOn($this->Source,'onload',true,true);$Cont=true;break;
  605. case 'onshow': $this->meth_Merge_AutoOn($this->Source,'onshow',true,true);$Cont=true;break;
  606. case 'var': $this->meth_Merge_AutoVar($this->Source,true);$Cont=true;break;
  607. }
  608. if ($Cont) continue;
  609. if ($PlugIn) $ArgPi[0] = $Name;
  610. $PosBeg = 0;
  611. // Initilize the user function (only once)
  612. if ($FctCheck) {
  613. $FctInfo = $Value;
  614. $ErrMsg = false;
  615. if (!$this->meth_Misc_UserFctCheck($FctInfo,'f',$ErrMsg,$ErrMsg)) return $this->meth_Misc_Alert('with MergeField() method',$ErrMsg);
  616. $FctArg = array('','');
  617. $SubStart = false;
  618. $FctCheck = false;
  619. }
  620. while ($Loc = $this->meth_Locator_FindTbs($this->Source,$Name,$PosBeg,'.')) {
  621. if ($Prm) $Loc->PrmLst = array_merge($DefaultPrm,$Loc->PrmLst);
  622. // Apply user function
  623. if ($IsUserFct) {
  624. $FctArg[0] = &$Loc->SubName; $FctArg[1] = &$Loc->PrmLst;
  625. $Value = call_user_func_array($FctInfo,$FctArg);
  626. }
  627. // Plug-ins
  628. if ($PlugIn) {
  629. $ArgPi[1] = $Loc->SubName; $ArgPi[3] = &$Loc->PrmLst; $ArgPi[5] = &$Loc->PosBeg; $ArgPi[6] = &$Loc->PosEnd;
  630. $Ok = $this->meth_PlugIn_RunAll($this->_piOnMergeField,$ArgPi);
  631. }
  632. // Merge the field
  633. if ($Ok) {
  634. $PosBeg = $this->meth_Locator_Replace($this->Source,$Loc,$Value,$SubStart);
  635. } else {
  636. $PosBeg = $Loc->PosEnd;
  637. }
  638. }
  639. }
  640. }
  641. public function Show($Render=false) {
  642. $Ok = true;
  643. if ($Render===false) $Render = $this->Render;
  644. if ($this->_PlugIns_Ok) {
  645. if (isset($this->_piBeforeShow) or isset($this->_piAfterShow)) {
  646. // Plug-ins
  647. $ArgLst = func_get_args();
  648. $ArgLst[0] = &$Render;
  649. if (isset($this->_piBeforeShow)) $Ok = $this->meth_PlugIn_RunAll($this->_piBeforeShow,$ArgLst);
  650. }
  651. }
  652. if ($Ok!==false) {
  653. $this->meth_Merge_AutoOn($this->Source,'onshow',true,true);
  654. $this->meth_Merge_AutoVar($this->Source,true);
  655. }
  656. if ($this->_PlugIns_Ok and isset($ArgLst) and isset($this->_piAfterShow)) $this->meth_PlugIn_RunAll($this->_piAfterShow,$ArgLst);
  657. if ($this->_ErrMsgName!=='') $this->MergeField($this->_ErrMsgName, $this->ErrMsg);
  658. if (($Render & TBS_OUTPUT)==TBS_OUTPUT) echo $this->Source;
  659. if (($this->_Mode==0) and (($Render & TBS_EXIT)==TBS_EXIT)) exit;
  660. return $Ok;
  661. }
  662. public function PlugIn($Prm1,$Prm2=0) {
  663. if (is_numeric($Prm1)) {
  664. switch ($Prm1) {
  665. case TBS_INSTALL:
  666. $PlugInId = $Prm2;
  667. // Try to install the plug-in
  668. if (isset($this->_PlugIns[$PlugInId])) {
  669. return $this->meth_Misc_Alert('with PlugIn() method','plug-in \''.$PlugInId.'\' is already installed.');
  670. } else {
  671. $ArgLst = func_get_args();
  672. array_shift($ArgLst); array_shift($ArgLst);
  673. return $this->meth_PlugIn_Install($PlugInId,$ArgLst,false);
  674. }
  675. case TBS_ISINSTALLED:
  676. // Check if the plug-in is installed
  677. return isset($this->_PlugIns[$Prm2]);
  678. case -4: // Deactivate special plug-ins
  679. $this->_PlugIns_Ok_save = $this->_PlugIns_Ok;
  680. $this->_PlugIns_Ok = false;
  681. return true;
  682. case -5: // Deactivate OnFormat
  683. $this->_piOnFrm_Ok_save = $this->_piOnFrm_Ok;
  684. $this->_piOnFrm_Ok = false;
  685. return true;
  686. case -10: // Restore
  687. if (isset($this->_PlugIns_Ok_save)) $this->_PlugIns_Ok = $this->_PlugIns_Ok_save;
  688. if (isset($this->_piOnFrm_Ok_save)) $this->_piOnFrm_Ok = $this->_piOnFrm_Ok_save;
  689. return true;
  690. }
  691. } elseif (is_string($Prm1)) {
  692. // Plug-in's command
  693. $PlugInId = $Prm1;
  694. if (!isset($this->_PlugIns[$PlugInId])) {
  695. if (!$this->meth_PlugIn_Install($PlugInId,array(),true)) return false;
  696. }
  697. if (!isset($this->_piOnCommand[$PlugInId])) return $this->meth_Misc_Alert('with PlugIn() method','plug-in \''.$PlugInId.'\' can\'t run any command because the OnCommand event is not defined or activated.');
  698. $ArgLst = func_get_args();
  699. array_shift($ArgLst);
  700. $Ok = call_user_func_array($this->_piOnCommand[$PlugInId],$ArgLst);
  701. if (is_null($Ok)) $Ok = true;
  702. return $Ok;
  703. }
  704. return $this->meth_Misc_Alert('with PlugIn() method','\''.$Prm1.'\' is an invalid plug-in key, the type of the value is \''.gettype($Prm1).'\'.');
  705. }
  706. // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  707. function meth_Locator_FindTbs(&$Txt,$Name,$Pos,$ChrSub) {
  708. // Find a TBS Locator
  709. $PosEnd = false;
  710. $PosMax = strlen($Txt) -1;
  711. $Start = $this->_ChrOpen.$Name;
  712. do {
  713. // Search for the opening char
  714. if ($Pos>$PosMax) return false;
  715. $Pos = strpos($Txt,$Start,$Pos);
  716. // If found => next chars are analyzed
  717. if ($Pos===false) {
  718. return false;
  719. } else {
  720. $Loc = new clsTbsLocator;
  721. $ReadPrm = false;
  722. $PosX = $Pos + strlen($Start);
  723. $x = $Txt[$PosX];
  724. if ($x===$this->_ChrClose) {
  725. $PosEnd = $PosX;
  726. } elseif ($x===$ChrSub) {
  727. $Loc->SubOk = true; // it is no longer the false value
  728. $ReadPrm = true;
  729. $PosX++;
  730. } elseif (strpos(';',$x)!==false) {
  731. $ReadPrm = true;
  732. $PosX++;
  733. } else {
  734. $Pos++;
  735. }
  736. $Loc->PosBeg = $Pos;
  737. if ($ReadPrm) {
  738. $this->f_Loc_PrmRead($Txt,$PosX,false,'\'',$this->_ChrOpen,$this->_ChrClose,$Loc,$PosEnd);
  739. if ($PosEnd===false) {
  740. $this->meth_Misc_Alert('','can\'t found the end of the tag \''.substr($Txt,$Pos,$PosX-$Pos+10).'...\'.');
  741. $Pos++;
  742. }
  743. }
  744. }
  745. } while ($PosEnd===false);
  746. $Loc->PosEnd = $PosEnd;
  747. if ($Loc->SubOk) {
  748. $Loc->FullName = $Name.'.'.$Loc->SubName;
  749. $Loc->SubLst = explode('.',$Loc->SubName);
  750. $Loc->SubNbr = count($Loc->SubLst);
  751. } else {
  752. $Loc->FullName = $Name;
  753. }
  754. if ($ReadPrm and isset($Loc->PrmLst['comm'])) {
  755. $Loc->PosBeg0 = $Loc->PosBeg;
  756. $Loc->PosEnd0 = $Loc->PosEnd;
  757. $comm = $Loc->PrmLst['comm'];
  758. if (($comm===true) or ($comm==='')) {
  759. $Loc->Enlarged = $this->f_Loc_EnlargeToStr($Txt,$Loc,'<!--' ,'-->');
  760. } else {
  761. $Loc->Enlarged = $this->f_Loc_EnlargeToTag($Txt,$Loc,$comm,false);
  762. }
  763. }
  764. return $Loc;
  765. }
  766. function &meth_Locator_SectionNewBDef(&$LocR,$BlockName,$Txt,$PrmLst) {
  767. $Chk = true;
  768. $LocLst = array();
  769. $LocNbr = 0;
  770. // Cache TBS locators
  771. if ($this->TurboBlock) {
  772. $Chk = false;
  773. $Pos = 0;
  774. $PrevEnd = -1;
  775. $PrevIsAMF = false;
  776. while ($Loc = $this->meth_Locator_FindTbs($Txt,$BlockName,$Pos,'.')) {
  777. $IsAMF = false;
  778. if (($Loc->SubName==='#') or ($Loc->SubName==='$')) {
  779. $Loc->IsRecInfo = true;
  780. $Loc->RecInfo = $Loc->SubName;
  781. $Loc->SubName = '';
  782. } else {
  783. $Loc->IsRecInfo = false;
  784. }
  785. if ($Loc->PosBeg>$PrevEnd) { // No embedding
  786. if (isset($Loc->PrmLst['att'])) {
  787. $LocSrc = substr($Txt,$Loc->PosBeg,$Loc->PosEnd-$Loc->PosBeg+1);
  788. $this->f_Xml_AttFind($Txt,$Loc,true,$this->AttDelim);
  789. if ($Loc->AttForward) {
  790. $IsAMF = true;
  791. } else {
  792. for ($i=$LocNbr;$i>0;$i--) {
  793. if ($LocLst[$i]->PosEnd>=$Loc->PosBeg) {
  794. $LocNbr--;
  795. } else {
  796. $i = 0;
  797. }
  798. }
  799. }
  800. unset($Loc->PrmLst['att']);
  801. }
  802. $LocNbr++;
  803. } else {
  804. // The previous tag is embedding => no increment, then previous Loc is overwrited
  805. $Chk = true;
  806. if ($PrevIsAMF) {
  807. $l = &$LocLst[$LocNbr];
  808. $this->meth_Misc_Alert('','TBS is not able to merge the field '.$LocSrc.' because parameter \'att\' makes this fied moving forward over another TBS field.');
  809. }
  810. }
  811. $PrevEnd = $Loc->PosEnd;
  812. $PrevIsAMF = false;
  813. if ($IsAMF) {
  814. $Pos = $Loc->PrevPosBeg;
  815. $PrevIsAMF = true;
  816. } elseif ($Loc->Enlarged) { // Parameter 'comm'
  817. $Pos = $Loc->PosBeg0+1;
  818. $Loc->Enlarged = false;
  819. } else {
  820. $Pos = $Loc->PosBeg+1;
  821. }
  822. $LocLst[$LocNbr] = $Loc;
  823. }
  824. }
  825. // Create the object
  826. $o = (object) null;
  827. $o->Prm = $PrmLst;
  828. $o->LocLst = $LocLst;
  829. $o->LocNbr = $LocNbr;
  830. $o->Name = $BlockName;
  831. $o->Src = $Txt;
  832. $o->Chk = $Chk;
  833. $o->IsSerial = false;
  834. $o->AutoSub = false;
  835. $i = 1;
  836. while (isset($PrmLst['sub'.$i])) {
  837. $o->AutoSub = $i;
  838. $i++;
  839. }
  840. $LocR->BDefLst[] = &$o; // Can be usefull for plug-in
  841. return $o;
  842. }
  843. function meth_Locator_SectionAddGrp(&$LocR,$BlockName,&$BDef,$Type,$Field,$Prm) {
  844. $BDef->PrevValue = false;
  845. $BDef->Type = $Type;
  846. // Save sub items in a structure near to Locator.
  847. $Field0 = $Field;
  848. if (strpos($Field,$this->_ChrOpen)===false) $Field = $this->_ChrOpen.$BlockName.'.'.$Field.$this->_ChrClose;
  849. $BDef->FDef = &$this->meth_Locator_SectionNewBDef($LocR,$BlockName,$Field,array());
  850. if ($BDef->FDef->LocNbr==0) $this->meth_Misc_Alert('Parameter '.$Prm,'The value \''.$Field0.'\' is unvalide for this parameter.');
  851. if ($Type==='H') {
  852. if ($LocR->HeaderFound===false) {
  853. $LocR->HeaderFound = true;
  854. $LocR->HeaderNbr = 0;
  855. $LocR->HeaderDef = array(); // 1 to HeaderNbr
  856. }
  857. $i = ++$LocR->HeaderNbr;
  858. $LocR->HeaderDef[$i] = &$BDef;
  859. } else {
  860. if ($LocR->FooterFound===false) {
  861. $LocR->FooterFound = true;
  862. $LocR->FooterNbr = 0;
  863. $LocR->FooterDef = array(); // 1 to FooterNbr
  864. }
  865. $BDef->AddLastGrp = ($Type==='F');
  866. $i = ++$LocR->FooterNbr;
  867. $LocR->FooterDef[$i] = &$BDef;
  868. }
  869. }
  870. function meth_Locator_Replace(&$Txt,&$Loc,&$Value,$SubStart) {
  871. // This function enables to merge a locator with a text and returns the position just after the replaced block
  872. // This position can be useful because we don't know in advance how $Value will be replaced.
  873. // Found the value if there is a subname
  874. if (($SubStart!==false) and $Loc->SubOk) {
  875. for ($i=$SubStart;$i<$Loc->SubNbr;$i++) {
  876. $x = $Loc->SubLst[$i]; // &$Loc... brings an error with Event Example, I don't know why.
  877. if (is_array($Value)) {
  878. if (isset($Value[$x])) {
  879. $Value = &$Value[$x];
  880. } elseif (array_key_exists($x,$Value)) {// can happens when value is NULL
  881. $Value = &$Value[$x];
  882. } else {
  883. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'item \''.$x.'\' is not an existing key in the array.',true);
  884. unset($Value); $Value = ''; break;
  885. }
  886. } elseif (is_object($Value)) {
  887. $ArgLst = $this->f_Misc_CheckArgLst($x);
  888. if (method_exists($Value,$x)) {
  889. if ($this->MethodsAllowed or !in_array(strtok($Loc->FullName,'.'),array('onload','onshow','var')) ) {
  890. $x = call_user_func_array(array(&$Value,$x),$ArgLst);
  891. } else {
  892. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'\''.$x.'\' is a method and the current TBS settings do not allow to call methods on automatic fields.',true);
  893. $x = '';
  894. }
  895. } elseif (property_exists($Value,$x)) {
  896. $x = &$Value->$x;
  897. } elseif (isset($Value->$x)) {
  898. $x = $Value->$x; // useful for overloaded property
  899. } else {
  900. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'item '.$x.'\' is neither a method nor a property in the class \''.get_class($Value).'\'.',true);
  901. unset($Value); $Value = ''; break;
  902. }
  903. $Value = &$x; unset($x); $x = '';
  904. } else {
  905. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'item before \''.$x.'\' is neither an object nor an array. Its type is '.gettype($Value).'.',true);
  906. unset($Value); $Value = ''; break;
  907. }
  908. }
  909. }
  910. $CurrVal = $Value; // Unlink
  911. if (isset($Loc->PrmLst['onformat'])) {
  912. if ($Loc->FirstMerge) {
  913. $Loc->OnFrmInfo = $Loc->PrmLst['onformat'];
  914. $Loc->OnFrmArg = array($Loc->FullName,'',&$Loc->PrmLst,&$this);
  915. $ErrMsg = false;
  916. if (!$this->meth_Misc_UserFctCheck($Loc->OnFrmInfo,'f',$ErrMsg,$ErrMsg)) {
  917. unset($Loc->PrmLst['onformat']);
  918. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'(parameter onformat) '.$ErrMsg);
  919. $Loc->OnFrmInfo = 'pi'; // Execute the function pi() just to avoid extra error messages
  920. }
  921. } else {
  922. $Loc->OnFrmArg[3] = &$this; // bugs.php.net/51174
  923. }
  924. $Loc->OnFrmArg[1] = &$CurrVal;
  925. if (isset($Loc->PrmLst['subtpl'])) {
  926. $this->meth_Misc_ChangeMode(true,$Loc,$CurrVal);
  927. call_user_func_array($Loc->OnFrmInfo,$Loc->OnFrmArg);
  928. $this->meth_Misc_ChangeMode(false,$Loc,$CurrVal);
  929. $Loc->ConvProtect = false;
  930. $Loc->ConvStr = false;
  931. } else {
  932. call_user_func_array($Loc->OnFrmInfo,$Loc->OnFrmArg);
  933. }
  934. }
  935. if ($Loc->FirstMerge) {
  936. if (isset($Loc->PrmLst['frm'])) {
  937. $Loc->ConvMode = 0; // Frm
  938. $Loc->ConvProtect = false;
  939. } else {
  940. // Analyze parameter 'htmlconv'
  941. if (isset($Loc->PrmLst['htmlconv'])) {
  942. $x = strtolower($Loc->PrmLst['htmlconv']);
  943. $x = '+'.str_replace(' ','',$x).'+';
  944. if (strpos($x,'+esc+')!==false) {$this->f_Misc_ConvSpe($Loc); $Loc->ConvStr = false; $Loc->ConvEsc = true; }
  945. if (strpos($x,'+wsp+')!==false) {$this->f_Misc_ConvSpe($Loc); $Loc->ConvWS = true; }
  946. if (strpos($x,'+js+')!==false) {$this->f_Misc_ConvSpe($Loc); $Loc->ConvStr = false; $Loc->ConvJS = true; }
  947. if (strpos($x,'+url+')!==false) {$this->f_Misc_ConvSpe($Loc); $Loc->ConvStr = false; $Loc->ConvUrl = true; }
  948. if (strpos($x,'+no+')!==false) $Loc->ConvStr = false;
  949. if (strpos($x,'+yes+')!==false) $Loc->ConvStr = true;
  950. if (strpos($x,'+nobr+')!==false) {$Loc->ConvStr = true; $Loc->ConvBr = false; }
  951. } else {
  952. if ($this->Charset===false) $Loc->ConvStr = false; // No conversion
  953. }
  954. // Analyze parameter 'protect'
  955. if (isset($Loc->PrmLst['protect'])) {
  956. $x = strtolower($Loc->PrmLst['protect']);
  957. if ($x==='no') {
  958. $Loc->ConvProtect = false;
  959. } elseif ($x==='yes') {
  960. $Loc->ConvProtect = true;
  961. }
  962. } elseif ($this->Protect===false) {
  963. $Loc->ConvProtect = false;
  964. }
  965. }
  966. if ($Loc->Ope = isset($Loc->PrmLst['ope'])) {
  967. $OpeLst = explode(',',$Loc->PrmLst['ope']);
  968. $Loc->OpeAct = array();
  969. $Loc->OpeArg = array();
  970. foreach ($OpeLst as $i=>$ope) {
  971. if ($ope==='list') {
  972. $Loc->OpeAct[$i] = 1;
  973. $Loc->OpePrm[$i] = (isset($Loc->PrmLst['valsep'])) ? $Loc->PrmLst['valsep'] : ',';
  974. } elseif ($ope==='minv') {
  975. $Loc->OpeAct[$i] = 11;
  976. $Loc->MSave = $Loc->MagnetId;
  977. } else {
  978. $x = substr($ope,0,4);
  979. if ($x==='max:') {
  980. if (isset($Loc->PrmLst['maxhtml'])) {$Loc->OpeAct[$i]=2;} elseif (isset($Loc->PrmLst['maxutf8'])) {$Loc->OpeAct[$i]=4;} else {$Loc->OpeAct[$i]=3;}
  981. $Loc->OpePrm[$i] = intval(trim(substr($ope,4)));
  982. $Loc->OpeEnd = (isset($Loc->PrmLst['maxend'])) ? $Loc->PrmLst['maxend'] : '...';
  983. if ($Loc->OpePrm[$i]<=0) $Loc->Ope = false;
  984. } elseif ($x==='mod:') {$Loc->OpeAct[$i] = 5; $Loc->OpePrm[$i] = '0'+trim(substr($ope,4));
  985. } elseif ($x==='add:') {$Loc->OpeAct[$i] = 6; $Loc->OpePrm[$i] = '0'+trim(substr($ope,4));
  986. } elseif ($x==='mul:') {$Loc->OpeAct[$i] = 7; $Loc->OpePrm[$i] = '0'+trim(substr($ope,4));
  987. } elseif ($x==='div:') {$Loc->OpeAct[$i] = 8; $Loc->OpePrm[$i] = '0'+trim(substr($ope,4));
  988. } elseif ($x==='mok:') {$Loc->OpeAct[$i] = 9; $Loc->OpeMOK[] = trim(substr($ope,4)); $Loc->MSave = $Loc->MagnetId;
  989. } elseif ($x==='mko:') {$Loc->OpeAct[$i] =10; $Loc->OpeMKO[] = trim(substr($ope,4)); $Loc->MSave = $Loc->MagnetId;
  990. } elseif ($x==='nif:') {$Loc->OpeAct[$i] =12; $Loc->OpePrm[$i] = trim(substr($ope,4));
  991. } elseif (isset($this->_piOnOperation)) {
  992. $Loc->OpeAct[$i] = 0;
  993. $Loc->OpePrm[$i] = $ope;
  994. $Loc->OpeArg[$i] = array($Loc->FullName,&$CurrVal,&$Loc->PrmLst,&$Txt,$Loc->PosBeg,$Loc->PosEnd,&$Loc);
  995. $Loc->PrmLst['_ope'] = $Loc->PrmLst['ope'];
  996. } elseif (!isset($Loc->PrmLst['noerr'])) {
  997. $this->meth_Misc_Alert($Loc,'parameter ope doesn\'t support value \''.$ope.'\'.',true);
  998. }
  999. }
  1000. }
  1001. }
  1002. $Loc->FirstMerge = false;
  1003. }
  1004. $ConvProtect = $Loc->ConvProtect;
  1005. // Plug-in OnFormat
  1006. if ($this->_piOnFrm_Ok) {
  1007. if (isset($Loc->OnFrmArgPi)) {
  1008. $Loc->OnFrmArgPi[1] = &$CurrVal;
  1009. $Loc->OnFrmArgPi[3] = &$this; // bugs.php.net/51174
  1010. } else {
  1011. $Loc->OnFrmArgPi = array($Loc->FullName,&$CurrVal,&$Loc->PrmLst,&$this);
  1012. }
  1013. $this->meth_PlugIn_RunAll($this->_piOnFormat,$Loc->OnFrmArgPi);
  1014. }
  1015. // Operation
  1016. if ($Loc->Ope) {
  1017. foreach ($Loc->OpeAct as $i=>$ope) {
  1018. switch ($ope) {
  1019. case 0:
  1020. $Loc->PrmLst['ope'] = $Loc->OpePrm[$i]; // for compatibility
  1021. $OpeArg = &$Loc->OpeArg[$i];
  1022. $OpeArg[1] = &$CurrVal; $OpeArg[3] = &$Txt;
  1023. if (!$this->meth_PlugIn_RunAll($this->_piOnOperation,$OpeArg)) return $Loc->PosBeg;
  1024. break;
  1025. case 1: if (is_array($CurrVal)) $CurrVal = implode($Loc->OpePrm[$i],$CurrVal); break;
  1026. case 2: if (strlen(''.$CurrVal)>$Loc->OpePrm[$i]) $this->f_Xml_Max($CurrVal,$Loc->OpePrm[$i],$Loc->OpeEnd); break;
  1027. case 3: if (strlen(''.$CurrVal)>$Loc->OpePrm[$i]) $CurrVal = substr(''.$CurrVal,0,$Loc->OpePrm[$i]).$Loc->OpeEnd; break;
  1028. case 4: if (strlen(''.$CurrVal)>$Loc->OpePrm[$i]) $CurrVal = mb_substr(''.$CurrVal,0,$Loc->OpePrm[$i],'UTF-8').$Loc->OpeEnd; break;
  1029. case 5: $CurrVal = ('0'+$CurrVal) % $Loc->OpePrm[$i]; break;
  1030. case 6: $CurrVal = ('0'+$CurrVal) + $Loc->OpePrm[$i]; break;
  1031. case 7: $CurrVal = ('0'+$CurrVal) * $Loc->OpePrm[$i]; break;
  1032. case 8: $CurrVal = ('0'+$CurrVal) / $Loc->OpePrm[$i]; break;
  1033. case 9; case 10:
  1034. if ($ope===9) {
  1035. $CurrVal = (in_array((string)$CurrVal,$Loc->OpeMOK)) ? ' ' : '';
  1036. } else {
  1037. $CurrVal = (in_array((string)$CurrVal,$Loc->OpeMKO)) ? '' : ' ';
  1038. } // no break here
  1039. case 11:
  1040. if ((string)$CurrVal==='') {
  1041. if ($Loc->MagnetId===0) $Loc->MagnetId = $Loc->MSave;
  1042. } else {
  1043. if ($Loc->MagnetId!==0) {
  1044. $Loc->MSave = $Loc->MagnetId;
  1045. $Loc->MagnetId = 0;
  1046. }
  1047. $CurrVal = '';
  1048. }
  1049. break;
  1050. case 12: if ((string)$CurrVal===$Loc->OpePrm[$i]) $CurrVal = ''; break;
  1051. }
  1052. }
  1053. }
  1054. // String conversion or format
  1055. if ($Loc->ConvMode===1) { // Usual string conversion
  1056. if (!is_string($CurrVal)) $CurrVal =(string)$CurrVal; // (string) is faster than strval() and settype()
  1057. if ($Loc->ConvStr) $this->meth_Conv_Str($CurrVal,$Loc->ConvBr);
  1058. } elseif ($Loc->ConvMode===0) { // Format
  1059. $CurrVal = $this->meth_Misc_Format($CurrVal,$Loc->PrmLst);
  1060. } elseif ($Loc->ConvMode===2) { // Special string conversion
  1061. if (!is_string($CurrVal)) $CurrVal = (string)$CurrVal;
  1062. if ($Loc->ConvStr) $this->meth_Conv_Str($CurrVal,$Loc->ConvBr);
  1063. if ($Loc->ConvEsc) $CurrVal = str_replace('\'','\'\'',$CurrVal);
  1064. if ($Loc->ConvWS) {
  1065. $check = ' ';
  1066. $nbsp = '&nbsp;';
  1067. do {
  1068. $pos = strpos($CurrVal,$check);
  1069. if ($pos!==false) $CurrVal = substr_replace($CurrVal,$nbsp,$pos,1);
  1070. } while ($pos!==false);
  1071. }
  1072. if ($Loc->ConvJS) {
  1073. $CurrVal = addslashes($CurrVal); // apply to ('), ("), (\) and (null)
  1074. $CurrVal = str_replace(array("\n","\r","\t"),array('\n','\r','\t'),$CurrVal);
  1075. }
  1076. if ($Loc->ConvUrl) $CurrVal = urlencode($CurrVal);
  1077. }
  1078. // if/then/else process, there may be several if/then
  1079. if ($Loc->PrmIfNbr) {
  1080. $z = false;
  1081. $i = 1;
  1082. while ($i!==false) {
  1083. if ($Loc->PrmIfVar[$i]) $Loc->PrmIfVar[$i] = $this->meth_Merge_AutoVar($Loc->PrmIf[$i],true);
  1084. $x = str_replace($this->_ChrVal,$CurrVal,$Loc->PrmIf[$i]);
  1085. if ($this->f_Misc_CheckCondition($x)) {
  1086. if (isset($Loc->PrmThen[$i])) {
  1087. if ($Loc->PrmThenVar[$i]) $Loc->PrmThenVar[$i] = $this->meth_Merge_AutoVar($Loc->PrmThen[$i],true);
  1088. $z = $Loc->PrmThen[$i];
  1089. }
  1090. $i = false;
  1091. } else {
  1092. $i++;
  1093. if ($i>$Loc->PrmIfNbr) {
  1094. if (isset($Loc->PrmLst['else'])) {
  1095. if ($Loc->PrmElseVar) $Loc->PrmElseVar = $this->meth_Merge_AutoVar($Loc->PrmLst['else'],true);
  1096. $z =$Loc->PrmLst['else'];
  1097. }
  1098. $i = false;
  1099. }
  1100. }
  1101. }
  1102. if ($z!==false) {
  1103. if ($ConvProtect) {
  1104. $CurrVal = str_replace($this->_ChrOpen,$this->_ChrProtect,$CurrVal); // TBS protection
  1105. $ConvProtect = false;
  1106. }
  1107. $CurrVal = str_replace($this->_ChrVal,$CurrVal,$z);
  1108. }
  1109. }
  1110. if (isset($Loc->PrmLst['file'])) {
  1111. $x = $Loc->PrmLst['file'];
  1112. if ($x===true) $x = $CurrVal;
  1113. $this->meth_Merge_AutoVar($x,false);
  1114. $x = trim(str_replace($this->_ChrVal,$CurrVal,$x));
  1115. $CurrVal = '';
  1116. if ($x!=='') {
  1117. if ($this->f_Misc_GetFile($CurrVal,$x,$this->_LastFile)) {
  1118. if (isset($Loc->PrmLst['getbody'])) $CurrVal = $this->f_Xml_GetPart($CurrVal,$Loc->PrmLst['getbody'],true);
  1119. if (isset($Loc->PrmLst['rename'])) $this->meth_Locator_Rename($CurrVal, $Loc->PrmLst['rename']);
  1120. } else {
  1121. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'the file \''.$x.'\' given by parameter file is not found or not readable.',true);
  1122. }
  1123. $ConvProtect = false;
  1124. }
  1125. }
  1126. if (isset($Loc->PrmLst['script'])) {// Include external PHP script
  1127. $x = $Loc->PrmLst['script'];
  1128. if ($x===true) $x = $CurrVal;
  1129. $this->meth_Merge_AutoVar($x,false);
  1130. $x = trim(str_replace($this->_ChrVal,$CurrVal,$x));
  1131. if ($x!=='') {
  1132. $this->_Subscript = $x;
  1133. $this->CurrPrm = &$Loc->PrmLst;
  1134. $sub = isset($Loc->PrmLst['subtpl']);
  1135. if ($sub) $this->meth_Misc_ChangeMode(true,$Loc,$CurrVal);
  1136. if ($this->meth_Misc_RunSubscript($CurrVal,$Loc->PrmLst)===false) {
  1137. if (!isset($Loc->PrmLst['noerr'])) $this->meth_Misc_Alert($Loc,'the file \''.$x.'\' given by parameter script is not found or not readable.',true);
  1138. }
  1139. if ($sub) $this->meth_Misc_ChangeMode(false,$Loc,$CurrVal);
  1140. if (isset($Loc->PrmLst['getbody'])) $CurrVal = $this->f_Xml_GetPart($CurrVal,$Loc->PrmLst['getbody'],true);
  1141. if (isset($Loc->PrmLst['rename'])) $this->meth_Locator_Rename($CurrVal, $Loc->PrmLst['rename']);
  1142. unset($this->CurrPrm);
  1143. $ConvProtect = false;
  1144. }
  1145. }
  1146. if (isset($Loc->PrmLst['att'])) $this->f_Xml_AttFind($Txt,$Loc,true,$this->AttDelim);
  1147. // Case when it's an empty string
  1148. if ($CurrVal==='') {
  1149. if ($Loc->MagnetId===false) {
  1150. if (isset($Loc->PrmLst['.'])) {
  1151. $Loc->MagnetId = -1;
  1152. } elseif (isset($Loc->PrmLst['ifempty'])) {
  1153. $Loc->MagnetId = -2;
  1154. } elseif (isset($Loc->PrmLst['magnet'])) {
  1155. $Loc->MagnetId = 1;
  1156. $Loc->PosBeg0 = $Loc->PosBeg;
  1157. $Loc->PosEnd0 = $Loc->PosEnd;
  1158. if ($Loc->PrmLst['magnet']==='#') {
  1159. if (isset($Loc->AttBeg)) {
  1160. $Loc->MagnetId = -3;
  1161. } else {
  1162. $this->meth_Misc_Alert($Loc,'parameter \'magnet=#\' cannot be processed because parameter \'att\' is not set or the attribute is not found.',true);
  1163. }
  1164. } elseif (isset($Loc->PrmLst['mtype'])) {
  1165. switch ($Loc->PrmLst['mtype']) {
  1166. case 'm+m': $Loc->MagnetId = 2; break;
  1167. case 'm*': $Loc->MagnetId = 3; break;
  1168. case '*m': $Loc->MagnetId = 4; break;
  1169. }
  1170. }
  1171. } elseif (isset($Loc->PrmLst['attadd'])) {
  1172. // In order to delete extra space
  1173. $Loc->PosBeg0 = $Loc->PosBeg;
  1174. $Loc->PosEnd0 = $Loc->PosEnd;
  1175. $Loc->MagnetId = 5;
  1176. } else {
  1177. $Loc->MagnetId = 0;
  1178. }
  1179. }
  1180. switch ($Loc->MagnetId) {
  1181. case 0: break;
  1182. case -1: $CurrVal = '&nbsp;'; break; // Enables to avoid null cells in HTML tables
  1183. case -2: $CurrVal = $Loc->PrmLst['ifempty']; break;
  1184. case -3: $Loc->Enlarged = true; $Loc->PosBeg = $Loc->AttBegM; $Loc->PosEnd = $Loc->AttEnd; break;
  1185. case 1:
  1186. $Loc->Enlarged = true;
  1187. $this->f_Loc_EnlargeToTag($Txt,$Loc,$Loc->PrmLst['magnet'],false);
  1188. break;
  1189. case 2:
  1190. $Loc->Enlarged = true;
  1191. $CurrVal = $this->f_Loc_EnlargeToTag($Txt,$Loc,$Loc->PrmLst['magnet'],true);
  1192. break;
  1193. case 3:
  1194. $Loc->Enlarged = true;
  1195. $Loc2 = $this->f_Xml_FindTag($Txt,$Loc->PrmLst['magnet'],true,$Loc->PosBeg,false,1,false);
  1196. if ($Loc2!==false) {
  1197. $Loc->PosBeg = $Loc2->PosBeg;
  1198. if ($Loc->PosEnd<$Loc2->PosEnd) $Loc->PosEnd = $Loc2->PosEnd;
  1199. }
  1200. break;
  1201. case 4:
  1202. $Loc->Enlarged = true;
  1203. $Loc2 = $this->f_Xml_FindTag($Txt,$Loc->PrmLst['magnet'],true,$Loc->PosBeg,true,1,false);
  1204. if ($Loc2!==false) $Loc->PosEnd = $Loc2->PosEnd;
  1205. break;
  1206. case 5:
  1207. $Loc->Enlarged = true;
  1208. if (substr($Txt,$Loc->PosBeg-1,1)==' ') $Loc->PosBeg--;
  1209. break;
  1210. }
  1211. $NewEnd = $Loc->PosBeg; // Useful when mtype='m+m'
  1212. } else {
  1213. if ($ConvProtect) $CurrVal = str_replace($this->_ChrOpen,$this->_ChrProtect,$CurrVal); // TBS protection
  1214. $NewEnd = $Loc->PosBeg + strlen($CurrVal);
  1215. }
  1216. $Txt = substr_replace($Txt,$CurrVal,$Loc->PosBeg,$Loc->PosEnd-$Loc->PosBeg+1);
  1217. return $NewEnd; // Return the new end position of the field
  1218. }
  1219. function meth_Locator_FindBlockNext(&$Txt,$BlockName,$PosBeg,$ChrSub,$Mode,&$P1,&$FieldBefore) {
  1220. // Return the first block locator just after the PosBeg position
  1221. // Mode = 1 : Merge_Auto => doesn't save $Loc->BlockSrc, save the bounds of TBS Def tags instead, return also fields
  1222. // Mode = 2 : FindBlockLst or GetBlockSource => save $Loc->BlockSrc without TBS Def tags
  1223. // Mode = 3 : GetBlockSource => save $Loc->BlockSrc with TBS Def tags
  1224. $SearchDef = true;
  1225. $FirstField = false;
  1226. // Search for the first tag with parameter "block"
  1227. while ($SearchDef and ($Loc = $this->meth_Locator_FindTbs($Txt,$BlockName,$PosBeg,$ChrSub))) {
  1228. if (isset($Loc->PrmLst['block'])) {
  1229. if (isset($Loc->PrmLst['p1'])) {
  1230. if ($P1) return false;
  1231. $P1 = true;
  1232. }
  1233. $Block = $Loc->PrmLst['block'];
  1234. $SearchDef = false;
  1235. } elseif ($Mode===1) {
  1236. return $Loc;
  1237. } elseif ($FirstField===false) {
  1238. $FirstField = $Loc;
  1239. }
  1240. $PosBeg = $Loc->PosEnd;
  1241. }
  1242. if ($SearchDef) {
  1243. if ($FirstField!==false) $FieldBefore = true;
  1244. return false;
  1245. }
  1246. $Loc->PosDefBeg = -1;
  1247. if ($Block==='begin') { // Block definied using begin/end
  1248. if (($FirstField!==false) and ($FirstField->PosEnd<$Loc->PosBeg)) $FieldBefore = true;
  1249. $Opened = 1;
  1250. while ($Loc2 = $this->meth_Locator_FindTbs($Txt,$BlockName,$PosBeg,$ChrSub)) {
  1251. if (isset($Loc2->PrmLst['block'])) {
  1252. switch ($Loc2->PrmLst['block']) {
  1253. case 'end': $Opened--; break;
  1254. case 'begin': $Opened++; break;
  1255. }
  1256. if ($Opened==0) {
  1257. if ($Mode===1) {
  1258. $Loc->PosBeg2 = $Loc2->PosBeg;
  1259. $Loc->PosEnd2 = $Loc2->PosEnd;
  1260. } else {
  1261. if ($Mode===2) {
  1262. $Loc->BlockSrc = substr($Txt,$Loc->PosEnd+1,$Loc2->PosBeg-$Loc->PosEnd-1);
  1263. } else {
  1264. $Loc->BlockSrc = substr($Txt,$Loc->PosBeg,$Loc2->PosEnd-$Loc->PosBeg+1);
  1265. }
  1266. $Loc->PosEnd = $Loc2->PosEnd;
  1267. }
  1268. $Loc->BlockFound = true;
  1269. return $Loc;
  1270. }
  1271. }
  1272. $PosBeg = $Loc2->PosEnd;
  1273. }
  1274. return $this->meth_Misc_Alert($Loc,'a least one tag with parameter \'block=end\' is missing.',false,'in block\'s definition');
  1275. }
  1276. if ($Mode===1) {
  1277. $Loc->PosBeg2 = false;
  1278. } else {
  1279. $beg = $Loc->PosBeg;
  1280. $end = $Loc->PosEnd;
  1281. if ($this->f_Loc_EnlargeToTag($Txt,$Loc,$Block,false)===false) return $this->meth_Misc_Alert($Loc,'at least one tag corresponding to '.$Loc->PrmLst['block'].' is not found. Check opening tags, closing tags and embedding levels.',false,'in block\'s definition');
  1282. if ($Loc->SubOk or ($Mode===3)) {
  1283. $Loc->BlockSrc = substr($Txt,$Loc->PosBeg,$Loc->PosEnd-$Loc->PosBeg+1);
  1284. $Loc->PosDefBeg = $beg - $Loc->PosBeg;
  1285. $Loc->PosDefEnd = $end - $Loc->PosBeg;
  1286. } else {
  1287. $Loc->BlockSrc = substr($Txt,$Loc->PosBeg,$beg-$Loc->PosBeg).substr($Txt,$end+1,$Loc->PosEnd-$end);
  1288. }
  1289. }
  1290. $Loc->BlockFound = true;
  1291. if (($FirstField!==false) and ($FirstField->PosEnd<$Loc->PosBeg)) $FieldBefore = true;
  1292. return $Loc; // methods return by ref by default
  1293. }
  1294. function meth_Locator_Rename(&$Txt, $Replace) {
  1295. // Rename or delete TBS tags names
  1296. if (is_string($Replace)) $Replace = explode(',',$Replace);
  1297. foreach ($Replace as $x) {
  1298. if (is_string($x)) $x = explode('=', $x);
  1299. if (count($x)==2) {
  1300. $old = trim($x[0]);
  1301. $new = trim($x[1]);
  1302. if ($old!=='') {
  1303. if ($new==='') {
  1304. $q = false;
  1305. $s = 'clear';
  1306. $this->meth_Merge_Block($Txt, $old, $s, $q, false, false);
  1307. } else {
  1308. $old = $this->_ChrOpen.$old;
  1309. $old = array($old.'.', $old.' ', $old.';');
  1310. $new = $this->_ChrOpen.$new;
  1311. $new = array($new.'.', $new.' ', $new.';');
  1312. $Txt = str_replace($old,$new,$Txt);
  1313. }
  1314. }
  1315. }
  1316. }
  1317. }
  1318. function meth_Locator_FindBlockLst(&$Txt,$BlockName,$Pos,$SpePrm) {
  1319. // Return a locator object covering all block definitions, even if there is no block definition found.
  1320. $LocR = new clsTbsLocator;
  1321. $LocR->P1 = false;
  1322. $LocR->FieldOutside = false;
  1323. $LocR->FOStop = false;
  1324. $LocR->BDefLst = array();
  1325. $LocR->NoData = false;
  1326. $LocR->Special = false;
  1327. $LocR->HeaderFound = false;
  1328. $LocR->FooterFound = false;
  1329. $LocR->SerialEmpty = false;
  1330. $LocR->GrpBreak = false; // Only for plug-ins
  1331. $LocR->WhenFound = false;
  1332. $LocR->WhenDefault = false;
  1333. $LocR->SectionNbr = 0; // Normal sections
  1334. $LocR->SectionLst = array(); // 1 to SectionNbr
  1335. $BDef = false;
  1336. $ParentLst = array();
  1337. $Pid = 0;
  1338. do {
  1339. if ($BlockName==='') {
  1340. $Loc = false;
  1341. } else {
  1342. $Loc = $this->meth_Locator_FindBlockNext($Txt,$BlockName,$Pos,'.',2,$LocR->P1,$LocR->FieldOutside);
  1343. }
  1344. if ($Loc===false) {
  1345. if ($Pid>0) { // parentgrp mode => disconnect $Txt from the source
  1346. $Parent = &$ParentLst[$Pid];
  1347. $Src = $Txt;
  1348. $Txt = &$Parent->Txt;
  1349. if ($LocR->BlockFound) {
  1350. // Redefine the Header block
  1351. $Parent->Src = substr($Src,0,$LocR->PosBeg);
  1352. // Add a Footer block
  1353. $BDef = &$this->meth_Locator_SectionNewBDef($LocR,$BlockName,substr($Src,$LocR->PosEnd+1),$Parent->Prm);
  1354. $this->meth_Locator_SectionAddGrp($LocR,$BlockName,$BDef,'F',$Parent->Fld,'parentgrp');
  1355. }
  1356. // Now go down to previous level
  1357. $Pos = $Parent->Pos;
  1358. $LocR->PosBeg = $Parent->Beg;
  1359. $LocR->PosEnd = $Parent->End;
  1360. $LocR->BlockFound = true;
  1361. unset($Parent);
  1362. unset($ParentLst[$Pid]);
  1363. $Pid--;
  1364. $Loc = true;
  1365. }
  1366. } else {
  1367. $Pos = $Loc->PosEnd;
  1368. // Define the block limits
  1369. if ($LocR->BlockFound) {
  1370. if ( $LocR->PosBeg > $Loc->PosBeg ) $LocR->PosBeg = $Loc->PosBeg;
  1371. if ( $LocR->PosEnd < $Loc->PosEnd ) $LocR->PosEnd = $Loc->PosEnd;
  1372. } else {
  1373. $LocR->BlockFound = true;
  1374. $LocR->PosBeg = $Loc->PosBeg;
  1375. $LocR->PosEnd = $Loc->PosEnd;
  1376. }
  1377. // Merge block parameters
  1378. if (count($Loc->PrmLst)>0) $LocR->PrmLst = array_merge($LocR->PrmLst,$Loc->PrmLst);
  1379. // Force dynamic parameter to be cachable
  1380. if ($Loc->PosDefBeg>=0) {
  1381. $dynprm = array('when','headergrp','footergrp','parentgrp');
  1382. foreach($dynprm as $dp) {
  1383. $n = 0;
  1384. if ((isset($Loc->PrmLst[$dp])) and (strpos($Loc->PrmLst[$dp],$this->_ChrOpen.$BlockName)!==false)) {
  1385. $n++;
  1386. if ($n==1) {
  1387. $len = $Loc->PosDefEnd - $Loc->PosDefBeg + 1;
  1388. $x = substr($Loc->BlockSrc,$Loc->PosDefBeg,$len);
  1389. }
  1390. $x = str_replace($Loc->PrmLst[$dp],'',$x);
  1391. }
  1392. if ($n>0) $Loc->BlockSrc = substr_replace($Loc->BlockSrc,$x,$Loc->PosDefBeg,$len);
  1393. }
  1394. }
  1395. // Save the block and cache its …

Large files files are truncated, but you can click here to view the full file