CMSimple_XH 開発者ドキュメント
adminfuncs.php
[詳解]
1 <?php
2 
30 {
31  global $pth;
32 
33  $internalPlugins = array(
34  'filebrowser', 'meta_tags', 'page_params', 'tinymce'
35  );
36  if (in_array($plugin, $internalPlugins)) {
37  $version = 'for ' . CMSIMPLE_XH_VERSION;
38  } else {
39  $filename = $pth['folder']['plugins'] . $plugin . '/version.nfo';
40  if (is_readable($filename)) {
41  $contents = file_get_contents($filename);
42  $contents = explode(',', $contents);
43  $version = $contents[2];
44  } else {
45  $version = '';
46  }
47  }
48  return $version;
49 }
50 
64 function XH_systemCheck(array $data)
65 {
66  global $tx;
67 
68  $stx = $tx['syscheck'];
69 
70  $o = "<h4>$stx[title]</h4>\n<ul id=\"xh_system_check\">\n";
71 
72  if (key_exists('phpversion', $data)) {
73  $ok = version_compare(PHP_VERSION, $data['phpversion']) >= 0;
74  $o .= XH_systemCheckLi('', $ok ? 'success' : 'fail', sprintf($stx['phpversion'], $data['phpversion']));
75  }
76 
77  if (key_exists('extensions', $data)) {
78  $cat = 'xh_system_check_cat_start';
79  foreach ($data['extensions'] as $ext) {
80  if (is_array($ext)) {
81  $notok = $ext[1] ? 'fail' : 'warning';
82  $ext = $ext[0];
83  } else {
84  $notok = 'fail';
85  }
87  $cat,
88  extension_loaded($ext) ? 'success' : $notok,
89  sprintf($stx['extension'], $ext)
90  );
91  $cat = '';
92  }
93  }
94 
95  if (key_exists('writable', $data)) {
96  $cat = 'xh_system_check_cat_start';
97  foreach ($data['writable'] as $file) {
98  if (is_array($file)) {
99  $notok = $file[1] ? 'fail' : 'warning';
100  $file = $file[0];
101  } else {
102  $notok = 'warning';
103  }
104  $o .= XH_systemCheckLi($cat, is_writable($file) ? 'success' : $notok, sprintf($stx['writable'], $file));
105  $cat = '';
106  }
107  }
108 
109  if (key_exists('other', $data)) {
110  $cat = 'xh_system_check_cat_start';
111  foreach ($data['other'] as $check) {
112  $notok = $check[1] ? 'fail' : 'warning';
113  $o .= XH_systemCheckLi($cat, $check[0] ? 'success' : $notok, $check[2]);
114  $cat = '';
115  }
116  }
117 
118  $o .= "</ul>\n";
119 
120  return $o;
121 }
122 
136 function XH_systemCheckLi($class, $state, $text)
137 {
138  global $tx;
139 
140  $class = "class=\"xh_$state $class\"";
141  return "<li $class>"
142  . sprintf($tx['syscheck']['message'], $text, $tx['syscheck'][$state])
143  . "</li>\n";
144 }
145 
157 function XH_absoluteUrlPath($path)
158 {
159  global $sn;
160 
161  $base = preg_replace('/index\.php$/', '', $sn);
162  $parts = explode('/', $base . $path);
163  $i = 0;
164  while ($i < count($parts)) {
165  switch ($parts[$i]) {
166  case '.':
167  array_splice($parts, $i, 1);
168  break;
169  case '..':
170  array_splice($parts, $i - 1, 2);
171  $i--;
172  break;
173  default:
174  $i++;
175  }
176  }
177  $path = implode('/', $parts);
178  return $path;
179 }
180 
190 function XH_isAccessProtected($path)
191 {
192  $url = preg_replace('/index\.php$/', '', CMSIMPLE_URL) . $path;
193  $defaultContext = stream_context_set_default(
194  array('http' => array('method' => 'HEAD', 'timeout' => 5))
195  );
196  $headers = get_headers($url);
197  stream_context_set_default(stream_context_get_params($defaultContext));
198  if ($headers) {
199  if (preg_match('/^HTTP\S*\s+4/', $headers[0])) {
200  return true;
201  }
202  }
203  return false;
204 }
205 
218 function XH_sysinfo()
219 {
220  global $pth, $cf, $tx, $sn;
221 
222  $o = '<p><b>' . $tx['sysinfo']['version'] . '</b></p>' . "\n";
223  $o .= '<ul>' . "\n" . '<li>' . CMSIMPLE_XH_VERSION . '&nbsp;&nbsp;Released: '
224  . CMSIMPLE_XH_DATE . '</li>' . "\n" . '</ul>' . "\n" . "\n";
225 
226  $o .= '<p><b>' . $tx['sysinfo']['plugins'] . '</b></p>' . "\n" . "\n";
227 
228  $o .= '<ul>' . "\n";
229  foreach (XH_plugins() as $temp) {
230  $o .= '<li>' . ucfirst($temp) . ' ' . XH_pluginVersion($temp) . '</li>'
231  . "\n";
232  }
233  $o .= '</ul>' . "\n" . "\n";
234 
235  $serverSoftware = !empty($_SERVER['SERVER_SOFTWARE'])
236  ? $_SERVER['SERVER_SOFTWARE']
237  : $tx['sysinfo']['unknown'];
238  $o .= '<p><b>' . $tx['sysinfo']['webserver'] . '</b></p>' . "\n"
239  . '<ul>' . "\n" . '<li>' . $serverSoftware . '</li>' . "\n"
240  . '</ul>' . "\n\n";
241  $o .= '<p><b>' . $tx['sysinfo']['php_version'] . '</b></p>' . "\n"
242  . '<ul>' . "\n" . '<li>' . phpversion() . '</li>' . "\n"
243  . '<li><a href="' . $sn . '?&phpinfo" target="blank"><b>'
244  . $tx['sysinfo']['phpinfo_link'] . '</b></a> &nbsp; '
245  . $tx['sysinfo']['phpinfo_hint'] . '</li>' . "\n" . '</ul>' . "\n" . "\n";
246 
247  $o .= '<h4>' . $tx['sysinfo']['helplinks'] . '</h4>' . "\n" . "\n";
248  $o .= <<<HTML
249 <ul>
250 <li><a href="http://www.cmsimple-xh.org/">cmsimple-xh.org &raquo;</a></li>
251 <li><a href="http://www.cmsimple-xh.org/wiki/">cmsimple-xh.org/wiki/ &raquo;</a></li>
252 <li><a href="http://www.cmsimpleforum.com/">cmsimpleforum.com &raquo;</a></li>
253 <li><a href="http://www.cmsimple-xh.org/de/?Alles_auf_einen_Blick">cmsimple-xh.org/de/?Alles_auf_einen_Blick &raquo;</a></li>
254 </ul>
255 
256 HTML;
257 
258  $stx = $tx['syscheck'];
259  $checks = array(
260  'phpversion' => '5.3.7',
261  'extensions' => array(
262  array('intl', false),
263  'json',
264  'mbstring',
265  'session'
266  ),
267  'writable' => array(),
268  'other' => array()
269  );
270  $temp = array(
271  'content', 'corestyle', 'images', 'downloads', 'userfiles', 'media'
272  );
273  foreach ($temp as $i) {
274  $checks['writable'][] = $pth['folder'][$i];
275  }
276  $temp = array('config', 'log', 'language', 'content', 'template', 'stylesheet');
277  foreach ($temp as $i) {
278  $checks['writable'][] = $pth['file'][$i];
279  }
280  $checks['writable'] = array_unique($checks['writable']);
281  sort($checks['writable']);
282  $files = array(
283  $pth['file']['config'], $pth['file']['content'], $pth['file']['template']
284  );
285  foreach ($files as $file) {
286  $checks['other'][] = array(
287  XH_isAccessProtected($file), false,
288  sprintf($stx['access_protected'], $file)
289  );
290  }
291  if ($tx['locale']['all'] == '') {
292  $checks['other'][] = array(true, false, $stx['locale_default']);
293  } else {
294  $checks['other'][] = array(
295  setlocale(LC_ALL, $tx['locale']['all']), false,
296  sprintf($stx['locale_available'], $tx['locale']['all'])
297  );
298  }
299  $checks['other'][] = array(
300  date_default_timezone_get() !== 'UTC',
301  false, $stx['timezone']
302  );
303  $checks['other'][] = array(
304  !get_magic_quotes_runtime(), false, $stx['magic_quotes']
305  );
306  $checks['other'][] = array(
307  !ini_get('safe_mode'), false, $stx['safe_mode']
308  );
309  $checks['other'][] = array(
310  !ini_get('session.use_trans_sid'), false, $stx['use_trans_sid']
311  );
312  $checks['other'][] = array(
313  ini_get('session.use_only_cookies'), false, $stx['use_only_cookies']
314  );
315  $checks['other'][] = array(
316  ini_get('session.cookie_lifetime') == 0, false, $stx['cookie_lifetime']
317  );
318  $checks['other'][] = array(
319  strpos(ob_get_contents(), "\xEF\xBB\xBF") !== 0,
320  false, $stx['bom']
321  );
322  $checks['other'][] = array(
323  !password_verify('test', $cf['security']['password']),
324  false, $stx['password']
325  );
326  $checks['other'][] = array(
327  function_exists('fsockopen'), false, $stx['fsockopen']
328  );
329  $o .= XH_systemCheck($checks);
330  return $o;
331 }
332 
333 
344 function XH_settingsView()
345 {
346  global $sn, $tx;
347 
348  $o = '<p>' . $tx['settings']['warning'] . '</p>' . "\n"
349  . '<h4>' . $tx['settings']['systemfiles'] . '</h4>' . "\n" . '<ul>' . "\n";
350 
351  foreach (array('config', 'language') as $i) {
352  $o .= '<li><a href="' . $sn . '?file=' . $i . '&amp;action=array">'
353  . utf8_ucfirst($tx['action']['edit']) . ' '
354  . $tx['filetype'][$i] . '</a></li>' . "\n";
355  }
356 
357  foreach (array('stylesheet', 'template') as $i) {
358  $o .= '<li><a href="' . $sn . '?file=' . $i . '&amp;action=edit">'
359  . utf8_ucfirst($tx['action']['edit']) . ' '
360  . $tx['filetype'][$i] . '</a></li>' . "\n";
361  }
362  foreach (array('log') as $i) {
363  $o .= '<li><a href="' . $sn . '?file=' . $i . '&amp;action=view">'
364  . utf8_ucfirst($tx['action']['view']) . ' '
365  . $tx['filetype'][$i] . '</a></li>' . "\n";
366  }
367  $o .= '</ul>' . "\n";
368 
369  $o .= '<h4>' . $tx['settings']['backup'] . '</h4>' . "\n";
370  $o .= XH_backupsView();
371  $o .= '<h4>' . $tx['settings']['more'] . '</h4>' . "\n"
372  . '<ul>' . "\n"
373  . '<li><a href="' . $sn . '?&validate">' . $tx['editmenu']['validate'] . '</a></li>'
374  . '<li><a href="' . $sn . '?&xh_pagedata">' .$tx['editmenu']['pagedata'] . '</a></li>'
375  . '<li><a href="' . $sn . '?&xh_change_password">' . $tx['editmenu']['change_password'] . '</a></li>'
376  . '<li><a href="' . $sn . '?&sysinfo">' . $tx['editmenu']['sysinfo'] . '</a></li>'
377  . '</ul>' . "\n";
378  return $o;
379 }
380 
392 function XH_logFileView()
393 {
394  global $pth, $tx, $title;
395 
396  $title = $tx['title']['log'];
397  return '<h1>' . $tx['title']['log'] . '</h1>'
398  . '<pre id="xh_logfile">' . XH_hsc(XH_readFile($pth['file']['log']))
399  . '</pre>'
400  . '<script type="text/javascript">'
401  . '(function () {'
402  . 'var elt = document.getElementById("xh_logfile");'
403  . 'elt.scrollTop = elt.scrollHeight;'
404  . '}())'
405  . '</script>'
406  . '<p>('
407  . $tx['log']['timestamp'] . ' &ndash; '
408  . $tx['log']['type'] . ' &ndash; '
409  . $tx['log']['module'] . ' &ndash; '
410  . $tx['log']['category'] . ' &ndash; '
411  . $tx['log']['description']
412  . ')</p>';
413 }
414 
427 function XH_backupsView()
428 {
429  global $pth, $sn, $tx, $_XH_csrfProtection;
430 
431  $o = '<ul>' . "\n";
432  if (isset($_GET['xh_success'])) {
433  $o .= XH_message('success', $tx['message'][stsl($_GET['xh_success'])]);
434  }
435  $o .= '<li>' . utf8_ucfirst($tx['filetype']['content']) . ' <a href="'
436  . $sn . '?file=content&amp;action=view" target="_blank">'
437  . $tx['action']['view'] . '</a>' . ' <a href="' . $sn . '?file=content">'
438  . $tx['action']['edit'] . '</a>' . ' <a href="'
439  . $sn . '?file=content&amp;action=download">' . $tx['action']['download']
440  . '</a>'
441  . ' <form action="' . $sn . '?&xh_backups" method="post"'
442  . ' class="xh_inline_form" id="xh_backup_form">'
443  . '<input type="hidden" name="file" value="content">'
444  . '<input type="hidden" name="action" value="backup">'
445  . '<input type="hidden" name="xh_suffix" value="extra">'
446  . '<input type="submit" class="submit" value="'
447  . $tx['action']['backup'] . '">'
448  . $_XH_csrfProtection->tokenInput()
449  . '</form>'
450  . ' <form action="' . $sn . '?&xh_backups" method="post"'
451  . ' class="xh_inline_form">'
452  . '<input type="hidden" name="file" value="content">'
453  . '<input type="hidden" name="action" value="empty">'
454  . '<input type="submit" class="submit" value="'
455  . $tx['action']['empty'] . '">'
456  . $_XH_csrfProtection->tokenInput()
457  . '</form>'
458  . '</li>' . "\n";
459  $o .= '</ul>' . "\n" . '<hr>' . "\n" . '<p>'
460  . $tx['settings']['backupexplain1'] . '</p>' . "\n" . '<p>'
461  . $tx['settings']['backupexplain2'] . '</p>' . "\n" . '<ul>' . "\n";
462  $fs = sortdir($pth['folder']['content']);
463  foreach ($fs as $p) {
464  if (XH_isContentBackup($p, false)) {
465  $size = filesize($pth['folder']['content'] . '/' . $p);
466  $size = round(($size) / 102.4) / 10;
467  $o .= '<li><a href="' . $sn . '?file=' . $p
468  . '&amp;action=view" target="_blank">'
469  . $p . '</a> (' . $size . ' KB)'
470  . ' <form action="' . $sn . '?&xh_backups" method="post"'
471  . ' class="xh_inline_form">'
472  . '<input type="hidden" name="file" value="' . $p . '">'
473  . '<input type="hidden" name="action" value="restore">'
474  . '<input type="submit" class="submit" value="'
475  . $tx['action']['restore'] . '">'
476  . $_XH_csrfProtection->tokenInput()
477  . '</form>'
478  . '</li>' . "\n";
479  }
480  }
481  $o .= '</ul>' . "\n";
482  return $o;
483 }
484 
496 function XH_pluginsView()
497 {
498  global $sn, $cf, $tx;
499 
500  $plugins = XH_plugins(true);
501  $hiddenPlugins = explode(',', $cf['plugins']['hidden']);
502  $hiddenPlugins = array_map('trim', $hiddenPlugins);
503  $plugins = array_diff($plugins, $hiddenPlugins);
504  natcasesort($plugins);
505  $plugins = array_values($plugins);
506 
507  $o = '<h1>' . $tx['title']['plugins'] . '</h1><ul>';
508  foreach ($plugins as $plugin) {
509  $item = array(
510  'label' => utf8_ucfirst($plugin),
511  'url' => "$sn?$plugin&normal",
512  'children' => XH_registerPluginMenuItem($plugin)
513  );
514  $o .= XH_adminMenuItem($item, 0);
515  }
516  $o .= '</ul>';
517  return $o;
518 }
519 
535 function pluginMenu($add = '', $link = '', $target = '', $text = '', array $style = array())
536 {
537  global $_XH_pluginMenu;
538 
539  switch (strtoupper($add)) {
540  case 'ROW':
541  $_XH_pluginMenu->makeRow($style);
542  break;
543  case 'TAB':
544  $_XH_pluginMenu->makeTab($link, $target, $text, $style);
545  break;
546  case 'DATA':
547  $_XH_pluginMenu->makeData($text, $style);
548  break;
549  case 'SHOW':
550  return $_XH_pluginMenu->show();
551  break;
552  }
553 }
554 
565 {
566  $pluginMenu = new XH\IntegratedPluginMenu();
567  $pluginMenu->render($showMain);
568 }
569 
585 function XH_registerPluginMenuItem($plugin, $label = null, $url = null, $target = null)
586 {
587  static $pluginMenu = array();
588 
589  if (isset($label) && isset($url)) {
590  $pluginMenu[$plugin][] = array(
591  'label' => $label,
592  'url' => $url,
593  'target' => $target
594  );
595  } else {
596  if (isset($pluginMenu[$plugin])) {
597  return $pluginMenu[$plugin];
598  } else {
599  return array();
600  }
601  }
602 }
603 
622 function XH_adminMenu(array $plugins = array())
623 {
624  global $sn, $edit, $s, $u, $cf, $tx, $su, $plugin_tx;
625 
626  if ($s < 0) {
627  $su = $u[0];
628  }
629  $changeMode = $edit ? 'normal' : 'edit';
630  $changeText = $edit ? $tx['editmenu']['normal'] : $tx['editmenu']['edit'];
631 
632  $filesMenu = array();
633  foreach (array('images', 'downloads', 'media') as $item) {
634  $filesMenu[] = array(
635  'label' => utf8_ucfirst($tx['editmenu'][$item]),
636  'url' => $sn . '?&edit&' . $item
637  );
638  }
639  $settingsMenu = array(
640  array(
641  'label' => utf8_ucfirst($tx['editmenu']['configuration']),
642  'url' => $sn . '?file=config&action=array'
643  ),
644  array(
645  'label' => utf8_ucfirst($tx['editmenu']['language']),
646  'url' => $sn . '?file=language&action=array'
647  ),
648  array(
649  'label' => utf8_ucfirst($tx['editmenu']['template']),
650  'url' => $sn . '?file=template&action=edit'
651  ),
652  array(
653  'label' => utf8_ucfirst($tx['editmenu']['stylesheet']),
654  'url' => $sn . '?file=stylesheet&action=edit'
655  ),
656  array(
657  'label' => utf8_ucfirst($tx['editmenu']['log']),
658  'url' => $sn . '?file=log&action=view'
659  ),
660  array(
661  'label' => utf8_ucfirst($tx['editmenu']['validate']),
662  'url' => $sn . '?&validate'
663  ),
664  array(
665  'label' => utf8_ucfirst($tx['editmenu']['backups']),
666  'url' => $sn . '?&xh_backups'
667  ),
668  array(
669  'label' => utf8_ucfirst($tx['editmenu']['pagedata']),
670  'url' => $sn . '?&xh_pagedata'
671  ),
672  array(
673  'label' => utf8_ucfirst($tx['editmenu']['change_password']),
674  'url' => $sn . '?&xh_change_password'
675  ),
676  array(
677  'label' => utf8_ucfirst($tx['editmenu']['sysinfo']),
678  'url' => $sn . '?&sysinfo'
679  )
680  );
681  $hiddenPlugins = explode(',', $cf['plugins']['hidden']);
682  $hiddenPlugins = array_map('trim', $hiddenPlugins);
683  $plugins = array_diff($plugins, $hiddenPlugins);
684  $total = count($plugins);
685  $rows = 12;
686  $columns = ceil($total / $rows);
687  $rows = ceil($total / $columns);
688  $width = 125 * $columns;
689  $marginLeft = min($width, 250) - $width;
690  natcasesort($plugins);
691  $plugins = array_values($plugins);
692  $orderedPlugins = array();
693  for ($j = 0; $j < $rows; ++$j) {
694  for ($i = 0; $i < $total; $i += $rows) {
695  $orderedPlugins[] = isset($plugins[$i + $j]) ? $plugins[$i + $j] : '';
696  }
697  }
698  $plugins = $orderedPlugins;
699  $pluginMenu = array();
700  foreach ($plugins as $plugin) {
701  $label = isset($plugin_tx[$plugin]['menu_plugin'])
702  ? $plugin_tx[$plugin]['menu_plugin']
703  : ucfirst($plugin);
704  $pluginMenuItem = array('label' => $label);
705  if ($plugin != '') {
706  $pluginMenuItem['url'] = $sn . '?' . $plugin . '&normal';
707  foreach (XH_registerPluginMenuItem($plugin) as $item) {
708  $pluginMenuItem['children'][] = $item;
709  }
710  }
711  $pluginMenu[] = $pluginMenuItem;
712  }
713  $menu = array(
714  array(
715  'label' => $changeText,
716  'url' => $sn . '?' . $su . '&' . $changeMode,
717  ),
718  array(
719  'label' => utf8_ucfirst($tx['editmenu']['pagemanager']),
720  'url' => $sn . '?&normal&xhpages'
721  ),
722  array(
723  'label' => utf8_ucfirst($tx['editmenu']['files']),
724  'url' => $sn . '?&edit&userfiles',
725  'children' => $filesMenu
726  ),
727  array(
728  'label' => utf8_ucfirst($tx['editmenu']['settings']),
729  'url' => $sn . '?&settings',
730  'children' => $settingsMenu
731  ),
732  array(
733  'label' => utf8_ucfirst($tx['editmenu']['plugins']),
734  'url' => $sn . '?&xh_plugins',
735  'children' => $pluginMenu,
736  'id' => 'xh_adminmenu_plugins',
737  'style' => 'width:' . $width . 'px; margin-left: ' . $marginLeft . 'px'
738  ),
739  array(
740  'label' => utf8_ucfirst($tx['editmenu']['logout']),
741  'url' => $sn . '?&logout'
742  )
743  );
744 
745  $t = "\n" . '<div id="xh_adminmenu">';
746  $t .= "\n" . '<ul>' . "\n";
747  foreach ($menu as $item) {
748  $t .= XH_adminMenuItem($item);
749  }
750  $t .= '</ul>' . "\n"
751  . '<div class="xh_break"></div>' . "\n" . '</div>' . "\n";
752  return $t;
753 }
754 
765 function XH_adminMenuItem(array $item, $level = 0)
766 {
767  $indent = str_repeat(' ', $level);
768  $t = $indent . '<li>';
769  if (isset($item['url'])) {
770  $t .= '<a href="' . XH_hsc($item['url']) . '"';
771  if (isset($item['target'])) {
772  $t .= ' target="' . $item['target'] . '"';
773  }
774  $t .= '>';
775  } else {
776  $t .= '<span>';
777  }
778  $t .= $item['label'];
779  if (isset($item['url'])) {
780  $t .= '</a>';
781  } else {
782  $t .= '</span>';
783  }
784  if (isset($item['children'])) {
785  $t .= "\n" . $indent . ' <ul';
786  if (isset($item['id'])) {
787  $t .= ' id="' . $item['id'] . '"';
788  }
789  if (isset($item['style'])) {
790  $t .= ' style="' . $item['style'] . '"';
791  }
792  $t .= '>' . "\n";
793  foreach ($item['children'] as $child) {
794  $t .= XH_adminMenuItem($child, $level + 1);
795  }
796  $t .= $indent . ' </ul>' . "\n" . $indent;
797  }
798  $t .= '</li>' . "\n";
799  return $t;
800 }
801 
812 function print_plugin_admin($main)
813 {
814  global $_XH_pluginMenu;
815 
816  return $_XH_pluginMenu->render(strtoupper($main) == 'ON');
817 }
818 
829 {
830  global $action, $admin;
831 
832  switch ($admin) {
833  case 'plugin_config':
834  $fileEdit = new XH\PluginConfigFileEdit();
835  break;
836  case 'plugin_language':
837  $fileEdit = new XH\PluginLanguageFileEdit();
838  break;
839  case 'plugin_stylesheet':
840  $fileEdit = new XH\PluginTextFileEdit();
841  break;
842  default:
843  return false;
844  }
845  switch ($action) {
846  case 'plugin_edit':
847  case 'plugin_text':
848  return $fileEdit->form();
849  case 'plugin_save':
850  case 'plugin_textsave':
851  return $fileEdit->submit();
852  default:
853  return false;
854  }
855 }
856 
857 
876 {
877  global $sn, $su, $s, $u, $c, $e, $cf, $tx, $_XH_csrfProtection, $l, $h, $s;
878 
879  $su = $u[$s]; // TODO: is changing of $su correct here???
880 
881  $editor = $cf['editor']['external'] == '' || init_editor();
882  if (!$editor) {
883  $msg = sprintf($tx['error']['noeditor'], $cf['editor']['external']);
884  $e .= '<li>' . $msg . '</li>' . "\n";
885  }
886  $o = '<form method="POST" id="ta" action="' . $sn . '">'
887  . tag('input type="hidden" name="selected" value="' . $u[$s] . '"');
888  //Add page level and heading to post data because the split markers
889  //are filtered out if mode is not "advanced"
890  if (!$cf['mode']['advanced']) {
891  $o .= tag('input type="hidden" name="level" value="' . $l[$s] . '"')
892  . tag('input type="hidden" name="heading" value="' . $h[$s] . '"');
893  //replace split-markers
894  $tempContent = preg_replace('/<!--XH_ml[1-9]:.*?-->/isu', '', $c[$s]);
895  } else {
896  $tempContent = $c[$s];
897  }
898  $o .= tag('input type="hidden" name="function" value="save"')
899  . '<textarea name="text" id="text" class="xh-editor" style="height: '
900  . $cf['editor']['height'] . 'px; width: 100%;" rows="30" cols="80">'
901  . XH_hsc($tempContent)
902  . '</textarea>'
903  . '<script type="text/javascript">'
904  . 'document.getElementById("text").style.height=(' . $cf['editor']['height']
905  . ') + "px";</script>'
906  . $_XH_csrfProtection->tokenInput();
907  if ($cf['editor']['external'] == '' || !$editor) {
908  $value = utf8_ucfirst($tx['action']['save']);
909  $o .= '<input type="submit" value="' . $value . '">';
910  }
911  $o .= '</form>';
912  return $o;
913 }
914 
928 function XH_saveContents()
929 {
930  global $c, $pth, $tx, $edit, $pd_router;
931 
932  if (!(XH_ADM && $edit)) {
933  trigger_error(
934  'Function ' . __FUNCTION__ . '() must not be called in view mode',
935  E_USER_WARNING
936  );
937  return false;
938  }
939  $hot = '<!--XH_ml[1-9]:';
940  $hct = '-->';
941  $title = utf8_ucfirst($tx['filetype']['content']);
942  $cnts = "<html><head><title>$title</title>\n"
943  . $pd_router->headAsPHP()
944  . '</head><body>' . "\n";
945  foreach ($c as $j => $i) {
946  preg_match("/(.*?)($hot(.+?)$hct)(.*)/isu", $i, $matches);
947  $page = $matches[1] . $matches[2] . PHP_EOL . $pd_router->pageAsPHP($j)
948  . $matches[4];
949  $cnts .= rmnl($page . "\n");
950  }
951  $cnts .= '</body></html>';
952  if (!file_exists($pth['folder']['content'])) {
953  mkdir($pth['folder']['content'], true);
954  }
955  return XH_writeFile($pth['file']['content'], $cnts) !== false;
956 }
957 
977 {
978  global $pth, $cf, $tx, $pd_router, $c, $s, $u, $selected;
979 
980  //clean up and inject split-markers
981  if (!$cf['mode']['advanced']) {
982  $text = preg_replace('/<!--XH_ml[1-9]:.*?-->/isu', '', $text);
983  $split = '<!--XH_ml' . stsl($_POST['level']) . ':'
984  . stsl($_POST['heading']) . '-->'
985  . "\n";
986  $text = $split . $text;
987  }
988  $hot = '<!--XH_ml[1-9]:';
989  $hct = '-->';
990  // TODO: this might be done before the plugins are loaded
991  // for backward compatibility
992  $text = stsl($text);
993  // remove empty headings
994  $text = preg_replace("/$hot(&nbsp;|&#160;|\xC2\xA0| )?$hct/isu", '', $text);
995  // replace P elements around plugin calls and scripting with DIVs
996  $text = preg_replace('/<p>({{{.*?}}}|#CMSimple .*?#)<\/p>/isu', '<div>$1</div>', $text);
997 
998  // handle missing heading on the first page
999  if ($s == 0) {
1000  if (!preg_match('/^<!--XH_ml[1-9]:.+-->/isu', $text)
1001  && !preg_match('/^(<p[^>]*>)?(\&nbsp;| |<br \/>)?(<\/p>)?$/isu', $text)
1002  ) {
1003  $text = '<!--XH_ml1:' . $tx['toc']['missing'] . '-->' . "\n" . $text;
1004  }
1005  }
1006  $c[$s] = $text; // keep editor contents, if saving fails
1007 
1008  // insert $text to $c
1009  $text = preg_replace('/<!--XH_ml[1-9]:/is', "\x00" . '$0', $text);
1010  $pages = explode("\x00", $text);
1011  // append everything before the first page to the previous page
1012  if ($s > 0) {
1013  $c[$s - 1] .= $pages[0];
1014  }
1015  array_shift($pages);
1016  array_splice($c, $s, 1, $pages);
1017 
1018  // delegate changes to $pd_router
1019  preg_match_all("/$hot(.+?)$hct/isu", $text, $matches);
1020  if ($pd_router->refresh_from_texteditor($matches[1], $s)) {
1021  // redirect to get back in sync
1022  if (count($matches[1]) > 0) {
1023  // page heading might have changed
1024  $urlParts = explode($cf['uri']['seperator'], $selected);
1025  array_splice($urlParts, -1, 1, uenc(trim(xh_rmws(strip_tags($matches[1][0])))));
1026  $su = implode($cf['uri']['seperator'], $urlParts);
1027  } else {
1028  // page was deleted; go to previous page
1029  $su = $u[max($s - 1, 0)];
1030  }
1031  header("Location: " . CMSIMPLE_URL . "?" . $su, true, 303);
1032  exit;
1033  } else {
1034  e('notwritable', 'content', $pth['file']['content']);
1035  }
1036 }
1037 
1050 {
1051  global $c, $cl, $pth, $e, $pd_router;
1052 
1053  XH_backup();
1054  if ($e) {
1055  return;
1056  }
1057  $c = array();
1058  for ($i = 0; $i < $cl; ++$i) {
1059  $pd_router->destroy($i);
1060  }
1061  if (XH_saveContents()) {
1062  // the following relocation is necessary to cater for the changed content
1063  $url = CMSIMPLE_URL . '?&xh_backups&xh_success=emptied';
1064  header('Location: ' . $url, true, 303);
1065  exit;
1066  } else {
1067  e('cntsave', 'content', $pth['file']['content']);
1068  }
1069 }
1070 
1083 function XH_restore($filename)
1084 {
1085  global $pth, $e;
1086 
1087  $tempFilename = $pth['folder']['content'] . 'restore.htm';
1088  if (!rename($filename, $tempFilename)) {
1089  e('cntsave', 'backup', $tempFilename);
1090  return;
1091  }
1092  XH_backup();
1093  if ($e) {
1094  if (!unlink($tempFilename)) {
1095  e('cntdelete', 'content', $tempFilename);
1096  }
1097  return;
1098  }
1099  if (!rename($tempFilename, $pth['file']['content'])) {
1100  e('cntsave', 'content', $pth['file']['content']);
1101  return;
1102  }
1103  // the following relocation is necessary to cater for the changed content
1104  $url = CMSIMPLE_URL . '?&xh_backups&xh_success=restored';
1105  header('Location: ' . $url, true, 303);
1106  exit;
1107 }
1108 
1118 function XH_extraBackup($suffix)
1119 {
1120  global $pth;
1121 
1122  $date = date("Ymd_His");
1123  $dest = $pth['folder']['content'] . $date . '_' . $suffix . '.htm';
1124  if (!copy($pth['file']['content'], $dest)) {
1125  e('cntsave', 'backup', $dest);
1126  } else {
1127  $url = CMSIMPLE_URL . '?&xh_backups&xh_success=backedup';
1128  header('Location: ' . $url, true, 303);
1129  exit;
1130  }
1131 }
1132 
1143 {
1144  global $tx;
1145 
1146  $keys = array(
1147  'action' => array('advanced_hide', 'advanced_show', 'cancel', 'ok'),
1148  'error' => array('server'),
1149  'password' => array('score'),
1150  'settings' => array('backupsuffix')
1151  );
1152  $l10n = array();
1153  foreach ($keys as $category => $keys2) {
1154  foreach ($keys2 as $key) {
1155  $l10n[$category][$key] = $tx[$category][$key];
1156  }
1157  }
1158  $o = '<script type="text/javascript">XH.i18n = '
1159  . XH_encodeJson($l10n) . '</script>' . PHP_EOL;
1160  return $o;
1161 }
1162 
1172 function XH_wantsPluginAdministration($pluginName)
1173 {
1174  return (bool) preg_match('/(?:^|&)' . preg_quote($pluginName, '/') . '(?=&|$)/', sv('QUERY_STRING'));
1175 }
print_plugin_admin($main)
Definition: adminfuncs.php:812
$l
Definition: cms.php:1003
$action
Definition: cms.php:460
XH_plugins($admin=false)
Definition: functions.php:1443
pluginMenu($add='', $link='', $target='', $text='', array $style=array())
Definition: adminfuncs.php:535
XH_isAccessProtected($path)
Definition: adminfuncs.php:190
$admin
Definition: cms.php:447
XH_isContentBackup($filename, $regularOnly=true)
Definition: functions.php:1949
XH_sysinfo()
Definition: adminfuncs.php:218
XH_adminMenuItem(array $item, $level=0)
Definition: adminfuncs.php:765
$plugin
Definition: cms.php:856
XH_pluginsView()
Definition: adminfuncs.php:496
$su
Definition: cms.php:778
$e
Definition: cms.php:127
li(array $ta, $st)
Definition: tplfuncs.php:217
sv($s)
Definition: functions.php:543
$j
Definition: cms.php:204
XH_readFile($filename)
Definition: functions.php:1601
const CMSIMPLE_URL
Definition: cms.php:761
XH_saveEditorContents($text)
Definition: adminfuncs.php:976
sortdir($dir)
Definition: functions.php:1063
XH_writeFile($filename, $contents)
Definition: functions.php:1626
$s
Definition: cms.php:953
rmnl($t)
Definition: functions.php:559
XH_registerPluginMenuItem($plugin, $label=null, $url=null, $target=null)
Definition: adminfuncs.php:585
tag($s)
Definition: functions.php:1126
utf8_ucfirst($string)
Definition: utf8.php:118
$_XH_pluginMenu
Definition: cms.php:845
XH_adminMenu(array $plugins=array())
Definition: adminfuncs.php:622
XH_saveContents()
Definition: adminfuncs.php:928
$i
Definition: cms.php:193
const CMSIMPLE_XH_VERSION
Definition: cms.php:209
$title
Definition: cms.php:100
$cf
Definition: cms.php:272
XH_pluginVersion($plugin)
Definition: adminfuncs.php:29
XH_systemCheckLi($class, $state, $text)
Definition: adminfuncs.php:136
XH_registerStandardPluginMenuItems($showMain)
Definition: adminfuncs.php:564
XH_settingsView()
Definition: adminfuncs.php:344
$c
Definition: cms.php:964
XH_wantsPluginAdministration($pluginName)
plugin_admin_common()
Definition: adminfuncs.php:828
$file
Definition: cms.php:640
XH_restore($filename)
$u
Definition: cms.php:990
XH_emptyContents()
XH_contentEditor()
Definition: adminfuncs.php:875
XH_logFileView()
Definition: adminfuncs.php:392
$o
Definition: cms.php:113
$temp
Definition: cms.php:182
XH_backupsView()
Definition: adminfuncs.php:427
e($et, $ft, $fn)
Definition: functions.php:655
$h
Definition: cms.php:977
$plugin_tx
Definition: cms.php:1095
$sn
Definition: cms.php:434
foreach(XH_plugins() as $plugin) $_XH_csrfProtection
Definition: cms.php:879
$tx
Definition: cms.php:363
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_extraBackup($suffix)
XH_encodeJson($value)
Definition: functions.php:2170
XH_systemCheck(array $data)
Definition: adminfuncs.php:64
$text
Definition: cms.php:698
$pth
Definition: cms.php:230
init_editor(array $elementClasses=array(), $initFile=false)
Definition: functions.php:354
XH_hsc($string)
Definition: functions.php:2204
uenc($s)
Definition: functions.php:1009
XH_backup()
Definition: functions.php:1826
$pd_router
Definition: cms.php:929
const CMSIMPLE_XH_DATE
Definition: cms.php:217
$edit
Definition: cms.php:602
$cl
Definition: cms.php:918
XH_message($type, $message)
Definition: functions.php:1806
XH_adminJSLocalization()
XH_absoluteUrlPath($path)
Definition: adminfuncs.php:157