PageRenderTime 37ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/manager/cacheextender/orig/document.parser.class.inc.php

https://github.com/good-web-master/modx.evo.custom
PHP | 2884 lines | 2423 code | 213 blank | 248 comment | 589 complexity | 744655921c001c01b362ba6476c44646 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * MODx Document Parser
  4. * Function: This class contains the main document parsing functions
  5. *
  6. */
  7. class DocumentParser {
  8. var $db; // db object
  9. var $event, $Event; // event object
  10. var $pluginEvent;
  11. var $config= null;
  12. var $rs;
  13. var $result;
  14. var $sql;
  15. var $table_prefix;
  16. var $debug;
  17. var $documentIdentifier;
  18. var $documentMethod;
  19. var $documentGenerated;
  20. var $documentContent;
  21. var $tstart;
  22. var $minParserPasses;
  23. var $maxParserPasses;
  24. var $documentObject;
  25. var $templateObject;
  26. var $snippetObjects;
  27. var $stopOnNotice;
  28. var $executedQueries;
  29. var $queryTime;
  30. var $currentSnippet;
  31. var $documentName;
  32. var $aliases;
  33. var $visitor;
  34. var $entrypage;
  35. var $documentListing;
  36. var $dumpSnippets;
  37. var $chunkCache;
  38. var $snippetCache;
  39. var $contentTypes;
  40. var $dumpSQL;
  41. var $queryCode;
  42. var $virtualDir;
  43. var $placeholders;
  44. var $sjscripts;
  45. var $jscripts;
  46. var $loadedjscripts;
  47. var $documentMap;
  48. var $forwards= 3;
  49. // constructor
  50. function DocumentParser() {
  51. $this->loadExtension('DBAPI') or die('Could not load DBAPI class.'); // load DBAPI class
  52. $this->dbConfig= & $this->db->config; // alias for backward compatibility
  53. $this->jscripts= array ();
  54. $this->sjscripts= array ();
  55. $this->loadedjscripts= array ();
  56. // events
  57. $this->event= new SystemEvent();
  58. $this->Event= & $this->event; //alias for backward compatibility
  59. $this->pluginEvent= array ();
  60. // set track_errors ini variable
  61. @ ini_set("track_errors", "1"); // enable error tracking in $php_errormsg
  62. }
  63. // loads an extension from the extenders folder
  64. function loadExtension($extname) {
  65. global $database_type;
  66. switch ($extname) {
  67. // Database API
  68. case 'DBAPI' :
  69. if (!include_once MODX_BASE_PATH . 'manager/includes/extenders/dbapi.' . $database_type . '.class.inc.php')
  70. return false;
  71. $this->db= new DBAPI;
  72. return true;
  73. break;
  74. // Manager API
  75. case 'ManagerAPI' :
  76. if (!include_once MODX_BASE_PATH . 'manager/includes/extenders/manager.api.class.inc.php')
  77. return false;
  78. $this->manager= new ManagerAPI;
  79. return true;
  80. break;
  81. default :
  82. return false;
  83. }
  84. }
  85. function getMicroTime() {
  86. list ($usec, $sec)= explode(' ', microtime());
  87. return ((float) $usec + (float) $sec);
  88. }
  89. function sendRedirect($url, $count_attempts= 0, $type= '', $responseCode= '') {
  90. if (empty ($url)) {
  91. return false;
  92. } else {
  93. if ($count_attempts == 1) {
  94. // append the redirect count string to the url
  95. $currentNumberOfRedirects= isset ($_REQUEST['err']) ? $_REQUEST['err'] : 0;
  96. if ($currentNumberOfRedirects > 3) {
  97. $this->messageQuit('Redirection attempt failed - please ensure the document you\'re trying to redirect to exists. <p>Redirection URL: <i>' . $url . '</i></p>');
  98. } else {
  99. $currentNumberOfRedirects += 1;
  100. if (strpos($url, "?") > 0) {
  101. $url .= "&err=$currentNumberOfRedirects";
  102. } else {
  103. $url .= "?err=$currentNumberOfRedirects";
  104. }
  105. }
  106. }
  107. if ($type == 'REDIRECT_REFRESH') {
  108. $header= 'Refresh: 0;URL=' . $url;
  109. }
  110. elseif ($type == 'REDIRECT_META') {
  111. $header= '<META HTTP-EQUIV="Refresh" CONTENT="0; URL=' . $url . '" />';
  112. echo $header;
  113. exit;
  114. }
  115. elseif ($type == 'REDIRECT_HEADER' || empty ($type)) {
  116. // check if url has /$base_url
  117. global $base_url, $site_url;
  118. if (substr($url, 0, strlen($base_url)) == $base_url) {
  119. // append $site_url to make it work with Location:
  120. $url= $site_url . substr($url, strlen($base_url));
  121. }
  122. if (strpos($url, "\n") === false) {
  123. $header= 'Location: ' . $url;
  124. } else {
  125. $this->messageQuit('No newline allowed in redirect url.');
  126. }
  127. }
  128. if ($responseCode && (strpos($responseCode, '30') !== false)) {
  129. header($responseCode);
  130. }
  131. header($header);
  132. exit();
  133. }
  134. }
  135. function sendForward($id, $responseCode= '') {
  136. if ($this->forwards > 0) {
  137. $this->forwards= $this->forwards - 1;
  138. $this->documentIdentifier= $id;
  139. $this->documentMethod= 'id';
  140. $this->documentObject= $this->getDocumentObject('id', $id);
  141. if ($responseCode) {
  142. header($responseCode);
  143. }
  144. $this->prepareResponse();
  145. exit();
  146. } else {
  147. header('HTTP/1.0 500 Internal Server Error');
  148. die('<h1>ERROR: Too many forward attempts!</h1><p>The request could not be completed due to too many unsuccessful forward attempts.</p>');
  149. }
  150. }
  151. function sendErrorPage() {
  152. // invoke OnPageNotFound event
  153. $this->invokeEvent('OnPageNotFound');
  154. // $this->sendRedirect($this->makeUrl($this->config['error_page'], '', '&refurl=' . urlencode($_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'])), 1);
  155. $this->sendForward($this->config['error_page'] ? $this->config['error_page'] : $this->config['site_start'], 'HTTP/1.0 404 Not Found');
  156. exit();
  157. }
  158. function sendUnauthorizedPage() {
  159. // invoke OnPageUnauthorized event
  160. $_REQUEST['refurl'] = $this->documentIdentifier;
  161. $this->invokeEvent('OnPageUnauthorized');
  162. if ($this->config['unauthorized_page']) {
  163. $unauthorizedPage= $this->config['unauthorized_page'];
  164. } elseif ($this->config['error_page']) {
  165. $unauthorizedPage= $this->config['error_page'];
  166. } else {
  167. $unauthorizedPage= $this->config['site_start'];
  168. }
  169. $this->sendForward($unauthorizedPage, 'HTTP/1.1 401 Unauthorized');
  170. exit();
  171. }
  172. // function to connect to the database
  173. // - deprecated use $modx->db->connect()
  174. function dbConnect() {
  175. $this->db->connect();
  176. $this->rs= $this->db->conn; // for compatibility
  177. }
  178. // function to query the database
  179. // - deprecated use $modx->db->query()
  180. function dbQuery($sql) {
  181. return $this->db->query($sql);
  182. }
  183. // function to count the number of rows in a record set
  184. function recordCount($rs) {
  185. return $this->db->getRecordCount($rs);
  186. }
  187. // - deprecated, use $modx->db->getRow()
  188. function fetchRow($rs, $mode= 'assoc') {
  189. return $this->db->getRow($rs, $mode);
  190. }
  191. // - deprecated, use $modx->db->getAffectedRows()
  192. function affectedRows($rs) {
  193. return $this->db->getAffectedRows($rs);
  194. }
  195. // - deprecated, use $modx->db->getInsertId()
  196. function insertId($rs) {
  197. return $this->db->getInsertId($rs);
  198. }
  199. // function to close a database connection
  200. // - deprecated, use $modx->db->disconnect()
  201. function dbClose() {
  202. $this->db->disconnect();
  203. }
  204. function getSettings() {
  205. if (!is_array($this->config) || empty ($this->config)) {
  206. if ($included= file_exists(MODX_BASE_PATH . 'assets/cache/siteCache.idx.php')) {
  207. $included= include_once (MODX_BASE_PATH . 'assets/cache/siteCache.idx.php');
  208. }
  209. if (!$included || !is_array($this->config) || empty ($this->config)) {
  210. include_once MODX_BASE_PATH . "/manager/processors/cache_sync.class.processor.php";
  211. $cache = new synccache();
  212. $cache->setCachepath(MODX_BASE_PATH . "/assets/cache/");
  213. $cache->setReport(false);
  214. $rebuilt = $cache->buildCache($this);
  215. $included = false;
  216. if($rebuilt && $included= file_exists(MODX_BASE_PATH . 'assets/cache/siteCache.idx.php')) {
  217. $included= include MODX_BASE_PATH . 'assets/cache/siteCache.idx.php';
  218. }
  219. if(!$included) {
  220. $result= $this->db->query('SELECT setting_name, setting_value FROM ' . $this->getFullTableName('system_settings'));
  221. while ($row= $this->db->getRow($result, 'both')) {
  222. $this->config[$row[0]]= $row[1];
  223. }
  224. }
  225. }
  226. // added for backwards compatibility - garry FS#104
  227. $this->config['etomite_charset'] = & $this->config['modx_charset'];
  228. // store base_url and base_path inside config array
  229. $this->config['base_url']= MODX_BASE_URL;
  230. $this->config['base_path']= MODX_BASE_PATH;
  231. $this->config['site_url']= MODX_SITE_URL;
  232. // load user setting if user is logged in
  233. $usrSettings= array ();
  234. if ($id= $this->getLoginUserID()) {
  235. $usrType= $this->getLoginUserType();
  236. if (isset ($usrType) && $usrType == 'manager')
  237. $usrType= 'mgr';
  238. if ($usrType == 'mgr' && $this->isBackend()) {
  239. // invoke the OnBeforeManagerPageInit event, only if in backend
  240. $this->invokeEvent("OnBeforeManagerPageInit");
  241. }
  242. if (isset ($_SESSION[$usrType . 'UsrConfigSet'])) {
  243. $usrSettings= & $_SESSION[$usrType . 'UsrConfigSet'];
  244. } else {
  245. if ($usrType == 'web')
  246. $query= $this->getFullTableName('web_user_settings') . ' WHERE webuser=\'' . $id . '\'';
  247. else
  248. $query= $this->getFullTableName('user_settings') . ' WHERE user=\'' . $id . '\'';
  249. $result= $this->db->query('SELECT setting_name, setting_value FROM ' . $query);
  250. while ($row= $this->db->getRow($result, 'both'))
  251. $usrSettings[$row[0]]= $row[1];
  252. if (isset ($usrType))
  253. $_SESSION[$usrType . 'UsrConfigSet']= $usrSettings; // store user settings in session
  254. }
  255. }
  256. if ($this->isFrontend() && $mgrid= $this->getLoginUserID('mgr')) {
  257. $musrSettings= array ();
  258. if (isset ($_SESSION['mgrUsrConfigSet'])) {
  259. $musrSettings= & $_SESSION['mgrUsrConfigSet'];
  260. } else {
  261. $query= $this->getFullTableName('user_settings') . ' WHERE user=\'' . $mgrid . '\'';
  262. if ($result= $this->db->query('SELECT setting_name, setting_value FROM ' . $query)) {
  263. while ($row= $this->db->getRow($result, 'both')) {
  264. $usrSettings[$row[0]]= $row[1];
  265. }
  266. $_SESSION['mgrUsrConfigSet']= $musrSettings; // store user settings in session
  267. }
  268. }
  269. if (!empty ($musrSettings)) {
  270. $usrSettings= array_merge($musrSettings, $usrSettings);
  271. }
  272. }
  273. $this->config= array_merge($this->config, $usrSettings);
  274. }
  275. }
  276. function getDocumentMethod() {
  277. // function to test the query and find the retrieval method
  278. if (isset ($_REQUEST['q'])) {
  279. return "alias";
  280. }
  281. elseif (isset ($_REQUEST['id'])) {
  282. return "id";
  283. } else {
  284. return "none";
  285. }
  286. }
  287. function getDocumentIdentifier($method) {
  288. // function to test the query and find the retrieval method
  289. $docIdentifier= $this->config['site_start'];
  290. switch ($method) {
  291. case 'alias' :
  292. $docIdentifier= $this->db->escape($_REQUEST['q']);
  293. break;
  294. case 'id' :
  295. if (!is_numeric($_REQUEST['id'])) {
  296. $this->sendErrorPage();
  297. } else {
  298. $docIdentifier= intval($_REQUEST['id']);
  299. }
  300. break;
  301. }
  302. return $docIdentifier;
  303. }
  304. // check for manager login session
  305. function checkSession() {
  306. if (isset ($_SESSION['mgrValidated'])) {
  307. return true;
  308. } else {
  309. return false;
  310. }
  311. }
  312. function checkPreview() {
  313. if ($this->checkSession() == true) {
  314. if (isset ($_REQUEST['z']) && $_REQUEST['z'] == 'manprev') {
  315. return true;
  316. } else {
  317. return false;
  318. }
  319. } else {
  320. return false;
  321. }
  322. }
  323. // check if site is offline
  324. function checkSiteStatus() {
  325. $siteStatus= $this->config['site_status'];
  326. if ($siteStatus == 1) {
  327. // site online
  328. return true;
  329. }
  330. elseif ($siteStatus == 0 && $this->checkSession()) {
  331. // site offline but launched via the manager
  332. return true;
  333. } else {
  334. // site is offline
  335. return false;
  336. }
  337. }
  338. function cleanDocumentIdentifier($qOrig) {
  339. (!empty($qOrig)) or $qOrig = $this->config['site_start'];
  340. $q= $qOrig;
  341. /* First remove any / before or after */
  342. if ($q[strlen($q) - 1] == '/')
  343. $q= substr($q, 0, -1);
  344. if ($q[0] == '/')
  345. $q= substr($q, 1);
  346. /* Save path if any */
  347. /* FS#476 and FS#308: only return virtualDir if friendly paths are enabled */
  348. if ($this->config['use_alias_path'] == 1) {
  349. $this->virtualDir= dirname($q);
  350. $this->virtualDir= ($this->virtualDir == '.' ? '' : $this->virtualDir);
  351. $q= basename($q);
  352. } else {
  353. $this->virtualDir= '';
  354. }
  355. $q= str_replace($this->config['friendly_url_prefix'], "", $q);
  356. $q= str_replace($this->config['friendly_url_suffix'], "", $q);
  357. if (is_numeric($q) && !$this->documentListing[$q]) { /* we got an ID returned, check to make sure it's not an alias */
  358. /* FS#476 and FS#308: check that id is valid in terms of virtualDir structure */
  359. if ($this->config['use_alias_path'] == 1) {
  360. if ((($this->virtualDir != '' && !$this->documentListing[$this->virtualDir . '/' . $q]) || ($this->virtualDir == '' && !$this->documentListing[$q])) && (($this->virtualDir != '' && in_array($q, $this->getChildIds($this->documentListing[$this->virtualDir], 1))) || ($this->virtualDir == '' && in_array($q, $this->getChildIds(0, 1))))) {
  361. $this->documentMethod= 'id';
  362. return $q;
  363. } else { /* not a valid id in terms of virtualDir, treat as alias */
  364. $this->documentMethod= 'alias';
  365. return $q;
  366. }
  367. } else {
  368. $this->documentMethod= 'id';
  369. return $q;
  370. }
  371. } else { /* we didn't get an ID back, so instead we assume it's an alias */
  372. if ($this->config['friendly_alias_urls'] != 1) {
  373. $q= $qOrig;
  374. }
  375. $this->documentMethod= 'alias';
  376. return $q;
  377. }
  378. }
  379. function checkCache($id) {
  380. $cacheFile= "assets/cache/docid_" . $id . ".pageCache.php";
  381. if (file_exists($cacheFile)) {
  382. $this->documentGenerated= 0;
  383. $flContent= implode("", file($cacheFile));
  384. $flContent= substr($flContent, 37); // remove php header
  385. $a= explode("<!--__MODxCacheSpliter__-->", $flContent, 2);
  386. if (count($a) == 1)
  387. return $a[0]; // return only document content
  388. else {
  389. $docObj= unserialize($a[0]); // rebuild document object
  390. // check page security
  391. if ($docObj['privateweb'] && isset ($docObj['__MODxDocGroups__'])) {
  392. $pass= false;
  393. $usrGrps= $this->getUserDocGroups();
  394. $docGrps= explode(",", $docObj['__MODxDocGroups__']);
  395. // check is user has access to doc groups
  396. if (is_array($usrGrps)) {
  397. foreach ($usrGrps as $k => $v)
  398. if (in_array($v, $docGrps)) {
  399. $pass= true;
  400. break;
  401. }
  402. }
  403. // diplay error pages if user has no access to cached doc
  404. if (!$pass) {
  405. if ($this->config['unauthorized_page']) {
  406. // check if file is not public
  407. $tbldg= $this->getFullTableName("document_groups");
  408. $secrs= $this->db->query("SELECT id FROM $tbldg WHERE document = '" . $id . "' LIMIT 1;");
  409. if ($secrs)
  410. $seclimit= mysql_num_rows($secrs);
  411. }
  412. if ($seclimit > 0) {
  413. // match found but not publicly accessible, send the visitor to the unauthorized_page
  414. $this->sendUnauthorizedPage();
  415. exit; // stop here
  416. } else {
  417. // no match found, send the visitor to the error_page
  418. $this->sendErrorPage();
  419. exit; // stop here
  420. }
  421. }
  422. }
  423. // Grab the Scripts
  424. if (isset($docObj['__MODxSJScripts__'])) $this->sjscripts = $docObj['__MODxSJScripts__'];
  425. if (isset($docObj['__MODxJScripts__'])) $this->jscripts = $docObj['__MODxJScripts__'];
  426. // Remove intermediate variables
  427. unset($docObj['__MODxDocGroups__'], $docObj['__MODxSJScripts__'], $docObj['__MODxJScripts__']);
  428. $this->documentObject= $docObj;
  429. return $a[1]; // return document content
  430. }
  431. } else {
  432. $this->documentGenerated= 1;
  433. return "";
  434. }
  435. }
  436. function outputContent($noEvent= false) {
  437. $this->documentOutput= $this->documentContent;
  438. if ($this->documentGenerated == 1 && $this->documentObject['cacheable'] == 1 && $this->documentObject['type'] == 'document' && $this->documentObject['published'] == 1) {
  439. if (!empty($this->sjscripts)) $this->documentObject['__MODxSJScripts__'] = $this->sjscripts;
  440. if (!empty($this->jscripts)) $this->documentObject['__MODxJScripts__'] = $this->jscripts;
  441. }
  442. // check for non-cached snippet output
  443. if (strpos($this->documentOutput, '[!') > -1) {
  444. $this->documentOutput= str_replace('[!', '[[', $this->documentOutput);
  445. $this->documentOutput= str_replace('!]', ']]', $this->documentOutput);
  446. // Parse document source
  447. $this->documentOutput= $this->parseDocumentSource($this->documentOutput);
  448. }
  449. // Moved from prepareResponse() by sirlancelot
  450. // Insert Startup jscripts & CSS scripts into template - template must have a <head> tag
  451. if ($js= $this->getRegisteredClientStartupScripts()) {
  452. // change to just before closing </head>
  453. // $this->documentContent = preg_replace("/(<head[^>]*>)/i", "\\1\n".$js, $this->documentContent);
  454. $this->documentOutput= preg_replace("/(<\/head>)/i", $js . "\n\\1", $this->documentOutput);
  455. }
  456. // Insert jscripts & html block into template - template must have a </body> tag
  457. if ($js= $this->getRegisteredClientScripts()) {
  458. $this->documentOutput= preg_replace("/(<\/body>)/i", $js . "\n\\1", $this->documentOutput);
  459. }
  460. // End fix by sirlancelot
  461. // remove all unused placeholders
  462. if (strpos($this->documentOutput, '[+') > -1) {
  463. $matches= array ();
  464. preg_match_all('~\[\+(.*?)\+\]~', $this->documentOutput, $matches);
  465. if ($matches[0])
  466. $this->documentOutput= str_replace($matches[0], '', $this->documentOutput);
  467. }
  468. $this->documentOutput= $this->rewriteUrls($this->documentOutput);
  469. // send out content-type and content-disposition headers
  470. if (IN_PARSER_MODE == "true") {
  471. $type= !empty ($this->contentTypes[$this->documentIdentifier]) ? $this->contentTypes[$this->documentIdentifier] : "text/html";
  472. header('Content-Type: ' . $type . '; charset=' . $this->config['modx_charset']);
  473. // if (($this->documentIdentifier == $this->config['error_page']) || $redirect_error)
  474. // header('HTTP/1.0 404 Not Found');
  475. if (!$this->checkPreview() && $this->documentObject['content_dispo'] == 1) {
  476. if ($this->documentObject['alias'])
  477. $name= $this->documentObject['alias'];
  478. else {
  479. // strip title of special characters
  480. $name= $this->documentObject['pagetitle'];
  481. $name= strip_tags($name);
  482. $name= strtolower($name);
  483. $name= preg_replace('/&.+?;/', '', $name); // kill entities
  484. $name= preg_replace('/[^\.%a-z0-9 _-]/', '', $name);
  485. $name= preg_replace('/\s+/', '-', $name);
  486. $name= preg_replace('|-+|', '-', $name);
  487. $name= trim($name, '-');
  488. }
  489. $header= 'Content-Disposition: attachment; filename=' . $name;
  490. header($header);
  491. }
  492. }
  493. $totalTime= ($this->getMicroTime() - $this->tstart);
  494. $queryTime= $this->queryTime;
  495. $phpTime= $totalTime - $queryTime;
  496. $queryTime= sprintf("%2.4f s", $queryTime);
  497. $totalTime= sprintf("%2.4f s", $totalTime);
  498. $phpTime= sprintf("%2.4f s", $phpTime);
  499. $source= $this->documentGenerated == 1 ? "database" : "cache";
  500. $queries= isset ($this->executedQueries) ? $this->executedQueries : 0;
  501. $out =& $this->documentOutput;
  502. if ($this->dumpSQL) {
  503. $out .= $this->queryCode;
  504. }
  505. $out= str_replace("[^q^]", $queries, $out);
  506. $out= str_replace("[^qt^]", $queryTime, $out);
  507. $out= str_replace("[^p^]", $phpTime, $out);
  508. $out= str_replace("[^t^]", $totalTime, $out);
  509. $out= str_replace("[^s^]", $source, $out);
  510. //$this->documentOutput= $out;
  511. // invoke OnWebPagePrerender event
  512. if (!$noEvent) {
  513. $this->invokeEvent("OnWebPagePrerender");
  514. }
  515. echo $this->documentOutput;
  516. ob_end_flush();
  517. }
  518. function checkPublishStatus() {
  519. $cacheRefreshTime= 0;
  520. @include $this->config["base_path"] . "assets/cache/sitePublishing.idx.php";
  521. $timeNow= time() + $this->config['server_offset_time'];
  522. if ($cacheRefreshTime <= $timeNow && $cacheRefreshTime != 0) {
  523. // now, check for documents that need publishing
  524. $sql = "UPDATE ".$this->getFullTableName("site_content")." SET published=1, publishedon=".time()." WHERE ".$this->getFullTableName("site_content").".pub_date <= $timeNow AND ".$this->getFullTableName("site_content").".pub_date!=0 AND published=0";
  525. if (@ !$result= $this->db->query($sql)) {
  526. $this->messageQuit("Execution of a query to the database failed", $sql);
  527. }
  528. // now, check for documents that need un-publishing
  529. $sql= "UPDATE " . $this->getFullTableName("site_content") . " SET published=0, publishedon=0 WHERE " . $this->getFullTableName("site_content") . ".unpub_date <= $timeNow AND " . $this->getFullTableName("site_content") . ".unpub_date!=0 AND published=1";
  530. if (@ !$result= $this->db->query($sql)) {
  531. $this->messageQuit("Execution of a query to the database failed", $sql);
  532. }
  533. // clear the cache
  534. $basepath= $this->config["base_path"] . "assets/cache/";
  535. if ($handle= opendir($basepath)) {
  536. $filesincache= 0;
  537. $deletedfilesincache= 0;
  538. while (false !== ($file= readdir($handle))) {
  539. if ($file != "." && $file != "..") {
  540. $filesincache += 1;
  541. if (preg_match("/\.pageCache/", $file)) {
  542. $deletedfilesincache += 1;
  543. while (!unlink($basepath . "/" . $file));
  544. }
  545. }
  546. }
  547. closedir($handle);
  548. }
  549. // update publish time file
  550. $timesArr= array ();
  551. $sql= "SELECT MIN(pub_date) AS minpub FROM " . $this->getFullTableName("site_content") . " WHERE pub_date>$timeNow";
  552. if (@ !$result= $this->db->query($sql)) {
  553. $this->messageQuit("Failed to find publishing timestamps", $sql);
  554. }
  555. $tmpRow= $this->db->getRow($result);
  556. $minpub= $tmpRow['minpub'];
  557. if ($minpub != NULL) {
  558. $timesArr[]= $minpub;
  559. }
  560. $sql= "SELECT MIN(unpub_date) AS minunpub FROM " . $this->getFullTableName("site_content") . " WHERE unpub_date>$timeNow";
  561. if (@ !$result= $this->db->query($sql)) {
  562. $this->messageQuit("Failed to find publishing timestamps", $sql);
  563. }
  564. $tmpRow= $this->db->getRow($result);
  565. $minunpub= $tmpRow['minunpub'];
  566. if ($minunpub != NULL) {
  567. $timesArr[]= $minunpub;
  568. }
  569. if (count($timesArr) > 0) {
  570. $nextevent= min($timesArr);
  571. } else {
  572. $nextevent= 0;
  573. }
  574. $basepath= $this->config["base_path"] . "assets/cache";
  575. $fp= @ fopen($basepath . "/sitePublishing.idx.php", "wb");
  576. if ($fp) {
  577. @ flock($fp, LOCK_EX);
  578. @ fwrite($fp, "<?php \$cacheRefreshTime=$nextevent; ?>");
  579. @ flock($fp, LOCK_UN);
  580. @ fclose($fp);
  581. }
  582. }
  583. }
  584. function postProcess() {
  585. // if the current document was generated, cache it!
  586. if ($this->documentGenerated == 1 && $this->documentObject['cacheable'] == 1 && $this->documentObject['type'] == 'document' && $this->documentObject['published'] == 1) {
  587. $basepath= $this->config["base_path"] . "assets/cache";
  588. // invoke OnBeforeSaveWebPageCache event
  589. $this->invokeEvent("OnBeforeSaveWebPageCache");
  590. if ($fp= @ fopen($basepath . "/docid_" . $this->documentIdentifier . ".pageCache.php", "w")) {
  591. // get and store document groups inside document object. Document groups will be used to check security on cache pages
  592. $sql= "SELECT document_group FROM " . $this->getFullTableName("document_groups") . " WHERE document='" . $this->documentIdentifier . "'";
  593. $docGroups= $this->db->getColumn("document_group", $sql);
  594. // Attach Document Groups and Scripts
  595. if (is_array($docGroups)) $this->documentObject['__MODxDocGroups__'] = implode(",", $docGroups);
  596. $docObjSerial= serialize($this->documentObject);
  597. $cacheContent= $docObjSerial . "<!--__MODxCacheSpliter__-->" . $this->documentContent;
  598. fputs($fp, "<?php die('Unauthorized access.'); ?>$cacheContent");
  599. fclose($fp);
  600. }
  601. }
  602. // Useful for example to external page counters/stats packages
  603. $this->invokeEvent('OnWebPageComplete');
  604. // end post processing
  605. }
  606. function mergeDocumentMETATags($template) {
  607. if ($this->documentObject['haskeywords'] == 1) {
  608. // insert keywords
  609. $keywords = $this->getKeywords();
  610. if (is_array($keywords) && count($keywords) > 0) {
  611. $keywords = implode(", ", $keywords);
  612. $metas= "\t<meta name=\"keywords\" content=\"$keywords\" />\n";
  613. }
  614. // Don't process when cached
  615. $this->documentObject['haskeywords'] = '0';
  616. }
  617. if ($this->documentObject['hasmetatags'] == 1) {
  618. // insert meta tags
  619. $tags= $this->getMETATags();
  620. foreach ($tags as $n => $col) {
  621. $tag= strtolower($col['tag']);
  622. $tagvalue= $col['tagvalue'];
  623. $tagstyle= $col['http_equiv'] ? 'http-equiv' : 'name';
  624. $metas .= "\t<meta $tagstyle=\"$tag\" content=\"$tagvalue\" />\n";
  625. }
  626. // Don't process when cached
  627. $this->documentObject['hasmetatags'] = '0';
  628. }
  629. if ($metas) $template = preg_replace("/(<head>)/i", "\\1\n\t" . trim($metas), $template);
  630. return $template;
  631. }
  632. // mod by Raymond
  633. function mergeDocumentContent($template) {
  634. $replace= array ();
  635. preg_match_all('~\[\*(.*?)\*\]~', $template, $matches);
  636. $variableCount= count($matches[1]);
  637. $basepath= $this->config["base_path"] . "manager/includes";
  638. for ($i= 0; $i < $variableCount; $i++) {
  639. $key= $matches[1][$i];
  640. $key= substr($key, 0, 1) == '#' ? substr($key, 1) : $key; // remove # for QuickEdit format
  641. $value= $this->documentObject[$key];
  642. if (is_array($value)) {
  643. include_once $basepath . "/tmplvars.format.inc.php";
  644. include_once $basepath . "/tmplvars.commands.inc.php";
  645. $w= "100%";
  646. $h= "300";
  647. $value= getTVDisplayFormat($value[0], $value[1], $value[2], $value[3], $value[4]);
  648. }
  649. $replace[$i]= $value;
  650. }
  651. $template= str_replace($matches[0], $replace, $template);
  652. return $template;
  653. }
  654. function mergeSettingsContent($template) {
  655. $replace= array ();
  656. $matches= array ();
  657. if (preg_match_all('~\[\(([a-z\_]*?)\)\]~', $template, $matches)) {
  658. $settingsCount= count($matches[1]);
  659. for ($i= 0; $i < $settingsCount; $i++) {
  660. if (array_key_exists($matches[1][$i], $this->config))
  661. $replace[$i]= $this->config[$matches[1][$i]];
  662. }
  663. $template= str_replace($matches[0], $replace, $template);
  664. }
  665. return $template;
  666. }
  667. function mergeChunkContent($content) {
  668. $replace= array ();
  669. $matches= array ();
  670. if (preg_match_all('~{{(.*?)}}~', $content, $matches)) {
  671. $settingsCount= count($matches[1]);
  672. for ($i= 0; $i < $settingsCount; $i++) {
  673. if (isset ($this->chunkCache[$matches[1][$i]])) {
  674. $replace[$i]= $this->chunkCache[$matches[1][$i]];
  675. } else {
  676. $sql= "SELECT `snippet` FROM " . $this->getFullTableName("site_htmlsnippets") . " WHERE " . $this->getFullTableName("site_htmlsnippets") . ".`name`='" . $this->db->escape($matches[1][$i]) . "';";
  677. $result= $this->db->query($sql);
  678. $limit= $this->db->getRecordCount($result);
  679. if ($limit < 1) {
  680. $this->chunkCache[$matches[1][$i]]= "";
  681. $replace[$i]= "";
  682. } else {
  683. $row= $this->db->getRow($result);
  684. $this->chunkCache[$matches[1][$i]]= $row['snippet'];
  685. $replace[$i]= $row['snippet'];
  686. }
  687. }
  688. }
  689. $content= str_replace($matches[0], $replace, $content);
  690. }
  691. return $content;
  692. }
  693. // Added by Raymond
  694. function mergePlaceholderContent($content) {
  695. $replace= array ();
  696. $matches= array ();
  697. if (preg_match_all('~\[\+(.*?)\+\]~', $content, $matches)) {
  698. $cnt= count($matches[1]);
  699. for ($i= 0; $i < $cnt; $i++) {
  700. $v= '';
  701. $key= $matches[1][$i];
  702. if (is_array($this->placeholders) && array_key_exists($key, $this->placeholders))
  703. $v= $this->placeholders[$key];
  704. if ($v === '')
  705. unset ($matches[0][$i]); // here we'll leave empty placeholders for last.
  706. else
  707. $replace[$i]= $v;
  708. }
  709. $content= str_replace($matches[0], $replace, $content);
  710. }
  711. return $content;
  712. }
  713. // evalPlugin
  714. function evalPlugin($pluginCode, $params) {
  715. $etomite= $modx= & $this;
  716. $modx->event->params= & $params; // store params inside event object
  717. if (is_array($params)) {
  718. extract($params, EXTR_SKIP);
  719. }
  720. ob_start();
  721. eval ($pluginCode);
  722. $msg= ob_get_contents();
  723. ob_end_clean();
  724. if ($msg && isset ($php_errormsg)) {
  725. if (!strpos($php_errormsg, 'Deprecated')) { // ignore php5 strict errors
  726. // log error
  727. $this->logEvent(1, 3, "<b>$php_errormsg</b><br /><br /> $msg", $this->Event->activePlugin . " - Plugin");
  728. if ($this->isBackend())
  729. $this->Event->alert("An error occurred while loading. Please see the event log for more information.<p />$msg");
  730. }
  731. } else {
  732. echo $msg;
  733. }
  734. unset ($modx->event->params);
  735. }
  736. function evalSnippet($snippet, $params) {
  737. $etomite= $modx= & $this;
  738. $modx->event->params= & $params; // store params inside event object
  739. if (is_array($params)) {
  740. extract($params, EXTR_SKIP);
  741. }
  742. ob_start();
  743. $snip= eval ($snippet);
  744. $msg= ob_get_contents();
  745. ob_end_clean();
  746. if ($msg && isset ($php_errormsg)) {
  747. if (!strpos($php_errormsg, 'Deprecated')) { // ignore php5 strict errors
  748. // log error
  749. $this->logEvent(1, 3, "<b>$php_errormsg</b><br /><br /> $msg", $this->currentSnippet . " - Snippet");
  750. if ($this->isBackend())
  751. $this->Event->alert("An error occurred while loading. Please see the event log for more information<p />$msg");
  752. }
  753. }
  754. unset ($modx->event->params);
  755. return $msg . $snip;
  756. }
  757. function evalSnippets($documentSource) {
  758. preg_match_all('~\[\[(.*?)\]\]~ms', $documentSource, $matches);
  759. $etomite= & $this;
  760. if ($matchCount= count($matches[1])) {
  761. for ($i= 0; $i < $matchCount; $i++) {
  762. $spos= strpos($matches[1][$i], '?', 0);
  763. if ($spos !== false) {
  764. $params= substr($matches[1][$i], $spos, strlen($matches[1][$i]));
  765. } else {
  766. $params= '';
  767. }
  768. $matches[1][$i]= str_replace($params, '', $matches[1][$i]);
  769. $snippetParams[$i]= $params;
  770. }
  771. $nrSnippetsToGet= $matchCount;
  772. for ($i= 0; $i < $nrSnippetsToGet; $i++) { // Raymond: Mod for Snippet props
  773. if (isset ($this->snippetCache[$matches[1][$i]])) {
  774. $snippets[$i]['name']= $matches[1][$i];
  775. $snippets[$i]['snippet']= $this->snippetCache[$matches[1][$i]];
  776. if (array_key_exists($matches[1][$i] . "Props", $this->snippetCache))
  777. $snippets[$i]['properties']= $this->snippetCache[$matches[1][$i] . "Props"];
  778. } else {
  779. // get from db and store a copy inside cache
  780. $sql= "SELECT `name`, `snippet`, `properties` FROM " . $this->getFullTableName("site_snippets") . " WHERE " . $this->getFullTableName("site_snippets") . ".`name`='" . $this->db->escape($matches[1][$i]) . "';";
  781. $result= $this->db->query($sql);
  782. $added = false;
  783. if ($this->db->getRecordCount($result) == 1) {
  784. $row= $this->db->getRow($result);
  785. if($row['name'] == $matches[1][$i]) {
  786. $snippets[$i]['name']= $row['name'];
  787. $snippets[$i]['snippet']= $this->snippetCache[$row['name']]= $row['snippet'];
  788. $snippets[$i]['properties']= $this->snippetCache[$row['name'] . "Props"]= $row['properties'];
  789. $added = true;
  790. }
  791. }
  792. if(!$added) {
  793. $snippets[$i]['name']= $matches[1][$i];
  794. $snippets[$i]['snippet']= $this->snippetCache[$matches[1][$i]]= "return false;";
  795. $snippets[$i]['properties']= '';
  796. }
  797. }
  798. }
  799. for ($i= 0; $i < $nrSnippetsToGet; $i++) {
  800. $parameter= array ();
  801. $snippetName= $this->currentSnippet= $snippets[$i]['name'];
  802. // FIXME Undefined index: properties
  803. if (array_key_exists('properties', $snippets[$i])) {
  804. $snippetProperties= $snippets[$i]['properties'];
  805. } else {
  806. $snippetProperties= '';
  807. }
  808. // load default params/properties - Raymond
  809. // FIXME Undefined variable: snippetProperties
  810. $parameter= $this->parseProperties($snippetProperties);
  811. // current params
  812. $currentSnippetParams= $snippetParams[$i];
  813. if (!empty ($currentSnippetParams)) {
  814. $tempSnippetParams= str_replace("?", "", $currentSnippetParams);
  815. $splitter= "&";
  816. if (strpos($tempSnippetParams, "&amp;") > 0)
  817. $tempSnippetParams= str_replace("&amp;", "&", $tempSnippetParams);
  818. //$tempSnippetParams = html_entity_decode($tempSnippetParams, ENT_NOQUOTES, $this->config['etomite_charset']); //FS#334 and FS#456
  819. $tempSnippetParams= explode($splitter, $tempSnippetParams);
  820. $snippetParamCount= count($tempSnippetParams);
  821. for ($x= 0; $x < $snippetParamCount; $x++) {
  822. if (strpos($tempSnippetParams[$x], '=', 0)) {
  823. if ($parameterTemp= explode("=", $tempSnippetParams[$x])) {
  824. $parameterTemp[0] = trim($parameterTemp[0]);
  825. $parameterTemp[1] = trim($parameterTemp[1]);
  826. $fp= strpos($parameterTemp[1], '`');
  827. $lp= strrpos($parameterTemp[1], '`');
  828. if (!($fp === false && $lp === false))
  829. $parameterTemp[1]= substr($parameterTemp[1], $fp +1, $lp -1);
  830. $parameter[$parameterTemp[0]]= $parameterTemp[1];
  831. }
  832. }
  833. }
  834. }
  835. $executedSnippets[$i]= $this->evalSnippet($snippets[$i]['snippet'], $parameter);
  836. if ($this->dumpSnippets == 1) {
  837. echo "<fieldset><legend><b>$snippetName</b></legend><textarea style='width:60%; height:200px'>" . htmlentities($executedSnippets[$i]) . "</textarea></fieldset><br />";
  838. }
  839. $documentSource= str_replace("[[" . $snippetName . $currentSnippetParams . "]]", $executedSnippets[$i], $documentSource);
  840. }
  841. }
  842. return $documentSource;
  843. }
  844. function makeFriendlyURL($pre, $suff, $alias) {
  845. $Alias = explode('/',$alias);
  846. $alias = array_pop($Alias);
  847. $dir = implode('/', $Alias);
  848. unset($Alias);
  849. return ($dir != '' ? "$dir/" : '') . $pre . $alias . $suff;
  850. }
  851. function rewriteUrls($documentSource) {
  852. // rewrite the urls
  853. if ($this->config['friendly_urls'] == 1) {
  854. $aliases= array ();
  855. foreach ($this->aliasListing as $item) {
  856. $aliases[$item['id']]= (strlen($item['path']) > 0 ? $item['path'] . '/' : '') . $item['alias'];
  857. }
  858. $in= '!\[\~([0-9]+)\~\]!ise'; // Use preg_replace with /e to make it evaluate PHP
  859. $isfriendly= ($this->config['friendly_alias_urls'] == 1 ? 1 : 0);
  860. $pref= $this->config['friendly_url_prefix'];
  861. $suff= $this->config['friendly_url_suffix'];
  862. $thealias= '$aliases[\\1]';
  863. $found_friendlyurl= "\$this->makeFriendlyURL('$pref','$suff',$thealias)";
  864. $not_found_friendlyurl= "\$this->makeFriendlyURL('$pref','$suff','" . '\\1' . "')";
  865. $out= "({$isfriendly} && isset({$thealias}) ? {$found_friendlyurl} : {$not_found_friendlyurl})";
  866. $documentSource= preg_replace($in, $out, $documentSource);
  867. } else {
  868. $in= '!\[\~([0-9]+)\~\]!is';
  869. $out= "index.php?id=" . '\1';
  870. $documentSource= preg_replace($in, $out, $documentSource);
  871. }
  872. return $documentSource;
  873. }
  874. /**
  875. * name: getDocumentObject - used by parser
  876. * desc: returns a document object - $method: alias, id
  877. */
  878. function getDocumentObject($method, $identifier) {
  879. $tblsc= $this->getFullTableName("site_content");
  880. $tbldg= $this->getFullTableName("document_groups");
  881. // allow alias to be full path
  882. if($method == 'alias') {
  883. $identifier = $this->cleanDocumentIdentifier($identifier);
  884. $method = $this->documentMethod;
  885. }
  886. if($method == 'alias' && $this->config['use_alias_path'] && array_key_exists($identifier, $this->documentListing)) {
  887. $method = 'id';
  888. $identifier = $this->documentListing[$identifier];
  889. }
  890. // get document groups for current user
  891. if ($docgrp= $this->getUserDocGroups())
  892. $docgrp= implode(",", $docgrp);
  893. // get document
  894. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  895. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  896. $sql= "SELECT sc.*
  897. FROM $tblsc sc
  898. LEFT JOIN $tbldg dg ON dg.document = sc.id
  899. WHERE sc." . $method . " = '" . $identifier . "'
  900. AND ($access) LIMIT 1;";
  901. $result= $this->db->query($sql);
  902. $rowCount= $this->db->getRecordCount($result);
  903. if ($rowCount < 1) {
  904. if ($this->config['unauthorized_page']) {
  905. // method may still be alias, while identifier is not full path alias, e.g. id not found above
  906. if ($method === 'alias') {
  907. $q = "SELECT dg.id FROM $tbldg dg, $tblsc sc WHERE dg.document = sc.id AND sc.alias = '{$identifier}' LIMIT 1;";
  908. } else {
  909. $q = "SELECT id FROM $tbldg WHERE document = '{$identifier}' LIMIT 1;";
  910. }
  911. // check if file is not public
  912. $secrs= $this->db->query($q);
  913. if ($secrs)
  914. $seclimit= mysql_num_rows($secrs);
  915. }
  916. if ($seclimit > 0) {
  917. // match found but not publicly accessible, send the visitor to the unauthorized_page
  918. $this->sendUnauthorizedPage();
  919. exit; // stop here
  920. } else {
  921. $this->sendErrorPage();
  922. exit;
  923. }
  924. }
  925. # this is now the document :) #
  926. $documentObject= $this->db->getRow($result);
  927. // load TVs and merge with document - Orig by Apodigm - Docvars
  928. $sql= "SELECT tv.*, IF(tvc.value!='',tvc.value,tv.default_text) as value ";
  929. $sql .= "FROM " . $this->getFullTableName("site_tmplvars") . " tv ";
  930. $sql .= "INNER JOIN " . $this->getFullTableName("site_tmplvar_templates")." tvtpl ON tvtpl.tmplvarid = tv.id ";
  931. $sql .= "LEFT JOIN " . $this->getFullTableName("site_tmplvar_contentvalues")." tvc ON tvc.tmplvarid=tv.id AND tvc.contentid = '" . $documentObject['id'] . "' ";
  932. $sql .= "WHERE tvtpl.templateid = '" . $documentObject['template'] . "'";
  933. $rs= $this->db->query($sql);
  934. $rowCount= $this->db->getRecordCount($rs);
  935. if ($rowCount > 0) {
  936. for ($i= 0; $i < $rowCount; $i++) {
  937. $row= $this->db->getRow($rs);
  938. $tmplvars[$row['name']]= array (
  939. $row['name'],
  940. $row['value'],
  941. $row['display'],
  942. $row['display_params'],
  943. $row['type']
  944. );
  945. }
  946. $documentObject= array_merge($documentObject, $tmplvars);
  947. }
  948. return $documentObject;
  949. }
  950. /**
  951. * name: parseDocumentSource - used by parser
  952. * desc: return document source aftering parsing tvs, snippets, chunks, etc.
  953. */
  954. function parseDocumentSource($source) {
  955. // set the number of times we are to parse the document source
  956. $this->minParserPasses= empty ($this->minParserPasses) ? 2 : $this->minParserPasses;
  957. $this->maxParserPasses= empty ($this->maxParserPasses) ? 10 : $this->maxParserPasses;
  958. $passes= $this->minParserPasses;
  959. for ($i= 0; $i < $passes; $i++) {
  960. // get source length if this is the final pass
  961. if ($i == ($passes -1))
  962. $st= strlen($source);
  963. if ($this->dumpSnippets == 1) {
  964. echo "<fieldset><legend><b style='color: #821517;'>PARSE PASS " . ($i +1) . "</b></legend>The following snippets (if any) were parsed during this pass.<div style='width:100%' align='center'>";
  965. }
  966. // invoke OnParseDocument event
  967. $this->documentOutput= $source; // store source code so plugins can
  968. $this->invokeEvent("OnParseDocument"); // work on it via $modx->documentOutput
  969. $source= $this->documentOutput;
  970. // combine template and document variables
  971. $source= $this->mergeDocumentContent($source);
  972. // replace settings referenced in document
  973. $source= $this->mergeSettingsContent($source);
  974. // replace HTMLSnippets in document
  975. $source= $this->mergeChunkContent($source);
  976. // insert META tags & keywords
  977. $source= $this->mergeDocumentMETATags($source);
  978. // find and merge snippets
  979. $source= $this->evalSnippets($source);
  980. // find and replace Placeholders (must be parsed last) - Added by Raymond
  981. $source= $this->mergePlaceholderContent($source);
  982. if ($this->dumpSnippets == 1) {
  983. echo "</div></fieldset><br />";
  984. }
  985. if ($i == ($passes -1) && $i < ($this->maxParserPasses - 1)) {
  986. // check if source length was changed
  987. $et= strlen($source);
  988. if ($st != $et)
  989. $passes++; // if content change then increase passes because
  990. } // we have not yet reached maxParserPasses
  991. }
  992. return $source;
  993. }
  994. function executeParser() {
  995. //error_reporting(0);
  996. if (version_compare(phpversion(), "5.0.0", ">="))
  997. set_error_handler(array (
  998. & $this,
  999. "phpError"
  1000. ), E_ALL);
  1001. else
  1002. set_error_handler(array (
  1003. & $this,
  1004. "phpError"
  1005. ));
  1006. $this->db->connect();
  1007. // get the settings
  1008. if (empty ($this->config)) {
  1009. $this->getSettings();
  1010. }
  1011. // IIS friendly url fix
  1012. if ($this->config['friendly_urls'] == 1 && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) {
  1013. $url= $_SERVER['QUERY_STRING'];
  1014. $err= substr($url, 0, 3);
  1015. if ($err == '404' || $err == '405') {
  1016. $k= array_keys($_GET);
  1017. unset ($_GET[$k[0]]);
  1018. unset ($_REQUEST[$k[0]]); // remove 404,405 entry
  1019. $_SERVER['QUERY_STRING']= $qp['query'];
  1020. $qp= parse_url(str_replace($this->config['site_url'], '', substr($url, 4)));
  1021. if (!empty ($qp['query'])) {
  1022. parse_str($qp['query'], $qv);
  1023. foreach ($qv as $n => $v)
  1024. $_REQUEST[$n]= $_GET[$n]= $v;
  1025. }
  1026. $_SERVER['PHP_SELF']= $this->config['base_url'] . $qp['path'];
  1027. $_REQUEST['q']= $_GET['q']= $qp['path'];
  1028. }
  1029. }
  1030. // check site settings
  1031. if (!$this->checkSiteStatus()) {
  1032. header('HTTP/1.0 503 Service Unavailable');
  1033. if (!$this->config['site_unavailable_page']) {
  1034. // display offline message
  1035. $this->documentContent= $this->config['site_unavailable_message'];
  1036. $this->outputContent();
  1037. exit; // stop processing here, as the site's offline
  1038. } else {
  1039. // setup offline page document settings
  1040. $this->documentMethod= "id";
  1041. $this->documentIdentifier= $this->config['site_unavailable_page'];
  1042. }
  1043. } else {
  1044. // make sure the cache doesn't need updating
  1045. $this->checkPublishStatus();
  1046. // find out which document we need to display
  1047. $this->documentMethod= $this->getDocumentMethod();
  1048. $this->documentIdentifier= $this->getDocumentIdentifier($this->documentMethod);
  1049. }
  1050. if ($this->documentMethod == "none") {
  1051. $this->documentMethod= "id"; // now we know the site_start, change the none method to id
  1052. }
  1053. if ($this->documentMethod == "alias") {
  1054. $this->documentIdentifier= $this->cleanDocumentIdentifier($this->documentIdentifier);
  1055. }
  1056. if ($this->documentMethod == "alias") {
  1057. // Check use_alias_path and check if $this->virtualDir is set to anything, then parse the path
  1058. if ($this->config['use_alias_path'] == 1) {
  1059. $alias= (strlen($this->virtualDir) > 0 ? $this->virtualDir . '/' : '') . $this->documentIdentifier;
  1060. if (array_key_exists($alias, $this->documentListing)) {
  1061. $this->documentIdentifier= $this->documentListing[$alias];
  1062. } else {
  1063. $this->sendErrorPage();
  1064. }
  1065. } else {
  1066. $this->documentIdentifier= $this->documentListing[$this->documentIdentifier];
  1067. }
  1068. $this->documentMethod= 'id';
  1069. }
  1070. // invoke OnWebPageInit event
  1071. $this->invokeEvent("OnWebPageInit");
  1072. // invoke OnLogPageView event
  1073. if ($this->config['track_visitors'] == 1) {
  1074. $this->invokeEvent("OnLogPageHit");
  1075. }
  1076. $this->prepareResponse();
  1077. }
  1078. function prepareResponse() {
  1079. // we now know the method and identifier, let's check the cache
  1080. $this->documentContent= $this->checkCache($this->documentIdentifier);
  1081. if ($this->documentContent != "") {
  1082. // invoke OnLoadWebPageCache event
  1083. $this->invokeEvent("OnLoadWebPageCache");
  1084. } else {
  1085. // get document object
  1086. $this->documentObject= $this->getDocumentObject($this->documentMethod, $this->documentIdentifier);
  1087. // write the documentName to the object
  1088. $this->documentName= $this->documentObject['pagetitle'];
  1089. // validation routines
  1090. if ($this->documentObject['deleted'] == 1) {
  1091. $this->sendErrorPage();
  1092. }
  1093. // && !$this->checkPreview()
  1094. if ($this->documentObject['published'] == 0) {
  1095. // Can't view unpublished pages
  1096. if (!$this->hasPermission('view_unpublished')) {
  1097. $this->sendErrorPage();
  1098. } else {
  1099. // Inculde the necessary files to check document permissions
  1100. include_once ($this->config['base_path'] . '/manager/processors/user_documents_permissions.class.php');
  1101. $udperms= new udperms();
  1102. $udperms->user= $this->getLoginUserID();
  1103. $udperms->document= $this->documentIdentifier;
  1104. $udperms->role= $_SESSION['mgrRole'];
  1105. // Doesn't have access to this document
  1106. if (!$udperms->checkPermissions()) {
  1107. $this->sendErrorPage();
  1108. }
  1109. }
  1110. }
  1111. // check whether it's a reference
  1112. if ($this->documentObject['type'] == "reference") {
  1113. if (is_numeric($this->documentObject['content'])) {
  1114. // if it's a bare document id
  1115. $this->documentObject['content']= $this->makeUrl($this->documentObject['content']);
  1116. }
  1117. elseif (strpos($this->documentObject['content'], '[~') !== false) {
  1118. // if it's an internal docid tag, process it
  1119. $this->documentObject['content']= $this->rewriteUrls($this->documentObject['content']);
  1120. }
  1121. $this->sendRedirect($this->documentObject['content'], 0, '', 'HTTP/1.0 301 Moved Permanently');
  1122. }
  1123. // check if we should not hit this document
  1124. if ($this->documentObject['donthit'] == 1) {
  1125. $this->config['track_visitors']= 0;
  1126. }
  1127. // get the template and start parsing!
  1128. if (!$this->documentObject['template'])
  1129. $this->documentContent= "[*content*]"; // use blank template
  1130. else {
  1131. $sql= "SELECT `content` FROM " . $this->getFullTableName("site_templates") . " WHERE " . $this->getFullTableName("site_templates") . ".`id` = '" . $this->documentObject['template'] . "';";
  1132. $result= $this->db->query($sql);
  1133. $rowCount= $this->db->getRecordCount($result);
  1134. if ($rowCount > 1) {
  1135. $this->messageQuit("Incorrect number of templates returned from database", $sql);
  1136. }
  1137. elseif ($rowCount == 1) {
  1138. $row= $this->db->getRow($result);
  1139. $this->documentContent= $row['content'];
  1140. }
  1141. }
  1142. // invoke OnLoadWebDocument event
  1143. $this->invokeEvent("OnLoadWebDocument");
  1144. // Parse document source
  1145. $this->documentContent= $this->parseDocumentSource($this->documentContent);
  1146. // setup <base> tag for friendly urls
  1147. // if($this->config['friendly_urls']==1 && $this->config['use_alias_path']==1) {
  1148. // $this->regClientStartupHTMLBlock('<base href="'.$this->config['site_url'].'" />');
  1149. // }
  1150. }
  1151. register_shutdown_function(array (
  1152. & $this,
  1153. "postProcess"
  1154. )); // tell PHP to call postProcess when it shuts down
  1155. $this->outputContent();
  1156. //$this->postProcess();
  1157. }
  1158. /***************************************************************************************/
  1159. /* API functions /
  1160. /***************************************************************************************/
  1161. function getParentIds($id, $height= 10) {
  1162. $parents= array ();
  1163. while ( $id && $height-- ) {
  1164. $thisid = $id;
  1165. $id = $this->aliasListing[$id]['parent'];
  1166. if (!$id) break;
  1167. $pkey = strlen($this->aliasListing[$thisid]['path']) ? $this->aliasListing[$thisid]['path'] : $this->aliasListing[$id]['alias'];
  1168. if (!strlen($pkey)) $pkey = "{$id}";
  1169. $parents[$pkey] = $id;
  1170. }
  1171. return $parents;
  1172. }
  1173. function getChildIds($id, $depth= 10, $children= array ()) {
  1174. // Initialise a static array to index parents->children
  1175. static $documentMap_cache = array();
  1176. if (!count($documentMap_cache)) {
  1177. foreach ($this->documentMap as $document) {
  1178. foreach ($document as $p => $c) {
  1179. $documentMap_cache[$p][] = $c;
  1180. }
  1181. }
  1182. }
  1183. // Get all the children for this parent node
  1184. if (isset($documentMap_cache[$id])) {
  1185. $depth--;
  1186. foreach ($documentMap_cache[$id] as $childId) {
  1187. $pkey = (strlen($this->aliasListing[$childId]['path']) ? "{$this->aliasListing[$childId]['path']}/" : '') . $this->aliasListing[$childId]['alias'];
  1188. if (!strlen($pkey)) $pkey = "{$childId}";
  1189. $children[$pkey] = $childId;
  1190. if ($depth) {
  1191. $children += $this->getChildIds($childId, $depth);
  1192. }
  1193. }
  1194. }
  1195. return $children;
  1196. }
  1197. # Displays a javascript alert message in the web browser
  1198. function webAlert($msg, $url= "") {
  1199. $msg= addslashes($this->db->escape($msg));
  1200. if (substr(strtolower($url), 0, 11) == "javascript:") {
  1201. $act= "__WebAlert();";
  1202. $fnc= "function __WebAlert(){" . substr($url, 11) . "};";
  1203. } else {
  1204. $act= ($url ? "window.location.href='" . addslashes($url) . "';" : "");
  1205. }
  1206. $html= "<script>$fnc window.setTimeout(\"alert('$msg');$act\",100);</script>";
  1207. if ($this->isFrontend())
  1208. $this->regClientScript($html);
  1209. else {
  1210. echo $html;
  1211. }
  1212. }
  1213. # Returns true if user has the currect permission
  1214. function hasPermission($pm) {
  1215. $state= false;
  1216. $pms= $_SESSION['mgrPermissions'];
  1217. if ($pms)
  1218. $state= ($pms[$pm] == 1);
  1219. return $state;
  1220. }
  1221. # Add an a alert message to the system event log
  1222. function logEvent($evtid, $type, $msg, $source= 'Parser') {
  1223. $msg= $this->db->escape($msg);
  1224. $source= $this->db->escape($source);
  1225. if ($GLOBALS['database_connection_charset'] == 'utf8' && extension_loaded('mbstring')) {
  1226. $source = mb_substr($source, 0, 50 , "UTF-8");
  1227. } else {
  1228. $source = substr($source, 0, 50);
  1229. }
  1230. $LoginUserID = $this->getLoginUserID();
  1231. if ($LoginUserID == '') $LoginUserID = 0;
  1232. $evtid= intval($evtid);
  1233. if ($type < 1) {
  1234. $type= 1;
  1235. }
  1236. elseif ($type > 3) {
  1237. $type= 3; // Types: 1 = information, 2 = warning, 3 = error
  1238. }
  1239. $sql= "INSERT INTO " . $this->getFullTableName("event_log") . " (eventid,type,createdon,source,description,user) " .
  1240. "VALUES($evtid,$type," . time() . ",'$source','$msg','" . $LoginUserID . "')";
  1241. $ds= @$this->db->query($sql);
  1242. if (!$ds) {
  1243. echo "Error while inserting event log into database.";
  1244. exit();
  1245. }
  1246. }
  1247. # Returns true if parser is executed in backend (manager) mode
  1248. function isBackend() {
  1249. return $this->insideManager() ? true : false;
  1250. }
  1251. # Returns true if parser is executed in frontend mode
  1252. function isFrontend() {
  1253. return !$this->insideManager() ? true : false;
  1254. }
  1255. function getAllChildren($id= 0, $sort= 'menuindex', $dir= 'ASC', $fields= 'id, pagetitle, description, parent, alias, menutitle') {
  1256. $tblsc= $this->getFullTableName("site_content");
  1257. $tbldg= $this->getFullTableName("document_groups");
  1258. // modify field names to use sc. table reference
  1259. $fields= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1260. $sort= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $sort)));
  1261. // get document groups for current user
  1262. if ($docgrp= $this->getUserDocGroups())
  1263. $docgrp= implode(",", $docgrp);
  1264. // build query
  1265. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  1266. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  1267. $sql= "SELECT DISTINCT $fields FROM $tblsc sc
  1268. LEFT JOIN $tbldg dg on dg.document = sc.id
  1269. WHERE sc.parent = '$id'
  1270. AND ($access)
  1271. GROUP BY sc.id
  1272. ORDER BY $sort $dir;";
  1273. $result= $this->db->query($sql);
  1274. $resourceArray= array ();
  1275. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  1276. array_push($resourceArray, @ $this->db->getRow($result));
  1277. }
  1278. return $resourceArray;
  1279. }
  1280. function getActiveChildren($id= 0, $sort= 'menuindex', $dir= 'ASC', $fields= 'id, pagetitle, description, parent, alias, menutitle') {
  1281. $tblsc= $this->getFullTableName("site_content");
  1282. $tbldg= $this->getFullTableName("document_groups");
  1283. // modify field names to use sc. table reference
  1284. $fields= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1285. $sort= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $sort)));
  1286. // get document groups for current user
  1287. if ($docgrp= $this->getUserDocGroups())
  1288. $docgrp= implode(",", $docgrp);
  1289. // build query
  1290. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  1291. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  1292. $sql= "SELECT DISTINCT $fields FROM $tblsc sc
  1293. LEFT JOIN $tbldg dg on dg.document = sc.id
  1294. WHERE sc.parent = '$id' AND sc.published=1 AND sc.deleted=0
  1295. AND ($access)
  1296. GROUP BY sc.id
  1297. ORDER BY $sort $dir;";
  1298. $result= $this->db->query($sql);
  1299. $resourceArray= array ();
  1300. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  1301. array_push($resourceArray, @ $this->db->getRow($result));
  1302. }
  1303. return $resourceArray;
  1304. }
  1305. function getDocumentChildren($parentid= 0, $published= 1, $deleted= 0, $fields= "*", $where= '', $sort= "menuindex", $dir= "ASC", $limit= "") {
  1306. $limit= ($limit != "") ? "LIMIT $limit" : "";
  1307. $tblsc= $this->getFullTableName("site_content");
  1308. $tbldg= $this->getFullTableName("document_groups");
  1309. // modify field names to use sc. table reference
  1310. $fields= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1311. $sort= ($sort == "") ? "" : 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $sort)));
  1312. if ($where != '')
  1313. $where= 'AND ' . $where;
  1314. // get document groups for current user
  1315. if ($docgrp= $this->getUserDocGroups())
  1316. $docgrp= implode(",", $docgrp);
  1317. // build query
  1318. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  1319. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  1320. $sql= "SELECT DISTINCT $fields
  1321. FROM $tblsc sc
  1322. LEFT JOIN $tbldg dg on dg.document = sc.id
  1323. WHERE sc.parent = '$parentid' AND sc.published=$published AND sc.deleted=$deleted $where
  1324. AND ($access)
  1325. GROUP BY sc.id " .
  1326. ($sort ? " ORDER BY $sort $dir " : "") . " $limit ";
  1327. $result= $this->db->query($sql);
  1328. $resourceArray= array ();
  1329. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  1330. array_push($resourceArray, @ $this->db->getRow($result));
  1331. }
  1332. return $resourceArray;
  1333. }
  1334. function getDocuments($ids= array (), $published= 1, $deleted= 0, $fields= "*", $where= '', $sort= "menuindex", $dir= "ASC", $limit= "") {
  1335. if (count($ids) == 0) {
  1336. return false;
  1337. } else {
  1338. $limit= ($limit != "") ? "LIMIT $limit" : ""; // LIMIT capabilities - rad14701
  1339. $tblsc= $this->getFullTableName("site_content");
  1340. $tbldg= $this->getFullTableName("document_groups");
  1341. // modify field names to use sc. table reference
  1342. $fields= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1343. $sort= ($sort == "") ? "" : 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $sort)));
  1344. if ($where != '')
  1345. $where= 'AND ' . $where;
  1346. // get document groups for current user
  1347. if ($docgrp= $this->getUserDocGroups())
  1348. $docgrp= implode(",", $docgrp);
  1349. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  1350. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  1351. $sql= "SELECT DISTINCT $fields FROM $tblsc sc
  1352. LEFT JOIN $tbldg dg on dg.document = sc.id
  1353. WHERE (sc.id IN (" . implode(",",$ids) . ") AND sc.published=$published AND sc.deleted=$deleted $where)
  1354. AND ($access)
  1355. GROUP BY sc.id " .
  1356. ($sort ? " ORDER BY $sort $dir" : "") . " $limit ";
  1357. $result= $this->db->query($sql);
  1358. $resourceArray= array ();
  1359. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  1360. array_push($resourceArray, @ $this->db->getRow($result));
  1361. }
  1362. return $resourceArray;
  1363. }
  1364. }
  1365. function getDocument($id= 0, $fields= "*", $published= 1, $deleted= 0) {
  1366. if ($id == 0) {
  1367. return false;
  1368. } else {
  1369. $tmpArr[]= $id;
  1370. $docs= $this->getDocuments($tmpArr, $published, $deleted, $fields, "", "", "", 1);
  1371. if ($docs != false) {
  1372. return $docs[0];
  1373. } else {
  1374. return false;
  1375. }
  1376. }
  1377. }
  1378. function getPageInfo($pageid= -1, $active= 1, $fields= 'id, pagetitle, description, alias') {
  1379. if ($pageid == 0) {
  1380. return false;
  1381. } else {
  1382. $tblsc= $this->getFullTableName("site_content");
  1383. $tbldg= $this->getFullTableName("document_groups");
  1384. $activeSql= $active == 1 ? "AND sc.published=1 AND sc.deleted=0" : "";
  1385. // modify field names to use sc. table reference
  1386. $fields= 'sc.' . implode(',sc.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1387. // get document groups for current user
  1388. if ($docgrp= $this->getUserDocGroups())
  1389. $docgrp= implode(",", $docgrp);
  1390. $access= ($this->isFrontend() ? "sc.privateweb=0" : "1='" . $_SESSION['mgrRole'] . "' OR sc.privatemgr=0") .
  1391. (!$docgrp ? "" : " OR dg.document_group IN ($docgrp)");
  1392. $sql= "SELECT $fields
  1393. FROM $tblsc sc
  1394. LEFT JOIN $tbldg dg on dg.document = sc.id
  1395. WHERE (sc.id=$pageid $activeSql)
  1396. AND ($access)
  1397. LIMIT 1 ";
  1398. $result= $this->db->query($sql);
  1399. $pageInfo= @ $this->db->getRow($result);
  1400. return $pageInfo;
  1401. }
  1402. }
  1403. function getParent($pid= -1, $active= 1, $fields= 'id, pagetitle, description, alias, parent') {
  1404. if ($pid == -1) {
  1405. $pid= $this->documentObject['parent'];
  1406. return ($pid == 0) ? false : $this->getPageInfo($pid, $active, $fields);
  1407. } else
  1408. if ($pid == 0) {
  1409. return false;
  1410. } else {
  1411. // first get the child document
  1412. $child= $this->getPageInfo($pid, $active, "parent");
  1413. // now return the child's parent
  1414. $pid= ($child['parent']) ? $child['parent'] : 0;
  1415. return ($pid == 0) ? false : $this->getPageInfo($pid, $active, $fields);
  1416. }
  1417. }
  1418. function getSnippetId() {
  1419. if ($this->currentSnippet) {
  1420. $tbl= $this->getFullTableName("site_snippets");
  1421. $rs= $this->db->query("SELECT id FROM $tbl WHERE name='" . $this->db->escape($this->currentSnippet) . "' LIMIT 1");
  1422. $row= @ $this->db->getRow($rs);
  1423. if ($row['id'])
  1424. return $row['id'];
  1425. }
  1426. return 0;
  1427. }
  1428. function getSnippetName() {
  1429. return $this->currentSnippet;
  1430. }
  1431. function clearCache() {
  1432. $basepath= $this->config["base_path"] . "assets/cache";
  1433. if (@ $handle= opendir($basepath)) {
  1434. $filesincache= 0;
  1435. $deletedfilesincache= 0;
  1436. while (false !== ($file= readdir($handle))) {
  1437. if ($file != "." && $file != "..") {
  1438. $filesincache += 1;
  1439. if (preg_match("/\.pageCache/", $file)) {
  1440. $deletedfilesincache += 1;
  1441. unlink($basepath . "/" . $file);
  1442. }
  1443. }
  1444. }
  1445. closedir($handle);
  1446. return true;
  1447. } else {
  1448. return false;
  1449. }
  1450. }
  1451. function makeUrl($id, $alias= '', $args= '', $scheme= '') {
  1452. $url= '';
  1453. $virtualDir= '';
  1454. $f_url_prefix = $this->config['friendly_url_prefix'];
  1455. $f_url_suffix = $this->config['friendly_url_suffix'];
  1456. if (!is_numeric($id)) {
  1457. $this->messageQuit('`' . $id . '` is not numeric and may not be passed to makeUrl()');
  1458. }
  1459. if ($args != '' && $this->config['friendly_urls'] == 1) {
  1460. // add ? to $args if missing
  1461. $c= substr($args, 0, 1);
  1462. if (strpos($f_url_prefix, '?') === false) {
  1463. if ($c == '&')
  1464. $args= '?' . substr($args, 1);
  1465. elseif ($c != '?') $args= '?' . $args;
  1466. } else {
  1467. if ($c == '?')
  1468. $args= '&' . substr($args, 1);
  1469. elseif ($c != '&') $args= '&' . $args;
  1470. }
  1471. }
  1472. elseif ($args != '') {
  1473. // add & to $args if missing
  1474. $c= substr($args, 0, 1);
  1475. if ($c == '?')
  1476. $args= '&' . substr($args, 1);
  1477. elseif ($c != '&') $args= '&' . $args;
  1478. }
  1479. if ($this->config['friendly_urls'] == 1 && $alias != '') {
  1480. $url= $f_url_prefix . $alias . $f_url_suffix . $args;
  1481. }
  1482. elseif ($this->config['friendly_urls'] == 1 && $alias == '') {
  1483. $alias= $id;
  1484. if ($this->config['friendly_alias_urls'] == 1) {
  1485. $al= $this->aliasListing[$id];
  1486. $alPath= !empty ($al['path']) ? $al['path'] . '/' : '';
  1487. if ($al && $al['alias'])
  1488. $alias= $al['alias'];
  1489. }
  1490. $alias= $alPath . $f_url_prefix . $alias . $f_url_suffix;
  1491. $url= $alias . $args;
  1492. } else {
  1493. $url= 'index.php?id=' . $id . $args;
  1494. }
  1495. $host= $this->config['base_url'];
  1496. // check if scheme argument has been set
  1497. if ($scheme != '') {
  1498. // for backward compatibility - check if the desired scheme is different than the current scheme
  1499. if (is_numeric($scheme) && $scheme != $_SERVER['HTTPS']) {
  1500. $scheme= ($_SERVER['HTTPS'] ? 'http' : 'https');
  1501. }
  1502. // to-do: check to make sure that $site_url incudes the url :port (e.g. :8080)
  1503. $host= $scheme == 'full' ? $this->config['site_url'] : $scheme . '://' . $_SERVER['HTTP_HOST'] . $host;
  1504. }
  1505. if ($this->config['xhtml_urls']) {
  1506. return preg_replace("/&(?!amp;)/","&amp;", $host . $virtualDir . $url);
  1507. } else {
  1508. return $host . $virtualDir . $url;
  1509. }
  1510. }
  1511. function getConfig($name= '') {
  1512. if (!empty ($this->config[$name])) {
  1513. return $this->config[$name];
  1514. } else {
  1515. return false;
  1516. }
  1517. }
  1518. function getVersionData() {
  1519. include $this->config["base_path"] . "manager/includes/version.inc.php";
  1520. $v= array ();
  1521. $v['version']= $modx_version;
  1522. $v['branch']= $modx_branch;
  1523. $v['release_date']= $modx_release_date;
  1524. $v['full_appname']= $modx_full_appname;
  1525. return $v;
  1526. }
  1527. function makeList($array, $ulroot= 'root', $ulprefix= 'sub_', $type= '', $ordered= false, $tablevel= 0) {
  1528. // first find out whether the value passed is an array
  1529. if (!is_array($array)) {
  1530. return "<ul><li>Bad list</li></ul>";
  1531. }
  1532. if (!empty ($type)) {
  1533. $typestr= " style='list-style-type: $type'";
  1534. } else {
  1535. $typestr= "";
  1536. }
  1537. $tabs= "";
  1538. for ($i= 0; $i < $tablevel; $i++) {
  1539. $tabs .= "\t";
  1540. }
  1541. $listhtml= $ordered == true ? $tabs . "<ol class='$ulroot'$typestr>\n" : $tabs . "<ul class='$ulroot'$typestr>\n";
  1542. foreach ($array as $key => $value) {
  1543. if (is_array($value)) {
  1544. $listhtml .= $tabs . "\t<li>" . $key . "\n" . $this->makeList($value, $ulprefix . $ulroot, $ulprefix, $type, $ordered, $tablevel +2) . $tabs . "\t</li>\n";
  1545. } else {
  1546. $listhtml .= $tabs . "\t<li>" . $value . "</li>\n";
  1547. }
  1548. }
  1549. $listhtml .= $ordered == true ? $tabs . "</ol>\n" : $tabs . "</ul>\n";
  1550. return $listhtml;
  1551. }
  1552. function userLoggedIn() {
  1553. $userdetails= array ();
  1554. if ($this->isFrontend() && isset ($_SESSION['webValidated'])) {
  1555. // web user
  1556. $userdetails['loggedIn']= true;
  1557. $userdetails['id']= $_SESSION['webInternalKey'];
  1558. $userdetails['username']= $_SESSION['webShortname'];
  1559. $userdetails['usertype']= 'web'; // added by Raymond
  1560. return $userdetails;
  1561. } else
  1562. if ($this->isBackend() && isset ($_SESSION['mgrValidated'])) {
  1563. // manager user
  1564. $userdetails['loggedIn']= true;
  1565. $userdetails['id']= $_SESSION['mgrInternalKey'];
  1566. $userdetails['username']= $_SESSION['mgrShortname'];
  1567. $userdetails['usertype']= 'manager'; // added by Raymond
  1568. return $userdetails;
  1569. } else {
  1570. return false;
  1571. }
  1572. }
  1573. function getKeywords($id= 0) {
  1574. if ($id == 0) {
  1575. $id= $this->documentObject['id'];
  1576. }
  1577. $tblKeywords= $this->getFullTableName('site_keywords');
  1578. $tblKeywordXref= $this->getFullTableName('keyword_xref');
  1579. $sql= "SELECT keywords.keyword FROM " . $tblKeywords . " AS keywords INNER JOIN " . $tblKeywordXref . " AS xref ON keywords.id=xref.keyword_id WHERE xref.content_id = '$id'";
  1580. $result= $this->db->query($sql);
  1581. $limit= $this->db->getRecordCount($result);
  1582. $keywords= array ();
  1583. if ($limit > 0) {
  1584. for ($i= 0; $i < $limit; $i++) {
  1585. $row= $this->db->getRow($result);
  1586. $keywords[]= $row['keyword'];
  1587. }
  1588. }
  1589. return $keywords;
  1590. }
  1591. function getMETATags($id= 0) {
  1592. if ($id == 0) {
  1593. $id= $this->documentObject['id'];
  1594. }
  1595. $sql= "SELECT smt.* " .
  1596. "FROM " . $this->getFullTableName("site_metatags") . " smt " .
  1597. "INNER JOIN " . $this->getFullTableName("site_content_metatags") . " cmt ON cmt.metatag_id=smt.id " .
  1598. "WHERE cmt.content_id = '$id'";
  1599. $ds= $this->db->query($sql);
  1600. $limit= $this->db->getRecordCount($ds);
  1601. $metatags= array ();
  1602. if ($limit > 0) {
  1603. for ($i= 0; $i < $limit; $i++) {
  1604. $row= $this->db->getRow($ds);
  1605. $metatags[$row['name']]= array (
  1606. "tag" => $row['tag'],
  1607. "tagvalue" => $row['tagvalue'],
  1608. "http_equiv" => $row['http_equiv']
  1609. );
  1610. }
  1611. }
  1612. return $metatags;
  1613. }
  1614. function runSnippet($snippetName, $params= array ()) {
  1615. if (isset ($this->snippetCache[$snippetName])) {
  1616. $snippet= $this->snippetCache[$snippetName];
  1617. $properties= $this->snippetCache[$snippetName . "Props"];
  1618. } else { // not in cache so let's check the db
  1619. $sql= "SELECT `name`, `snippet`, `properties` FROM " . $this->getFullTableName("site_snippets") . " WHERE " . $this->getFullTableName("site_snippets") . ".`name`='" . $this->db->escape($snippetName) . "';";
  1620. $result= $this->db->query($sql);
  1621. if ($this->db->getRecordCount($result) == 1) {
  1622. $row= $this->db->getRow($result);
  1623. $snippet= $this->snippetCache[$row['name']]= $row['snippet'];
  1624. $properties= $this->snippetCache[$row['name'] . "Props"]= $row['properties'];
  1625. } else {
  1626. $snippet= $this->snippetCache[$snippetName]= "return false;";
  1627. $properties= '';
  1628. }
  1629. }
  1630. // load default params/properties
  1631. $parameters= $this->parseProperties($properties);
  1632. $parameters= array_merge($parameters, $params);
  1633. // run snippet
  1634. return $this->evalSnippet($snippet, $parameters);
  1635. }
  1636. function getChunk($chunkName) {
  1637. $t= $this->chunkCache[$chunkName];
  1638. return $t;
  1639. }
  1640. // deprecated
  1641. function putChunk($chunkName) { // alias name >.<
  1642. return $this->getChunk($chunkName);
  1643. }
  1644. function parseChunk($chunkName, $chunkArr, $prefix= "{", $suffix= "}") {
  1645. if (!is_array($chunkArr)) {
  1646. return false;
  1647. }
  1648. $chunk= $this->getChunk($chunkName);
  1649. foreach ($chunkArr as $key => $value) {
  1650. $chunk= str_replace($prefix . $key . $suffix, $value, $chunk);
  1651. }
  1652. return $chunk;
  1653. }
  1654. function getUserData() {
  1655. include $this->config["base_path"] . "manager/includes/extenders/getUserData.extender.php";
  1656. return $tmpArray;
  1657. }
  1658. function toDateFormat($timestamp = 0, $mode = '') {
  1659. $timestamp = trim($timestamp);
  1660. $timestamp = intval($timestamp);
  1661. switch($this->config['datetime_format']) {
  1662. case 'YYYY/mm/dd':
  1663. $dateFormat = '%Y/%m/%d';
  1664. break;
  1665. case 'dd-mm-YYYY':
  1666. $dateFormat = '%d-%m-%Y';
  1667. break;
  1668. case 'mm/dd/YYYY':
  1669. $dateFormat = '%m/%d/%Y';
  1670. break;
  1671. /*
  1672. case 'dd-mmm-YYYY':
  1673. $dateFormat = '%e-%b-%Y';
  1674. break;
  1675. */
  1676. }
  1677. if (empty($mode)) {
  1678. $strTime = strftime($dateFormat . " %H:%M:%S", $timestamp);
  1679. } elseif ($mode == 'dateOnly') {
  1680. $strTime = strftime($dateFormat, $timestamp);
  1681. } elseif ($mode == 'formatOnly') {
  1682. $strTime = $dateFormat;
  1683. }
  1684. return $strTime;
  1685. }
  1686. function toTimeStamp($str) {
  1687. $str = trim($str);
  1688. if (empty($str)) {return '';}
  1689. switch($this->config['datetime_format']) {
  1690. case 'YYYY/mm/dd':
  1691. if (!preg_match('/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}[0-9 :]*$/', $str)) {return '';}
  1692. list ($Y, $m, $d, $H, $M, $S) = sscanf($str, '%4d/%2d/%2d %2d:%2d:%2d');
  1693. break;
  1694. case 'dd-mm-YYYY':
  1695. if (!preg_match('/^[0-9]{2}-[0-9]{2}-[0-9]{4}[0-9 :]*$/', $str)) {return '';}
  1696. list ($d, $m, $Y, $H, $M, $S) = sscanf($str, '%2d-%2d-%4d %2d:%2d:%2d');
  1697. break;
  1698. case 'mm/dd/YYYY':
  1699. if (!preg_match('/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}[0-9 :]*$/', $str)) {return '';}
  1700. list ($m, $d, $Y, $H, $M, $S) = sscanf($str, '%2d/%2d/%4d %2d:%2d:%2d');
  1701. break;
  1702. /*
  1703. case 'dd-mmm-YYYY':
  1704. if (!preg_match('/^[0-9]{2}-[0-9a-z]+-[0-9]{4}[0-9 :]*$/i', $str)) {return '';}
  1705. list ($m, $d, $Y, $H, $M, $S) = sscanf($str, '%2d-%3s-%4d %2d:%2d:%2d');
  1706. break;
  1707. */
  1708. }
  1709. if (!$H && !$M && !$S) {$H = 0; $M = 0; $S = 0;}
  1710. $timeStamp = mktime($H, $M, $S, $m, $d, $Y);
  1711. $timeStamp = intval($timeStamp);
  1712. return $timeStamp;
  1713. }
  1714. #::::::::::::::::::::::::::::::::::::::::
  1715. # Added By: Raymond Irving - MODx
  1716. #
  1717. function getDocumentChildrenTVars($parentid= 0, $tvidnames= array (), $published= 1, $docsort= "menuindex", $docsortdir= "ASC", $tvfields= "*", $tvsort= "rank", $tvsortdir= "ASC") {
  1718. $docs= $this->getDocumentChildren($parentid, $published, 0, '*', '', $docsort, $docsortdir);
  1719. if (!$docs)
  1720. return false;
  1721. else {
  1722. $result= array ();
  1723. // get user defined template variables
  1724. $fields= ($tvfields == "") ? "tv.*" : 'tv.' . implode(',tv.', preg_replace("/^\s/i", "", explode(',', $tvfields)));
  1725. $tvsort= ($tvsort == "") ? "" : 'tv.' . implode(',tv.', preg_replace("/^\s/i", "", explode(',', $tvsort)));
  1726. if ($tvidnames == "*")
  1727. $query= "tv.id<>0";
  1728. else
  1729. $query= (is_numeric($tvidnames[0]) ? "tv.id" : "tv.name") . " IN ('" . implode("','", $tvidnames) . "')";
  1730. if ($docgrp= $this->getUserDocGroups())
  1731. $docgrp= implode(",", $docgrp);
  1732. $docCount= count($docs);
  1733. for ($i= 0; $i < $docCount; $i++) {
  1734. $tvs= array ();
  1735. $docRow= $docs[$i];
  1736. $docid= $docRow['id'];
  1737. $sql= "SELECT $fields, IF(tvc.value!='',tvc.value,tv.default_text) as value ";
  1738. $sql .= "FROM " . $this->getFullTableName('site_tmplvars') . " tv ";
  1739. $sql .= "INNER JOIN " . $this->getFullTableName('site_tmplvar_templates')." tvtpl ON tvtpl.tmplvarid = tv.id ";
  1740. $sql .= "LEFT JOIN " . $this->getFullTableName('site_tmplvar_contentvalues')." tvc ON tvc.tmplvarid=tv.id AND tvc.contentid = '" . $docid . "' ";
  1741. $sql .= "WHERE " . $query . " AND tvtpl.templateid = " . $docRow['template'];
  1742. if ($tvsort)
  1743. $sql .= " ORDER BY $tvsort $tvsortdir ";
  1744. $rs= $this->db->query($sql);
  1745. $limit= @ $this->db->getRecordCount($rs);
  1746. for ($x= 0; $x < $limit; $x++) {
  1747. array_push($tvs, @ $this->db->getRow($rs));
  1748. }
  1749. // get default/built-in template variables
  1750. ksort($docRow);
  1751. foreach ($docRow as $key => $value) {
  1752. if ($tvidnames == "*" || in_array($key, $tvidnames))
  1753. array_push($tvs, array (
  1754. "name" => $key,
  1755. "value" => $value
  1756. ));
  1757. }
  1758. if (count($tvs))
  1759. array_push($result, $tvs);
  1760. }
  1761. return $result;
  1762. }
  1763. }
  1764. function getDocumentChildrenTVarOutput($parentid= 0, $tvidnames= array (), $published= 1, $docsort= "menuindex", $docsortdir= "ASC") {
  1765. $docs= $this->getDocumentChildren($parentid, $published, 0, '*', '', $docsort, $docsortdir);
  1766. if (!$docs)
  1767. return false;
  1768. else {
  1769. $result= array ();
  1770. for ($i= 0; $i < count($docs); $i++) {
  1771. $tvs= $this->getTemplateVarOutput($tvidnames, $docs[$i]["id"], $published);
  1772. if ($tvs)
  1773. $result[$docs[$i]['id']]= $tvs; // Use docid as key - netnoise 2006/08/14
  1774. }
  1775. return $result;
  1776. }
  1777. }
  1778. // Modified by Raymond for TV - Orig Modified by Apodigm - DocVars
  1779. # returns a single TV record. $idnames - can be an id or name that belongs the template that the current document is using
  1780. function getTemplateVar($idname= "", $fields= "*", $docid= "", $published= 1) {
  1781. if ($idname == "") {
  1782. return false;
  1783. } else {
  1784. $result= $this->getTemplateVars(array ($idname), $fields, $docid, $published, "", ""); //remove sorting for speed
  1785. return ($result != false) ? $result[0] : false;
  1786. }
  1787. }
  1788. # returns an array of TV records. $idnames - can be an id or name that belongs the template that the current document is using
  1789. function getTemplateVars($idnames= array (), $fields= "*", $docid= "", $published= 1, $sort= "rank", $dir= "ASC") {
  1790. if (($idnames != '*' && !is_array($idnames)) || count($idnames) == 0) {
  1791. return false;
  1792. } else {
  1793. $result= array ();
  1794. // get document record
  1795. if ($docid == "") {
  1796. $docid= $this->documentIdentifier;
  1797. $docRow= $this->documentObject;
  1798. } else {
  1799. $docRow= $this->getDocument($docid, '*', $published);
  1800. if (!$docRow)
  1801. return false;
  1802. }
  1803. // get user defined template variables
  1804. $fields= ($fields == "") ? "tv.*" : 'tv.' . implode(',tv.', preg_replace("/^\s/i", "", explode(',', $fields)));
  1805. $sort= ($sort == "") ? "" : 'tv.' . implode(',tv.', preg_replace("/^\s/i", "", explode(',', $sort)));
  1806. if ($idnames == "*")
  1807. $query= "tv.id<>0";
  1808. else
  1809. $query= (is_numeric($idnames[0]) ? "tv.id" : "tv.name") . " IN ('" . implode("','", $idnames) . "')";
  1810. if ($docgrp= $this->getUserDocGroups())
  1811. $docgrp= implode(",", $docgrp);
  1812. $sql= "SELECT $fields, IF(tvc.value!='',tvc.value,tv.default_text) as value ";
  1813. $sql .= "FROM " . $this->getFullTableName('site_tmplvars')." tv ";
  1814. $sql .= "INNER JOIN " . $this->getFullTableName('site_tmplvar_templates')." tvtpl ON tvtpl.tmplvarid = tv.id ";
  1815. $sql .= "LEFT JOIN " . $this->getFullTableName('site_tmplvar_contentvalues')." tvc ON tvc.tmplvarid=tv.id AND tvc.contentid = '" . $docid . "' ";
  1816. $sql .= "WHERE " . $query . " AND tvtpl.templateid = " . $docRow['template'];
  1817. if ($sort)
  1818. $sql .= " ORDER BY $sort $dir ";
  1819. $rs= $this->db->query($sql);
  1820. for ($i= 0; $i < @ $this->db->getRecordCount($rs); $i++) {
  1821. array_push($result, @ $this->db->getRow($rs));
  1822. }
  1823. // get default/built-in template variables
  1824. ksort($docRow);
  1825. foreach ($docRow as $key => $value) {
  1826. if ($idnames == "*" || in_array($key, $idnames))
  1827. array_push($result, array (
  1828. "name" => $key,
  1829. "value" => $value
  1830. ));
  1831. }
  1832. return $result;
  1833. }
  1834. }
  1835. # returns an associative array containing TV rendered output values. $idnames - can be an id or name that belongs the template that the current document is using
  1836. function getTemplateVarOutput($idnames= array (), $docid= "", $published= 1, $sep='') {
  1837. if (count($idnames) == 0) {
  1838. return false;
  1839. } else {
  1840. $output= array ();
  1841. $vars= ($idnames == '*' || is_array($idnames)) ? $idnames : array ($idnames);
  1842. $docid= intval($docid) ? intval($docid) : $this->documentIdentifier;
  1843. $result= $this->getTemplateVars($vars, "*", $docid, $published, "", "", $sep); // remove sort for speed
  1844. if ($result == false)
  1845. return false;
  1846. else {
  1847. $baspath= $this->config["base_path"] . "manager/includes";
  1848. include_once $baspath . "/tmplvars.format.inc.php";
  1849. include_once $baspath . "/tmplvars.commands.inc.php";
  1850. for ($i= 0; $i < count($result); $i++) {
  1851. $row= $result[$i];
  1852. if (!$row['id'])
  1853. $output[$row['name']]= $row['value'];
  1854. else $output[$row['name']]= getTVDisplayFormat($row['name'], $row['value'], $row['display'], $row['display_params'], $row['type'], $docid, $sep);
  1855. }
  1856. return $output;
  1857. }
  1858. }
  1859. }
  1860. # returns the full table name based on db settings
  1861. function getFullTableName($tbl) {
  1862. return $this->db->config['dbase'] . ".`" . $this->db->config['table_prefix'] . $tbl . "`";
  1863. }
  1864. # return placeholder value
  1865. function getPlaceholder($name) {
  1866. return $this->placeholders[$name];
  1867. }
  1868. # sets a value for a placeholder
  1869. function setPlaceholder($name, $value) {
  1870. $this->placeholders[$name]= $value;
  1871. }
  1872. # set arrays or object vars as placeholders
  1873. function toPlaceholders($subject, $prefix= '') {
  1874. if (is_object($subject)) {
  1875. $subject= get_object_vars($subject);
  1876. }
  1877. if (is_array($subject)) {
  1878. foreach ($subject as $key => $value) {
  1879. $this->toPlaceholder($key, $value, $prefix);
  1880. }
  1881. }
  1882. }
  1883. function toPlaceholder($key, $value, $prefix= '') {
  1884. if (is_array($value) || is_object($value)) {
  1885. $this->toPlaceholders($value, "{$prefix}{$key}.");
  1886. } else {
  1887. $this->setPlaceholder("{$prefix}{$key}", $value);
  1888. }
  1889. }
  1890. # returns the virtual relative path to the manager folder
  1891. function getManagerPath() {
  1892. global $base_url;
  1893. $pth= $base_url . 'manager/';
  1894. return $pth;
  1895. }
  1896. # returns the virtual relative path to the cache folder
  1897. function getCachePath() {
  1898. global $base_url;
  1899. $pth= $base_url . 'assets/cache/';
  1900. return $pth;
  1901. }
  1902. # sends a message to a user's message box
  1903. function sendAlert($type, $to, $from, $subject, $msg, $private= 0) {
  1904. $private= ($private) ? 1 : 0;
  1905. if (!is_numeric($to)) {
  1906. // Query for the To ID
  1907. $sql= "SELECT id FROM " . $this->getFullTableName("manager_users") . " WHERE username='$to';";
  1908. $rs= $this->db->query($sql);
  1909. if ($this->db->getRecordCount($rs)) {
  1910. $rs= $this->db->getRow($rs);
  1911. $to= $rs['id'];
  1912. }
  1913. }
  1914. if (!is_numeric($from)) {
  1915. // Query for the From ID
  1916. $sql= "SELECT id FROM " . $this->getFullTableName("manager_users") . " WHERE username='$from';";
  1917. $rs= $this->db->query($sql);
  1918. if ($this->db->getRecordCount($rs)) {
  1919. $rs= $this->db->getRow($rs);
  1920. $from= $rs['id'];
  1921. }
  1922. }
  1923. // insert a new message into user_messages
  1924. $sql= "INSERT INTO " . $this->getFullTableName("user_messages") . " ( id , type , subject , message , sender , recipient , private , postdate , messageread ) VALUES ( '', '$type', '$subject', '$msg', '$from', '$to', '$private', '" . time() . "', '0' );";
  1925. $rs= $this->db->query($sql);
  1926. }
  1927. # Returns true, install or interact when inside manager
  1928. // deprecated
  1929. function insideManager() {
  1930. $m= false;
  1931. if (defined('IN_MANAGER_MODE') && IN_MANAGER_MODE == 'true') {
  1932. $m= true;
  1933. if (defined('SNIPPET_INTERACTIVE_MODE') && SNIPPET_INTERACTIVE_MODE == 'true')
  1934. $m= "interact";
  1935. else
  1936. if (defined('SNIPPET_INSTALL_MODE') && SNIPPET_INSTALL_MODE == 'true')
  1937. $m= "install";
  1938. }
  1939. return $m;
  1940. }
  1941. # Returns current user id
  1942. function getLoginUserID($context= '') {
  1943. if ($context && isset ($_SESSION[$context . 'Validated'])) {
  1944. return $_SESSION[$context . 'InternalKey'];
  1945. }
  1946. elseif ($this->isFrontend() && isset ($_SESSION['webValidated'])) {
  1947. return $_SESSION['webInternalKey'];
  1948. }
  1949. elseif ($this->isBackend() && isset ($_SESSION['mgrValidated'])) {
  1950. return $_SESSION['mgrInternalKey'];
  1951. }
  1952. }
  1953. # Returns current user name
  1954. function getLoginUserName($context= '') {
  1955. if (!empty($context) && isset ($_SESSION[$context . 'Validated'])) {
  1956. return $_SESSION[$context . 'Shortname'];
  1957. }
  1958. elseif ($this->isFrontend() && isset ($_SESSION['webValidated'])) {
  1959. return $_SESSION['webShortname'];
  1960. }
  1961. elseif ($this->isBackend() && isset ($_SESSION['mgrValidated'])) {
  1962. return $_SESSION['mgrShortname'];
  1963. }
  1964. }
  1965. # Returns current login user type - web or manager
  1966. function getLoginUserType() {
  1967. if ($this->isFrontend() && isset ($_SESSION['webValidated'])) {
  1968. return 'web';
  1969. }
  1970. elseif ($this->isBackend() && isset ($_SESSION['mgrValidated'])) {
  1971. return 'manager';
  1972. } else {
  1973. return '';
  1974. }
  1975. }
  1976. # Returns a record for the manager user
  1977. function getUserInfo($uid) {
  1978. $sql= "
  1979. SELECT mu.username, mu.password, mua.*
  1980. FROM " . $this->getFullTableName("manager_users") . " mu
  1981. INNER JOIN " . $this->getFullTableName("user_attributes") . " mua ON mua.internalkey=mu.id
  1982. WHERE mu.id = '$uid'
  1983. ";
  1984. $rs= $this->db->query($sql);
  1985. $limit= mysql_num_rows($rs);
  1986. if ($limit == 1) {
  1987. $row= $this->db->getRow($rs);
  1988. if (!$row["usertype"])
  1989. $row["usertype"]= "manager";
  1990. return $row;
  1991. }
  1992. }
  1993. # Returns a record for the web user
  1994. function getWebUserInfo($uid) {
  1995. $sql= "
  1996. SELECT wu.username, wu.password, wua.*
  1997. FROM " . $this->getFullTableName("web_users") . " wu
  1998. INNER JOIN " . $this->getFullTableName("web_user_attributes") . " wua ON wua.internalkey=wu.id
  1999. WHERE wu.id='$uid'
  2000. ";
  2001. $rs= $this->db->query($sql);
  2002. $limit= mysql_num_rows($rs);
  2003. if ($limit == 1) {
  2004. $row= $this->db->getRow($rs);
  2005. if (!$row["usertype"])
  2006. $row["usertype"]= "web";
  2007. return $row;
  2008. }
  2009. }
  2010. # Returns an array of document groups that current user is assigned to.
  2011. # This function will first return the web user doc groups when running from frontend otherwise it will return manager user's docgroup
  2012. # Set $resolveIds to true to return the document group names
  2013. function getUserDocGroups($resolveIds= false) {
  2014. if ($this->isFrontend() && isset ($_SESSION['webDocgroups']) && isset ($_SESSION['webValidated'])) {
  2015. $dg= $_SESSION['webDocgroups'];
  2016. $dgn= isset ($_SESSION['webDocgrpNames']) ? $_SESSION['webDocgrpNames'] : false;
  2017. } else
  2018. if ($this->isBackend() && isset ($_SESSION['mgrDocgroups']) && isset ($_SESSION['mgrValidated'])) {
  2019. $dg= $_SESSION['mgrDocgroups'];
  2020. $dgn= $_SESSION['mgrDocgrpNames'];
  2021. } else {
  2022. $dg= '';
  2023. }
  2024. if (!$resolveIds)
  2025. return $dg;
  2026. else
  2027. if (is_array($dgn))
  2028. return $dgn;
  2029. else
  2030. if (is_array($dg)) {
  2031. // resolve ids to names
  2032. $dgn= array ();
  2033. $tbl= $this->getFullTableName("documentgroup_names");
  2034. $ds= $this->db->query("SELECT name FROM $tbl WHERE id IN (" . implode(",", $dg) . ")");
  2035. while ($row= $this->db->getRow($ds))
  2036. $dgn[count($dgn)]= $row['name'];
  2037. // cache docgroup names to session
  2038. if ($this->isFrontend())
  2039. $_SESSION['webDocgrpNames']= $dgn;
  2040. else
  2041. $_SESSION['mgrDocgrpNames']= $dgn;
  2042. return $dgn;
  2043. }
  2044. }
  2045. function getDocGroups() {
  2046. return $this->getUserDocGroups();
  2047. } // deprecated
  2048. # Change current web user's password - returns true if successful, oterhwise return error message
  2049. function changeWebUserPassword($oldPwd, $newPwd) {
  2050. $rt= false;
  2051. if ($_SESSION["webValidated"] == 1) {
  2052. $tbl= $this->getFullTableName("web_users");
  2053. $ds= $this->db->query("SELECT `id`, `username`, `password` FROM $tbl WHERE `id`='" . $this->getLoginUserID() . "'");
  2054. $limit= mysql_num_rows($ds);
  2055. if ($limit == 1) {
  2056. $row= $this->db->getRow($ds);
  2057. if ($row["password"] == md5($oldPwd)) {
  2058. if (strlen($newPwd) < 6) {
  2059. return "Password is too short!";
  2060. }
  2061. elseif ($newPwd == "") {
  2062. return "You didn't specify a password for this user!";
  2063. } else {
  2064. $this->db->query("UPDATE $tbl SET password = md5('" . $this->db->escape($newPwd) . "') WHERE id='" . $this->getLoginUserID() . "'");
  2065. // invoke OnWebChangePassword event
  2066. $this->invokeEvent("OnWebChangePassword", array (
  2067. "userid" => $row["id"],
  2068. "username" => $row["username"],
  2069. "userpassword" => $newPwd
  2070. ));
  2071. return true;
  2072. }
  2073. } else {
  2074. return "Incorrect password.";
  2075. }
  2076. }
  2077. }
  2078. }
  2079. function changePassword($o, $n) {
  2080. return changeWebUserPassword($o, $n);
  2081. } // deprecated
  2082. # returns true if the current web user is a member the specified groups
  2083. function isMemberOfWebGroup($groupNames= array ()) {
  2084. if (!is_array($groupNames))
  2085. return false;
  2086. // check cache
  2087. $grpNames= isset ($_SESSION['webUserGroupNames']) ? $_SESSION['webUserGroupNames'] : false;
  2088. if (!is_array($grpNames)) {
  2089. $tbl= $this->getFullTableName("webgroup_names");
  2090. $tbl2= $this->getFullTableName("web_groups");
  2091. $sql= "SELECT wgn.name
  2092. FROM $tbl wgn
  2093. INNER JOIN $tbl2 wg ON wg.webgroup=wgn.id AND wg.webuser='" . $this->getLoginUserID() . "'";
  2094. $grpNames= $this->db->getColumn("name", $sql);
  2095. // save to cache
  2096. $_SESSION['webUserGroupNames']= $grpNames;
  2097. }
  2098. foreach ($groupNames as $k => $v)
  2099. if (in_array(trim($v), $grpNames))
  2100. return true;
  2101. return false;
  2102. }
  2103. # Registers Client-side CSS scripts - these scripts are loaded at inside the <head> tag
  2104. function regClientCSS($src, $media='') {
  2105. if (empty($src) || isset ($this->loadedjscripts[$src]))
  2106. return '';
  2107. $nextpos= max(array_merge(array(0),array_keys($this->sjscripts)))+1;
  2108. $this->loadedjscripts[$src]['startup']= true;
  2109. $this->loadedjscripts[$src]['version']= '0';
  2110. $this->loadedjscripts[$src]['pos']= $nextpos;
  2111. if (strpos(strtolower($src), "<style") !== false || strpos(strtolower($src), "<link") !== false) {
  2112. $this->sjscripts[$nextpos]= $src;
  2113. } else {
  2114. $this->sjscripts[$nextpos]= "\t" . '<link rel="stylesheet" type="text/css" href="'.$src.'" '.($media ? 'media="'.$media.'" ' : '').'/>';
  2115. }
  2116. }
  2117. # Registers Startup Client-side JavaScript - these scripts are loaded at inside the <head> tag
  2118. function regClientStartupScript($src, $options= array('name'=>'', 'version'=>'0', 'plaintext'=>false)) {
  2119. $this->regClientScript($src, $options, true);
  2120. }
  2121. # Registers Client-side JavaScript - these scripts are loaded at the end of the page unless $startup is true
  2122. function regClientScript($src, $options= array('name'=>'', 'version'=>'0', 'plaintext'=>false), $startup= false) {
  2123. if (empty($src))
  2124. return ''; // nothing to register
  2125. if (!is_array($options)) {
  2126. if (is_bool($options)) // backward compatibility with old plaintext parameter
  2127. $options=array('plaintext'=>$options);
  2128. elseif (is_string($options)) // Also allow script name as 2nd param
  2129. $options=array('name'=>$options);
  2130. else
  2131. $options=array();
  2132. }
  2133. $name= isset($options['name']) ? strtolower($options['name']) : '';
  2134. $version= isset($options['version']) ? $options['version'] : '0';
  2135. $plaintext= isset($options['plaintext']) ? $options['plaintext'] : false;
  2136. $key= !empty($name) ? $name : $src;
  2137. unset($overwritepos); // probably unnecessary--just making sure
  2138. $useThisVer= true;
  2139. if (isset($this->loadedjscripts[$key])) { // a matching script was found
  2140. // if existing script is a startup script, make sure the candidate is also a startup script
  2141. if ($this->loadedjscripts[$key]['startup'])
  2142. $startup= true;
  2143. if (empty($name)) {
  2144. $useThisVer= false; // if the match was based on identical source code, no need to replace the old one
  2145. } else {
  2146. $useThisVer = version_compare($this->loadedjscripts[$key]['version'], $version, '<');
  2147. }
  2148. if ($useThisVer) {
  2149. if ($startup==true && $this->loadedjscripts[$key]['startup']==false) {
  2150. // remove old script from the bottom of the page (new one will be at the top)
  2151. unset($this->jscripts[$this->loadedjscripts[$key]['pos']]);
  2152. } else {
  2153. // overwrite the old script (the position may be important for dependent scripts)
  2154. $overwritepos= $this->loadedjscripts[$key]['pos'];
  2155. }
  2156. } else { // Use the original version
  2157. if ($startup==true && $this->loadedjscripts[$key]['startup']==false) {
  2158. // need to move the exisiting script to the head
  2159. $version= $this->loadedjscripts[$key][$version];
  2160. $src= $this->jscripts[$this->loadedjscripts[$key]['pos']];
  2161. unset($this->jscripts[$this->loadedjscripts[$key]['pos']]);
  2162. } else {
  2163. return ''; // the script is already in the right place
  2164. }
  2165. }
  2166. }
  2167. if ($useThisVer && $plaintext!=true && (strpos(strtolower($src), "<script") === false))
  2168. $src= "\t" . '<script type="text/javascript" src="' . $src . '"></script>';
  2169. if ($startup) {
  2170. $pos= isset($overwritepos) ? $overwritepos : max(array_merge(array(0),array_keys($this->sjscripts)))+1;
  2171. $this->sjscripts[$pos]= $src;
  2172. } else {
  2173. $pos= isset($overwritepos) ? $overwritepos : max(array_merge(array(0),array_keys($this->jscripts)))+1;
  2174. $this->jscripts[$pos]= $src;
  2175. }
  2176. $this->loadedjscripts[$key]['version']= $version;
  2177. $this->loadedjscripts[$key]['startup']= $startup;
  2178. $this->loadedjscripts[$key]['pos']= $pos;
  2179. }
  2180. # Registers Client-side Startup HTML block
  2181. function regClientStartupHTMLBlock($html) {
  2182. $this->regClientScript($html, true, true);
  2183. }
  2184. # Registers Client-side HTML block
  2185. function regClientHTMLBlock($html) {
  2186. $this->regClientScript($html, true);
  2187. }
  2188. # Remove unwanted html tags and snippet, settings and tags
  2189. function stripTags($html, $allowed= "") {
  2190. $t= strip_tags($html, $allowed);
  2191. $t= preg_replace('~\[\*(.*?)\*\]~', "", $t); //tv
  2192. $t= preg_replace('~\[\[(.*?)\]\]~', "", $t); //snippet
  2193. $t= preg_replace('~\[\!(.*?)\!\]~', "", $t); //snippet
  2194. $t= preg_replace('~\[\((.*?)\)\]~', "", $t); //settings
  2195. $t= preg_replace('~\[\+(.*?)\+\]~', "", $t); //placeholders
  2196. $t= preg_replace('~{{(.*?)}}~', "", $t); //chunks
  2197. return $t;
  2198. }
  2199. # add an event listner to a plugin - only for use within the current execution cycle
  2200. function addEventListener($evtName, $pluginName) {
  2201. if (!$evtName || !$pluginName)
  2202. return false;
  2203. if (!array_key_exists($evtName,$this->pluginEvent))
  2204. $this->pluginEvent[$evtName] = array();
  2205. return array_push($this->pluginEvent[$evtName], $pluginName); // return array count
  2206. }
  2207. # remove event listner - only for use within the current execution cycle
  2208. function removeEventListener($evtName) {
  2209. if (!$evtName)
  2210. return false;
  2211. unset ($this->pluginEvent[$evtName]);
  2212. }
  2213. # remove all event listners - only for use within the current execution cycle
  2214. function removeAllEventListener() {
  2215. unset ($this->pluginEvent);
  2216. $this->pluginEvent= array ();
  2217. }
  2218. # invoke an event. $extParams - hash array: name=>value
  2219. function invokeEvent($evtName, $extParams= array ()) {
  2220. if (!$evtName)
  2221. return false;
  2222. if (!isset ($this->pluginEvent[$evtName]))
  2223. return false;
  2224. $el= $this->pluginEvent[$evtName];
  2225. $results= array ();
  2226. $numEvents= count($el);
  2227. if ($numEvents > 0)
  2228. for ($i= 0; $i < $numEvents; $i++) { // start for loop
  2229. $pluginName= $el[$i];
  2230. $pluginName = stripslashes($pluginName);
  2231. // reset event object
  2232. $e= & $this->Event;
  2233. $e->_resetEventObject();
  2234. $e->name= $evtName;
  2235. $e->activePlugin= $pluginName;
  2236. // get plugin code
  2237. if (isset ($this->pluginCache[$pluginName])) {
  2238. $pluginCode= $this->pluginCache[$pluginName];
  2239. $pluginProperties= $this->pluginCache[$pluginName . "Props"];
  2240. } else {
  2241. $sql= "SELECT `name`, `plugincode`, `properties` FROM " . $this->getFullTableName("site_plugins") . " WHERE `name`='" . $pluginName . "' AND `disabled`=0;";
  2242. $result= $this->db->query($sql);
  2243. if ($this->db->getRecordCount($result) == 1) {
  2244. $row= $this->db->getRow($result);
  2245. $pluginCode= $this->pluginCache[$row['name']]= $row['plugincode'];
  2246. $pluginProperties= $this->pluginCache[$row['name'] . "Props"]= $row['properties'];
  2247. } else {
  2248. $pluginCode= $this->pluginCache[$pluginName]= "return false;";
  2249. $pluginProperties= '';
  2250. }
  2251. }
  2252. // load default params/properties
  2253. $parameter= $this->parseProperties($pluginProperties);
  2254. if (!empty ($extParams))
  2255. $parameter= array_merge($parameter, $extParams);
  2256. // eval plugin
  2257. $this->evalPlugin($pluginCode, $parameter);
  2258. if ($e->_output != "")
  2259. $results[]= $e->_output;
  2260. if ($e->_propagate != true)
  2261. break;
  2262. }
  2263. $e->activePlugin= "";
  2264. return $results;
  2265. }
  2266. # parses a resource property string and returns the result as an array
  2267. function parseProperties($propertyString) {
  2268. $parameter= array ();
  2269. if (!empty ($propertyString)) {
  2270. $tmpParams= explode("&", $propertyString);
  2271. for ($x= 0; $x < count($tmpParams); $x++) {
  2272. if (strpos($tmpParams[$x], '=', 0)) {
  2273. $pTmp= explode("=", $tmpParams[$x]);
  2274. $pvTmp= explode(";", trim($pTmp[1]));
  2275. if ($pvTmp[1] == 'list' && $pvTmp[3] != "")
  2276. $parameter[trim($pTmp[0])]= $pvTmp[3]; //list default
  2277. else
  2278. if ($pvTmp[1] != 'list' && $pvTmp[2] != "")
  2279. $parameter[trim($pTmp[0])]= $pvTmp[2];
  2280. }
  2281. }
  2282. }
  2283. return $parameter;
  2284. }
  2285. /*############################################
  2286. Etomite_dbFunctions.php
  2287. New database functions for Etomite CMS
  2288. Author: Ralph A. Dahlgren - rad14701@yahoo.com
  2289. Etomite ID: rad14701
  2290. See documentation for usage details
  2291. ############################################*/
  2292. function getIntTableRows($fields= "*", $from= "", $where= "", $sort= "", $dir= "ASC", $limit= "") {
  2293. // function to get rows from ANY internal database table
  2294. if ($from == "") {
  2295. return false;
  2296. } else {
  2297. $where= ($where != "") ? "WHERE $where" : "";
  2298. $sort= ($sort != "") ? "ORDER BY $sort $dir" : "";
  2299. $limit= ($limit != "") ? "LIMIT $limit" : "";
  2300. $tbl= $this->getFullTableName($from);
  2301. $sql= "SELECT $fields FROM $tbl $where $sort $limit;";
  2302. $result= $this->db->query($sql);
  2303. $resourceArray= array ();
  2304. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  2305. array_push($resourceArray, @ $this->db->getRow($result));
  2306. }
  2307. return $resourceArray;
  2308. }
  2309. }
  2310. function putIntTableRow($fields= "", $into= "") {
  2311. // function to put a row into ANY internal database table
  2312. if (($fields == "") || ($into == "")) {
  2313. return false;
  2314. } else {
  2315. $tbl= $this->getFullTableName($into);
  2316. $sql= "INSERT INTO $tbl SET ";
  2317. foreach ($fields as $key => $value) {
  2318. $sql .= $key . "=";
  2319. if (is_numeric($value))
  2320. $sql .= $value . ",";
  2321. else
  2322. $sql .= "'" . $value . "',";
  2323. }
  2324. $sql= rtrim($sql, ",");
  2325. $sql .= ";";
  2326. $result= $this->db->query($sql);
  2327. return $result;
  2328. }
  2329. }
  2330. function updIntTableRow($fields= "", $into= "", $where= "", $sort= "", $dir= "ASC", $limit= "") {
  2331. // function to update a row into ANY internal database table
  2332. if (($fields == "") || ($into == "")) {
  2333. return false;
  2334. } else {
  2335. $where= ($where != "") ? "WHERE $where" : "";
  2336. $sort= ($sort != "") ? "ORDER BY $sort $dir" : "";
  2337. $limit= ($limit != "") ? "LIMIT $limit" : "";
  2338. $tbl= $this->getFullTableName($into);
  2339. $sql= "UPDATE $tbl SET ";
  2340. foreach ($fields as $key => $value) {
  2341. $sql .= $key . "=";
  2342. if (is_numeric($value))
  2343. $sql .= $value . ",";
  2344. else
  2345. $sql .= "'" . $value . "',";
  2346. }
  2347. $sql= rtrim($sql, ",");
  2348. $sql .= " $where $sort $limit;";
  2349. $result= $this->db->query($sql);
  2350. return $result;
  2351. }
  2352. }
  2353. function getExtTableRows($host= "", $user= "", $pass= "", $dbase= "", $fields= "*", $from= "", $where= "", $sort= "", $dir= "ASC", $limit= "") {
  2354. // function to get table rows from an external MySQL database
  2355. if (($host == "") || ($user == "") || ($pass == "") || ($dbase == "") || ($from == "")) {
  2356. return false;
  2357. } else {
  2358. $where= ($where != "") ? "WHERE $where" : "";
  2359. $sort= ($sort != "") ? "ORDER BY $sort $dir" : "";
  2360. $limit= ($limit != "") ? "LIMIT $limit" : "";
  2361. $tbl= $dbase . "." . $from;
  2362. $this->dbExtConnect($host, $user, $pass, $dbase);
  2363. $sql= "SELECT $fields FROM $tbl $where $sort $limit;";
  2364. $result= $this->db->query($sql);
  2365. $resourceArray= array ();
  2366. for ($i= 0; $i < @ $this->db->getRecordCount($result); $i++) {
  2367. array_push($resourceArray, @ $this->db->getRow($result));
  2368. }
  2369. return $resourceArray;
  2370. }
  2371. }
  2372. function putExtTableRow($host= "", $user= "", $pass= "", $dbase= "", $fields= "", $into= "") {
  2373. // function to put a row into an external database table
  2374. if (($host == "") || ($user == "") || ($pass == "") || ($dbase == "") || ($fields == "") || ($into == "")) {
  2375. return false;
  2376. } else {
  2377. $this->dbExtConnect($host, $user, $pass, $dbase);
  2378. $tbl= $dbase . "." . $into;
  2379. $sql= "INSERT INTO $tbl SET ";
  2380. foreach ($fields as $key => $value) {
  2381. $sql .= $key . "=";
  2382. if (is_numeric($value))
  2383. $sql .= $value . ",";
  2384. else
  2385. $sql .= "'" . $value . "',";
  2386. }
  2387. $sql= rtrim($sql, ",");
  2388. $sql .= ";";
  2389. $result= $this->db->query($sql);
  2390. return $result;
  2391. }
  2392. }
  2393. function updExtTableRow($host= "", $user= "", $pass= "", $dbase= "", $fields= "", $into= "", $where= "", $sort= "", $dir= "ASC", $limit= "") {
  2394. // function to update a row into an external database table
  2395. if (($fields == "") || ($into == "")) {
  2396. return false;
  2397. } else {
  2398. $this->dbExtConnect($host, $user, $pass, $dbase);
  2399. $tbl= $dbase . "." . $into;
  2400. $where= ($where != "") ? "WHERE $where" : "";
  2401. $sort= ($sort != "") ? "ORDER BY $sort $dir" : "";
  2402. $limit= ($limit != "") ? "LIMIT $limit" : "";
  2403. $sql= "UPDATE $tbl SET ";
  2404. foreach ($fields as $key => $value) {
  2405. $sql .= $key . "=";
  2406. if (is_numeric($value))
  2407. $sql .= $value . ",";
  2408. else
  2409. $sql .= "'" . $value . "',";
  2410. }
  2411. $sql= rtrim($sql, ",");
  2412. $sql .= " $where $sort $limit;";
  2413. $result= $this->db->query($sql);
  2414. return $result;
  2415. }
  2416. }
  2417. function dbExtConnect($host, $user, $pass, $dbase) {
  2418. // function to connect to external database
  2419. $tstart= $this->getMicroTime();
  2420. if (@ !$this->rs= mysql_connect($host, $user, $pass)) {
  2421. $this->messageQuit("Failed to create connection to the $dbase database!");
  2422. } else {
  2423. mysql_select_db($dbase);
  2424. $tend= $this->getMicroTime();
  2425. $totaltime= $tend - $tstart;
  2426. if ($this->dumpSQL) {
  2427. $this->queryCode .= "<fieldset style='text-align:left'><legend>Database connection</legend>" . sprintf("Database connection to %s was created in %2.4f s", $dbase, $totaltime) . "</fieldset><br />";
  2428. }
  2429. $this->queryTime= $this->queryTime + $totaltime;
  2430. }
  2431. }
  2432. function getFormVars($method= "", $prefix= "", $trim= "", $REQUEST_METHOD) {
  2433. // function to retrieve form results into an associative array
  2434. $results= array ();
  2435. $method= strtoupper($method);
  2436. if ($method == "")
  2437. $method= $REQUEST_METHOD;
  2438. if ($method == "POST")
  2439. $method= & $_POST;
  2440. elseif ($method == "GET") $method= & $_GET;
  2441. else
  2442. return false;
  2443. reset($method);
  2444. foreach ($method as $key => $value) {
  2445. if (($prefix != "") && (substr($key, 0, strlen($prefix)) == $prefix)) {
  2446. if ($trim) {
  2447. $pieces= explode($prefix, $key, 2);
  2448. $key= $pieces[1];
  2449. $results[$key]= $value;
  2450. } else
  2451. $results[$key]= $value;
  2452. }
  2453. elseif ($prefix == "") $results[$key]= $value;
  2454. }
  2455. return $results;
  2456. }
  2457. ########################################
  2458. // END New database functions - rad14701
  2459. ########################################
  2460. /***************************************************************************************/
  2461. /* End of API functions */
  2462. /***************************************************************************************/
  2463. function phpError($nr, $text, $file, $line) {
  2464. if (error_reporting() == 0 || $nr == 0 || ($nr == 8 && $this->stopOnNotice == false)) {
  2465. return true;
  2466. }
  2467. if (is_readable($file)) {
  2468. $source= file($file);
  2469. $source= htmlspecialchars($source[$line -1]);
  2470. } else {
  2471. $source= "";
  2472. } //Error $nr in $file at $line: <div><code>$source</code></div>
  2473. $this->messageQuit("PHP Parse Error", '', true, $nr, $file, $source, $text, $line);
  2474. }
  2475. function messageQuit($msg= 'unspecified error', $query= '', $is_error= true, $nr= '', $file= '', $source= '', $text= '', $line= '') {
  2476. $version= isset ($GLOBALS['version']) ? $GLOBALS['version'] : '';
  2477. $release_date= isset ($GLOBALS['release_date']) ? $GLOBALS['release_date'] : '';
  2478. $parsedMessageString= "
  2479. <html><head><title>MODx Content Manager $version &raquo; $release_date</title>
  2480. <style>TD, BODY { font-size: 11px; font-family:verdana; }</style>
  2481. <script type='text/javascript'>
  2482. function copyToClip()
  2483. {
  2484. holdtext.innerText = sqlHolder.innerText;
  2485. Copied = holdtext.createTextRange();
  2486. Copied.execCommand('Copy');
  2487. }
  2488. </script>
  2489. </head><body>
  2490. ";
  2491. if ($is_error) {
  2492. $parsedMessageString .= "<h3 style='color:red'>&laquo; MODx Parse Error &raquo;</h3>
  2493. <table border='0' cellpadding='1' cellspacing='0'>
  2494. <tr><td colspan='3'>MODx encountered the following error while attempting to parse the requested resource:</td></tr>
  2495. <tr><td colspan='3'><b style='color:red;'>&laquo; $msg &raquo;</b></td></tr>";
  2496. } else {
  2497. $parsedMessageString .= "<h3 style='color:#003399'>&laquo; MODx Debug/ stop message &raquo;</h3>
  2498. <table border='0' cellpadding='1' cellspacing='0'>
  2499. <tr><td colspan='3'>The MODx parser recieved the following debug/ stop message:</td></tr>
  2500. <tr><td colspan='3'><b style='color:#003399;'>&laquo; $msg &raquo;</b></td></tr>";
  2501. }
  2502. if (!empty ($query)) {
  2503. $parsedMessageString .= "<tr><td colspan='3'><b style='color:#999;font-size: 9px;'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQL:&nbsp;<span id='sqlHolder'>$query</span></b>
  2504. <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='javascript:copyToClip();' style='color:#821517;font-size: 9px; text-decoration: none'>[Copy SQL to ClipBoard]</a><textarea id='holdtext' style='display:none;'></textarea></td></tr>";
  2505. }
  2506. if ($text != '') {
  2507. $errortype= array (
  2508. E_ERROR => "Error",
  2509. E_WARNING => "Warning",
  2510. E_PARSE => "Parsing Error",
  2511. E_NOTICE => "Notice",
  2512. E_CORE_ERROR => "Core Error",
  2513. E_CORE_WARNING => "Core Warning",
  2514. E_COMPILE_ERROR => "Compile Error",
  2515. E_COMPILE_WARNING => "Compile Warning",
  2516. E_USER_ERROR => "User Error",
  2517. E_USER_WARNING => "User Warning",
  2518. E_USER_NOTICE => "User Notice",
  2519. );
  2520. $parsedMessageString .= "<tr><td>&nbsp;</td></tr><tr><td colspan='3'><b>PHP error debug</b></td></tr>";
  2521. $parsedMessageString .= "<tr><td valign='top'>&nbsp;&nbsp;Error: </td>";
  2522. $parsedMessageString .= "<td colspan='2'>$text</td><td>&nbsp;</td>";
  2523. $parsedMessageString .= "</tr>";
  2524. $parsedMessageString .= "<tr><td valign='top'>&nbsp;&nbsp;Error type/ Nr.: </td>";
  2525. $parsedMessageString .= "<td colspan='2'>" . $errortype[$nr] . " - $nr</b></td><td>&nbsp;</td>";
  2526. $parsedMessageString .= "</tr>";
  2527. $parsedMessageString .= "<tr><td>&nbsp;&nbsp;File: </td>";
  2528. $parsedMessageString .= "<td colspan='2'>$file</td><td>&nbsp;</td>";
  2529. $parsedMessageString .= "</tr>";
  2530. $parsedMessageString .= "<tr><td>&nbsp;&nbsp;Line: </td>";
  2531. $parsedMessageString .= "<td colspan='2'>$line</td><td>&nbsp;</td>";
  2532. $parsedMessageString .= "</tr>";
  2533. if ($source != '') {
  2534. $parsedMessageString .= "<tr><td valign='top'>&nbsp;&nbsp;Line $line source: </td>";
  2535. $parsedMessageString .= "<td colspan='2'>$source</td><td>&nbsp;</td>";
  2536. $parsedMessageString .= "</tr>";
  2537. }
  2538. }
  2539. $parsedMessageString .= "<tr><td>&nbsp;</td></tr><tr><td colspan='3'><b>Parser timing</b></td></tr>";
  2540. $parsedMessageString .= "<tr><td>&nbsp;&nbsp;MySQL: </td>";
  2541. $parsedMessageString .= "<td><i>[^qt^]</i></td><td>(<i>[^q^] Requests</i>)</td>";
  2542. $parsedMessageString .= "</tr>";
  2543. $parsedMessageString .= "<tr><td>&nbsp;&nbsp;PHP: </td>";
  2544. $parsedMessageString .= "<td><i>[^p^]</i></td><td>&nbsp;</td>";
  2545. $parsedMessageString .= "</tr>";
  2546. $parsedMessageString .= "<tr><td>&nbsp;&nbsp;Total: </td>";
  2547. $parsedMessageString .= "<td><i>[^t^]</i></td><td>&nbsp;</td>";
  2548. $parsedMessageString .= "</tr>";
  2549. $parsedMessageString .= "</table>";
  2550. $parsedMessageString .= "</body></html>";
  2551. $totalTime= ($this->getMicroTime() - $this->tstart);
  2552. $queryTime= $this->queryTime;
  2553. $phpTime= $totalTime - $queryTime;
  2554. $queries= isset ($this->executedQueries) ? $this->executedQueries : 0;
  2555. $queryTime= sprintf("%2.4f s", $queryTime);
  2556. $totalTime= sprintf("%2.4f s", $totalTime);
  2557. $phpTime= sprintf("%2.4f s", $phpTime);
  2558. $parsedMessageString= str_replace("[^q^]", $queries, $parsedMessageString);
  2559. $parsedMessageString= str_replace("[^qt^]", $queryTime, $parsedMessageString);
  2560. $parsedMessageString= str_replace("[^p^]", $phpTime, $parsedMessageString);
  2561. $parsedMessageString= str_replace("[^t^]", $totalTime, $parsedMessageString);
  2562. // Set 500 response header
  2563. header('HTTP/1.1 500 Internal Server Error');
  2564. // Display error
  2565. echo $parsedMessageString;
  2566. ob_end_flush();
  2567. // Log error
  2568. $this->logEvent(0, 3, $parsedMessageString, $source= 'Parser');
  2569. // Make sure and die!
  2570. exit();
  2571. }
  2572. function getRegisteredClientScripts() {
  2573. return implode("\n", $this->jscripts);
  2574. }
  2575. function getRegisteredClientStartupScripts() {
  2576. return implode("\n", $this->sjscripts);
  2577. }
  2578. /**
  2579. * Format alias to be URL-safe. Strip invalid characters.
  2580. *
  2581. * @param string Alias to be formatted
  2582. * @return string Safe alias
  2583. */
  2584. function stripAlias($alias) {
  2585. // let add-ons overwrite the default behavior
  2586. $results = $this->invokeEvent('OnStripAlias', array ('alias'=>$alias));
  2587. if (!empty($results)) {
  2588. // if multiple plugins are registered, only the last one is used
  2589. return end($results);
  2590. } else {
  2591. // default behavior: strip invalid characters and replace spaces with dashes.
  2592. $alias = strip_tags($alias); // strip HTML
  2593. $alias = preg_replace('/[^\.A-Za-z0-9 _-]/', '', $alias); // strip non-alphanumeric characters
  2594. $alias = preg_replace('/\s+/', '-', $alias); // convert white-space to dash
  2595. $alias = preg_replace('/-+/', '-', $alias); // convert multiple dashes to one
  2596. $alias = trim($alias, '-'); // trim excess
  2597. return $alias;
  2598. }
  2599. }
  2600. // End of class.
  2601. }
  2602. // SystemEvent Class
  2603. class SystemEvent {
  2604. var $name;
  2605. var $_propagate;
  2606. var $_output;
  2607. var $activated;
  2608. var $activePlugin;
  2609. function SystemEvent($name= "") {
  2610. $this->_resetEventObject();
  2611. $this->name= $name;
  2612. }
  2613. // used for displaying a message to the user
  2614. function alert($msg) {
  2615. global $SystemAlertMsgQueque;
  2616. if ($msg == "")
  2617. return;
  2618. if (is_array($SystemAlertMsgQueque)) {
  2619. if ($this->name && $this->activePlugin)
  2620. $title= "<div><b>" . $this->activePlugin . "</b> - <span style='color:maroon;'>" . $this->name . "</span></div>";
  2621. $SystemAlertMsgQueque[]= "$title<div style='margin-left:10px;margin-top:3px;'>$msg</div>";
  2622. }
  2623. }
  2624. // used for rendering an out on the screen
  2625. function output($msg) {
  2626. $this->_output .= $msg;
  2627. }
  2628. function stopPropagation() {
  2629. $this->_propagate= false;
  2630. }
  2631. function _resetEventObject() {
  2632. unset ($this->returnedValues);
  2633. $this->name= "";
  2634. $this->_output= "";
  2635. $this->_propagate= true;
  2636. $this->activated= false;
  2637. }
  2638. }
  2639. ?>