CMSimple_XH 開発者ドキュメント
functions.php
[詳解]
1 <?php
2 
19 /*
20  ======================================
21  CMSimple_XH 1.7.0
22  2017-07-02
23  based on CMSimple version 3.3 - December 31. 2009
24  For changelog, downloads and information please see http://www.cmsimple-xh.org/
25  ======================================
26  -- COPYRIGHT INFORMATION START --
27  Based on CMSimple version 3.3 - December 31. 2009
28  Small - simple - smart
29  (c) 1999-2009 Peter Andreas Harteg - peter@harteg.dk
30 
31  This file is part of CMSimple_XH
32  For licence see notice in /cmsimple/cms.php
33  -- COPYRIGHT INFORMATION END --
34  ======================================
35  */
36 
37 
45 function geturl($u)
46 {
47  $t = '';
48  if ($fh = fopen(preg_replace("/\&amp;/is", "&", $u), "r")) {
49  while (!feof($fh)) {
50  $t .= fread($fh, 1024);
51  }
52  fclose($fh);
53  return preg_replace("/.*<body[^>]*>(.*)<\/body>.*/is", '$1', $t);
54  }
55 }
56 
64 function geturlwp($u)
65 {
66  global $su;
67 
68  $t = '';
69  $qs = preg_replace("/^" . preg_quote($su, '/') . "(\&)?/s", "", sv('QUERY_STRING'));
70  if ($fh = fopen($u . '?' . $qs, "r")) {
71  while (!feof($fh)) {
72  $t .= fread($fh, 1024);
73  }
74  fclose($fh);
75  return $t;
76  }
77 }
78 
90 function h($n)
91 {
92  global $h;
93 
94  trigger_error('Function h() is deprecated', E_USER_DEPRECATED);
95 
96  return $h[$n];
97 }
98 
110 function l($n)
111 {
112  global $l;
113 
114  trigger_error('Function l() is deprecated', E_USER_DEPRECATED);
115 
116  return $l[$n];
117 }
118 
134 function evaluate_cmsimple_scripting($__text, $__compat = true)
135 {
136  extract($GLOBALS, EXTR_REFS);
137  $__scripts = array();
138  preg_match_all('~#CMSimple (.*?)#~is', $__text, $__scripts);
139  if (count($__scripts[1]) > 0) {
140  $output = preg_replace('~#CMSimple (?!hide)(.*?)#~is', '', $__text);
141  if ($__compat) {
142  $__scripts[1] = array_reverse($__scripts[1]);
143  }
144  foreach ($__scripts[1] as $__script) {
145  if (!in_array(strtolower($__script), array('hide', 'remove'))) {
146  $__script = html_entity_decode($__script, ENT_QUOTES, 'UTF-8');
147  try {
148  eval($__script);
149  } catch (ParseError $ex) {
150  trigger_error('Parse error: ' . $ex->getMessage(), E_USER_WARNING);
151  }
152  if ($__compat) {
153  break;
154  }
155  }
156  }
157  $eval_script_output = $output;
158  $output = '';
159  return $eval_script_output;
160  }
161  return $__text;
162 }
163 
187 {
188  global $tx;
189 
190  $message = '<span class="xh_fail">' . $tx['error']['plugincall']
191  . '</span>';
192  $re = '/{{{(?:PLUGIN:)?([a-z_0-9]+)\s*\(?(.*?)\)?;?}}}/iu';
193  preg_match_all($re, $text, $calls, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
194  $results = array();
195  foreach ($calls as $call) {
196  $arguments = preg_replace(
197  array(
198  '/&(quot|#34);/i', '/&(amp|#38);/i', '/&(apos|#39);/i',
199  '/&(lt|#60);/i', '/&(gt|#62);/i', '/&(nbsp|#160);/i'
200  ),
201  array('"', '&', '\'', '<', '>', ' '),
202  $call[2][0]
203  );
204  $function = $call[1][0];
205  if (function_exists($function)) {
206  try {
207  $results[] = XH_evaluateSinglePluginCall(
208  $function . '(' . $arguments . ')'
209  );
210  } catch (ParseError $ex) {
211  $results[] = '';
212  trigger_error('Parse error: ' . $ex->getMessage(), E_USER_WARNING);
213  }
214  } else {
215  $results[] = sprintf($message, $function);
216  }
217  }
218  $calls = array_reverse($calls);
219  $results = array_reverse($results);
220  foreach ($calls as $i => $call) {
221  $length = strlen($call[0][0]);
222  $offset = $call[0][1];
223  XH_spliceString($text, $offset, $length, $results[$i]);
224  }
225  return $text;
226 }
227 
242 function XH_evaluateSinglePluginCall($___expression)
243 {
244  extract($GLOBALS);
245  return preg_replace_callback(
246  '/#(CMSimple .*?)#/is',
247  'XH_escapeCMSimpleScripting',
248  eval('return ' . $___expression . ';')
249  );
250 }
251 
261 function XH_escapeCMSimpleScripting(array $matches)
262 {
263  trigger_error(
264  'CMSimple scripting not allowed in return value of plugin call',
265  E_USER_WARNING
266  );
267  return "#\xE2\x80\x8B{$matches[1]}#";
268 }
269 
285 function XH_spliceString(&$string, $offset, $length = 0, $replacement = '')
286 {
287  $result = substr($string, $offset, $length);
288  $string = substr($string, 0, $offset) . $replacement
289  . substr($string, $offset + $length);
290  return $result;
291 }
292 
303 function evaluate_scripting($text, $compat = true)
304 {
306 }
307 
322 function newsbox($heading)
323 {
324  global $c, $cl, $h, $edit;
325 
326  for ($i = 0; $i < $cl; $i++) {
327  if ($h[$i] == $heading) {
328  $pattern = '/.*?<!--XH_ml[1-9]:.*?-->/isu';
329  $body = preg_replace($pattern, "", $c[$i]);
330  $pattern = '/#CMSimple (.*?)#/is';
331  return $edit
332  ? $body
333  : preg_replace($pattern, '', evaluate_scripting($body, false));
334  }
335  }
336  return false;
337 }
338 
354 function init_editor(array $elementClasses = array(), $initFile = false)
355 {
356  global $pth, $cf;
357 
358  $fn = $pth['folder']['plugins'] . $cf['editor']['external'] . '/init.php';
359  if (!file_exists($fn)) {
360  return false;
361  }
362  include_once $fn;
363  $function = 'init_' . $cf['editor']['external'];
364 
365  if (!function_exists($function)) {
366  return false;
367  }
368 
369  $function($elementClasses, $initFile);
370 
371  return true;
372 }
373 
386 // @codingStandardsIgnoreStart
387 function include_editor()
388 {
389 // @codingStandardsIgnoreEnd
390  global $pth, $cf;
391 
392  $fn = $pth['folder']['plugins'] . $cf['editor']['external'] . '/init.php';
393  if (!file_exists($fn)) {
394  return false;
395  }
396  include_once $fn;
397  $function = 'include_' . $cf['editor']['external'];
398 
399  if (!function_exists($function)) {
400  return false;
401  }
402 
403  $function();
404 
405  return true;
406 }
407 
424 function editor_replace($elementID = false, $config = '')
425 {
426  global $pth, $cf;
427 
428  if (!$elementID) {
429  trigger_error('No elementID given', E_USER_NOTICE);
430  return false;
431  }
432 
433  $fn = $pth['folder']['plugins'] . $cf['editor']['external'] . '/init.php';
434  if (!file_exists($fn)) {
435  return false;
436  }
437  include_once $fn;
438  $function = $cf['editor']['external'] . '_replace';
439 
440  if (!function_exists($function)) {
441  return false;
442  }
443 
444  return $function($elementID, $config);
445 }
446 
464 function XH_finalCleanUp($html)
465 {
466  global $errors, $cf, $tx, $bjs;
467 
468  if (XH_ADM === true) {
469  $debugHint = '';
470  $errorList = '';
471 
472  if (error_reporting() > 0) {
473  $debugHint .= '<div class="xh_debug">' . "\n"
474  . $tx['message']['debug_mode'] . "\n"
475  . '</div>' . "\n";
476  }
477 
478  $adminMenuFunc = trim($cf['editmenu']['external']);
479  if ($adminMenuFunc == '' || !function_exists($adminMenuFunc)) {
480  $adminMenuFunc = 'XH_adminMenu';
481  }
482 
483  if (count($errors) > 0) {
484  $errorList .= '<div class="xh_debug_warnings"><ul>';
485  $errors = array_unique($errors);
486  foreach ($errors as $error) {
487  $errorList .= '<li>' . $error . '</li>';
488  }
489  $errorList .= '</ul></div>';
490  }
491  if (isset($cf['editmenu']['scroll'])
492  && $cf['editmenu']['scroll'] == 'true'
493  ) {
494  $id = ' id="xh_adminmenu_scrolling"';
495  } else {
496  $id =' id="xh_adminmenu_fixed"';
497  }
498 
499  $adminMenu = $adminMenuFunc(XH_plugins(true));
500  $replacement = '$0' . '<div' . $id . '>' . addcslashes($debugHint, '$\\')
501  . addcslashes($adminMenu, '$\\')
502  . '</div>' ."\n" . addcslashes($errorList, '$\\');
503  $html = preg_replace('~<body[^>]*>~i', $replacement, $html, 1);
504  }
505 
506  if (!empty($bjs)) {
507  $html = str_replace('</body', "$bjs\n</body", $html);
508  }
509  return XH_afterFinalCleanUp($html);
510 }
511 
521 function initvar($name)
522 {
523  trigger_error('Function ' . __FUNCTION__ . '() is deprecated', E_USER_DEPRECATED);
524 
525  if (!isset($GLOBALS[$name])) {
526  if (isset($_GET[$name])) {
527  $GLOBALS[$name] = $_GET[$name];
528  } elseif (isset($_POST[$name])) {
529  $GLOBALS[$name] = $_POST[$name];
530  } else {
531  $GLOBALS[$name] = '';
532  }
533  }
534 }
535 
543 function sv($s)
544 {
545  if (isset($_SERVER[$s])) {
546  return $_SERVER[$s];
547  } else {
548  return '';
549  }
550 }
551 
559 function rmnl($t)
560 {
561  return preg_replace("/(\r\n|\r|\n)+/", "\n", $t);
562 }
563 
573 function XH_rmws($str)
574 {
575  $ws = '[\x09-\x0d\x20]'
576  . '|\xc2[\x85\xa0]'
577  . '|\xe1(\x9a\x80|\xa0\x8e)'
578  . '|\xe2\x80[\x80-\x8a\xa8\xa9\xaf]'
579  . '|\xe2\x81\x9f'
580  . '|\xe3\x80\x80';
581  return preg_replace('/(?:' . $ws . ')+/', ' ', $str);
582 }
583 
591 function rmanl($t)
592 {
593  return preg_replace("/(\r\n|\r|\n)+/", "", $t);
594 }
595 
606 function stsl($t)
607 {
608  return get_magic_quotes_gpc() ? stripslashes($t) : $t;
609 }
610 
623 function download($fl)
624 {
625  global $download, $o;
626 
627  if (!is_readable($fl)
628  || ($download != '' && !preg_match('/.+\..+$/', $fl))
629  ) {
630  shead('404');
631  $o .= '<p>File ' . XH_hsc($fl) . '</p>';
632  return;
633  } else {
634  header('Content-Type: application/save-as');
635  header('Content-Disposition: attachment; filename="' . basename($fl) . '"');
636  header('Content-Length:' . filesize($fl));
637  header('Content-Transfer-Encoding: binary');
638  readfile($fl);
639  exit;
640  }
641 }
642 
655 function e($et, $ft, $fn)
656 {
657  global $e, $tx;
658 
659  $e .= '<li><b>' . $tx['error'][$et] . ' ' . $tx['filetype'][$ft] . '</b>'
660  . '<br>' . $fn . '</li>' . "\n";
661 }
662 
681 function rfc()
682 {
683  global $edit, $c, $cl, $h, $u, $l, $su, $s, $tx, $e, $pth, $pd_router, $xh_publisher;
684 
685  $contents = XH_readContents();
686  if ($contents === false) {
687  e('missing', 'content', $pth['file']['content']);
688  $contents = array(
689  array(), array(), array(), array(), array(),
690  new XH\PageDataRouter(array(), array(), array(), array()),
691  array()
692  );
693  }
694  list($u, $tooLong, $h, $l, $c, $pd_router, $removed) = array_values($contents);
695  $duplicate = 0;
696 
697  $cl = count($c);
698  $s = -1;
699 
700  if ($cl == 0) {
701  $c[] = '<!--XH_ml1:' . $tx['toc']['newpage'] . '-->'; //HI
702  $h[] = trim(strip_tags($tx['toc']['newpage']));
703  $u[] = uenc($h[0]);
704  $l[] = 1;
705  if ($su == $u[0]) {
706  $s = 0;
707  }
708  $cl = 1;
709  $removed = array(false);
710  $pd_router->appendNewPage(array('last_edit' => '0'));
711  $xh_publisher = new XH\Publisher($removed);
712  return;
713  }
714 
715  foreach ($tooLong as $i => $tl) {
716  if (XH_ADM && $tl) {
717  $e .= '<li><b>' . $tx['uri']['toolong'] . '</b>' . '<br>'
718  . '<a href="?' . $u[$i] . '">' . $h[$i] . '</a>' . '</li>';
719  }
720  }
721 
722  foreach ($u as $i => $url) {
723  if (($su == $url || $su == urlencode($url))
724  && (XH_ADM && $edit || !$removed[$i])
725  ) {
726  $s = $i;
727  } // get index of selected page
728 
729  for ($j = $i + 1; $j < $cl; $j++) { //check for duplicate "urls"
730  if ($u[$j] == $u[$i]) {
731  $duplicate++;
732  $h[$j] = $tx['toc']['dupl'] . ' ' . $duplicate;
733  $u[$j] = uenc($h[$j]);
734  }
735  }
736  }
737 
738  $xh_publisher = new XH\Publisher($removed);
739 }
740 
765 function XH_readContents($language = null)
766 {
767  global $pth, $cf, $edit;
768 
769  if (isset($language)) {
770  $contentFolder = $pth['folder']['base'] . 'content/' . $language . '/';
771  $contentFile = $contentFolder . 'content.htm';
772  $pageDataFile = $contentFolder . 'pagedata.php';
773  $tx = XH_includeVar($pth['folder']['language'] . $language . '.php', 'tx');
774  } else {
775  $contentFile = $pth['file']['content'];
776  $pageDataFile = $pth['file']['pagedata'];
777  $tx = $GLOBALS['tx'];
778  }
779 
780  $c = array();
781  $h = array();
782  $u = array();
783  $tooLong = array();
784  $removed = array();
785  $l = array();
786  $empty = 0;
787  $search = explode(XH_URICHAR_SEPARATOR, $tx['urichar']['org']);
788  $replace = explode(XH_URICHAR_SEPARATOR, $tx['urichar']['new']);
789 
790  if (($content = XH_readFile($contentFile)) === false) {
791  return false;
792  }
793  $content = preg_split('/(?=<!--XH_ml[1-9]:)/i', $content);
794  $content[] = preg_replace('/(.*?)<\/body>.*/isu', '$1', array_pop($content));
795  $contentHead = array_shift($content);
796 
797  $temp_h = array();
798  foreach ($content as $page) {
799  $c[] = $page;
800  preg_match('~<!--XH_ml([1-9]):(.*)-->~isU', $page, $temp);
801  $l[] = $temp[1];
802  $temp_h[] = trim(xh_rmws(strip_tags($temp[2])));
803  }
804 
805  /*
806  * just a helper for the "url" construction:
807  * will be filled like this [0] => "Page"
808  * [1] => "Subpage"
809  * [2] => "Sub_Subpage" etc.
810  */
811  $ancestors = array();
812 
813  foreach ($temp_h as $i => $heading) {
814  $temp = $heading;
815  if ($temp == '') {
816  $empty++;
817  $temp = $tx['toc']['empty'] . ' ' . $empty;
818  }
819  $h[] = $temp;
820  $ancestors[$l[$i] - 1] = XH_uenc($temp, $search, $replace);
821  $ancestors = array_slice($ancestors, 0, $l[$i]);
822  $url = implode($cf['uri']['seperator'], $ancestors);
823  $u[] = utf8_substr($url, 0, $cf['uri']['length']);
824  $tooLong[] = utf8_strlen($url) > $cf['uri']['length'];
825  $removed[] = false;
826  }
827 
828  $page_data_fields = $temp_data = array();
829  if (preg_match('/<\?php(.*?)\?>/isu', $contentHead, $m)) {
830  eval($m[1]);
831  }
832  $page_data = array();
833  $hasPageData = false;
834  foreach ($c as $i => $j) {
835  if (preg_match('/<\?php(.*?)\?>/is', $j, $m)) {
836  eval($m[1]);
837  $c[$i] = preg_replace('/<\?php(.*?)\?>/is', '', $j);
838  $hasPageData = true;
839  } else {
840  $page_data[] = array();
841  }
842  }
843 
844  if (empty($page_data_fields) && empty($temp_data) && !$hasPageData
845  && is_readable($pageDataFile)
846  ) {
847  include $pageDataFile;
848  }
849 
850  $pd_router = new XH\PageDataRouter($h, $page_data_fields, $temp_data, $page_data);
851 
852  // remove unpublished pages
853  if (!($edit && XH_ADM)) {
854  foreach ($c as $i => $text) {
855  if (cmscript('remove', $text)) {
856  $c[$i] = '#CMSimple hide# #CMSimple shead(404);#';
857  $removed[$i] = true;
858  }
859  }
860  }
861 
862  //TODO: don't use $cf['menu']['levels'] anymore
863  $cf['menu']['levels'] = count($l) ? max($l) : 1;
864 
865  return array(
866  'urls' => $u,
867  'too_long' => $tooLong,
868  'headings' => $h,
869  'levels' => $l,
870  'pages' => $c,
871  'pd_router' => $pd_router,
872  'removed' => $removed
873  );
874 }
875 
886 {
887  global $s;
888 
889  for ($i = $s - 1; $i > -1; $i--) {
890  if (!hide($i)) {
891  return $i;
892  }
893  }
894  return false;
895 }
896 
907 function XH_findNextPage()
908 {
909  global $s, $cl;
910 
911  for ($i = $s + 1; $i < $cl; $i++) {
912  if (!hide($i)) {
913  return $i;
914  }
915  }
916  return false;
917 }
918 
931 function a($i, $x)
932 {
933  global $sn, $u, $cf;
934 
935  if ($i == 0 && !XH_ADM) {
936  if ($x == '' && $cf['locator']['show_homepage'] == 'true') {
937  return '<a href="' . $sn . '?' . $u[0] . '">';
938  }
939  }
940  return isset($u[$i])
941  ? '<a href="' . $sn . '?' . $u[$i] . $x . '">'
942  : '<a href="' . $sn . '?' . $x . '">';
943 }
944 
957 function meta($n)
958 {
959  global $cf, $tx, $print;
960 
961  $exclude = array('robots', 'keywords', 'description');
962  $value = isset($tx['meta'][$n]) ? $tx['meta'][$n] : $cf['meta'][$n];
963  if ($n != 'codepage' && !empty($value) && !($print && in_array($n, $exclude))) {
964  $content = XH_hsc($value);
965  return '<meta name="' . $n . '" content="' . $content . '">' . "\n";
966  }
967 }
968 
980 function ml($i)
981 {
982  global $f, $sn, $tx;
983 
984  $t = '';
985  if ($f != $i) {
986  $t .= '<a href="' . $sn . '?&amp;' . $i . '">';
987  }
988  $t .= $tx['menu'][$i];
989  if ($f != $i) {
990  $t .= '</a>';
991  }
992  return $t;
993 }
994 
1009 function uenc($s)
1010 {
1011  global $tx;
1012 
1013  if (isset($tx['urichar']['org']) && isset($tx['urichar']['new'])) {
1014  $search = explode(XH_URICHAR_SEPARATOR, $tx['urichar']['org']);
1015  $replace = explode(XH_URICHAR_SEPARATOR, $tx['urichar']['new']);
1016  } else {
1017  $search = $replace = array();
1018  }
1019  return XH_uenc($s, $search, $replace);
1020 }
1021 
1042 function XH_uenc($s, array $search, array $replace)
1043 {
1044  global $cf;
1045 
1046  $separator = $cf['uri']['word_separator'];
1047  $s = str_replace($search, $replace, $s);
1048  $s = str_replace('+', $separator, urlencode($s));
1049  $s = trim($s, $separator);
1050  $s = preg_replace('/' . preg_quote($separator, '/') . '+/', $separator, $s);
1051  return $s;
1052 }
1053 
1063 function sortdir($dir)
1064 {
1065  $fs = array();
1066  if ($fd = opendir($dir)) {
1067  while (false !== ($fn = readdir($fd))) {
1068  $fs[] = $fn;
1069  }
1070  closedir($fd);
1071  }
1072  sort($fs, SORT_STRING);
1073  return $fs;
1074 }
1075 
1084 function cmscript($script, $text)
1085 {
1086  $pattern = str_replace('(.*?)', $script, '/#CMSimple (.*?)#/is');
1087  return preg_match($pattern, $text);
1088 }
1089 
1100 function hide($i)
1101 {
1102  global $c, $edit;
1103 
1104  if ($i < 0) {
1105  return false;
1106  }
1107  return (!($edit && XH_ADM) && cmscript('hide', $c[$i]));
1108 }
1109 
1126 function tag($s)
1127 {
1128  return '<' . $s . '>';
1129 }
1130 
1144 function shead($s)
1145 {
1146  global $iis, $cgi, $tx, $title, $o;
1147 
1148  if ($s == '401') {
1149  header(
1150  ($cgi || $iis) ? 'status: 401 Unauthorized' : 'HTTP/1.0 401 Unauthorized'
1151  );
1152  } elseif ($s == '403') {
1153  header(($cgi || $iis) ? 'status: 403 Forbidden' : 'HTTP/1.0 403 Forbidden');
1154  } elseif ($s == '404') {
1155  if (function_exists('custom_404')) {
1156  custom_404();
1157  } else {
1158  header(
1159  ($cgi || $iis) ? 'status: 404 Not Found' : 'HTTP/1.0 404 Not Found'
1160  );
1161  }
1162  }
1163  if ($title == '') {
1164  $title = $tx['error'][$s];
1165  }
1166  $o = '<h1>' . $title . '</h1>' . $o;
1167 }
1168 
1192 function XH_debugmode()
1193 {
1194  global $pth;
1195 
1196  $dbglevel = '';
1197  $filename = $pth['folder']['downloads'] . '_XHdebug.txt';
1198  if (file_exists($filename)) {
1199  ini_set('display_errors', 1);
1200  $dbglevel = file_get_contents($filename);
1201  if (strlen($dbglevel) == 1) {
1202  set_error_handler('XH_debug');
1203  switch ($dbglevel) {
1204  case 0:
1205  error_reporting(0);
1206  break;
1207  case 1:
1208  error_reporting(E_ERROR | E_USER_WARNING | E_PARSE);
1209  break;
1210  case 2:
1211  error_reporting(E_ERROR | E_WARNING | E_USER_WARNING | E_PARSE);
1212  break;
1213  case 3:
1214  error_reporting(
1215  E_ERROR | E_WARNING | E_USER_WARNING | E_PARSE | E_NOTICE
1216  );
1217  break;
1218  case 4:
1219  error_reporting(E_ALL ^ (E_NOTICE | E_WARNING | E_USER_WARNING));
1220  break;
1221  case 5:
1222  error_reporting(E_ALL ^ E_NOTICE);
1223  break;
1224  case 6:
1225  error_reporting(E_ALL);
1226  break;
1227  default:
1228  error_reporting(E_ERROR | E_USER_WARNING | E_PARSE);
1229  }
1230  } else {
1231  error_reporting(E_ERROR | E_USER_WARNING | E_PARSE);
1232  }
1233  } else {
1234  ini_set('display_errors', 0);
1235  error_reporting(0);
1236  }
1237  return error_reporting() > 0;
1238 }
1239 
1252 function XH_debug($errno, $errstr, $errfile, $errline)
1253 {
1254  global $errors;
1255 
1256  if (!(error_reporting() & $errno)) {
1257  // This error code is not included in error_reporting
1258  return;
1259  }
1260 
1261  switch ($errno) {
1262  case E_USER_ERROR:
1263  $errtype = 'XH-ERROR';
1264  break;
1265  case E_USER_WARNING:
1266  $errtype = 'XH-WARNING';
1267  break;
1268  case E_USER_NOTICE:
1269  $errtype = 'XH-NOTICE';
1270  break;
1271  case E_USER_DEPRECATED:
1272  $errtype = 'XH-DEPRECATED';
1273  $backtrace = debug_backtrace(false);
1274  $errfile = $backtrace[2]['file'];
1275  $errline = $backtrace[2]['line'];
1276  break;
1277  case E_WARNING:
1278  $errtype = 'WARNING';
1279  break;
1280  case E_NOTICE:
1281  $errtype = 'NOTICE';
1282  break;
1283  case E_STRICT:
1284  $errtype = 'STRICT';
1285  break;
1286  case E_DEPRECATED:
1287  $errtype = 'DEPRECATED';
1288  break;
1289  default:
1290  $errtype = "Unknow error type [$errno]";
1291  }
1292 
1293  $errors[] = "<b>$errtype:</b> $errstr" . '<br>' . "$errfile:$errline"
1294  . '<br>' . "\n";
1295 
1296  if ($errno === E_USER_ERROR) {
1297  die($errors[count($errors) - 1]);
1298  }
1299 
1300  /* Don't execute PHP internal error handler */
1301  return true;
1302 }
1303 
1318 function XH_checkValidUtf8(array $arr)
1319 {
1320  global $tx;
1321 
1322  foreach ($arr as $elt) {
1323  if (is_array($elt)) {
1324  XH_checkValidUtf8($elt);
1325  } elseif (!utf8_is_valid($elt)) {
1326  header('HTTP/1.0 400 Bad Request');
1327  header('Content-Type: text/html; charset=UTF-8');
1328  echo <<<EOT
1329 <!DOCTYPE html>
1330 <html>
1331  <head><title>{$tx['title']['bad_request']}</title></head>
1332  <body>{$tx['error']['badrequest']}</body>
1333 </html>
1334 EOT;
1335  exit;
1336  }
1337  }
1338 }
1339 
1353 {
1354  $config = preg_match('/config.php$/', $dst) ? 'config' : '';
1355  if (!file_exists($dst)) {
1356  if (is_readable($src = dirname($dst) . "/default$config.php")) {
1357  return copy($src, $dst);
1358  } elseif (is_readable($src = dirname($dst) . "/en$config.php")) {
1359  return copy($src, $dst);
1360  }
1361  }
1362  return true;
1363 }
1364 
1378 {
1379  global $pth, $sl;
1380  static $helpFiles = array();
1381 
1382  $folders = array(
1383  'plugin' => '/',
1384  'plugin_classes' => '/classes/',
1385  'plugin_config' => '/config/',
1386  'plugin_content' => '/content/',
1387  'plugin_css' => '/css/',
1388  'plugin_help' => '/help/',
1389  'plugin_includes' => '/includes/',
1390  'plugin_languages' => '/languages/'
1391  );
1392  foreach ($folders as $key => $folder) {
1393  $pth['folder'][$key] = $pth['folder']['plugins'] . $plugin . $folder;
1394  }
1395 
1396  $pth['file']['plugin_index'] = $pth['folder']['plugin'] . 'index.php';
1397  $pth['file']['plugin_admin'] = $pth['folder']['plugin'] . 'admin.php';
1398 
1399  $pth['file']['plugin_language'] = $pth['folder']['plugin_languages']
1400  . strtolower($sl) . '.php';
1401 
1402  $pth['file']['plugin_classes'] = $pth['folder']['plugin_classes']
1403  . 'required_classes.php';
1404  $pth['file']['plugin_config'] = $pth['folder']['plugin_config']
1405  . 'config.php';
1406  $pth['file']['plugin_stylesheet'] = $pth['folder']['plugin_css']
1407  . 'stylesheet.css';
1408 
1409  if (!isset($helpFiles[$plugin])) {
1410  $helpFiles[$plugin] = $pth['folder']['plugin_help']
1411  . 'help_' . strtolower($sl) . '.htm';
1412  if (!file_exists($helpFiles[$plugin])) {
1413  $helpFiles[$plugin] = $pth['folder']['plugin_help'] . 'help_en.htm';
1414  }
1415  if (!file_exists($helpFiles[$plugin])
1416  && file_exists($pth['folder']['plugin_help'] . 'help.htm')
1417  ) {
1418  $helpFiles[$plugin] = $pth['folder']['plugin_help'] . 'help.htm';
1419  }
1420  }
1421  $pth['file']['plugin_help'] = $helpFiles[$plugin];
1422 }
1423 
1443 function XH_plugins($admin = false)
1444 {
1445  global $pth, $cf;
1446  static $plugins = null;
1447  static $admPlugins = null;
1448 
1449  if (!isset($plugins)) {
1450  $plugins = array();
1451  $admPlugins = array();
1452  $disabledPlugins = explode(',', $cf['plugins']['disabled']);
1453  $disabledPlugins = array_map('trim', $disabledPlugins);
1454  if (is_dir($pth['folder']['plugins']) && ($dh = opendir($pth['folder']['plugins']))) {
1455  while (($fn = readdir($dh)) !== false) {
1456  if (strpos($fn, '.') !== 0
1457  && is_dir($pth['folder']['plugins'] . $fn)
1458  && !in_array($fn, $disabledPlugins)
1459  ) {
1460  $plugins[] = $fn;
1461  pluginFiles($fn);
1462  if (is_file($pth['file']['plugin_admin'])) {
1463  $admPlugins[] = $fn;
1464  }
1465  }
1466  }
1467  closedir($dh);
1468  }
1469  natcasesort($plugins);
1470  $plugins = array_values($plugins);
1471  natcasesort($admPlugins);
1472  $admPlugins = array_values($admPlugins);
1473  }
1474  return $admin ? $admPlugins : $plugins;
1475 }
1476 
1484 function gc($s)
1485 {
1486  if (isset($_COOKIE[$s])) {
1487  return $_COOKIE[$s];
1488  }
1489 }
1490 
1498 function logincheck()
1499 {
1500  global $cf;
1501 
1502  XH_startSession();
1503  return isset($_SESSION['xh_password'])
1504  && $_SESSION['xh_password'] == $cf['security']['password']
1505  && isset($_SESSION['xh_user_agent'])
1506  && $_SESSION['xh_user_agent'] == md5($_SERVER['HTTP_USER_AGENT']);
1507 }
1508 
1523 function XH_logMessage($type, $module, $category, $description)
1524 {
1525  global $pth;
1526 
1527  $timestamp = date('Y-m-d H:i:s');
1528  $message = "$timestamp\t$type\t$module\t$category\t$description";
1529  $ok = false;
1530  $stream = fopen($pth['file']['log'], 'a');
1531  if ($stream) {
1532  if (XH_lockFile($stream, LOCK_EX)) {
1533  $ok = fwrite($stream, $message . PHP_EOL) !== false;
1534  fflush($stream);
1535  XH_lockFile($stream, LOCK_UN);
1536  }
1537  fclose($stream);
1538  }
1539  return $ok;
1540 }
1541 
1556 function loginforms()
1557 {
1558  global $cf, $tx, $onload, $f, $o, $s, $sn, $su;
1559 
1560  if ($f == 'login' || $f == 'xh_login_failed') {
1561  $cf['meta']['robots'] = "noindex";
1562  $onload .= 'document.forms[\'login\'].elements[\'keycut\'].focus();';
1563  $message = ($f == 'xh_login_failed')
1564  ? XH_message('fail', $tx['login']['failure'])
1565  : '';
1566  $f = $tx['menu']['login'];
1567  $o .= '<div class="xh_login">'
1568  . '<h1>' . $tx['menu']['login'] . '</h1>'
1569  . $message
1570  . '<p><b>' . $tx['login']['warning'] . '</b></p>'
1571  . '<form id="login" name="login" action="' . $sn . '?' . $su
1572  . '" method="post">'
1573  . '<input type="hidden" name="login" value="true">'
1574  . '<input type="hidden" name="selected" value="' . $su . '">'
1575  . '<input type="password" name="keycut" id="passwd" value="">'
1576  . ' '
1577  . '<input type="submit" name="submit" id="submit" value="'
1578  . $tx['menu']['login'] . '">'
1579  . '</form>';
1580  if (!empty($cf['security']['email'])) {
1581  $o .= '<a href="' . $sn . '?&function=forgotten">'
1582  . $tx['title']['password_forgotten'] . '</a>';
1583  }
1584  $o .= '<p><a href="' . "$sn?$su" . '">' . $tx['login']['back']
1585  . '</a></p>';
1586  $o .= ' </div>';
1587  $s = -1;
1588  }
1589 }
1590 
1601 function XH_readFile($filename)
1602 {
1603  $contents = false;
1604  $stream = fopen($filename, 'rb');
1605  if ($stream) {
1606  if (XH_lockFile($stream, LOCK_SH)) {
1607  $contents = stream_get_contents($stream);
1608  XH_lockFile($stream, LOCK_UN);
1609  }
1610  fclose($stream);
1611  }
1612  return $contents;
1613 }
1614 
1626 function XH_writeFile($filename, $contents)
1627 {
1628  $res = false;
1629  $stream = fopen($filename, 'cb');
1630  if ($stream) {
1631  if (XH_lockFile($stream, LOCK_EX)) {
1632  ftruncate($stream, 0);
1633  $res = fwrite($stream, $contents);
1634  fflush($stream);
1635  XH_lockFile($stream, LOCK_UN);
1636  }
1637  fclose($stream);
1638  }
1639  return $res;
1640 }
1641 
1654 function XH_afterPluginLoading($callback = null)
1655 {
1656  static $callbacks = array();
1657 
1658  if (isset($callback)) {
1659  $callbacks[] = $callback;
1660  } else {
1661  foreach ($callbacks as $callback) {
1662  $callback();
1663  }
1664  }
1665 }
1666 
1683 function XH_afterFinalCleanUp($param)
1684 {
1685  static $callbacks = array();
1686 
1687  if (is_callable($param)) {
1688  $callbacks[] = $param;
1689  } else {
1690  foreach ($callbacks as $callback) {
1691  $param = $callback($param);
1692  }
1693  return $param;
1694  }
1695 }
1696 
1708 {
1709  global $pth;
1710 
1711  $plugins = XH_plugins();
1712 
1713  $ofn = $pth['folder']['corestyle'] . 'xhstyles.css';
1714  $expired = !file_exists($ofn) || filemtime($pth['file']['corestyle']) > filemtime($ofn);
1715 
1716  // check for newly (un)installed plugins
1717  if (!$expired) {
1718  if (($ofp = fopen($ofn, 'r')) !== false
1719  && fgets($ofp, 4096) && fgets($ofp, 4096)
1720  && ($oldPlugins = fgets($ofp, 4096))
1721  ) {
1722  $oldPlugins = explode(',', trim($oldPlugins, " *\r\n"));
1723  $expired = $plugins != $oldPlugins;
1724  } else {
1725  $expired = true;
1726  }
1727  if ($ofp !== false) {
1728  fclose($ofp);
1729  }
1730  }
1731 
1732  // check for changes in the individual plugin stylesheets
1733  if (!$expired) {
1734  foreach ($plugins as $plugin) {
1735  $fn = $pth['folder']['plugins'] . $plugin . '/css/stylesheet.css';
1736  if (file_exists($fn) && filemtime($fn) > filemtime($ofn)) {
1737  $expired = true;
1738  break;
1739  }
1740  }
1741  }
1742 
1743  // create combined plugin stylesheet
1744  if ($expired) {
1745  $o = array(
1746  PHP_EOL . '/' . str_pad(' ' . $pth['file']['corestyle'], 76, '*', STR_PAD_LEFT) . ' */'
1747  . PHP_EOL . PHP_EOL . file_get_contents($pth['file']['corestyle'])
1748  );
1749  foreach ($plugins as $plugin) {
1750  $fn = $pth['folder']['plugins'] . $plugin . '/css/stylesheet.css';
1751  if (file_exists($fn)) {
1752  $css = file_get_contents($fn);
1753  if (substr($css, 0, 3) === "\xEF\xBB\xBF") {
1754  $css = substr($css, 3);
1755  }
1756  $css = XH_adjustStylesheetURLs($plugin, $css);
1757  $css = PHP_EOL
1758  . '/' . str_pad(' ' . $fn, 76, '*', STR_PAD_LEFT) . ' */'
1759  . PHP_EOL . PHP_EOL . $css;
1760  $o[] = $css;
1761  }
1762  }
1763  $o = '/*' . PHP_EOL
1764  . ' * Automatically created by CMSimple_XH. DO NOT MODIFY!' . PHP_EOL
1765  . ' * ' . implode(',', $plugins) . PHP_EOL
1766  . ' */' . PHP_EOL . PHP_EOL
1767  . implode(PHP_EOL . PHP_EOL, $o);
1768  if (!XH_writeFile($ofn, $o)) {
1769  e('cntwriteto', 'stylesheet', $ofn);
1770  }
1771  }
1772 
1773  return $ofn;
1774 }
1775 
1788 {
1789  return preg_replace(
1790  '/url\(\s*(["\']?)(?!\s*["\']?\/|\s*["\']?http[s]?:)(.*?)(["\']?)\s*\)/s',
1791  "url(\$1../../plugins/$plugin/css/\$2\$3)",
1792  $css
1793  );
1794 }
1795 
1806 function XH_message($type, $message)
1807 {
1808  $class = 'xh_' . $type;
1809  $args = array_slice(func_get_args(), 2);
1810  $message = vsprintf($message, $args);
1811  $message = XH_hsc($message);
1812  return '<p class="' . $class . '">' . $message . '</p>';
1813 }
1814 
1826 function XH_backup()
1827 {
1828  global $pth;
1829 
1830  $languages = XH_secondLanguages();
1831  $folders = array($pth['folder']['base'] . 'content/');
1832  foreach ($languages as $language) {
1833  $folders[] = $pth['folder']['base'] . 'content/' . $language . '/';
1834  }
1835  $backup = new XH\Backup($folders);
1836  return $backup->execute();
1837 }
1838 
1850 function XH_isLanguageFolder($name)
1851 {
1852  global $pth;
1853 
1854  $path = $pth['folder']['base'] . $name;
1855  return is_dir($path) && preg_match('/^[A-z]{2}$/', $name)
1856  && file_exists($path . '/.2lang');
1857 }
1858 
1869 function XH_title($site, $subtitle)
1870 {
1871  global $cf;
1872 
1873  if ($site != '') {
1874  $site = XH_hsc($site);
1875  $replacePairs = array('{SITE}' => $site, '{PAGE}' => $subtitle);
1876  $title = strtr($cf['title']['format'], $replacePairs);
1877  } else {
1878  $title = $subtitle;
1879  }
1880  return $title;
1881 }
1882 
1895 function XH_builtinTemplate($bodyClass)
1896 {
1897  global $sl, $_XH_csrfProtection, $bjs;
1898 
1899  echo '<!DOCTYPE html>', "\n", '<html',
1900  (strlen($sl) == 2 ? " lang=\"$sl\"" : ''), '>', "\n";
1901  $content = XH_convertPrintUrls(content());
1902  echo '<head>', "\n" . head(),
1903  '<meta name="robots" content="noindex">', "\n",
1904  '</head>', "\n", '<body class="', $bodyClass,'"', onload(), '>', "\n",
1905  $content, $bjs, '</body>', "\n", '</html>', "\n";
1906  if (isset($_XH_csrfProtection)) {
1907  $_XH_csrfProtection->store();
1908  }
1909  exit;
1910 }
1927 function XH_helpIcon($tooltip)
1928 {
1929  global $pth, $tx;
1930 
1931  $src = $pth['folder']['corestyle'] . 'help_icon.png';
1932  $o = '<div class="pl_tooltip">'
1933  . '<img src="' . $src . '" alt="' . $tx['editmenu']['help'] . '">'
1934  . '<div>' . $tooltip . '</div>'
1935  . '</div>';
1936  return $o;
1937 }
1938 
1949 function XH_isContentBackup($filename, $regularOnly = true)
1950 {
1951  $suffix = $regularOnly ? 'content' : '[^.]+';
1952  return (bool) preg_match('/^\d{8}_\d{6}_' . $suffix . '.htm$/', $filename);
1953 }
1954 
1964 function XH_templates()
1965 {
1966  global $pth;
1967 
1968  $templates = array();
1969  if (is_dir($pth['folder']['templates']) && ($handle = opendir($pth['folder']['templates']))) {
1970  while (($file = readdir($handle)) !== false) {
1971  $dir = $pth['folder']['templates'] . $file;
1972  if ($file[0] != '.' && is_dir($dir)
1973  && file_exists($dir . '/template.htm')
1974  ) {
1975  $templates[] = $file;
1976  }
1977  }
1978  closedir($handle);
1979  }
1980  natcasesort($templates);
1981  return $templates;
1982 }
1983 
1994 {
1995  global $pth;
1996 
1997  $languages = array();
1998  if (is_dir($pth['folder']['language']) && ($handle = opendir($pth['folder']['language']))) {
1999  while (($file = readdir($handle)) !== false) {
2000  if (preg_match('/^([a-z]{2})\.php$/i', $file, $m)) {
2001  $languages[] = $m[1];
2002  }
2003  }
2004  closedir($handle);
2005  }
2006  natcasesort($languages);
2007  return $languages;
2008 }
2009 
2022 {
2023  global $pth;
2024  static $langs;
2025 
2026  if (!isset($langs)) {
2027  $langs = array();
2028  if (is_dir($pth['folder']['base']) && ($dir = opendir($pth['folder']['base']))) {
2029  while (($entry = readdir($dir)) !== false) {
2030  if ($entry[0] != '.' && XH_isLanguageFolder($entry)) {
2031  $langs[] = $entry;
2032  }
2033  }
2034  closedir($dir);
2035  }
2036  sort($langs);
2037  }
2038  return $langs;
2039 }
2049 function XH_isInternalPath($path)
2050 {
2051  global $sl, $cf;
2052 
2053  $parts = explode('/', $path);
2054  $part0 = '';
2055  if ($parts[0] === '.'
2056  || $parts[0] === '..' && $sl !== $cf['language']['default']
2057  ) {
2058  $part0 = array_shift($parts);
2059  }
2060  if (empty($parts)) {
2061  return true;
2062  }
2063  if (($sl === $cf['language']['default'] || $part0 === '..')
2064  && array_search($parts[0], XH_secondLanguages())
2065  ) {
2066  array_shift($parts);
2067  }
2068  if (empty($parts)) {
2069  return true;
2070  }
2071  if ($parts[0] === '' || $parts[0] === 'index.php') {
2072  array_shift($parts);
2073  }
2074  return empty($parts);
2075 }
2076 
2086 function XH_isInternalUrl($urlParts)
2087 {
2088  $ok = true;
2089  foreach (array('scheme', 'host', 'port', 'user', 'pass') as $key) {
2090  $ok = $ok && !isset($urlParts[$key]);
2091  }
2092  $ok = $ok
2093  && (!isset($urlParts['path']) || XH_isInternalPath($urlParts['path']));
2094  return $ok;
2095 }
2096 
2107 function XH_convertToPrintUrl(array $matches)
2108 {
2109  $url = $matches[3];
2110  $parts = parse_url($url);
2111  if (XH_isInternalUrl($parts)) {
2112  $parts['query'] = (isset($parts['query']) ? $parts['query'] . '&amp;' : '');
2113  $parts['query'] .= 'print';
2114  $url = isset($parts['path']) ? $parts['path'] : '';
2115  $url .= '?' . $parts['query'];
2116  if (isset($parts['fragment'])) {
2117  $url .= '#' . $parts['fragment'];
2118  }
2119  }
2120  return $matches[1] . $url . $matches[2];
2121 }
2122 
2132 function XH_convertPrintUrls($pageContent)
2133 {
2134  $regex = '/(<a[^>]+href=(["\']))([^"\']*)\\2/iu';
2135  $content = preg_replace_callback($regex, 'XH_convertToPrintUrl', $pageContent);
2136  return $content;
2137 }
2138 
2152 function XH_decodeJson($string)
2153 {
2154  return json_decode($string);
2155 }
2156 
2170 function XH_encodeJson($value)
2171 {
2172  return json_encode($value);
2173 }
2174 
2188 {
2189  return json_last_error();
2190 }
2191 
2204 function XH_hsc($string)
2205 {
2206  if (!defined('ENT_SUBSTITUTE')) {
2207  $string = utf8_bad_replace($string, "\xEF\xBF\xBD");
2208  $string = htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
2209  } else {
2210  $string = htmlspecialchars($string, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8');
2211  }
2212  return $string;
2213 }
2214 
2227 function XH_mailform($subject = null)
2228 {
2229  global $cf;
2230 
2231  if ($cf['mailform']['email'] == '') {
2232  return false;
2233  }
2234 
2235  $mailform = new XH\Mailform(true, $subject);
2236  return $mailform->process();
2237 }
2238 
2251 function XH_includeVar($_filename, $_varname)
2252 {
2253  $_res = false;
2254  $_stream = fopen($_filename, 'r');
2255  if ($_stream) {
2256  if (XH_lockFile($_stream, LOCK_SH)) {
2257  $_res = include $_filename;
2258  XH_lockFile($_stream, LOCK_UN);
2259  }
2260  fclose($_stream);
2261  }
2262  if (!isset($$_varname)) {
2263  $$_varname = array();
2264  }
2265  return $_res !== false ? $$_varname : false;
2266 }
2267 
2278 function XH_numberSuffix($count)
2279 {
2280  if ($count == 1) {
2281  $suffix = '_1';
2282  } elseif ($count >= 2 && $count <= 4) {
2283  $suffix = '_2_4';
2284  } else {
2285  $suffix = '_5';
2286  }
2287  return $suffix;
2288 }
2289 
2304 function XH_readConfiguration($plugin = false, $language = false)
2305 {
2306  global $pth;
2307 
2308  if (!$plugin) {
2309  if (!$language) {
2310  $varname = 'cf';
2311  $defaultFilename = $pth['folder']['cmsimple'] . 'defaultconfig.php';
2312  $filename = $pth['file']['config'];
2313  } else {
2314  $varname = 'tx';
2315  $defaultFilename = $pth['folder']['language'] . 'default.php';
2316  $filename = $pth['file']['language'];
2317  }
2318  } else {
2319  if (!$language) {
2320  $varname = 'plugin_cf';
2321  $defaultFilename = $pth['folder']['plugin_config'] . 'defaultconfig.php';
2322  $filename = $pth['file']['plugin_config'];
2323  } else {
2324  $varname = 'plugin_tx';
2325  $defaultFilename = $pth['folder']['plugin_languages'] . 'default.php';
2326  $filename = $pth['file']['plugin_language'];
2327  }
2328  }
2329  if (is_readable($defaultFilename)) {
2330  include $defaultFilename;
2331  } else {
2332  $$varname = array();
2333  }
2334  if (is_readable($filename)) {
2335  $var = XH_includeVar($filename, $varname);
2336  $$varname = XH_unionOf2DArrays(
2337  is_array($var) ? $var : array(),
2338  is_array($$varname) ? $$varname : array()
2339  );
2340  }
2341  return $$varname;
2342 }
2343 
2356 function XH_unionOf2DArrays(array $array1, array $array2)
2357 {
2358  foreach ($array1 as $key => $subarray1) {
2359  $subarray2 = isset($array2[$key]) ? $array2[$key] : array();
2360  $array2[$key] = $subarray1 + $subarray2;
2361  }
2362  return $array2;
2363 }
2364 
2385 function XH_renameFile($oldname, $newname)
2386 {
2387  return rename($oldname, $newname);
2388 }
2389 
2401 function XH_exit($status = 0)
2402 {
2403  exit($status);
2404 }
2405 
2417 {
2418  global $sn, $sl;
2419 
2420  return preg_replace(
2421  '/\/' . preg_quote($sl, '/') . '\/$/',
2422  '/',
2423  preg_replace('/\/index\.php$/', '/', $sn)
2424  );
2425 }
2426 
2441 function XH_registerPluginType($type, $plugin = null)
2442 {
2443  static $plugins = array();
2444 
2445  if (isset($plugin)) {
2446  $plugins[$type][] = $plugin;
2447  } else {
2448  if (isset($plugins[$type])) {
2449  $result = $plugins[$type];
2450  natcasesort($result);
2451  return array_values($result);
2452  } else {
2453  return array();
2454  }
2455  }
2456 }
2457 
2466 {
2467  return XH_registerPluginType('editor');
2468 }
2469 
2478 {
2479  return XH_registerPluginType('filebrowser');
2480 }
2481 
2490 {
2491  return XH_registerPluginType('pagemanager');
2492 }
2493 
2502 {
2503  return XH_registerPluginType('editmenu');
2504 }
2505 
2520 function XH_onShutdown()
2521 {
2522  global $tx;
2523 
2524  if (!XH_ADM && isset($_SESSION['xh_password'])) {
2525  unset($_SESSION['xh_password']);
2526  }
2527 
2528  if (error_reporting() <= 0) {
2529  $lastError = error_get_last();
2530  if (in_array($lastError['type'], array(E_ERROR, E_PARSE))) {
2531  echo $tx['error']['fatal'];
2532  }
2533  }
2534 }
2547 function XH_formatDate($timestamp)
2548 {
2549  global $cf, $tx;
2550 
2551  if (class_exists('IntlDateFormatter', false)) {
2552  $dateFormatter = new IntlDateFormatter(
2553  $tx['locale']['all'] ? $tx['locale']['all'] : null,
2554  constant('IntlDateFormatter::' . strtoupper($cf['format']['date'])),
2555  constant('IntlDateFormatter::' . strtoupper($cf['format']['time']))
2556  );
2557  return $dateFormatter->format($timestamp);
2558  }
2559  return date($tx['lastupdate']['dateformat'], $timestamp);
2560 }
2561 
2574 function XH_lockFile($handle, $operation)
2575 {
2576  return flock($handle, $operation);
2577 }
2578 
2589 function XH_highlightSearchWords(array $words, $text)
2590 {
2591  $words = array_unique($words);
2592  usort($words, function ($a, $b) {
2593  return strlen($b) - strlen($a);
2594  });
2595  $patterns = array();
2596  foreach ($words as $word) {
2597  $word = trim($word);
2598  if ($word != '') {
2599  $patterns[] = '/' . preg_quote($word, '/') . '(?![^<]*>)/isuU';
2600  }
2601  }
2602  return preg_replace($patterns, '<span class="xh_find">$0</span>', $text);
2603 }
2604 
2616 function XH_autoload($className)
2617 {
2618  global $pth;
2619 
2620  $className = str_replace('_', '\\', $className);
2621  // set $package, $subpackages and $class
2622  $subpackages = explode('\\', $className);
2623  if (count($subpackages) <= 1) {
2624  return;
2625  }
2626  $packages = array_splice($subpackages, 0, 1);
2627  $package = $packages[0];
2628  $classes = array_splice($subpackages, -1);
2629  $class = $classes[0];
2630 
2631  // construct $filename
2632  if ($package == 'XH') {
2633  $folder = $pth['folder']['classes'];
2634  } else {
2635  $folder = $pth['folder']['plugins'] . strtolower($package) . '/classes/';
2636  }
2637  foreach ($subpackages as $subpackage) {
2638  $folder .= strtolower($subpackage) . '/';
2639  }
2640  $filename = $folder . $class . '.php';
2641 
2642  if (!file_exists($filename)) {
2643  return;
2644  }
2645 
2646  include_once $filename;
2647 
2648  if (class_exists($className)) {
2649  class_alias($className, str_replace('\\', '_', $className));
2650  }
2651 }
2652 
2663 {
2664  global $pth;
2665 
2666  if (session_id() == '') {
2667  $sessionName = 'XH_' . bin2hex(CMSIMPLE_ROOT);
2668  file_put_contents("{$pth['folder']['cmsimple']}.sessionname", $sessionName);
2669  session_name($sessionName);
2670  session_start();
2671  }
2672 }
2673 
2687 function XH_poweredBy()
2688 {
2689  global $cf, $tx, $pth;
2690 
2691  $o = '<h5>' . $tx['title']['cms'] . '</h5>'
2692  . '<ul><li><a href="http://cmsimple-xh.org">CMSimple_XH</a></li></ul>';
2693  $defaulttpl = $tx['subsite']['template'] == ''
2694  ? $cf['site']['template']
2695  : $tx['subsite']['template'];
2696 
2697  $tpltext = '';
2698  foreach (XH_templates() as $template) {
2699  $tpltext .= $defaulttpl == $template
2700  ? '<dt>' . $tx['template']['active'] . ucfirst($template) . '</dt>'
2701  : '<dt>' . ucfirst($template) . '</dt>';
2702  $infoPath = $pth['folder']['templates'] . '/' . $template . '/templateinfo.htm';
2703  if (is_file($infoPath)) {
2704  $tplinfo = utf8_substr(
2705  strip_tags(file_get_contents($infoPath), '<a><br><br/>'),
2706  0,
2707  400
2708  );
2709  $tpltext .= '<dd>';
2710  if ($tplinfo) {
2711  $tpltext .= $tplinfo;
2712  }
2713  $tpltext .= '</dd>';
2714  }
2715  }
2716 
2717  $o .= '<h5>' . $tx['title']['templates'] . '</h5><dl>' . $tpltext . '</dl>';
2718  $t = '';
2719  foreach (XH_plugins() as $plugin) {
2720  $url = XH_pluginURL($plugin);
2721  if ($url) {
2722  $t .= '<li><a href="' . $url . '">' . ucfirst($plugin)
2723  . '</a></li>';
2724  }
2725  }
2726  $o .= $t? '<h5>' . $tx['title']['plugins'] . '</h5><ul>' . $t . '</ul>' : '';
2727  return $o;
2728 }
2729 
2744 {
2745  global $pth;
2746 
2747  $standardPlugins = array(
2748  'fa', 'filebrowser', 'meta_tags', 'page_params', 'pagemanager' , 'tinymce',
2749  'jquery', 'hi_updatecheck',
2750  );
2751  if (in_array($plugin, $standardPlugins)) {
2752  $url = false;
2753  } else {
2754  $filename = $pth['folder']['plugins'] . $plugin . '/version.nfo';
2755  if (is_readable($filename)) {
2756  $contents = file_get_contents($filename);
2757  $contents = explode(',', $contents);
2758  $url = $contents[5];
2759  } else {
2760  $url = false;
2761  }
2762  }
2763  return $url;
2764 }
2765 
2787 {
2788  global $title, $h, $s, $f, $l, $tx, $cf, $xh_publisher;
2789 
2790  if (hide($s) && $cf['show_hidden']['path_locator'] != 'true') {
2791  return array(array($h[$s], XH_getPageURL($s)));
2792  }
2793  $firstPublishedPage = $xh_publisher->getFirstPublishedPage();
2794  if ($s == $firstPublishedPage) {
2795  return array(array($h[$s], XH_getPageURL($s)));
2796  } elseif ($title != '' && (!isset($h[$s]) || $h[$s] != $title)) {
2797  $res = array(array($title, null));
2798  } elseif ($f != '') {
2799  return array(array(ucfirst($f), null));
2800  } elseif ($s > $firstPublishedPage) {
2801  $res = array();
2802  $tl = $l[$s];
2803  if ($tl > 1) {
2804  for ($i = $s - 1; $i > $firstPublishedPage; $i--) {
2805  if ($l[$i] < $tl) {
2806  array_unshift($res, array($h[$i], XH_getPageURL($i)));
2807  $tl--;
2808  }
2809  if ($tl < 2) {
2810  break;
2811  }
2812  }
2813  }
2814  } else {
2815  return array(array('&nbsp;', null));
2816  }
2817  if ($cf['locator']['show_homepage'] == 'true') {
2818  array_unshift(
2819  $res,
2820  array($tx['locator']['home'], XH_getPageURL($firstPublishedPage))
2821  );
2822  if ($s > $firstPublishedPage && $h[$s] == $title) {
2823  $res[] = array($h[$s], XH_getPageURL($s));
2824  }
2825  return $res;
2826  } else {
2827  if ($s > $firstPublishedPage && $h[$s] == $title) {
2828  $res[] = array($h[$s], XH_getPageURL($s));
2829  }
2830  return $res;
2831  }
2832 }
2833 
2846 function XH_getPageURL($index)
2847 {
2848  global $sn, $u;
2849 
2850  return $sn . '?' . $u[$index];
2851 }
2852 
2863 {
2864  global $selected;
2865 
2866  $queryString = ltrim(preg_replace('/&?selected=[^&]+/', '', $_SERVER['QUERY_STRING']), '&');
2867  if ($queryString) {
2868  $queryString = "$selected&$queryString";
2869  } else {
2870  $queryString = $selected;
2871  }
2872  return CMSIMPLE_URL . "?$queryString";
2873 }
content()
Definition: tplfuncs.php:464
$print
Definition: cms.php:629
$download
Definition: cms.php:535
XH_onShutdown()
Definition: functions.php:2520
$l
Definition: cms.php:1003
evaluate_cmsimple_scripting($__text, $__compat=true)
Definition: functions.php:134
$xh_publisher
Definition: cms.php:940
XH_logMessage($type, $module, $category, $description)
Definition: functions.php:1523
XH_plugins($admin=false)
Definition: functions.php:1443
$function
Definition: cms.php:473
XH_evaluateSinglePluginCall($___expression)
Definition: functions.php:242
XH_getPageURL($index)
Definition: functions.php:2846
$admin
Definition: cms.php:447
utf8_substr($string, $offset, $length=null)
Definition: utf8.php:42
XH_debug($errno, $errstr, $errfile, $errline)
Definition: functions.php:1252
XH_debugmode()
Definition: functions.php:1192
XH_secondLanguages()
Definition: functions.php:2021
XH_isContentBackup($filename, $regularOnly=true)
Definition: functions.php:1949
XH_builtinTemplate($bodyClass)
Definition: functions.php:1895
loginforms()
Definition: functions.php:1556
XH_renameFile($oldname, $newname)
Definition: functions.php:2385
$plugin
Definition: cms.php:856
$su
Definition: cms.php:778
XH_checkValidUtf8(array $arr)
Definition: functions.php:1318
XH_includeVar($_filename, $_varname)
Definition: functions.php:2251
XH_getRootFolder()
Definition: functions.php:2416
XH_isLanguageFolder($name)
Definition: functions.php:1850
$e
Definition: cms.php:127
XH_redirectSelectedUrl()
Definition: functions.php:2862
sv($s)
Definition: functions.php:543
h($n)
Definition: functions.php:90
$j
Definition: cms.php:204
XH_readFile($filename)
Definition: functions.php:1601
XH_poweredBy()
Definition: functions.php:2687
const CMSIMPLE_URL
Definition: cms.php:761
XH_isInternalPath($path)
Definition: functions.php:2049
sortdir($dir)
Definition: functions.php:1063
XH_registeredFilebrowserPlugins()
Definition: functions.php:2477
XH_writeFile($filename, $contents)
Definition: functions.php:1626
pluginFiles($plugin)
Definition: functions.php:1377
$s
Definition: cms.php:953
rmnl($t)
Definition: functions.php:559
XH_findNextPage()
Definition: functions.php:907
logincheck()
Definition: functions.php:1498
XH_adjustStylesheetURLs($plugin, $css)
Definition: functions.php:1787
include_editor()
Definition: functions.php:387
tag($s)
Definition: functions.php:1126
ml($i)
Definition: functions.php:980
geturlwp($u)
Definition: functions.php:64
XH_finalCleanUp($html)
Definition: functions.php:464
XH_startSession()
Definition: functions.php:2662
XH_createLanguageFile($dst)
Definition: functions.php:1352
$i
Definition: cms.php:193
geturl($u)
Definition: functions.php:45
download($fl)
Definition: functions.php:623
$title
Definition: cms.php:100
XH_mailform($subject=null)
Definition: functions.php:2227
XH_registeredEditorPlugins()
Definition: functions.php:2465
$cf
Definition: cms.php:272
XH_getLocatorModel()
Definition: functions.php:2786
XH_afterPluginLoading($callback=null)
Definition: functions.php:1654
$f
Definition: cms.php:836
const XH_URICHAR_SEPARATOR(preg_match('/cms.php/i', $_SERVER['PHP_SELF']))
Definition: cms.php:88
XH_autoload($className)
Definition: functions.php:2616
XH_templates()
Definition: functions.php:1964
if($cf['site']['compat']) $errors
Definition: cms.php:309
XH_registerPluginType($type, $plugin=null)
Definition: functions.php:2441
editor_replace($elementID=false, $config='')
Definition: functions.php:424
hide($i)
Definition: functions.php:1100
XH_numberSuffix($count)
Definition: functions.php:2278
XH_lockFile($handle, $operation)
Definition: functions.php:2574
XH_formatDate($timestamp)
Definition: functions.php:2547
rmanl($t)
Definition: functions.php:591
XH_uenc($s, array $search, array $replace)
Definition: functions.php:1042
$c
Definition: cms.php:964
l($n)
Definition: functions.php:110
XH_availableLocalizations()
Definition: functions.php:1993
$search
Definition: cms.php:652
XH_convertPrintUrls($pageContent)
Definition: functions.php:2132
XH_registeredPagemanagerPlugins()
Definition: functions.php:2489
if(!isset($cf['folders']['content'])) if($cf['site']['timezone'] !=='' &&function_exists('date_default_timezone_set')) $sl
Definition: cms.php:331
$file
Definition: cms.php:640
XH_exit($status=0)
Definition: functions.php:2401
$u
Definition: cms.php:990
$bjs
Definition: cms.php:159
utf8_strlen($string)
Definition: utf8.php:28
meta($n)
Definition: functions.php:957
$o
Definition: cms.php:113
$onload
Definition: cms.php:171
$temp
Definition: cms.php:182
const CMSIMPLE_ROOT($temp as $i)
Definition: cms.php:747
XH_pluginURL($plugin)
Definition: functions.php:2743
e($et, $ft, $fn)
Definition: functions.php:655
evaluate_scripting($text, $compat=true)
Definition: functions.php:303
$cgi
Definition: cms.php:421
$iis
Definition: cms.php:410
$h
Definition: cms.php:977
onload()
Definition: tplfuncs.php:138
$sn
Definition: cms.php:434
foreach(XH_plugins() as $plugin) $_XH_csrfProtection
Definition: cms.php:879
$tx
Definition: cms.php:363
utf8_is_valid($string)
Definition: utf8.php:139
XH_highlightSearchWords(array $words, $text)
Definition: functions.php:2589
XH_unionOf2DArrays(array $array1, array $array2)
Definition: functions.php:2356
stsl($t)
Definition: functions.php:606
const XH_ADM
Definition: cms.php:897
$selected
Definition: cms.php:664
a($i, $x)
Definition: functions.php:931
XH_spliceString(&$string, $offset, $length=0, $replacement='')
Definition: functions.php:285
XH_findPreviousPage()
Definition: functions.php:885
XH_encodeJson($value)
Definition: functions.php:2170
shead($s)
Definition: functions.php:1144
$text
Definition: cms.php:698
XH_escapeCMSimpleScripting(array $matches)
Definition: functions.php:261
$pth
Definition: cms.php:230
XH_registeredEditmenuPlugins()
Definition: functions.php:2501
init_editor(array $elementClasses=array(), $initFile=false)
Definition: functions.php:354
XH_hsc($string)
Definition: functions.php:2204
utf8_bad_replace($string, $replace='?')
Definition: utf8.php:167
XH_afterFinalCleanUp($param)
Definition: functions.php:1683
XH_convertToPrintUrl(array $matches)
Definition: functions.php:2107
XH_isInternalUrl($urlParts)
Definition: functions.php:2086
XH_rmws($str)
Definition: functions.php:573
XH_lastJsonError()
Definition: functions.php:2187
XH_decodeJson($string)
Definition: functions.php:2152
uenc($s)
Definition: functions.php:1009
XH_backup()
Definition: functions.php:1826
$pd_router
Definition: cms.php:929
evaluate_plugincall($text)
Definition: functions.php:186
$edit
Definition: cms.php:602
$mailform
Definition: cms.php:524
cmscript($script, $text)
Definition: functions.php:1084
$cl
Definition: cms.php:918
XH_readConfiguration($plugin=false, $language=false)
Definition: functions.php:2304
newsbox($heading)
Definition: functions.php:322
XH_helpIcon($tooltip)
Definition: functions.php:1927
gc($s)
Definition: functions.php:1484
initvar($name)
Definition: functions.php:521
XH_pluginStylesheet()
Definition: functions.php:1707
XH_message($type, $message)
Definition: functions.php:1806
if($su==uenc('site/cms info')) if(XH_ADM) if($s==-1 &&! $f && $o=='' && $su=='') if(XH_ADM) $output
Definition: cms.php:1292
rfc()
Definition: functions.php:681
XH_title($site, $subtitle)
Definition: functions.php:1869
XH_readContents($language=null)
Definition: functions.php:765
head()
Definition: tplfuncs.php:73